Skip to content

Commit 500c1b5

Browse files
fix(devx): assert the seed escape depth a tree-scoped walk is rooted at (#18340)
Fixes #15565 Clause-②: no Reason: no spec surface is narrowed or widened here. The diff is one gate script under `scripts/`; `packages/spec` is read by the gate, never edited. ## What this adds A sixth limb to `check:cross-package-test-inputs`, judged on the SEED a directory descent is rooted at rather than on the names the descent produces. The five existing limbs are package-scoped or name-scoped, and a `readdirSync` descending on a loop variable is neither: it names no literal (limb 3 blind), adds no glob (limbs 4 and 5 blind), and inside a package that already carries a table entry the two package-scoped limbs are already satisfied. So the tree-scoped absence pin the ADR-0049 retirement playbook mandates could land in `packages/spec` with its whole radius unhashed while this gate exited 0 naming nothing. The input was already there: the escape verdict is computed from the seed's DEPTH, and an argument this scan cannot read costs the NAME and keeps the DEPTH. ## The narrowed mandate, in the source Triage ruled 「**先收窄 mandate,再断言收窄后的半径**」 and the maintainer's batch ruling returned the card to the queue on the grounds that it restores an invariant with no product-semantics fork. The narrowed mandate is written into the gate's own header docblock (not only here), and it is what the limb asserts: > A tree-scoped pin descends from NAMED ROOTS, and every root it descends from is a directory some declared glob REACHES — as is every directory below that root. It does not descend from the repo root itself. Stated at the grain the limb judges at: declaring one FILE under `docs/audits/` reaches INTO `docs/` and no further, so a walk rooted at `docs/` is judged by its children. The header records both bounds it accepts (directory REACH rather than file coverage; dot-directories skipped as the pins skip them). ## Measurements — every one paired, none recalled Baseline re-taken on `objectstack-ai/objectstack` at `a09725dde` (today's `main`), because the card's readings were `8e18931dd`. Each limb was fired by one anchored mutation, the gate's exit code captured to disk before anything read it, and each file restored by blob equality against HEAD plus an empty `git diff HEAD`. | limb | firing mutation | exit | |---|---|---| | 1 escaping package, no entry | delete the `@objectstack/metadata-protocol` entry | 1, names the package | | 2 stale entry | add an entry for a non-escaping package | 1, names it stale | | 3 named path no glob covers | add a quoted `scripts/js-comment-mask.mjs` to a test | 1, names path and test | | 4 glob nothing holds | add a glob to the entry AND to `turbo.json` | 1, names the glob | | 5 `turbo.json` missing input | delete one `$TURBO_ROOT$` input | 1, names the input | | **6 the blind spot** | add one undeclared root to the live pin's walk | **0, names nothing** | That last row is the card's claim, re-taken rather than recalled. The same mutation on this branch: - **RED** — one root (`docs`) added to the live #15513 pin's folded array and nothing else: exit 1, naming the seven `docs/` subtrees no glob reaches, and NOT `docs/audits`. - **GREEN** — the same edit plus `docs/**` on the entry and in `turbo.json`: exit 0, and the printed walked-root count moves 13 to 14. The green is a root that was JUDGED, not one that stopped resolving. - **REVERSE CONTROL** — an anonymous descent added to a test in another package and rooted INSIDE it: exit 0, count still 13. Moving only the ROOT of that same descent out of the package reds. One file, one descent, one variable — which is what separates this from a limb that reds on directory walks in general. - **ledger staleness** — an accepted radius nothing owes reds in the same pass, so the ledger can only shrink. Ablation discipline: no `sed -i` / `perl -i`. Every mutation went through an anchored replacement that exits non-zero when the anchor is absent or not unique, printing the occurrence-count delta and the byte-length delta; every restore is proved by `git hash-object` equality with the HEAD blob and an empty `git diff HEAD`, never by an exit code; every driver carries `trap … EXIT INT TERM`. ## What the limb accepts today, and why it is not the allowance the ruling refused `ACCEPTED_WALK_RADII` records THREE pre-existing census and corpus sweeps in other packages — none of them a retirement pin, each already carrying its own written bound in its test's header. The MANDATED shape is enforced from the first run: the live pin's five roots are all reached by `@objectstack/spec`'s globs, and a new pin whose root they do not reach reds. Option C — a dated allowance for the mandated shape — is what triage refused, and is not what this is. Buying the three radius widenings instead would be three cost decisions nobody has ruled on, in three packages outside this card. ## A defect this branch found in its own first draft The ledger originally spelled three test paths and one nested root whole, and named the bare recursive packages glob in backticks inside a reason string. `scripts/pm/dispatch-gates.mjs` reads every quoted span in a gate's MODULE BODY as a path that gate watches — a backticked span INSIDE a quoted sentence included — so those four literals put five watch hints on this gate that it does not read, and two of them turned pins red in `check:pm-dispatch-gates`. Rows are now segments joined at runtime and reasons name globs in words. Measured both sides: this gate's hint population is 140 with 0 declared here, on `main` and on this branch alike. ## Gates `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` derived 33 runnable commands for this path. All 33 run green. The `--ran` reconciliation and the NOT-MEASURED families CI owns are listed in the dispatch report. No changeset: nothing published moves. Measured rather than assumed — 70 manifests carry a `files[]`, none names anything under the repo-root `scripts/` directory, and the positive control is that all 70 name `dist`. ## Acceptance notes - `repoRelativeLiterals()`'s top-level alternation is `packages|apps|examples|content|scripts|skills` — it has no `docs`, while `docs/...` IS a declarable glob (`@objectstack/spec` declares one audit file there). So a test that quotes a whole `docs/...` path is invisible to the flat collector, the same shape as the missing `skills/` the gate's own header records. Measured with a lit control: the `docs/` literal collects nothing, the `scripts/` literal collects. Filed separately rather than widened here — it is a different limb's data set. - `symlinkSync` is absent from `NON_DESCENT_CALLEES` while its siblings `cpSync` / `renameSync` / `rmSync` are present, so a symlinked directory reads as a walk root. On this tree that is `scripts` for `@objectstack/spec`, already declared and arguably a real input (the test runs a build through that symlink). Noted, not filed: no PR and no author is heading for this file. Authored by the `domain:devx` executor seat in session `session_017ef78bLdybu3AffehKkhfk` (https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk) — recorded in prose because this body was edited after creation, and the edit channel appends its own footer block. --- _Generated by [Claude Code](https://claude.ai/code)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3dbb49c commit 500c1b5

1 file changed

Lines changed: 659 additions & 4 deletions

File tree

0 commit comments

Comments
 (0)