Repository navigation
[finding] the reading discipline mechanically guards a ZERO but not a WRONG NON-ZERO — six instances in one shift, five of them the seat's own #18798
Description
Activity
Claim: PM loop round 1
Session:session_01Gqi43smmqjJ5sUrhfoPeKu
Branch:claude/issue-18798-non-zero-reading-owes-a-control
Worktree:objectstack-issue-18798
Domain:domain:skills
Seat:domain:skills#1
File surface:.claude/skills/pm-dispatch/references/core-rules.mdonly (rules layer, 151 / 151 at the ratchet ceiling, rows ≤ 120 B; :45 「零命中须配同主体必中词,否则该零作废;同仪器的控制词双零是仪器坏,⛔ 不读作缺席。」 is the ONE mechanical demand the discipline makes of an instrument and it guards a ZERO only — the companion maxim 「非零不证明尺子对」 has no paired action, and the card's six instances (five of them non-zero readings that reached a card, a brief or a dispatch) plus the triage's two own instances (a three-set diff structurally blind to same-round in-and-out; a unit-correct, control-lit, true count that answered the WRONG question) are the measured cost; deliverable = the mechanical demand extended, in ≤ 2 rows paid in-file, to any reading that another agent will ACT on (a card, a brief, a dispatch — ⛔ not a seat's own use-and-discard probes, the card's own boundary that the triage endorses): the reading states its UNIT and answers the triage's second question — 「what would have made it NOT this value」 — and a lead handed to a dev is marked 「⛔ a lead, not an answer — walk it yourself」; ⛔ SKILL.md :163 (the same zero rule in the skill's own words) is NOT touched — SKILL.md is serial behind PR #18666 / #18679 — the dev runs the mirror gates and reports whether the skill line must move in lockstep (then the seat queues that half); ⛔platform-readings.md:226–:227 are NOT touched either — #18774 is on that file now, and any fact rows this card wants there queue behind it; ⛔ no blanket 「every number needs a control」 — the card and the triage both refuse that tax, and so does the seat); rules layer ⇒ draft at the governed terminal, the seat's four-piece, the maintainer lands
Container & model:M(非零读数的机械要求一到两行 + 单位与反问 + 线索标记),mode:subagent,model: claude-opus-5—node scripts/pm/dispatch-gates.mjs --tier --repo objectstack-ai/objectstack .claude/skills/pm-dispatch/references/core-rules.mdat 2026-09-17T21:48Z on the fast-forwarded tree (9846f2763c): 「Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s)」; default tier taken; the seat's contract-tier review at delivery
Clause-②: no
Thread-read: 5721561755
Serial constraints cleared: 28 open PRs' file lists read at 2026-09-17T21:46Z — none touchescore-rules.md(PR #18511's :112 re-key LANDED earlier);os-verify-lock.sh --statusat 2026-09-17T21:46Z: free; shared checkout atorigin/main9846f2763c. Hot-file queue behind this card on core-rules.md: #18536's rules half. Sibling cards the triage names for one trip: #18755 (p2, 「a lit control certifies the INSTRUMENT, not the QUESTION」 — SKILL.md serial) and #18744 (p2, HELD: its measurement burns the shared GraphQL pool) — read, ⛔ not folded: the seat keeps three cards three PRs because their levels and files differ. Slot: the one freed by #18683's delivery (PR #18799, under the seat's review); #18721 and #18774 in flight; PR #18796 (#18664) under review; PR #18795 (#18527) four-piece hung. Total order at 2026-09-17T21:48Z: p1 — #18774 (dispatched) · this card; p2 — #18536 (SKILL.md serial) · #18699 (behind PR #18725) · #18743 (SKILL.md serial) · #18744 (HELD) · #18755 (SKILL.md serial) · #18764 (behind PR #18799); p3 — #18622 · #18662 (FREE, next) · #18665 (SKILL.md serial) · #18686 (behind #18744) · #18705 (MANDATORY).
Ruling-ref: 5721561755
Generated by Claude Code
os-dev-report
{ "issue": 18798, "status": "done", "branch": "claude/issue-18798-non-zero-reading-owes-a-control", "pr": "https://github.com/objectstack-ai/objectstack/pull/18809", "head_sha": "46b7bd6a464a21406556ff297350cb0410fb5381", "files": [ ".claude/skills/pm-dispatch/references/core-rules.md" ], "session": "session_01Gqi43smmqjJ5sUrhfoPeKu", "premise_still_valid": true, "premise_check": "Verified on origin/main before writing. HOLDS with one correction that strengthens the card: core-rules :45 is indeed the ONLY mechanical demand made of an instrument and it guards a zero (git grep '零命中' over .claude reads 4 lines - core-rules :45, :51 second clause, SKILL.md :163, os-dev.md :72 - lit control '控制词' reads 7 lines, absent control 0/exit 1). The CORRECTION: the companion maxim the card quotes, 「非零不证明尺子对」, is NOT on the tree in any spelling (git grep '非零|尺子' over .claude + AGENTS.md reads ONE line, os-dev.md:227, about a non-zero EXIT code; controls as above). So the non-zero side had not even a maxim, let alone a paired action. The card's :51 observation holds verbatim: its third clause repeats the zero rule for triage dedupe.", "summary": "One row added to .claude/skills/pm-dispatch/references/core-rules.md at :46, directly under the zero rule it generalises, and paid in file: 151 -> 151 lines, 3 insertions / 3 deletions, one file. The row carries three clauses - the reading states its UNIT, it answers the triage's second question 「什么本来会让它不是这个值」, and a reading handed to a dev as a lead is always marked a lead rather than an answer. Scope is the card's own criterion 「他人据以行动的」 (a card, a brief, a dispatch), so a seat's use-and-discard probe owes nothing and no blanket tax on every number is written or implied. Draft PR #18809 opened, skip-changeset labelled, left draft: the seat's four-piece and the maintainer land it.", "row_added_verbatim": { "path_line": ".claude/skills/pm-dispatch/references/core-rules.md:46", "text": "- 他人据以行动的读数须带单位并答什么本来会让它不是这个值;递 dev 的恒标线索非答案。", "bytes": 119, "cap": 120, "placement": "immediately under :45, the zero rule it generalises" }, "rows_paid": [ { "row": "core-rules.md :51 (was 119 B) - RETIRED, the whole line", "clause_1": "「分诊查重零命中须控制词」 - THE PAYMENT: a near-duplicate of :45, which already states the zero rule generally and unconditionally, so the dedupe instance adds no mechanical demand. This is the duplication the card itself names.", "clause_2": "「子代理自死不等于维护者中止,需显式信号」 - merged into :111, the claim-reclamation rule it governs. New :111 (119 B): 「- dev 自死不等于维护者中止,需显式信号;回收前先救工作树,有提交的活分支 ⛔ 永不回收。」 'dev' is SKILL.md :174's own word for the subject.", "clause_3": "「立卡者只附查重词」 - merged into :80, the execution-versus-triage division of labour. New :80 (102 B): 「- 执行席 ⛔ 跳过分诊动作,读到标签当既成事实;立卡者不查重、只附查重词。」 The added 「不查重」 is SKILL.md :176's own spelling, not new content." } ], "payments_refused": "Two other shapes were weighed. (1) An adjacent-pair merge: the ratchet's own comment on this file MEASURED zero of its adjacent bullet pairs merging under the 120 B cap (smallest 156 B); re-measured by hand, reproduced. (2) Merging the two preamble lines :2-:3: it frees a line, but every spelling that keeps 「本文不新增规则」 verbatim measures 133 B or more, so it can only be bought by deleting the file's own self-description - worse content to spend than a duplicated clause. ⛔ No re-wrap was used as currency; the only content deleted is the duplicated clause.", "eight_instances": [ { "n": 1, "instrument": "startswith('Blocked-by:') over issue bodies", "answered": "bodies only, line-initial, undecorated - the comment channel and decorated lines are invisible", "caught_by": "② (a Blocked-by: in a comment moves the number not at all)", "cost": "two non-defects entered a handover brief as work items" }, { "n": 2, "instrument": "grep -E '^[-+][^-+]' over a charter diff", "answered": "the doc's lines start with '- ', so its changed diff lines read '--' and were excluded", "caught_by": "② (needs a known-changed line as positive control)", "cost": "'almost nothing changed' - really 46 + 14 lines including a reversed rule" }, { "n": 3, "instrument": "a starred control reading 'this package's routes do i18n lookups'", "answered": "every hit was a comment or a metadata key name", "caught_by": "② only; ① does NOT catch it (if the routes did not do lookups the grep still reads non-zero)", "cost": "an option costed an order of magnitude low" }, { "n": 4, "instrument": "a package_version_id grep handed to a dev as a lead", "answered": "the zero was true; the mechanism was elsewhere", "caught_by": "③ the lead clause ONLY - neither ① nor ② catches a correct reading pointing the wrong way", "cost": "caught in time only because the dispatch said it was a lead" }, { "n": 5, "instrument": "git grep -c ... | wc -l to count call sites", "answered": "it counts FILES", "caught_by": "① directly, ② as well", "cost": "reported 5 call sites; there are 9" }, { "n": 6, "instrument": "a PARAPHRASED calibration case (cloud#2020, the card's origin)", "answered": "it passed for the wrong reason - the paraphrase dropped the sentence carrying the cue", "caught_by": "② (answerable only against the verbatim excerpt it is not)", "cost": "the class the dev named: an ablation that passes because nothing was mutated" }, { "n": 7, "instrument": "the triage seat's own three-set endpoint diff, residual 0", "answered": "structurally blind to same-round in-and-out", "caught_by": "② only; ① does NOT catch it (the unit, cards, is right)", "cost": "the residual read correctly only because the seat remembered judging the card" }, { "n": 8, "instrument": "the triage seat's own #18791 grep - unit right, control lit, count true", "answered": "the WRONG QUESTION: who has already written the bad value, not who is TEACHING it", "caught_by": "NOT CAUGHT - see wrong_question_boundary", "cost": "#18791 went p2 until re-measured, then p1" } ], "wrong_question_boundary": "Reported as a measured disagreement with the triage's expectation rather than smoothed over. The triage proposed ② as the question that catches the zero, the non-zero AND the unit-correct-but-wrong-question shape. Measured against the row as written it does NOT catch instance 8: ① is satisfied, ② is answerable ('an authored block carrying the bad value would have made it non-zero'), and the reading was true. What fails there is the QUESTION, which is exactly #18755's shape. One wording would reach it - binding ② to the CONCLUSION the reading is carried for ('what reading would have overturned the call this number is used to make') rather than to the instrument - and it was refused on the axes: it costs a re-derivation of the decision per reading (创业阶段不扩散 / the card's budget boundary), and it would silently absorb #18755 while that card is open and graded p2 on its own, which the triage's own dedupe ruling refuses.", "four_axis_written": "① + ② together, in one row. ① alone (the card's original candidate) is refused outright by instance 8 and was already refused by the triage.", "four_axis_reasons": { "实际业务需求": "Measured on the eight instances, not on which question reads better: ① alone catches 1 of 8 (#5); ② alone catches 6 of 8; neither covers the set, and instance 4 needs the third clause. ① costs one word per reading and buys the one instance whose defect is purely a unit error, so dropping it saves no budget and loses the cheapest catch in the corpus.", "项目长远合理性": "They are different kinds of obligation and collapsing them hides the cheap one behind the expensive one. ① is a FORMAT demand that keeps a number self-describing when the next seat re-reads the card weeks later; ② is an EVIDENCE demand about the instrument. A unit-less number in a landed card cannot be re-checked by anyone at all.", "防 AI 写代码犯错": "The deciding axis. ② can be discharged with a plausible sentence and an AI seat is very good at plausible sentences; ① is mechanically refusable by a reader (is there a unit word beside the number or not). Keeping the loud, checkable half is the contract-first choice, the same reason a strict schema beats a tolerant consumer.", "创业阶段不扩散需求": "The tax is bounded by the SCOPE clause, not by dropping a question. Readings that reach a card, a brief or a dispatch are a small fraction of the probes a round fires; the card and the triage both drew that boundary and the row states it positively (「他人据以行动的」). ⛔ No blanket demand on every number." }, "budget_cut": "Two clauses did not fit the one-row budget and are named for the seat to queue, ideally on the SKILL.md twin this PR owes (where the reading discipline already spends two lines on the zero rule): the explicit negative boundary 「⛔ 自用即弃的探针不欠此税」, and the discharge form of ② 「答案取逐字工件或具名反例」 (the cloud#2020 rule - an instrument either measures the real artefact or carries a control that establishes what it is counting). The dispatch allowed up to 2 rows; a second row was refused because the only remaining payment in this file is the preamble merge above, which spends worse content than it buys.", "mirror_reading_skill_md_163": "BY GATE: NO. BY THE PROTOCOL'S OWN BINDING TEXT: YES, and this PR does not carry that half. (a) No gate compares the two documents: git grep -l 'core-rules' over scripts/ .github/ package.json reads 2 FILES - check-skill-line-ratchet.mjs (counts lines only) and dispatch-gates.mjs (derives families); lit controls on the same instrument and corpus: 'platform-readings' 7 files, 'SKILL.md' 40 files; absent control (nonsense token) 0, exit 1. Second instrument agrees: git grep -n '核心条款' over scripts/ .github/ reads exactly ONE line, a COMMENT at check-skill-line-ratchet.mjs:1126 quoting the rule, with 受管面 lit as control. (b) The binding text is unambiguous: SKILL.md :43 「核心条款住 `references/core-rules.md`,是本文的子集」, SKILL.md :44 「一条规则在本文与核心条款一处改动,另一处同 PR 同改」, core-rules :3 「本文不新增规则」. (c) Both reference PRs the dispatch named carried the twin in the SAME PR - PR #18511 (SKILL.md :522/:640 + core-rules :112) and PR #18481 (SKILL.md :390/:391/:403/:404/:712 + core-rules :95/:96/:137, which also declared in its body the one item that has no core-rules twin). Two of two. (d) THE OWED HALF for the seat to queue: SKILL.md's reading-discipline block :163-:164 gains the same rule. Not in this diff because SKILL.md is serial behind PR #18666 / PR #18679 - the seat's ruling, not a reading this PR takes. check:skill-frame-sync ran green but judges the four-axis DECISION FRAME's coherence and scans for undeclared copies of that frame; it is not a rules-row mirror and its green says nothing about the twin obligation.", "closes_18755_gap": "NO - it narrows it and does not close it. #18755's principle is that a lit control certifies the INSTRUMENT, not the QUESTION: a live instrument pointed at a question its DOMAIN cannot answer (grep-by-content asked an existence question about a FILENAME). This row binds readings that reach a card, a brief or a dispatch, so #18755's own near-miss - a probe heading into a finding - would be inside the demand, and answering ② there ('a file whose CONTENTS name the suite') exposes the domain mismatch. But a seat's own discard probe stays outside this row by design, and instance 8 above shows a reading that satisfies ① and ② and is still wrong about the question. ⇒ #18755 still owns a real hole; the seat can rule on it with this row on the table, and if it wants the hole closed here the wording is the conclusion-bound ② named in wrong_question_boundary.", "ratchet_before_after": "AT main (331462d11f, the branch base): 「✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/core-rules.md is 151 lines (ceiling 151; headroom 0).」 AT head 46b7bd6a46: byte-identical line, exit 0. Widest introduced row 119 B (:46 and :111); :80 is 102 B; measured over all 151 lines, none exceeds 120 B. git diff --stat 331462d11f HEAD = 1 file changed, 3 insertions(+), 3 deletions(-).", "tests": "No unit tests and no ablation leg: a prose rule with no runtime and no dist, so there is nothing to mutate and rebuild. The measurement is the diff + the ratchet pair + the derived gate sweep. Derived with no hand-fed path list (node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, run from the worktree) = 16 families, all 16 run in the foreground with each exit code captured by redirect-then-$?: check-closing-keyword-parity 0; check-closing-keyword-parity --self-test 0; check-comment-mask-corpus 0; pm/check-governed-queue-guard --self-test 0; pm/check-harness-current --self-test 0; lint check:doc-formula-expressions 0; check:agent-test-spelling 0; check:doc-authoring 0; check:driver-memory-census 0; check:nul-bytes 0; check:pm-governed-merges 0; check:pm-skill-id-lint 0; check:pm-skill-ratchet 0; check:refd-timer-probe 0; check:skill-frame-sync 0; check:watch-hint-literal 0. Reconciliation: 「✓ dispatch-gates --ran: 16 derived famil(ies) accounted for - 16 run, 0 NOT-MEASURED (a DERIVED zero - all 16 recorded an exit code and none of them is 3)」. check:doc-formula-expressions first answered EXIT 3 PREREQUISITE NOT MET (@objectstack/formula and @objectstack/lint unbuilt) - not a finding and not a measurement; both were built under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0, held 1s, waited 0s) and the gate then answered 0. Two more run because the derivation named their rosters rather than cleared them: check:pm-settings-deny-roster (roster under .claude) 0, check-skills-token-ratchet 0 (published catalog untouched). Repo-wide pnpm lint (eslint . --no-inline-config) exit 0, no output. Control characters: check:nul-bytes 0 (8850 text files, no raw ASCII control bytes) plus a direct C0+DEL sweep of the edited file, no match exit 1.", "pr_state": "DRAFT, base main, Fixes #18798, 「Clause-②: no」 in the body at creation. Labels after the write: size/xs (bot) + skip-changeset (mine, read-back compared against union(read, target) - nothing missing). needs:contract-review is ABSENT from the PR (not mine to hang); node scripts/pm/check-clause2-carriers.mjs --pair 18809 exits 0 and reads both limbs as DECLARED `no` (card claim 5721692985 and PR body agree). ⛔ Not flipped out of draft, no reviewers requested, no needs-user-decision, body written once at creation and never PATCHed. Body read back after the write: byte-identical to what was sent except the trailing newline the platform strips, exactly ONE attribution footer in the session-URL form.", "mcp_calls": "0 - no MCP GitHub tool was called, read or write.", "api_writes": "3 REST proxy writes, each with Content-Type: application/json and a body from a file: POST /repos/objectstack-ai/objectstack/pulls (draft create); POST /repos/objectstack-ai/objectstack/issues/18809/labels (additive, skip-changeset); POST /repos/objectstack-ai/objectstack/issues/18798/comments (this report). Plus 2 git pushes (the empty-branch routing probe and the commit), which are not REST writes. ⛔ No PATCH of the PR body, ⛔ no POST /issues.", "open_questions": [], "out_of_scope_findings": [ "to file (class b - declared coverage measured false; dedupe words: 「核心条款 同 PR 同改」 · 「core-rules SKILL.md 无镜像门禁」 · 「本文不新增规则」 · 「twin line SKILL.md:44」 · 「digest subset drift」): SKILL.md :44's twin-edit obligation and the subset relation SKILL.md :43 / core-rules :3 declare are enforced by NO gate - the only occurrence of 核心条款 under scripts/ is a comment at check-skill-line-ratchet.mjs:1126 quoting the rule (lit controls: 'platform-readings' 7 files, 'SKILL.md' 40 files, 受管面 present in the same corpus; absent control 0/exit 1). This PR is itself the instance: it lands a rule in the digest that SKILL.md does not state, and nothing mechanical will say so. dev does not POST issues; handed to the seat.", "noted, not filed: core-rules :5 「PM 不写任何文件」 and :23 「PM ⛔ 不写文件也不写代码」 state the same prohibition twice (红线 and 全体座位的不变量). A future card needing payment in this file can merge :23 with :24 - whose 「⛔ 不得自审自合」 is already carried by :5's 「⛔ 永不合自己的、红的或未复核的 PR」 - for one line at 115 B, measured. Handler: the next card that has to pay a row in this file.", "noted, not filed: core-rules :43 「不取本地工作树」 and :44 「⛔ 不用共享检出树」 overlap; folding them frees bytes but not a line, so it funds nothing. Handler: none.", "noted, not filed: the card quotes a companion maxim 「非零不证明尺子对」 as living in SKILL.md / platform-readings; it is on the tree in no spelling (see premise_check). Nothing to fix - the card's conclusion is strengthened, not weakened - but a future reader of the card should not go looking for that line. Handler: this report." ] }
Generated by Claude Code
os-dev-report
{ "issue": 18798, "round": 2, "status": "done", "branch": "claude/issue-18798-non-zero-reading-owes-a-control", "pr": "https://github.com/objectstack-ai/objectstack/pull/18809", "head_sha": "e81a7ed60c5d6f77c9f8265138744e7490c0cdc4", "head_sha_round_1": "46b7bd6a464a21406556ff297350cb0410fb5381", "files": [ ".claude/skills/pm-dispatch/SKILL.md" ], "session": "session_01Gqi43smmqjJ5sUrhfoPeKu", "premise_still_valid": true, "premise_check": "Verified on the fetched tip before writing, and re-verified at every fetch during the round: origin/main moved 8904880601 → ac720a9865 → e7eb4e9184 → a7bafc29af while this ran, and SKILL.md's blob is 5112f2589c at all four tips and at the branch's merge-base 331462d11f (git rev-parse REF:path, four readings, all equal), so every line number below is valid on the tip. SKILL.md :43 「核心条款住 references/core-rules.md,是本文的子集」 and :44 「一条规则在本文与核心条款一处改动,另一处同 PR 同改」 read verbatim as the dispatch quotes them; the zero rule is :163-:164; SKILL.md is 812 / 812 at the ratchet (check:pm-skill-ratchet at 46b7bd6a46: 「.claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812; headroom 0)」, exit 0). PR #18666's SKILL.md hunks are @@ -198,12 / -536,7 / -625,7 / -642,7 and PR #18679's are @@ -306,7 / -729,6, re-derived from GET /pulls/N/files; each band's first context line matches the tip at that number.", "summary": "One NEW commit e81a7ed60c on the same branch (round 1's 46b7bd6a46 untouched; no amend, no force-push): SKILL.md gains the twin of core-rules :46 at :165, byte-identical to core-rules :46 (md5 2a15a5bc042bfa842e0e3654ceab2698 for both lines), and a second line at :166 carrying the two clauses round 1's budget cut - the negative boundary and the discharge form of the counter-question. Both paid in file, 812 → 812, by retiring two lines whose every clause SKILL.md states elsewhere and which have NO core-rules counterpart (checked against all 151 core-rules lines, so the subset relation holds in both directions after this commit). One deviation from the dispatch's line lead: the twin sits under :164, not :163, because the zero rule is two lines (:163 the rule + same-subject definition, :164 the double-zero control) and core-rules :45 fuses exactly those two - 「directly under the zero rule」 is after :164; inserting between them would split one rule. PR left DRAFT, body NOT patched, no label written by me; the bot re-sized it size/xs → size/s after the push (another actor's write, left alone). Everything round 2 adds is in this report for the seat's 终稿.", "twin_line": { "path_line": ".claude/skills/pm-dispatch/SKILL.md:165", "text": "- 他人据以行动的读数须带单位并答什么本来会让它不是这个值;递 dev 的恒标线索非答案。", "bytes": 119, "cap": 120, "same_rule_proof": "byte-identical to core-rules.md :46 (both md5 2a15a5bc042bfa842e0e3654ceab2698) - the file's own precedent for an identical twin is SKILL.md :159 = core-rules :43 verbatim. The 1-byte headroom under the cap leaves no room for the 细则 to say more, so identical is also the only spelling that fits.", "placement": "under :164, i.e. directly under the two-line zero rule :163-:164 that core-rules :45 fuses into one row; the dispatch's 「directly under :163」 was read as a line lead (deviation reported, not smoothed)" }, "second_line": { "carried": true, "path_line": ".claude/skills/pm-dispatch/SKILL.md:166", "text": "- ⛔ 自用即弃的探针不欠此税;「不是这个值」的答案取逐字工件或具名反例。", "bytes": 103, "cap": 120, "content": "clause 1 is round 1's named negative boundary 「⛔ 自用即弃的探针不欠此税」 verbatim; clause 2 is round 1's named discharge form 「答案取逐字工件或具名反例」 with 「不是这个值」 quoted from the twin above it so the answer binds to that question. No third clause added.", "core_rules_owed": "none - it refines the twin (the negative side of 「他人据以行动的」 and the form of the 答 clause), the same shape as :163's 「同主体 = …」 and :164's 「换法重画再报」, which are 细则 with no core-rules row; SKILL.md :43 makes core-rules the SUBSET, so a refinement lives in SKILL.md alone" }, "rows_paid": [ { "retired": "old :480 (now absent) - 「- 文件面申报到区域级,每单必填;分支名必须带 issue 号。」 (61 B), the whole line", "survives_at": "clause 「文件面申报到区域级」 = :448 (now :450) 「① 认领申报文件面到区域级,拿不准就串行。」 verbatim; clause 「每单必填」 = the claim template is 固定形状 (:798) and its fixed line 「File surface: …」 (:807) is copied by every claim per :473 (now :475) 「② 认领评论(英文)照抄 模板与表 节」; clause 「分支名必须带 issue 号」 = the template's fixed line 「Branch: claude/issue-N-slug」 (:803) and AGENTS.md §2 (binding, outranks this file). core-rules carries no twin of this line (grep 区域级 / 分支名 / issue 号 over core-rules: 0 lines; lit control 文件面: :68, :105).", "pays_for": "the second line (:166)" }, { "retired": "old :583 (now absent) - 「- 重放 ⛔ 不重新验收、不重复 ACCEPT;通知到达不读作还活着,不到达也不读作已死。」 (109 B), the whole line", "survives_at": "clause 「重放 ⛔ 不重新验收、不重复 ACCEPT」 = :582 (now :583) 「通知重放先算身份再读内容:与已验收那份同身份 ⇒ 记重放即结束。」 - 即结束 is the rule; clause 「通知到达不读作还活着,不到达也不读作已死」 = :567 (now :568) 「探活是每轮巡检的固定动作;完成通知不可靠,缺席什么都不证明。」 plus :573 (now :574) 「判据永远取正向证据」 and :575 (now :576) 「判死只有三类依据」, none of which is a notification. core-rules carries no twin (grep 重放 / 通知 over core-rules: 0 lines; lit control 探活: :117).", "pays_for": "the twin (:165)" } ], "payments_refused": "Two better-looking candidates were refused for the exact defect this round repairs. old :574 「45 分钟是发探针的门槛,⛔ 不是判死的门槛。」 is stated by :570 + :576 (「⛔ 非本文任何常数」) but core-rules :118 carries it verbatim (「45 分钟是发探针的门槛而非判死门槛…」), so retiring it would leave the digest stating a sentence the skill no longer spells. old :640 「…记录 = 同形评论落 PR 或卡。」 is the SKILL.md source of core-rules :123's 「同形复核记录」 - same problem. Neither re-wrap nor any rule deletion was used; both retired lines are restatements whose every clause survives verbatim at the sites named.", "ratchet_before_after": "BEFORE at 46b7bd6a46 (pnpm check:pm-skill-ratchet, exit 0): 「✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812; headroom 0).」 AFTER at e81a7ed60c (same command, committed tree, exit 0): byte-identical line. Widest bullet line in the file 120 B at :100 (pre-existing); the two new lines 119 B and 103 B. git diff --stat origin/main...HEAD: SKILL.md 4 (+2/-2), core-rules.md 6 (+3/-3, round 1), 2 files, 5 insertions, 5 deletions.", "four_axis_block": "range :733-:754 after the commit - unchanged, because the two retirements (old :480, old :583) sit above :733 and net the insertion to zero for every line from :584 down; md5 of sed -n 733,754p at HEAD = 3327d02c56f8a0eca88569dad2270f32, equal to the dispatch's reading; check:skill-frame-sync exit 0 (「the one declared copy of the decision frame is internally coherent」).", "overlap_measured": "My hunks in git diff origin/main...HEAD -- SKILL.md (default context, OLD numbering): @@ -162,6 +162,8 (insert after :164), @@ -477,7 +479,6 (delete :480), @@ -580,7 +581,6 (delete :583). Bands (OLD numbering): PR #18666 :198-:209, :536-:542, :625-:631, :642-:648; PR #18679 :306-:312, :729-:735. Shared lines: 0 for each of the six (computed over the touched lines 164/165, 480, 583 and over the context-widened hunks :162-:167, :477-:483, :580-:586). In the NEW numbering the bands' content is unmoved: #18666 → :200-:211, :537-:543, :625-:631, :642-:648; #18679 → :308-:314, :729-:735.", "tests": "No unit tests and no ablation leg: prose rule, no runtime, no dist. Measurement = the diff + the ratchet pair + the derived sweep. Derived with no hand-fed path list from the worktree (node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack; change set 2 paths vs merge-base 331462d11f, three-dot) = 19 families (round 1 had 16; new: check:pm-expected-skips, check:pm-governed-prose, check:pm-half-states). All 19 run in the foreground, each exit captured redirect-then-$?: node scripts/check-closing-keyword-parity.mjs 0; …--self-test 0; node scripts/check-comment-mask-corpus.mjs 0; node scripts/pm/check-governed-queue-guard.mjs --self-test 0; node scripts/pm/check-harness-current.mjs --self-test 0; pnpm --filter @objectstack/lint run check:doc-formula-expressions 0; pnpm check:agent-test-spelling 0; check:doc-authoring 0; check:driver-memory-census 0; check:nul-bytes 0; check:pm-expected-skips 0; check:pm-governed-merges 0; check:pm-governed-prose 0; check:pm-half-states 0; check:pm-skill-id-lint 0; check:pm-skill-ratchet 0; check:refd-timer-probe 0; check:skill-frame-sync 0; check:watch-hint-literal 0. Reconciliation: 「✓ dispatch-gates --ran: 19 derived famil(ies) accounted for - 19 run, 0 NOT-MEASURED (a DERIVED zero - all 19 recorded an exit code and none of them is 3)」, exit 0. check:doc-formula-expressions needed @objectstack/formula and @objectstack/lint built: the first attempt under scripts/pm/os-verify-lock.sh (pnpm --filter formula --filter lint build) failed exit 1 on TS2307 Cannot find module @objectstack/spec (spec unbuilt in the fresh worktree - not a finding); the closure was then built under the lock with pnpm exec turbo run build --filter=@objectstack/lint... --concurrency=2, FULL TURBO 4/4 cached, VERDICT command-exit 0, held 1s, waited 0s, after which the gate answered 0. STALE-TREE handling: the derivation warned that scripts/pm/check-half-states.mjs and check-clause2-carriers.mjs are newer on origin/main (commits 8904880601, e08fae860d) than on the branch tree, so a throwaway worktree at origin/main e7eb4e9184 with only the branch's two files restored (SKILL.md blob 4d715da09d equal to HEAD's) re-derived the IDENTICAL 19-command list with no stale warning, and the two stale families read 0 on their current copies (check:pm-half-states 0, 「4921 cases pass」; check-clause2-carriers --pair 18809 0, both limbs DECLARED no). Two roster families the derivation flags as 「read before treating as passed」: pnpm check:pm-settings-deny-roster 0 (17 declared = enforced), node scripts/check-skills-token-ratchet.mjs 0 (34 authored bundle files within ceilings). Repo-wide pnpm lint (eslint . --no-inline-config) exit 0 at e81a7ed60c, no findings. Control characters: check:nul-bytes 0 (8850 text files, no raw ASCII control bytes) plus a direct C0+DEL grep of SKILL.md, no match, exit 1. check:pm-dispatch-gates was NOT derived and was not run.", "gates_named_by_dispatch": { "check:pm-skill-ratchet (check-skill-line-ratchet)": "exit 0 before (46b7bd6a46) and after (e81a7ed60c), 812 / 812 both", "check:skill-frame-sync": "exit 0", "check:pm-skill-id-lint": "exit 0 (27 files clean)", "check-clause2-carriers --pair 18809": "exit 0 on the branch copy and exit 0 on origin/main's copy; needs:contract-review ABSENT from the PR (not mine to hang)" }, "pr_state": "DRAFT, open, base main, head e81a7ed60c, 2 commits, files: SKILL.md +2/-2 and core-rules.md +3/-3. Labels now: documentation, size/s, skip-changeset - size/xs became size/s by the size bot after my push; I wrote no label this round. Body untouched (no PATCH); reviewers untouched; not flipped out of draft.", "mcp_calls": "0 - no MCP GitHub tool was called, read or write.", "api_writes": "1 REST proxy write: POST /repos/objectstack-ai/objectstack/issues/18798/comments (this report, Content-Type: application/json, body from a file). Plus 2 git pushes (the no-op routing probe on the existing branch - Everything up-to-date - and the commit), not REST writes. ⛔ No PATCH of the PR body, no label write, no POST /issues, no POST /pulls.", "open_questions": [], "out_of_scope_findings": [ "to file (class b, restated from round 1 unchanged, still unfiled by me; dedupe words: 「核心条款 同 PR 同改」 · 「core-rules SKILL.md 无镜像门禁」 · 「本文不新增规则」 · 「twin line SKILL.md:44」 · 「digest subset drift」): SKILL.md :44's same-PR twin obligation and the :43 subset relation are enforced by no gate - this round found it bites in BOTH directions (a SKILL.md payment can strand a core-rules row just as round 1 stranded a SKILL.md one), and only a hand-check of all 151 core-rules lines caught the two refused payments. Handed to the seat.", "noted, not filed: SKILL.md :575 (was :574) 「45 分钟是发探针的门槛,⛔ 不是判死的门槛。」 is stated by :571 + :577 but has a core-rules twin at :118, so the next line paid in SKILL.md can retire it only together with a core-rules :118 rewrite in the same PR. Handler: the next card that has to pay a row in SKILL.md.", "noted, not filed: SKILL.md :640 「记录 = 同形评论落 PR 或卡」 is the only SKILL.md spelling behind core-rules :123's 「同形复核记录」; same two-file payment constraint. Handler: the next card that has to pay a row in SKILL.md.", "noted, not filed: os-verify-lock.sh --status reported 「holder pid 3031, held 715s - node scripts/pm/dispatch-gates.mjs --self-test」 (liveness: ALIVE, same process) while my first lock call queued 0-ahead and acquired after 15s; a 12-minute self-test holding the heavy lock was not reproduced and not investigated. Handler: none." ] }
Generated by Claude Code
ACCEPT — in-seat contract-tier review of PR #18809 (head
e81a7ed60c, two rounds; reports 5721989070 and 5722230405) by the skills seat, 2026-09-17T22:53Z. Verified against GitHub and a scratch worktree at the head, ⛔ not against the reports:- Scope = the claim (5721692985) plus the seat's own round-2 correction, disclosed: two files, +5 / −5 in two commits —
references/core-rules.md+3 / −3 (round 1) and.claude/skills/pm-dispatch/SKILL.md+2 / −2 (round 2);skip-changesetcorrect (.claude/**publishes nothing);Clause-②: noon the PR body and the claim,check-clause2-carriers --pair 188090 (seat's run at the head);check-governed-merges --pr 18809GOVERNED (.claude/**×2) ⇒ four-piece, the maintainer lands. The round-1 dispatch EXCLUDED SKILL.md for the seat's hot-file serial; SKILL.md :43 / :44 and core-rules :3 bind the twin to the SAME PR, so that exclusion was the seat's error — the round-1 dev read the text back, and the seat ran round 2 at the MANDATORY tier on the same branch (a new commit, no history rewritten). - The rule, read on the head: core-rules :46 (119 B) 「他人据以行动的读数须带单位并答什么本来会让它不是这个值;递 dev 的恒标线索非答案。」 directly under the zero rule :45; SKILL.md :165 byte-identical to it (seat's md5 on both lines:
2a15a5bc), under the two-line zero rule :163–:164 that core-rules :45 fuses — the dev's placement under :164 rather than the seat's 「under :163」 is the right reading of 「directly under the zero rule」; SKILL.md :166 (103 B) 「⛔ 自用即弃的探针不欠此税;「不是这个值」的答案取逐字工件或具名反例。」 carries the two clauses round 1's one-row budget cut — a 细则 refinement of the twin, owing no digest row (the subset relation runs from SKILL.md to the digest). Scope of the rule is the card's own boundary — a reading another agent ACTS on (a card, a brief, a dispatch); a seat's use-and-discard probe owes nothing; ⛔ no blanket tax on every number. - Payment, verified as content: core-rules :51 retired whole — its dedupe clause restated :45's zero rule, 「子代理自死不等于维护者中止,需显式信号」 merged into :111 (119 B) and 「立卡者只附查重词」 into :80 (102 B); SKILL.md old :480 「文件面申报到区域级,每单必填;分支名必须带 issue 号。」 retired — survives at :450 「① 认领申报文件面到区域级…」 (seat grep 1), the claim template's :803
Branch:line with :475, and AGENTS.md §2; SKILL.md old :583 「重放 ⛔ 不重新验收、不重复 ACCEPT;通知到达不读作还活着,不到达也不读作已死。」 retired — survives at :583 「…同身份 ⇒ 记重放即结束」 (seat grep 1) and :568 「完成通知不可靠,缺席什么都不证明」 (seat grep 1); neither retired line reads at the head (seat grep 0 / 0) and neither has a core-rules twin. Two better-looking SKILL.md payments were REFUSED because core-rules :118 and :123 carry them — the very defect this PR repairs from the other side. ⛔ No re-wrap as currency; no rule leaves the corpus. - Ratchets and pins, seat's run at the head: SKILL.md 812 / 812, core-rules 151 / 151,
check-skill-line-ratchetexit 0, every touched row ≤ 120 B; the four-axis block still :733–:754 with md53327d02c56f8a0eca88569dad2270f32(the two retirements above :733 net the insertions to zero);check:skill-frame-sync0 andcheck:pm-skill-id-lint0 per the report. - Overlap (seat's read of the hunks): SKILL.md
@@ -162,6/@@ -477,7/@@ -580,7against PR docs(pm-dispatch): name the repository each cited instrument answers for #18666's :198–:209 / :536–:542 / :625–:631 / :642–:648 and PR skills(pm-dispatch): a ruling's file/symbol/line/call-shape clause carries its reading or is marked 未验证 — the 派发令 evidentiary duty extended to 裁决 #18679's :306–:312 / :729–:735 — zero shared lines; both open PRs still apply in any landing order. - The premise, corrected in the card's favour: the companion maxim the card quotes, 「非零不证明尺子对」, is on the tree in NO spelling (round 1: one grep line, os-dev.md :227, about a non-zero EXIT code; controls lit) — the non-zero side had no maxim at all, let alone a paired action. The eight instances measured against the row as written: clause ① alone catches 1 of 8, clause ② 6 of 8, the lead clause instance 4; instance 8 (unit right, control lit, count true, WRONG QUESTION) is NOT caught — reported as a measured disagreement with the triage's expectation and not smoothed; the conclusion-bound ② that would reach it was refused on the axes (a re-derivation per reading; it would silently absorb the open finding(skills): a lit control certifies the INSTRUMENT, not the QUESTION — a live grep, its lit control and its absent control all fired while answering something the tool structurally cannot see #18755). This row narrows finding(skills): a lit control certifies the INSTRUMENT, not the QUESTION — a live grep, its lit control and its absent control all fired while answering something the tool structurally cannot see #18755's hole and does not close it — said so.
- Gates: round 1 16 derived / 16 run / 0 UNRUN; round 2 19 derived / 19 run / 0 UNRUN (a throwaway worktree at
origin/mainwith the branch's two files restored re-derived the identical list, so the stale-tree warning was answered on current copies:check:pm-half-states4921,--pair0); all exit 0;check:pm-settings-deny-roster0 andcheck-skills-token-ratchet0 outside the derived set; repo-widepnpm lintexit 0 at both heads; control-byte scans clean — per the reports. Seat-side: the ratchets, the md5s, the twin identity, the retired-line survival, pair 0, GOVERNED, harness CURRENT. CI on the head: 26 check runs read explicitly, every onecompleted— 17 success, 9 skipped (all in the expected-skips roster, exit 0); commit statussuccess; nonefailure. - Writes: round 1
api_writes3 (draft PR,skip-changesetread back, report), round 2api_writes1 (report);mcp_calls0 in both; PR body written once at create and never PATCHed — so its## 维护者速读(草稿)still says the SKILL.md half is 「由席位排队补上」; the seat's 终稿 on the PR corrects that (both halves are in this PR). No label, reviewer or draft-flip writes by either round. - Out-of-scope, carried: (1) FILED by the seat as [finding] SKILL.md :44's same-PR twin obligation and the :43 / core-rules :3 subset relation are enforced by no gate — PR #18809 carried a core-rules row without its SKILL.md twin for one round, a SKILL.md payment can strand a core-rules row the same way, and only a hand-check of all 151 digest lines catches either #18820 — no gate enforces SKILL.md :44's same-PR twin or the :43 subset relation, and PR skills(pm-dispatch): a reading another agent acts on owes its UNIT and a counterfactual — the discipline guarded a ZERO only #18809 measured it biting in both directions; (2) SKILL.md :575 (the 45-minute probe threshold) and :640 have core-rules twins (:118, :123) — the next SKILL.md payment retires them only with the digest row in the same PR; (3) core-rules :5 / :23 state the PM-writes-nothing prohibition twice — a payment for the next card on that file; (4) a
dispatch-gates --self-testheld the verify lock ~12 minutes — noted, not investigated. - Landing: governed ⇒ the four-piece follows now — this ACCEPT,
## 维护者速读(终稿)on the PR,needs-user-decision, review requested from os-zhuang + hotlong; the maintainer lands. Serials: SKILL.md — PR docs(pm-dispatch): name the repository each cited instrument answers for #18666 ∥ PR skills(pm-dispatch): a ruling's file/symbol/line/call-shape clause carries its reading or is marked 未验证 — the 派发令 evidentiary duty extended to 裁决 #18679 ∥ this PR (no line overlap); core-rules → skills(pm-dispatch): ADR-0136 D2 becomes the triage protocol —Journey:line, journey bands, cross-lane product-first order, journeys feed the queue #18489 (twins).
Generated by Claude Code
- Scope = the claim (5721692985) plus the seat's own round-2 correction, disclosed: two files, +5 / −5 in two commits —
LANDED — PR #18809 (#18798 p1, governed
references/core-rules.md:46 「他人据以行动的读数须带单位并答什么本来会让它不是这个值;递 dev 的恒标线索非答案。」 paid by :51 into :80 / :111 (151 / 151) AND its SKILL.md twin :165 (byte-identical) + :166 (the two boundary clauses) paid by old :480 / :583 (812 / 812), added in a round 2 at the MANDATORY tier after the seat's own round-1 dispatch wrongly excluded SKILL.md against :44 — #18820 filed on that; four-axis block md5 unchanged) merged through the queue at 2026-09-18T02:05:05Z (merged_at), squash6427ee2480a359e028f5c76da75152a14368f6d0(single parentb3e437db2668ec45ee4ea37149b0e1ef09143937, an ancestor oforigin/main). Governed surface (.claude/skills/**): the seat's ACCEPT 5722292544 here,## 维护者速读(终稿)5722292765 on the PR,needs-user-decision+ reviewers at 2026-09-17T22:54Z; os-zhuang APPROVED at 2026-09-18T01:15:37Z (review 5243130232 on the ACCEPT heade81a7ed60c), marked ready and enqueued by hand at 2026-09-18T01:15:42Z; the seat strippedneeds-user-decisionat 2026-09-18T01:16:52Z per ruling C (--pair 188090, CI 31 / 13 skipped rostered, harness CURRENT at88aa326deb). The card auto-closedcompletedat 2026-09-18T02:05:06Z on the PR'sFixes;pm:dispatchedis stripped in the same act. Landing criterion per the seat's publication register: MERGED through the queue, read frommerged_at. ⇒ with PR #18666 and #18679 landed too, the SKILL.md serial is FREE for #18536 · #18743 · #18755 · #18665 — the next seat's; SKILL.md stays at 812 / 812.
Generated by Claude Code
The gap
references/platform-readings.mdand the SKILL's reading discipline make one mechanical demandabout instruments:
That guards a ZERO. The companion sentence — 「非零不证明尺子对」 — is a maxim with no paired
mechanical action. Nothing in the protocol makes a seat prove that a non-zero reading counted the
thing it claimed to count.
Why now: six instances in one shift, five of them from the seat itself
Raised by the
os-devon cloud#2020 (report5564612360, 2026-09-07), which asked whether its findingwas "worth flagging as a general lesson". It found that a paraphrased calibration case passed for
the wrong reason — the paraphrase had dropped the sentence carrying the cue, so the case exercised a
path the real corpus never takes. The dev named the class itself:
The
repo:cloudseat then produced five more of the same shape in a single round (R39, 2026-09-17),all of them its own:
startswith("Blocked-by:")over bodiesgrep -E '^[-+][^-+]'over a charter diff-, so diff lines read--and the pattern excluded thempackage_version_idgrep handed to a dev as a leadgit grep -c … | wc -lto count call sites⭐ Five of the six are NON-ZERO readings. The existing rule would not have caught any of them.
What a remedy would have to do
⛔ Not "be more careful" — that is what everyone was already being. The dev's own remedy is the shape
worth generalising: an instrument either measures the real artefact (a verbatim corpus excerpt, a real
call site) or it carries a control that establishes what it is counting.
Concretely, candidates the skills seat could weigh:
state the unit (files? occurrences? lines?) alongside the number;
「⛔ this is a lead, not an answer — walk it yourself」 (it saved cloud#2306 from instance Add Changesets and GitHub Actions automation #4);
synthetic cases only for shapes that cannot exist pre-fix, and labelled as such.
⛔ Do not turn this into a blanket "every number needs a control" — that tax would fall hardest on the
cheap probes that make the loop affordable, and the discipline already has a budget problem. The
question worth answering is which readings are load-bearing enough to owe a control: R39's five all
went into a card, a brief or a dispatch brief, i.e. somewhere another agent would act on them. A reading
a seat uses and discards is not the same thing.
查重词
非零不证明尺子对·control word for non-zero readings·instrument counts the wrong unit·git grep -c wc -l file count·verbatim corpus excerpt calibration case·lead not an answer dispatchGenerated by Claude Code