Repository navigation
fix(scripts): hold check-engine-double-contract --write to the same population floor as the reporting run - #18097
Conversation
…ing run #17099 gave check-engine-double-contract a population floor so a run that read almost nothing REFUSES instead of reporting on the fraction it reached. That floor was spelled inline in report(), and `--write` is a sibling branch of the same dispatch chain: it re-scanned and rewrote both ledgers with nothing in front of it. A scan that silently under-collected, run through the regeneration command this gate's own RETAINED messages prescribe, baked the smaller population into the pinned and seam ledgers as the new truth — the floor protected the reader and left the writer free to destroy the thing being protected. One shared refusePopulationFloor() now turns a fallen floor into an exit, and it is the only thing in the file that does. report() and writeLedger() both call it; writeLedger() calls it before the first writeFileSync, so a refused regeneration leaves the ledgers that were already on disk. Not a second copy of the floor: populationFloorProblem stays the only decider. `--census` deliberately stays out — it reaches no verdict and writes nothing. The floor is over the DERIVED population and never over a ledger's size, so the documented bootstrap still holds: a fresh checkout with the artifacts absent walks the whole tree, clears all four counts, and writes them. A new self-test battery reads this file's own source and pins the wiring: both branches route through the helper, the write call precedes the first writeFileSync, and exactly one place turns a fallen floor into an exit. The 23 existing floor cases all passed while `--write` never called it — driving a pure decider cannot say which branches reach it. The POPULATION FLOORS header's one-package reproduction is re-judged in place rather than deleted: the reading it establishes is unchanged and is why the floors exist, but its `--write` step is now a refusal. Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU Co-authored-by: Claude <noreply@anthropic.com>
|
PM 复核:收下,已 undraft + 武装。 分诊问的是「你取了哪个顺序、是不是第四份拷贝」—— 你给的答案比那个问题更强。 ⭐⭐ 1. 不是第四份拷贝,而且第三份被结构性钉死了本席在分支上逐行读:
⇒ 文件从「一处内联拒绝」变成「一个 helper + 两个调用点」,⛔ 不是三处。 ⭐ 而真正让本席记下来的是 expect('ROUTING — and does it BEFORE the first writeFileSync, not after',
bodyOfFunction('writeLedger').indexOf(REFUSAL_CALL)
< bodyOfFunction('writeLedger').indexOf('writeFileSync('));⇒ 顺序本身被断言了。 谁将来把某个 ⭐⭐ 2. Leg B 才让 Leg A 成为证据 —— 这句话是本轮最该被引用的一句
⇒ ⭐ 那个 15/800 正是 #17099 的 dev 当初量到的塌缩。 没有 Leg B,Leg A 的「没写」可能只是因为那条路径本来就不写;有了 Leg B,「没写」才是地板挡住的。⛔ 本班反复在拦的就是这个:一个只见过不开火的对照,证明不了开关接上了。 3. 账本判定:CORRECT,不需要恢复 —— 而依据是可读的门禁自己的溯源行: ⇒ 当前四个总体全部高于地板,而且高于账本记录的那次派生(+182/+136/+21/+21)。⭐ 若此前某次 4. 还原纪律里的一处细节,值得单独说
⭐ 一个空的哈希输出,在朴素的比较里会和另一个空值相等 ⇒ 「还原成功」。你把空输出判成失败,⛔ 不让它伪装成一致。加上 anchor/marker 分开计数、blob 哈希被观察到移动两次( 5. 三条 out-of-scope,判如你所报
Generated by Claude Code |
Clause-②: no
Closes #17117
#17099 gave
check-engine-double-contracta population floor so a run that read almostnothing REFUSES instead of reporting on the fraction it reached. That floor was spelled inline
in
report(), and--writeis a sibling branch of the same dispatch chain — it re-scannedand rewrote both ledgers with nothing in front of it. The floor protected the reader and left
the writer free to destroy the thing being protected.
What changed
One shared
refusePopulationFloor()is now the only thing in the file that turns a fallen floorinto an exit.
report()andwriteLedger()both call it;writeLedger()calls it before thefirst
writeFileSync, so a refused regeneration leaves the ledgers that were already on diskand says so.
Not a fourth copy — see the ordering note below.
populationFloorProblemstays the onlydecider; the file goes from one inline refusal to one helper with two call sites.
--censusdeliberately stays out: it reaches no verdict and writes nothing (#9747's ruling), so it has
nothing to destroy; the day it writes or decides anything it joins the list rather than growing a
third refusal.
The floor is over the derived population and never over a ledger's size, so the bootstrap both
ledger readers document still holds: a fresh checkout with the artifacts absent walks the whole
tree, clears all four counts, and writes them.
Verdict on today's ledger — CORRECT, nothing restored
Triage pinned this as the prerequisite: if a previous
--writealready baked an under-collectedpopulation, the pin is wrong today and restoring it is part of the fix. It is not wrong.
Measured on the unmodified tree at the branch point (
66e34d14d9), before any edit:Three legs, and the first is decisive rather than circumstantial:
exits 0. The growth direction errors once per row the census finds and the ledger does not; the
loss direction errors once per row the ledger records and the scan no longer sees. A green run
therefore means the ledger's set equals today's census row for row — a baked-down ledger
could not produce it. This is a measurement of the ledger, not an inference about its history.
(+182/+136/+21/+21). A collapsed scan is not what produced this ledger.
with one legitimate 6-row dip (782 → 776 on 2026-09-10). No collapse anywhere in that window.
not an absence claim over all time; legs 1 and 2 do not depend on history at all.
⇒ Nothing was restored, because nothing needed restoring. The ledgers are byte-identical to
origin/mainin this PR — the diff is one file.Positive control —
--writerefuses instead of writing a shrunken ledgerAcceptance ⭐: without this, floor-added and floor-not-added look identical. Run from the committed
state; the under-collection is the same one-package collapse the POPULATION FLOORS header was
measured on (
SCAN_ROOTSrestricted topackages/mcp).Leg A — floor wired, scan restricted.
--writeexits 2 (EXIT_POPULATION_REFUSED):Leg B — ablation, the writer's floor call removed, same restricted scan.
--writeexits 0and rewrites both ledgers:
15 pinned rows where the tree has 800 — the exact collapse #17099's dev measured and the card was
filed on. Leg B is what makes Leg A evidence rather than a tautology.
Restore settled by bytes, ⛔ never by an exit code (the container's
trapcan silently notfire — #17875;
trapis present as a crash-path convenience only and is not the proof):An empty
git hash-objectoutput is treated as FAILURE, not as "nothing to compare", and themutation legs prove they landed by counting the anchor text before and after — an editor's exit
code is not on-disk evidence.
Order taken, and the shape — re-stated because triage asked
This card first, #17118 not touched, per the PM's ruling. #17118 records that the floor
mechanism exists three times under two spellings across the gate family.
This implementation is not a fourth copy of the floor. It adds no new floor anywhere: it
de-duplicates within this file, going from one inline refusal to one helper invoked from two
branches. Net copies of the floor in the tree are unchanged. A self-test case asserts the shape
directly — exactly one place in this file turns a fallen floor into an exit — so a future
branch that grew its own refusal reds rather than passing.
⇒ This leaves #17118 strictly easier, not harder: its consolidation now re-points one helper in
this file instead of two inline blocks. I do not judge that the shared helper had to land
first, and I did not widen.
Self-test — the wiring, not the decider
The 23 existing floor cases all passed while
--writenever called the floor. That is the shape ofthe defect: driving a pure decider cannot say which branches reach it. A new battery
(
Every branch that SCANS routes through the floor (#17117), 6 cases) reads this file's ownsource — same instrument as the existing
PROVENANCE — the pass path in report() still prints itcase — and pins that both branches route through the helper, that the write call precedes the first
writeFileSync, and that exactly one place exits on a fallen floor. A control case asserts the bodyreader finds a body at all, so the four scoped assertions cannot pass vacuously.
Reverse-read — including the zeros
What in the tree does this change make false?
recipe. Its
--writestep now meets a refusal. The reading it was taken to establish isunchanged and is still why the floors exist; the note says which half is history and which half
still holds.
What states that the floor applies only to the reporting run? ZERO outside the gate.
git grepfor the scope phrasing across the tree returns one unrelated hit incheck-undeclared-dep-imports.mjs(its own floors' provenance wording). The only prose that carriedthe scope was inside this gate, and both places are handled above.
What describes this ledger's population? ZERO prose statements of its size. The only external
mentions are three per-file comments
(
plugin-security/src/permission-set-drift.test.ts,permission-set-overlay-discard.test.ts,runtime/src/standalone-stack-seeder-declaration-copy.test.ts) that each describe their own row,not the population — unaffected. The
800and875figures are computed at runtime, never writteninto prose.
Reverse direction — anything that was false and is now true? The two ledger
$commentstrings arethe only places outside the gate naming
--write("Regenerate with … ; never hand-edit"). They weretrue before and remain true: the command is unchanged, it now refuses on a collapsed scan. Both
files are byte-identical in this PR.
Verification
All against
e7427b155c, the final commit.pnpm check:engine-double-contract— exit 0,OK — 875 pinned, 133 in the DEBT ledger, 3 exempt, provenance3685/2732/932/800.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran …→✓ 32 derived famil(ies) accounted for — 32 run, 0 NOT-MEASURED (a DERIVED zero — all 32 recorded an exit code and none of them is 3).node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD— exit 0.grepexit 1 (clean), captured before any pipe.$?captured before any pipe,⛔ never through one.
Repo-wide scans (
pnpm lintand the 51 artifact-roster, 11 wide-population, 14 pending-changesetfamilies and the path-scheduled CI job the derivation names) are CI's runs, declared not run
locally — they are outside the derived set by that tool's own accounting.
Changeset — SKIP, measured
.changesetskipped and theskip-changesetlabel applied (a label, not a body sentence).Measured rather than assumed: the changed path lies inside 0 of the repo's 70 published
package directories, and the repo root package is
private: true. Positive control —packages/objectql/src/engine-delete-dispatch.tsresolves into exactly one published package whosefiles[]is["dist","README.md","CHANGELOG.md"], so the instrument does find a published file whenone exists. Nothing any package ships moves.
验收备注
--census(the third sibling branch) is left alone deliberately, and the reason is in the code:it reaches no verdict and changes no exit code, so it is a reporter with nothing to destroy. Noted
in the helper's doc comment as the criterion for when it would join.
check-type-check-coverage's--re-measure/--lowerbranches may hold thesame shape and that the ordering there was not established. I did not widen into it; it is
[finding] The population-floor mechanism now exists three times under two spellings —
floorProblemin one gate,populationFloorProblemin two more, with the refusal wording re-typed each time #17118's neighbourhood and the PM ruled against widening.Generated by Claude Code