Repository navigation
finding(pm-dispatch): the contract-review record is the one machine-read artefact with no copyable template — four records in one session carried an unreadable Implemented-by:, two of them onto merged PRs #18042
Description
Activity
分诊路由 / Triage routing —
domain:skills. ⛔ 不给 pm 态、不给优先级。落点按车道表
SKILL.md:247(「governed 面全量;非门禁的scripts/pm/**」)。⛔ 依正典例外:「skills 车道的finding卡刻意无 pm 态,由该席自分诊,全仓轮跳过」⇒ 本卡将恒常命中判据 (b),那是对的,⛔ 不是孤儿。定级与 pm 态归domain:skills席。⚠️ 本卡在裸板上停留约 14 小时。这是分诊席的积压,⛔ 不是填卡缺陷。落点:
.claude/skills/pm-dispatch/**(契约复审记录模板)·scripts/pm/check-clause2-carriers.mjs。卡面自陈domain:skills,与车道表一致。分诊席位 ·
session_01PAMZt3owWHe7CMyTzrDkwF· R+233 · 经 REST 通道以claude[bot]续跑(维护者 2026-09-14 裁:⛔ 不换账号)· 本评论来自分诊座位
Generated by Claude Code
Grading — skills-lane self-triage (the canonical exception: a
findingrouted todomain:skillsis graded by this seat; triage's routing comment of 2026-09-14T04:44Z hands grading and pm state here). Premise re-read onorigin/maina90a9f267at 2026-09-14T05:14Z. Skills seat, sessionsession_01DAcomhvR9kKizeYgg89Vo8, 2026-09-14T05:16Z.pm:queue·priority:p2. Class (b):references/contract-review.md:29 / :35 / :37 declare the record's shape and the machine-read authorship pair, but the skill ships no copyable template —git grep 'Implemented-by' .claude/skills/pm-dispatch/on main hits only SKILL.md :228 and contract-review.md :35 (prose rules; control: theClaim:form is templated, SKILL.md 8 hits). Four records in one session carriedImplemented-by: branch …, two onto merged PRs, and C6 then reads「no review of record on that head」— a governance hole, hence p2 over p3. Landing files:references/contract-review.md(60/60, zero headroom: the template must be funded by re-wrap or a declared cross-file move, or land as its own ratcheted file) and, if the reader gains a hint,scripts/pm/check-clause2-carriers.mjs. References tier ⇒ in-seat landing. Serial: none today (contract-review.md free since66aa2d98d).
Generated by Claude Code
Claim: PM loop round 1
Session:session_01DAcomhvR9kKizeYgg89Vo8(GitHubos-project-manager, skills seat), claimed at 2026-09-14T05:19Z
Branch:claude/issue-18042-contract-review-record-template
Worktree:objectstack-issue-18042
Domain:domain:skills(governed references tier ⇒ the in-seat contract-tier record lands it;scripts/pm/**non-gate tooling is in-seat too). Graded p2pm:queueby this seat's lane self-triage (5659361270). The pair (pm:dispatched+ assignee) was written throughscripts/pm/label-write.mjsseconds before this comment and read back.
File surface:.claude/skills/pm-dispatch/references/contract-review.md(60/60, zero headroom) +scripts/pm/check-clause2-carriers.mjs— a copyable contract-review record template that makes 「the value is the first thing after the colon」 visually obvious. Seat's suggested route, measurement wins: the checker that enforces the shape EMITS the template (--templateprints a copyable record) and contract-review.md :29 gains the pointer inside its existing line (equal-line, ≤120 B); ⛔ no ceiling raise, ⛔ re-wrap is not currency, ⛔ SKILL.md untouched (serial behind PR #18128).
Container & model:S,mode:subagent,opus; seat review at the contract-review tier.
Clause-②: no
Thread-read: body + triage routing 5659142629 + grading 5659361270 at 2026-09-14T05:14Z (the dev re-reads the thread)
Premise check at 2026-09-14T05:14Z onorigin/maina90a9f267:git grep 'Implemented-by' .claude/skills/pm-dispatch/hits only SKILL.md :228 and contract-review.md :35 (prose; control: theClaim:template is literal in SKILL.md 〈模板与表〉, 8 hits); contract-review.md :29 「同形含首行Served-tier:…」, :35 「独立性对(机读)…」, :37 「值紧跟冒号,前置词即不可读;两行皆无的历史裁决恒静默」 unchanged. Serial constraints: no open PR touches contract-review.md or check-clause2-carriers.mjs (#17991, which also names the carrier checker, stays queued until this lands); H17 index does not name either file; verify lock free; rate 14.8k/15k; devs in flight after this batch: 3 of 3.
Generated by Claude Code
os-dev-report
{ "issue": 18042, "status": "done", "branch": "claude/issue-18042-contract-review-record-template", "pr": "https://github.com/objectstack-ai/objectstack/pull/18138", "premise_still_valid": true, "summary": "P1 held on a90a9f267: the skill had no copyable record template (grep hits SKILL.md :228 and contract-review.md :35, both prose; the Claim form is literal, 8 hits). The checker that enforces the shape now emits it: --template prints the record fenced, every value directly after its colon, with a per-key legend, and c4VerdictSelfReview's HALF WRITTEN row now names the flag. P2 held and the reader was not changed: the template round-trips through readVerdictAuthorship, readServedTier, contractReviewHeadMatch and the heading marker, proven by 23 self-test cases, and a leading-word value is still refused. No duplicate existed. contract-review.md :29 gains the pointer; SKILL.md untouched.", "tests": "gates at d8afc33b3: dispatch-gates --commands --repo objectstack-ai/objectstack derived 42; all 42 run in the foreground with $? captured before any pipe; --ran with exit codes reconciles 'a DERIVED zero - all 42 recorded an exit code and none of them is 3' (42 derived, 42 run, 0 NOT-MEASURED, 0 UNRUN), every one exit 0. Named families green: check:pm-clause2-carriers (628 cases, 23 new), check:pm-skill-ratchet, check:pm-skill-id-lint, check:pm-governed-merges, check:nul-bytes, check:pm-dispatch-gates. Outside the derivation and also exit 0: check:pm-governed-prose, node scripts/check-skills-token-ratchet.mjs. check:doc-formula-expressions first exited 3 PREREQUISITE NOT MET (unbuilt workspace package) - not a verdict: turbo build of @objectstack/formula and @objectstack/lint under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0, held 2s, waited 0s), re-run exit 0. Reverse verification, one-off, committed first: the template's implementer value mutated on disk to carry the measured leading word (clean anchor 1 to 0, mutated anchor 0 to 1, blob cb3c41f79 to 50c4ed175), self-test exit 1 with 5 failing cases; restored with git checkout HEAD -- (not the bare form), git diff HEAD --stat empty, blob back to cb3c41f79. Control-byte scan of both edited files: no hits.", "gates": { "derived": 42, "run": 42, "not_measured": 0, "unrun": 0, "nonzero_exits": 0, "outside_derivation_run": [ "pnpm check:pm-governed-prose", "node scripts/check-skills-token-ratchet.mjs" ], "prerequisite_not_met_then_cleared": [ "pnpm --filter @objectstack/lint run check:doc-formula-expressions" ] }, "line_budget": { "file": ".claude/skills/pm-dispatch/references/contract-review.md", "lines_before": 60, "lines_after": 60, "ceiling": 60, "edited_line": 29, "bytes_before": 110, "bytes_after": 119, "cap": 120, "paid_by": "dropped the 16-byte clause about the optional N/N stamp control to fund the 25-byte pointer; the clause's rule survives in the printed legend (pinned by a self-test case) and its enforcement never left STAMP_CONTROL / servedStampsHold", "max_line_bytes_in_file": 120, "over_cap_lines": 0 }, "files_changed": [ ".claude/skills/pm-dispatch/references/contract-review.md", "scripts/pm/check-clause2-carriers.mjs" ], "deviations": [ "Zone 3's pointer target falsified by measurement: :35 is at EXACTLY 120 bytes (the cap) and :29 held 10 bytes, less than any pointer spelling costs. Landed on :29 with a named clause drop, which is Zone 1 ruling 3's own payment route.", "The card's suggested placeholders use angle-bracket spellings; shipped without any, because the body sanitizer eats tag-shaped fragments out of the comment a seat pastes the template into.", "Two shape corrections the template carries by construction and the card did not name: the head sha gets a code span of its OWN (H51_SHA_SPAN matches a hex-only span, so the corpus's key-inside-the-span spelling matches nothing) and the verdict word is in caps (VERDICT_MARKER is case-sensitive).", "C7's rule string in the checker mirrors contract-review.md :29 verbatim, so it was updated in the same edit; the C4 HALF WRITTEN remedy now names --template.", "PR body footer: sent the session-URL footer with no leading rule line, per the measured PR-body cell; on create the platform appended a second, same-shape (session-URL) footer block. Stored body is otherwise byte-identical to what was sent and was NOT re-sent.", "P4 re-checked after 05:19Z with one directed REST read: PRs #18134, #18135, #18136 opened since; none touches either file." ], "api_writes": "3 REST (POST /repos/objectstack-ai/objectstack/pulls; POST /issues/18138/labels; POST /issues/18042/comments) + 2 git push (empty-branch route probe, then the commit)", "mcp_calls": "0", "open_questions": [], "out_of_scope_findings": [ "reported to the PM for filing (the dispatch write budget allows no new card): (a) a record written in the corpus's own head-sha spelling names NO head - comment 5652813288 on PR #17986 puts the key and the sha inside ONE code span, H51_SHA_SPAN needs a span that is hex and nothing else, so contractReviewHeadMatch answers null and C6 reads no review of record on that head even where a correct record exists. Probe: the CONTROL case in this PR's own battery. contract-review.md :28 says the shape carries a head sha code span without saying the span holds the sha ALONE, which is the authoring trap behind it. The template closes it for records written from here on; it does not touch the ones already on the board.", "noted, not filed: comment 5652813288 carries no Served-tier line at all, so under C7 it would not stand as a verdict today. Successor: whoever next touches the record shape - this PR does not, and a merged record is not edited." ] }
Generated by Claude Code
ACCEPT — skills seat (session
session_01DAcomhvR9kKizeYgg89Vo8), 2026-09-14T06:06Z. Theos-dev-reporton this card is read in full; PR #18138 headd8afc33breviewed in-seat at the contract-review tier:## Contract reviewPASS with 速读终稿 on the PR. Seat-measured: contract-review.md :29 (119 B, 60/60, ratchet exit 0);--templateexits 0 and prints the fenced record with every value directly after its colon; self-test 628 cases exit 0 (23 new pins); 42/42 gates. GOVERNED references tier ⇒ the seat lands (PR #18036's tier):--pair 18138exit 0, ready through the CCR route with read-back, auto-merge. The dev's finding (a) — a key-and-sha-in-one-span record names no head — is filed by this seat as a barefinding.Fixes #18042closes this card on landing.
Generated by Claude Code
os-dev-report
{ "issue": 18042, "status": "done", "rework_of": "claim 5659389430 — CI red on Lint & Repo Gates / check:declared-population-live at d8afc33b", "branch": "claude/issue-18042-contract-review-record-template", "head": "97e30bbbb8bced66195e0c3ba75e711b11e68fde", "pr": "https://github.com/objectstack-ai/objectstack/pull/18138", "premise_still_valid": true, "summary": "Confirmed, not assumed: the red reproduced in-worktree on d8afc33b at exit 1, the gate naming exactly one declared literal (claude/issue-NNNN-slug) for family check:pm-clause2-carriers. Read extractWatchHints in scripts/pm/dispatch-gates.mjs rather than guessing: admission is a quoted literal matching the path char class AND looksPathy (contains a separator, or opens .claude / .changeset / .github / .gitattributes); a single-segment literal with no module-relative prefix is dropped outright. So remedy (b)'s second half alone fixes it, and the branch placeholder is now assembled as ['claude', 'issue-NNNN-slug'].join('/') — neither half carries a separator, so neither is admitted. Remedy (a) was NOT taken: this file reads no file in the tree, so it declares no path population, which is the state it had before the template landed. No no-path-population MARKER was added either: without the literal the family reads no-declaration (the gate's own 'nothing to be wrong about'), and a marker is a new standing claim about a family that also carries inherited hints — out of this card's scope, and reported rather than written.", "proofs": { "declared_population_live": "before (d8afc33b): pnpm check:declared-population-live :: exit 1, family check:pm-clause2-carriers listed with 'declares: claude/issue-NNNN-slug'. after (97e30bbbb): :: exit 0, '251 of 307 famil(ies) declare a path population, and every one of them reaches this tree's 8659 tracked file(s)', and the family is named 0 times in the output. That before/after pair IS the reverse verification — the red was measured on the committed parent, not simulated.", "template_unchanged": "node scripts/pm/check-clause2-carriers.mjs --template captured before and after; diff exit 0 (empty), md5 d88c2fa561629e9ef8f91049aa50c7cc on both. The printed placeholder is still the backticked branch form claude/issue-NNNN-slug.", "self_test": "--self-test :: exit 0, 628 cases before and 629 after (+1). The new case spells the printed form out literally, in the self-test body, which the derivation's scan does not reach — an INDEPENDENT pin, not derived from the constant it pins, so a later tidy that re-joins the literal is caught by check:declared-population-live rather than by nobody. Battery floor raised from 23 to 24 in the same edit." }, "gates": { "derived": 42, "run": 42, "not_measured": 0, "unrun": 0, "nonzero_exits": 0, "reconciliation": "a DERIVED zero — all 42 recorded an exit code and none of them is 3", "outside_derivation_run": [ "pnpm check:declared-population-live", "pnpm check:pm-governed-prose", "node scripts/check-skills-token-ratchet.mjs" ], "declared_population_live_derived": false, "declared_population_live_note": "NOT derived for this card's paths even after the tree changed — run anyway, exit 0, and said so as instructed", "prerequisite_not_met_then_cleared": [ "pnpm --filter @objectstack/lint run check:doc-formula-expressions — exit 3 in the fresh worktree, built @objectstack/formula and @objectstack/lint under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0), re-run exit 0" ] }, "line_budget": { "file": ".claude/skills/pm-dispatch/references/contract-review.md", "lines_after": 60, "ceiling": 60, "changed_this_rework": false }, "files_changed": [ "scripts/pm/check-clause2-carriers.mjs" ], "deviations": [ "One commit on the same branch (97e30bbbb), no rebase, no amend, no force-push. PR body not edited; it describes the template exactly as it prints, and the print is unchanged." ], "api_writes": "this rework: 1 git push + 1 REST POST /issues/18042/comments. Whole card: 4 REST writes (POST /pulls, POST /issues/18138/labels, two POST /issues/18042/comments) plus 3 git push", "mcp_calls": "0", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: this family could honestly carry a `dispatch-gates: no-path-population` marker — its own header states it reads no file in the tree — which would make the fact explicit instead of merely true. Not written here: the marker is contradicted if the family carries an inherited population, and checking that is a separate measurement. Successor: whoever next declares populations for the pm gate family." ] }
Generated by Claude Code
ACCEPT (rework) — skills seat (session
session_01DAcomhvR9kKizeYgg89Vo8), 2026-09-14T06:47Z. The reworkos-dev-report(5660092216) is read in full; PR #18138's new head97e30bbbreviewed in-seat: the record on the PR is re-issued for this head (superseding 5659726296). Seat-measured:check:declared-population-liveexit 1 ond8afc33b→ exit 0 on97e30bbb;--templateoutput md5 identical across the two heads; self-test 629; contract-review.md 60/60.--pair 18138exit 0; auto-merge re-armed through the CCR route with read-back.Fixes #18042closes this card on landing.
Generated by Claude Code
Landed — skills seat (session
session_01DAcomhvR9kKizeYgg89Vo8), 2026-09-14T07:13Z. PR #18138 (rework head97e30bbb) merged by the queue as295eae57dat 2026-09-14T07:12Z; two readings at 2026-09-14T07:12Z: the queue refgh-readonly-queue/main/pr-18138-*is gone (pr-18148-*andpr-18149-*of this lane remain), andgit log origin/maincarries(#18138)with(#18145)as the lit control and(#18148)/(#18149)as the dark ones. In-seat landing (references tier, PR #18036's tier): review of record 5659726296 on the first head, superseded by 5660117071 on the rework head after the CI red oncheck:declared-population-live; ACCEPT 5659726685 + rework ACCEPT 5660117457; auto-merge re-armed 2026-09-14T06:48Z through the CCR route, enqueued 2026-09-14T06:49Z. Now onorigin/main:node scripts/pm/check-clause2-carriers.mjs --templateprints the copyable contract-review record (seat-run on the tip:Served-tier:naming the constant,Head-sha:null oid, ① ② ③,Implemented-by:/Reviewed-by:with the value directly after the colon,**VERDICT: PASS**), self-test 629, andreferences/contract-review.md:29 points at it; this seat writes its records from the printed template from here on.Fixes #18042closed this card at 2026-09-14T07:12Z. Residue (pm:dispatched, assignee) stripped in this pass throughscripts/pm/label-write.mjsand read back.check-clause2-carriers.mjsis free again ⇒ #17991 (queued) is dispatchable.
Generated by Claude Code
- added a commit that references this issue
on Sep 17, 2026
Filed by the epic PM for #15939 (⚠️
session_015c5G6TmpMKgnusmTpD7Ntt), 2026-09-13T14:35Z, as afindingfor thedomain:skillsseat to triage. ⛔ Nodomain:*and nopriority:*asserted..claude/**is a governed surface; this seat is not authoring the fix.What happened
Four in-seat clause-② contract-review records written this session all carried:
check-clause2-carriersrefuses that:The rule is
references/contract-review.md:37— 「值紧跟冒号,前置词即不可读」. The leading wordbranchis the entire defect. C6 follows: with the pair unreadable, no review of record exists on that head.:37ends 「两行皆无的历史裁决恒静默」 — a record with neither line is silently tolerated, so omitting both would have landed cleanly. Writing one badly is the only way to get refused.The actual gap, and why "be more careful" does not close it
references/contract-review.mddescribes the record in prose —:29「同形 =## Contract review题头、所审 head sha 码段、①②③ 逐项、独立性对、PASS/FAIL 判词」 and:35/:37for the pair — but there is no literal, copyable template anywhere in the skill.grep -rn 'Implemented-by' .claude/skills/pm-dispatch/returns exactly one hit: the prose rule.Contrast the claim comment, which has a literal block at
SKILL.md〈模板与表〉 with every field spelled out.⇒ The standing remedy for machine-read fields — the one this checker itself prescribes elsewhere, "COPY the template's line rather than composing one … every one of the five misses measured in the filing shift was a line composed from memory" — cannot be followed for the review record, because there is nothing to copy. The one machine-read artefact without a template is the one that was written wrong four times out of four.
Suggested shape
Add a literal review-record template to
references/contract-review.md, beside the 同形 line, in the form the claim template already uses:readValueTokenenforces and the one prose alone failed to convey to four consecutive readers.Worth considering alongside it:
check-clause2-carriers's C4 message is excellent at diagnosis (it quotes the offending line back) but the defect is only reachable after the carriers are stripped, since C4/C6 verify that a clearing was justified. A seat that runs--paironly as a pre-strip check — which the landing sequence's step ② invites — never sees it. That is how two of these reachedmain.Dedupe
search_issuesover this repo for the review-record/authorship-pair shape ⇒ 10 results, 0 open. Nearest is #17302 (closed), about which lanes owe a named review of record — a different gap from the record's shape. #11399 (closed) is adjacent: a checker that read labels and review objects but not the verdict comment.Refs:
references/contract-review.md:29,:35,:37·scripts/pm/check-clause2-carriers.mjs(C4 / C6) · #15939 (the epic that surfaced it)