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

Closed

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

    Claim: PM loop round 2 · 2026-10-10T22:11Z
    Session: session_016njDy8ozy9B9Ns5Y8kAWEK
    Account: marchtian (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-22636-runtime-gate-flow-entrances
    Worktree: objectstack-issue-22636
    Domain: domain:spec (packages/lint by the anchor exception; metadata-protocol by the cross-domain exception path, as triage 6095364551 declares)
    Seat: domain:spec#2
    File surface (at origin/main 0f77ff5202; stop on breach and explain in the report):


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 22636,
    "status": "needs_decision",
    "branch": "claude/issue-22636-runtime-gate-flow-entrances",
    "pr": null,
    "session": "session_016njDy8ozy9B9Ns5Y8kAWEK",
    "premise_still_valid": true,
    "summary": "Stopped before any edit. The branch was pushed empty at 0f77ff5 and carries no commit. The premise holds: a flow write's per-write snapshot carries no flows and no actions. W, however, cannot be built inside this dispatch, for three independent reasons, each measured at origin/main 0f77ff5. (1) The protocol.ts boundary. The context collections are not produced in runtime-authoring-gate.ts. evaluateRuntimeAuthoringGate (:1041-1046) only folds the four collections it is handed. Its only production caller, protocol.ts assertRuntimeAuthoringRules, gathers them at :6261-6287 (listCollection x4 in one Promise.all) and passes them at :6321-6345. The batch door's collectBatchPendingDeclarations (:22392-22394) is a -? mapped literal over RuntimePendingDeclarations (= RuntimeStackContext), so a new context key is a compile error there. Threading flows and actions therefore needs two edits in protocol.ts, the dispatch's stop-and-report file. (2) A packages/spec change. Once flows and actions are in CONTEXT_STACK_KEYS, the derived NAME_KEYED_STACK_KEYS (context intersected with written) gains both. Every flow-write and action-write finding path at the door then changes from flows[0]... to flows.NAME... and actions.NAME.... RuntimeAuthoringIssueSchema.path (packages/spec/src/api/protocol.zod.ts:560-571) declares the opposite: 'Every other write type is the sole member of its own collection, so its [0] is trivially stable and stays positional (flows[0]...)'. Keeping the paths positional instead would hand the caller flows[29], the def0d3e defect. The dispatch says: if a spec change is needed, stop and report. (3) A prior maintainer ruling. Ruling 5791822697 on #19527 (batch 215 item 4, maintainer approval quoted there) has item 3: 'No snapshot widening: RuntimeStackContext / CONTEXT_STACK_KEYS are unchanged'. Its option A (carry actions + tools) was not taken because 'it is paid on every gated write, the object / flow doors included'. Its governing text keeps universe-resolving rules off the door because they read stack.actions as a resolution universe, which is exactly what flowCelEntrances does. The LIT pin runtime-gate.inert-type-writes.test.ts:650-672 goes red by design under W. The claim's prior-rulings terms did not reach this ruling; the code cites it at runtime-gate.ts:182-186 and authoring-rules.ts:1141-1145. Measured beyond the stops: the phantom census, the rule census, a synthetic phantom vector W must close, the closure direction and the load path (tests field and open_questions). The opened-set gap is decided here as 'open the flow' and not built, because it rides the card's PR.",
    "tests": "No package suite ran because no code changed (git status --porcelain is empty; HEAD 0f77ff5). Build: OS_VERIFY_LOCK_SLOT=issue-22636 bash scripts/pm/os-verify-lock.sh -c "pnpm --workspace-concurrency=2 --filter '@objectstack/lint...' build" printed 'VERDICT command-exit 0 · held the lock 108s'. Measurements ran from scratchpad scripts only, never committed, against packages/lint/dist built at 0f77ff5. (a) Rule census. A Proxy logged top-level snapshot reads for every runtime-gated rule. 10 flow-write rules read flows: validateStackExpressions, validateFlowFilterTokens, validatePresetComparands, validateEmptyCombinators, validateReferenceIntegrity, validateFlowTriggerReadiness, validateFlowApiTriggerSecret, validateApprovalApprovers, lintFlowPatterns, lintFlowCredentialLiterals. Two of them also read actions: validateStackExpressions and validateReferenceIntegrity. Rules on other write types read the same collections too: validateStackExpressions on action and hook writes; validatePresetComparands on object, view, page, dashboard and report writes; lintLivenessProperties on datasource, email_template and mapping writes; validateReferenceIntegrity on dataset writes. CONTEXT_STACK_KEYS is uniform, so all of these would judge every stored flow and action on such writes. (b) Phantom census (#8309 discipline). BEFORE is the real gate (runRuntimeAuthoringRules). AFTER is a script re-implementation of the gate's differential, with flows and actions carried and the root judgment's stand-down removed. The widened gate does not exist, so AFTER is an emulation. Each shipped flow was written as a CREATE (the stack without it) and as a RE-SAVE. Findings per leg, before then after: app-crm (1 flow, 1 action) 0 then 0; app-todo (4 flows, 8 actions) 2 then 2; app-showcase (30 flows, 71 actions; collections loaded from source because the config's connector plugins are unbuilt) 14 then 14. In every leg after the change: 0 findings located on another entry and 0 new findings on the written flow. Build-door vs widened-door root refusals per flow: 0 mismatches. (c) Firing controls on the showcase stack, door refusals before then after. An edge 'user.id == "u1"': 0 then 1. 'record.status' with a type:flow action launching it: 0 then 0. 'record.status' with no entrance: 0 then 1. (d) Synthetic phantom vector, which the corpus does not exercise. Sibling G has the edge 'recrd.status == "open"'. The written flow F is record-triggered on a declared object and has a subflow node calling G. G's refusal ends '...or correct the name.' without F and '...did you mean record?' with F. The fingerprints differ, so G's pre-existing condition is charged to F's create. On a re-save the stored pass holds the finding but cannot cancel it: isLocatedOnAnotherEntry reads only the object prose spelling, and validateStackExpressions carries the flow prose spelling as its path. The same vector applies to an action write that launches G. dispatch-gates --commands --repo objectstack-ai/objectstack on the branch exited 2: 'this branch changes nothing against origin/main (merge base 0f77ff5) — nothing to derive'.",
    "mcp_calls": "0",
    "api_writes": "1 — POST /repos//issues/22636/comments (this os-dev-report, via scripts/pm/post-stamped.mjs on the route it selects). The git push of the empty branch is not a REST write. No pr_create and no label-write were used.",
    "open_questions": [
    {
    "question": "Does W go ahead against ruling 5791822697 item 3 ('No snapshot widening: RuntimeStackContext / CONTEXT_STACK_KEYS are unchanged')? Or does the runtime door's stand-down S become the by-design boundary?",
    "options": [
    "A — widen as triage 6095364551 directs, under a new ruling that supersedes item 3 for flows and actions. flows and actions join RuntimeStackContext. protocol.ts gathers them, and the batch accumulator routes flow and action drafts (protocol.ts in the surface). The RuntimeAuthoringIssueSchema.path describe changes, because flow and action paths become name-keyed (packages/spec/src/api/protocol.zod.ts in the surface). isLocatedOnAnotherEntry learns the flow prose spelling, and the did-you-mean phantom vector is closed. S and its pins are removed. Four axes. Business need: the MCP/Studio door would refuse user.id as validate does, but no shipped flow has an unbound root (census: 0 new refusals), so the pull is the trap class, not a measured incident. Long-term: one verdict at both doors (contract-first). Anti-AI: strongest, because the AI author's main door refuses the documented user/ctx/os trap. Startup: most expensive. Every gated write of all 16 types pays 2-4 more indexed sys_metadata reads plus the ADR-0087 replay of every stored flow and action (the cost item 3 refused). It also needs a spec wire-contract change and edits in three packages, and it creates a new phantom class to engineer away.",
    "B — keep item 3. S becomes the by-design boundary: its docblock and pins change from 'until #22636' to the ruling's reason, as the skill hold-out did, and W closes as not planned. Four axes. Business need: no measured incident is left uncovered. validate still refuses, and the run fails at first evaluation with an explicit error ('Unknown variable: user'). Long-term: consistent with the ruling that universe-resolving judgments belong to the whole-stack rule; the two doors keep a declared, pinned asymmetry. Anti-AI: weaker at MCP, where an AI author's save of user.id succeeds and fails only at run time. Startup: zero cost, no spec or protocol change, no new gate.",
    "C — widen for flow writes only, with a per-type gather in protocol.ts. This removes the cost on the other 15 types. But it is a second gather mechanism beside the uniform CONTEXT_STACK_KEYS, which the dispatch says not to invent, and it still needs the spec, protocol.ts and phantom work of A."
    ],
    "recommendation": "B. Three of the four axes favour it. Startup: A pays the per-write cost item 3 refused, plus a spec wire-contract change and a new phantom class. Long-term: B keeps the ruling's boundary for universe-resolving judgments. Business need: the corpus has zero pull, and the run already fails with an explicit error. The anti-AI axis favours A, and that is the real trade-off, because #4463 weighted the AI door highest; it is the maintainer's call. If A is chosen, the next dispatch needs protocol.ts (two sites) and packages/spec/src/api/protocol.zod.ts in its surface, sequenced after #22726, and Q2 answered."
    },
    {
    "question": "If W goes ahead (Q1 A or C): which stored flows and actions does the runtime door read?",
    "options": [
    "A — unnarrowed: the environment's stored flows and actions, as permissions, books and datasets are today. The door sees every entrance, including a dependent package's action. It reads more than the build door, which validates one package, so the runtime door may accept what validate refuses.",
    "B — the package closure (narrowObjectsToPackageClosure's limbs). Its universe agrees with the build door's. But entrances point from dependents to dependencies (a package that depends on P1 launches P1's flow), so the closure drops exactly the cross-package entrances and returns a false 422 on a flow that only a dependent package's action launches."
    ],
    "recommendation": "A. The closure was built for objects' scale and reference direction, and entrances run the other way. A false 422 on the only door a Studio tenant has is worse than the asymmetry, which is the module's own principle. A also follows the precedent of every non-object context collection."
    },
    {
    "question": "The opened-set gap (seat 3's note 6102568544): a record-* trigger with no start config.objectName. Open the flow, or refuse the trigger shape?",
    "options": [
    "A — open the flow in flowCelEntrances: kind record_change with no objectName adds an openedBy reason. Pin: such a flow is not judged, and the same flow with a declared objectName still is. This is lint-internal.",
    "B — refuse the trigger shape. This narrows an authoring surface, and its natural home is trigger-readiness, not the root judge."
    ],
    "recommendation": "A, decided here and not built, because it rides the card's PR, which this round could not open. Measured: record-change-trigger.ts:308-312 registers the hook with object: binding.object, which is undefined without objectName, and :389 reads binding.object ?? ctx.object. flowCelEntrances hands such a flow record and opens nothing, so a bare root that is a field only of an undeclared object is refused, although the run may flatten that object's row. Four axes. Business need: every shipped record-* trigger names objectName (loaded corpora: showcase 19 of 19, todo 1 of 1, crm has none; plus the 3 dogfood fixtures), the runtime honours the shape, and the spec leaves start config open. Long-term: A is the module's existing rule (an entrance handing a record whose keys are not in hand opens the flow), with no contract change. Anti-AI: refusing would make a forgotten objectName fail validation, which favours B, but that verdict belongs to trigger-readiness and would be a new gate. Startup: a new gate defaults to no. If Q1 lands on B, the opened-set gap and the owed map-child pin ('a map child of an open parent is opened by the fixpoint', a build-door pin) can land as their own small PR (Part of #22636). That PR widens validate's accept set, so its Clause-② reading is yes, not the claim's no (narrowing)."
    }
    ],
    "out_of_scope_findings": [
    "class: b · reach: named producer — runtime-gate.ts nameKeyFindingPath (:945) feeds evaluateRuntimeAuthoringGate's toIssue unchanged into the 422 issues[].path of a dataset save; also exception: release-text (the describe ships as the generated JSON schema and content/docs/references/api/protocol.mdx:2349) · evidence: RuntimeAuthoringIssueSchema.path (packages/spec/src/api/protocol.zod.ts:560-571) names the collection-resident write types as object / permission / book and says every other write type stays positional. Since #19143 a dataset write is collection-resident and its findings are name-keyed: runtime-gate.dataset-writes.test.ts:310 expects 'datasets.acme_invoice_metrics.dimensions[0].field' and :313 refuses a positional datasets[N]. Seam: spec:RuntimeAuthoringIssueSchema.path → runtime:nameKeyFindingPath (packages/lint/src/runtime-gate.ts:945) · dedupe words: RuntimeAuthoringIssueSchema path name-keyed dataset · collection-resident write types describe · issues path positional flows[0]",
    "carrier: if Q1 lands on A, the same describe edit W owes carries the finding above; otherwise there is no carrier, and it goes to the filing seat as written."
    ],
    "gates": "none run — no diff. dispatch-gates --commands --repo objectstack-ai/objectstack exited 2: 'this branch changes nothing against origin/main (merge base 0f77ff5) — nothing to derive'. The full lint suite and the metadata-protocol runtime-gate suites were not run, because there is no change for them to judge.",
    "line_budget": "n/a — no governed or skills surface touched",
    "deviations": [
    "Stopped before any edit under the dispatch's stop rules (protocol.ts surface; packages/spec change needed) and reported a ruling conflict instead of choosing a side. No PR, no label-write, no PR assignee.",
    "PM mechanism assumption 1 is half right. runtime-authoring-gate.ts:1041-1046 folds the four collections, but their producer is protocol.ts (assertRuntimeAuthoringRules :6261-6345 and collectBatchPendingDeclarations :22392-22394).",
    "PM mechanism assumption 2: the gate uses neither named mechanism. It uses the candidate-minus-baseline differential, plus #22118's stored pass for findings positively located on another entry.",
    "The claim's 'Nothing rules against this widening' is contradicted by ruling 5791822697 item 3.",
    "The phantom census AFTER leg is a script emulation of the differential, not the gate's code, because the widened gate does not exist."
    ],
    "files_changed": []
    }

  3. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    待裁(needs-user-decision):运行时发布门是否也要拦住「流程里用了没绑定的变量」?这要推翻 9 月 23 日裁决的第 3 条

    domain:spec seat 2 (#18549) · marchtian · session session_016njDy8ozy9B9Ns5Y8kAWEK · 2026-10-10T22:33Z · holder of claim 6102723366, released in this act. Thread-read: 6102874585 (the dev's needs_decision report).

    维护者速读

    • 改了什么: 没改代码。dev 开工前先实测,发现分诊给的方向和你 9 月 23 日的一条裁决冲突,就停下了。
    • 为什么要你定:
    • 席位意见: 荐 B:维持裁决,运行时门对这类问题按设计不判,只由 validate 判。回退 A:推翻第 3 条,对流程和动作扩大快照。
    • 你要做的: 回一个字母,例如「22636 B」。

    一句话问题

    AI 作者通过 MCP 保存一个流程,里面写了 user.id(这个变量在流程里根本不存在)。objectstack validate 会拒,运行时保存那道门不拒,要等流程真跑起来才报错。要定的是:保存那道门要不要也拒。

    背景

    Governing text

    • 裁决 5791822697 第 3 条(上引)。它的「Governing text」还写明:跨条目的「宇宙解析」类判断不过运行时门,因为它们把 stack.actions 当解析宇宙读(authoring-rules.ts 的 validateActionNameRefs / validateActionDispatchContract)。flowCelEntrances 正是这一类。
    • 代码里的引用:packages/lint/src/runtime-gate.ts:182–:186,packages/lint/src/authoring-rules.ts:1141–:1145。
    • LIT 测试 runtime-gate.inert-type-writes.test.ts:650–:672 按这条裁决钉住「一个 skill、一条规则、两个宇宙」,A 下按设计会变红。
    • 检索式:git grep -n "5791822697" origin/main -- packages/lint/src/。

    前提(各带复核命令)

    • P1(成立): 快照不含 flows / actions。复核:git grep -n "CONTEXT_STACK_KEYS" origin/main -- packages/lint/src/runtime-gate.ts。
    • P2(成立): 快照集合由 protocol.ts 收集,而非 runtime-authoring-gate.ts。复核:git grep -n "assertRuntimeAuthoringRules\|collectBatchPendingDeclarations" origin/main -- packages/metadata-protocol/src/protocol.ts。
    • P3(成立): 运行时门对流程变量绑定的判断现在站退。复核:git grep -n "perWriteSnapshotEntrance" origin/main -- packages/lint/src/。

    选项 × 真实代价 × 工作量

    选项 做什么 客户/作者看得到的后果 工作量
    A 推翻第 3 条,对流程和动作扩大快照;撤掉 S;spec 里 path 描述改为流程/动作按名;修上述误报向量 MCP / Studio 保存时就拒 user.id,两道门结论一致。代价:16 类写入每次都多 2–4 次索引读,外加所有存量流程和动作的 ADR-0087 回放(正是第 3 条拒绝的成本);错误路径从 flows[0]… 变成 flows.NAME…,对读这个字段的客户端是一次线上契约变化 3 个包(spec、lint、metadata-protocol)1 个 PR。参照 #22565 的 PR #22609(+1276/−6),本卡还多 protocol.ts 与误报修复,估计相当或更大
    B 维持第 3 条:S 由「等 #22636」改为「按设计」,文档与测试引用这条裁决;#22636 以 not planned 关闭 MCP 保存 user.id 照样成功,首次运行报明确错误;validate 照样拒。两道门有一处声明过、钉住的不对称 lint 1 个小 PR(改注释与测试措辞,约百行内),参照 #22730(+268/−48)以下
    C 只对流程写入扩大快照(按写入类型分别收集) 其余 15 类写入不付成本;但要在统一的快照机制旁另起一套,spec、protocol.ts 与误报修复一样不少 约同 A,另加一套收集机制

    业务含义直译

    • A: 前台收件时就把所有附件对一遍总账;每收一件都要翻一次总账,包括跟流程无关的件。
    • B: 前台只看这一件本身,对总账交给每晚的总审(validate);漏到前台的错,第一次办理时会被当场退回并写明原因。
    • C: 只对「流程」这一类件翻总账,但前台要多学一套收件流程。

    四轴分析(业务立场)

    • 项目长远合理性: B 与你的裁决和 ADR-0109 §3 的架构边界一致:跨条目的「宇宙解析」判断归整栈检查,运行时门只判单条目自身。A 让两道门结论一致(契约先行),但要把这条边界改掉,并新增一类要专门治理的误报。C 是两套机制并存。
    • 实际业务需求: 误报普查里三个示例应用都没有未绑定变量,改前改后零新增拒绝;拉动来自这一类陷阱本身,不是一次实测到的事故。漏网后果是「首次运行报明确错误」,不是数据错。
    • 防 AI 犯错: 这一轴偏 A:AI 作者最常用的就是 MCP 这道门,A 能在保存时就拒掉文档里点名的 user / ctx / os 陷阱。这是真实的权衡,[runtime/metadata] 作者时规则只存在于 CLI:Studio/REST/MCP 的运行时授权面是第四扇门,26 条规则一条不跑——#4409 修完后最大的敞口 #4463 曾把 AI 这道门的权重排得最高。
    • 创业阶段不扩散: B 零成本、不改线上契约、不新增门禁;A 让每次写入付成本,还改一处线上契约。

    os-decision-facets

    推荐:22636 B。回退 A(若你认为 AI 门的权重压过每次写入的成本)。

    • 终态:两年后仍是两道门分工:运行时门判单条目、整栈检查判跨条目引用。这和主流低代码平台一致:Salesforce 的 Flow 在保存时只做单流程校验,跨元数据依赖在部署和运行时校验。
    • 置信缺口:误报普查的 AFTER 一侧是脚本模拟,扩大后的门并不存在;A 的成本(每次写入多 2–4 次读取加回放)是按代码推算,没有压测。
    • 自检:只看①选 B;②④ 同向;③ 翻向 A,所以如实列出回退 A。工作量 A 约为 B 的 10 倍以上,在此点名。

    另两问(席位已答,不上箱)

    • 若裁 A,运行时门读哪些流程和动作? 席位答:整个环境存量,不按包依赖闭包收窄。入口方向和对象引用相反,是「依赖方启动被依赖方的流程」。按闭包收窄,会把只由依赖方动作启动的流程误拒(422),在 Studio 租户唯一能用的门上误拒,比两道门不对称更糟。
    • 「触发器没写 objectName」的缺口(第 3 席 6102568544): 席位答 打开该流程(在 lint 内,flowCelEntrances 加一个打开原因),⛔ 不拒收这种触发器写法(那是收窄可编写面、新门禁)。这一项和欠下的 map 子流程 pin 与 A/B 无关。

    裁后执行

    Release: session_016njDy8ozy9B9Ns5Y8kAWEK · why: the direction conflicts with maintainer ruling 5791822697 item 3, which no seat can override · to: needs-user-decision, unassigned. The branch claude/issue-22636-runtime-gate-flow-entrances stays at 0f77ff5202, empty, as the claim's marker.


    Generated by Claude Code

  4. 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.

  5. 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

  6. 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.

  7. 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"
    ]
    }

  8. 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.

  9. 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": []
    }

  10. 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.
  11. 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