Skip to content

fix(devx): give affected-docs' route walk a PATH, not a basename (#11866) - #12002

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-11866-affected-docs-basename-arms
Aug 25, 2026
Merged

fix(devx): give affected-docs' route walk a PATH, not a basename (#11866)#12002
os-steve merged 1 commit into
mainfrom
claude/issue-11866-affected-docs-basename-arms

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes#11866

scanRouteSurface's walk handed isTestFilee.name — a basename — so the
__tests__ / __mocks__ / __fixtures__ arm, which requires a /, could never match
there. Only the *.test.* / *.spec.* arm did any work, and the directory exclusion the
function documents was not happening for either consumer of that walk: the bridge's
own registrar discovery, or the #11178 ceiling population filled in the same pass.

The remedy, and the question the card declined to rule

The card explicitly left open "whether the walk should exclude these directories at
all — the ceiling in PR #11865 arguably wants the widest possible population."

Resolved: exclude, from both consumers. Not on taste — on what the ceiling's verdict
means. A row counted remediable by discovery is a claim that widening the filename
convention
would reach it, and no widening of that convention may legitimately admit a
test double. A witness under __tests__/ would therefore move a row into remediable
against a remedy nobody can take — precisely the conflation bridgeCoverageFrom's split
exists to end ("it aimed a whole card at widening a recognizer that was never the
constraint"
). Two supporting measurements:

  • The superset invariant survives. Both populations come off this one walk, so they
    narrow together and reachable still cannot exceed the ceiling.
  • No ratchet moves.check-affected-docs.mjs exits non-zero on brokenScan alone —
    the 45/221 ratio and the 82-tail ceiling are reported, never gated. There is no
    shrink-only number here to move down.

Route (a) from triage — pass the walk-relative path — over route (b) (basename against
the file arms, joined path against the directory arms): isTestFile is defined over a
path, its docblock says so, and all 14 of its existing self-test cases pass one. (b)
would enshrine a two-convention contract that nothing pins.

Measurements

The card's "0 live" claim, re-measured on d63b01436 (it was taken on 589758d22,
before #11865 landed): still exactly 3 files, still 0 matching REGISTRAR_FILE_RE or
LEDGER_FILE_REhono/src/__mocks__/runtime.ts, cli/src/utils/__tests__/server-body.ts,
service-datasource/src/__tests__/entitled-caller.fixture.ts. Latent, not live: confirmed.

And the half the card did not measure — the ceiling.sourceFiles admits any file, not
just convention-matched ones, so a test-dir file declaring a path: would inflate the
ceiling without ever matching REGISTRAR_FILE_RE. Measured directly: --bridge-coverage
and --bridge-coverage --json are byte-identical across this change (12 registrar
files · 43 tails · 82-tail ceiling · 45/177 reach · 14/56/107 causes). The dormant-hole
framing holds for both halves.

"Passing rel is safe" — falsified in the loose direction, and it holds. Of the 4625
.ts files under packages/**: 3 excluded-by-path-but-not-by-basename, 0 the other
way. The file arms are anchored (^|/), so a basename they match is matched inside a path
too — reordering rel ahead of the test is a strict tightening of this walk.

The other callers of isTestFile, swept (the card did not): it is module-local, never
exported, and the script is only ever spawned. Three call sites — the walk (basename,
broken), the --self-test cases (full paths, correct), and the changed-file loop over
git diff --name-only output (full paths, correct). Only the broken one is touched, so
the fix cannot break a caller that was already passing a path.

The pin, and why it is not vacuous

⚠️ The live population is zero, so a pin built from real repo paths would pass just as
green with the bug in place and pin nothing. The fixtures are therefore chosen to be
files the basename test admits and the path test excludes__tests__/x-route.ts
carries no .test. / .spec. infix, so under the old call site it was walked, matched
REGISTRAR_FILE_RE, and a test double contributed production route tails.

The walk is split out as walkSourceFiles(root, readDir)readDir injectable for the
same reason packageRootOf's hasPackageJson is — so the pin walks the call site
against a fake tree, not the predicate. That matters: the existing self-test pins
isTestFile with full paths and is green either way; the function was never the broken
half.

Red before, green after, observed on disk in both directions. The one call-site
argument was mutated back to e.name under a trap … EXIT INT TERM, with the mutation
confirmed by anchored grep -c on both the injected and the removed text (the first
attempt was a silent no-op — a perl\Q…\E anchor with pre-escaped parens matched
nothing and exited 0; the on-disk check caught it, and that reading was discarded):

leganchored on-disk check--self-test
mutated (pre-fix argument)fixed form 0 · buggy form 1FAILED, 9 case(s) — 4 registrar files and 6 source files against the 1 and 2 asserted
restoredfixed form 1 · buggy form 0 · git status clean✓ 451 cases pass.

--bridge-coverage under the mutation is identical to the pre-fix baseline, which is the
same zero-live fact from the other side.

#11857 — checked for collision, and there is none

#11857 is the sibling gap in the same function (the patterns: isTestFile excludes
neither test/fixtures/*.ts nor *.bench.ts, plus a larger evidence-based admission
route). Not fixed here. The two are disjoint on today's tree — measured: all three
files #11857 enumerates are admitted both before and after this change. They are also
complementary, in one direction: test/fixtures/*.ts is itself a path-shaped pattern,
so adding it to isTestFile while this call site still passed a basename would produce
another dead arm — the identical failure. This PR is a prerequisite for #11857's cheaper
half, never a competitor to it. Textually, #11857 would edit the predicate body and may
extend walkSourceFiles; that is a rebase touch, not a semantic conflict.

Verification

Run at ad9307722, the branch head.

  • node scripts/docs-audit/affected-docs.mjs --self-test✓ affected-docs self-test: 451 cases pass.
  • All 12 gate families derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no hand-written path list — it reads the change set off the merge base itself), plus check:nul-bytes, green. Their own verdict lines, not bare exit codes:
    • ✓ check-affected-docs451 cases pass. · ✓ check-drift-comment: 56 cases pass across 5 fixture diff(s).
    • ✓ check-self-test-wired: every one of the 127 script(s) CI runs that ship a --self-test has that self-test run by CI.
    • ✓ check:entry-guard: 156 scripts/ file(s) · ✓ check:parse-guard: 155 scripts/ file(s)
    • ✓ check-governed-merges --self-test: 129 assertions · ✓ check-pnpm-filter-targets --self-test: 40 assertions
    • ✓ check-agent-test-spelling: 0 violations · ✓ docs-accuracy-audit scope is in sync
    • OK: all 96 declared cross-package glob(s)… · OK: 16 package(s) read outside themselves…
    • check-nul-bytes: OK (scanned 6661 text file(s) … no raw ASCII control bytes)
  • Repo-widepnpm lint (eslint . --no-inline-config) run in full, not narrowed — clean, 55s under the shared verify lock.

No changeset: this edits a CI-internal script and releases nothing — the case
lint.yml names as textbook skip-changeset. Label applied and read back.


Generated by Claude Code

`scanRouteSurface`'s walk handed `isTestFile` `e.name`, so the
`__tests__` / `__mocks__` / `__fixtures__` arms -- which require a `/` --
could never match there. Only the `*.test.*` / `*.spec.*` arm did any
work, and the directory exclusion the function documents was not
happening for either consumer of that walk: the bridge's own registrar
discovery, or the #11178 ceiling population it fills in the same pass.
Split the walk out as `walkSourceFiles(root, readDir)` and test the
walk-relative path. Measured as a strict tightening rather than assumed:
of the 4625 `.ts` files under `packages/**` on d63b014, 3 were admitted
by the basename test and are excluded by the path test, and ZERO go the
other way -- the file arms are anchored `(^|/)`, so a basename they match
is matched inside a path too.
The self-test could not see this: it pins `isTestFile` with full paths,
and the predicate was never the broken half. The new cases walk a fake
tree through the call site, with fixtures chosen for non-vacuity -- the
live population is zero, so a pin built from real paths would pass just
as green with the bug in place.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 497ded78018ece3edd58c94405831b8fd9f198d3packageMentionDocs.

@os-steve
os-steve marked this pull request as ready for review August 25, 2026 04:34
@os-steve
os-steve enabled auto-merge August 25, 2026 04:35
@os-steve
os-steve added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 1620c1dAug 25, 2026
33 checks passed
@os-steve
os-steve deleted the claude/issue-11866-affected-docs-basename-arms branch August 25, 2026 04:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-steve@claude