Skip to content

docs(pm-dispatch): add the witness-grep leg to the in-flight overlap interception - #17956

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-17935-inflight-overlap-witness-grep
Sep 13, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-17935-inflight-overlap-witness-grep

Conversation

@claude

@claude claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Fixes #17935

The in-flight overlap interception asked exactly one question — do the file faces intersect — and
the card measures a coupling that question cannot reach: two PRs, each green on its own, red only
once both sit on one tree, because one PR's assertion NAMES a row the other deletes. This lands the
second leg the card's one-line criterion asks for.

The rule as landed

.claude/skills/pm-dispatch/references/dispatch-runbook.md, section 〈派发词构造细则〉, the new line
sitting directly under the file-face leg it extends:

- 在飞重叠每轮拦截:main 新落 PR 与在飞申报文件面求交,相交即发四句警告。
- 另一腿:本轮删/改名标识符 grep 每个在飞 PR 的 diff,命中同发,⛔ 不因文件面不相交跳过。
- 四句:合 main 重跑测试矩阵、读对方 diff 重划边界、只补它没覆盖的、被完全覆盖就停下。

Measured against the card's criterion (quoted verbatim, untranslated):

在飞重叠的检查项里,除文件清单外出现一条:核对是否有任一在飞 PR 的断言点名了本轮 diff 删除或改名的
符号 / 行 / 标识符
;⛔ 且该条不得以文件面互不相交为由跳过。

  • it greps against each in-flight PR's diff, not its file list — the cheapest of the two shapes
    the card suggests, and it needs no new tool;
  • 「命中同发」 gives a hit the same disposition an intersection gets: the four sentences, defined on
    the next line, so the two legs converge on one action;
  • 「⛔ 不因文件面不相交跳过」 puts the card's prohibition in the rule's own text, so the skip is
    refused where a seat reads it, not only in the card that filed it.

Line budget — 241 / 241, net 0

lines bytes note
ceiling (check:pm-skill-ratchet) 241 — headroom 0
before 241 17542
after 241 17554 +12 bytes, 0 lines
added +1 118 the new line, under the 120-byte cap
deleted -1 106 the density payment, below

The payment is a deletion inside the same section, not a re-wrap: the diff is exactly one removed
line and one added line, and no other line was re-flowed. The line deleted is

- ⛔ 不在消费者侧打补丁;只写一个路径名,是要求 dev 在守约与修对之间二选一。

and both of its clauses survive without it:

  • 「⛔ 不在消费者侧打补丁」 is already stated in SKILL.md line 549 —
    「文件面写两句:预期落点;生产者在别包时修生产者侧并报落点,⛔ 不在消费者侧打补丁。」 — and again in
    AGENTS.md Prime Directive 12 ("never add a lenient alias or ?? fallback in a consumer").
  • 「只写一个路径名,是要求 dev 在守约与修对之间二选一」 is a rationale tail for the rule stated two
    lines above it (「文件面两句原文照抄」), which already requires both sentences to be copied.

Those are the two categories this file's own ceiling comment names as removable, quoted from
scripts/pm/check-skill-line-ratchet.mjs at the dispatch-runbook.md entry: "provenance
narratives, incident post-mortems and rationale tails leave the corpus; one rule per ≤120-byte
line, no rule already stated in SKILL.md".

Acceptance greps — both directions

Run in the worktree at this branch's head against origin/main:

check before after
不因文件面不相交跳过 in the runbook 0 (exit 1) 1 (exit 0)
literal control 在飞重叠 in the runbook 1 1
git diff --stat origin/main -- .claude/skills/pm-dispatch/SKILL.md — empty (SKILL.md untouched)
wc -l on the runbook 241 241
LC_ALL=C awk 'length($0)>120' over the runbook prints nothing prints nothing
control-character self-scan over the runbook clean clean

SKILL.md is deliberately untouched: it is serial with another in-flight card this wave, and a
pointer there, if it is ever wanted, rides that file's next PR.

The new rule, applied to this PR

The leg this PR adds is cheap enough to run on the PR that adds it. This diff deletes exactly one
line; its distinctive identifiers were grepped against the diff — not the file list — of all 26
open PRs in this repository:

grepped identifier hits across 26 open PR diffs
只写一个路径名 0
二选一 0
不在消费者侧打补丁 0
positive control ⛔ (CJK rule text, same corpus, same grep) 21 of 26

The control is what makes the three zeros a reading rather than a broken grep. Same pass re-checked
the serial constraint the claim comment declared: no open PR touches dispatch-runbook.md.

The second shape — recorded, NOT built

The card offers a stronger shape that this PR deliberately does not implement:

更强的形状:凡编辑「在缩小的表」(ledger / 豁免表 / drift 表)的 PR,在派发令里互相点名,因为这类表的
对照必然点名其成员。

It is recorded here as an option, not a deliverable. It costs a standing classification (which
tables count as shrinking tables) that the grep leg does not need, and the grep leg already covers
the measured instance. If the grep leg proves to be run inconsistently, this is the escalation.

Adjacent rules that do NOT already cover this

SKILL.md line 479 — 「本卡 pin 断言兄弟卡在改的行为 ⇒ 派发令注明」 — is the mirror direction (this
card asserts on a sibling's behaviour) and fires only when triage already knows the pair. Line 450
— 「文件面不相交只保证文本可合并;跨文件语义耦合由队列 CI 逮住,⛔ 不读作不可能冲突」 — names the
coupling but routes it to queue CI, which is precisely the expensive half the card measured: the
queue does catch it, on the second PR, as a red. Neither is a mechanical pre-check, so this is not a
duplicate rule.

Gates

Derived from the tree with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths passed; derived at commit da4eee77), all run, reconciled
with --ran: 14 derived, 14 run, 0 NOT-MEASURED, 0 UNRUN — a derived zero, every family
carrying a recorded exit code.

node scripts/check-closing-keyword-parity.mjs                       :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test           :: exit 0
node scripts/check-comment-mask-corpus.mjs                          :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions   :: exit 0
pnpm check:agent-test-spelling                                      :: exit 0
pnpm check:doc-authoring                                            :: exit 0
pnpm check:driver-memory-census                                     :: exit 0
pnpm check:nul-bytes                                                :: exit 0
pnpm check:pm-governed-merges                                       :: exit 0
pnpm check:pm-skill-id-lint                                         :: exit 0
pnpm check:pm-skill-ratchet                                         :: exit 0
pnpm check:refd-timer-probe                                         :: exit 0
pnpm check:skill-frame-sync                                         :: exit 0
pnpm check:watch-hint-literal                                       :: exit 0
pnpm check:pm-governed-prose                                        :: exit 0   (named by the dispatch, outside the derived 14)

check:doc-formula-expressions first returned exit 3 — PREREQUISITE NOT MET, the gate's own
"nothing was measured" code, because @objectstack/formula and @objectstack/lint were unbuilt in
a fresh worktree. Built through the shared verify lock
(scripts/pm/os-verify-lock.sh, slot issue-17935, command exit 0) and re-run to a real exit 0.
The repo-wide sweep (pnpm lint and the whole gate farm) belongs to CI, not to this worktree.

No changeset: .claude/** ships nothing — the path is not inside any package's published files[]
— so this carries the skip-changeset label.

维护者速读(草稿)

改了什么 —— PM 派发手册里「在飞重叠」的拦截从一问变成两问:除了文件面求交,还要把本轮 diff 删除或
改名的标识符,拿去 grep 每一个在飞 PR 的 diff(不是它的文件清单),命中与相交同样发那四句警告,并且
⛔ 不许以「文件面互不相交」为由跳过这一问。全文只动这一个文件的两行(加一行、删一行)。

为什么改 —— 实测到一次两个 PR 各自全绿、合到一棵树才红:一个 PR 的测试点名断言某一行存在,另一个 PR
正好把那一行删了。两个席位都按现行规则查了文件面,结论都对 —— 规则问的问题本身答不到这个耦合。这个形状
不罕见:凡 ledger、豁免表、drift 表这类「在缩小的表」,它们的对照必须点名成员,否则对照没有意义。

风险与代价(含回滚) —— 代价是每轮派发多一次 grep,没有新工具、没有新门禁、没有新脚本。规则面净增
零行:新增那一行由同节内一行的删除买单,被删那行的禁令原文仍在 SKILL.md 第 549 行与 AGENTS.md 第 12 条
里,余下半句是上两行已有规则的理由尾巴。回滚 = 还原这一个文件的两行,不牵动任何代码、门禁或产物。

席位意见 ——

你要做的 —— 只需判断两件事:① 这一问是否值得每轮都问(代价是一次 grep);② 那条被删的行,它的禁令
落在 SKILL.md 与 AGENTS.md 上是否够。若都同意,人工合入即可 —— 这是受管面(.claude/**),按
Prime Directive 14 由维护者手工确认合并,本 PR 全程保持 draft,席位不翻 ready、不排队、不开自动合并。


Generated by Claude Code

…interception

The in-flight overlap check asked one question — do the file faces
intersect — so a PR whose assertion NAMES a symbol another in-flight PR
deletes or renames passes both seats' checks and goes red only once both
land on one tree. Add a second leg: grep this round's deleted/renamed
identifiers against every in-flight PR's diff, not its file list, and
never skip it because the file faces are disjoint.

Paid at 241/241 by deleting one line in the same section whose rule
survives in SKILL.md (「⛔ 不在消费者侧打补丁」) and whose remainder was a
rationale tail for the copy-both-sentences rule stated one line above.

Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8
Co-authored-by: Claude <noreply@anthropic.com>
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 13, 2026
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 13, 2026
@claude

claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Contract review

Head: da4eee77 (PR #17956, card #17935) — read at 2026-09-13T08:11Z by the skills seat at the contract-review tier (served model claude-fable-5-1, get_session external_metadata.last_served_model at 2026-09-13T08:08Z); the build was default-tier (model: opus; dispatch-gates --tier derives no path mandate for references/**), so this record is the compensating control.

① derived judgments: the diff is one file, +1/−1 against merge-base bdb247d9 (origin/main has since moved to c8a006fc by PR #17908, which touches no .claude/** path — measured, empty diffstat on this file between merge-base and main). (a) The new leg at :220 states the card's one-line criterion — grep the identifiers this round's diff deletes or renames against every in-flight PR's DIFF, a hit gets the same four-sentence disposition as a file-face intersection, and ⛔ never skipped on file-face disjointness — and sits directly under the interception line (:219) it extends, above the four sentences (:221) it reuses; the seat's own measured instance (objectui#9338 / objectui#9343, two PRs each green alone and red on one tree because one PR's assertion named a row the other deleted) is what the leg would have caught, and no rule or tool on origin/main asks for it (dev's grep witness|点名证人|deleted or renamed over .claude/skills/pm-dispatch + scripts/pm → only script-header prose; control 在飞重叠 hits SKILL.md :550/:551 and runbook :220). (b) Payment: the deleted :213 「⛔ 不在消费者侧打补丁;只写一个路径名,是要求 dev 在守约与修对之间二选一。」 — its prohibition is stated on origin/main at SKILL.md :549 (「…⛔ 不在消费者侧打补丁。」) and AGENTS.md :234 (Prime Directive 12, no lenient alias or ?? fallback in a consumer); 「只写一个路径名」 is the single X of :211 「预期落点是 X」; what is lost is the rationale tail (「是要求 dev 在守约与修对之间二选一」), which appears nowhere else — a density trade, flagged to the maintainer in the 速读 with the alternative the dev noted (SKILL.md :550 already carries a compressed copy of runbook :220, so :220 itself is the next density candidate). (c) Declared deviation accepted: the claim fixed the surface as :220–:221 AND payment inside 〈派发词构造细则〉; :220–:221 carry no deletable clause, so payment at :213 in the same section satisfies the section constraint and breaches the line-range one — declared in the report, not silent. Measured on the head by the seat: 241 → 241 lines (ceiling 241, headroom 0), no line over 120 bytes (new line 118 B), control-character scan clean, 不因文件面不相交跳过 0 → 1, 不在消费者侧打补丁 1 → 0, 只写一个路径名 1 → 0, control 在飞重叠 1 → 1 and 四句:合 main 1 → 1; single commit, Fixes #17935 once, one footer, ## 维护者速读(草稿) present. No accept-set or public-surface change (check-clause2-carriers --pair 17956 exit 0, seat-run, both carriers Clause-②: no, no widening tell).
② semver: .claude/** publishes nothing ⇒ skip-changeset (present on the PR, read back); consistent with the declared Clause-②: no.
③ boundary flags: none raised (open_questions: []). Two out-of-scope notes carried as the dev named them (SKILL.md :550 as the next density candidate for the #17905 SKILL.md chain; the /labels write silently no-ops without Content-Type: application/json, already in this seat's platform readings).

Implemented-by: claude/issue-17935-inflight-overlap-witness-grep (mode:subagent)
Reviewed-by: session_01DAcomhvR9kKizeYgg89Vo8

Verdict: PASS. Governed surface (.claude/**): no gate carrier was hung (the content limb is reviewed here); the PR stays a draft for the maintainer's hand merge.


Generated by Claude Code

@claude

claude Bot commented Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

改了什么 —— 只动 .claude/skills/pm-dispatch/references/dispatch-runbook.md 两行(加一、删一,241 → 241)。「在飞重叠」拦截从一问变两问:文件面求交之外,把本轮 diff 删除/改名的标识符 grep 每个在飞 PR 的 diff,命中同发那四句,⛔ 不因文件面不相交跳过。

为什么改 —— 你今早点名的第三张卡(#17935):两个 PR 各自全绿、合到一棵树才红,因为一个 PR 的断言点名了另一个 PR 删掉的那一行;现行规则只问文件面,答不到这种耦合。ledger、豁免表、drift 表这类「在缩小的表」都会再撞到。

风险与代价(含回滚) —— 每轮派发多一次 grep;无新工具、无新门禁。买单的是同节 :213 那行:它的禁令(不在消费者侧打补丁)原文仍在 SKILL.md :549 与 AGENTS.md 第 12 条,「只写一个路径名」就是 :211 的那个 X;真正丢的是半句理由(「要求 dev 在守约与修对之间二选一」),别处没有。若你想留这半句,替代买单是 :220 本行——SKILL.md :550 已有它的压缩副本——那要等 #17905 的 SKILL.md PR 一起做。回滚 = 还原这一个文件的两行。

席位意见 —— 收。本席在 head da4eee77 上亲核:新句 1、被删句 0、对照句在;无行超 120 字节;控制字符扫描干净;单父提交;check-clause2-carriers --pair 17956 exit 0;dev 侧 14 个派生门禁全 exit 0 并对账(含 check:pm-skill-ratchet 241/241);契约复核 PASS 记录在本 PR 上一条。dev 申报了一处偏离:认领指定 :220–:221 且同节买单,两者不能同时成立(那两行无可删子句),故买单落在同节 :213——已申报,本席接受。CI 在读时 Lint & Repo Gates(棘轮所在)仍在跑,其余全绿。base 已被 #17908 推进(不碰本文件),合入无冲突。

你要做的(一个动作) —— 受管面(.claude/**):CI 转绿后,若接受 :213 的买单就 approve 并人工合入;若要留那半句理由,一句话回我,本席退回 dev 改按 :220 买单。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 13, 2026 08:12
@os-zhuang
os-zhuang enabled auto-merge September 13, 2026 08:12
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 13, 2026
Merged via the queue into main with commit f62787c Sep 13, 2026
35 of 36 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-17935-inflight-overlap-witness-grep branch September 13, 2026 09:19
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 17, 2026
…ict declares (objectstack-ai#17990)

Fixes objectstack-ai#17915

`CONTRACT_REVIEW_TIER`'s own docblock declares the comparison against
the **served** tier EXACT — "never a family or prefix floor" — and
nothing in this tree performed it. The dispatching seat passes a model
as a dispatch parameter, and a passed parameter is configuration rather
than a reading; the docblock's other half said the re-review sub-round's
"opening self-check reads this", but a self-check is prose to the
reviewer, so a round that simply did not run it produced a verdict
indistinguishable from one that did. The census on the card measured 11
rounds served below the declared tier across four days and eleven PRs,
five of them the only clearance a merged `Clause-②: yes` pair ever had.

This lands items 1–3 of the director ruling: the verdict carries the
reading, and the strip is gated on it.

## What changed

**`.claude/skills/pm-dispatch/references/contract-review.md`** (2 lines
of new rule, net 0 at the ratchet):

- 〈复核归属与资格(席内)〉 gains, beside the 同形 definition:
  > 同形含首行 `Served-tier:`,值取复核者转录的 harness `model` 盖章;无此行不成裁决。
- 〈降档保险丝(机读)〉 turns the prose instruction into the mechanism it
described:
> 清标前 `--pair`:裁决 `Served-tier:` ≠ `CONTRACT_REVIEW_TIER` ⇒ exit 4,点名
PR、评论、读数。

**`scripts/pm/check-clause2-carriers.mjs`** — a new finding row, **C7**:

- `readServedTier` reads a `Served-tier:` key line with `Reviewed-by:`'s
own discipline (case-sensitive key, the markdown decoration a seat
writes without meaning it). Three-valued: `read` / `unreadable` /
`missing` — a carrier never started and one started and left unreadable
are different facts.
- ⭐ The value grammar is `[N/M ]tier`, **corrected from a fixture
against the live board** before shipping. Every record the ruling's own
remediation rounds are posting right now spells it control-first —
`Served-tier: 75/75 \`…\`` on PR objectstack-ai#17877, `138/138` on objectstack-ai#17498 — and the
ruling's specimen is written the same way. A reader that demanded the
tier token immediately after the colon would have refused every verdict
produced under the rule it enforces, on day one. The `N/M` is judged
rather than skipped: it is the zero-hit control the discipline already
requires, and a count that is not total is the 「回退证据」 whose own rule
text voids a verdict entire. Absent, it is vacuous — the tier alone
decides, which is the ruling's minimum, so nothing the ruling permits is
refused.
- `reviewOfRecord` carries the reading on the record it already chose,
so C6 and C7 can never disagree about which verdict a clear stands on.
- `c7ServedTierBelow` fires on **C6's population and no other** —
`needsRecordRead`'s completed state, i.e. a clearance judgment of a hung
carrier: declared `yes`, the gate bound and cleared on both carriers,
head unmoved. The refusal names the PR, the verdict comment and the
served value, at exit 4 (a limb not standing), never 3.
- The comparison is EXACT against `CONTRACT_REVIEW_TIER`, **imported**
from `dispatch-gates.mjs` so the model id keeps exactly one value site
across `scripts/pm/**` and `.claude/skills/pm-dispatch/**`. No model
identifier appears anywhere in this diff outside that import.
- 42 self-test cases in a new battery: the ruling's three (at tier
green, below tier red, line missing red), the live value shape and its
bulleted/bolded spelling, the control pins (`0/0` void, `12/133` refused
as fallback evidence, absent vacuous, a perfect control never rescuing a
below-tier value), the exactness pins (a family prefix and an extended
value both refused), and the four populations the row must never reach.

### Deliberately NOT in scope

A `Clause-②: no` pair that never carried the label is never refused for
lacking the line — it is not in the candidate shape, so the row cannot
reach it. A pair still carrying the gate owes nothing yet. An absent or
unsigned record stays C6's row alone. No PASS/FAIL token is read to
reach any of it: what produced a verdict is measurable, what it
concluded stays human.

## One deviation from the dispatched file surface — and why it is inside
it

The dispatch scoped the diff to those two files. It is those two files —
but one edit inside the checker was not foreseen and is worth reading
before approving.

`scripts/pm/check-clause2-carriers.mjs` carried a `dispatch-gates:
no-path-population` marker: "this gate reads no file in the tree at all
… so **no card's file surface can predict it**". The input half is still
exactly true. The other half stopped being true the moment C7's import
landed: a card editing `CONTRACT_REVIEW_TIER` moves the value every
clearance is judged against, so it *does* predict this gate. `pnpm
check:pm-dispatch-gates` catches this directly — its live-half case `no
family both DECLARES no path population and names paths anyway` went red
on `check:pm-clause2-carriers`, measured by ablation (base tree: hints
`[]`; with the import: hints `[".github/workflows"]`).

Keeping a declaration that stopped being true is the exact shape C7
itself exists against, so the marker is **retired**, and the comment
left in its place states the trade rather than hiding it: the import
channel contributes a followed module's *own* literals, so this family
now also inherits a `.github/workflows` lead it never opens, on a gate
whose CI step runs the self-test only. The designed narrowing
(`inherited-population`, declared by the followed module) cannot express
this case — it is per-**module**, and the same module's globs *are* a
real population for `check:pm-widening-tells`, which reads them. Filed
separately as objectstack-ai#17991 rather than worked around here.

⛔ The alternative — restating the tier in this file — is the thing that
let the declared tier and the served one drift apart in the first place,
and is refused.

## Acceptance measurements

All taken at `fed29ced`, against base `9ccc4179`.

| reading | before | after |
|---|---:|---:|
| `Served-tier` in `references/contract-review.md` | 0 | 2 |
| `Served-tier` in `check-clause2-carriers.mjs` | 0 | 26 |
| `Reviewed-by` in `references/contract-review.md` (lit control) | 1 | 1
|
| `references/contract-review.md` lines | 60 | 60 |
| `check-clause2-carriers.mjs` longest line (bytes) | 390 | 390 |

- Every line of `references/contract-review.md` is ≤ 120 bytes
(`LC_ALL=C awk 'length($0)>120'` prints nothing); the four edited lines
measure 105 / 113 / 111 / 108 B. The 120-byte register is the reference
file's; the checker keeps its own line style unchanged (471 → 502 lines
over 120 B, max unmoved at 390).
- `git diff --stat origin/main...HEAD` → exactly
`.claude/skills/pm-dispatch/references/contract-review.md` and
`scripts/pm/check-clause2-carriers.mjs`.
- Line budget, paid by density and not by re-wrap: `+1` the 同形 line,
`+1` the mechanism line replacing the 转录档位核验 prose, `-1` by folding 「⛔
自述档位不是读数」 and 「传参只是配置 ⛔ 不作达档读数」 into one clause (they are one rule: a
tier claim that is not a harness stamp is not a reading), `-1` by
dropping the 转录核验 grep recipe, whose method survives at :49
(「每场前必读服役档,读法见 `platform-readings.md`」) and in the new 同形 line. `node
scripts/pm/check-skill-line-ratchet.mjs` green at 60/60, headroom 0.

## Checks

- `pnpm check:pm-clause2-carriers` — **588 cases pass** (546 before this
PR; the C7 battery is 42 and is registered with its own floor,
`SELF_TEST_BATTERY_FLOOR` 19 → 20, preserving the roster's existing
slack).
- Gate families derived with `node scripts/pm/dispatch-gates.mjs
--commands --repo objectstack-ai/objectstack` (no paths) on the merged
head: **41 families, 41 run, 41 exit 0**. Reconciled: `--ran` reports
`41 derived famil(ies) accounted for — 41 run, 0 NOT-MEASURED (a DERIVED
zero — all 41 recorded an exit code and none of them is 3)`.
- `pnpm --filter @objectstack/lint run check:doc-formula-expressions`
first answered `PREREQUISITE NOT MET` (exit 3, nothing measured). Built
its two declared prerequisites under the shared verify lock (`VERDICT
command-exit 0 · held the lock 141s`) and re-ran it: exit 0.
- **Reverse verification** (both legs on the committed tree, restored
and verified by blob hash): adding the `Served-tier:` requirement turned
the reference record fixture red — `⭐ the objectstack-ai#14155 specimen WITH its
record still reads CLEAN overall` failed with `["C7"]` — before the
fixture gained the line. The row can fail.
- **Live control**, `node scripts/pm/check-clause2-carriers.mjs --pair
17956`: exit **2** on this head and exit **2** on the base script for
the same PR, same sentence (`PR objectstack-ai#17956 is not open, or names no card
this file can derive`). The pair could not be formed, so nothing about
it was judged — the dispatch expected 0 for a `Clause-②: no` pair, and
that PR has since left the open set. ⛔ Not a C7 refusal, and unmoved by
this diff.
- Narrowed lint, with its three readings: universe is `eslint .` over
one `eslint.config.mjs`; `npx eslint --no-inline-config --format json
scripts/pm/check-clause2-carriers.mjs` → 1 file, 0 errors, 0 warnings;
the narrowing excludes nothing because that config "never enables
type-aware linting (no `parserOptions.project`, no typed
`@typescript-eslint` rules) for ANY file" (its own line 328), so this
diff cannot move any untouched file's verdict. The `.md` is not an
eslint input.
- `grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'` over both edited files:
no hits; `pnpm check:nul-bytes` green.

## Changeset

`skip-changeset` — `scripts/pm/**` and `.claude/**` publish nothing:
neither path is in any package's `files[]`, and both are on the fast
track (`.claude/**` and PM tooling). Label applied and read back.

## Acceptance notes

- **Filed as objectstack-ai#17991** — the import channel's over-reach, with both
readings: `inherited-population` is keyed on the followed MODULE while
fabrication is a property of the CALLER (the same module's globs are a
real population for `check:pm-widening-tells`, which reads them), and
the `if (entry.selfTest) continue;` guard built to stop exactly this
inheritance never fires for a `pnpm check:*` family, because `selfTest`
is read off the workflow argv while the `--self-test` lives in the
`package.json` script body. Searched first: objectstack-ai#11556 (already resolved,
and left alone here) is the same class by a route its remedy cannot
express; no open card covers it.
- Noted, not filed: nothing else. No other adjacent observation reached
a reproducible defect, a quotable contract violation or an authoring
trap.

## 维护者速读(草稿)

**改了什么** — 契约复核裁决从此必须带一行 `Served-tier:`,值取复核者转录里 harness 逐消息盖的 `model`
字段;`check-clause2-carriers.mjs --pair` 在判定「双载体已清」时读这一行,不等于
`CONTRACT_REVIEW_TIER` 就拒(exit 4),并点名 PR、裁决评论和读到的档位。规则文本同步落在
`references/contract-review.md`,行数 60 → 60。

**为什么改** — 常量自己的 docblock 写着「与服役档的比较是 EXACT」,而树上没有任何东西在比。派进去的 model
是配置不是读数,「开场自检」是写给复核者的散文:一轮不跑它,产出的裁决与跑了的长得一模一样。卡上实测 11 轮在档下产出裁决,其中 5
轮是已合并 `Clause-②: yes` PR 唯一的清标依据。这是本仓在别处一律拒绝的 declared ≠
enforced,落在「一次公共契约加宽到底有没有被复核过」那道门本身。

**风险与代价(含回滚)** —
失败方向是响亮的:清标被拒,不是被静默放行。代价一:规则落地前写的历史裁决没有这一行,再被判定时会红,补救是复核席把自己转录里已经盖好的读数补写成一条新记录(最新的记录优先,不动载体)。代价二:本
PR 让这个门禁第一次有了树内依赖(`CONTRACT_REVIEW_TIER` 所在文件),因此退掉了它「无路径面」的旧声明;派生因此多送一条
`.github/workflows` 的线索,是噪音、已在文件里写明,并已记入验收备注。回滚 = revert 本 PR,一次 revert
即可,门禁回到今天的状态。

**席位意见** — (留空,待席位定稿)

**你要做的** — 受管面(`.claude/**`),本 PR 恒为 draft,⛔ 不由任何 AI 席位合并、入队或挂
auto-merge。请人工确认两件事:① 规则文本那两行的措辞;② 退掉 `no-path-population`
声明这一步是否接受(替代方案是把常量在本文件再写一遍,那正是让档位漂移的那个形状,已拒)。

## Provenance

Authored by the `domain:skills` seat's dispatched executor, session
`session_01DAcomhvR9kKizeYgg89Vo8`
(https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8), on branch
`claude/issue-17915-served-tier-gates-the-strip`. Attribution is stated
here in prose because a REST edit of a PR body appends its own footer
block: the first edit of this body left two, and this revision sends
none so the appended one is the only one.


---
_Generated by [Claude Code](https://claude.ai/code)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation needs-user-decision size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants