Skip to content

fix(devx): print the importer's real repo-relative path in the prerequisite advisory - #14217

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-13826-prerequisite-command-path
Sep 1, 2026
Merged

baozhoutao merged 1 commit into
mainfrom
claude/issue-13826-prerequisite-command-path

Conversation

@claude

@claude claude Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Fixes #13826

scripts/import-prerequisite.mjs derived the gate name from the importer's basename and then interpolated it into a hard-coded scripts/ directory. That basename is correct for the 42 importers under scripts/** and wrong for the three under packages/lint/scripts/**.

Premise re-verified on this tree, not inherited from the card

The card measured on a pre-#13983 branch. #13983 (exit-code reclassification, PR #14009) has since landed in the same output region, so the advisory now carries exit 3. Re-measured here at merge base 24b66352 with node_modules genuinely absent — the defect survives that change untouched:

$ node packages/lint/scripts/check-doc-formula-expressions.mjs     -> EXIT=3
  `node scripts/check-doc-formula-expressions.mjs > /tmp/check-doc-formula-expressions.log 2>&1; echo "EXIT=$?"`.

$ node scripts/check-doc-formula-expressions.mjs                   -> EXIT=1
  Error: Cannot find module

That is the whole cost, and it is worse than a cosmetic path. The banner exists because the reader is already confused about an exit code; it handed them a third failure wearing a finding's exit 1, which reads as an unrelated breakage rather than as a typo in the banner.

Before / after

importer before after
packages/lint/scripts/check-doc-formula-expressions.mjs node scripts/check-doc-formula-expressions.mjs … (no such file) node packages/lint/scripts/check-doc-formula-expressions.mjs … (runs)
scripts/check-ci-filter-parity.mjs node scripts/check-ci-filter-parity.mjs … byte-identical

The scripts/** advisory is unchanged as a whole file, not merely by eye — same sha256 before and after: 0fd6f669cc17d2061b249d2f24af5d2b75ac2563325f23a85602dbb6772c3dea. That is the load-bearing half: 45 gates inherit this paragraph verbatim.

Scope, held to the triage grading

Why pnpm-workspace.yaml and not .git

.git is the obvious marker and is wrong for the checkout shape this repo mandates. In a linked worktree (git worktree add), .git is a file holding a gitdir: pointer, not a directory — measured here at 70 bytes. A walk testing isDirectory() steps straight past the worktree root and reports no root at all, in the one tree every agent actually works in. The self-test carries that as a paired measurement: the manifest walk finds the root, and a negative control proves the .git-isDirectory walk finds nothing in the same fixture.

Nearest marker wins, as node and pnpm resolve. When no root is locatable the command falls back to the absolute path — always runnable — never to the old basename guess.

Verification

Self-test grows 49 to 60 cases. The new pins were ablated rather than assumed: with the hard-coded scripts/ interpolation put back (mutation confirmed on disk, anchor counts flipped 1 to 0 / 0 to 1), 4 of 60 cases go red, naming the defect verbatim; the restore leg is proven by blob-hash identity to HEAD.

Gate family derived from the actual diff via node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (14 families), all run at e550a5d2:

self-test 0 · agent-test-spelling 0 · bash32-floor 0 · cli-command-ids 0
cross-package-test-inputs 0 · entry-guard 0 · parse-guard 0
pnpm-filter-targets 0 · watch-hint-literal 0 · ci-filter-parity 0
check-cross-package-test-inputs 0 · shard-attestation 0
check:doc-formula-expressions 0 · check:doc-security-posture 0
check-reference-carrier-shape (+ --self-test) 0
check-ratchet-remedy-authority 0 · check-nul-bytes 0

check-ratchet-remedy-authority was run because this diff changes remedy prose: 183 scripts swept, import-prerequisite.mjs stays among the 165 handing out no ratchet-expanding remedy, unchanged from baseline. check-test-completeness returns exit 3 (PREREQUISITE NOT MET — it grades a saved turbo run test log, none named): NOT MEASURED, not red, and unrelated to this diff.

The fix dogfoods itself: with @objectstack/formula unbuilt, the live refusal now prints node packages/lint/scripts/check-doc-formula-expressions.mjs — the same gate, the same reproduction as the card, now with a command that runs.

No changeset: this diff publishes nothing from any package. skip-changeset applied.

Sibling cards on this file

Triage's baton order is #13983 then this card then #14007. #13983 landed as PR #14009 and is merged. #14007 (wiring the 60-case self-test into CI) is queued behind this one and stays untouched here — it edits the same reportPrerequisiteNotMet output region.

Generated by Claude Code


Generated by Claude Code

…uisite advisory

The advisory interpolated the gate BASENAME into a hard-coded `scripts/`
directory. Correct for the 42 importers under `scripts/**`, wrong for the
three under `packages/lint/scripts/**`: it printed
`node scripts/check-doc-formula-expressions.mjs`, which names no file. Copy-
pasting it answered `Cannot find module` at exit 1 — a banner whose purpose
is to stop a reader misreading an exit code handed them a third failure
wearing a finding's code.

Derive the path from `importerUrl` instead. The headline gate name stays a
basename (it is correct as one), and so does the `/tmp/NAME.log` sink — a
repo-relative path there would name directories that do not exist.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
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

Development

Successfully merging this pull request may close these issues.

import-prerequisite.mjs prints a node scripts/NAME.mjs command that does not exist, for the three importers under packages/lint/scripts/

2 participants