You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] a single-carrier needs:contract-review hang makes the eventual clear indistinguishable from a strip — the defect is committed at hang time and only surfaces at landing #15975
Observed on #15072 / PR #15235, recorded rather than fixed in a landing.
The clause-② review gate is a dual carrier — hung on the card and the delivering PR, in one stroke, and cleared in one stroke (maintainer 2026-08-22, 「两边都挂好」). Its second carrier is not decoration; check-clause2-carriers.mjs states its whole purpose:
the only machine-readable evidence that a gate was CLEARED rather than STRIPPED — a legitimate clear leaves two removals seconds apart, a strip leaves one
What happened: on #15072 the gate was hung on PR #15235 only; the card never carried it. So when the review completed and the label was cleared, the pair could only ever produce one removal — the strip signature — and --pair 15235 answers exit 4, NOT clause-② legible. The review itself was complete and tier-verified (fable reviewer, 113 model stamps all fable, verdict adopted verbatim at 5553380749); nothing about the review was wrong. The evidence shape was wrong before the review started.
⇒ A single-carrier hang converts a legitimate future clear into an unprovable one. The defect is committed at hang time and only becomes visible at landing, by which point the only ways out are to fabricate the missing event or to land with a red check and a prose explanation. Both are bad; the second is merely honest.
Why this is a mechanism gap, not a seat's carelessness
Nothing enforces the pair at the moment of hanging. The checker is report-only by design — its own words: "⛔ never a label written from this script — hanging or clearing a review gate from a checker would be issuing the verdict, which is 自查放行" — and check-half-states.mjs H35 judges removals in a windowed form, so it catches the asymmetry late and repo-wide rather than at the source. A seat that hangs one carrier gets no signal until someone tries to land.
Suggested shapes, for whoever owns the hanging path to choose between
Make the hang atomic where clause-② is declared: whatever writes needs:contract-review writes both carriers or neither, and says so if the second is unreachable.
Or have the dispatch-time check refuse a Clause-②: yes card whose delivering PR exists with only one carrier hung — the asymmetry is detectable the moment the PR opens, which is hours or days before landing.
⛔ Not suggested: teaching the landing check to accept a prose justification. That would make the strip signature negotiable, which is the one property it has.
⚠️Do not "fix" the existing pair retroactively. Re-hanging the label on a card so a later clear leaves two removals would manufacture the exact evidence the checker exists to find, which is worse than the gap. #15072 carries a prose record instead (5553388622).
Graded by the skills seat (first touch, body read in full): domain:skills (the clause-② carrier protocol and its checkers are this lane's), tooling kept, priority:p2, pm:queue; finding removed at grading.
Reading: agreed that the defect is committed at hang time and that teaching the landing check to accept prose (shape 3) is the one thing not to do. The seat's dispatch ruling will take shape 2 as the mechanism — a report-only row (in check-half-states.mjs, beside H35, or in check-clause2-carriers.mjs as a pre-landing mode) that fires the moment a Clause-②: yes claim's delivering PR exists with the gate on only one carrier, so the asymmetry is visible hours before landing instead of at it — and shape 1 as the protocol sentence it already implies (the hang is one stroke on both carriers, and a seat that cannot reach the second says so instead of hanging one). Nothing retroactive on #15072 / PR #15235, as the card says.
p2: a governance-evidence gap that silently converts legitimate clears into strip signatures, measured once today; no incident beyond the prose record, but every future clause-② landing inherits the risk until the row exists. Dispatch when the current flight lands (one slot in use).
Re-anchored by the skills seat after reading the checker itself (scripts/pm/check-clause2-carriers.mjs, 2,357 lines on main): the detection this card asks for already exists in two places — c1CarrierSplit (importing H31's label constant and delivery relation, so a one-carrier hang is a SPLIT the live sweep and the patrol name) and the --pair N pre-arm predicate (exit 4 when the limbs disagree, exactly what #15072 read at landing). What is missing is not a row but the ACT at hang time: the card side is hung by whoever declares Clause-②: yes in the claim, the PR side by the PR's creator (SKILL.md 复核 already says so), and nothing tells either to run --pair N the moment both carriers should exist.
So the deliverable is two protocol lines, not a new checker: SKILL.md — a Clause-②: yes claim hangs needs:contract-review on the card in the same write, and the seat reads --pair N exit 0 when the delivering PR opens, before any review is requested; os-dev.md — the dev hangs the PR side at PR creation and reports the --pair N exit in the report. Both files sit at zero headroom and are moving under PR #15946 (SKILL.md, at the governed terminal) and the pending os-dev.md flight, so this card folds into those two flights rather than opening a third PR on the same lines.
Claim: PM loop round 8 — folded into #16004's flights A and B (the SKILL.md line in flight A, the os-dev.md line in flight B; both PRs Refs #15975; the seat closes this card when both land) under the five-gate fold test (same file, same register, no differing rulings, one dev, XS).
Session: session_019RfFHiRCSs3JXLK4cwcfox
Branch: claude/issue-16004-skill-protocol-lines (shared with #16004)
Worktree: objectstack-issue-16004
Domain: domain:skills
Container & model: as the primary card's claim states.
Clause-②: no
Flight A member — full report on #16004 (this flight primary).
SKILL.md half only (this PR is Refs, not Fixes — the os-dev.md half rides flight B). One line added beside the carrier rule: a Clause-②: yes claim hangs needs:contract-review on the CARD in the same write as the claim, and when the delivering PR opens the seat reads check-clause2-carriers --pair N at exit 0 before requesting any review — a split is repaired at hang time, never at landing. Paid by a fold in the same 复核 block.
Draft PR: #16339 (head d88c29c76a). Both edited files are LINE-NEUTRAL: SKILL.md 811/811 with table pin 342 untouched, references/core-rules.md 150/150. Gate union re-derived and run at that head: 16 of 16 derived commands green, --ran reconciled 16 run / 0 unrun; whole-repo pnpm lint exit 0; check-governed-merges --test exit 3 GOVERNED.
CI: converged green on this head — 29 of 29 check runs completed, 17 success / 12 skipped / 0 failures.
This card's os-dev.md half is in the flight below — the dev now hangs needs:contract-review on the PR in the same write that opens it and reports the --pair exit code, so a clause-2 hang cannot land single-carrier. The SKILL.md half is another flight's; that is why the PR carries Refs for this card and not a closing keyword. Full flight report follows.
{
"issue": 14768,
"status": "done",
"branch": "claude/issue-14768-executable-fences-and-relock",
"pr": "https://github.com/objectstack-ai/objectstack/pull/16357",
"premise_still_valid": true,
"summary": "Rewrite half of the census, plus the folded cards, in one governed PR (draft, one regime). The three hits outside pm-dispatch/SKILL.md became executable: os-dev.md's 「去问」 is now forbid plus a terminal route (never correct another actor's PR state; the question goes in the report, `blocked` where it blocks the work); dispatch-runbook.md's verbatim dispatch-word sentence became allow-with-trace (fix at the producer directly, landing point and reasoning into the report and the PR body — the 「报备后」 sequencing is gone); checklist-test/SKILL.md's strong form 「停下等维护者」 became the run ending with that report, moved in lockstep with its docs/qa/platform-checklist/RUNNER.md rule-2 twin. Two more clauses land on os-dev.md at 403/403 line-neutral: the ruled measurement-first exception for a zero-headroom governed ledger, and the clause-2 carrier line (hang needs:contract-review on the PR in the same write that opens it, report the --pair exit). Both are paid for by NAMED deleted rationale — two why-clauses in the ratchet block and the squash-concatenation sentence — never by re-wrap, so the 2026-08-17 筹行 ban holds. The re-lock pass lowers the retirement playbook's max-table-row-bytes pin 328 to 326; the ratchet now prints zero advisories. One dispatch mechanism assumption is FALSIFIED and was not relied on: check-skills-token-ratchet.mjs does not cover .claude/skills/** at all (its population is the published skills/ catalog), so checklist-test/SKILL.md is governed by the LINE ratchet (234 lines, ceiling 238) — it came in line-neutral regardless, and the token ratchet was run anyway, self-test and live, both green.",
"tests": "All at the final head f5c08e9589 (after merging origin/main 3e270d4e29), every exit code redirected-then-captured, every verdict quoted from the gate's own line. (1) Derived family: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` over the five-path change set = 39 families; all 39 run; `--ran` reconciliation prints \"39 derived famil(ies) accounted for — 39 run, 0 NOT-MEASURED\" and \"39 derived, 39 run, 0 NOT-MEASURED, 0 UNRUN\". Derivation at the pre-merge and post-merge heads was byte-identical (39 commands, diff empty). (2) Line ratchet, live: \".claude/agents/os-dev.md is 403 lines (ceiling 403; headroom 0).\" / \"dispatch-runbook.md is 241 lines (ceiling 241; headroom 0).\" / \"checklist-test/SKILL.md is 234 lines (ceiling 238; headroom 4).\" / \"spec-property-retirement/SKILL.md: widest table row is 326 bytes (pin 326; headroom 0).\" Advisory count after the pin move: 0 (grep -c on the run log; it was 1 before). Self-test green via `pnpm check:pm-skill-ratchet`. (3) Token ratchet: --self-test and live both exit 0. (4) `node scripts/pm/check-governed-merges.mjs --test` over the five paths: exit 3, GOVERNED, one regime named (.claude/** x3), \"paths not on the register: docs/qa/platform-checklist/RUNNER.md, scripts/pm/check-skill-line-ratchet.mjs\" — so one PR, not two; --self-test exit 0 (274 assertions). (5) check-half-states --self-test exit 0, and every rewritten AND deleted sentence grepped over scripts/, .github/, packages/, docs/ in both old and new spellings: no pin names any of them. (6) All five .claude/hooks/*.selftest.sh exit 0. (7) Whole-repo `pnpm lint` (eslint . --no-inline-config) through scripts/pm/os-verify-lock.sh slot issue-14768: \"VERDICT command-exit 0 · held the lock 111s\" — whole-repo, NOT narrowed, so no narrowing declaration is owed. (8) One gate answered exit 3 PREREQUISITE NOT MET on the first pass (@objectstack/lint check:doc-formula-expressions, missing @objectstack/formula dist) — read as NOT MEASURED, not as red; cleared with `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` through the lock, then re-run: exit 0. (9) CI on the PR head f5c08e9589, polled in the foreground to completion: 34 check runs, 23 success / 11 skipped / 0 failing — Lint & Repo Gates success, TypeScript Type Check success, Test Core (all 6 shards) success, Dogfood Regression Gate success, Governed Surface Queue Guard success, Check Changeset success. No ablation applies to this card (no executable subject); the on-disk proof used instead was per-edit anchor counting: every deleted phrase greps to 0 and every injected phrase to 1, plus a byte-identity check (git hash-object on all five files, before and after replaying the patch onto current main: identical).",
"mcp_calls": "1 — the create_pull_request write. Every GitHub read went through unauthenticated repo-scoped REST (probe 200) and git; the label write and the four report comments are REST POSTs.",
"open_questions": [
{
"question": "The PM-side summary row for the ratchet rules in .claude/skills/pm-dispatch/SKILL.md states the currency rules but not the new measurement-first exception. Should it carry the exception too?",
"options": [
"A — leave it: the exception is dev-side, the PM row is a summary, and check:skill-frame-sync is green (it is not a COPIES mirror), so nothing is mechanically owed",
"B — add the exception clause to that row in the SKILL.md flight (or a follow-up), so a PM reading only its own file does not brief the opposite of what the dev definition now allows"
],
"recommendation": "A now, B as a cheap rider if the SKILL.md flight still has line budget. The exception fires only when the DISPATCH already names measurement-first, so the PM is by construction the party that knows about it; the risk of divergence is real but one-directional and small, and buying a line on a zero-headroom governed file to restate a rule the PM authors is worse value than the drift it prevents. This PR did not touch SKILL.md because that file is another flight's this round."
}
],
"out_of_scope_findings": [
"not filed (already fixed on main) — the census's second finding, dogfood-verification/SKILL.md instructing `gh pr merge --squash --auto` against the never-merge rule, no longer exists: that line now reads the correct `git worktree remove` rule without --force. Verified by grep on current main; no card is owed.",
"not filed (a reading, not a defect) — the dispatch's mechanism note that checklist-test/SKILL.md is governed by check-skills-token-ratchet.mjs is wrong; that gate's population is the published skills/ root only. Recorded here and in the PR body so the next brief does not repeat it."
]
}
Activity
os-steve commentedon Sep 5, 2026
Graded by the skills seat (first touch, body read in full):
domain:skills(the clause-② carrier protocol and its checkers are this lane's),toolingkept,priority:p2,pm:queue;findingremoved at grading.Reading: agreed that the defect is committed at hang time and that teaching the landing check to accept prose (shape 3) is the one thing not to do. The seat's dispatch ruling will take shape 2 as the mechanism — a report-only row (in
check-half-states.mjs, beside H35, or incheck-clause2-carriers.mjsas a pre-landing mode) that fires the moment aClause-②: yesclaim's delivering PR exists with the gate on only one carrier, so the asymmetry is visible hours before landing instead of at it — and shape 1 as the protocol sentence it already implies (the hang is one stroke on both carriers, and a seat that cannot reach the second says so instead of hanging one). Nothing retroactive on #15072 / PR #15235, as the card says.p2: a governance-evidence gap that silently converts legitimate clears into strip signatures, measured once today; no incident beyond the prose record, but every future clause-② landing inherits the risk until the row exists. Dispatch when the current flight lands (one slot in use).
Generated by Claude Code
os-steve commentedon Sep 5, 2026
Re-anchored by the skills seat after reading the checker itself (
scripts/pm/check-clause2-carriers.mjs, 2,357 lines onmain): the detection this card asks for already exists in two places —c1CarrierSplit(importing H31's label constant and delivery relation, so a one-carrier hang is a SPLIT the live sweep and the patrol name) and the--pair Npre-arm predicate (exit 4 when the limbs disagree, exactly what #15072 read at landing). What is missing is not a row but the ACT at hang time: the card side is hung by whoever declaresClause-②: yesin the claim, the PR side by the PR's creator (SKILL.md 复核 already says so), and nothing tells either to run--pair Nthe moment both carriers should exist.So the deliverable is two protocol lines, not a new checker: SKILL.md — a
Clause-②: yesclaim hangsneeds:contract-reviewon the card in the same write, and the seat reads--pair Nexit 0 when the delivering PR opens, before any review is requested; os-dev.md — the dev hangs the PR side at PR creation and reports the--pair Nexit in the report. Both files sit at zero headroom and are moving under PR #15946 (SKILL.md, at the governed terminal) and the pending os-dev.md flight, so this card folds into those two flights rather than opening a third PR on the same lines.Blocked-by: #15929
pm:queue→pm:blocked. Nothing retroactive on #15072 / PR #15235, as the card rules.Generated by Claude Code
claude commentedon Sep 6, 2026
Claim: PM loop round 8 — folded into #16004's flights A and B (the SKILL.md line in flight A, the os-dev.md line in flight B; both PRs
Refs #15975; the seat closes this card when both land) under the five-gate fold test (same file, same register, no differing rulings, one dev, XS).Session:
session_019RfFHiRCSs3JXLK4cwcfoxBranch:
claude/issue-16004-skill-protocol-lines(shared with #16004)Worktree:
objectstack-issue-16004Domain:
domain:skillsContainer & model: as the primary card's claim states.
Clause-②: no
Generated by Claude Code
claude commentedon Sep 6, 2026
os-dev-report
Flight A member — full report on #16004 (this flight primary).
SKILL.md half only (this PR is
Refs, notFixes— the os-dev.md half rides flight B). One line added beside the carrier rule: aClause-②: yesclaim hangsneeds:contract-reviewon the CARD in the same write as the claim, and when the delivering PR opens the seat readscheck-clause2-carriers --pair Nat exit 0 before requesting any review — a split is repaired at hang time, never at landing. Paid by a fold in the same 复核 block.Draft PR: #16339 (head
d88c29c76a). Both edited files are LINE-NEUTRAL: SKILL.md 811/811 with table pin 342 untouched,references/core-rules.md150/150. Gate union re-derived and run at that head: 16 of 16 derived commands green,--ranreconciled 16 run / 0 unrun; whole-repopnpm lintexit 0;check-governed-merges --testexit 3 GOVERNED.CI: converged green on this head — 29 of 29 check runs completed, 17 success / 12 skipped / 0 failures.
Generated by Claude Code
claude commentedon Sep 6, 2026
os-dev-report
This card's os-dev.md half is in the flight below — the dev now hangs
needs:contract-reviewon the PR in the same write that opens it and reports the--pairexit code, so a clause-2 hang cannot land single-carrier. The SKILL.md half is another flight's; that is why the PR carriesRefsfor this card and not a closing keyword. Full flight report follows.{ "issue": 14768, "status": "done", "branch": "claude/issue-14768-executable-fences-and-relock", "pr": "https://github.com/objectstack-ai/objectstack/pull/16357", "premise_still_valid": true, "summary": "Rewrite half of the census, plus the folded cards, in one governed PR (draft, one regime). The three hits outside pm-dispatch/SKILL.md became executable: os-dev.md's 「去问」 is now forbid plus a terminal route (never correct another actor's PR state; the question goes in the report, `blocked` where it blocks the work); dispatch-runbook.md's verbatim dispatch-word sentence became allow-with-trace (fix at the producer directly, landing point and reasoning into the report and the PR body — the 「报备后」 sequencing is gone); checklist-test/SKILL.md's strong form 「停下等维护者」 became the run ending with that report, moved in lockstep with its docs/qa/platform-checklist/RUNNER.md rule-2 twin. Two more clauses land on os-dev.md at 403/403 line-neutral: the ruled measurement-first exception for a zero-headroom governed ledger, and the clause-2 carrier line (hang needs:contract-review on the PR in the same write that opens it, report the --pair exit). Both are paid for by NAMED deleted rationale — two why-clauses in the ratchet block and the squash-concatenation sentence — never by re-wrap, so the 2026-08-17 筹行 ban holds. The re-lock pass lowers the retirement playbook's max-table-row-bytes pin 328 to 326; the ratchet now prints zero advisories. One dispatch mechanism assumption is FALSIFIED and was not relied on: check-skills-token-ratchet.mjs does not cover .claude/skills/** at all (its population is the published skills/ catalog), so checklist-test/SKILL.md is governed by the LINE ratchet (234 lines, ceiling 238) — it came in line-neutral regardless, and the token ratchet was run anyway, self-test and live, both green.", "tests": "All at the final head f5c08e9589 (after merging origin/main 3e270d4e29), every exit code redirected-then-captured, every verdict quoted from the gate's own line. (1) Derived family: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` over the five-path change set = 39 families; all 39 run; `--ran` reconciliation prints \"39 derived famil(ies) accounted for — 39 run, 0 NOT-MEASURED\" and \"39 derived, 39 run, 0 NOT-MEASURED, 0 UNRUN\". Derivation at the pre-merge and post-merge heads was byte-identical (39 commands, diff empty). (2) Line ratchet, live: \".claude/agents/os-dev.md is 403 lines (ceiling 403; headroom 0).\" / \"dispatch-runbook.md is 241 lines (ceiling 241; headroom 0).\" / \"checklist-test/SKILL.md is 234 lines (ceiling 238; headroom 4).\" / \"spec-property-retirement/SKILL.md: widest table row is 326 bytes (pin 326; headroom 0).\" Advisory count after the pin move: 0 (grep -c on the run log; it was 1 before). Self-test green via `pnpm check:pm-skill-ratchet`. (3) Token ratchet: --self-test and live both exit 0. (4) `node scripts/pm/check-governed-merges.mjs --test` over the five paths: exit 3, GOVERNED, one regime named (.claude/** x3), \"paths not on the register: docs/qa/platform-checklist/RUNNER.md, scripts/pm/check-skill-line-ratchet.mjs\" — so one PR, not two; --self-test exit 0 (274 assertions). (5) check-half-states --self-test exit 0, and every rewritten AND deleted sentence grepped over scripts/, .github/, packages/, docs/ in both old and new spellings: no pin names any of them. (6) All five .claude/hooks/*.selftest.sh exit 0. (7) Whole-repo `pnpm lint` (eslint . --no-inline-config) through scripts/pm/os-verify-lock.sh slot issue-14768: \"VERDICT command-exit 0 · held the lock 111s\" — whole-repo, NOT narrowed, so no narrowing declaration is owed. (8) One gate answered exit 3 PREREQUISITE NOT MET on the first pass (@objectstack/lint check:doc-formula-expressions, missing @objectstack/formula dist) — read as NOT MEASURED, not as red; cleared with `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` through the lock, then re-run: exit 0. (9) CI on the PR head f5c08e9589, polled in the foreground to completion: 34 check runs, 23 success / 11 skipped / 0 failing — Lint & Repo Gates success, TypeScript Type Check success, Test Core (all 6 shards) success, Dogfood Regression Gate success, Governed Surface Queue Guard success, Check Changeset success. No ablation applies to this card (no executable subject); the on-disk proof used instead was per-edit anchor counting: every deleted phrase greps to 0 and every injected phrase to 1, plus a byte-identity check (git hash-object on all five files, before and after replaying the patch onto current main: identical).", "mcp_calls": "1 — the create_pull_request write. Every GitHub read went through unauthenticated repo-scoped REST (probe 200) and git; the label write and the four report comments are REST POSTs.", "open_questions": [ { "question": "The PM-side summary row for the ratchet rules in .claude/skills/pm-dispatch/SKILL.md states the currency rules but not the new measurement-first exception. Should it carry the exception too?", "options": [ "A — leave it: the exception is dev-side, the PM row is a summary, and check:skill-frame-sync is green (it is not a COPIES mirror), so nothing is mechanically owed", "B — add the exception clause to that row in the SKILL.md flight (or a follow-up), so a PM reading only its own file does not brief the opposite of what the dev definition now allows" ], "recommendation": "A now, B as a cheap rider if the SKILL.md flight still has line budget. The exception fires only when the DISPATCH already names measurement-first, so the PM is by construction the party that knows about it; the risk of divergence is real but one-directional and small, and buying a line on a zero-headroom governed file to restate a rule the PM authors is worse value than the drift it prevents. This PR did not touch SKILL.md because that file is another flight's this round." } ], "out_of_scope_findings": [ "not filed (already fixed on main) — the census's second finding, dogfood-verification/SKILL.md instructing `gh pr merge --squash --auto` against the never-merge rule, no longer exists: that line now reads the correct `git worktree remove` rule without --force. Verified by grep on current main; no card is owed.", "not filed (a reading, not a defect) — the dispatch's mechanism note that checklist-test/SKILL.md is governed by check-skills-token-ratchet.mjs is wrong; that gate's population is the published skills/ root only. Recorded here and in the PR body so the next brief does not repeat it." ] }Generated by Claude Code