Uh oh!
There was an error while loading. Please reload this page.
fix(pm): fold H22 closed-card pm:* residue into the H39 census as a count - #14101
Merged
Conversation
…ount Ruled 2026-08-31 (批 #13): closed-card pm:* residue is archive, not state, made harmless reader-side by open-scoped queries. The rendered patrol body was saying both things at once — the census clause said no cleanup is owed while H22 filed a row per member of that same population (94 of a 247-row sweep, 38%). H22 keeps its predicate, window and floor; what changes is the disposition of a positive verdict: it becomes a count in the reserved census section instead of a finding row. It therefore leaves HALF_STATE_FAMILY_BAND, the same as the other reserved-section legs (H17/H39/H40), and the coverage scan pins that in both directions. The predicate was never wrong and nothing here claims otherwise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Msg17tAHJ3jVTYFgHydCm2
os-sam
marked this pull request as ready for review
September 1, 2026 05:33
os-sam
enabled auto-merge
September 1, 2026 05:33
os-sam
commented
Sep 1, 2026
Collaborator
Provenance — flipped ready and armed auto-merge by the dispatching seat (skills-lane PM, session Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#14072
One rendered patrol body was telling a reader two incompatible things about one population: the H39 census clause said closed-card
pm:*residue is archive owed no cleanup, while H22 filed a finding row per member of that same population — 94 of the sweep's 247 rows on the filing card's measurement, 88 of 227 on this container's own run today. This PR folds H22 into the census as a COUNT, which is the card's first form and triage's third-tier adjudication.Premise step — the mandatory one, and it HOLDS
The adjudication made the fold conditional on a falsifiable premise: that 批 #13 was ruled on the REASON (readers scope
pm:*queries to open cards) rather than on the then-enumerated batch of stale archives, and that it reserved no fresh-residue window. I read the ruling text on the decision card that produced the census clause, #13605, plus its two census neighbours #13526 and #13901, before writing any code.Maintainer ruling, 2026-08-31, 第 6 场总监席决裁批 #13, verbatim and untranslated:
The recorded operative reasoning on the same thread, also verbatim:
Verdict: the premise HOLDS, on three independent readings of that text:
state:open过滤」. 「巡检」 is the patrol itself, and 「一律」 admits no exception.The earlier round on #13605 left this open deliberately — its ACCEPT recorded the H22 question for a veto window and said a one-line follow-up on its own card was the right route. This is that card.
H22's own counter-argument is answered, not deleted
H22's section header carried an argument that predates the ruling and was undefeated on its own terms. It is kept WORD FOR WORD in the file, and the ruling's effect on it is now stated in the same header rather than left for a reader to infer:
The header now continues:
It also records why the 3-day window could not survive as a row boundary: the ruling's reason reaches a two-hour-old residue exactly as it reaches an August one, so the window was cutting one archive into a part that got ninety-four rows and a part that got a number.
⛔ Not claimed
The H22 predicate was never wrong. All 94 rows were correctly computed, and the classifier's SELECTION is unchanged — closed gate, dated floor,
PM_RESIDUE_LABELSall decide exactly the same cards, and the original selection cases are kept in the suite, re-expressed against the labels. What changed is the DISPOSITION of a positive verdict.What the diff does
h22ClosedCardPmResiduereturns the residue LABELS instead of a finding sentence. The imperative it used to return prescribed "Strip thepm:*state label(s)" — the write 批 [WIP] Add Chinese version of the documentation #13 refused by name — so it could not be left in the file as prose nobody renders. A self-test case pins that no strip imperative can survive inside the classifier.h22FreshResidueTallycounts carriers and the per-label breakdown over the closed cards the sweep ALREADY holds. Zero extra requests. It carriesreadbesidecardsso a clean pass and an unread pass stay different facts (check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690).renderClosedResidueCensustakes the tally and renders it as one clause of the SAME sentence. Still one line, still informational, still no glyph and no imperative. It renders even when the census leg failed, because the two readings come from two passes and dropping one that WAS taken is check:react-declaration-parity 是唯一没接进任何 workflow 的源码审计门禁,且无 MANIFEST 时静默 skip 退出 0 —— 它现在永远不可能红 #4690 inside the section that exists to refuse it.familyRegistryCoveragepins it from both sides:missingcatches a restored push with no band,extracatches a restored band with no push. That is a stronger guarantee than theinventoryband it gave up, where it was first in line to be trimmed.Live before/after, real board data, this container
Two full markdown sweeps,
node scripts/pm/check-half-states.mjs --format=markdown, both exit 0 — BEFORE onorigin/mainatdda969cd7in a comparison worktree, AFTER on this branch at649d18410.H22ledger rowinventory / 90 computed / 0 renderedinventorylast: H22's 90 computed rows rendered 0 before this change, so removing them frees nothing the trim was giving to anyone else. The ±1 rendered-row difference above is run-to-run board drift (H2 fell 35 to 31 and H8 5 to 3 between the two sweeps), not an effect of the fold. What the fold actually removes is 96 computed rows — 41.7% of this run's corpus — one 90-row ledger entry that rendered zero, one family from the trim callout, and the contradiction the card filed.The census line, before and after, rendered live:
BEFORE:
AFTER:
The 88 cards that used to be 88 rows are the same 88 cards, now a number in the sentence that explains why they are not rows.
Self-test
node scripts/pm/check-half-states.mjs --self-test— BEFORE2017 cases passexit 0 (measured onorigin/mainatdda969cd7in a comparison worktree); AFTER2062 cases passexit 0. +45 cases.Ablation — three legs, each proven on disk, each restore blob-proven
The implementation was COMMITTED first, so every restore had a real commit to return to. Each leg proved the mutation landed by counting the injected spelling against the original one (never a bare
--stat, never the editor's exit code), restored withgit checkout HEAD -- ABSOLUTE_PATH(never a baregit checkout -- path, which reads the index a checkout-from-ref has already written), and proved the restore by blob-hash equality against the HEAD blob plus an emptygit diff HEAD— never by an exit code. The harness carried atrapon EXIT/INT/TERM. No rebuild leg applies: this is a standalone.mjsrun directly by node and resolved by path, with nodist/and no package build between the source and the self-test.every emitted family carries a bandnamesH22;the sweep pushes no H22 row any moreflips trueH22back in the band registryno band names a family the sweep never emitsnamesH22, the SECTION-family pin flips, and the ledger's folded-family pin flipsControl before and after the run: blob
d01cf419f930cd0f863f5bcd299fe75f03d5cbefequals the HEAD blob,git diff HEADempty, self-test2062 cases passexit 0.Gates
Derived from the real change set after the last commit —
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, exit 0, at649d18410(the script reads the merge-base change set itself; no hand-built path list). 19 derived. Every exit code captured by redirecting to a file BEFORE reading it, never through a pipe.17 exit 0:
check-ci-filter-parity·check-closing-keyword-parity·check-cross-package-test-inputs(both spellings) ·check-shard-attestation·bare-root-worklist --self-test·check:pm-half-states(2062 cases pass) ·check:pm-dispatch-gates(1090 cases pass) ·check:nul-bytes(75 self-test assertions, then 7,702 text files, no raw control bytes) ·check:agent-test-spelling·check:bash32-floor·check:cli-command-ids·check:entry-guard·check:parse-guard·check:partof-closing-keyword --self-test(28 cases) ·check:pnpm-filter-targets·check:watch-hint-literal.2 NOT MEASURED, each self-classifying, neither a red:
node scripts/check-partof-closing-keyword.mjsexits 2NOT WIREDwith no PR body in the environment — itspnpmspelling is the--self-testabove and exits 0, and this body was checked against the predicate separately;node scripts/check-test-completeness.mjsexits 3 and its own text instructs the local family runner to record NOT MEASURED.Plus, beyond the derived family:
pnpm lint— repo-wideeslint . --no-inline-config, NO narrowing — exit 0 in 65s under the shared verify lock, and a direct control-byte grep over the edited file, empty. The live sweep itself ran three times from this container, exit 0 each time.The edited file is a gate script, so its own suite is owed beyond the derived family: it has no
*.test.tsanywhere in the tree (checked bygit grepfor its filename) — its suite IS the--self-testabove, run at every stage.Scope
One file,
scripts/pm/check-half-states.mjs. No workflow change was required. Scripts-only, publishing nothing from any package, soskip-changesetis applied and no changeset is added.Generated by Claude Code
Generated by Claude Code