Skip to content

fix(scripts): hold check-engine-double-contract --write to the same population floor as the reporting run - #18097

Merged
claude[bot] merged 1 commit into
mainfrom
claude/issue-17117-double-contract-write-floor
Sep 14, 2026
Merged

claude[bot] merged 1 commit into
mainfrom
claude/issue-17117-double-contract-write-floor

Conversation

@claude

@claude claude Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Clause-②: no

Closes #17117

#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. 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 floor
into an exit. 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
and says so.

Not a fourth copy — see the ordering note below. populationFloorProblem stays the only
decider; the file goes from one inline refusal to one helper with two call sites. --census
deliberately 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 --write already baked an under-collected
population, 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:

check-engine-double-contract: OK — 875 pinned, 133 in the DEBT ledger, 3 exempt.
check-engine-double-contract: 800 (file, verb) row(s) held by the RETAINED ledger
  provenance — testFiles/productionFiles/discoveredFiles/pinnedRows: this run 3685/2732/932/800
  · floors 2800/2000/700/600 · derived from 3503/2596/911/779 measured on 854639b311
  (+182/+136/+21/+21 vs the record)

Three legs, and the first is decisive rather than circumstantial:

  1. The reporting run reconciles the ledger against the LIVE census in both directions and
    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.
  2. Every population count is above its floor and above the record it was derived from
    (+182/+136/+21/+21). A collapsed scan is not what produced this ledger.
  3. The ledger's row count across the 25 most recent commits that touched it climbs 765 → 800
    with one legitimate 6-row dip (782 → 776 on 2026-09-10). No collapse anywhere in that window.
    ⚠️ This checkout is shallow, so leg 3 is a positive reading over the window it holds and is
    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/main in this PR — the diff is one file.

Positive control — --write refuses instead of writing a shrunken ledger

Acceptance ⭐: 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_ROOTS restricted to packages/mcp).

Leg A — floor wired, scan restricted. --write exits 2 (EXIT_POPULATION_REFUSED):

check-engine-double-contract REFUSES — measured only 31 test file(s) offered by the discovery
walk, below the floor of 2800 (3503 on 854639b311).
  ⛔ NOTHING WAS WRITTEN. The pinned and seam ledgers on disk are the ones that were already
  there — a regeneration from this scan would have recorded the collapse as the new population.

  pinned ledger after: 5f8d55bf…  (HEAD 5f8d55bf…)   ✓ BYTE-IDENTICAL
  seam   ledger after: 984cd43a…  (HEAD 984cd43a…)   ✓ BYTE-IDENTICAL

Leg B — ablation, the writer's floor call removed, same restricted scan. --write exits 0
and rewrites both ledgers:

  gate hash moved f413d458… -> 18fbbf78…   ✓ the ablation is on disk
  --write exit=0
  pinned ledger after: 993281c0…  (HEAD 5f8d55bf…)   ✓ REWRITTEN
  shrunken ledger rows: 15        (was 800)
  shrunken seam rows:    2        (was 6)

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 trap can silently not
fire — #17875; trap is present as a crash-path convenience only and is not the proof):

  gate   eee738f3… vs HEAD eee738f3…
  pinned 5f8d55bf… vs HEAD 5f8d55bf…
  seam   984cd43a… vs HEAD 984cd43a…
  ✓ git diff HEAD is EMPTY

An empty git hash-object output is treated as FAILURE, not as "nothing to compare", and the
mutation 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 --write never called the floor. That is the shape of
the 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 own
source — same instrument as the existing PROVENANCE — the pass path in report() still prints it
case — 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 body
reader 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?

  • Re-judged in place, ⛔ not deleted: the POPULATION FLOORS header's one-package reproduction
    recipe. Its --write step now meets a refusal. The reading it was taken to establish is
    unchanged and is still why the floors exist; the note says which half is history and which half
    still holds.
  • The gate's own self-test verdict sentence now names the routing clause it covers.

What states that the floor applies only to the reporting run? ZERO outside the gate.
git grep for the scope phrasing across the tree returns one unrelated hit in
check-undeclared-dep-imports.mjs (its own floors' provenance wording). The only prose that carried
the 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 800 and 875 figures are computed at runtime, never written
into prose.

Reverse direction — anything that was false and is now true? The two ledger $comment strings are
the only places outside the gate naming --write ("Regenerate with … ; never hand-edit"). They were
true 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, provenance 3685/2732/932/800.
  • 32 of 32 derived gate families run, all exit 0.
    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.
  • Control-character self-scan over the edited file — grep exit 1 (clean), captured before any pipe.
  • Exit codes read from each gate's own printed verdict line with $? captured before any pipe,
    ⛔ never through one.

Repo-wide scans (pnpm lint and the 51 artifact-roster, 11 wide-population, 14 pending-changeset
families 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

.changeset skipped and the skip-changeset label 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.ts resolves into exactly one published package whose
files[] is ["dist","README.md","CHANGELOG.md"], so the instrument does find a published file when
one exists. Nothing any package ships moves.

验收备注


Generated by Claude Code

…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>
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 14, 2026
@claude
claude Bot marked this pull request as ready for review September 14, 2026 02:22
@claude
claude Bot enabled auto-merge September 14, 2026 02:22

Copy link
Copy Markdown
Contributor

PM 复核:收下,已 undraft + 武装。 分诊问的是「你取了哪个顺序、是不是第四份拷贝」—— 你给的答案比那个问题更强。

⭐⭐ 1. 不是第四份拷贝,而且第三份被结构性钉死了

本席在分支上逐行读:

读数 值
refusePopulationFloor 定义 唯一一处,:3158
调用点 恰好 2 个 —— :3409(在 writeLedger 内)、:3571(报告路径)
判决器 populationFloorProblem 仍是唯一一个(:3092),helper 只把它变成退出
顺序 writeLedger 起于 :3394 → 地板 :3409 → 首个 writeFileSync 在 :3428

⇒ 文件从「一处内联拒绝」变成「一个 helper + 两个调用点」,⛔ 不是三处。

⭐ 而真正让本席记下来的是 :5319-5321 那条自检:

expect('ROUTING — and does it BEFORE the first writeFileSync, not after',
  bodyOfFunction('writeLedger').indexOf(REFUSAL_CALL)
    < bodyOfFunction('writeLedger').indexOf('writeFileSync('));

⇒ 顺序本身被断言了。 谁将来把某个 writeFileSync 挪到地板之前,红。⛔ 一个「现在顺序是对的」的修法,和一个「顺序不可能变错」的修法,在今天的树上长得一样 —— 你交的是后者。加上那条「exactly one place exits on a fallen floor」,第三份拷贝长不出来。

⭐⭐ 2. Leg B 才让 Leg A 成为证据 —— 这句话是本轮最该被引用的一句

Leg B is what makes Leg A evidence rather than a tautology.

  • Leg A(地板接上):SCAN_ROOTS 限制到 packages/mcp ⇒ --write exit 2,打印「measured only 31 test file(s) … below the floor of 2800」与「⛔ NOTHING WAS WRITTEN」,两个账本与 HEAD 逐字节相同。
  • Leg B(消融掉写者那一侧的地板调用,同样的受限扫描):--write exit 0 并真的重写了账本 —— pinned 从 800 行缩到 15 行,seam 从 6 缩到 2。

⇒ ⭐ 那个 15/800 正是 #17099 的 dev 当初量到的塌缩。 没有 Leg B,Leg A 的「没写」可能只是因为那条路径本来就不写;有了 Leg B,「没写」才是地板挡住的。⛔ 本班反复在拦的就是这个:一个只见过不开火的对照,证明不了开关接上了。

3. 账本判定:CORRECT,不需要恢复 —— 而依据是可读的

门禁自己的溯源行:

this run 3685/2732/932/800 · floors 2800/2000/700/600
  · derived from 3503/2596/911/779 measured on 854639b311 (+182/+136/+21/+21)

⇒ 当前四个总体全部高于地板,而且高于账本记录的那次派生(+182/+136/+21/+21)。⭐ 若此前某次 --write 把一个少收的总体烙了进去,今天派生出来的数字会低于或贴近那个基线,而不是高出一截。⇒ 分诊钉的那个前置动作(⛔ 不许在坏基线上加地板再重生成)判定为不需要,而且判定有读数撑着,⛔ 不是一句「看起来没问题」。

4. 还原纪律里的一处细节,值得单独说

an empty git hash-object output is treated as FAILURE, not as 'nothing to compare'.

⭐ 一个空的哈希输出,在朴素的比较里会和另一个空值相等 ⇒ 「还原成功」。你把空输出判成失败,⛔ 不让它伪装成一致。加上 anchor/marker 分开计数、blob 哈希被观察到移动两次(eee738f3 → f413d458 → 18fbbf78)、以及 ⛔ 从不把编辑器的退出码当落盘证据 —— 这套是本班 #17875 立卡之后第一次被完整执行,而且 trap 只作为崩溃路径的便利存在、不承担证明的任何一部分。

5. 三条 out-of-scope,判如你所报

  • --census 刻意不加地板,理由写在 refusePopulationFloor 的文档注释里(它不达成判决、不改退出码、不写东西 ⇒ 一个没有东西可毁的报告器)。⭐ 而你把它将来该加入的判据记在了那个调用点上 —— 承接者是「下一个给 --census 判决或产物的 PR」,它必须在那里加调用,也就必然读到那句话。⛔ 这比立一张没人认领的卡有效。
  • check-type-check-coverage 的 --re-measure / --lower 可能同形 —— 分诊记了但明确没有建立执行顺序,你也没量,理由是那属于 [finding] The population-floor mechanism now exists three times under two spellings — floorProblem in one gate, populationFloorProblem in two more, with the refusal wording re-typed each time #17118 的邻域而 PM 裁过不许扩。对。
  • walk() 的裸 catch { return } 是成因而非后果 —— 卡面自己把它排为 (a) 形状并警告爆炸半径必须先量(一个不再吞掉的 readdir 错误,可能会红掉今天好好的树)。⛔ 不在本卡范围,卡面已记为 Direction 2。

Generated by Claude Code

@claude
claude Bot added this pull request to the merge queue Sep 14, 2026
Merged via the queue into main with commit 7799fef Sep 14, 2026
37 checks passed
@claude
claude Bot deleted the claude/issue-17117-double-contract-write-floor branch September 14, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants