feat(pm): give the contract-review independence clause a machine carrier (C4) - #14216

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier
Sep 2, 2026
Merged

feat(pm): give the contract-review independence clause a machine carrier (C4)#14216
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #14209 — direction A's guard half. #14209 stays open: its template half is deferred on a
governance blocker named under "What is NOT in this PR", and merging this alone must not close the card.

Ruling being implemented (maintainer, 2026-09-01, verbatim and untranslated): 「同意 A」 — the
contract-review verdict template carries an Implemented-by: / Reviewed-by: session-ID pair, and the
guard refuses to recognise a verdict whose two IDs are the same session.

What changed

One file: scripts/pm/check-clause2-carriers.mjs, one new finding row C4, report-only like every
other row. No existing row is weakened or reordered, no label is ever written (the file's standing
NEVER_WRITES rule), and no sibling script is touched.

C4 reports a pair whose governing contract-review verdict names the SAME session on both authorship
lines — a self-review, which does not count as an independent review. The clause it finally carries is
references/contract-review.md's own: the in-seat path is scoped to 「低档实现者的契约增量,非自身产物」,
and its isolation sub-rule will not feed a reviewer even 「派发席自己的结论(污染即失独立性)」.

Four states, exactly as the card's scope sets them:

verdict on the card threadC4
both lines, same session IDfires — self-review
both lines, distinct session IDssilent — this is the shape the clause asks for
neither line (a legacy verdict)silent — absence never turns a historic pair red
one line onlyfires as its own MALFORMED state — half a pair compares to nothing

The four design choices worth reviewing

  1. The discriminator is a VERDICT: key line, picked from the live corpus rather than invented: real
    verdicts open a fenced block whose first line is VERDICT: PASS, beside REVIEWED-HEAD: and
    CLAUSE-2-PATH:. The same board supplies the near miss that makes the colon load-bearing — an os-dev
    report writes `VERDICT command-exit 0` in prose, repeatedly. Both are pinned as self-test
    fixtures, so a discriminator that matched the bare WORD would read a build log as a review verdict.
  2. Spelling strictness mirrors the Clause-②: reader one section up: case-sensitive key, the session
    token immediately after the colon, trailing reasoning tolerated, the same markdown decoration allowed.
    One convention for machine spellings in this file, not two. Its residual hole is stated in the row
    rather than hidden: both IDs are SELF-DECLARED, and this file compares them to each other without
    cross-checking either against the implementation claim — it catches the honest self-review.
  3. The NEWEST verdict carrying the pair governs. Load-bearing, not tidy: a self-review followed by an
    independent re-review is precisely the remedy the row asks for, so judging every verdict ever posted
    would leave a remediated pair red on every later sweep — the defect [finding] check-clause2-carriers.mjs --pair answers C3 / exit 4 on a LEGITIMATELY cleared clause-② pair — the completed state (declaration outlives the label) is indistinguishable from the fail-open it hunts #14155 had to repair in C3, where
    a row that could never clear made the landing check's own precondition unsatisfiable.
  4. It costs no new request. C4 reads the card comment thread the declaration limb already fetches.

The file header's boundary sentence was narrowed to match, not quietly broken: it read "it does not read
verdict comments"; it now reads "it reads no verdict VALUE", with a starred paragraph saying that the
authorship pair is the one thing read out of a verdict and that no PASS or FAIL token is read to reach
it. The PASS half of the recovery rule stays human, exactly as before.

What is NOT in this PR, and why — please read before reviewing scope

The dispatched surface was two files. The second, .claude/skills/pm-dispatch/references/contract-review.md
(the template lines plus one sentence about the guard), is not here, and could not be added inside the
dispatched surface.
Measured, not assumed:

  • check-skill-line-ratchet.mjs pins that file at 60 lines, and it is 60 lines — the gate's own
    verdict line is contract-review.md is 60 lines (ceiling 60; headroom 0). Any net growth is red.
  • Both in-place payments are refused by standing rulings, so the growth cannot be self-funded. Re-wrap or
    densify to buy lines is 筹行, banned by the maintainer's 2026-08-17 ruling as recorded in SKILL.md:
    「⛔ re-wrap(折行合并)不得用作筹行 …… 新增以删减付账;密度优化仅随净减内容的 PR 顺带」. Deleting a
    ruled clause is refused on the state-machine precedent, recorded twice in this very file's own ceiling
    comments.
  • The remaining route is the one this file's ceiling took on both prior occasions (51 to 57, then 57 to
    60): raise the ceiling, with the maintainer ruling quoted in the raising PR body — which means
    editing scripts/pm/check-skill-line-ratchet.mjs, a third file the dispatch did not authorize and
    explicitly said to stop on rather than improvise.

⚠️ It is also the wrong shape to improvise here specifically: granting my own diff an exemption from a
governance control, unilaterally, is the same act #14209 exists to record. So the guard ships and the
template waits for an authorization only the dispatching seat or the maintainer can give.

Consequence if this merges alone: none adverse. A verdict carrying neither line is silent by mandate,
so C4 simply does not fire until seats start writing the pair — the row is forward-compatible and inert
on today's board. The template half is what turns it on.

To finish the card on this branch: authorize the ceiling raise (60 to about 66), add the template
lines plus the guard sentence to the review-checklist section, record the raise above the CEILINGS entry
in the established comment form, and flip this PR's first line to the closing keyword.

Gates run

All readings at the pushed head 57f23063f (the final commit), every exit captured by
redirect-then-capture, never across a pipe.

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack EXIT=0, repo assertion held,
    1 path vs merge base b992b1d64, three-dot, 199 families discovered, 13 matched plus 2
    convention-triggered (adds or edits a GATE SCRIPT).
  • All 15 run. 14 EXIT=0: check:pm-clause2-carriers, check:pm-dispatch-gates,
    bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
    check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard,
    check:pnpm-filter-targets, check:watch-hint-literal, check-cross-package-test-inputs.mjs,
    check-ci-filter-parity.mjs, check-shard-attestation.mjs.
  • 1 NOT MEASURED, not a red: check-test-completeness.mjs EXIT=3, its own text — "The log comes from
    a test RUN. This gate does not run tests and cannot produce one … the local reading for this gate is
    NOT MEASURED." CI covers it.
  • ⚠️check-ci-filter-parity.mjs and check-shard-attestation.mjs first returned EXIT=3 PREREQUISITE
    NOT MET ("the dependency yaml is not installed") because the worktree had no node_modules yet;
    both were re-run after pnpm install and are the EXIT=0 readings above. Recorded because a 3 read as a
    pass would have been the false green.
  • Repo-wide, NOT narrowed: eslint . --no-inline-config --format json EXIT=0 — 5,644 files, 0 errors,
    0 warnings
    , with the edited file confirmed present in the linted set by its own JSON row.
  • check-nul-bytes.mjs EXIT=0 (7,766 files). Control-character self-scan over the edited file with
    grep -naP returned rc=1, no matches.
  • check-skill-line-ratchet.mjs EXIT=0 — unchanged, since no ceilinged file is touched.
  • Self-test: 138 cases pass, up from 98 on the base commit — 40 new, of which 30 are C4's.

Ablation — the new cases can actually fail

Run from the committed implementation, so the restore leg had something true to restore to. The C4
comparison was neutered (if (implementedBy !== reviewedBy) replaced by if (true), marker appended).
Mutation confirmed ON DISK before running, not from the editor's exit code: the original anchor's
grep -cF count went 1 to 0 and the injected marker's 0 to 1. Ablated run: EXIT=1, 11 of 138 cases
failed
, including "a same-session verdict FIRES C4" and "a self-reviewed pair is adverse even when
every carrier reading is clean". Restore by git checkout HEAD -- (absolute path) under an EXIT/INT/TERM
trap, then proved rather than assumed: git diff HEAD empty, marker count back to 0, and the worktree
blob hash equal to the HEAD blob hash (2ea30125… both sides). Self-test green again at 138.

No rebuild leg applies and none is claimed: this script is plain ESM executed from source, with no dist
between the edit and the run.

Landing shape

Draft, and it stays draft — .claude/-adjacent PM tooling under the governed four-step, which the
dispatching seat runs after this report. No auto-merge, no ready flip from here. skip-changeset applies
and is set: the diff is confined to scripts/pm/**, which publishes from no package.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-support-ai@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(pm): give the contract-review independence clause a machine carrier (C4) - #14216

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier
Sep 2, 2026
Merged

feat(pm): give the contract-review independence clause a machine carrier (C4)#14216
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #14209 — direction A's guard half. #14209 stays open: its template half is deferred on a
governance blocker named under "What is NOT in this PR", and merging this alone must not close the card.

Ruling being implemented (maintainer, 2026-09-01, verbatim and untranslated): 「同意 A」 — the
contract-review verdict template carries an Implemented-by: / Reviewed-by: session-ID pair, and the
guard refuses to recognise a verdict whose two IDs are the same session.

What changed

One file: scripts/pm/check-clause2-carriers.mjs, one new finding row C4, report-only like every
other row. No existing row is weakened or reordered, no label is ever written (the file's standing
NEVER_WRITES rule), and no sibling script is touched.

C4 reports a pair whose governing contract-review verdict names the SAME session on both authorship
lines — a self-review, which does not count as an independent review. The clause it finally carries is
references/contract-review.md's own: the in-seat path is scoped to 「低档实现者的契约增量,非自身产物」,
and its isolation sub-rule will not feed a reviewer even 「派发席自己的结论(污染即失独立性)」.

Four states, exactly as the card's scope sets them:

verdict on the card threadC4
both lines, same session IDfires — self-review
both lines, distinct session IDssilent — this is the shape the clause asks for
neither line (a legacy verdict)silent — absence never turns a historic pair red
one line onlyfires as its own MALFORMED state — half a pair compares to nothing

The four design choices worth reviewing

  1. The discriminator is a VERDICT: key line, picked from the live corpus rather than invented: real
    verdicts open a fenced block whose first line is VERDICT: PASS, beside REVIEWED-HEAD: and
    CLAUSE-2-PATH:. The same board supplies the near miss that makes the colon load-bearing — an os-dev
    report writes `VERDICT command-exit 0` in prose, repeatedly. Both are pinned as self-test
    fixtures, so a discriminator that matched the bare WORD would read a build log as a review verdict.
  2. Spelling strictness mirrors the Clause-②: reader one section up: case-sensitive key, the session
    token immediately after the colon, trailing reasoning tolerated, the same markdown decoration allowed.
    One convention for machine spellings in this file, not two. Its residual hole is stated in the row
    rather than hidden: both IDs are SELF-DECLARED, and this file compares them to each other without
    cross-checking either against the implementation claim — it catches the honest self-review.
  3. The NEWEST verdict carrying the pair governs. Load-bearing, not tidy: a self-review followed by an
    independent re-review is precisely the remedy the row asks for, so judging every verdict ever posted
    would leave a remediated pair red on every later sweep — the defect [finding] check-clause2-carriers.mjs --pair answers C3 / exit 4 on a LEGITIMATELY cleared clause-② pair — the completed state (declaration outlives the label) is indistinguishable from the fail-open it hunts #14155 had to repair in C3, where
    a row that could never clear made the landing check's own precondition unsatisfiable.
  4. It costs no new request. C4 reads the card comment thread the declaration limb already fetches.

The file header's boundary sentence was narrowed to match, not quietly broken: it read "it does not read
verdict comments"; it now reads "it reads no verdict VALUE", with a starred paragraph saying that the
authorship pair is the one thing read out of a verdict and that no PASS or FAIL token is read to reach
it. The PASS half of the recovery rule stays human, exactly as before.

What is NOT in this PR, and why — please read before reviewing scope

The dispatched surface was two files. The second, .claude/skills/pm-dispatch/references/contract-review.md
(the template lines plus one sentence about the guard), is not here, and could not be added inside the
dispatched surface.
Measured, not assumed:

  • check-skill-line-ratchet.mjs pins that file at 60 lines, and it is 60 lines — the gate's own
    verdict line is contract-review.md is 60 lines (ceiling 60; headroom 0). Any net growth is red.
  • Both in-place payments are refused by standing rulings, so the growth cannot be self-funded. Re-wrap or
    densify to buy lines is 筹行, banned by the maintainer's 2026-08-17 ruling as recorded in SKILL.md:
    「⛔ re-wrap(折行合并)不得用作筹行 …… 新增以删减付账;密度优化仅随净减内容的 PR 顺带」. Deleting a
    ruled clause is refused on the state-machine precedent, recorded twice in this very file's own ceiling
    comments.
  • The remaining route is the one this file's ceiling took on both prior occasions (51 to 57, then 57 to
    60): raise the ceiling, with the maintainer ruling quoted in the raising PR body — which means
    editing scripts/pm/check-skill-line-ratchet.mjs, a third file the dispatch did not authorize and
    explicitly said to stop on rather than improvise.

⚠️ It is also the wrong shape to improvise here specifically: granting my own diff an exemption from a
governance control, unilaterally, is the same act #14209 exists to record. So the guard ships and the
template waits for an authorization only the dispatching seat or the maintainer can give.

Consequence if this merges alone: none adverse. A verdict carrying neither line is silent by mandate,
so C4 simply does not fire until seats start writing the pair — the row is forward-compatible and inert
on today's board. The template half is what turns it on.

To finish the card on this branch: authorize the ceiling raise (60 to about 66), add the template
lines plus the guard sentence to the review-checklist section, record the raise above the CEILINGS entry
in the established comment form, and flip this PR's first line to the closing keyword.

Gates run

All readings at the pushed head 57f23063f (the final commit), every exit captured by
redirect-then-capture, never across a pipe.

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack EXIT=0, repo assertion held,
    1 path vs merge base b992b1d64, three-dot, 199 families discovered, 13 matched plus 2
    convention-triggered (adds or edits a GATE SCRIPT).
  • All 15 run. 14 EXIT=0: check:pm-clause2-carriers, check:pm-dispatch-gates,
    bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
    check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard,
    check:pnpm-filter-targets, check:watch-hint-literal, check-cross-package-test-inputs.mjs,
    check-ci-filter-parity.mjs, check-shard-attestation.mjs.
  • 1 NOT MEASURED, not a red: check-test-completeness.mjs EXIT=3, its own text — "The log comes from
    a test RUN. This gate does not run tests and cannot produce one … the local reading for this gate is
    NOT MEASURED." CI covers it.
  • ⚠️check-ci-filter-parity.mjs and check-shard-attestation.mjs first returned EXIT=3 PREREQUISITE
    NOT MET ("the dependency yaml is not installed") because the worktree had no node_modules yet;
    both were re-run after pnpm install and are the EXIT=0 readings above. Recorded because a 3 read as a
    pass would have been the false green.
  • Repo-wide, NOT narrowed: eslint . --no-inline-config --format json EXIT=0 — 5,644 files, 0 errors,
    0 warnings
    , with the edited file confirmed present in the linted set by its own JSON row.
  • check-nul-bytes.mjs EXIT=0 (7,766 files). Control-character self-scan over the edited file with
    grep -naP returned rc=1, no matches.
  • check-skill-line-ratchet.mjs EXIT=0 — unchanged, since no ceilinged file is touched.
  • Self-test: 138 cases pass, up from 98 on the base commit — 40 new, of which 30 are C4's.

Ablation — the new cases can actually fail

Run from the committed implementation, so the restore leg had something true to restore to. The C4
comparison was neutered (if (implementedBy !== reviewedBy) replaced by if (true), marker appended).
Mutation confirmed ON DISK before running, not from the editor's exit code: the original anchor's
grep -cF count went 1 to 0 and the injected marker's 0 to 1. Ablated run: EXIT=1, 11 of 138 cases
failed
, including "a same-session verdict FIRES C4" and "a self-reviewed pair is adverse even when
every carrier reading is clean". Restore by git checkout HEAD -- (absolute path) under an EXIT/INT/TERM
trap, then proved rather than assumed: git diff HEAD empty, marker count back to 0, and the worktree
blob hash equal to the HEAD blob hash (2ea30125… both sides). Self-test green again at 138.

No rebuild leg applies and none is claimed: this script is plain ESM executed from source, with no dist
between the edit and the run.

Landing shape

Draft, and it stays draft — .claude/-adjacent PM tooling under the governed four-step, which the
dispatching seat runs after this report. No auto-merge, no ready flip from here. skip-changeset applies
and is set: the diff is confined to scripts/pm/**, which publishes from no package.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-support-ai@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(pm): give the contract-review independence clause a machine carrier (C4) - #14216

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier
Sep 2, 2026
Merged

feat(pm): give the contract-review independence clause a machine carrier (C4)#14216
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #14209 — direction A's guard half. #14209 stays open: its template half is deferred on a
governance blocker named under "What is NOT in this PR", and merging this alone must not close the card.

Ruling being implemented (maintainer, 2026-09-01, verbatim and untranslated): 「同意 A」 — the
contract-review verdict template carries an Implemented-by: / Reviewed-by: session-ID pair, and the
guard refuses to recognise a verdict whose two IDs are the same session.

What changed

One file: scripts/pm/check-clause2-carriers.mjs, one new finding row C4, report-only like every
other row. No existing row is weakened or reordered, no label is ever written (the file's standing
NEVER_WRITES rule), and no sibling script is touched.

C4 reports a pair whose governing contract-review verdict names the SAME session on both authorship
lines — a self-review, which does not count as an independent review. The clause it finally carries is
references/contract-review.md's own: the in-seat path is scoped to 「低档实现者的契约增量,非自身产物」,
and its isolation sub-rule will not feed a reviewer even 「派发席自己的结论(污染即失独立性)」.

Four states, exactly as the card's scope sets them:

verdict on the card threadC4
both lines, same session IDfires — self-review
both lines, distinct session IDssilent — this is the shape the clause asks for
neither line (a legacy verdict)silent — absence never turns a historic pair red
one line onlyfires as its own MALFORMED state — half a pair compares to nothing

The four design choices worth reviewing

  1. The discriminator is a VERDICT: key line, picked from the live corpus rather than invented: real
    verdicts open a fenced block whose first line is VERDICT: PASS, beside REVIEWED-HEAD: and
    CLAUSE-2-PATH:. The same board supplies the near miss that makes the colon load-bearing — an os-dev
    report writes `VERDICT command-exit 0` in prose, repeatedly. Both are pinned as self-test
    fixtures, so a discriminator that matched the bare WORD would read a build log as a review verdict.
  2. Spelling strictness mirrors the Clause-②: reader one section up: case-sensitive key, the session
    token immediately after the colon, trailing reasoning tolerated, the same markdown decoration allowed.
    One convention for machine spellings in this file, not two. Its residual hole is stated in the row
    rather than hidden: both IDs are SELF-DECLARED, and this file compares them to each other without
    cross-checking either against the implementation claim — it catches the honest self-review.
  3. The NEWEST verdict carrying the pair governs. Load-bearing, not tidy: a self-review followed by an
    independent re-review is precisely the remedy the row asks for, so judging every verdict ever posted
    would leave a remediated pair red on every later sweep — the defect [finding] check-clause2-carriers.mjs --pair answers C3 / exit 4 on a LEGITIMATELY cleared clause-② pair — the completed state (declaration outlives the label) is indistinguishable from the fail-open it hunts #14155 had to repair in C3, where
    a row that could never clear made the landing check's own precondition unsatisfiable.
  4. It costs no new request. C4 reads the card comment thread the declaration limb already fetches.

The file header's boundary sentence was narrowed to match, not quietly broken: it read "it does not read
verdict comments"; it now reads "it reads no verdict VALUE", with a starred paragraph saying that the
authorship pair is the one thing read out of a verdict and that no PASS or FAIL token is read to reach
it. The PASS half of the recovery rule stays human, exactly as before.

What is NOT in this PR, and why — please read before reviewing scope

The dispatched surface was two files. The second, .claude/skills/pm-dispatch/references/contract-review.md
(the template lines plus one sentence about the guard), is not here, and could not be added inside the
dispatched surface.
Measured, not assumed:

  • check-skill-line-ratchet.mjs pins that file at 60 lines, and it is 60 lines — the gate's own
    verdict line is contract-review.md is 60 lines (ceiling 60; headroom 0). Any net growth is red.
  • Both in-place payments are refused by standing rulings, so the growth cannot be self-funded. Re-wrap or
    densify to buy lines is 筹行, banned by the maintainer's 2026-08-17 ruling as recorded in SKILL.md:
    「⛔ re-wrap(折行合并)不得用作筹行 …… 新增以删减付账;密度优化仅随净减内容的 PR 顺带」. Deleting a
    ruled clause is refused on the state-machine precedent, recorded twice in this very file's own ceiling
    comments.
  • The remaining route is the one this file's ceiling took on both prior occasions (51 to 57, then 57 to
    60): raise the ceiling, with the maintainer ruling quoted in the raising PR body — which means
    editing scripts/pm/check-skill-line-ratchet.mjs, a third file the dispatch did not authorize and
    explicitly said to stop on rather than improvise.

⚠️ It is also the wrong shape to improvise here specifically: granting my own diff an exemption from a
governance control, unilaterally, is the same act #14209 exists to record. So the guard ships and the
template waits for an authorization only the dispatching seat or the maintainer can give.

Consequence if this merges alone: none adverse. A verdict carrying neither line is silent by mandate,
so C4 simply does not fire until seats start writing the pair — the row is forward-compatible and inert
on today's board. The template half is what turns it on.

To finish the card on this branch: authorize the ceiling raise (60 to about 66), add the template
lines plus the guard sentence to the review-checklist section, record the raise above the CEILINGS entry
in the established comment form, and flip this PR's first line to the closing keyword.

Gates run

All readings at the pushed head 57f23063f (the final commit), every exit captured by
redirect-then-capture, never across a pipe.

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack EXIT=0, repo assertion held,
    1 path vs merge base b992b1d64, three-dot, 199 families discovered, 13 matched plus 2
    convention-triggered (adds or edits a GATE SCRIPT).
  • All 15 run. 14 EXIT=0: check:pm-clause2-carriers, check:pm-dispatch-gates,
    bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
    check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard,
    check:pnpm-filter-targets, check:watch-hint-literal, check-cross-package-test-inputs.mjs,
    check-ci-filter-parity.mjs, check-shard-attestation.mjs.
  • 1 NOT MEASURED, not a red: check-test-completeness.mjs EXIT=3, its own text — "The log comes from
    a test RUN. This gate does not run tests and cannot produce one … the local reading for this gate is
    NOT MEASURED." CI covers it.
  • ⚠️check-ci-filter-parity.mjs and check-shard-attestation.mjs first returned EXIT=3 PREREQUISITE
    NOT MET ("the dependency yaml is not installed") because the worktree had no node_modules yet;
    both were re-run after pnpm install and are the EXIT=0 readings above. Recorded because a 3 read as a
    pass would have been the false green.
  • Repo-wide, NOT narrowed: eslint . --no-inline-config --format json EXIT=0 — 5,644 files, 0 errors,
    0 warnings
    , with the edited file confirmed present in the linted set by its own JSON row.
  • check-nul-bytes.mjs EXIT=0 (7,766 files). Control-character self-scan over the edited file with
    grep -naP returned rc=1, no matches.
  • check-skill-line-ratchet.mjs EXIT=0 — unchanged, since no ceilinged file is touched.
  • Self-test: 138 cases pass, up from 98 on the base commit — 40 new, of which 30 are C4's.

Ablation — the new cases can actually fail

Run from the committed implementation, so the restore leg had something true to restore to. The C4
comparison was neutered (if (implementedBy !== reviewedBy) replaced by if (true), marker appended).
Mutation confirmed ON DISK before running, not from the editor's exit code: the original anchor's
grep -cF count went 1 to 0 and the injected marker's 0 to 1. Ablated run: EXIT=1, 11 of 138 cases
failed
, including "a same-session verdict FIRES C4" and "a self-reviewed pair is adverse even when
every carrier reading is clean". Restore by git checkout HEAD -- (absolute path) under an EXIT/INT/TERM
trap, then proved rather than assumed: git diff HEAD empty, marker count back to 0, and the worktree
blob hash equal to the HEAD blob hash (2ea30125… both sides). Self-test green again at 138.

No rebuild leg applies and none is claimed: this script is plain ESM executed from source, with no dist
between the edit and the run.

Landing shape

Draft, and it stays draft — .claude/-adjacent PM tooling under the governed four-step, which the
dispatching seat runs after this report. No auto-merge, no ready flip from here. skip-changeset applies
and is set: the diff is confined to scripts/pm/**, which publishes from no package.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-support-ai@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(pm): give the contract-review independence clause a machine carrier (C4) - #14216

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier
Sep 2, 2026
Merged

feat(pm): give the contract-review independence clause a machine carrier (C4)#14216
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #14209 — direction A's guard half. #14209 stays open: its template half is deferred on a
governance blocker named under "What is NOT in this PR", and merging this alone must not close the card.

Ruling being implemented (maintainer, 2026-09-01, verbatim and untranslated): 「同意 A」 — the
contract-review verdict template carries an Implemented-by: / Reviewed-by: session-ID pair, and the
guard refuses to recognise a verdict whose two IDs are the same session.

What changed

One file: scripts/pm/check-clause2-carriers.mjs, one new finding row C4, report-only like every
other row. No existing row is weakened or reordered, no label is ever written (the file's standing
NEVER_WRITES rule), and no sibling script is touched.

C4 reports a pair whose governing contract-review verdict names the SAME session on both authorship
lines — a self-review, which does not count as an independent review. The clause it finally carries is
references/contract-review.md's own: the in-seat path is scoped to 「低档实现者的契约增量,非自身产物」,
and its isolation sub-rule will not feed a reviewer even 「派发席自己的结论(污染即失独立性)」.

Four states, exactly as the card's scope sets them:

verdict on the card threadC4
both lines, same session IDfires — self-review
both lines, distinct session IDssilent — this is the shape the clause asks for
neither line (a legacy verdict)silent — absence never turns a historic pair red
one line onlyfires as its own MALFORMED state — half a pair compares to nothing

The four design choices worth reviewing

  1. The discriminator is a VERDICT: key line, picked from the live corpus rather than invented: real
    verdicts open a fenced block whose first line is VERDICT: PASS, beside REVIEWED-HEAD: and
    CLAUSE-2-PATH:. The same board supplies the near miss that makes the colon load-bearing — an os-dev
    report writes `VERDICT command-exit 0` in prose, repeatedly. Both are pinned as self-test
    fixtures, so a discriminator that matched the bare WORD would read a build log as a review verdict.
  2. Spelling strictness mirrors the Clause-②: reader one section up: case-sensitive key, the session
    token immediately after the colon, trailing reasoning tolerated, the same markdown decoration allowed.
    One convention for machine spellings in this file, not two. Its residual hole is stated in the row
    rather than hidden: both IDs are SELF-DECLARED, and this file compares them to each other without
    cross-checking either against the implementation claim — it catches the honest self-review.
  3. The NEWEST verdict carrying the pair governs. Load-bearing, not tidy: a self-review followed by an
    independent re-review is precisely the remedy the row asks for, so judging every verdict ever posted
    would leave a remediated pair red on every later sweep — the defect [finding] check-clause2-carriers.mjs --pair answers C3 / exit 4 on a LEGITIMATELY cleared clause-② pair — the completed state (declaration outlives the label) is indistinguishable from the fail-open it hunts #14155 had to repair in C3, where
    a row that could never clear made the landing check's own precondition unsatisfiable.
  4. It costs no new request. C4 reads the card comment thread the declaration limb already fetches.

The file header's boundary sentence was narrowed to match, not quietly broken: it read "it does not read
verdict comments"; it now reads "it reads no verdict VALUE", with a starred paragraph saying that the
authorship pair is the one thing read out of a verdict and that no PASS or FAIL token is read to reach
it. The PASS half of the recovery rule stays human, exactly as before.

What is NOT in this PR, and why — please read before reviewing scope

The dispatched surface was two files. The second, .claude/skills/pm-dispatch/references/contract-review.md
(the template lines plus one sentence about the guard), is not here, and could not be added inside the
dispatched surface.
Measured, not assumed:

  • check-skill-line-ratchet.mjs pins that file at 60 lines, and it is 60 lines — the gate's own
    verdict line is contract-review.md is 60 lines (ceiling 60; headroom 0). Any net growth is red.
  • Both in-place payments are refused by standing rulings, so the growth cannot be self-funded. Re-wrap or
    densify to buy lines is 筹行, banned by the maintainer's 2026-08-17 ruling as recorded in SKILL.md:
    「⛔ re-wrap(折行合并)不得用作筹行 …… 新增以删减付账;密度优化仅随净减内容的 PR 顺带」. Deleting a
    ruled clause is refused on the state-machine precedent, recorded twice in this very file's own ceiling
    comments.
  • The remaining route is the one this file's ceiling took on both prior occasions (51 to 57, then 57 to
    60): raise the ceiling, with the maintainer ruling quoted in the raising PR body — which means
    editing scripts/pm/check-skill-line-ratchet.mjs, a third file the dispatch did not authorize and
    explicitly said to stop on rather than improvise.

⚠️ It is also the wrong shape to improvise here specifically: granting my own diff an exemption from a
governance control, unilaterally, is the same act #14209 exists to record. So the guard ships and the
template waits for an authorization only the dispatching seat or the maintainer can give.

Consequence if this merges alone: none adverse. A verdict carrying neither line is silent by mandate,
so C4 simply does not fire until seats start writing the pair — the row is forward-compatible and inert
on today's board. The template half is what turns it on.

To finish the card on this branch: authorize the ceiling raise (60 to about 66), add the template
lines plus the guard sentence to the review-checklist section, record the raise above the CEILINGS entry
in the established comment form, and flip this PR's first line to the closing keyword.

Gates run

All readings at the pushed head 57f23063f (the final commit), every exit captured by
redirect-then-capture, never across a pipe.

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack EXIT=0, repo assertion held,
    1 path vs merge base b992b1d64, three-dot, 199 families discovered, 13 matched plus 2
    convention-triggered (adds or edits a GATE SCRIPT).
  • All 15 run. 14 EXIT=0: check:pm-clause2-carriers, check:pm-dispatch-gates,
    bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
    check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard,
    check:pnpm-filter-targets, check:watch-hint-literal, check-cross-package-test-inputs.mjs,
    check-ci-filter-parity.mjs, check-shard-attestation.mjs.
  • 1 NOT MEASURED, not a red: check-test-completeness.mjs EXIT=3, its own text — "The log comes from
    a test RUN. This gate does not run tests and cannot produce one … the local reading for this gate is
    NOT MEASURED." CI covers it.
  • ⚠️check-ci-filter-parity.mjs and check-shard-attestation.mjs first returned EXIT=3 PREREQUISITE
    NOT MET ("the dependency yaml is not installed") because the worktree had no node_modules yet;
    both were re-run after pnpm install and are the EXIT=0 readings above. Recorded because a 3 read as a
    pass would have been the false green.
  • Repo-wide, NOT narrowed: eslint . --no-inline-config --format json EXIT=0 — 5,644 files, 0 errors,
    0 warnings
    , with the edited file confirmed present in the linted set by its own JSON row.
  • check-nul-bytes.mjs EXIT=0 (7,766 files). Control-character self-scan over the edited file with
    grep -naP returned rc=1, no matches.
  • check-skill-line-ratchet.mjs EXIT=0 — unchanged, since no ceilinged file is touched.
  • Self-test: 138 cases pass, up from 98 on the base commit — 40 new, of which 30 are C4's.

Ablation — the new cases can actually fail

Run from the committed implementation, so the restore leg had something true to restore to. The C4
comparison was neutered (if (implementedBy !== reviewedBy) replaced by if (true), marker appended).
Mutation confirmed ON DISK before running, not from the editor's exit code: the original anchor's
grep -cF count went 1 to 0 and the injected marker's 0 to 1. Ablated run: EXIT=1, 11 of 138 cases
failed
, including "a same-session verdict FIRES C4" and "a self-reviewed pair is adverse even when
every carrier reading is clean". Restore by git checkout HEAD -- (absolute path) under an EXIT/INT/TERM
trap, then proved rather than assumed: git diff HEAD empty, marker count back to 0, and the worktree
blob hash equal to the HEAD blob hash (2ea30125… both sides). Self-test green again at 138.

No rebuild leg applies and none is claimed: this script is plain ESM executed from source, with no dist
between the edit and the run.

Landing shape

Draft, and it stays draft — .claude/-adjacent PM tooling under the governed four-step, which the
dispatching seat runs after this report. No auto-merge, no ready flip from here. skip-changeset applies
and is set: the diff is confined to scripts/pm/**, which publishes from no package.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-support-ai@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(pm): give the contract-review independence clause a machine carrier (C4) - #14216

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier
Sep 2, 2026
Merged

feat(pm): give the contract-review independence clause a machine carrier (C4)#14216
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #14209 — direction A's guard half. #14209 stays open: its template half is deferred on a
governance blocker named under "What is NOT in this PR", and merging this alone must not close the card.

Ruling being implemented (maintainer, 2026-09-01, verbatim and untranslated): 「同意 A」 — the
contract-review verdict template carries an Implemented-by: / Reviewed-by: session-ID pair, and the
guard refuses to recognise a verdict whose two IDs are the same session.

What changed

One file: scripts/pm/check-clause2-carriers.mjs, one new finding row C4, report-only like every
other row. No existing row is weakened or reordered, no label is ever written (the file's standing
NEVER_WRITES rule), and no sibling script is touched.

C4 reports a pair whose governing contract-review verdict names the SAME session on both authorship
lines — a self-review, which does not count as an independent review. The clause it finally carries is
references/contract-review.md's own: the in-seat path is scoped to 「低档实现者的契约增量,非自身产物」,
and its isolation sub-rule will not feed a reviewer even 「派发席自己的结论(污染即失独立性)」.

Four states, exactly as the card's scope sets them:

verdict on the card threadC4
both lines, same session IDfires — self-review
both lines, distinct session IDssilent — this is the shape the clause asks for
neither line (a legacy verdict)silent — absence never turns a historic pair red
one line onlyfires as its own MALFORMED state — half a pair compares to nothing

The four design choices worth reviewing

  1. The discriminator is a VERDICT: key line, picked from the live corpus rather than invented: real
    verdicts open a fenced block whose first line is VERDICT: PASS, beside REVIEWED-HEAD: and
    CLAUSE-2-PATH:. The same board supplies the near miss that makes the colon load-bearing — an os-dev
    report writes `VERDICT command-exit 0` in prose, repeatedly. Both are pinned as self-test
    fixtures, so a discriminator that matched the bare WORD would read a build log as a review verdict.
  2. Spelling strictness mirrors the Clause-②: reader one section up: case-sensitive key, the session
    token immediately after the colon, trailing reasoning tolerated, the same markdown decoration allowed.
    One convention for machine spellings in this file, not two. Its residual hole is stated in the row
    rather than hidden: both IDs are SELF-DECLARED, and this file compares them to each other without
    cross-checking either against the implementation claim — it catches the honest self-review.
  3. The NEWEST verdict carrying the pair governs. Load-bearing, not tidy: a self-review followed by an
    independent re-review is precisely the remedy the row asks for, so judging every verdict ever posted
    would leave a remediated pair red on every later sweep — the defect [finding] check-clause2-carriers.mjs --pair answers C3 / exit 4 on a LEGITIMATELY cleared clause-② pair — the completed state (declaration outlives the label) is indistinguishable from the fail-open it hunts #14155 had to repair in C3, where
    a row that could never clear made the landing check's own precondition unsatisfiable.
  4. It costs no new request. C4 reads the card comment thread the declaration limb already fetches.

The file header's boundary sentence was narrowed to match, not quietly broken: it read "it does not read
verdict comments"; it now reads "it reads no verdict VALUE", with a starred paragraph saying that the
authorship pair is the one thing read out of a verdict and that no PASS or FAIL token is read to reach
it. The PASS half of the recovery rule stays human, exactly as before.

What is NOT in this PR, and why — please read before reviewing scope

The dispatched surface was two files. The second, .claude/skills/pm-dispatch/references/contract-review.md
(the template lines plus one sentence about the guard), is not here, and could not be added inside the
dispatched surface.
Measured, not assumed:

  • check-skill-line-ratchet.mjs pins that file at 60 lines, and it is 60 lines — the gate's own
    verdict line is contract-review.md is 60 lines (ceiling 60; headroom 0). Any net growth is red.
  • Both in-place payments are refused by standing rulings, so the growth cannot be self-funded. Re-wrap or
    densify to buy lines is 筹行, banned by the maintainer's 2026-08-17 ruling as recorded in SKILL.md:
    「⛔ re-wrap(折行合并)不得用作筹行 …… 新增以删减付账;密度优化仅随净减内容的 PR 顺带」. Deleting a
    ruled clause is refused on the state-machine precedent, recorded twice in this very file's own ceiling
    comments.
  • The remaining route is the one this file's ceiling took on both prior occasions (51 to 57, then 57 to
    60): raise the ceiling, with the maintainer ruling quoted in the raising PR body — which means
    editing scripts/pm/check-skill-line-ratchet.mjs, a third file the dispatch did not authorize and
    explicitly said to stop on rather than improvise.

⚠️ It is also the wrong shape to improvise here specifically: granting my own diff an exemption from a
governance control, unilaterally, is the same act #14209 exists to record. So the guard ships and the
template waits for an authorization only the dispatching seat or the maintainer can give.

Consequence if this merges alone: none adverse. A verdict carrying neither line is silent by mandate,
so C4 simply does not fire until seats start writing the pair — the row is forward-compatible and inert
on today's board. The template half is what turns it on.

To finish the card on this branch: authorize the ceiling raise (60 to about 66), add the template
lines plus the guard sentence to the review-checklist section, record the raise above the CEILINGS entry
in the established comment form, and flip this PR's first line to the closing keyword.

Gates run

All readings at the pushed head 57f23063f (the final commit), every exit captured by
redirect-then-capture, never across a pipe.

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack EXIT=0, repo assertion held,
    1 path vs merge base b992b1d64, three-dot, 199 families discovered, 13 matched plus 2
    convention-triggered (adds or edits a GATE SCRIPT).
  • All 15 run. 14 EXIT=0: check:pm-clause2-carriers, check:pm-dispatch-gates,
    bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
    check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard,
    check:pnpm-filter-targets, check:watch-hint-literal, check-cross-package-test-inputs.mjs,
    check-ci-filter-parity.mjs, check-shard-attestation.mjs.
  • 1 NOT MEASURED, not a red: check-test-completeness.mjs EXIT=3, its own text — "The log comes from
    a test RUN. This gate does not run tests and cannot produce one … the local reading for this gate is
    NOT MEASURED." CI covers it.
  • ⚠️check-ci-filter-parity.mjs and check-shard-attestation.mjs first returned EXIT=3 PREREQUISITE
    NOT MET ("the dependency yaml is not installed") because the worktree had no node_modules yet;
    both were re-run after pnpm install and are the EXIT=0 readings above. Recorded because a 3 read as a
    pass would have been the false green.
  • Repo-wide, NOT narrowed: eslint . --no-inline-config --format json EXIT=0 — 5,644 files, 0 errors,
    0 warnings
    , with the edited file confirmed present in the linted set by its own JSON row.
  • check-nul-bytes.mjs EXIT=0 (7,766 files). Control-character self-scan over the edited file with
    grep -naP returned rc=1, no matches.
  • check-skill-line-ratchet.mjs EXIT=0 — unchanged, since no ceilinged file is touched.
  • Self-test: 138 cases pass, up from 98 on the base commit — 40 new, of which 30 are C4's.

Ablation — the new cases can actually fail

Run from the committed implementation, so the restore leg had something true to restore to. The C4
comparison was neutered (if (implementedBy !== reviewedBy) replaced by if (true), marker appended).
Mutation confirmed ON DISK before running, not from the editor's exit code: the original anchor's
grep -cF count went 1 to 0 and the injected marker's 0 to 1. Ablated run: EXIT=1, 11 of 138 cases
failed
, including "a same-session verdict FIRES C4" and "a self-reviewed pair is adverse even when
every carrier reading is clean". Restore by git checkout HEAD -- (absolute path) under an EXIT/INT/TERM
trap, then proved rather than assumed: git diff HEAD empty, marker count back to 0, and the worktree
blob hash equal to the HEAD blob hash (2ea30125… both sides). Self-test green again at 138.

No rebuild leg applies and none is claimed: this script is plain ESM executed from source, with no dist
between the edit and the run.

Landing shape

Draft, and it stays draft — .claude/-adjacent PM tooling under the governed four-step, which the
dispatching seat runs after this report. No auto-merge, no ready flip from here. skip-changeset applies
and is set: the diff is confined to scripts/pm/**, which publishes from no package.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-support-ai@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(pm): give the contract-review independence clause a machine carrier (C4) - #14216

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier
Sep 2, 2026
Merged

feat(pm): give the contract-review independence clause a machine carrier (C4)#14216
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #14209 — direction A's guard half. #14209 stays open: its template half is deferred on a
governance blocker named under "What is NOT in this PR", and merging this alone must not close the card.

Ruling being implemented (maintainer, 2026-09-01, verbatim and untranslated): 「同意 A」 — the
contract-review verdict template carries an Implemented-by: / Reviewed-by: session-ID pair, and the
guard refuses to recognise a verdict whose two IDs are the same session.

What changed

One file: scripts/pm/check-clause2-carriers.mjs, one new finding row C4, report-only like every
other row. No existing row is weakened or reordered, no label is ever written (the file's standing
NEVER_WRITES rule), and no sibling script is touched.

C4 reports a pair whose governing contract-review verdict names the SAME session on both authorship
lines — a self-review, which does not count as an independent review. The clause it finally carries is
references/contract-review.md's own: the in-seat path is scoped to 「低档实现者的契约增量,非自身产物」,
and its isolation sub-rule will not feed a reviewer even 「派发席自己的结论(污染即失独立性)」.

Four states, exactly as the card's scope sets them:

verdict on the card threadC4
both lines, same session IDfires — self-review
both lines, distinct session IDssilent — this is the shape the clause asks for
neither line (a legacy verdict)silent — absence never turns a historic pair red
one line onlyfires as its own MALFORMED state — half a pair compares to nothing

The four design choices worth reviewing

  1. The discriminator is a VERDICT: key line, picked from the live corpus rather than invented: real
    verdicts open a fenced block whose first line is VERDICT: PASS, beside REVIEWED-HEAD: and
    CLAUSE-2-PATH:. The same board supplies the near miss that makes the colon load-bearing — an os-dev
    report writes `VERDICT command-exit 0` in prose, repeatedly. Both are pinned as self-test
    fixtures, so a discriminator that matched the bare WORD would read a build log as a review verdict.
  2. Spelling strictness mirrors the Clause-②: reader one section up: case-sensitive key, the session
    token immediately after the colon, trailing reasoning tolerated, the same markdown decoration allowed.
    One convention for machine spellings in this file, not two. Its residual hole is stated in the row
    rather than hidden: both IDs are SELF-DECLARED, and this file compares them to each other without
    cross-checking either against the implementation claim — it catches the honest self-review.
  3. The NEWEST verdict carrying the pair governs. Load-bearing, not tidy: a self-review followed by an
    independent re-review is precisely the remedy the row asks for, so judging every verdict ever posted
    would leave a remediated pair red on every later sweep — the defect [finding] check-clause2-carriers.mjs --pair answers C3 / exit 4 on a LEGITIMATELY cleared clause-② pair — the completed state (declaration outlives the label) is indistinguishable from the fail-open it hunts #14155 had to repair in C3, where
    a row that could never clear made the landing check's own precondition unsatisfiable.
  4. It costs no new request. C4 reads the card comment thread the declaration limb already fetches.

The file header's boundary sentence was narrowed to match, not quietly broken: it read "it does not read
verdict comments"; it now reads "it reads no verdict VALUE", with a starred paragraph saying that the
authorship pair is the one thing read out of a verdict and that no PASS or FAIL token is read to reach
it. The PASS half of the recovery rule stays human, exactly as before.

What is NOT in this PR, and why — please read before reviewing scope

The dispatched surface was two files. The second, .claude/skills/pm-dispatch/references/contract-review.md
(the template lines plus one sentence about the guard), is not here, and could not be added inside the
dispatched surface.
Measured, not assumed:

  • check-skill-line-ratchet.mjs pins that file at 60 lines, and it is 60 lines — the gate's own
    verdict line is contract-review.md is 60 lines (ceiling 60; headroom 0). Any net growth is red.
  • Both in-place payments are refused by standing rulings, so the growth cannot be self-funded. Re-wrap or
    densify to buy lines is 筹行, banned by the maintainer's 2026-08-17 ruling as recorded in SKILL.md:
    「⛔ re-wrap(折行合并)不得用作筹行 …… 新增以删减付账;密度优化仅随净减内容的 PR 顺带」. Deleting a
    ruled clause is refused on the state-machine precedent, recorded twice in this very file's own ceiling
    comments.
  • The remaining route is the one this file's ceiling took on both prior occasions (51 to 57, then 57 to
    60): raise the ceiling, with the maintainer ruling quoted in the raising PR body — which means
    editing scripts/pm/check-skill-line-ratchet.mjs, a third file the dispatch did not authorize and
    explicitly said to stop on rather than improvise.

⚠️ It is also the wrong shape to improvise here specifically: granting my own diff an exemption from a
governance control, unilaterally, is the same act #14209 exists to record. So the guard ships and the
template waits for an authorization only the dispatching seat or the maintainer can give.

Consequence if this merges alone: none adverse. A verdict carrying neither line is silent by mandate,
so C4 simply does not fire until seats start writing the pair — the row is forward-compatible and inert
on today's board. The template half is what turns it on.

To finish the card on this branch: authorize the ceiling raise (60 to about 66), add the template
lines plus the guard sentence to the review-checklist section, record the raise above the CEILINGS entry
in the established comment form, and flip this PR's first line to the closing keyword.

Gates run

All readings at the pushed head 57f23063f (the final commit), every exit captured by
redirect-then-capture, never across a pipe.

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack EXIT=0, repo assertion held,
    1 path vs merge base b992b1d64, three-dot, 199 families discovered, 13 matched plus 2
    convention-triggered (adds or edits a GATE SCRIPT).
  • All 15 run. 14 EXIT=0: check:pm-clause2-carriers, check:pm-dispatch-gates,
    bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
    check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard,
    check:pnpm-filter-targets, check:watch-hint-literal, check-cross-package-test-inputs.mjs,
    check-ci-filter-parity.mjs, check-shard-attestation.mjs.
  • 1 NOT MEASURED, not a red: check-test-completeness.mjs EXIT=3, its own text — "The log comes from
    a test RUN. This gate does not run tests and cannot produce one … the local reading for this gate is
    NOT MEASURED." CI covers it.
  • ⚠️check-ci-filter-parity.mjs and check-shard-attestation.mjs first returned EXIT=3 PREREQUISITE
    NOT MET ("the dependency yaml is not installed") because the worktree had no node_modules yet;
    both were re-run after pnpm install and are the EXIT=0 readings above. Recorded because a 3 read as a
    pass would have been the false green.
  • Repo-wide, NOT narrowed: eslint . --no-inline-config --format json EXIT=0 — 5,644 files, 0 errors,
    0 warnings
    , with the edited file confirmed present in the linted set by its own JSON row.
  • check-nul-bytes.mjs EXIT=0 (7,766 files). Control-character self-scan over the edited file with
    grep -naP returned rc=1, no matches.
  • check-skill-line-ratchet.mjs EXIT=0 — unchanged, since no ceilinged file is touched.
  • Self-test: 138 cases pass, up from 98 on the base commit — 40 new, of which 30 are C4's.

Ablation — the new cases can actually fail

Run from the committed implementation, so the restore leg had something true to restore to. The C4
comparison was neutered (if (implementedBy !== reviewedBy) replaced by if (true), marker appended).
Mutation confirmed ON DISK before running, not from the editor's exit code: the original anchor's
grep -cF count went 1 to 0 and the injected marker's 0 to 1. Ablated run: EXIT=1, 11 of 138 cases
failed
, including "a same-session verdict FIRES C4" and "a self-reviewed pair is adverse even when
every carrier reading is clean". Restore by git checkout HEAD -- (absolute path) under an EXIT/INT/TERM
trap, then proved rather than assumed: git diff HEAD empty, marker count back to 0, and the worktree
blob hash equal to the HEAD blob hash (2ea30125… both sides). Self-test green again at 138.

No rebuild leg applies and none is claimed: this script is plain ESM executed from source, with no dist
between the edit and the run.

Landing shape

Draft, and it stays draft — .claude/-adjacent PM tooling under the governed four-step, which the
dispatching seat runs after this report. No auto-merge, no ready flip from here. skip-changeset applies
and is set: the diff is confined to scripts/pm/**, which publishes from no package.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-support-ai@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(pm): give the contract-review independence clause a machine carrier (C4) - #14216

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier
Sep 2, 2026
Merged

feat(pm): give the contract-review independence clause a machine carrier (C4)#14216
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #14209 — direction A's guard half. #14209 stays open: its template half is deferred on a
governance blocker named under "What is NOT in this PR", and merging this alone must not close the card.

Ruling being implemented (maintainer, 2026-09-01, verbatim and untranslated): 「同意 A」 — the
contract-review verdict template carries an Implemented-by: / Reviewed-by: session-ID pair, and the
guard refuses to recognise a verdict whose two IDs are the same session.

What changed

One file: scripts/pm/check-clause2-carriers.mjs, one new finding row C4, report-only like every
other row. No existing row is weakened or reordered, no label is ever written (the file's standing
NEVER_WRITES rule), and no sibling script is touched.

C4 reports a pair whose governing contract-review verdict names the SAME session on both authorship
lines — a self-review, which does not count as an independent review. The clause it finally carries is
references/contract-review.md's own: the in-seat path is scoped to 「低档实现者的契约增量,非自身产物」,
and its isolation sub-rule will not feed a reviewer even 「派发席自己的结论(污染即失独立性)」.

Four states, exactly as the card's scope sets them:

verdict on the card threadC4
both lines, same session IDfires — self-review
both lines, distinct session IDssilent — this is the shape the clause asks for
neither line (a legacy verdict)silent — absence never turns a historic pair red
one line onlyfires as its own MALFORMED state — half a pair compares to nothing

The four design choices worth reviewing

  1. The discriminator is a VERDICT: key line, picked from the live corpus rather than invented: real
    verdicts open a fenced block whose first line is VERDICT: PASS, beside REVIEWED-HEAD: and
    CLAUSE-2-PATH:. The same board supplies the near miss that makes the colon load-bearing — an os-dev
    report writes `VERDICT command-exit 0` in prose, repeatedly. Both are pinned as self-test
    fixtures, so a discriminator that matched the bare WORD would read a build log as a review verdict.
  2. Spelling strictness mirrors the Clause-②: reader one section up: case-sensitive key, the session
    token immediately after the colon, trailing reasoning tolerated, the same markdown decoration allowed.
    One convention for machine spellings in this file, not two. Its residual hole is stated in the row
    rather than hidden: both IDs are SELF-DECLARED, and this file compares them to each other without
    cross-checking either against the implementation claim — it catches the honest self-review.
  3. The NEWEST verdict carrying the pair governs. Load-bearing, not tidy: a self-review followed by an
    independent re-review is precisely the remedy the row asks for, so judging every verdict ever posted
    would leave a remediated pair red on every later sweep — the defect [finding] check-clause2-carriers.mjs --pair answers C3 / exit 4 on a LEGITIMATELY cleared clause-② pair — the completed state (declaration outlives the label) is indistinguishable from the fail-open it hunts #14155 had to repair in C3, where
    a row that could never clear made the landing check's own precondition unsatisfiable.
  4. It costs no new request. C4 reads the card comment thread the declaration limb already fetches.

The file header's boundary sentence was narrowed to match, not quietly broken: it read "it does not read
verdict comments"; it now reads "it reads no verdict VALUE", with a starred paragraph saying that the
authorship pair is the one thing read out of a verdict and that no PASS or FAIL token is read to reach
it. The PASS half of the recovery rule stays human, exactly as before.

What is NOT in this PR, and why — please read before reviewing scope

The dispatched surface was two files. The second, .claude/skills/pm-dispatch/references/contract-review.md
(the template lines plus one sentence about the guard), is not here, and could not be added inside the
dispatched surface.
Measured, not assumed:

  • check-skill-line-ratchet.mjs pins that file at 60 lines, and it is 60 lines — the gate's own
    verdict line is contract-review.md is 60 lines (ceiling 60; headroom 0). Any net growth is red.
  • Both in-place payments are refused by standing rulings, so the growth cannot be self-funded. Re-wrap or
    densify to buy lines is 筹行, banned by the maintainer's 2026-08-17 ruling as recorded in SKILL.md:
    「⛔ re-wrap(折行合并)不得用作筹行 …… 新增以删减付账;密度优化仅随净减内容的 PR 顺带」. Deleting a
    ruled clause is refused on the state-machine precedent, recorded twice in this very file's own ceiling
    comments.
  • The remaining route is the one this file's ceiling took on both prior occasions (51 to 57, then 57 to
    60): raise the ceiling, with the maintainer ruling quoted in the raising PR body — which means
    editing scripts/pm/check-skill-line-ratchet.mjs, a third file the dispatch did not authorize and
    explicitly said to stop on rather than improvise.

⚠️ It is also the wrong shape to improvise here specifically: granting my own diff an exemption from a
governance control, unilaterally, is the same act #14209 exists to record. So the guard ships and the
template waits for an authorization only the dispatching seat or the maintainer can give.

Consequence if this merges alone: none adverse. A verdict carrying neither line is silent by mandate,
so C4 simply does not fire until seats start writing the pair — the row is forward-compatible and inert
on today's board. The template half is what turns it on.

To finish the card on this branch: authorize the ceiling raise (60 to about 66), add the template
lines plus the guard sentence to the review-checklist section, record the raise above the CEILINGS entry
in the established comment form, and flip this PR's first line to the closing keyword.

Gates run

All readings at the pushed head 57f23063f (the final commit), every exit captured by
redirect-then-capture, never across a pipe.

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack EXIT=0, repo assertion held,
    1 path vs merge base b992b1d64, three-dot, 199 families discovered, 13 matched plus 2
    convention-triggered (adds or edits a GATE SCRIPT).
  • All 15 run. 14 EXIT=0: check:pm-clause2-carriers, check:pm-dispatch-gates,
    bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
    check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard,
    check:pnpm-filter-targets, check:watch-hint-literal, check-cross-package-test-inputs.mjs,
    check-ci-filter-parity.mjs, check-shard-attestation.mjs.
  • 1 NOT MEASURED, not a red: check-test-completeness.mjs EXIT=3, its own text — "The log comes from
    a test RUN. This gate does not run tests and cannot produce one … the local reading for this gate is
    NOT MEASURED." CI covers it.
  • ⚠️check-ci-filter-parity.mjs and check-shard-attestation.mjs first returned EXIT=3 PREREQUISITE
    NOT MET ("the dependency yaml is not installed") because the worktree had no node_modules yet;
    both were re-run after pnpm install and are the EXIT=0 readings above. Recorded because a 3 read as a
    pass would have been the false green.
  • Repo-wide, NOT narrowed: eslint . --no-inline-config --format json EXIT=0 — 5,644 files, 0 errors,
    0 warnings
    , with the edited file confirmed present in the linted set by its own JSON row.
  • check-nul-bytes.mjs EXIT=0 (7,766 files). Control-character self-scan over the edited file with
    grep -naP returned rc=1, no matches.
  • check-skill-line-ratchet.mjs EXIT=0 — unchanged, since no ceilinged file is touched.
  • Self-test: 138 cases pass, up from 98 on the base commit — 40 new, of which 30 are C4's.

Ablation — the new cases can actually fail

Run from the committed implementation, so the restore leg had something true to restore to. The C4
comparison was neutered (if (implementedBy !== reviewedBy) replaced by if (true), marker appended).
Mutation confirmed ON DISK before running, not from the editor's exit code: the original anchor's
grep -cF count went 1 to 0 and the injected marker's 0 to 1. Ablated run: EXIT=1, 11 of 138 cases
failed
, including "a same-session verdict FIRES C4" and "a self-reviewed pair is adverse even when
every carrier reading is clean". Restore by git checkout HEAD -- (absolute path) under an EXIT/INT/TERM
trap, then proved rather than assumed: git diff HEAD empty, marker count back to 0, and the worktree
blob hash equal to the HEAD blob hash (2ea30125… both sides). Self-test green again at 138.

No rebuild leg applies and none is claimed: this script is plain ESM executed from source, with no dist
between the edit and the run.

Landing shape

Draft, and it stays draft — .claude/-adjacent PM tooling under the governed four-step, which the
dispatching seat runs after this report. No auto-merge, no ready flip from here. skip-changeset applies
and is set: the diff is confined to scripts/pm/**, which publishes from no package.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-support-ai@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(pm): give the contract-review independence clause a machine carrier (C4) - #14216

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier
Sep 2, 2026
Merged

feat(pm): give the contract-review independence clause a machine carrier (C4)#14216
os-zhuang merged 1 commit into
mainfrom
claude/issue-14209-review-independence-carrier

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Part of #14209 — direction A's guard half. #14209 stays open: its template half is deferred on a
governance blocker named under "What is NOT in this PR", and merging this alone must not close the card.

Ruling being implemented (maintainer, 2026-09-01, verbatim and untranslated): 「同意 A」 — the
contract-review verdict template carries an Implemented-by: / Reviewed-by: session-ID pair, and the
guard refuses to recognise a verdict whose two IDs are the same session.

What changed

One file: scripts/pm/check-clause2-carriers.mjs, one new finding row C4, report-only like every
other row. No existing row is weakened or reordered, no label is ever written (the file's standing
NEVER_WRITES rule), and no sibling script is touched.

C4 reports a pair whose governing contract-review verdict names the SAME session on both authorship
lines — a self-review, which does not count as an independent review. The clause it finally carries is
references/contract-review.md's own: the in-seat path is scoped to 「低档实现者的契约增量,非自身产物」,
and its isolation sub-rule will not feed a reviewer even 「派发席自己的结论(污染即失独立性)」.

Four states, exactly as the card's scope sets them:

verdict on the card threadC4
both lines, same session IDfires — self-review
both lines, distinct session IDssilent — this is the shape the clause asks for
neither line (a legacy verdict)silent — absence never turns a historic pair red
one line onlyfires as its own MALFORMED state — half a pair compares to nothing

The four design choices worth reviewing

  1. The discriminator is a VERDICT: key line, picked from the live corpus rather than invented: real
    verdicts open a fenced block whose first line is VERDICT: PASS, beside REVIEWED-HEAD: and
    CLAUSE-2-PATH:. The same board supplies the near miss that makes the colon load-bearing — an os-dev
    report writes `VERDICT command-exit 0` in prose, repeatedly. Both are pinned as self-test
    fixtures, so a discriminator that matched the bare WORD would read a build log as a review verdict.
  2. Spelling strictness mirrors the Clause-②: reader one section up: case-sensitive key, the session
    token immediately after the colon, trailing reasoning tolerated, the same markdown decoration allowed.
    One convention for machine spellings in this file, not two. Its residual hole is stated in the row
    rather than hidden: both IDs are SELF-DECLARED, and this file compares them to each other without
    cross-checking either against the implementation claim — it catches the honest self-review.
  3. The NEWEST verdict carrying the pair governs. Load-bearing, not tidy: a self-review followed by an
    independent re-review is precisely the remedy the row asks for, so judging every verdict ever posted
    would leave a remediated pair red on every later sweep — the defect [finding] check-clause2-carriers.mjs --pair answers C3 / exit 4 on a LEGITIMATELY cleared clause-② pair — the completed state (declaration outlives the label) is indistinguishable from the fail-open it hunts #14155 had to repair in C3, where
    a row that could never clear made the landing check's own precondition unsatisfiable.
  4. It costs no new request. C4 reads the card comment thread the declaration limb already fetches.

The file header's boundary sentence was narrowed to match, not quietly broken: it read "it does not read
verdict comments"; it now reads "it reads no verdict VALUE", with a starred paragraph saying that the
authorship pair is the one thing read out of a verdict and that no PASS or FAIL token is read to reach
it. The PASS half of the recovery rule stays human, exactly as before.

What is NOT in this PR, and why — please read before reviewing scope

The dispatched surface was two files. The second, .claude/skills/pm-dispatch/references/contract-review.md
(the template lines plus one sentence about the guard), is not here, and could not be added inside the
dispatched surface.
Measured, not assumed:

  • check-skill-line-ratchet.mjs pins that file at 60 lines, and it is 60 lines — the gate's own
    verdict line is contract-review.md is 60 lines (ceiling 60; headroom 0). Any net growth is red.
  • Both in-place payments are refused by standing rulings, so the growth cannot be self-funded. Re-wrap or
    densify to buy lines is 筹行, banned by the maintainer's 2026-08-17 ruling as recorded in SKILL.md:
    「⛔ re-wrap(折行合并)不得用作筹行 …… 新增以删减付账;密度优化仅随净减内容的 PR 顺带」. Deleting a
    ruled clause is refused on the state-machine precedent, recorded twice in this very file's own ceiling
    comments.
  • The remaining route is the one this file's ceiling took on both prior occasions (51 to 57, then 57 to
    60): raise the ceiling, with the maintainer ruling quoted in the raising PR body — which means
    editing scripts/pm/check-skill-line-ratchet.mjs, a third file the dispatch did not authorize and
    explicitly said to stop on rather than improvise.

⚠️ It is also the wrong shape to improvise here specifically: granting my own diff an exemption from a
governance control, unilaterally, is the same act #14209 exists to record. So the guard ships and the
template waits for an authorization only the dispatching seat or the maintainer can give.

Consequence if this merges alone: none adverse. A verdict carrying neither line is silent by mandate,
so C4 simply does not fire until seats start writing the pair — the row is forward-compatible and inert
on today's board. The template half is what turns it on.

To finish the card on this branch: authorize the ceiling raise (60 to about 66), add the template
lines plus the guard sentence to the review-checklist section, record the raise above the CEILINGS entry
in the established comment form, and flip this PR's first line to the closing keyword.

Gates run

All readings at the pushed head 57f23063f (the final commit), every exit captured by
redirect-then-capture, never across a pipe.

  • node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack EXIT=0, repo assertion held,
    1 path vs merge base b992b1d64, three-dot, 199 families discovered, 13 matched plus 2
    convention-triggered (adds or edits a GATE SCRIPT).
  • All 15 run. 14 EXIT=0: check:pm-clause2-carriers, check:pm-dispatch-gates,
    bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
    check:cli-command-ids, check:cross-package-test-inputs, check:entry-guard, check:parse-guard,
    check:pnpm-filter-targets, check:watch-hint-literal, check-cross-package-test-inputs.mjs,
    check-ci-filter-parity.mjs, check-shard-attestation.mjs.
  • 1 NOT MEASURED, not a red: check-test-completeness.mjs EXIT=3, its own text — "The log comes from
    a test RUN. This gate does not run tests and cannot produce one … the local reading for this gate is
    NOT MEASURED." CI covers it.
  • ⚠️check-ci-filter-parity.mjs and check-shard-attestation.mjs first returned EXIT=3 PREREQUISITE
    NOT MET ("the dependency yaml is not installed") because the worktree had no node_modules yet;
    both were re-run after pnpm install and are the EXIT=0 readings above. Recorded because a 3 read as a
    pass would have been the false green.
  • Repo-wide, NOT narrowed: eslint . --no-inline-config --format json EXIT=0 — 5,644 files, 0 errors,
    0 warnings
    , with the edited file confirmed present in the linted set by its own JSON row.
  • check-nul-bytes.mjs EXIT=0 (7,766 files). Control-character self-scan over the edited file with
    grep -naP returned rc=1, no matches.
  • check-skill-line-ratchet.mjs EXIT=0 — unchanged, since no ceilinged file is touched.
  • Self-test: 138 cases pass, up from 98 on the base commit — 40 new, of which 30 are C4's.

Ablation — the new cases can actually fail

Run from the committed implementation, so the restore leg had something true to restore to. The C4
comparison was neutered (if (implementedBy !== reviewedBy) replaced by if (true), marker appended).
Mutation confirmed ON DISK before running, not from the editor's exit code: the original anchor's
grep -cF count went 1 to 0 and the injected marker's 0 to 1. Ablated run: EXIT=1, 11 of 138 cases
failed
, including "a same-session verdict FIRES C4" and "a self-reviewed pair is adverse even when
every carrier reading is clean". Restore by git checkout HEAD -- (absolute path) under an EXIT/INT/TERM
trap, then proved rather than assumed: git diff HEAD empty, marker count back to 0, and the worktree
blob hash equal to the HEAD blob hash (2ea30125… both sides). Self-test green again at 138.

No rebuild leg applies and none is claimed: this script is plain ESM executed from source, with no dist
between the edit and the run.

Landing shape

Draft, and it stays draft — .claude/-adjacent PM tooling under the governed four-step, which the
dispatching seat runs after this report. No auto-merge, no ready flip from here. skip-changeset applies
and is set: the diff is confined to scripts/pm/**, which publishes from no package.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-support-ai@os-zhuang@claude