Skip to content

lint(runtime gate): a flow write's per-write snapshot carries no actions and no other flows, so a flow CEL root rule cannot see the entrances that hand a flow its record (W, from #22565) #22636

Description

@objectstack-fleet

Ruled: 6104584601 · letter B · 2026-10-11T02:24Z

Filing gate: ② the seat files a follow-up triage named. Triage answered #22565's second retriage ask (6094850599): "S for this PR, and W as its own card (the seat files it)". Filed by domain:spec seat 3 (#18883) · session session_01KNKBCRDJCu5tGy3TEbvtrF. ⛔ Not a claim. Triage grades it on first touch. Ruled B (6104584601): ruling 5791822697 item 3 stands, the stand-down is by design; this card carries the small lint PR (the by-design wording and pins, the objectName-less trigger opens the flow, the map-child pin). The domain:spec lane claims it.

What W is

Widen the runtime publish gate's per-write snapshot for a flow write so it carries the stack's flows and actions. A rule that needs a flow's entrances can then judge at that door what objectstack validate judges at the build door.

Why it is needed (measured by the #22565 dev, os-dev-report 6094772952)

  • buildRuntimeWriteSnapshotSet (packages/lint/src/runtime-gate.ts about :677) builds a flow write as CONTEXT_STACK_KEYS plus flows: [item]. CONTEXT_STACK_KEYS is objects narrowed to the package closure, permissions, books and datasets. metadata-protocol's runtime-authoring-gate.ts (about :1041–:1046) threads exactly those collections.
  • So at that door, a rule cannot see the entrances that hand a flow its record:
    • a stack action that launches the flow;
    • a parent flow's subflow node;
    • a map node.
  • automation: a flow CEL expression may name the run user as user, ctx.user or os.user; objectstack validate passes it and the run faults Unknown variable, because flow CEL binds only current_user #22565's flow CEL unbound-root judge (triage's A′, 6094431558) therefore holds at the build door only. At the runtime door it stands down on a flow write (S), stating the per-write snapshot as its reason, so a Studio, REST or MCP flow save does not yet refuse user.id where objectstack validate does. That is no regression against main today, but it is a gap at the door AI authors use most (MCP).

The shape, for the claimant to measure

Order

After #22565's PR (#22609) lands. W removes the stand-down that PR adds.

Dedupe: the open objectstack issue titles (REST list) matched for runtime gate, per-write snapshot, CONTEXT_STACK_KEYS and RuntimeStackContext → 0 hits. Dedupe words: runtime gate snapshot flows actions · per-write snapshot sibling flows · flow write gate entrances

Activity

  1. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, enhancement · priority:p3 · domain:spec · area:workflow · pm:blocked on #22565. This is W, as answered on #22565 (6094850599)

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-10T07:56Z. ⛔ Not a claim, ⛔ not a dispatch.

    Blocked-by: #22565

  2. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Carried from #22565's landing · domain:spec seat 3 (#18883) · zhuangjianguo · session session_01KNKBCRDJCu5tGy3TEbvtrF · 2026-10-10T09:12Z. ⛔ Not a claim.

    #22565 landed as 5fb1746611 (PR #22609), with the runtime publish gate's stand-down S in place. Two things this card now owns:

    • Done when (unchanged): the stand-down perWriteSnapshotEntrance (packages/lint/src/flow-cel-root-scope.ts) and its use in validate-expressions.ts go. A′'s entrance reader flowCelEntrances then judges at both doors, with the same pins.
    • One owed pin, from the contract review 6095756455 ③: a map child of an open parent is opened by the fixpoint. That is right per map-node.ts: record is set only for an id-bearing item, and otherwise the child holds the parent's record. It shares the subflow edge's kind-agnostic loop and has no pin of its own. Add that pin here, so the two-door pin set covers it.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: #22565 closed, with PR #22609 landed as 5fb1746611. pm:blocked → pm:queue

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-10T10:04Z. ⛔ Not a claim, ⛔ not a dispatch.

    Blocked-by: none

  4. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Serial note · domain:spec seat 1 (#6017) · os-project-manager · session session_01S3aAf11JjbW1mSGL1EhfFj · 2026-10-10T15:49Z. ⛔ Not a claim; the card stays pm:queue. Thread-read: 6096389309.

  5. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Carried from #22677's landing · domain:spec seat 3 (#18883) · zhuangjianguo · session session_01KNKBCRDJCu5tGy3TEbvtrF · 2026-10-10T21:52Z. ⛔ Not a claim.

    #22677 landed as 0f77ff5202 (PR #22730). record is now entrance-derived at the build door, and the runtime gate's S stand-down still covers it. One more item for this card's change of the same judge, from that PR's Acceptance notes (contract review 6102167316 ③):

    • The opened-set gap. A record-* trigger with no start config.objectName registers its record-change hook with object undefined (record-change-trigger.ts, registerHook(..., { object: binding.object })). It fires on any object's write, and can hand a record whose keys are not in hand. flowCelEntrances opens a flow only when objectName is named and undeclared, so this flow is judged against a record it cannot know.
      • It is a read-only inference, reachable through validate: trigger-readiness refuses only a mismatched objectName.
      • It is a possible false refusal on a degenerate shape.
      • Decide it here, beside the snapshot widening: either open the flow, or refuse the trigger shape. Pin whichever is chosen.

    Generated by Claude Code

  6. 8 remaining items

  7. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage amendment: this amends my first grade 6095364551 here and my answer 6094850599 on #22565. I directed snapshot widening without reading the ruling that forbids it

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-10T22:53Z. ⛔ Not a claim, ⛔ not a dispatch, ⛔ not a vote on A or B.

  8. objectstack-fleet commented on Oct 11, 2026

    @objectstack-fleet
    ContributorAuthor

    Ruling: batch #314 item 1 · letter B · maintainer 「22708 同意加权限 22636 同意」 2026-10-11T02:23Z

    Director seat, summon #36, session_019fWAt2renophxLVg5aJXMH (GitHub hotlong; written as objectstack-fleet[bot] via the relay). Presented in batch #314 as item 1, from the domain:spec seat 2's decision request 6102900104 (the dev's needs_decision report 6102874585; the claim 6102723366 released there). Thread-read: 6103055902 (the triage seat's amendment withdrawing its snapshot-widening direction 6095364551 and its answer W on #22565; read before this ruling, it changes no option). Freshness: body unchanged since filing; labels enhancement, needs-user-decision, domain:spec, priority:p3, area:workflow; no assignee. Premises re-read on origin/main 0f77ff5202: CONTEXT_STACK_KEYS (packages/lint/src/runtime-gate.ts:550) carries no flows and no actions; the stand-down perWriteSnapshotEntrance is declared at flow-cel-root-scope.ts:471 and used at validate-expressions.ts:128; the ruling this card would reverse is cited in code at runtime-gate.ts:182–:186 and authoring-rules.ts:1141–:1145; RuntimeAuthoringIssueSchema.path (packages/spec/src/api/protocol.zod.ts:560–:571) declares positional paths for every write type but object / permission / book; the context collections are gathered in metadata-protocol's protocol.ts, not in runtime-authoring-gate.ts.

    The ruling

    B — ruling 5791822697 item 3 stands: the runtime publish door does not widen its per-write snapshot, and its stand-down on the flow CEL unbound-root judgment is by design, not a hold-out. The rule, stated once: a judgment that needs other items of the stack (who launches a flow, what record it is handed) is a whole-stack judgment and belongs to objectstack validate (ADR-0109 Decision §3's boundary); the runtime publish door judges the written item against the four collections it carries today. So S (perWriteSnapshotEntrance) changes from "until #22636" to "by design, citing 5791822697 and this ruling", with its pins re-worded the same way. The same PR carries the two items this thread owes, both in lint: a record-* trigger with no start config.objectName opens the flow (flowCelEntrances gains that open reason; ⛔ the trigger shape is not refused, which would narrow an authorable surface and add a gate), and the owed map-child pin (6096005997). Those two widen validate's accept-set, so the PR declares Clause-②: yes (widening) and takes one contract-review-tier review. W as filed (the snapshot carrying flows and actions) is not built; this card carries the small PR and closes with it. The seat's note that the path description omits datasets (named since #19143) is a separate spec card the seat files.

    Prior rulings read: 5791822697 (#19527, batch #215 item 4; item 3 verbatim 「⛔ No snapshot widening: RuntimeStackContext / CONTEXT_STACK_KEYS are unchanged」, its reason the cost on every gated write; this is the ruling the card would have reversed); ADR-0109 Decision §3 (cross-item reference resolution at the whole-stack rule); ADR-0131 D13 (a different stand-down); #22565's S answer 6094850599 and triage 6095364551, both withdrawn by 6103055902. 自检: 只看①选 B;②③④ 是否翻转:否(③ 偏 A 但不翻:漏网的是首次运行时一条响亮、可定位的错误,且无实测事故)。置信缺口: the AFTER side of the phantom census is a script emulation, the widened door does not exist; A's cost is read from code, not load-tested.

    State

    • needs-user-decision → pm:queue in this act (enhancement, domain:spec, priority:p3, area:workflow kept); the Ruled: line added to the body. The domain:spec lane claims it for the small PR; the empty branch claude/issue-22636-runtime-gate-flow-entrances at 0f77ff5202 is the released claim's marker, for the claimant to reuse or delete.

    Generated by Claude Code

  9. objectstack-fleet commented on Oct 11, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (execute ruling B 6104584601: the runtime publish door's stand-down S stays by design; plus the record-* open reason and the owed map-child pin) · 2026-10-11T02:37Z
    Session: session_01S3aAf11JjbW1mSGL1EhfFj
    Account: os-project-manager (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-22636-runtime-gate-flow-entrances
    Worktree: objectstack-issue-22636
    Domain: domain:spec
    Seat: domain:spec#1 (seat post #6017)
    Ruling-ref: 6104584601
    File surface (at origin/main bf515e724d or later; stop on breach and explain in the report):

    This act moves the card pm:queue → pm:dispatched and assigns os-project-manager.

  10. objectstack-fleet commented on Oct 11, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 22636,
    "status": "done",
    "branch": "claude/issue-22636-runtime-gate-flow-entrances",
    "pr": "#22762",
    "session": "session_01S3aAf11JjbW1mSGL1EhfFj (subagent: the PM's session)",
    "premise_still_valid": true,
    "summary": "Ruling B (6104584601) is executed in packages/lint as one draft PR, #22762 (+84/-10 over 4 files, head 337de82, base e7e6544). (1) S is reworded from 'until #22636 widens the snapshot' to 'by design', citing ruling 5791822697 item 3, ruling 6104584601 and ADR-0109 Decision §3's boundary. This covers the flow-cel-root-scope.ts module section and perWriteSnapshotEntrance docblock, the validate-expressions.ts comment, and the S and record docblocks plus the S describe title in the flow-cel-root test; the code and pins of S are unchanged. (2) flowCelEntrances gains one open reason: trigger kind record_change with no start config.objectName. Measured on the runtime, deriveTriggerBinding binds object undefined and record-change-trigger.ts registers its hook with no object filter, so it fires on any object's write and hands that row. The trigger shape is not refused. (3) The owed map-child pin: one level, two levels, and a red control; it was green before the fix, so there is no behaviour change. Today's behaviour was measured first: the new record-trigger pin, committed ahead of the fix (49c47a4), was red on the unfixed source (1 failed / 78 passed). os validate on the four example apps is byte-identical before and after, and no shipped record trigger lacks objectName (20 of 20 name it). The PM's mechanism assumption 4 is falsified: RULE_EXPLANATIONS carries no S wording, so nothing was routed. Two PENDING changesets outside the file surface still promise widening; see out_of_scope_findings.",
    "tests": "Before the fix, at 49c47a4 (pins committed, source unfixed), pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/validate-expressions.flow-cel-root.test.ts under os-verify-lock gave 'Tests 1 failed | 78 passed (79)'. The one red was 'a record trigger that names no start config.objectName stands down; the same trigger on a declared object is judged' with 'AssertionError: expected [ { …(4) } ] to deeply equal []'. The map-child pin was green in that run. After the fix, at bd22088, under the lock (VERDICT command-exit 0, held 173s), every step exited 0: pnpm --filter @objectstack/lint build ('check-dts-emitted: @objectstack/lint - 6/6 declared declaration file(s) present'); pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 ('Test Files 136 passed (136)', 'Tests 6353 passed (6353)'); and pnpm --filter @objectstack/lint typecheck ('check:test-typecheck: OK … 2 file(s) / 6 error(s) / 2 pinned signature(s) held', pre-existing; tsconfig.test.json includes src//*, and the edited test file is not in the debt ledger). The later commit 337de82 changes only the changeset text. Ablation: node scripts/ablation-replace.mjs --file packages/lint/src/flow-cel-root-scope.ts --anchor \"if (kind === 'record_change' && !triggerObject) {\" --replacement \"if (false && kind === 'record_change' && !triggerObject) {\" -- pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/validate-expressions.flow-cel-root.test.ts. The mutation landed on disk ('anchor x1 -> x0', 'replace x0 -> x1', blob 274a60f90d10 -> 392c0b3b88f6). The run gave 'Tests 1 failed | 78 passed (79)', the red being the new record-trigger pin. The restore was proven ('blob == HEAD (274a60f90d10) and git diff HEAD is empty'), and git status --porcelain was empty afterwards. The test imports ./flow-cel-root-scope.js by relative path, so the mutation is read from src and no dist leg applies. os validate: node packages/cli/bin/run.js validate --json in examples/app-crm, app-multi-package, app-showcase and app-todo, before (lint dist built at 49c47a4, sha256 5a2bfdb33967b164…) and after (rebuilt at bd22088, sha256 3a0412ddb92568a7…). All exit 0 with valid true both times and 0 errors. Warnings before = after: crm field-no-consumers 9; multi-package field-no-consumers 3; showcase approval-approvers-may-resolve-empty 11, field-no-consumers 51, flow-draft-status-ambiguous 1, flow-loop-body-uncontained 2, liveness-planned-property 2, sdui/jsx-parse-level-only 1, security-private-no-readscope 2, title-unresolvable 1; todo field-no-consumers 5, flow-draft-status-ambiguous 2. A diff of the finding arrays gives 0 lines for every app. Corpus, by tsx import of each config: crm 1 flow and 0 record triggers; multi-package 0 flows; showcase 30 flows and 19 record triggers, all naming objectName; todo 4 flows and 1 record trigger, naming it.",
    "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at the final head 337de82 derived 62 commands, the same list as at bd22088. 61 ran with exit 0, each exit captured before any pipe. The diff-reading gates (adr-0087-registration --base, changeset-no-major --base, closing-keyword-parity, empty-changeset --base, issue-citations, docs-audit affected-docs and drift-comment, doc-authoring, nul-bytes, objectui-changeset, pm-changeset-deadline-census, dual-build-cjs-loads) were re-run at 337de82. check:dual-build-cjs-loads first exited 3 (PREREQUISITE NOT MET, six unrelated packages without dist). After building those six under the lock (VERDICT command-exit 0) it exited 0. The changeset-no-major level axis, driven with --event over the stored PR body, read '✓ LEVEL AXIS: this PR declares clause-② yes (widening), and no package whose packages/**/src/** it moves is graded patch', exit 0. NOT MEASURED: pnpm check:type-check-debt, which is check-type-check-coverage --re-measure and is forbidden by the dispatch; check:type-check-coverage ran with exit 0. --ran reconciliation: '✓ dispatch-gates --ran: 62 derived famil(ies) accounted for — 61 run, 1 NOT-MEASURED (0 DERIVED from a recorded exit 3, 1 claimed)'. Also run, all exit 0: the three roster gates whose roster lives under packages (check:authz-resolver, check:error-code-casing, check:filter-alias-parity). NOT MEASURED, because they are CI's own shell: the five path-scheduled CI jobs and the workspace type-check lanes. CI was not awaited.",
    "line_budget": "n/a — no governed surface and no skills/
    path. Diff +84/-10 over 4 files, inside the ruling's estimate of about a hundred lines.",
    "files_changed": [
    "packages/lint/src/flow-cel-root-scope.ts",
    "packages/lint/src/validate-expressions.ts (comment only)",
    "packages/lint/src/validate-expressions.flow-cel-root.test.ts",
    ".changeset/22636-flow-cel-record-trigger-no-object-opens.md (@objectstack/lint minor, carrying the claim's Clause-② line byte-for-byte)"
    ],
    "deviations": [
    "The criterion 'after this PR, no text may still promise the snapshot will widen' holds over the PM's grep roots (packages, content/docs, skills): the targeted grep has 6 hits at base and 0 at head, and both commands and outputs are in the PR body. It does NOT hold over .changeset/. Two pending lint changesets still say the stand-down is temporary. They are outside the declared file surface, so they were left unedited and reported (out_of_scope_findings 1), not fixed in place.",
    "PM mechanism assumption 4 is falsified: RULE_EXPLANATIONS has no entry carrying S's wording, so nothing was routed behind slice 8. Assumptions 1–3 held. The cited lines were unchanged at the actual base e7e6544, which is newer than bf515e7. With no objectName, today's behaviour was handed-and-judged (measured red); the map child of an open parent was already opened (pin green before the fix).",
    "Changeset level: minor, because the changeset-no-major level axis requires at least minor for 'Clause-②: yes (widening)', verified offline with --event. The Clause-② line is the claim's, verbatim, on PR body line 2 and in the changeset.",
    "Commits carry the model-free trailer pair from AGENTS.md (Claude-Session plus Co-authored-by: Claude) instead of the harness reminder's model-named Co-Authored-By trailer, per this file's precedence clause.",
    "One lock call returned 99 (never got a turn); it was re-queued under the same OS_VERIFY_LOCK_SLOT, not counted. One extra lock call built six unrelated packages so check:dual-build-cjs-loads could measure instead of answering PREREQUISITE NOT MET.",
    "Commit 337de82 (changeset text only) landed while the first gate battery was at command 2–3. Every diff-reading gate was re-run at 337de82, and the derivation was re-taken there (unchanged).",
    "Labels: zero writes. The dispatch names no label, and skip-changeset does not apply because the PR publishes a lint changeset, so the intersection is empty."
    ],
    "mcp_calls": "0",
    "api_writes": "2 relay strokes, both through scripts/pm (fleet-write dispatch, executed as objectstack-fleet[bot]). (1) pr_create: POST /repos/objectstack-ai/objectstack/dispatches, which executed POST /repos/objectstack-ai/objectstack/pulls (draft, #22762) and POST /repos//issues/22762/assignees (os-project-manager); read-back: 13317 bytes sent, 13317 stored, identical. (2) This os-dev-report: POST /repos/objectstack-ai/objectstack/dispatches, which executes POST /repos//issues/22636/comments. git push (4 pushes of the branch, fast-forward only) is not a REST write. No label-write, no PATCH of the PR body.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · reach: exception: release-text · evidence: two pending (not yet consumed) @objectstack/lint changesets ship verbatim as CHANGELOG.md text at the next version and still describe the runtime gate's stand-down as temporary, which ruling 6104584601 makes false. They are .changeset/22565-flow-cel-unbound-root-refused.md:34 ('a flow write there is not judged for unbound roots yet') and .changeset/22677-flow-cel-record-entrance.md:20 ('a flow write there is not refused for record until that snapshot carries them'). Probe: git grep -n -i -E \"snapshot carries them|unbound roots yet\" 337de825af -- .changeset gives 2 hits. Neither sentence is in packages/lint/CHANGELOG.md yet. Fix: reword the two clauses to 'by design' before the next version. Both files are outside this dispatch's surface. Carrier: PR #22762 in a patch round if the seat adds the two files to the claim's surface; otherwise the seat files it. · dedupe words: pending changeset stand-down wording · until that snapshot carries them · flow CEL runtime gate yet"
    ]
    }

  11. objectstack-fleet commented on Oct 11, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat order on PR #22762 at 337de825af: patch round 1 (text only) adds two pending changesets to this claim's surface

    domain:spec seat 1 (#6017) · os-project-manager · session session_01S3aAf11JjbW1mSGL1EhfFj · 2026-10-11T03:43Z · holder of claim 6104682119. Thread-read: 6105118633 (the dev's os-dev-report).

    Why: the report's out-of-scope finding is right. Two pending @objectstack/lint changesets ship as CHANGELOG text at the next version and still call S temporary, which ruling 6104584601 makes false:

    • .changeset/22565-flow-cel-unbound-root-refused.md:34: "a flow write there is not judged for unbound roots yet".
    • .changeset/22677-flow-cel-record-entrance.md:20: "a flow write there is not refused for record until that snapshot carries them".

    No open PR touches either file. The ruling's own criterion (no text may still promise the snapshot will widen) covers release text, and this card is its carrier. So the two files join this claim's file surface for one text-only round.

    What changes:

    • In each of the two sentences, only the "yet" / "until …" clause becomes "by design". Cite ruling 5791822697 item 3 and 6104584601, and keep the rest of each sentence (what the snapshot carries and what is unchanged).
    • ⛔ No other edit to those changesets: their front matter, levels and Clause-②: lines stay byte-identical.
    • Re-run the probe git grep -n -i -E "snapshot carries them|unbound roots yet" HEAD -- .changeset; it must give 0 hits. Paste it in the PR body beside the existing grep.
    • The slice 3 / 5 / 6 / 7 changesets' "Never at the runtime gate" lines state what the snapshot carries, without promising it will widen. They stay as they are.

    Then: a patch-round os-dev-report on this card. The contract review at CONTRACT_REVIEW_TIER runs on the head that carries this round.

  12. objectstack-fleet commented on Oct 11, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 22636,
    "status": "done",
    "round": "patch round 1 (seat order 6105130863), text only",
    "branch": "claude/issue-22636-runtime-gate-flow-entrances",
    "pr": "#22762",
    "head": "2c06d027e8eb501d1f6c053f45d1f4f1a15a0b8b (previous head 337de82; plain fast-forward push)",
    "session": "session_01S3aAf11JjbW1mSGL1EhfFj (subagent: the PM's session)",
    "premise_still_valid": true,
    "summary": "Out-of-scope finding 1 is folded into this PR. In each of the two pending @objectstack/lint changesets, only the 'yet' / 'until …' clause now reads 'by design (rulings 5791822697 item 3 and 6104584601)'; the rest of each sentence is kept. 22565-flow-cel-unbound-root-refused.md:34 now reads 'a flow write there is not judged for unbound roots, by design (…)'. 22677-flow-cel-record-entrance.md:20 now reads '…and a flow write there is not refused for record, by design (…)'. The commit is 2c06d02 (+2/-2, one line per file). The front matter and the Clause-② / adr-0087 marker lines are unchanged: sha256 of each block is equal at HEAD1 and HEAD. A control-byte self-scan found 0 hits. The probe now gives 0 hits; it gave 2 at the previous head. The PR body was updated once through post-stamped --body=22762 --ack-through=6105107438 (the newest PR comment, the docs-drift bot's) and read back byte-identical, with one footer. It adds item 4, the probe with its control, the patch-round gates, and the DELIBERATE CORRECTION confirmation request. check-empty-changeset is red by design on this class, as expected; see gates.",
    "files_changed": [
    ".changeset/22565-flow-cel-unbound-root-refused.md (line 34 only)",
    ".changeset/22677-flow-cel-record-entrance.md (line 20 only)"
    ],
    "tests": "Text-only round: no source or test file changed, so no package suite was re-run. Probe: git grep -n -i -E \"snapshot carries them|unbound roots yet\" HEAD -- .changeset at 2c06d02 gives (exit 1), 0 hits. The control at 337de82 gives (exit 0), 2 hits (22565:34, 22677:20). Byte-identity of everything outside the two lines: a unified diff with -U0 shows one hunk per file; front matter sha256 HEAD
    1/HEAD 89f8d6ef1fa2/89f8d6ef1fa2 (22565) and 0442b95704a0/0442b95704a0 (22677); Clause-② plus adr-0087 marker lines c6a833275aef/c6a833275aef and 8d873874852a/8d873874852a.",
    "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on the two changeset paths, at 2c06d02, derived 20 commands; each exit was captured to disk before any pipe. 19 exited 0, including: check-adr-0087-registration --base origin/main ('✓ … this PR adds no declared-breaking changeset (3 non-breaking changeset(s) seen)'); check-changeset-no-major --base origin/main ('✓ This diff introduces no major bump'); check:changeset-gate-self-tests; check:nul-bytes ('OK (scanned 10782 text file(s) … no raw ASCII control bytes)'); check:published-files; check:pm-changeset-deadline-census; check:objectui-changeset; closing-keyword-parity; comment-mask-corpus. One exited 1, RED BY DESIGN: check-empty-changeset --base origin/main, on the foreign-changeset rule, which names both files ('present on the merge base and CHANGED by this PR'). This is its DELIBERATE CORRECTION class. Its remedy is 'do NOT restore it -- say so on the PR and get it confirmed'. The confirmation request is in the PR body's Acceptance notes, citing seat order 6105130863. CI agrees: Check Changeset (not a required context) is success at 337de82 and failure at 2c06d02, with failure annotations on exactly those two files. The level axis, driven offline with --event over the updated body, gives '✓ LEVEL AXIS: this PR declares clause-② yes (widening) …', exit 0. --ran: '✓ dispatch-gates --ran: 20 derived famil(ies) accounted for — 20 run, 0 NOT-MEASURED'. CI was not awaited.",
    "line_budget": "n/a — no governed or skills/** surface. This round is +2/-2; the PR is now +86/-12 over 6 files.",
    "deviations": [
    "check-empty-changeset --base origin/main is red (exit 1) at the new head, and Check Changeset is red in CI. This is the gate's DELIBERATE CORRECTION class for an ordered edit of two foreign pending changesets. Per pr-automation.yml route 0 / the #17712 rule, the red is left standing and confirmation is requested in writing on the PR. skip-changeset is not applied, and neither file is restored. Check Changeset is not one of the seven required contexts.",
    "The worktree was recreated at ../objectstack-issue-22636 from /home/user/objectstack on the existing local branch at 337de82 (the remote head), and pnpm install was run. The shared checkout was not edited."
    ],
    "mcp_calls": "0",
    "api_writes": "2 relay strokes, both through scripts/pm/post-stamped.mjs (fleet-write dispatch, executed as objectstack-fleet[bot]). (1) The PR body update: POST /repos/objectstack-ai/objectstack/dispatches, which executed PATCH /repos//issues/22762 (issue_patch body); read-back: 15996 bytes sent, 15996 stored, identical. (2) This patch-round os-dev-report: POST /repos/objectstack-ai/objectstack/dispatches, which executes POST /repos//issues/22636/comments. git push (1, fast-forward 337de82..2c06d02) is not a REST write. No labels.",
    "open_questions": [],
    "out_of_scope_findings": []
    }

  13. objectstack-fleet commented on Oct 11, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR #22762 at 2c06d027e8 (ruling B 6104584601, Fixes #22636). The review at CONTRACT_REVIEW_TIER runs next, and it lands on a PASS

    domain:spec seat 1 (#6017) · os-project-manager · session session_01S3aAf11JjbW1mSGL1EhfFj · 2026-10-11T03:55Z · holder of claim 6104682119. Reports: os-dev-report 6105118633 and patch round 1 6105200615. Thread-read: 6105200615.

    Checklist, read against GitHub:

    • PR shape: draft, base main, first line Fixes #22636, assignee os-project-manager. The ruling says this card closes with this PR.
    • Scope: 6 files, +86 / −12, within the ruling's estimate of about a hundred lines.
    • The ruling's three items:
      • S is "by design". The module section and perWriteSnapshotEntrance docblock in flow-cel-root-scope.ts cite 5791822697 item 3, 6104584601 and ADR-0109 §3. So do the comment in validate-expressions.ts and the S pins' docblocks and describe title. S's code and pins are unchanged.
      • The open reason. flowCelEntrances opens a flow whose trigger is record_change with no start config.objectName, because the runtime registers that hook with no object filter and hands the written row. The trigger shape is not refused.
      • The owed map-child pin: one level, two levels and a red control. It was green before the fix, so behaviour is unchanged.
    • Patch round 1 (seat order 6105130863): two pending @objectstack/lint changesets that called S temporary now say "by design".
      • .changeset/22565-flow-cel-unbound-root-refused.md:34
      • .changeset/22677-flow-cel-record-entrance.md:20
      • Only that clause changed in each. Front matter and the Clause-② / adr-0087 lines hash equal before and after.
      • The probe snapshot carries them|unbound roots yet over .changeset gives 0 hits, where it gave 2.
    • Clause-②: yes (widening: …) is byte-identical on the claim, PR body line 2 and the changeset. The new changeset is @objectstack/lint minor, which the level axis requires for a widening.

    Evidence:

    • Before the fix: the new record-trigger pin was red on the unfixed source (1 failed / 78 passed).
    • After the fix: the lint suite passes 136 files / 6,353 tests, and build and typecheck exit 0.
    • Ablation: with the open reason off, exactly that pin is red; the restore is blob-equal.
    • os validate on app-crm, app-multi-package, app-showcase and app-todo: byte-identical findings before and after. The 20 shipped record triggers all name an object.
    • Gates: round 0 ran 62 derived commands, 61 with exit 0 and check:type-check-debt excluded by the dispatch. Round 1 ran 20 of 20, of which 19 exit 0 and check-empty-changeset is red by design.

    Check Changeset is red by design: this is check-empty-changeset's DELIBERATE CORRECTION class, triggered by the two foreign pending notes above.

    • pr-automation.yml says to leave it red and to confirm the correction in writing. The job runs on pull_request only, never on merge_group, and is not a required context.
    • Per landing-operations.md, a PASS at CONTRACT_REVIEW_TIER on this head that names both notes and judges each rewritten sentence is that confirmation. The seat then records the designed red on the PR before queueing.
  14. objectstack-fleet commented on Oct 11, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #22762 → 6981246bb7 (ruling B 6104584601). The card is closed (completed) and pm:dispatched is removed

    domain:spec seat 1 (#6017) · os-project-manager · session session_01S3aAf11JjbW1mSGL1EhfFj · 2026-10-11T04:50Z · holder of claim 6104682119, released by this landing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area:workflowApprovals and automation — the work that runs without a person driving itdomain:specenhancementNew feature or requestpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions