feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919) - #14413

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls
Sep 2, 2026
Merged

feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919)#14413
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13919

The #12981 census (scripts/measure-durability-swallow-family.mjs) declares four
control families and, measured on origin/main, nothing ran any of them — zero
references to the script anywhere in package.json or .github/**, counter-checked
against a control that must return non-zero (measure-stall-guard-headroom, 2 hits) so
the zero was a reading and not a broken query. Meanwhile the resolver those controls pin
was repaired three times (#13459, #13474, PR #13915), each time with no gate holding the
previous repair, and the census's numbers feed #12981's repair worklist — so a wrong
denominator propagates into that programme with nobody watching.

The ruling this implements (verbatim, unchanged — comment 5494601066, maintainer 2026-09-01 「同意」)

  1. B:measure-durability-swallow-family.mjs 增一个轻量 flag,把 RESOLUTION_CONTROLS + NEGATIVE_CONTROLS + REGRESSION_CONTROLS 三族(修复计划不可能消灭的那三族)接为 check:* 进 CI —— 先例 check:stall-guard-headroom(package.json:150)同形;
  2. 拆分单入口形状的授权:The durability log-level gate cannot see the catch { return null; } seeder family — 15 files outside #12923's five, and neither widening path is cheap #12981 裁定认可的单入口仪器形状由本裁决显式修订为「单入口 + 分族 flag」—— 仪器的测量属性不变,每次运行照印 "a MEASUREMENT, not a gate";
  3. 三条边界(⛔ 均为硬边):
  4. C(维持不接线)排除 —— 现状就是本卡的成因,三次无守护修复已实测。

What landed

One mode selector, no duplicated reporting.selfTestMode(argv) reads the mode;
selfTest(mode) takes one gated ? [] : POSITIVE_CONTROLS on the loop it must skip, one
extra success-print branch, and one refusal branch. The problem list, the failure
formatter, the census call and the other three family loops are the same code on both
paths. Implementation cost against ruling item 3, bullet 3: the stop condition was not
reached
— the split needed no duplication of the self-test's reporting logic.

  • --self-test=gated runs RESOLUTION + NEGATIVE + REGRESSION, plus the
    zero-member floor. Wired as root check:swallow-census-controls and run from
    lint.yml beside the sanctioned precedent check:stall-guard-headroom — the same
    shape and the same asymmetry: the self-test leg only, never a bare invocation.
  • Bare --self-test is byte-identical (proof below); --self-test=all is its
    spelling. Print semantics of the bare legs are deliberately untouched — that surface
    belongs to [finding] the #12981 census prints 5 DARK sites as "the repair worklist" when 4 are settled determinations — an annotation cannot move a site out of the bucket #13886, see the serial note.
  • An unknown mode is REFUSED with exit 2 rather than falling through. Without this,
    --self-test=gatd would miss argv.includes('--self-test'), reach report(), exit 0
    and read in a CI log exactly like a self-test that passed.
  • Ruling item 2, the measurement property: the gated run prints the instrument's own
    banner line, now a single constant shared with report() rather than a second copy.

Why POSITIVE stays out, in the file's own terms rather than restated: SELF_TEST_MODES
points at the dark control's recorded why, where batch 2 already turned this
self-test red for doing exactly what the ruling asked. The exclusion is written as
permanent, not pending — repairs move a member from tier dark to tier channelled
and it stays a member, so none of the three wired families can be destroyed by a
successful repair.

DURABILITY_CRITICAL_CALLEES is untouched, no entry was added to
durability-degradation.baseline.json, and the gate vocabulary is unchanged in either
direction (ruling item 3, bullet 2 — this PR must not be used to bring that step forward).

Readings

All on 93aecd5cf (the implementation commit; the two follow-ups touch only PM tooling). Every mutation confirmed on disk before the reading was taken
(injected marker counted and deleted text counted), every restore proved by hashing
the path against its HEAD blob, each harness carrying trap restore EXIT INT TERM with
absolute paths.

runexitverdict line
--self-test=gated on this branch03 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 56 member site(s) total
bare --self-test04 positive, 3 negative, 2 regression, 6 resolution — the base branch's line, byte for byte
--self-test=gatd2x REFUSED: unknown self-test mode

Bare-output identity, measured not asserted. The base blob (e2a7fa5b8) was checked
out over the path, confirmed on disk by hash, run, and restored to the HEAD blob
(71f3ae1e5, verified). cmp on the two captures: identical.

Ablation A — the RESOLUTION family, on the defect it exists for. Reverted
indexFunctionBodies().get to the flat last-wins lookup (marker present 1, anchor
consumed). --self-test=gatedexit 1, four resolution controls firing:

 - resolution control moved: packages/objectql/src/engine.ts :: ObjectQL :: update()
-> expected `ObjectQL`, got ObjectRepository@7620, ObjectRepository@7722, ...
- resolution control moved: ... :: delete() -> got ObjectRepository@12213
- resolution control moved: ... :: transaction() -> got ScopedContext@12677
- resolution control moved: packages/runtime/src/app-plugin.ts :: resolveMappedObjects
:: push() -> expected REFUSAL, got collectBundleActions@457

Bare --self-test → exit 1 on the same tree. ⇒ the wired leg carries a real failure
signal into CI.

Ablation C — the hazard the ruling excluded POSITIVE for, reproduced. Simulated a
successful repair of the dark positive control's site by giving
share-link-service.ts :: resolveToken's telemetry catch a console.error (marker
present 1, original comment text consumed):

runexit
bare --self-test1positive control found NO member: packages/plugins/plugin-sharing/src/share-link-service.ts
--self-test=gated056 members becomes 55, and the gate stays green

⇒ this is the ruling's boundary 1 as a measurement: the full self-test reddens when the
repair programme succeeds
, and the wired subset does not.

Ablation B — reported as a NULL result rather than dropped. Removing the #13459
bare-identifier refusal from the lexical walk landed on disk — marker 1, the deleted
return null; gone — and moved nothing: --json before and after is equal in every
stat (files 2193, guardedWrites 221, refusedShadowed 4, 56 members, empty symmetric
difference on the member set). The site the action-execution regression control pins is
answered a second time by the scope-aware body index, which refuses it too. So the two
departures are defence-in-depth there, and this ablation proves nothing about the
REGRESSION family in either direction. It is recorded because a discarded null ablation is
how a "we exercised that family" claim gets minted from a reading that never happened;
Ablation A is the failure proof.

Two things the wiring forced, both found by running the derived gates

Neither is scope creep: both are consequences of this card's own change, each caught by a
gate on this PR's derived list, and each landed with the repair the gate's own remedy text
names rather than the one that quiets it.

1. scripts/pm/dispatch-gates.mjs — the seam card is now a GATE SCRIPT. Its
--self-test went red in three cases. Wiring check:swallow-census-controls makes
measure-durability-swallow-family.mjs a file some discovered check family runs, so the
"adds or edits a GATE SCRIPT" convention KIND started hitting it — and that card is the
fixture chosen for the one assertion pair that needs the block harvest and --commands to
agree exactly, i.e. a card no convention KIND hits. Repointed at
measure-partial-retirement-annotation.mjs (block 13, commands 13, convention 0, four
node rows — measured), which is the very shape the census copied and which no check
family runs. ⛔ Not repaired by loosening the equality; the comment says so at the
constant. The third case is COMPOUND_ANCHOR_LEDGER: the new selfTestMode argv parser
matches the compound self-test name anchor and is classified accidental: true, which is
what that ledger's own "Maintaining this table" section prescribes — ⛔ explicitly not by
renaming the function to dodge the anchor.

2. scripts/pm/bare-root-worklist.mjs — a FRESH bare-root row. Wiring the family
makes the census's SCAN_ROOT visible to scripts/pm/bare-root-worklist.mjs
as a FRESH, unjudged row, and its --self-test reds until a verdict is recorded (it did,
on the first sweep). Recorded REFUSE-WIDE, measured on this tree in both terms and not
carried from a sibling row: the walk admits every non-test, non-declaration TypeScript
source under the root at four extensions — 2193 of 5755 (38%), numerator from the
instrument's own printed scan count, denominator from git ls-files packages. Same class
and nearly the same ratio as the check:authz-resolver row: a bare-root declaration would
be TRUE and is refused for width alone.

No changeset — skip-changeset

This diff publishes nothing from any package: a root check:* alias, a lint.yml step, a
repo-root measure-* script, and a PM worklist verdict. The precedent is exact —
0079e2585 (#13358), which wired this same family's precedent and touched precisely
.github/workflows/lint.yml + package.json + scripts/measure-stall-guard-headroom.mjs,
carried no changeset. An empty-frontmatter changeset is not the alternative:
scripts/check-empty-changeset.mjs rejects one, and its header records why (an empty
changeset is a real input to changesets/action and can stall a release, which the label
cannot). The label is applied on this PR.

Serial note — #13886 is next on this file

#13886 (same file, print semantics of the DARK worklist) is queued behind this card
(triage 2026-09-01, comment 5486764050) and is deliberately not folded in. That is also
why the bare self-test legs' output is left byte-identical here: changing print semantics
is that card's surface, not this one's. #13886 is not addressed by this PR and remains
open.

Gate record

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
from the real change set (three-dot against merge base e80889095; the tool takes the
change set from git itself, no hand-written path list). Re-derived after each of the two
follow-up commits — the union stayed at 37 families throughout. All 37 were run, and
the union was re-run on the final commit 990649a77:

  • 34 green, including the new check:swallow-census-controls itself,
    check:pm-dispatch-gates (✓ dispatch-gates self-test: 1232 cases pass.),
    check:self-test-wired and check:self-test-workflow-commands — the two the new step
    newly puts this script into the population of — plus
    check:declared-population-live, check:ratchet-remedy-authority,
    check:watch-hint-literal, check:entry-guard, check:parse-guard and
    node scripts/pm/bare-root-worklist.mjs --self-test (OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale, none missing, none contradicted.).
  • 3 NOT MEASURED, all exit 3 and none of them a finding, each quoting its own verdict
    line: check-test-completeness.mjs ("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"),
    check:dual-build-cjs-loads and check:type-check-debt ("PREREQUISITE NOT MET... ⛔
    This is NOT a pass and NOT a finding: nothing was measured"). Structural — they need a
    built workspace or a real test-run log, which CI has and a local sweep does not.
  • 2 were red, both on this card's own consequences, both repaired above:
    scripts/pm/bare-root-worklist.mjs --self-test (FRESH row) and
    check:pm-dispatch-gates (3 of 1232 cases). Both green on the final commit.

Exit codes were captured before any pipe (cmd > log 2>&1; rc=$?), never through one, and
every verdict quoted here is the gate's own printed line rather than a bare $?.


Generated by Claude Code

…me cannot destroy (#13919)
`scripts/measure-durability-swallow-family.mjs` declares four control families
and, measured on `origin/main`, nothing ran any of them: zero references to the
script in `package.json` or `.github/**`, counter-checked against
`measure-stall-guard-headroom` (2 hits) so the zero was a reading and not a
broken query. Meanwhile the resolver those controls pin was repaired three
times with no gate holding any previous repair, and the census's numbers feed
the #12981 repair worklist, so a wrong denominator propagates unwatched.
Adds one lightweight mode selector, `--self-test=gated`, wired as
`check:swallow-census-controls` from `lint.yml` beside the sanctioned precedent
`check:stall-guard-headroom`. The gated run asserts RESOLUTION + NEGATIVE +
REGRESSION plus the zero-member floor -- the families a successful repair
cannot destroy, because a repair moves a member from tier `dark` to tier
`channelled` and it stays a member.
POSITIVE_CONTROLS stays manual, permanently. It pins tier-1 DARK members of the
worklist the repair programme exists to remove; the file's own record shows
batch 2 already turning this self-test red for doing exactly what the ruling
asked. A gate that reddens on success is not a gate.
Bare `--self-test` is byte-identical (`--self-test=all` is its spelling), and an
unknown mode is REFUSED with exit 2 rather than falling through to the census,
which would exit 0 and read in a CI log like a self-test that passed.
…13919)
Wiring `check:swallow-census-controls` makes the census's SCAN_ROOT visible to
the bare-root sweep as a FRESH, unjudged row. REFUSE-WIDE, measured on this
tree: the walk admits every non-test TypeScript source under `packages` (2193
of 5755, 38%), the same class and nearly the same ratio as check:authz-resolver,
so a bare-root declaration would be TRUE and is refused for width alone.
…onest (#13919)
Wiring `check:swallow-census-controls` turns
`measure-durability-swallow-family.mjs` into a GATE SCRIPT, so the
convention KIND now hits it and it can no longer serve as the card where the
block harvest and `--commands` must agree exactly. Repointed at
`measure-partial-retirement-annotation.mjs` — the shape the census copied,
which no check family runs. Also classifies the new `selfTestMode` argv
parser in COMPOUND_ANCHOR_LEDGER as accidental, rather than renaming it to
dodge the anchor.
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/m ci/cd dependencies Pull requests that update a dependency file labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:34
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 793065dSep 2, 2026
39 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13919-swallow-census-gated-controls branch September 2, 2026 05:58
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@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(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919) - #14413

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls
Sep 2, 2026
Merged

feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919)#14413
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13919

The #12981 census (scripts/measure-durability-swallow-family.mjs) declares four
control families and, measured on origin/main, nothing ran any of them — zero
references to the script anywhere in package.json or .github/**, counter-checked
against a control that must return non-zero (measure-stall-guard-headroom, 2 hits) so
the zero was a reading and not a broken query. Meanwhile the resolver those controls pin
was repaired three times (#13459, #13474, PR #13915), each time with no gate holding the
previous repair, and the census's numbers feed #12981's repair worklist — so a wrong
denominator propagates into that programme with nobody watching.

The ruling this implements (verbatim, unchanged — comment 5494601066, maintainer 2026-09-01 「同意」)

  1. B:measure-durability-swallow-family.mjs 增一个轻量 flag,把 RESOLUTION_CONTROLS + NEGATIVE_CONTROLS + REGRESSION_CONTROLS 三族(修复计划不可能消灭的那三族)接为 check:* 进 CI —— 先例 check:stall-guard-headroom(package.json:150)同形;
  2. 拆分单入口形状的授权:The durability log-level gate cannot see the catch { return null; } seeder family — 15 files outside #12923's five, and neither widening path is cheap #12981 裁定认可的单入口仪器形状由本裁决显式修订为「单入口 + 分族 flag」—— 仪器的测量属性不变,每次运行照印 "a MEASUREMENT, not a gate";
  3. 三条边界(⛔ 均为硬边):
  4. C(维持不接线)排除 —— 现状就是本卡的成因,三次无守护修复已实测。

What landed

One mode selector, no duplicated reporting.selfTestMode(argv) reads the mode;
selfTest(mode) takes one gated ? [] : POSITIVE_CONTROLS on the loop it must skip, one
extra success-print branch, and one refusal branch. The problem list, the failure
formatter, the census call and the other three family loops are the same code on both
paths. Implementation cost against ruling item 3, bullet 3: the stop condition was not
reached
— the split needed no duplication of the self-test's reporting logic.

  • --self-test=gated runs RESOLUTION + NEGATIVE + REGRESSION, plus the
    zero-member floor. Wired as root check:swallow-census-controls and run from
    lint.yml beside the sanctioned precedent check:stall-guard-headroom — the same
    shape and the same asymmetry: the self-test leg only, never a bare invocation.
  • Bare --self-test is byte-identical (proof below); --self-test=all is its
    spelling. Print semantics of the bare legs are deliberately untouched — that surface
    belongs to [finding] the #12981 census prints 5 DARK sites as "the repair worklist" when 4 are settled determinations — an annotation cannot move a site out of the bucket #13886, see the serial note.
  • An unknown mode is REFUSED with exit 2 rather than falling through. Without this,
    --self-test=gatd would miss argv.includes('--self-test'), reach report(), exit 0
    and read in a CI log exactly like a self-test that passed.
  • Ruling item 2, the measurement property: the gated run prints the instrument's own
    banner line, now a single constant shared with report() rather than a second copy.

Why POSITIVE stays out, in the file's own terms rather than restated: SELF_TEST_MODES
points at the dark control's recorded why, where batch 2 already turned this
self-test red for doing exactly what the ruling asked. The exclusion is written as
permanent, not pending — repairs move a member from tier dark to tier channelled
and it stays a member, so none of the three wired families can be destroyed by a
successful repair.

DURABILITY_CRITICAL_CALLEES is untouched, no entry was added to
durability-degradation.baseline.json, and the gate vocabulary is unchanged in either
direction (ruling item 3, bullet 2 — this PR must not be used to bring that step forward).

Readings

All on 93aecd5cf (the implementation commit; the two follow-ups touch only PM tooling). Every mutation confirmed on disk before the reading was taken
(injected marker counted and deleted text counted), every restore proved by hashing
the path against its HEAD blob, each harness carrying trap restore EXIT INT TERM with
absolute paths.

runexitverdict line
--self-test=gated on this branch03 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 56 member site(s) total
bare --self-test04 positive, 3 negative, 2 regression, 6 resolution — the base branch's line, byte for byte
--self-test=gatd2x REFUSED: unknown self-test mode

Bare-output identity, measured not asserted. The base blob (e2a7fa5b8) was checked
out over the path, confirmed on disk by hash, run, and restored to the HEAD blob
(71f3ae1e5, verified). cmp on the two captures: identical.

Ablation A — the RESOLUTION family, on the defect it exists for. Reverted
indexFunctionBodies().get to the flat last-wins lookup (marker present 1, anchor
consumed). --self-test=gatedexit 1, four resolution controls firing:

 - resolution control moved: packages/objectql/src/engine.ts :: ObjectQL :: update()
-> expected `ObjectQL`, got ObjectRepository@7620, ObjectRepository@7722, ...
- resolution control moved: ... :: delete() -> got ObjectRepository@12213
- resolution control moved: ... :: transaction() -> got ScopedContext@12677
- resolution control moved: packages/runtime/src/app-plugin.ts :: resolveMappedObjects
:: push() -> expected REFUSAL, got collectBundleActions@457

Bare --self-test → exit 1 on the same tree. ⇒ the wired leg carries a real failure
signal into CI.

Ablation C — the hazard the ruling excluded POSITIVE for, reproduced. Simulated a
successful repair of the dark positive control's site by giving
share-link-service.ts :: resolveToken's telemetry catch a console.error (marker
present 1, original comment text consumed):

runexit
bare --self-test1positive control found NO member: packages/plugins/plugin-sharing/src/share-link-service.ts
--self-test=gated056 members becomes 55, and the gate stays green

⇒ this is the ruling's boundary 1 as a measurement: the full self-test reddens when the
repair programme succeeds
, and the wired subset does not.

Ablation B — reported as a NULL result rather than dropped. Removing the #13459
bare-identifier refusal from the lexical walk landed on disk — marker 1, the deleted
return null; gone — and moved nothing: --json before and after is equal in every
stat (files 2193, guardedWrites 221, refusedShadowed 4, 56 members, empty symmetric
difference on the member set). The site the action-execution regression control pins is
answered a second time by the scope-aware body index, which refuses it too. So the two
departures are defence-in-depth there, and this ablation proves nothing about the
REGRESSION family in either direction. It is recorded because a discarded null ablation is
how a "we exercised that family" claim gets minted from a reading that never happened;
Ablation A is the failure proof.

Two things the wiring forced, both found by running the derived gates

Neither is scope creep: both are consequences of this card's own change, each caught by a
gate on this PR's derived list, and each landed with the repair the gate's own remedy text
names rather than the one that quiets it.

1. scripts/pm/dispatch-gates.mjs — the seam card is now a GATE SCRIPT. Its
--self-test went red in three cases. Wiring check:swallow-census-controls makes
measure-durability-swallow-family.mjs a file some discovered check family runs, so the
"adds or edits a GATE SCRIPT" convention KIND started hitting it — and that card is the
fixture chosen for the one assertion pair that needs the block harvest and --commands to
agree exactly, i.e. a card no convention KIND hits. Repointed at
measure-partial-retirement-annotation.mjs (block 13, commands 13, convention 0, four
node rows — measured), which is the very shape the census copied and which no check
family runs. ⛔ Not repaired by loosening the equality; the comment says so at the
constant. The third case is COMPOUND_ANCHOR_LEDGER: the new selfTestMode argv parser
matches the compound self-test name anchor and is classified accidental: true, which is
what that ledger's own "Maintaining this table" section prescribes — ⛔ explicitly not by
renaming the function to dodge the anchor.

2. scripts/pm/bare-root-worklist.mjs — a FRESH bare-root row. Wiring the family
makes the census's SCAN_ROOT visible to scripts/pm/bare-root-worklist.mjs
as a FRESH, unjudged row, and its --self-test reds until a verdict is recorded (it did,
on the first sweep). Recorded REFUSE-WIDE, measured on this tree in both terms and not
carried from a sibling row: the walk admits every non-test, non-declaration TypeScript
source under the root at four extensions — 2193 of 5755 (38%), numerator from the
instrument's own printed scan count, denominator from git ls-files packages. Same class
and nearly the same ratio as the check:authz-resolver row: a bare-root declaration would
be TRUE and is refused for width alone.

No changeset — skip-changeset

This diff publishes nothing from any package: a root check:* alias, a lint.yml step, a
repo-root measure-* script, and a PM worklist verdict. The precedent is exact —
0079e2585 (#13358), which wired this same family's precedent and touched precisely
.github/workflows/lint.yml + package.json + scripts/measure-stall-guard-headroom.mjs,
carried no changeset. An empty-frontmatter changeset is not the alternative:
scripts/check-empty-changeset.mjs rejects one, and its header records why (an empty
changeset is a real input to changesets/action and can stall a release, which the label
cannot). The label is applied on this PR.

Serial note — #13886 is next on this file

#13886 (same file, print semantics of the DARK worklist) is queued behind this card
(triage 2026-09-01, comment 5486764050) and is deliberately not folded in. That is also
why the bare self-test legs' output is left byte-identical here: changing print semantics
is that card's surface, not this one's. #13886 is not addressed by this PR and remains
open.

Gate record

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
from the real change set (three-dot against merge base e80889095; the tool takes the
change set from git itself, no hand-written path list). Re-derived after each of the two
follow-up commits — the union stayed at 37 families throughout. All 37 were run, and
the union was re-run on the final commit 990649a77:

  • 34 green, including the new check:swallow-census-controls itself,
    check:pm-dispatch-gates (✓ dispatch-gates self-test: 1232 cases pass.),
    check:self-test-wired and check:self-test-workflow-commands — the two the new step
    newly puts this script into the population of — plus
    check:declared-population-live, check:ratchet-remedy-authority,
    check:watch-hint-literal, check:entry-guard, check:parse-guard and
    node scripts/pm/bare-root-worklist.mjs --self-test (OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale, none missing, none contradicted.).
  • 3 NOT MEASURED, all exit 3 and none of them a finding, each quoting its own verdict
    line: check-test-completeness.mjs ("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"),
    check:dual-build-cjs-loads and check:type-check-debt ("PREREQUISITE NOT MET... ⛔
    This is NOT a pass and NOT a finding: nothing was measured"). Structural — they need a
    built workspace or a real test-run log, which CI has and a local sweep does not.
  • 2 were red, both on this card's own consequences, both repaired above:
    scripts/pm/bare-root-worklist.mjs --self-test (FRESH row) and
    check:pm-dispatch-gates (3 of 1232 cases). Both green on the final commit.

Exit codes were captured before any pipe (cmd > log 2>&1; rc=$?), never through one, and
every verdict quoted here is the gate's own printed line rather than a bare $?.


Generated by Claude Code

…me cannot destroy (#13919)
`scripts/measure-durability-swallow-family.mjs` declares four control families
and, measured on `origin/main`, nothing ran any of them: zero references to the
script in `package.json` or `.github/**`, counter-checked against
`measure-stall-guard-headroom` (2 hits) so the zero was a reading and not a
broken query. Meanwhile the resolver those controls pin was repaired three
times with no gate holding any previous repair, and the census's numbers feed
the #12981 repair worklist, so a wrong denominator propagates unwatched.
Adds one lightweight mode selector, `--self-test=gated`, wired as
`check:swallow-census-controls` from `lint.yml` beside the sanctioned precedent
`check:stall-guard-headroom`. The gated run asserts RESOLUTION + NEGATIVE +
REGRESSION plus the zero-member floor -- the families a successful repair
cannot destroy, because a repair moves a member from tier `dark` to tier
`channelled` and it stays a member.
POSITIVE_CONTROLS stays manual, permanently. It pins tier-1 DARK members of the
worklist the repair programme exists to remove; the file's own record shows
batch 2 already turning this self-test red for doing exactly what the ruling
asked. A gate that reddens on success is not a gate.
Bare `--self-test` is byte-identical (`--self-test=all` is its spelling), and an
unknown mode is REFUSED with exit 2 rather than falling through to the census,
which would exit 0 and read in a CI log like a self-test that passed.
…13919)
Wiring `check:swallow-census-controls` makes the census's SCAN_ROOT visible to
the bare-root sweep as a FRESH, unjudged row. REFUSE-WIDE, measured on this
tree: the walk admits every non-test TypeScript source under `packages` (2193
of 5755, 38%), the same class and nearly the same ratio as check:authz-resolver,
so a bare-root declaration would be TRUE and is refused for width alone.
…onest (#13919)
Wiring `check:swallow-census-controls` turns
`measure-durability-swallow-family.mjs` into a GATE SCRIPT, so the
convention KIND now hits it and it can no longer serve as the card where the
block harvest and `--commands` must agree exactly. Repointed at
`measure-partial-retirement-annotation.mjs` — the shape the census copied,
which no check family runs. Also classifies the new `selfTestMode` argv
parser in COMPOUND_ANCHOR_LEDGER as accidental, rather than renaming it to
dodge the anchor.
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/m ci/cd dependencies Pull requests that update a dependency file labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:34
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 793065dSep 2, 2026
39 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13919-swallow-census-gated-controls branch September 2, 2026 05:58
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@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(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919) - #14413

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls
Sep 2, 2026
Merged

feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919)#14413
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13919

The #12981 census (scripts/measure-durability-swallow-family.mjs) declares four
control families and, measured on origin/main, nothing ran any of them — zero
references to the script anywhere in package.json or .github/**, counter-checked
against a control that must return non-zero (measure-stall-guard-headroom, 2 hits) so
the zero was a reading and not a broken query. Meanwhile the resolver those controls pin
was repaired three times (#13459, #13474, PR #13915), each time with no gate holding the
previous repair, and the census's numbers feed #12981's repair worklist — so a wrong
denominator propagates into that programme with nobody watching.

The ruling this implements (verbatim, unchanged — comment 5494601066, maintainer 2026-09-01 「同意」)

  1. B:measure-durability-swallow-family.mjs 增一个轻量 flag,把 RESOLUTION_CONTROLS + NEGATIVE_CONTROLS + REGRESSION_CONTROLS 三族(修复计划不可能消灭的那三族)接为 check:* 进 CI —— 先例 check:stall-guard-headroom(package.json:150)同形;
  2. 拆分单入口形状的授权:The durability log-level gate cannot see the catch { return null; } seeder family — 15 files outside #12923's five, and neither widening path is cheap #12981 裁定认可的单入口仪器形状由本裁决显式修订为「单入口 + 分族 flag」—— 仪器的测量属性不变,每次运行照印 "a MEASUREMENT, not a gate";
  3. 三条边界(⛔ 均为硬边):
  4. C(维持不接线)排除 —— 现状就是本卡的成因,三次无守护修复已实测。

What landed

One mode selector, no duplicated reporting.selfTestMode(argv) reads the mode;
selfTest(mode) takes one gated ? [] : POSITIVE_CONTROLS on the loop it must skip, one
extra success-print branch, and one refusal branch. The problem list, the failure
formatter, the census call and the other three family loops are the same code on both
paths. Implementation cost against ruling item 3, bullet 3: the stop condition was not
reached
— the split needed no duplication of the self-test's reporting logic.

  • --self-test=gated runs RESOLUTION + NEGATIVE + REGRESSION, plus the
    zero-member floor. Wired as root check:swallow-census-controls and run from
    lint.yml beside the sanctioned precedent check:stall-guard-headroom — the same
    shape and the same asymmetry: the self-test leg only, never a bare invocation.
  • Bare --self-test is byte-identical (proof below); --self-test=all is its
    spelling. Print semantics of the bare legs are deliberately untouched — that surface
    belongs to [finding] the #12981 census prints 5 DARK sites as "the repair worklist" when 4 are settled determinations — an annotation cannot move a site out of the bucket #13886, see the serial note.
  • An unknown mode is REFUSED with exit 2 rather than falling through. Without this,
    --self-test=gatd would miss argv.includes('--self-test'), reach report(), exit 0
    and read in a CI log exactly like a self-test that passed.
  • Ruling item 2, the measurement property: the gated run prints the instrument's own
    banner line, now a single constant shared with report() rather than a second copy.

Why POSITIVE stays out, in the file's own terms rather than restated: SELF_TEST_MODES
points at the dark control's recorded why, where batch 2 already turned this
self-test red for doing exactly what the ruling asked. The exclusion is written as
permanent, not pending — repairs move a member from tier dark to tier channelled
and it stays a member, so none of the three wired families can be destroyed by a
successful repair.

DURABILITY_CRITICAL_CALLEES is untouched, no entry was added to
durability-degradation.baseline.json, and the gate vocabulary is unchanged in either
direction (ruling item 3, bullet 2 — this PR must not be used to bring that step forward).

Readings

All on 93aecd5cf (the implementation commit; the two follow-ups touch only PM tooling). Every mutation confirmed on disk before the reading was taken
(injected marker counted and deleted text counted), every restore proved by hashing
the path against its HEAD blob, each harness carrying trap restore EXIT INT TERM with
absolute paths.

runexitverdict line
--self-test=gated on this branch03 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 56 member site(s) total
bare --self-test04 positive, 3 negative, 2 regression, 6 resolution — the base branch's line, byte for byte
--self-test=gatd2x REFUSED: unknown self-test mode

Bare-output identity, measured not asserted. The base blob (e2a7fa5b8) was checked
out over the path, confirmed on disk by hash, run, and restored to the HEAD blob
(71f3ae1e5, verified). cmp on the two captures: identical.

Ablation A — the RESOLUTION family, on the defect it exists for. Reverted
indexFunctionBodies().get to the flat last-wins lookup (marker present 1, anchor
consumed). --self-test=gatedexit 1, four resolution controls firing:

 - resolution control moved: packages/objectql/src/engine.ts :: ObjectQL :: update()
-> expected `ObjectQL`, got ObjectRepository@7620, ObjectRepository@7722, ...
- resolution control moved: ... :: delete() -> got ObjectRepository@12213
- resolution control moved: ... :: transaction() -> got ScopedContext@12677
- resolution control moved: packages/runtime/src/app-plugin.ts :: resolveMappedObjects
:: push() -> expected REFUSAL, got collectBundleActions@457

Bare --self-test → exit 1 on the same tree. ⇒ the wired leg carries a real failure
signal into CI.

Ablation C — the hazard the ruling excluded POSITIVE for, reproduced. Simulated a
successful repair of the dark positive control's site by giving
share-link-service.ts :: resolveToken's telemetry catch a console.error (marker
present 1, original comment text consumed):

runexit
bare --self-test1positive control found NO member: packages/plugins/plugin-sharing/src/share-link-service.ts
--self-test=gated056 members becomes 55, and the gate stays green

⇒ this is the ruling's boundary 1 as a measurement: the full self-test reddens when the
repair programme succeeds
, and the wired subset does not.

Ablation B — reported as a NULL result rather than dropped. Removing the #13459
bare-identifier refusal from the lexical walk landed on disk — marker 1, the deleted
return null; gone — and moved nothing: --json before and after is equal in every
stat (files 2193, guardedWrites 221, refusedShadowed 4, 56 members, empty symmetric
difference on the member set). The site the action-execution regression control pins is
answered a second time by the scope-aware body index, which refuses it too. So the two
departures are defence-in-depth there, and this ablation proves nothing about the
REGRESSION family in either direction. It is recorded because a discarded null ablation is
how a "we exercised that family" claim gets minted from a reading that never happened;
Ablation A is the failure proof.

Two things the wiring forced, both found by running the derived gates

Neither is scope creep: both are consequences of this card's own change, each caught by a
gate on this PR's derived list, and each landed with the repair the gate's own remedy text
names rather than the one that quiets it.

1. scripts/pm/dispatch-gates.mjs — the seam card is now a GATE SCRIPT. Its
--self-test went red in three cases. Wiring check:swallow-census-controls makes
measure-durability-swallow-family.mjs a file some discovered check family runs, so the
"adds or edits a GATE SCRIPT" convention KIND started hitting it — and that card is the
fixture chosen for the one assertion pair that needs the block harvest and --commands to
agree exactly, i.e. a card no convention KIND hits. Repointed at
measure-partial-retirement-annotation.mjs (block 13, commands 13, convention 0, four
node rows — measured), which is the very shape the census copied and which no check
family runs. ⛔ Not repaired by loosening the equality; the comment says so at the
constant. The third case is COMPOUND_ANCHOR_LEDGER: the new selfTestMode argv parser
matches the compound self-test name anchor and is classified accidental: true, which is
what that ledger's own "Maintaining this table" section prescribes — ⛔ explicitly not by
renaming the function to dodge the anchor.

2. scripts/pm/bare-root-worklist.mjs — a FRESH bare-root row. Wiring the family
makes the census's SCAN_ROOT visible to scripts/pm/bare-root-worklist.mjs
as a FRESH, unjudged row, and its --self-test reds until a verdict is recorded (it did,
on the first sweep). Recorded REFUSE-WIDE, measured on this tree in both terms and not
carried from a sibling row: the walk admits every non-test, non-declaration TypeScript
source under the root at four extensions — 2193 of 5755 (38%), numerator from the
instrument's own printed scan count, denominator from git ls-files packages. Same class
and nearly the same ratio as the check:authz-resolver row: a bare-root declaration would
be TRUE and is refused for width alone.

No changeset — skip-changeset

This diff publishes nothing from any package: a root check:* alias, a lint.yml step, a
repo-root measure-* script, and a PM worklist verdict. The precedent is exact —
0079e2585 (#13358), which wired this same family's precedent and touched precisely
.github/workflows/lint.yml + package.json + scripts/measure-stall-guard-headroom.mjs,
carried no changeset. An empty-frontmatter changeset is not the alternative:
scripts/check-empty-changeset.mjs rejects one, and its header records why (an empty
changeset is a real input to changesets/action and can stall a release, which the label
cannot). The label is applied on this PR.

Serial note — #13886 is next on this file

#13886 (same file, print semantics of the DARK worklist) is queued behind this card
(triage 2026-09-01, comment 5486764050) and is deliberately not folded in. That is also
why the bare self-test legs' output is left byte-identical here: changing print semantics
is that card's surface, not this one's. #13886 is not addressed by this PR and remains
open.

Gate record

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
from the real change set (three-dot against merge base e80889095; the tool takes the
change set from git itself, no hand-written path list). Re-derived after each of the two
follow-up commits — the union stayed at 37 families throughout. All 37 were run, and
the union was re-run on the final commit 990649a77:

  • 34 green, including the new check:swallow-census-controls itself,
    check:pm-dispatch-gates (✓ dispatch-gates self-test: 1232 cases pass.),
    check:self-test-wired and check:self-test-workflow-commands — the two the new step
    newly puts this script into the population of — plus
    check:declared-population-live, check:ratchet-remedy-authority,
    check:watch-hint-literal, check:entry-guard, check:parse-guard and
    node scripts/pm/bare-root-worklist.mjs --self-test (OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale, none missing, none contradicted.).
  • 3 NOT MEASURED, all exit 3 and none of them a finding, each quoting its own verdict
    line: check-test-completeness.mjs ("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"),
    check:dual-build-cjs-loads and check:type-check-debt ("PREREQUISITE NOT MET... ⛔
    This is NOT a pass and NOT a finding: nothing was measured"). Structural — they need a
    built workspace or a real test-run log, which CI has and a local sweep does not.
  • 2 were red, both on this card's own consequences, both repaired above:
    scripts/pm/bare-root-worklist.mjs --self-test (FRESH row) and
    check:pm-dispatch-gates (3 of 1232 cases). Both green on the final commit.

Exit codes were captured before any pipe (cmd > log 2>&1; rc=$?), never through one, and
every verdict quoted here is the gate's own printed line rather than a bare $?.


Generated by Claude Code

…me cannot destroy (#13919)
`scripts/measure-durability-swallow-family.mjs` declares four control families
and, measured on `origin/main`, nothing ran any of them: zero references to the
script in `package.json` or `.github/**`, counter-checked against
`measure-stall-guard-headroom` (2 hits) so the zero was a reading and not a
broken query. Meanwhile the resolver those controls pin was repaired three
times with no gate holding any previous repair, and the census's numbers feed
the #12981 repair worklist, so a wrong denominator propagates unwatched.
Adds one lightweight mode selector, `--self-test=gated`, wired as
`check:swallow-census-controls` from `lint.yml` beside the sanctioned precedent
`check:stall-guard-headroom`. The gated run asserts RESOLUTION + NEGATIVE +
REGRESSION plus the zero-member floor -- the families a successful repair
cannot destroy, because a repair moves a member from tier `dark` to tier
`channelled` and it stays a member.
POSITIVE_CONTROLS stays manual, permanently. It pins tier-1 DARK members of the
worklist the repair programme exists to remove; the file's own record shows
batch 2 already turning this self-test red for doing exactly what the ruling
asked. A gate that reddens on success is not a gate.
Bare `--self-test` is byte-identical (`--self-test=all` is its spelling), and an
unknown mode is REFUSED with exit 2 rather than falling through to the census,
which would exit 0 and read in a CI log like a self-test that passed.
…13919)
Wiring `check:swallow-census-controls` makes the census's SCAN_ROOT visible to
the bare-root sweep as a FRESH, unjudged row. REFUSE-WIDE, measured on this
tree: the walk admits every non-test TypeScript source under `packages` (2193
of 5755, 38%), the same class and nearly the same ratio as check:authz-resolver,
so a bare-root declaration would be TRUE and is refused for width alone.
…onest (#13919)
Wiring `check:swallow-census-controls` turns
`measure-durability-swallow-family.mjs` into a GATE SCRIPT, so the
convention KIND now hits it and it can no longer serve as the card where the
block harvest and `--commands` must agree exactly. Repointed at
`measure-partial-retirement-annotation.mjs` — the shape the census copied,
which no check family runs. Also classifies the new `selfTestMode` argv
parser in COMPOUND_ANCHOR_LEDGER as accidental, rather than renaming it to
dodge the anchor.
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/m ci/cd dependencies Pull requests that update a dependency file labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:34
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 793065dSep 2, 2026
39 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13919-swallow-census-gated-controls branch September 2, 2026 05:58
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@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(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919) - #14413

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls
Sep 2, 2026
Merged

feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919)#14413
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13919

The #12981 census (scripts/measure-durability-swallow-family.mjs) declares four
control families and, measured on origin/main, nothing ran any of them — zero
references to the script anywhere in package.json or .github/**, counter-checked
against a control that must return non-zero (measure-stall-guard-headroom, 2 hits) so
the zero was a reading and not a broken query. Meanwhile the resolver those controls pin
was repaired three times (#13459, #13474, PR #13915), each time with no gate holding the
previous repair, and the census's numbers feed #12981's repair worklist — so a wrong
denominator propagates into that programme with nobody watching.

The ruling this implements (verbatim, unchanged — comment 5494601066, maintainer 2026-09-01 「同意」)

  1. B:measure-durability-swallow-family.mjs 增一个轻量 flag,把 RESOLUTION_CONTROLS + NEGATIVE_CONTROLS + REGRESSION_CONTROLS 三族(修复计划不可能消灭的那三族)接为 check:* 进 CI —— 先例 check:stall-guard-headroom(package.json:150)同形;
  2. 拆分单入口形状的授权:The durability log-level gate cannot see the catch { return null; } seeder family — 15 files outside #12923's five, and neither widening path is cheap #12981 裁定认可的单入口仪器形状由本裁决显式修订为「单入口 + 分族 flag」—— 仪器的测量属性不变,每次运行照印 "a MEASUREMENT, not a gate";
  3. 三条边界(⛔ 均为硬边):
  4. C(维持不接线)排除 —— 现状就是本卡的成因,三次无守护修复已实测。

What landed

One mode selector, no duplicated reporting.selfTestMode(argv) reads the mode;
selfTest(mode) takes one gated ? [] : POSITIVE_CONTROLS on the loop it must skip, one
extra success-print branch, and one refusal branch. The problem list, the failure
formatter, the census call and the other three family loops are the same code on both
paths. Implementation cost against ruling item 3, bullet 3: the stop condition was not
reached
— the split needed no duplication of the self-test's reporting logic.

  • --self-test=gated runs RESOLUTION + NEGATIVE + REGRESSION, plus the
    zero-member floor. Wired as root check:swallow-census-controls and run from
    lint.yml beside the sanctioned precedent check:stall-guard-headroom — the same
    shape and the same asymmetry: the self-test leg only, never a bare invocation.
  • Bare --self-test is byte-identical (proof below); --self-test=all is its
    spelling. Print semantics of the bare legs are deliberately untouched — that surface
    belongs to [finding] the #12981 census prints 5 DARK sites as "the repair worklist" when 4 are settled determinations — an annotation cannot move a site out of the bucket #13886, see the serial note.
  • An unknown mode is REFUSED with exit 2 rather than falling through. Without this,
    --self-test=gatd would miss argv.includes('--self-test'), reach report(), exit 0
    and read in a CI log exactly like a self-test that passed.
  • Ruling item 2, the measurement property: the gated run prints the instrument's own
    banner line, now a single constant shared with report() rather than a second copy.

Why POSITIVE stays out, in the file's own terms rather than restated: SELF_TEST_MODES
points at the dark control's recorded why, where batch 2 already turned this
self-test red for doing exactly what the ruling asked. The exclusion is written as
permanent, not pending — repairs move a member from tier dark to tier channelled
and it stays a member, so none of the three wired families can be destroyed by a
successful repair.

DURABILITY_CRITICAL_CALLEES is untouched, no entry was added to
durability-degradation.baseline.json, and the gate vocabulary is unchanged in either
direction (ruling item 3, bullet 2 — this PR must not be used to bring that step forward).

Readings

All on 93aecd5cf (the implementation commit; the two follow-ups touch only PM tooling). Every mutation confirmed on disk before the reading was taken
(injected marker counted and deleted text counted), every restore proved by hashing
the path against its HEAD blob, each harness carrying trap restore EXIT INT TERM with
absolute paths.

runexitverdict line
--self-test=gated on this branch03 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 56 member site(s) total
bare --self-test04 positive, 3 negative, 2 regression, 6 resolution — the base branch's line, byte for byte
--self-test=gatd2x REFUSED: unknown self-test mode

Bare-output identity, measured not asserted. The base blob (e2a7fa5b8) was checked
out over the path, confirmed on disk by hash, run, and restored to the HEAD blob
(71f3ae1e5, verified). cmp on the two captures: identical.

Ablation A — the RESOLUTION family, on the defect it exists for. Reverted
indexFunctionBodies().get to the flat last-wins lookup (marker present 1, anchor
consumed). --self-test=gatedexit 1, four resolution controls firing:

 - resolution control moved: packages/objectql/src/engine.ts :: ObjectQL :: update()
-> expected `ObjectQL`, got ObjectRepository@7620, ObjectRepository@7722, ...
- resolution control moved: ... :: delete() -> got ObjectRepository@12213
- resolution control moved: ... :: transaction() -> got ScopedContext@12677
- resolution control moved: packages/runtime/src/app-plugin.ts :: resolveMappedObjects
:: push() -> expected REFUSAL, got collectBundleActions@457

Bare --self-test → exit 1 on the same tree. ⇒ the wired leg carries a real failure
signal into CI.

Ablation C — the hazard the ruling excluded POSITIVE for, reproduced. Simulated a
successful repair of the dark positive control's site by giving
share-link-service.ts :: resolveToken's telemetry catch a console.error (marker
present 1, original comment text consumed):

runexit
bare --self-test1positive control found NO member: packages/plugins/plugin-sharing/src/share-link-service.ts
--self-test=gated056 members becomes 55, and the gate stays green

⇒ this is the ruling's boundary 1 as a measurement: the full self-test reddens when the
repair programme succeeds
, and the wired subset does not.

Ablation B — reported as a NULL result rather than dropped. Removing the #13459
bare-identifier refusal from the lexical walk landed on disk — marker 1, the deleted
return null; gone — and moved nothing: --json before and after is equal in every
stat (files 2193, guardedWrites 221, refusedShadowed 4, 56 members, empty symmetric
difference on the member set). The site the action-execution regression control pins is
answered a second time by the scope-aware body index, which refuses it too. So the two
departures are defence-in-depth there, and this ablation proves nothing about the
REGRESSION family in either direction. It is recorded because a discarded null ablation is
how a "we exercised that family" claim gets minted from a reading that never happened;
Ablation A is the failure proof.

Two things the wiring forced, both found by running the derived gates

Neither is scope creep: both are consequences of this card's own change, each caught by a
gate on this PR's derived list, and each landed with the repair the gate's own remedy text
names rather than the one that quiets it.

1. scripts/pm/dispatch-gates.mjs — the seam card is now a GATE SCRIPT. Its
--self-test went red in three cases. Wiring check:swallow-census-controls makes
measure-durability-swallow-family.mjs a file some discovered check family runs, so the
"adds or edits a GATE SCRIPT" convention KIND started hitting it — and that card is the
fixture chosen for the one assertion pair that needs the block harvest and --commands to
agree exactly, i.e. a card no convention KIND hits. Repointed at
measure-partial-retirement-annotation.mjs (block 13, commands 13, convention 0, four
node rows — measured), which is the very shape the census copied and which no check
family runs. ⛔ Not repaired by loosening the equality; the comment says so at the
constant. The third case is COMPOUND_ANCHOR_LEDGER: the new selfTestMode argv parser
matches the compound self-test name anchor and is classified accidental: true, which is
what that ledger's own "Maintaining this table" section prescribes — ⛔ explicitly not by
renaming the function to dodge the anchor.

2. scripts/pm/bare-root-worklist.mjs — a FRESH bare-root row. Wiring the family
makes the census's SCAN_ROOT visible to scripts/pm/bare-root-worklist.mjs
as a FRESH, unjudged row, and its --self-test reds until a verdict is recorded (it did,
on the first sweep). Recorded REFUSE-WIDE, measured on this tree in both terms and not
carried from a sibling row: the walk admits every non-test, non-declaration TypeScript
source under the root at four extensions — 2193 of 5755 (38%), numerator from the
instrument's own printed scan count, denominator from git ls-files packages. Same class
and nearly the same ratio as the check:authz-resolver row: a bare-root declaration would
be TRUE and is refused for width alone.

No changeset — skip-changeset

This diff publishes nothing from any package: a root check:* alias, a lint.yml step, a
repo-root measure-* script, and a PM worklist verdict. The precedent is exact —
0079e2585 (#13358), which wired this same family's precedent and touched precisely
.github/workflows/lint.yml + package.json + scripts/measure-stall-guard-headroom.mjs,
carried no changeset. An empty-frontmatter changeset is not the alternative:
scripts/check-empty-changeset.mjs rejects one, and its header records why (an empty
changeset is a real input to changesets/action and can stall a release, which the label
cannot). The label is applied on this PR.

Serial note — #13886 is next on this file

#13886 (same file, print semantics of the DARK worklist) is queued behind this card
(triage 2026-09-01, comment 5486764050) and is deliberately not folded in. That is also
why the bare self-test legs' output is left byte-identical here: changing print semantics
is that card's surface, not this one's. #13886 is not addressed by this PR and remains
open.

Gate record

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
from the real change set (three-dot against merge base e80889095; the tool takes the
change set from git itself, no hand-written path list). Re-derived after each of the two
follow-up commits — the union stayed at 37 families throughout. All 37 were run, and
the union was re-run on the final commit 990649a77:

  • 34 green, including the new check:swallow-census-controls itself,
    check:pm-dispatch-gates (✓ dispatch-gates self-test: 1232 cases pass.),
    check:self-test-wired and check:self-test-workflow-commands — the two the new step
    newly puts this script into the population of — plus
    check:declared-population-live, check:ratchet-remedy-authority,
    check:watch-hint-literal, check:entry-guard, check:parse-guard and
    node scripts/pm/bare-root-worklist.mjs --self-test (OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale, none missing, none contradicted.).
  • 3 NOT MEASURED, all exit 3 and none of them a finding, each quoting its own verdict
    line: check-test-completeness.mjs ("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"),
    check:dual-build-cjs-loads and check:type-check-debt ("PREREQUISITE NOT MET... ⛔
    This is NOT a pass and NOT a finding: nothing was measured"). Structural — they need a
    built workspace or a real test-run log, which CI has and a local sweep does not.
  • 2 were red, both on this card's own consequences, both repaired above:
    scripts/pm/bare-root-worklist.mjs --self-test (FRESH row) and
    check:pm-dispatch-gates (3 of 1232 cases). Both green on the final commit.

Exit codes were captured before any pipe (cmd > log 2>&1; rc=$?), never through one, and
every verdict quoted here is the gate's own printed line rather than a bare $?.


Generated by Claude Code

…me cannot destroy (#13919)
`scripts/measure-durability-swallow-family.mjs` declares four control families
and, measured on `origin/main`, nothing ran any of them: zero references to the
script in `package.json` or `.github/**`, counter-checked against
`measure-stall-guard-headroom` (2 hits) so the zero was a reading and not a
broken query. Meanwhile the resolver those controls pin was repaired three
times with no gate holding any previous repair, and the census's numbers feed
the #12981 repair worklist, so a wrong denominator propagates unwatched.
Adds one lightweight mode selector, `--self-test=gated`, wired as
`check:swallow-census-controls` from `lint.yml` beside the sanctioned precedent
`check:stall-guard-headroom`. The gated run asserts RESOLUTION + NEGATIVE +
REGRESSION plus the zero-member floor -- the families a successful repair
cannot destroy, because a repair moves a member from tier `dark` to tier
`channelled` and it stays a member.
POSITIVE_CONTROLS stays manual, permanently. It pins tier-1 DARK members of the
worklist the repair programme exists to remove; the file's own record shows
batch 2 already turning this self-test red for doing exactly what the ruling
asked. A gate that reddens on success is not a gate.
Bare `--self-test` is byte-identical (`--self-test=all` is its spelling), and an
unknown mode is REFUSED with exit 2 rather than falling through to the census,
which would exit 0 and read in a CI log like a self-test that passed.
…13919)
Wiring `check:swallow-census-controls` makes the census's SCAN_ROOT visible to
the bare-root sweep as a FRESH, unjudged row. REFUSE-WIDE, measured on this
tree: the walk admits every non-test TypeScript source under `packages` (2193
of 5755, 38%), the same class and nearly the same ratio as check:authz-resolver,
so a bare-root declaration would be TRUE and is refused for width alone.
…onest (#13919)
Wiring `check:swallow-census-controls` turns
`measure-durability-swallow-family.mjs` into a GATE SCRIPT, so the
convention KIND now hits it and it can no longer serve as the card where the
block harvest and `--commands` must agree exactly. Repointed at
`measure-partial-retirement-annotation.mjs` — the shape the census copied,
which no check family runs. Also classifies the new `selfTestMode` argv
parser in COMPOUND_ANCHOR_LEDGER as accidental, rather than renaming it to
dodge the anchor.
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/m ci/cd dependencies Pull requests that update a dependency file labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:34
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 793065dSep 2, 2026
39 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13919-swallow-census-gated-controls branch September 2, 2026 05:58
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@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(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919) - #14413

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls
Sep 2, 2026
Merged

feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919)#14413
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13919

The #12981 census (scripts/measure-durability-swallow-family.mjs) declares four
control families and, measured on origin/main, nothing ran any of them — zero
references to the script anywhere in package.json or .github/**, counter-checked
against a control that must return non-zero (measure-stall-guard-headroom, 2 hits) so
the zero was a reading and not a broken query. Meanwhile the resolver those controls pin
was repaired three times (#13459, #13474, PR #13915), each time with no gate holding the
previous repair, and the census's numbers feed #12981's repair worklist — so a wrong
denominator propagates into that programme with nobody watching.

The ruling this implements (verbatim, unchanged — comment 5494601066, maintainer 2026-09-01 「同意」)

  1. B:measure-durability-swallow-family.mjs 增一个轻量 flag,把 RESOLUTION_CONTROLS + NEGATIVE_CONTROLS + REGRESSION_CONTROLS 三族(修复计划不可能消灭的那三族)接为 check:* 进 CI —— 先例 check:stall-guard-headroom(package.json:150)同形;
  2. 拆分单入口形状的授权:The durability log-level gate cannot see the catch { return null; } seeder family — 15 files outside #12923's five, and neither widening path is cheap #12981 裁定认可的单入口仪器形状由本裁决显式修订为「单入口 + 分族 flag」—— 仪器的测量属性不变,每次运行照印 "a MEASUREMENT, not a gate";
  3. 三条边界(⛔ 均为硬边):
  4. C(维持不接线)排除 —— 现状就是本卡的成因,三次无守护修复已实测。

What landed

One mode selector, no duplicated reporting.selfTestMode(argv) reads the mode;
selfTest(mode) takes one gated ? [] : POSITIVE_CONTROLS on the loop it must skip, one
extra success-print branch, and one refusal branch. The problem list, the failure
formatter, the census call and the other three family loops are the same code on both
paths. Implementation cost against ruling item 3, bullet 3: the stop condition was not
reached
— the split needed no duplication of the self-test's reporting logic.

  • --self-test=gated runs RESOLUTION + NEGATIVE + REGRESSION, plus the
    zero-member floor. Wired as root check:swallow-census-controls and run from
    lint.yml beside the sanctioned precedent check:stall-guard-headroom — the same
    shape and the same asymmetry: the self-test leg only, never a bare invocation.
  • Bare --self-test is byte-identical (proof below); --self-test=all is its
    spelling. Print semantics of the bare legs are deliberately untouched — that surface
    belongs to [finding] the #12981 census prints 5 DARK sites as "the repair worklist" when 4 are settled determinations — an annotation cannot move a site out of the bucket #13886, see the serial note.
  • An unknown mode is REFUSED with exit 2 rather than falling through. Without this,
    --self-test=gatd would miss argv.includes('--self-test'), reach report(), exit 0
    and read in a CI log exactly like a self-test that passed.
  • Ruling item 2, the measurement property: the gated run prints the instrument's own
    banner line, now a single constant shared with report() rather than a second copy.

Why POSITIVE stays out, in the file's own terms rather than restated: SELF_TEST_MODES
points at the dark control's recorded why, where batch 2 already turned this
self-test red for doing exactly what the ruling asked. The exclusion is written as
permanent, not pending — repairs move a member from tier dark to tier channelled
and it stays a member, so none of the three wired families can be destroyed by a
successful repair.

DURABILITY_CRITICAL_CALLEES is untouched, no entry was added to
durability-degradation.baseline.json, and the gate vocabulary is unchanged in either
direction (ruling item 3, bullet 2 — this PR must not be used to bring that step forward).

Readings

All on 93aecd5cf (the implementation commit; the two follow-ups touch only PM tooling). Every mutation confirmed on disk before the reading was taken
(injected marker counted and deleted text counted), every restore proved by hashing
the path against its HEAD blob, each harness carrying trap restore EXIT INT TERM with
absolute paths.

runexitverdict line
--self-test=gated on this branch03 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 56 member site(s) total
bare --self-test04 positive, 3 negative, 2 regression, 6 resolution — the base branch's line, byte for byte
--self-test=gatd2x REFUSED: unknown self-test mode

Bare-output identity, measured not asserted. The base blob (e2a7fa5b8) was checked
out over the path, confirmed on disk by hash, run, and restored to the HEAD blob
(71f3ae1e5, verified). cmp on the two captures: identical.

Ablation A — the RESOLUTION family, on the defect it exists for. Reverted
indexFunctionBodies().get to the flat last-wins lookup (marker present 1, anchor
consumed). --self-test=gatedexit 1, four resolution controls firing:

 - resolution control moved: packages/objectql/src/engine.ts :: ObjectQL :: update()
-> expected `ObjectQL`, got ObjectRepository@7620, ObjectRepository@7722, ...
- resolution control moved: ... :: delete() -> got ObjectRepository@12213
- resolution control moved: ... :: transaction() -> got ScopedContext@12677
- resolution control moved: packages/runtime/src/app-plugin.ts :: resolveMappedObjects
:: push() -> expected REFUSAL, got collectBundleActions@457

Bare --self-test → exit 1 on the same tree. ⇒ the wired leg carries a real failure
signal into CI.

Ablation C — the hazard the ruling excluded POSITIVE for, reproduced. Simulated a
successful repair of the dark positive control's site by giving
share-link-service.ts :: resolveToken's telemetry catch a console.error (marker
present 1, original comment text consumed):

runexit
bare --self-test1positive control found NO member: packages/plugins/plugin-sharing/src/share-link-service.ts
--self-test=gated056 members becomes 55, and the gate stays green

⇒ this is the ruling's boundary 1 as a measurement: the full self-test reddens when the
repair programme succeeds
, and the wired subset does not.

Ablation B — reported as a NULL result rather than dropped. Removing the #13459
bare-identifier refusal from the lexical walk landed on disk — marker 1, the deleted
return null; gone — and moved nothing: --json before and after is equal in every
stat (files 2193, guardedWrites 221, refusedShadowed 4, 56 members, empty symmetric
difference on the member set). The site the action-execution regression control pins is
answered a second time by the scope-aware body index, which refuses it too. So the two
departures are defence-in-depth there, and this ablation proves nothing about the
REGRESSION family in either direction. It is recorded because a discarded null ablation is
how a "we exercised that family" claim gets minted from a reading that never happened;
Ablation A is the failure proof.

Two things the wiring forced, both found by running the derived gates

Neither is scope creep: both are consequences of this card's own change, each caught by a
gate on this PR's derived list, and each landed with the repair the gate's own remedy text
names rather than the one that quiets it.

1. scripts/pm/dispatch-gates.mjs — the seam card is now a GATE SCRIPT. Its
--self-test went red in three cases. Wiring check:swallow-census-controls makes
measure-durability-swallow-family.mjs a file some discovered check family runs, so the
"adds or edits a GATE SCRIPT" convention KIND started hitting it — and that card is the
fixture chosen for the one assertion pair that needs the block harvest and --commands to
agree exactly, i.e. a card no convention KIND hits. Repointed at
measure-partial-retirement-annotation.mjs (block 13, commands 13, convention 0, four
node rows — measured), which is the very shape the census copied and which no check
family runs. ⛔ Not repaired by loosening the equality; the comment says so at the
constant. The third case is COMPOUND_ANCHOR_LEDGER: the new selfTestMode argv parser
matches the compound self-test name anchor and is classified accidental: true, which is
what that ledger's own "Maintaining this table" section prescribes — ⛔ explicitly not by
renaming the function to dodge the anchor.

2. scripts/pm/bare-root-worklist.mjs — a FRESH bare-root row. Wiring the family
makes the census's SCAN_ROOT visible to scripts/pm/bare-root-worklist.mjs
as a FRESH, unjudged row, and its --self-test reds until a verdict is recorded (it did,
on the first sweep). Recorded REFUSE-WIDE, measured on this tree in both terms and not
carried from a sibling row: the walk admits every non-test, non-declaration TypeScript
source under the root at four extensions — 2193 of 5755 (38%), numerator from the
instrument's own printed scan count, denominator from git ls-files packages. Same class
and nearly the same ratio as the check:authz-resolver row: a bare-root declaration would
be TRUE and is refused for width alone.

No changeset — skip-changeset

This diff publishes nothing from any package: a root check:* alias, a lint.yml step, a
repo-root measure-* script, and a PM worklist verdict. The precedent is exact —
0079e2585 (#13358), which wired this same family's precedent and touched precisely
.github/workflows/lint.yml + package.json + scripts/measure-stall-guard-headroom.mjs,
carried no changeset. An empty-frontmatter changeset is not the alternative:
scripts/check-empty-changeset.mjs rejects one, and its header records why (an empty
changeset is a real input to changesets/action and can stall a release, which the label
cannot). The label is applied on this PR.

Serial note — #13886 is next on this file

#13886 (same file, print semantics of the DARK worklist) is queued behind this card
(triage 2026-09-01, comment 5486764050) and is deliberately not folded in. That is also
why the bare self-test legs' output is left byte-identical here: changing print semantics
is that card's surface, not this one's. #13886 is not addressed by this PR and remains
open.

Gate record

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
from the real change set (three-dot against merge base e80889095; the tool takes the
change set from git itself, no hand-written path list). Re-derived after each of the two
follow-up commits — the union stayed at 37 families throughout. All 37 were run, and
the union was re-run on the final commit 990649a77:

  • 34 green, including the new check:swallow-census-controls itself,
    check:pm-dispatch-gates (✓ dispatch-gates self-test: 1232 cases pass.),
    check:self-test-wired and check:self-test-workflow-commands — the two the new step
    newly puts this script into the population of — plus
    check:declared-population-live, check:ratchet-remedy-authority,
    check:watch-hint-literal, check:entry-guard, check:parse-guard and
    node scripts/pm/bare-root-worklist.mjs --self-test (OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale, none missing, none contradicted.).
  • 3 NOT MEASURED, all exit 3 and none of them a finding, each quoting its own verdict
    line: check-test-completeness.mjs ("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"),
    check:dual-build-cjs-loads and check:type-check-debt ("PREREQUISITE NOT MET... ⛔
    This is NOT a pass and NOT a finding: nothing was measured"). Structural — they need a
    built workspace or a real test-run log, which CI has and a local sweep does not.
  • 2 were red, both on this card's own consequences, both repaired above:
    scripts/pm/bare-root-worklist.mjs --self-test (FRESH row) and
    check:pm-dispatch-gates (3 of 1232 cases). Both green on the final commit.

Exit codes were captured before any pipe (cmd > log 2>&1; rc=$?), never through one, and
every verdict quoted here is the gate's own printed line rather than a bare $?.


Generated by Claude Code

…me cannot destroy (#13919)
`scripts/measure-durability-swallow-family.mjs` declares four control families
and, measured on `origin/main`, nothing ran any of them: zero references to the
script in `package.json` or `.github/**`, counter-checked against
`measure-stall-guard-headroom` (2 hits) so the zero was a reading and not a
broken query. Meanwhile the resolver those controls pin was repaired three
times with no gate holding any previous repair, and the census's numbers feed
the #12981 repair worklist, so a wrong denominator propagates unwatched.
Adds one lightweight mode selector, `--self-test=gated`, wired as
`check:swallow-census-controls` from `lint.yml` beside the sanctioned precedent
`check:stall-guard-headroom`. The gated run asserts RESOLUTION + NEGATIVE +
REGRESSION plus the zero-member floor -- the families a successful repair
cannot destroy, because a repair moves a member from tier `dark` to tier
`channelled` and it stays a member.
POSITIVE_CONTROLS stays manual, permanently. It pins tier-1 DARK members of the
worklist the repair programme exists to remove; the file's own record shows
batch 2 already turning this self-test red for doing exactly what the ruling
asked. A gate that reddens on success is not a gate.
Bare `--self-test` is byte-identical (`--self-test=all` is its spelling), and an
unknown mode is REFUSED with exit 2 rather than falling through to the census,
which would exit 0 and read in a CI log like a self-test that passed.
…13919)
Wiring `check:swallow-census-controls` makes the census's SCAN_ROOT visible to
the bare-root sweep as a FRESH, unjudged row. REFUSE-WIDE, measured on this
tree: the walk admits every non-test TypeScript source under `packages` (2193
of 5755, 38%), the same class and nearly the same ratio as check:authz-resolver,
so a bare-root declaration would be TRUE and is refused for width alone.
…onest (#13919)
Wiring `check:swallow-census-controls` turns
`measure-durability-swallow-family.mjs` into a GATE SCRIPT, so the
convention KIND now hits it and it can no longer serve as the card where the
block harvest and `--commands` must agree exactly. Repointed at
`measure-partial-retirement-annotation.mjs` — the shape the census copied,
which no check family runs. Also classifies the new `selfTestMode` argv
parser in COMPOUND_ANCHOR_LEDGER as accidental, rather than renaming it to
dodge the anchor.
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/m ci/cd dependencies Pull requests that update a dependency file labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:34
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 793065dSep 2, 2026
39 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13919-swallow-census-gated-controls branch September 2, 2026 05:58
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@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(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919) - #14413

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls
Sep 2, 2026
Merged

feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919)#14413
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13919

The #12981 census (scripts/measure-durability-swallow-family.mjs) declares four
control families and, measured on origin/main, nothing ran any of them — zero
references to the script anywhere in package.json or .github/**, counter-checked
against a control that must return non-zero (measure-stall-guard-headroom, 2 hits) so
the zero was a reading and not a broken query. Meanwhile the resolver those controls pin
was repaired three times (#13459, #13474, PR #13915), each time with no gate holding the
previous repair, and the census's numbers feed #12981's repair worklist — so a wrong
denominator propagates into that programme with nobody watching.

The ruling this implements (verbatim, unchanged — comment 5494601066, maintainer 2026-09-01 「同意」)

  1. B:measure-durability-swallow-family.mjs 增一个轻量 flag,把 RESOLUTION_CONTROLS + NEGATIVE_CONTROLS + REGRESSION_CONTROLS 三族(修复计划不可能消灭的那三族)接为 check:* 进 CI —— 先例 check:stall-guard-headroom(package.json:150)同形;
  2. 拆分单入口形状的授权:The durability log-level gate cannot see the catch { return null; } seeder family — 15 files outside #12923's five, and neither widening path is cheap #12981 裁定认可的单入口仪器形状由本裁决显式修订为「单入口 + 分族 flag」—— 仪器的测量属性不变,每次运行照印 "a MEASUREMENT, not a gate";
  3. 三条边界(⛔ 均为硬边):
  4. C(维持不接线)排除 —— 现状就是本卡的成因,三次无守护修复已实测。

What landed

One mode selector, no duplicated reporting.selfTestMode(argv) reads the mode;
selfTest(mode) takes one gated ? [] : POSITIVE_CONTROLS on the loop it must skip, one
extra success-print branch, and one refusal branch. The problem list, the failure
formatter, the census call and the other three family loops are the same code on both
paths. Implementation cost against ruling item 3, bullet 3: the stop condition was not
reached
— the split needed no duplication of the self-test's reporting logic.

  • --self-test=gated runs RESOLUTION + NEGATIVE + REGRESSION, plus the
    zero-member floor. Wired as root check:swallow-census-controls and run from
    lint.yml beside the sanctioned precedent check:stall-guard-headroom — the same
    shape and the same asymmetry: the self-test leg only, never a bare invocation.
  • Bare --self-test is byte-identical (proof below); --self-test=all is its
    spelling. Print semantics of the bare legs are deliberately untouched — that surface
    belongs to [finding] the #12981 census prints 5 DARK sites as "the repair worklist" when 4 are settled determinations — an annotation cannot move a site out of the bucket #13886, see the serial note.
  • An unknown mode is REFUSED with exit 2 rather than falling through. Without this,
    --self-test=gatd would miss argv.includes('--self-test'), reach report(), exit 0
    and read in a CI log exactly like a self-test that passed.
  • Ruling item 2, the measurement property: the gated run prints the instrument's own
    banner line, now a single constant shared with report() rather than a second copy.

Why POSITIVE stays out, in the file's own terms rather than restated: SELF_TEST_MODES
points at the dark control's recorded why, where batch 2 already turned this
self-test red for doing exactly what the ruling asked. The exclusion is written as
permanent, not pending — repairs move a member from tier dark to tier channelled
and it stays a member, so none of the three wired families can be destroyed by a
successful repair.

DURABILITY_CRITICAL_CALLEES is untouched, no entry was added to
durability-degradation.baseline.json, and the gate vocabulary is unchanged in either
direction (ruling item 3, bullet 2 — this PR must not be used to bring that step forward).

Readings

All on 93aecd5cf (the implementation commit; the two follow-ups touch only PM tooling). Every mutation confirmed on disk before the reading was taken
(injected marker counted and deleted text counted), every restore proved by hashing
the path against its HEAD blob, each harness carrying trap restore EXIT INT TERM with
absolute paths.

runexitverdict line
--self-test=gated on this branch03 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 56 member site(s) total
bare --self-test04 positive, 3 negative, 2 regression, 6 resolution — the base branch's line, byte for byte
--self-test=gatd2x REFUSED: unknown self-test mode

Bare-output identity, measured not asserted. The base blob (e2a7fa5b8) was checked
out over the path, confirmed on disk by hash, run, and restored to the HEAD blob
(71f3ae1e5, verified). cmp on the two captures: identical.

Ablation A — the RESOLUTION family, on the defect it exists for. Reverted
indexFunctionBodies().get to the flat last-wins lookup (marker present 1, anchor
consumed). --self-test=gatedexit 1, four resolution controls firing:

 - resolution control moved: packages/objectql/src/engine.ts :: ObjectQL :: update()
-> expected `ObjectQL`, got ObjectRepository@7620, ObjectRepository@7722, ...
- resolution control moved: ... :: delete() -> got ObjectRepository@12213
- resolution control moved: ... :: transaction() -> got ScopedContext@12677
- resolution control moved: packages/runtime/src/app-plugin.ts :: resolveMappedObjects
:: push() -> expected REFUSAL, got collectBundleActions@457

Bare --self-test → exit 1 on the same tree. ⇒ the wired leg carries a real failure
signal into CI.

Ablation C — the hazard the ruling excluded POSITIVE for, reproduced. Simulated a
successful repair of the dark positive control's site by giving
share-link-service.ts :: resolveToken's telemetry catch a console.error (marker
present 1, original comment text consumed):

runexit
bare --self-test1positive control found NO member: packages/plugins/plugin-sharing/src/share-link-service.ts
--self-test=gated056 members becomes 55, and the gate stays green

⇒ this is the ruling's boundary 1 as a measurement: the full self-test reddens when the
repair programme succeeds
, and the wired subset does not.

Ablation B — reported as a NULL result rather than dropped. Removing the #13459
bare-identifier refusal from the lexical walk landed on disk — marker 1, the deleted
return null; gone — and moved nothing: --json before and after is equal in every
stat (files 2193, guardedWrites 221, refusedShadowed 4, 56 members, empty symmetric
difference on the member set). The site the action-execution regression control pins is
answered a second time by the scope-aware body index, which refuses it too. So the two
departures are defence-in-depth there, and this ablation proves nothing about the
REGRESSION family in either direction. It is recorded because a discarded null ablation is
how a "we exercised that family" claim gets minted from a reading that never happened;
Ablation A is the failure proof.

Two things the wiring forced, both found by running the derived gates

Neither is scope creep: both are consequences of this card's own change, each caught by a
gate on this PR's derived list, and each landed with the repair the gate's own remedy text
names rather than the one that quiets it.

1. scripts/pm/dispatch-gates.mjs — the seam card is now a GATE SCRIPT. Its
--self-test went red in three cases. Wiring check:swallow-census-controls makes
measure-durability-swallow-family.mjs a file some discovered check family runs, so the
"adds or edits a GATE SCRIPT" convention KIND started hitting it — and that card is the
fixture chosen for the one assertion pair that needs the block harvest and --commands to
agree exactly, i.e. a card no convention KIND hits. Repointed at
measure-partial-retirement-annotation.mjs (block 13, commands 13, convention 0, four
node rows — measured), which is the very shape the census copied and which no check
family runs. ⛔ Not repaired by loosening the equality; the comment says so at the
constant. The third case is COMPOUND_ANCHOR_LEDGER: the new selfTestMode argv parser
matches the compound self-test name anchor and is classified accidental: true, which is
what that ledger's own "Maintaining this table" section prescribes — ⛔ explicitly not by
renaming the function to dodge the anchor.

2. scripts/pm/bare-root-worklist.mjs — a FRESH bare-root row. Wiring the family
makes the census's SCAN_ROOT visible to scripts/pm/bare-root-worklist.mjs
as a FRESH, unjudged row, and its --self-test reds until a verdict is recorded (it did,
on the first sweep). Recorded REFUSE-WIDE, measured on this tree in both terms and not
carried from a sibling row: the walk admits every non-test, non-declaration TypeScript
source under the root at four extensions — 2193 of 5755 (38%), numerator from the
instrument's own printed scan count, denominator from git ls-files packages. Same class
and nearly the same ratio as the check:authz-resolver row: a bare-root declaration would
be TRUE and is refused for width alone.

No changeset — skip-changeset

This diff publishes nothing from any package: a root check:* alias, a lint.yml step, a
repo-root measure-* script, and a PM worklist verdict. The precedent is exact —
0079e2585 (#13358), which wired this same family's precedent and touched precisely
.github/workflows/lint.yml + package.json + scripts/measure-stall-guard-headroom.mjs,
carried no changeset. An empty-frontmatter changeset is not the alternative:
scripts/check-empty-changeset.mjs rejects one, and its header records why (an empty
changeset is a real input to changesets/action and can stall a release, which the label
cannot). The label is applied on this PR.

Serial note — #13886 is next on this file

#13886 (same file, print semantics of the DARK worklist) is queued behind this card
(triage 2026-09-01, comment 5486764050) and is deliberately not folded in. That is also
why the bare self-test legs' output is left byte-identical here: changing print semantics
is that card's surface, not this one's. #13886 is not addressed by this PR and remains
open.

Gate record

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
from the real change set (three-dot against merge base e80889095; the tool takes the
change set from git itself, no hand-written path list). Re-derived after each of the two
follow-up commits — the union stayed at 37 families throughout. All 37 were run, and
the union was re-run on the final commit 990649a77:

  • 34 green, including the new check:swallow-census-controls itself,
    check:pm-dispatch-gates (✓ dispatch-gates self-test: 1232 cases pass.),
    check:self-test-wired and check:self-test-workflow-commands — the two the new step
    newly puts this script into the population of — plus
    check:declared-population-live, check:ratchet-remedy-authority,
    check:watch-hint-literal, check:entry-guard, check:parse-guard and
    node scripts/pm/bare-root-worklist.mjs --self-test (OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale, none missing, none contradicted.).
  • 3 NOT MEASURED, all exit 3 and none of them a finding, each quoting its own verdict
    line: check-test-completeness.mjs ("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"),
    check:dual-build-cjs-loads and check:type-check-debt ("PREREQUISITE NOT MET... ⛔
    This is NOT a pass and NOT a finding: nothing was measured"). Structural — they need a
    built workspace or a real test-run log, which CI has and a local sweep does not.
  • 2 were red, both on this card's own consequences, both repaired above:
    scripts/pm/bare-root-worklist.mjs --self-test (FRESH row) and
    check:pm-dispatch-gates (3 of 1232 cases). Both green on the final commit.

Exit codes were captured before any pipe (cmd > log 2>&1; rc=$?), never through one, and
every verdict quoted here is the gate's own printed line rather than a bare $?.


Generated by Claude Code

…me cannot destroy (#13919)
`scripts/measure-durability-swallow-family.mjs` declares four control families
and, measured on `origin/main`, nothing ran any of them: zero references to the
script in `package.json` or `.github/**`, counter-checked against
`measure-stall-guard-headroom` (2 hits) so the zero was a reading and not a
broken query. Meanwhile the resolver those controls pin was repaired three
times with no gate holding any previous repair, and the census's numbers feed
the #12981 repair worklist, so a wrong denominator propagates unwatched.
Adds one lightweight mode selector, `--self-test=gated`, wired as
`check:swallow-census-controls` from `lint.yml` beside the sanctioned precedent
`check:stall-guard-headroom`. The gated run asserts RESOLUTION + NEGATIVE +
REGRESSION plus the zero-member floor -- the families a successful repair
cannot destroy, because a repair moves a member from tier `dark` to tier
`channelled` and it stays a member.
POSITIVE_CONTROLS stays manual, permanently. It pins tier-1 DARK members of the
worklist the repair programme exists to remove; the file's own record shows
batch 2 already turning this self-test red for doing exactly what the ruling
asked. A gate that reddens on success is not a gate.
Bare `--self-test` is byte-identical (`--self-test=all` is its spelling), and an
unknown mode is REFUSED with exit 2 rather than falling through to the census,
which would exit 0 and read in a CI log like a self-test that passed.
…13919)
Wiring `check:swallow-census-controls` makes the census's SCAN_ROOT visible to
the bare-root sweep as a FRESH, unjudged row. REFUSE-WIDE, measured on this
tree: the walk admits every non-test TypeScript source under `packages` (2193
of 5755, 38%), the same class and nearly the same ratio as check:authz-resolver,
so a bare-root declaration would be TRUE and is refused for width alone.
…onest (#13919)
Wiring `check:swallow-census-controls` turns
`measure-durability-swallow-family.mjs` into a GATE SCRIPT, so the
convention KIND now hits it and it can no longer serve as the card where the
block harvest and `--commands` must agree exactly. Repointed at
`measure-partial-retirement-annotation.mjs` — the shape the census copied,
which no check family runs. Also classifies the new `selfTestMode` argv
parser in COMPOUND_ANCHOR_LEDGER as accidental, rather than renaming it to
dodge the anchor.
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/m ci/cd dependencies Pull requests that update a dependency file labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:34
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 793065dSep 2, 2026
39 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13919-swallow-census-gated-controls branch September 2, 2026 05:58
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@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(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919) - #14413

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls
Sep 2, 2026
Merged

feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919)#14413
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13919

The #12981 census (scripts/measure-durability-swallow-family.mjs) declares four
control families and, measured on origin/main, nothing ran any of them — zero
references to the script anywhere in package.json or .github/**, counter-checked
against a control that must return non-zero (measure-stall-guard-headroom, 2 hits) so
the zero was a reading and not a broken query. Meanwhile the resolver those controls pin
was repaired three times (#13459, #13474, PR #13915), each time with no gate holding the
previous repair, and the census's numbers feed #12981's repair worklist — so a wrong
denominator propagates into that programme with nobody watching.

The ruling this implements (verbatim, unchanged — comment 5494601066, maintainer 2026-09-01 「同意」)

  1. B:measure-durability-swallow-family.mjs 增一个轻量 flag,把 RESOLUTION_CONTROLS + NEGATIVE_CONTROLS + REGRESSION_CONTROLS 三族(修复计划不可能消灭的那三族)接为 check:* 进 CI —— 先例 check:stall-guard-headroom(package.json:150)同形;
  2. 拆分单入口形状的授权:The durability log-level gate cannot see the catch { return null; } seeder family — 15 files outside #12923's five, and neither widening path is cheap #12981 裁定认可的单入口仪器形状由本裁决显式修订为「单入口 + 分族 flag」—— 仪器的测量属性不变,每次运行照印 "a MEASUREMENT, not a gate";
  3. 三条边界(⛔ 均为硬边):
  4. C(维持不接线)排除 —— 现状就是本卡的成因,三次无守护修复已实测。

What landed

One mode selector, no duplicated reporting.selfTestMode(argv) reads the mode;
selfTest(mode) takes one gated ? [] : POSITIVE_CONTROLS on the loop it must skip, one
extra success-print branch, and one refusal branch. The problem list, the failure
formatter, the census call and the other three family loops are the same code on both
paths. Implementation cost against ruling item 3, bullet 3: the stop condition was not
reached
— the split needed no duplication of the self-test's reporting logic.

  • --self-test=gated runs RESOLUTION + NEGATIVE + REGRESSION, plus the
    zero-member floor. Wired as root check:swallow-census-controls and run from
    lint.yml beside the sanctioned precedent check:stall-guard-headroom — the same
    shape and the same asymmetry: the self-test leg only, never a bare invocation.
  • Bare --self-test is byte-identical (proof below); --self-test=all is its
    spelling. Print semantics of the bare legs are deliberately untouched — that surface
    belongs to [finding] the #12981 census prints 5 DARK sites as "the repair worklist" when 4 are settled determinations — an annotation cannot move a site out of the bucket #13886, see the serial note.
  • An unknown mode is REFUSED with exit 2 rather than falling through. Without this,
    --self-test=gatd would miss argv.includes('--self-test'), reach report(), exit 0
    and read in a CI log exactly like a self-test that passed.
  • Ruling item 2, the measurement property: the gated run prints the instrument's own
    banner line, now a single constant shared with report() rather than a second copy.

Why POSITIVE stays out, in the file's own terms rather than restated: SELF_TEST_MODES
points at the dark control's recorded why, where batch 2 already turned this
self-test red for doing exactly what the ruling asked. The exclusion is written as
permanent, not pending — repairs move a member from tier dark to tier channelled
and it stays a member, so none of the three wired families can be destroyed by a
successful repair.

DURABILITY_CRITICAL_CALLEES is untouched, no entry was added to
durability-degradation.baseline.json, and the gate vocabulary is unchanged in either
direction (ruling item 3, bullet 2 — this PR must not be used to bring that step forward).

Readings

All on 93aecd5cf (the implementation commit; the two follow-ups touch only PM tooling). Every mutation confirmed on disk before the reading was taken
(injected marker counted and deleted text counted), every restore proved by hashing
the path against its HEAD blob, each harness carrying trap restore EXIT INT TERM with
absolute paths.

runexitverdict line
--self-test=gated on this branch03 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 56 member site(s) total
bare --self-test04 positive, 3 negative, 2 regression, 6 resolution — the base branch's line, byte for byte
--self-test=gatd2x REFUSED: unknown self-test mode

Bare-output identity, measured not asserted. The base blob (e2a7fa5b8) was checked
out over the path, confirmed on disk by hash, run, and restored to the HEAD blob
(71f3ae1e5, verified). cmp on the two captures: identical.

Ablation A — the RESOLUTION family, on the defect it exists for. Reverted
indexFunctionBodies().get to the flat last-wins lookup (marker present 1, anchor
consumed). --self-test=gatedexit 1, four resolution controls firing:

 - resolution control moved: packages/objectql/src/engine.ts :: ObjectQL :: update()
-> expected `ObjectQL`, got ObjectRepository@7620, ObjectRepository@7722, ...
- resolution control moved: ... :: delete() -> got ObjectRepository@12213
- resolution control moved: ... :: transaction() -> got ScopedContext@12677
- resolution control moved: packages/runtime/src/app-plugin.ts :: resolveMappedObjects
:: push() -> expected REFUSAL, got collectBundleActions@457

Bare --self-test → exit 1 on the same tree. ⇒ the wired leg carries a real failure
signal into CI.

Ablation C — the hazard the ruling excluded POSITIVE for, reproduced. Simulated a
successful repair of the dark positive control's site by giving
share-link-service.ts :: resolveToken's telemetry catch a console.error (marker
present 1, original comment text consumed):

runexit
bare --self-test1positive control found NO member: packages/plugins/plugin-sharing/src/share-link-service.ts
--self-test=gated056 members becomes 55, and the gate stays green

⇒ this is the ruling's boundary 1 as a measurement: the full self-test reddens when the
repair programme succeeds
, and the wired subset does not.

Ablation B — reported as a NULL result rather than dropped. Removing the #13459
bare-identifier refusal from the lexical walk landed on disk — marker 1, the deleted
return null; gone — and moved nothing: --json before and after is equal in every
stat (files 2193, guardedWrites 221, refusedShadowed 4, 56 members, empty symmetric
difference on the member set). The site the action-execution regression control pins is
answered a second time by the scope-aware body index, which refuses it too. So the two
departures are defence-in-depth there, and this ablation proves nothing about the
REGRESSION family in either direction. It is recorded because a discarded null ablation is
how a "we exercised that family" claim gets minted from a reading that never happened;
Ablation A is the failure proof.

Two things the wiring forced, both found by running the derived gates

Neither is scope creep: both are consequences of this card's own change, each caught by a
gate on this PR's derived list, and each landed with the repair the gate's own remedy text
names rather than the one that quiets it.

1. scripts/pm/dispatch-gates.mjs — the seam card is now a GATE SCRIPT. Its
--self-test went red in three cases. Wiring check:swallow-census-controls makes
measure-durability-swallow-family.mjs a file some discovered check family runs, so the
"adds or edits a GATE SCRIPT" convention KIND started hitting it — and that card is the
fixture chosen for the one assertion pair that needs the block harvest and --commands to
agree exactly, i.e. a card no convention KIND hits. Repointed at
measure-partial-retirement-annotation.mjs (block 13, commands 13, convention 0, four
node rows — measured), which is the very shape the census copied and which no check
family runs. ⛔ Not repaired by loosening the equality; the comment says so at the
constant. The third case is COMPOUND_ANCHOR_LEDGER: the new selfTestMode argv parser
matches the compound self-test name anchor and is classified accidental: true, which is
what that ledger's own "Maintaining this table" section prescribes — ⛔ explicitly not by
renaming the function to dodge the anchor.

2. scripts/pm/bare-root-worklist.mjs — a FRESH bare-root row. Wiring the family
makes the census's SCAN_ROOT visible to scripts/pm/bare-root-worklist.mjs
as a FRESH, unjudged row, and its --self-test reds until a verdict is recorded (it did,
on the first sweep). Recorded REFUSE-WIDE, measured on this tree in both terms and not
carried from a sibling row: the walk admits every non-test, non-declaration TypeScript
source under the root at four extensions — 2193 of 5755 (38%), numerator from the
instrument's own printed scan count, denominator from git ls-files packages. Same class
and nearly the same ratio as the check:authz-resolver row: a bare-root declaration would
be TRUE and is refused for width alone.

No changeset — skip-changeset

This diff publishes nothing from any package: a root check:* alias, a lint.yml step, a
repo-root measure-* script, and a PM worklist verdict. The precedent is exact —
0079e2585 (#13358), which wired this same family's precedent and touched precisely
.github/workflows/lint.yml + package.json + scripts/measure-stall-guard-headroom.mjs,
carried no changeset. An empty-frontmatter changeset is not the alternative:
scripts/check-empty-changeset.mjs rejects one, and its header records why (an empty
changeset is a real input to changesets/action and can stall a release, which the label
cannot). The label is applied on this PR.

Serial note — #13886 is next on this file

#13886 (same file, print semantics of the DARK worklist) is queued behind this card
(triage 2026-09-01, comment 5486764050) and is deliberately not folded in. That is also
why the bare self-test legs' output is left byte-identical here: changing print semantics
is that card's surface, not this one's. #13886 is not addressed by this PR and remains
open.

Gate record

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
from the real change set (three-dot against merge base e80889095; the tool takes the
change set from git itself, no hand-written path list). Re-derived after each of the two
follow-up commits — the union stayed at 37 families throughout. All 37 were run, and
the union was re-run on the final commit 990649a77:

  • 34 green, including the new check:swallow-census-controls itself,
    check:pm-dispatch-gates (✓ dispatch-gates self-test: 1232 cases pass.),
    check:self-test-wired and check:self-test-workflow-commands — the two the new step
    newly puts this script into the population of — plus
    check:declared-population-live, check:ratchet-remedy-authority,
    check:watch-hint-literal, check:entry-guard, check:parse-guard and
    node scripts/pm/bare-root-worklist.mjs --self-test (OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale, none missing, none contradicted.).
  • 3 NOT MEASURED, all exit 3 and none of them a finding, each quoting its own verdict
    line: check-test-completeness.mjs ("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"),
    check:dual-build-cjs-loads and check:type-check-debt ("PREREQUISITE NOT MET... ⛔
    This is NOT a pass and NOT a finding: nothing was measured"). Structural — they need a
    built workspace or a real test-run log, which CI has and a local sweep does not.
  • 2 were red, both on this card's own consequences, both repaired above:
    scripts/pm/bare-root-worklist.mjs --self-test (FRESH row) and
    check:pm-dispatch-gates (3 of 1232 cases). Both green on the final commit.

Exit codes were captured before any pipe (cmd > log 2>&1; rc=$?), never through one, and
every verdict quoted here is the gate's own printed line rather than a bare $?.


Generated by Claude Code

…me cannot destroy (#13919)
`scripts/measure-durability-swallow-family.mjs` declares four control families
and, measured on `origin/main`, nothing ran any of them: zero references to the
script in `package.json` or `.github/**`, counter-checked against
`measure-stall-guard-headroom` (2 hits) so the zero was a reading and not a
broken query. Meanwhile the resolver those controls pin was repaired three
times with no gate holding any previous repair, and the census's numbers feed
the #12981 repair worklist, so a wrong denominator propagates unwatched.
Adds one lightweight mode selector, `--self-test=gated`, wired as
`check:swallow-census-controls` from `lint.yml` beside the sanctioned precedent
`check:stall-guard-headroom`. The gated run asserts RESOLUTION + NEGATIVE +
REGRESSION plus the zero-member floor -- the families a successful repair
cannot destroy, because a repair moves a member from tier `dark` to tier
`channelled` and it stays a member.
POSITIVE_CONTROLS stays manual, permanently. It pins tier-1 DARK members of the
worklist the repair programme exists to remove; the file's own record shows
batch 2 already turning this self-test red for doing exactly what the ruling
asked. A gate that reddens on success is not a gate.
Bare `--self-test` is byte-identical (`--self-test=all` is its spelling), and an
unknown mode is REFUSED with exit 2 rather than falling through to the census,
which would exit 0 and read in a CI log like a self-test that passed.
…13919)
Wiring `check:swallow-census-controls` makes the census's SCAN_ROOT visible to
the bare-root sweep as a FRESH, unjudged row. REFUSE-WIDE, measured on this
tree: the walk admits every non-test TypeScript source under `packages` (2193
of 5755, 38%), the same class and nearly the same ratio as check:authz-resolver,
so a bare-root declaration would be TRUE and is refused for width alone.
…onest (#13919)
Wiring `check:swallow-census-controls` turns
`measure-durability-swallow-family.mjs` into a GATE SCRIPT, so the
convention KIND now hits it and it can no longer serve as the card where the
block harvest and `--commands` must agree exactly. Repointed at
`measure-partial-retirement-annotation.mjs` — the shape the census copied,
which no check family runs. Also classifies the new `selfTestMode` argv
parser in COMPOUND_ANCHOR_LEDGER as accidental, rather than renaming it to
dodge the anchor.
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/m ci/cd dependencies Pull requests that update a dependency file labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:34
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 793065dSep 2, 2026
39 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13919-swallow-census-gated-controls branch September 2, 2026 05:58
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@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(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919) - #14413

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls
Sep 2, 2026
Merged

feat(tooling): gate the swallow-census control families the repair programme cannot destroy (#13919)#14413
baozhoutao merged 3 commits into
mainfrom
claude/issue-13919-swallow-census-gated-controls

Conversation

@claude

@claudeclaudeBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Fixes#13919

The #12981 census (scripts/measure-durability-swallow-family.mjs) declares four
control families and, measured on origin/main, nothing ran any of them — zero
references to the script anywhere in package.json or .github/**, counter-checked
against a control that must return non-zero (measure-stall-guard-headroom, 2 hits) so
the zero was a reading and not a broken query. Meanwhile the resolver those controls pin
was repaired three times (#13459, #13474, PR #13915), each time with no gate holding the
previous repair, and the census's numbers feed #12981's repair worklist — so a wrong
denominator propagates into that programme with nobody watching.

The ruling this implements (verbatim, unchanged — comment 5494601066, maintainer 2026-09-01 「同意」)

  1. B:measure-durability-swallow-family.mjs 增一个轻量 flag,把 RESOLUTION_CONTROLS + NEGATIVE_CONTROLS + REGRESSION_CONTROLS 三族(修复计划不可能消灭的那三族)接为 check:* 进 CI —— 先例 check:stall-guard-headroom(package.json:150)同形;
  2. 拆分单入口形状的授权:The durability log-level gate cannot see the catch { return null; } seeder family — 15 files outside #12923's five, and neither widening path is cheap #12981 裁定认可的单入口仪器形状由本裁决显式修订为「单入口 + 分族 flag」—— 仪器的测量属性不变,每次运行照印 "a MEASUREMENT, not a gate";
  3. 三条边界(⛔ 均为硬边):
  4. C(维持不接线)排除 —— 现状就是本卡的成因,三次无守护修复已实测。

What landed

One mode selector, no duplicated reporting.selfTestMode(argv) reads the mode;
selfTest(mode) takes one gated ? [] : POSITIVE_CONTROLS on the loop it must skip, one
extra success-print branch, and one refusal branch. The problem list, the failure
formatter, the census call and the other three family loops are the same code on both
paths. Implementation cost against ruling item 3, bullet 3: the stop condition was not
reached
— the split needed no duplication of the self-test's reporting logic.

  • --self-test=gated runs RESOLUTION + NEGATIVE + REGRESSION, plus the
    zero-member floor. Wired as root check:swallow-census-controls and run from
    lint.yml beside the sanctioned precedent check:stall-guard-headroom — the same
    shape and the same asymmetry: the self-test leg only, never a bare invocation.
  • Bare --self-test is byte-identical (proof below); --self-test=all is its
    spelling. Print semantics of the bare legs are deliberately untouched — that surface
    belongs to [finding] the #12981 census prints 5 DARK sites as "the repair worklist" when 4 are settled determinations — an annotation cannot move a site out of the bucket #13886, see the serial note.
  • An unknown mode is REFUSED with exit 2 rather than falling through. Without this,
    --self-test=gatd would miss argv.includes('--self-test'), reach report(), exit 0
    and read in a CI log exactly like a self-test that passed.
  • Ruling item 2, the measurement property: the gated run prints the instrument's own
    banner line, now a single constant shared with report() rather than a second copy.

Why POSITIVE stays out, in the file's own terms rather than restated: SELF_TEST_MODES
points at the dark control's recorded why, where batch 2 already turned this
self-test red for doing exactly what the ruling asked. The exclusion is written as
permanent, not pending — repairs move a member from tier dark to tier channelled
and it stays a member, so none of the three wired families can be destroyed by a
successful repair.

DURABILITY_CRITICAL_CALLEES is untouched, no entry was added to
durability-degradation.baseline.json, and the gate vocabulary is unchanged in either
direction (ruling item 3, bullet 2 — this PR must not be used to bring that step forward).

Readings

All on 93aecd5cf (the implementation commit; the two follow-ups touch only PM tooling). Every mutation confirmed on disk before the reading was taken
(injected marker counted and deleted text counted), every restore proved by hashing
the path against its HEAD blob, each harness carrying trap restore EXIT INT TERM with
absolute paths.

runexitverdict line
--self-test=gated on this branch03 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 56 member site(s) total
bare --self-test04 positive, 3 negative, 2 regression, 6 resolution — the base branch's line, byte for byte
--self-test=gatd2x REFUSED: unknown self-test mode

Bare-output identity, measured not asserted. The base blob (e2a7fa5b8) was checked
out over the path, confirmed on disk by hash, run, and restored to the HEAD blob
(71f3ae1e5, verified). cmp on the two captures: identical.

Ablation A — the RESOLUTION family, on the defect it exists for. Reverted
indexFunctionBodies().get to the flat last-wins lookup (marker present 1, anchor
consumed). --self-test=gatedexit 1, four resolution controls firing:

 - resolution control moved: packages/objectql/src/engine.ts :: ObjectQL :: update()
-> expected `ObjectQL`, got ObjectRepository@7620, ObjectRepository@7722, ...
- resolution control moved: ... :: delete() -> got ObjectRepository@12213
- resolution control moved: ... :: transaction() -> got ScopedContext@12677
- resolution control moved: packages/runtime/src/app-plugin.ts :: resolveMappedObjects
:: push() -> expected REFUSAL, got collectBundleActions@457

Bare --self-test → exit 1 on the same tree. ⇒ the wired leg carries a real failure
signal into CI.

Ablation C — the hazard the ruling excluded POSITIVE for, reproduced. Simulated a
successful repair of the dark positive control's site by giving
share-link-service.ts :: resolveToken's telemetry catch a console.error (marker
present 1, original comment text consumed):

runexit
bare --self-test1positive control found NO member: packages/plugins/plugin-sharing/src/share-link-service.ts
--self-test=gated056 members becomes 55, and the gate stays green

⇒ this is the ruling's boundary 1 as a measurement: the full self-test reddens when the
repair programme succeeds
, and the wired subset does not.

Ablation B — reported as a NULL result rather than dropped. Removing the #13459
bare-identifier refusal from the lexical walk landed on disk — marker 1, the deleted
return null; gone — and moved nothing: --json before and after is equal in every
stat (files 2193, guardedWrites 221, refusedShadowed 4, 56 members, empty symmetric
difference on the member set). The site the action-execution regression control pins is
answered a second time by the scope-aware body index, which refuses it too. So the two
departures are defence-in-depth there, and this ablation proves nothing about the
REGRESSION family in either direction. It is recorded because a discarded null ablation is
how a "we exercised that family" claim gets minted from a reading that never happened;
Ablation A is the failure proof.

Two things the wiring forced, both found by running the derived gates

Neither is scope creep: both are consequences of this card's own change, each caught by a
gate on this PR's derived list, and each landed with the repair the gate's own remedy text
names rather than the one that quiets it.

1. scripts/pm/dispatch-gates.mjs — the seam card is now a GATE SCRIPT. Its
--self-test went red in three cases. Wiring check:swallow-census-controls makes
measure-durability-swallow-family.mjs a file some discovered check family runs, so the
"adds or edits a GATE SCRIPT" convention KIND started hitting it — and that card is the
fixture chosen for the one assertion pair that needs the block harvest and --commands to
agree exactly, i.e. a card no convention KIND hits. Repointed at
measure-partial-retirement-annotation.mjs (block 13, commands 13, convention 0, four
node rows — measured), which is the very shape the census copied and which no check
family runs. ⛔ Not repaired by loosening the equality; the comment says so at the
constant. The third case is COMPOUND_ANCHOR_LEDGER: the new selfTestMode argv parser
matches the compound self-test name anchor and is classified accidental: true, which is
what that ledger's own "Maintaining this table" section prescribes — ⛔ explicitly not by
renaming the function to dodge the anchor.

2. scripts/pm/bare-root-worklist.mjs — a FRESH bare-root row. Wiring the family
makes the census's SCAN_ROOT visible to scripts/pm/bare-root-worklist.mjs
as a FRESH, unjudged row, and its --self-test reds until a verdict is recorded (it did,
on the first sweep). Recorded REFUSE-WIDE, measured on this tree in both terms and not
carried from a sibling row: the walk admits every non-test, non-declaration TypeScript
source under the root at four extensions — 2193 of 5755 (38%), numerator from the
instrument's own printed scan count, denominator from git ls-files packages. Same class
and nearly the same ratio as the check:authz-resolver row: a bare-root declaration would
be TRUE and is refused for width alone.

No changeset — skip-changeset

This diff publishes nothing from any package: a root check:* alias, a lint.yml step, a
repo-root measure-* script, and a PM worklist verdict. The precedent is exact —
0079e2585 (#13358), which wired this same family's precedent and touched precisely
.github/workflows/lint.yml + package.json + scripts/measure-stall-guard-headroom.mjs,
carried no changeset. An empty-frontmatter changeset is not the alternative:
scripts/check-empty-changeset.mjs rejects one, and its header records why (an empty
changeset is a real input to changesets/action and can stall a release, which the label
cannot). The label is applied on this PR.

Serial note — #13886 is next on this file

#13886 (same file, print semantics of the DARK worklist) is queued behind this card
(triage 2026-09-01, comment 5486764050) and is deliberately not folded in. That is also
why the bare self-test legs' output is left byte-identical here: changing print semantics
is that card's surface, not this one's. #13886 is not addressed by this PR and remains
open.

Gate record

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
from the real change set (three-dot against merge base e80889095; the tool takes the
change set from git itself, no hand-written path list). Re-derived after each of the two
follow-up commits — the union stayed at 37 families throughout. All 37 were run, and
the union was re-run on the final commit 990649a77:

  • 34 green, including the new check:swallow-census-controls itself,
    check:pm-dispatch-gates (✓ dispatch-gates self-test: 1232 cases pass.),
    check:self-test-wired and check:self-test-workflow-commands — the two the new step
    newly puts this script into the population of — plus
    check:declared-population-live, check:ratchet-remedy-authority,
    check:watch-hint-literal, check:entry-guard, check:parse-guard and
    node scripts/pm/bare-root-worklist.mjs --self-test (OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale, none missing, none contradicted.).
  • 3 NOT MEASURED, all exit 3 and none of them a finding, each quoting its own verdict
    line: check-test-completeness.mjs ("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"),
    check:dual-build-cjs-loads and check:type-check-debt ("PREREQUISITE NOT MET... ⛔
    This is NOT a pass and NOT a finding: nothing was measured"). Structural — they need a
    built workspace or a real test-run log, which CI has and a local sweep does not.
  • 2 were red, both on this card's own consequences, both repaired above:
    scripts/pm/bare-root-worklist.mjs --self-test (FRESH row) and
    check:pm-dispatch-gates (3 of 1232 cases). Both green on the final commit.

Exit codes were captured before any pipe (cmd > log 2>&1; rc=$?), never through one, and
every verdict quoted here is the gate's own printed line rather than a bare $?.


Generated by Claude Code

…me cannot destroy (#13919)
`scripts/measure-durability-swallow-family.mjs` declares four control families
and, measured on `origin/main`, nothing ran any of them: zero references to the
script in `package.json` or `.github/**`, counter-checked against
`measure-stall-guard-headroom` (2 hits) so the zero was a reading and not a
broken query. Meanwhile the resolver those controls pin was repaired three
times with no gate holding any previous repair, and the census's numbers feed
the #12981 repair worklist, so a wrong denominator propagates unwatched.
Adds one lightweight mode selector, `--self-test=gated`, wired as
`check:swallow-census-controls` from `lint.yml` beside the sanctioned precedent
`check:stall-guard-headroom`. The gated run asserts RESOLUTION + NEGATIVE +
REGRESSION plus the zero-member floor -- the families a successful repair
cannot destroy, because a repair moves a member from tier `dark` to tier
`channelled` and it stays a member.
POSITIVE_CONTROLS stays manual, permanently. It pins tier-1 DARK members of the
worklist the repair programme exists to remove; the file's own record shows
batch 2 already turning this self-test red for doing exactly what the ruling
asked. A gate that reddens on success is not a gate.
Bare `--self-test` is byte-identical (`--self-test=all` is its spelling), and an
unknown mode is REFUSED with exit 2 rather than falling through to the census,
which would exit 0 and read in a CI log like a self-test that passed.
…13919)
Wiring `check:swallow-census-controls` makes the census's SCAN_ROOT visible to
the bare-root sweep as a FRESH, unjudged row. REFUSE-WIDE, measured on this
tree: the walk admits every non-test TypeScript source under `packages` (2193
of 5755, 38%), the same class and nearly the same ratio as check:authz-resolver,
so a bare-root declaration would be TRUE and is refused for width alone.
…onest (#13919)
Wiring `check:swallow-census-controls` turns
`measure-durability-swallow-family.mjs` into a GATE SCRIPT, so the
convention KIND now hits it and it can no longer serve as the card where the
block harvest and `--commands` must agree exactly. Repointed at
`measure-partial-retirement-annotation.mjs` — the shape the census copied,
which no check family runs. Also classifies the new `selfTestMode` argv
parser in COMPOUND_ANCHOR_LEDGER as accidental, rather than renaming it to
dodge the anchor.
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 2, 2026
@github-actionsgithub-actionsBot added size/m ci/cd dependencies Pull requests that update a dependency file labels Sep 2, 2026
@baozhoutao
baozhoutao marked this pull request as ready for review September 2, 2026 05:34
@baozhoutao
baozhoutao added this pull request to the merge queueSep 2, 2026
Merged via the queue into main with commit 793065dSep 2, 2026
39 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-13919-swallow-census-gated-controls branch September 2, 2026 05:58
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filesize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@baozhoutao@claude