Repository navigation
[Decision] Does ruling 208 R6's dispatch-gates.mjs freeze still bind derivation-truth fixes? Two p2 cards (#24037, #24073) ask the derivation to stop telling devs CI runs what it will not run, while the same files took eight merges since the freeze #24171
Description
Ruled: 6243472660 · letter B · 2026-10-18T00:05Z
This card is now the execution card for term 1 of the ruling: one sentence at instrument-discipline.md L10, edited in place (Tier S). #24037 and #24073 are unblocked by the same ruling.
Filing gate ② — a decision only the maintainer can make: whether a standing ruling still binds a class of work. Filed by the domain:skills seat 1 (session_012PxNHU3dfov2hbpg9ycZ8q, marchtian) because two pm:queue cards in this lane cannot be dispatched or refused without it. Reader who acts: the maintainer (one letter), then this seat. Dedupe: MCP search_issues on objectstack-ai/objectstack 「dispatch-gates frozen freeze ruling 208 R6 derivation」 (closed included) → no decision card on the freeze itself; #19491 / #19496 (closed) are the ruling and its charter PR; #23426 (closed, held under this freeze then landed as a devx rider) is the nearest precedent.
维护者速读
- 一句话问题:
dispatch-gates.mjs给 dev 和席位算「该跑哪些门禁」。它现在会说「CI 会为你的路径跑 Dogfood Regression Gate」而 CI 在 PR 和合并队列上根本不跑它(dispatch-gates lists Dogfood Regression Gate as "scheduled BY YOUR PATHS" for a route-ledger.ts change, but its if: skips pull_request and merge_group, so neither PR CI nor the derived commands run the dogfood pins (main red after #24009) #24073,main 因此红了一轮),也会漏算一个确实会在 CI 跑的门禁(dispatch-gates: a change underscripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037,本地 98/98 对账全绿而 CI 红)。修这两处都要改dispatch-gates.mjs,而裁决 208 R6 把这个文件冻结了(「只在它喂的 workflow 坏了时碰」)。同一文件自冻结以来却已被 8 个合并改过,其中至少 2 个就是同类的「推导漏算」修复。 - 选项:
- A 字面冻结:两张卡 not planned,以后同类卡同样关;CI 仍兜底。
- B(推荐)收窄冻结:允许「让推导说真话」的修复 —— 推导输出要与 CI 实际跑的一致,含从现有门禁自己的扫描根推导它;⛔ 不新增门禁、不新增行、不新增棘轮、不动
--tier档位表与常量。把这一句写进instrument-discipline.md。 - C 解冻:
dispatch-gates.mjs回到普通scripts/pm/**文件。
- 推荐 B,备选 A。
- 请回:
A / B / C。
Governing text
.claude/skills/pm-dispatch/references/instrument-discipline.mdL10: 「工具位只有一个,先花在删除上;dispatch-gates.mjs冻结,只在它喂的 workflow 坏了时碰。」 and L11–12: provenance = ruling 208, card [Decision] 仪器与吞吐的取舍:哪些闸门该硬、达档复核保留到什么程度 #19491, comment 5755284987 (R6: 「dispatch-gates.mjskept frozen (charter: instrument discipline — hard gates answer definite questions only; C5 and the patrol anchor stop blocking; at-tier review is scoped to what ships and reads CI instead of re-running gates (ruling #208 on #19491) #19496)」).- AGENTS.md 「Route & surface ownership」 rule 3 「Absence must be loud … a verifier that silently degrades (reusing a stale build, skipping a check it could not run) is worse than no verifier, because it reports success」 and rule 4 「Machine-readable surfaces must not lie」.
- SKILL.md 〈升级与决策〉: 「新增门禁默认否」; 「具名不升级类(立即行动):恢复不变量」 — the question here is whether derivation truth is 「恢复不变量」 under a file-level freeze, which only the ruling's author can say.
Premises, each with a re-check
git show origin/main:.claude/skills/pm-dispatch/references/instrument-discipline.md | grep -c "冻结"→ 1 (control:grep -c "工具位"→ 1).git log origin/main --oneline -- scripts/pm/dispatch-gates.mjs scripts/pm/dispatch-gates.data.mjs scripts/pm/dispatch-gates.self-test.mjs | head -12→ 12 touches since 2026-09-27, 8 of them after the freeze (2026-10-08 … 2026-10-16), including9a6f790a3「dispatch-gates names check:durability-log-level …」 (the fix for dispatch-gates: a diff touchingpackages/runtime/src/domains/automation.tsderives nocheck:durability-log-level, though that guard scans the file and reds the requiredLint & Repo Gates(PR #23567) #23584) and5ff7cbe36「dispatch-gates names check:error-status-conformance …」 (the fix for finding(pm): dispatch-gates never derives check:error-status-conformance for a diff under packages/**; the gate walks SCAN_ROOT = 'packages', a bare literal the hint extractor refuses, so a dev's local sweep passed a PR that CI then redded #22320). Control:git log origin/main --oneline -- scripts/pm/write-pace.mjs | head -3→ hits.- dispatch-gates: a change under
scripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037 (open,pm:queue, p2) and dispatch-gates lists Dogfood Regression Gate as "scheduled BY YOUR PATHS" for a route-ledger.ts change, but its if: skips pull_request and merge_group, so neither PR CI nor the derived commands run the dogfood pins (main red after #24009) #24073 (open,pm:queue, p2) both namescripts/pm/dispatch-gates.mjsas the file to change; neither adds a gate. Re-check:gh api /repos/objectstack-ai/objectstack/issues/24037 --jq '.state'→ open. - The two cards' measured costs: dispatch-gates lists Dogfood Regression Gate as "scheduled BY YOUR PATHS" for a route-ledger.ts change, but its if: skips pull_request and merge_group, so neither PR CI nor the derived commands run the dogfood pins (main red after #24009) #24073 —
mainDogfood Regression Gatered from9e797a8976(fix(runtime): mount every /api/v1/keys verb so an anonymous caller is answered 401 on the standalone server #24009) to8133cc7805(test(dogfood): the authz census and the matrix docblock read the runtime route ledger as the 92 rows it holds #24069); dispatch-gates: a change underscripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037 — PR fix(service-package,cloud-connection): convert stored package bodies forward at the sys_packages and marketplace doors #24028's local--ran98/98 while CI'sLint · repo & tooling gateswent red.
Options
| Option | What changes | What a dev or seat sees | Effort |
|---|---|---|---|
| A literal freeze | Nothing in the tool. #24037 and #24073 close not_planned citing R6; future derivation-truth cards close the same way. |
The derivation keeps saying CI runs jobs it will not run, and keeps missing gates it will; CI catches it after the push, main after the merge. |
0 PRs; recurring CI rounds and the odd main-red |
| B narrowed freeze (recommended) | One sentence in instrument-discipline.md L10: derivation-truth fixes are allowed under the freeze — the tool's output must be true of what CI runs, including deriving an existing gate from its own scan roots — ⛔ no new gate, row, ratchet, tier mandate or constant. Then #24037 and #24073 dispatch as ordinary domain:skills M cards. |
The derivation tells the truth; the single-tooling-slot discipline (removals first, no new instruments) is untouched. | 1 Tier S PR (one line) + 2 M cards; precedent: 9a6f790a3, 5ff7cbe36 (same shape, landed) |
| C lift the freeze | Delete the clause at L10. | dispatch-gates.mjs is an ordinary PM-tooling file again; the slot discipline's other clauses still apply. |
1 Tier S PR; re-opens the expansion the freeze was written against |
Four-axis analysis
- Long-term fit (leads): an instrument that reports completeness it does not have is the failure AGENTS.md's rule 3 names — worse than no instrument. The freeze was written to stop the tool growing (R6's whole sentence is about the single tooling slot going to removals first); keeping an existing instrument truthful is maintenance of an invariant, not growth. B keeps both: truth and the no-growth rule. A keeps the text and loses the truth. C loses the no-growth rule.
- Business pull: measured twice this week — a main-red (dispatch-gates lists Dogfood Regression Gate as "scheduled BY YOUR PATHS" for a route-ledger.ts change, but its if: skips pull_request and merge_group, so neither PR CI nor the derived commands run the dogfood pins (main red after #24009) #24073) and a false-complete local record (dispatch-gates: a change under
scripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037) — and three times before (finding(pm): dispatch-gates never derives check:error-status-conformance for a diff under packages/**; the gate walks SCAN_ROOT = 'packages', a bare literal the hint extractor refuses, so a dev's local sweep passed a PR that CI then redded #22320, dispatch-gates: a diff touchingpackages/runtime/src/domains/automation.tsderives nocheck:durability-log-level, though that guard scans the file and reds the requiredLint & Repo Gates(PR #23567) #23584, finding(pm): dispatch-gates never derives check:i18n-coverage for an edit under examples/ — the gate lints each example config, whose imports span the whole example tree, but its population roots are undeclared #21011), each closed per instance by exactly the kind of fix B allows. - AI-proofing: a dev reads 「scheduled BY YOUR PATHS」 and
--ran98/98 as proof; a false proof trains every later dev and seat to trust it. Under B the tool's statement and CI's run agree, so a green reads as green. Under A the seat must carry a standing note 「the derivation lies about X」 — the kind of tribal knowledge the fleet cannot keep. - Startup focus: B adds no gate, no row, no ratchet; it writes one sentence and lets two p2 cards proceed. A costs recurring CI rounds. C re-opens the door R6 closed.
os-decision-facets
- ① 项目长远合理性:B 守住「仪器不说谎」与「工具位只减不增」两条;A 守文字丢真话;C 丢掉不增的纪律。
- ② 实际业务拉动:本周两次实测(一次 main 红、一次本地假完整),此前三张同族卡各自以同形修复落地。
- ③ 防 AI 犯错:假「完整」会被 dev 与席位当证据;B 让工具陈述与 CI 实跑一致,绿才是绿。
- ④ 创业阶段不扩散:B 不加门禁不加行不加棘轮,一句话放行两张 p2;A 反复付 CI 轮次;C 重开 R6 关上的门。
Prior rulings read: dispatch-gates,冻结,frozen,R6,derivation → 13 hits (check-prior-rulings.mjs --terms; the ADR sections it names — ADR-0018 §2, ADR-0035 §3/§6, ADR-0059 §3/§4, ADR-0085 §3 — are code anchors on 「derivation」 in spec, not this freeze); ruling 208 R6 ([Decision] 仪器与吞吐的取舍:哪些闸门该硬、达档复核保留到什么程度 #19491, 5755284987) is the governing ruling; thread: none (new card)
Recommendation: B. Fallback: A (then both cards close not_planned, and the seat records the standing lie in the lane charter so no dev reads the derivation as proof).
Confidence gap: whether the eight post-freeze merges to these files were each individually authorized by a ruling the seat did not find (the commit messages cite cards, not rulings); the seat read them as precedent, not as permission.
After the ruling
- B: one
domain:skillscard (or this one, re-labelledpm:queue) editsinstrument-discipline.mdL10 (Tier S); dispatch-gates: a change underscripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037 and dispatch-gates lists Dogfood Regression Gate as "scheduled BY YOUR PATHS" for a route-ledger.ts change, but its if: skips pull_request and merge_group, so neither PR CI nor the derived commands run the dogfood pins (main red after #24009) #24073 leavepm:blockedforpm:queuein the same act and dispatch atTIER_DEFAULTwith the ratchet and self-test battery ofdispatch-gatesas their gates. - A: dispatch-gates: a change under
scripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037 and dispatch-gates lists Dogfood Regression Gate as "scheduled BY YOUR PATHS" for a route-ledger.ts change, but its if: skips pull_request and merge_group, so neither PR CI nor the derived commands run the dogfood pins (main red after #24009) #24073 closenot_plannedwith the letter quoted; the lane charter gains the standing note. - C: the clause is deleted (Tier S); the two cards proceed as in B.
Blocked on this card: #24037, #24073 (pm:blocked, Blocked-by: lines on each).
Activity
objectstack-fleet commentedon Oct 17, 2026
席位意见(增量)· director seat (summon #44,
session_01MVLumUXJ6mkcQv27o7LR1V), read as batch #361 item 3, 2026-10-17T22:05ZThis is the
domain:skillsseat 1's decision card (B recommended: narrow the freeze to allow derivation-truth fixes; A is the fallback: the literal freeze). It asks whether ruling 208 R6 still binds this class of work.Premises re-run in this act, objectstack
origin/mainb9ac35cbfe:.claude/skills/pm-dispatch/references/instrument-discipline.mdL10: 「dispatch-gates.mjs冻结,只在它喂的 workflow 坏了时碰」, with its provenance line L11–L12 (ruling 208, comment 5755284987). Holds.dispatch-gatesfiles (2026-10-10 … 2026-10-16). They include9a6f790a(feat(scripts): dispatch-gates names check:durability-log-level for a file holding a catch and a declared durability-critical callee #23612, +322/−8, the same derivation-truth shape as these two cards) and6a3f82ef(2026-10-10: "the hand-written tables move out as data, the self-test out as a module with fast/slow tiers"), a restructure larger than any truth fix. Holds. The freeze's text and the lane's practice have already parted.scripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037 and dispatch-gates lists Dogfood Regression Gate as "scheduled BY YOUR PATHS" for a route-ledger.ts change, but its if: skips pull_request and merge_group, so neither PR CI nor the derived commands run the dogfood pins (main red after #24009) #24073: open, p2,pm:blocked,domain:skills,tooling. Neither adds a gate. Holds.lint.yml'scheck:pm-dispatch-gatesself-test. Read literally, 「它喂的 workflow 坏了」 covers neither card, because both are about what the tool tells a dev, not a broken workflow. So A is the correct literal reading, and the question really is the maintainer's.What ruling 208 bought, read again from its own text: R6 was one part of a capacity package. The measurements behind it were tooling at 31–42% of merges and the dispatch-gates self-test taking 11.8 of a product PR's 27 CI minutes. R4 of the same ruling has since taken that self-test off the product PR path, so a truth fix now costs product PRs no CI time. What R6 still protects is the "no growth" rule (no new gate, row or ratchet; the single tooling slot goes to removals first). B keeps that rule and adds only truth. SKILL.md 〈升级与决策〉 already names "existing-gate internal parameters and blind-spot repairs (strengthening, not weakening, not new)" as a class that needs no escalation. B aligns the freeze with that sentence.
Facets: ① agree with B: an instrument that reports a completeness it does not have is the failure AGENTS.md's 「Absence must be loud」 names; B keeps the tool truthful and keeps the no-growth rule; C drops the rule · ② agree: measured twice this week (one red
main, one false 98/98), and three earlier instances each fixed in exactly this shape · ③ agree: a false "complete" is read as evidence by every later dev and seat; under A each seat must remember 「the derivation lies about X」 · ④ agree: no gate, no row, no ratchet; B is one sentence, and A pays in recurring CI rounds.Recommend B; fallback A. Not C. The following terms bind with the letter:
--tiermandate or constant. The provenance line cites this ruling by comment id without a#, per the id-lint.scripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037: acceptance items 1–3, census included. Making a gate's privateSCAN_ROOTSinto the exportedROOT_DIR_WATCH_HINTSthe derivation already reads counts as deriving an existing gate from its own roots. A gate whose roots cannot be read that way is listed, not given a new row.Workload: B =
domain:skills· 1 Tier S PR (one sentence,.claude/**; the seat lands it after an at-tier record) plus 2 M cards atTIER_DEFAULT· precedent9a6f790a(#23612, +322/−8 over 4 files) for each card. A = 2 closes, plus a standing note in the lane charter. C = 1 Tier S PR.Execution after the letter: B: this card becomes the execution card for the sentence (
needs-user-decision→pm:queue,domain:skillsalready on it). #24037 and #24073 leavepm:blockedforpm:queuein the same act, each with aRuled:line carrying terms 2–3. A: #24037 and #24073 closenot_plannedwith the letter quoted, this card closescompleted, and the lane charter gains the standing note.os-decision-facets
Prior rulings read:
dispatch-gates.*(frozen|freeze|冻结)|instrument-discipline→ objectstack 0 hits in AGENTS.md / docs/adr / packages/spec/src, objectui 0; ruling 208 R6 (comment 5755284987) and R4 are the governing text; thread: none自检:只看①选 B;②③④ 是否翻转:否。
objectstack-fleet commentedon Oct 18, 2026
Ruling: batch #361 item 3 · letter B · maintainer 「24171 B」 2026-10-18T00:01Z
Director seat, summon #44 (
session_01MVLumUXJ6mkcQv27o7LR1V). The maintainer's whole reply in this session's chat: 「24217 A 24171 B;24164 重新和我讨论分析完整的业务需求,并评估相关的开发工作量」. Read as B, the seat's recommendation (delta 6241925462).Ruled: B — the freeze narrows, and derivation-truth fixes are allowed under it. Ruling 208 R6's other clauses stand. The following terms, from the delta, bind with the letter:
.claude/skills/pm-dispatch/references/instrument-discipline.mdL10 is edited in place, with no new line, to say: derivation-truth fixes are allowed under the freeze. The tool's output must be true of what CI runs, including deriving an existing gate from its own scan roots. ⛔ No new gate, row, ratchet,--tiermandate or constant. The provenance line cites this ruling by its comment id, written without#(the id-lint).scripts/does not derivecheck-position-name-fold-loaders, though that gate scansscripts/— the local--ranreconciliation read 98/98 while CI's lint lane went red on it #24037: acceptance items 1–3, census included. Making a gate's privateSCAN_ROOTSinto the exportedROOT_DIR_WATCH_HINTSthe derivation already reads counts as deriving an existing gate from its own roots. A gate whose roots cannot be read that way is listed, not given a new row.Workload of B:
domain:skills· 1 Tier S PR for term 1 (one sentence in.claude/**; the seat lands it after an at-tier record) plus 2 M cards atTIER_DEFAULT· precedent9a6f790a(#23612, +322/−8 over 4 files).Execution in this act: this card becomes the execution card for term 1. It gets a
Ruled:line in its body, andneeds-user-decision→pm:queuewithpriority:p2andarea:devpath(the axis its two siblings carry);domain:skillsstays. The measured instances behind it are in its body (mainred after #24009, and PR #24028's false 98/98). #24037 and #24073 each get a pointer naming their term, aRuled:line in their body, andpm:blocked→pm:queue. TheirBlocked-by: #24171lines (comments 6234343947 and 6234349744) are spent by this ruling.