From 99cc617bfe807d75e8231cf343aff018d25a217d Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 14 Aug 2026 04:32:48 +0000 Subject: [PATCH] =?UTF-8?q?docs(agents,pm-dispatch):=20bind=20a=20gate-uni?= =?UTF-8?q?on=20run=20to=20a=20commit=20=E2=80=94=20run=20it=20after=20the?= =?UTF-8?q?=20final=20commit=20and=20quote=20HEAD=20(#8550)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dev-seat contract said which gates to run and never when. A gate log carries no sha, so a union run taken before the last commits reports green over a tree that is no longer the head and nothing notices — and the natural order (implement, verify, answer review) puts verification before the final commits by construction. Ratchets make it sharp: a stale ratchet run is a claim about a ledger measured against different code. os-dev.md: the union contract now requires running after the final commit and quoting `git rev-parse --short HEAD` in the report and PR body, with a re-run (or at minimum the ratchet family) at the new head after any post-review push. Also records the third engine-double remedy the gate's own message does not name: override the file's existing double. review-checklist.md: the reviewer's half, placed beside the existing CI head-pinning clauses so the two read as one discipline — compare the quoted HEAD to the PR's current head.sha; a mismatch is a reading about a dead tree and counts in neither direction, an unquoted HEAD is no reading at all. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_018WuTtyckQa1VcXwgd52JpN --- .claude/agents/os-dev.md | 20 ++++++++++++++++++- .../references/review-checklist.md | 8 ++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.claude/agents/os-dev.md b/.claude/agents/os-dev.md index 8aef9ffcc2..51ffc4d200 100644 --- a/.claude/agents/os-dev.md +++ b/.claude/agents/os-dev.md @@ -135,7 +135,10 @@ quote. - A new fake engine's `delete()` opens with `assertEngineDeleteDispatch(options)` from `@objectstack/objectql` — never a hand-mirrored id/multi check, which has exactly the hole `check:engine-double-contract` names. Copy one of the pinned fakes the gate lists on a - green run. + green run. Needing a double the file does not already have? The gate's message offers + "pin the new one rather than raising it", but a third remedy it does not name is usually + better: **override the file's existing double** instead of declaring a second one — then + there is no new double to pin and no ledger to touch at all. ## Local verification scope — targeted gates locally, the full farm is CI's job @@ -156,6 +159,21 @@ reads the real gate-job conclusions after your report. ⛔ Not licence to skip t families — they are the cheap half you still owe; what you no longer owe is waiting for CI before reporting. +**Run the union AFTER your final commit, and quote `git rev-parse --short HEAD` from that +run** — in the report's `tests` field and in the PR body, both. A gate log carries no sha, +so a union run taken before the last commit reports green over a tree that is no longer the +head and **nothing anywhere notices**: neither you re-reading your own transcript nor the +PM reading the PR body can tell a covering run from a stale one, and the natural order +(implement, verify, then answer review) puts the verification before the last commits by +construction — so the failure lands hardest on the PRs that got the most review, which is +the wrong way round. Ratchets are why this bites: a stale ordinary-lint run is usually +still true, but a stale **ratchet** run is a claim about a ledger measured against +different code, and the ratchets are precisely the gates a late commit moves. On any +post-review push, re-run the union — or at minimum the ratchet family — at the new head +**before** the report or the PR body is updated. An unquoted HEAD is not a small omission: +it makes a green union unreviewable, so quote it even when the union and the final commit +were obviously the same tree. + ## Standard clauses live HERE, not in your dispatch prompt The prompt carries only per-card deltas (ruling quotes, the 裁决 / PM-机制假设partition, diff --git a/.claude/skills/pm-dispatch/references/review-checklist.md b/.claude/skills/pm-dispatch/references/review-checklist.md index 073443d8ef..6afcbe85b1 100644 --- a/.claude/skills/pm-dispatch/references/review-checklist.md +++ b/.claude/skills/pm-dispatch/references/review-checklist.md @@ -50,6 +50,14 @@ `head_sha` —— 不一致的 run 是关于一个死提交的读数,绿与红**双向都不入账**:旧 head 的绿会把「新推送未验」读成「消费者干净」,旧 head 的红会把当前 head 已修 掉的缺陷重新挂回 PR。 +- **dev 本地跑的门禁并集,同样先钉 head —— 同一条纪律,不是第二条**:dev 的契约 + 要求在**最后一次提交之后**跑并集,并把那一跑的 `git rev-parse --short HEAD` 抄 + 进报告与 PR 正文;复核就读这个 HEAD 与 PR 当前 `head.sha` 比一次。对不上 ⇒ 那 + 份「本地全绿」是关于一棵死树的读数,与上一条同理**双向都不入账**;正文没抄 + HEAD ⇒ 按**没有读数**处理(既不是绿也不是红),以门禁 job 结论为准。门禁日志不 + 带 sha,所以这个抄写是唯一能把一次绿绑到一棵树上的东西 —— 而复核轮之后又推了提 + 交、报告里的 HEAD 却没跟着动,正是它要抓的那一形:补跑并集(至少棘轮族)再更报 + 告,棘轮恰恰是最后一次提交会动的那一族。 - **被取代 head 上的 run 永不重跑**:非当前 head 上的 `cancelled` 结论零动作 —— 新推送自带全套 run。重跑烧掉一整个重量级周期,还能忠实复现一个已被当前 head 修 掉的缺陷、给绿 PR 挂上假红;实测两次误重跑都源于读到 `cancelled` 没先比对