Skip to content

feat(devx): a row selector for measure-self-test-floor --probe (#15759) - #15833

Merged
baozhoutao merged 3 commits into
mainfrom
claude/issue-15759-self-test-floor-probe-row-selector
Sep 5, 2026
Merged

feat(devx): a row selector for measure-self-test-floor --probe (#15759)#15833
baozhoutao merged 3 commits into
mainfrom
claude/issue-15759-self-test-floor-probe-row-selector

Conversation

@claude

@claude claude Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #15759

--probe swept every census row twice and had no way to name ONE. scripts/pm/dispatch-gates.mjs alone was measured at 434.3 s and the full sweep is 183 rows spawned twice, so it does not fit a foreground turn — which is why every single-row reading this instrument has on record was taken by re-driving main()'s loop in a private throwaway. A throwaway is a COPY of the decision the shipped sweep makes (which row, which entry, which budget), and the repair's evidence then comes from the copy while the original ships. That is the class of mistake this instrument's own controls refuse elsewhere: sitesInSource was LIFTED rather than copied on #13874, precisely so a reading and the shipped code could not drift.

What landed

--only PATH (repeatable, --only=PATH accepted, repo-relative or absolute) selects census rows for the probe.

  • Lifted, not copied. probeRows() IS the sweep's loop body — probePlan() then probeEarlyReturn() — and main() calls it on both paths. There is no second copy of the decision to drift. Its plan / probe parameters exist only so a control can COUNT the probe's calls; main() passes neither.
  • Refuses, never sweeps empty. A selector naming no census row exits 2 and lists the nearest rows. nearestRows reads two tiers — rows whose path CONTAINS the whole selector (a bare basename, a directory, a truncated prefix), otherwise only the rows sharing the LONGEST basename prefix, the maximum and never a threshold. A first cut scored summed path parts; measured on this census, one miss then "matched" 181 of 182 rows, and a diagnostic that names everything names nothing.
  • Narrows the PROBE, not the census. The row count, the floor column and the handshake column are printed over the whole population; only hole 2 is restricted, and it announces over how many of how many. A selector that shrank the census would print 1 file(s) under scripts/ dispatch on --self-test, which is false. Excluded rows publish NOT PROBED in --json, because a missing probe key is what a run without --probe publishes.
  • Argv shapes that must refuse rather than widen: --only with no value, --only --probe (the flag taken as the value), --only=, and --only without --probe. Read permissively, --only --probe means "sweep everything" — the outcome that takes hours and looks like success, reached by a typo.
  • The script ships no --help flag (its controls run inline on every invocation and it has no --self-test mode either). Its usage block in the header IS its help text; it is extended, and a USAGE constant now prints on every refusal. The header doc carries a new --only section.
  • classifyHandshake / definitionSpan are untouched.

Measurement

All exit codes captured before any pipe. Wall times are SHARED-BOX seconds under scripts/pm/os-verify-lock.sh, which excludes other locked runs and nothing else.

Inert with no --only — the base file and this one, same tree, same installed worktree, at HEAD 98a0b76:

HEAD_BLOB=9805aeff46dc073023cf46ed115bb6d03b174ce3 BASE_BLOB=b9d6d38dcfe092071bc236c66a22fecbb008ae7e (differ: yes)
ON-DISK after checkout of base: b9d6d38dcfe092071bc236c66a22fecbb008ae7e
BEFORE_EXIT=0
restored to 9805aeff46dc073023cf46ed115bb6d03b174ce3
AFTER_EXIT=0
CMP_EXIT=0 (0 = byte-for-byte identical)
17619 inert-before.txt
17619 inert-after.txt
git diff HEAD --quiet exit=0

One row, through the shipped path. The card's own assumption is honoured: no real sweep over scripts/pm/dispatch-gates.mjs. The row measured is scripts/invoked-as.mjs, whose own --self-test runs in 0.41 s. real 0m58.259s for the whole invocation, of which ~57 s is this tool's unconditional controls plus the static census (a bare node scripts/measure-self-test-floor.mjs in the same worktree: real 0m57.633s) — the selected row itself is the ~1 s remainder, against 183 rows spawned twice for the full sweep. This run and the refusal runs below were taken at d741da9, before origin/main was merged in, when the census held 182 rows; the census is 183 rows at 98a0b76.

⚠ `--only` RESTRICTED this probe to 1 of 182 census row(s). The other
   181 were NOT PROBED, and nothing below is a reading of them.
    selected: scripts/invoked-as.mjs

Hole 2 -- silently defeated by an early `return` in the self-test (MEASURED):
  0 DEFEATED, 1 HELD, 0 ACCIDENT, 0 NOT MEASURED.
    HELD  scripts/invoked-as.mjs -- ✗ invoked-as self-test: selfTest() returned without reaching its verdict,

--json for the same run, which is the "twice" made readable — a baseline run and a mutated run, both reported:

{ "file": "scripts/invoked-as.mjs",
  "probe": { "verdict": "HELD", "entry": "selfTest", "baselineExit": 0, "mutatedExit": 1,
             "mutatedBytes": 196, "mutatedSpoke": true } }
{ "file": "scripts/js-comment-mask.mjs",
  "probe": { "verdict": "NOT PROBED", "why": "excluded by --only" } }

Refusals, exit code quoted from the run itself:

$ node scripts/measure-self-test-floor.mjs --probe --only scripts/invoked-a.mjs      → EXIT=2
measure-self-test-floor: `--only scripts/invoked-a.mjs` names no census row (read as `scripts/invoked-a.mjs`).
  nearest rows by path: scripts/invoked-as.mjs

$ node scripts/measure-self-test-floor.mjs --probe --only                            → EXIT=2
measure-self-test-floor: `--only` was given no value (it is followed by nothing).

$ node scripts/measure-self-test-floor.mjs --only --probe                            → EXIT=2
measure-self-test-floor: `--only` was given no value (it is followed by "--probe").

$ node scripts/measure-self-test-floor.mjs --only scripts/invoked-as.mjs             → EXIT=2
measure-self-test-floor: `--only` selects rows for the PROBE, and `--probe` was not passed. There is no
sweep to restrict, and the census below it is printed whole either way.

Ablation, three legs, trap-guarded, absolute paths, each mutation proven on disk before the run (the removed text goes 1 → 0, the injected marker 0 → 1, the blob differs from the HEAD blob) and each restore proven byte-identical (git hash-object equal to the HEAD blob AND git diff HEAD empty). The unmodified run exits 0; each ablated run exits 1 naming the controls it broke:

HEAD_BLOB=9805aeff46dc073023cf46ed115bb6d03b174ce3
===== LEG refusal        (a missing row returns an empty selection instead of refusing)
ON-DISK removed-text count 1 -> 0 ; injected-text count 0 -> 1 ; blob ca598d7a367ac035cd8550b11e806bd99783b2ba
ABLATED_EXIT=1   SELECTOR CONTROL FAILED lines: 5
  - SELECTOR CONTROL FAILED: a selector naming no row did not refuse (got [])
RESTORED blob=9805aeff46dc073023cf46ed115bb6d03b174ce3 ; git diff HEAD --stat: []
===== LEG selection      (the selection is ignored and the whole population returned)
ON-DISK removed-text count 1 -> 0 ; injected-text count 0 -> 1 ; blob 00a03f0c70e8ce3d0f8f715a368eba7e0ebe0118
ABLATED_EXIT=1   SELECTOR CONTROL FAILED lines: 7
  - SELECTOR CONTROL FAILED: a selector naming one row exactly did not select exactly that row
RESTORED blob=9805aeff46dc073023cf46ed115bb6d03b174ce3 ; git diff HEAD --stat: []
===== LEG argv           (a flag is accepted as the --only value)
ON-DISK removed-text count 1 -> 0 ; injected-text count 0 -> 1 ; blob 17326c5658a85cee2145344f368dba4d4f6413b3
ABLATED_EXIT=1   SELECTOR CONTROL FAILED lines: 1
  - SELECTOR CONTROL FAILED: `--only --probe` took the FLAG as the selector value
RESTORED blob=9805aeff46dc073023cf46ed115bb6d03b174ce3 ; git diff HEAD --stat: []
===== FINAL
final blob=9805aeff46dc073023cf46ed115bb6d03b174ce3 HEAD=9805aeff46dc073023cf46ed115bb6d03b174ce3
git diff HEAD --quiet exit=0

One control in the temp-fixture half of runControls() drives probeRows over a two-row fixture population with one row selected and compares its verdict against a DIRECT probeEarlyReturn call on the same fixture. That is the anti-drift reading: if a private copy of the loop ever grows here, those two verdicts separate.

Gates. node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack derived 28 commands on the merged tree (98a0b76, no STALE TREE warning); all 28 ran and all 28 exited 0. Six of them first read PREREQUISITE NOT MET (exit 3) or ERR_MODULE_NOT_FOUND in the fresh worktree — check-reference-carrier-shape (x2), check-ci-filter-parity, check-closing-keyword-parity (x2), check-comment-mask-corpus, check:driver-memory-census — and were re-run to a real reading after pnpm install --offline; none is reported green on the failed attempt. pnpm check:nul-bytescheck-nul-bytes: OK (scanned 7640 text file(s) -- 7640 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes), and a direct grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' over the file found nothing.

node scripts/pm/check-governed-merges.mjs --test scripts/measure-self-test-floor.mjs on the final one-file list → exit 0, ✅ NOT governed — ordinary queue landing applies to a PR with exactly this file list. git merge-tree --write-tree origin/main HEAD after a fresh fetch → exit 0, no conflict. All 30 open PRs were enumerated through GET /repos/objectstack-ai/objectstack/pulls/N/files; none touches scripts/measure-self-test-floor.mjs, so there are no collisions. scripts/pm/dispatch-gates.mjs (held by #15830 / #15806) was RUN but not touched.

Scripts-only diff, nothing published changes → skip-changeset.

🤖 Generated with Claude Code

https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk


Generated by Claude Code

…5759)

`--probe` swept every census row twice and had no way to name ONE, so every
single-row reading on record was taken by re-driving `main()`'s loop in a
private throwaway -- a COPY of the decision (which row, which entry, which
budget) the shipped sweep makes.

`--only <path>` (repeatable, `--only=<path>` too, repo-relative or absolute)
selects census rows for the probe. Both paths run the same `population()` ->
`probePlan()` -> `probeEarlyReturn()` chain through `probeRows()`, which is the
sweep's own loop body LIFTED rather than copied -- the `sitesInSource` treatment
from #13874, so a single-row reading and the shipped sweep cannot drift.

- A selector naming no census row exits 2 and lists the nearest rows by path
  substring; a part every row carries is not scored. Never a silent empty sweep,
  whose `0 DEFEATED, 0 HELD, 0 ACCIDENT` is the flattering reading this
  instrument exists to expose.
- `--only` narrows the PROBE, not the census: the row count, the floor column
  and the handshake column stay whole, and hole 2 announces over how many of how
  many rows it was measured. Excluded rows publish `NOT PROBED` in `--json`.
- With no `--only` the sweep is handed the population object itself and every
  byte of the output is unchanged (measured: 17,516 bytes, `cmp` clean).
- Controls for all three cases, plus one that drives `probeRows` over a real
  fixture and compares its verdict against a direct `probeEarlyReturn` call --
  the anti-drift reading a private loop copy would break.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…ts (#15759)

A per-part score ranked the right row first and then padded the list with every
row that merely ends in `.mjs` -- measured on this census, a single miss
"matched" 181 of 182 rows, and a diagnostic that names everything names nothing.

`nearestRows` now reads two tiers: rows whose path CONTAINS the whole selector
(a bare basename, a directory, a truncated prefix), and otherwise only the rows
sharing the LONGEST basename prefix with it -- the maximum, never a threshold.
`--only scripts/invoked-a.mjs` now lists exactly `scripts/invoked-as.mjs`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…-selector

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
@claude

claude Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Flipped ready + auto-merge enabled (10:29Z, method: MERGE). All seven required contexts on 98a0b7604 read non-failing: Lint & Repo Gates, TypeScript Type Check, Test Core, Dogfood Regression Gate, Governed Surface Queue Guard success; Build Core, Temporal Conformance (live PG + MySQL) skipped; no other red. git merge-tree --write-tree origin/main <branch> → EXIT=0 against ec0a6e7bd. Watched; on landing #15759 closes.


Generated by Claude Code

@baozhoutao
baozhoutao added this pull request to the merge queue Sep 5, 2026
Merged via the queue into main with commit fd33337 Sep 5, 2026
36 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-15759-self-test-floor-probe-row-selector branch September 5, 2026 10:55
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