Repository navigation
docs(pm-dispatch): name MCP rerun_failed_jobs as the one exception to the no-MCP-write invariant - #22997
Conversation
… the no-MCP-write invariant The all-seats invariant said content writes go through the REST proxy only and no MCP write exists, while the platform readings record that MCP `rerun_failed_jobs` answers 201 and the deny roster does not carry it. A seat reading only the invariant waited on the maintainer for a re-run the rules allow. The invariant now names the exception on the same line, bounded by the CI-red single re-run and the head comparison. Paid in place under the 319-line ceiling and the 120-byte line cap: the fleet-identity clause and the attribution clause share the next line; the write-pace clause (3 s gap, 40 per hour, stop on 429) leaves the prose and stays enforced by scripts/pm/write-pace.mjs on every write; the AGENTS.md pointer leaves with it, AGENTS.md being the identity rule's authority. Claude-Session: https://claude.ai/code/session_01CinRQcE6T8SvMbhH8D3NhS Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Scope: the governed rule-text face — ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
维护者速读(终稿)· PR #22997 · #22979席位 1( 改了什么: 为什么改:两段文本冲突——SKILL.md 说无 MCP 写,platform-readings 记着 MCP 风险与代价(含回滚):两行协议文本,零运行时影响。删掉的节奏规则在 席位意见:ACCEPT;契约复核(达档、在席)PASS 已贴。两点要你知道:① dev 用 Edit 改这个文件时被 auto-mode 分类器拒绝(无理由),随后用 你要做的:同意即 APPROVED review,并亲手翻 ready、入队(或直接合并);或者在 PR/聊天里说一声「席位落」,席位按原样再发一次落地动作。 Generated by Claude Code |
Fixes #22979
Clause-②: no
The all-seats invariant in
.claude/skills/pm-dispatch/SKILL.mdsaid content writes go through the REST proxy only and no MCP write exists, whilereferences/platform-readings.mdrecords that MCPrerun_failed_jobsanswers 201 and the deny roster does not carry it. A seat reading only the invariant waited on the maintainer for a re-run the rules allow (the measured instance: the timing-drift red on PR #22935, re-run answered 201 once the maintainer asked). The invariant now names the one exception on the same line, bounded by the CI-red single re-run and the head comparison. Nothing wider: no other MCP write becomes permitted, the content-write rule and the relay identity stay as they were, andCONTENT_WRITE_TOOLS/permissions.denyare untouched.Line 92, before and after (verbatim)
Before,
origin/mainat712361b7a(identical at the dispatch's246edf5b3; no commit touched either file in between):After, this PR at
dea49749a:The exception's bound points at rules that already exist: the single re-run is the four-branch red handling in
references/landing-operations.mdlines 30–34 (known flaky re-submitted as is; a new signature re-run once only when the three facts hold; the same signature bouncing again stops it); the head comparison isreferences/review-checklist.mdline 47 andreferences/platform-readings.mdlines 295–296 (a re-run of a stale head cancels the current head's run, so a re-run is a write, not a read).Why two lines, and what paid for it
Work item 1 asked for the exception on line 92 as one line and, failing that, for the two spellings tried. The ratchet enforces a 120-byte line cap (
MAX_LINE_BYTES = 120inscripts/pm/check-skill-line-ratchet.mjs); line 92 stood at 116 bytes with the attribution clause alone at 69 bytes, so no honest one-line spelling exists. The two measured:rerun_failed_jobs(限 CI 红规则的单次重跑,先核 head);user.login记令牌不记席位,归属 = 文本里的 session ID。」 — 198 bytes;rerun_failed_jobs,先核 head);user.login记令牌不记席位,归属 = 文本里的 session ID。」 — 163 bytes.The ruling's remedy for a line that must be added is a deletion of content in the same file, declared here, so the edit stays at net zero lines and does not report
blocked:user.login记令牌不记席位,归属 = 文本里的 session ID) moves byte-identical to line 93, directly under the rule it qualified, and shares that line with the fleet-identity clause. It is not deleted.scripts/pm/write-pace.mjs, which everyscripts/pm/write tool runs behind (header rules ①–③: the 3 s gap, the 40-per-hour budget, the stop on 403/429), and in AGENTS.md's write-gate paragraph (write-pace.mjsserialises and spaces every write verb fleet-wide). The pace is enforced mechanically on every write whether or not the prose repeats the numbers.(AGENTS.md)pointer after the fleet identity. AGENTS.md is that rule's authority (every GitHub write leaves throughscripts/pm/, asobjectstack-fleet[bot]),references/rest-channel.mdline 10 restates it, and SKILL.md's priority line already ranks AGENTS.md above this file. With the pointer kept, line 93 reads 121 bytes.If the seat or the maintainer would rather keep the pace clause in the main file, the alternative is to report
blockedand have the maintainer name the line to give up; this PR takes the ruling's declared-deletion path instead and says so in the report.The other work items
references/platform-readings.mdis untouched: the head comparison is legible at lines 295–296; the single re-run is a rule, not a reading, and lives inlanding-operations.mdwhere line 92 now sends the reader; tightening line 292 to carry 「单次」 measures 123 bytes without dropping 「锁 1 未禁」, which is the load-bearing half of that reading (锁 1 is the deny list). 460/460 lines, unchanged..claude/agents/os-dev.mdis untouched: itsmcp_callsrule stands at line 62 (报告记api_writes与mcp_calls) and line 371 (a write tool in the list = this report is refused). The dev never re-runs CI..claude/settings.jsondeny roster, lines 81–99: 17mcp__github__entries, none forrerun_failed_jobsoractions_run_trigger;check:pm-settings-deny-rosterreads declared = enforced (17 = 17).CONTENT_WRITE_TOOLSinscripts/pm/check-settings-deny-roster.mjsnames neither tool. No settings change is needed to name the exception..claude/**at Tier S, and the dispatch dispatched it as Tier S. This PR follows AGENTS.md.Ratchet reading per file
.claude/skills/pm-dispatch/SKILL.md.claude/skills/pm-dispatch/references/platform-readings.mdGates, at
dea49749aDerived with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths; 1 path vs merge base712361b7a): 20 commands. All 20 run with exit codes recorded;--ranreconciliation:✓ dispatch-gates --ran: 20 derived famil(ies) accounted for — 20 run, 0 NOT-MEASURED (a DERIVED zero — all 20 recorded an exit code and none of them is 3).Two more named by the dispatch and outside the derivation, also run green:check:pm-settings-deny-roster,check:skill-frame-freshness.One derived gate,
pnpm --filter @objectstack/lint run check:doc-formula-expressions, first exited 3 (prerequisite not met:@objectstack/formulaand@objectstack/lintnot built). Built under the shared verify lock (os-verify-lock: VERDICT command-exit 0 · held the lock 1s · waited 0s, all four tasks cached), then re-run: exit 0.Verdict lines as the gates printed them:
Control-byte self-scan of the edited file: zero matches. No package is touched, so there is no build closure and no package test to owe;
pnpm lintstays CI's run.skip-changeset:.claude/**publishes nothing.Acceptance notes
.claude/**); noted here, not filed.git apply(the one bare-action retry the platform readings allow), and the diff above is the whole of it.维护者速读(草稿)
改了什么:PM 协议主文
SKILL.md第 92 行,「⛔ 无 MCP 写」这条全席位不变量现在同一行点名唯一例外:MCPrerun_failed_jobs,只限 CI 红规则的单次重跑,动手前先核对 run 的 head 与 PR 当前 head。第 93 行改为写侧身份 + 归属条款(归属条款原样搬过来,一字未改)。原第 93 行的节奏条款(3 秒/笔、每账号每小时 40 笔、429 即停)离开散文,仍由scripts/pm/write-pace.mjs在每一笔写上机械执行。platform-readings.md、os-dev.md、settings.json三个文件都没动。为什么改:规则与读数打架 —— 规则说没有 MCP 写,读数说
rerun_failed_jobs回 201 且锁 1 没禁。席位按「两条细则冲突按更严的一条」等了你一次本可自己做的重跑,这是你在卡片上问的那个成本。规则现在自己说出例外,下次席位不再等人。风险与代价(含回滚):① 例外只点名一个工具,并绑定既有的单次重跑规则与 head 核对,没有放宽任何别的 MCP 写;deny 名单与
CONTENT_WRITE_TOOLS原样。② 节奏数字不再出现在主文散文里,只在write-pace.mjs的头部与 AGENTS.md;所有写工具每笔都走 write-pace,行为不变,少的是一行提醒。③ 行数棘轮 319/319、字节上限 120 都守住,门禁全绿。回滚 = revert 这一个提交,两行回到原样,零数据影响。席位意见:
你要做的:本 PR 落在
.claude/**,按 AGENTS.md 第 14 条是 Tier S,由席位达档复核 PASS 后走队列落地,不需要你点批准。只有一件事值得你说一句:若你不同意节奏条款离开主文,席位会改为由你指定要删的那一行,或由你决定抬一行上限。Generated by Claude Code