Repository navigation
import-prerequisite.mjs prints a node scripts/NAME.mjs command that does not exist, for the three importers under packages/lint/scripts/ #13826
Description
Activity
Claim: PM loop round 1
Session:session_01WLJQhde67SeTccsmnBVarV
Branch:claude/issue-13826-prerequisite-command-path
Worktree:objectstack-issue-13826
Domain:domain:devx
File surface:scripts/import-prerequisite.mjsonly (command-path derivation + its--self-testpins). ⛔ The headline gate NAME stays a basename per triage; ⛔ the three lint importers are not edited — they inherit the fix (stop on breach; explain in the report)
Container & model: M,mode:subagent,model: claude-opus-5— no path mandate; judgment tier for a shared frame 45 gates inherit (repo-root resolution from an importer URL has worktree subtleties).
Clause-②: no
Serial constraints cleared: triage's baton order #13983 → this card → #14007 honoured — #13983 MERGED (PR #14009); #14007 stays queued behind this card (samereportPrerequisiteNotMetoutput region, merge-conflict face overlaps). No open PR touchesscripts/import-prerequisite.mjs(the #13429 branch's PR landed). In-flight #13835 (packages/lint rule) and #13642 (dispatch-gates print block) are disjoint files. Premise note for the dev: the card measured at a pre-#13983 branch — the frame's exit codes changed since (exit 3 class); re-derive the current output shape before pinning.
Generated by Claude Code
Dev claim.
Session:session_01WLJQhde67SeTccsmnBVarV
Branch:claude/issue-13826-prerequisite-command-path
Worktree:objectstack-issue-13826Premise re-verified on
origin/main@24b66352(post-#13983), not inherited from the card. The card measured on a pre-#13983 branch; #13983 has since merged, so the output region now carries exit 3. Re-measured here withnode_modulesgenuinely absent:$ node packages/lint/scripts/check-doc-formula-expressions.mjs -> EXIT=3 check-doc-formula-expressions: PREREQUISITE NOT MET - the dependency `typescript` is not installed (Exit code 3, distinct from a finding's 1 - capture it BEFORE any pipe: `node scripts/check-doc-formula-expressions.mjs > /tmp/check-doc-formula-expressions.log 2>&1; echo "EXIT=$?"`.The defect survives #13983 unchanged:
scripts/check-doc-formula-expressions.mjsdoes not exist, and copy-pasting the printed line answersCannot find moduleat exit 1 - which reads as a finding from a third, unrelated breakage. Premise valid; proceeding.File surface:
scripts/import-prerequisite.mjsonly. The headline gate name stays a basename per triage; the three lint importers are not edited (they inherit the frame).Generated by Claude Code
Generated by Claude Code
os-dev-report
{
"issue": 13826,
"status": "done",
"branch": "claude/issue-13826-prerequisite-command-path",
"pr": "#14217",
"premise_still_valid": true,
"files_changed": [
"scripts/import-prerequisite.mjs"
],
"summary": "Premise re-verified on my own tree at merge base 24b6635 (post-#13983, advisory already exit 3), not inherited from the card: with node_modules genuinely absent, check-doc-formula-expressions printednode scripts/check-doc-formula-expressions.mjs, which names no file, and copy-pasting it answered Cannot find module at EXIT=1 - a third failure wearing a finding's exit code. Fixed by deriving the printed command from importerUrl: walk up to the nearest pnpm-workspace.yaml, emit a POSIX repo-relative path, fall back to the ABSOLUTE path when no root is locatable (never to the old basename guess). Marker is the workspace manifest and NOT .git, measured: in a linked worktree .git is a 70-byte FILE, so a .git-isDirectory walk finds no root at all in the exact checkout shape every agent works in. Per triage the headline gate name stays a basename, and the /tmp/NAME.log sink keeps the basename too - a repo-relative path there would spell /tmp/packages/lint/scripts/....log, whose parent dirs do not exist, relocating the same defect one token right. The three lint importers were not edited; they inherit the frame. No CI wiring (that is #14007, queued behind this card).",
"before_after": {
"lint_importer": {
"file": "packages/lint/scripts/check-doc-formula-expressions.mjs",
"before": "node scripts/check-doc-formula-expressions.mjs > /tmp/check-doc-formula-expressions.log 2>&1; echo "EXIT=$?" (no such file; copy-paste = EXIT 1 Cannot find module)",
"after": "node packages/lint/scripts/check-doc-formula-expressions.mjs > /tmp/check-doc-formula-expressions.log 2>&1; echo "EXIT=$?" (runs; returns the gate own EXIT 3)"
},
"scripts_importer": {
"file": "scripts/check-ci-filter-parity.mjs",
"before": "node scripts/check-ci-filter-parity.mjs > /tmp/check-ci-filter-parity.log 2>&1; echo "EXIT=$?"",
"after": "IDENTICAL - full advisory sha256 unchanged before and after: 0fd6f669cc17d2061b249d2f24af5d2b75ac2563325f23a85602dbb6772c3dea (45 gates inherit this paragraph)"
}
},
"tests": "All at commit e550a5d (clean tree; union run ON the final commit). --self-test 49 -> 60 cases, EXIT=0. ABLATION (committed first, trap-guarded): hard-coded scripts/ interpolation restored, mutation CONFIRMED ON DISK by anchor counts flipping 1->0 / 0->1 (a first attempt was a NO-OP and was caught by that guard and redone, not silently re-run); result 4 of 60 cases RED in the predicted direction, failure text namingnode scripts/check-doc-formula-expressions.mjsverbatim; restore leg proven by blob hash identical to HEAD (a7ccff1f...) plus empty git diff HEAD and counts back to 1/0. Gate family derived from the actual diff via scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (14 families, not a recalled list); exit codes captured BEFORE any pipe via redirect-then-capture: 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 0 (+ --self-test 0), check-ratchet-remedy-authority 0, check-nul-bytes 0. check-test-completeness EXIT=3 = PREREQUISITE NOT MET (grades a saved turbo run test log, none named) - read as NOT MEASURED, not red, unrelated to this diff. The two lint gates first returned 3 (unbuilt); rebuilt the closure and re-ran to a real 0 rather than reporting the refusal as a pass. check-ratchet-remedy-authority run because this diff changes REMEDY PROSE: 183 scripts swept, import-prerequisite.mjs stays among the 165 offering no ratchet-expanding remedy, unchanged from its pre-edit baseline. Control-byte self-scan of the edited file clean beyond the gate.",
"gates_note": "No dedicated vitest suite exists for this script - its --self-test IS its suite, and it is wired into no workflow (that gap is #14007, deliberately left for it).",
"mcp_calls": "0 - the repo-scoped REST probe returned 200, so issue body, comments, PR create, label write and every read-back went through REST; no MCP GitHub call was made.",
"deviations": [
"skip-changeset applied at PR-open time via the additive POST endpoint (not waiting for Check Changeset to red). Read back after the size-labeler window: labels are size/m + skip-changeset - the labeler PUT did not strip it.",
"PR body read back in full: the only delta is the platform appending its own --- + footer (90 bytes longer, nothing eaten); all load-bearing fragments verified present. Not repaired, since a PATCH would also downgrade the session-URL footer."
],
"out_of_scope_findings": [],
"open_questions": []
}Generated by Claude Code
Generated by Claude Code
✅ ACCEPT — PR #14217. Verified against the tree and the checks, not against the report
domain:devx, sessionsession_01WLJQhde67SeTccsmnBVarV, R1. Reviewer of record.Checks — every one: 32 check runs on
e550a5d23, all completed, 0 red. Path fork: 1 file (scripts/import-prerequisite.mjs, +167/−3); no governed surface ⇒ ordinary ready → queue. Clause-②: no.skip-changesetcorrect.What was spot-checked: the before/after pair shows the lint importer's printed command becoming runnable (returns the gate's own exit 3) while the
scripts/**importer's full advisory is sha256-identical before and after — the 45-gate shared paragraph provably untouched. The repo-root marker ispnpm-workspace.yaml, ⛔ not.git— the dev measured that in a linked worktree.gitis a file, so a.git-directory walk finds no root in the exact checkout shape every agent uses; that is the subtle failure the dispatch flagged, caught by measurement. The/tmp/NAME.logsink keeps the basename (a repo-relative path there would relocate the defect one token right). Ablation committed-first, disk-confirmed both directions (including catching its own first no-op attempt), 4/60 cases red on the exact restored defect. Headline gate name untouched per triage.Disposition: flipping ready, re-reading spawned checks, arming into the merge queue. Card stays
pm:dispatcheduntil MERGED. On merge, #14007 (wiring the now-60-case self-test into CI) becomes the final baton of the import-prerequisite sequence.
Generated by Claude Code
落地收口 — PR #14217 MERGED (
ee385c7eonorigin/main)domain:devx, sessionsession_01WLJQhde67SeTccsmnBVarV, R1. Same-window close-out. Card auto-closedcompletedviaFixes;pm:dispatchedstripped in the paired second write, read back clean.The prerequisite advisory now prints the importer's real repo-relative path (worktree-safe root detection via
pnpm-workspace.yaml), the 45-gate shared paragraph byte-identical. #14007 (wire the now-60-case self-test into CI) is the final baton of the import-prerequisite sequence and is dispatchable.
Generated by Claude Code
Found and measured while fixing #13429 (PR on
claude/issue-13429-pipe-shape-advisory-siblings). Out of scope there: that card is about the advisory's CONTENT; this is the interpolated command beside it, a separate defect with a separate fix.The defect
scripts/import-prerequisite.mjsderives the gate name from the importer's basename:and then prints a command that hard-codes the
scripts/directory:node scripts/${gate}.mjs .... The basename is right for the 42 importers underscripts/**, and wrong for the three that are not:packages/lint/scripts/check-doc-formula-expressions.mjspackages/lint/scripts/check-doc-security-posture.mjspackages/lint/scripts/check-reference-carrier-shape.mjsMeasured, not reasoned
On
claude/issue-13429-pipe-shape-advisory-siblingsat8f739a646, with@objectstack/formuladeliberately unbuilt:There is no
scripts/check-doc-formula-expressions.mjs. Copy-pasting the printed line answersCannot find module, which reads as a second, unrelated breakage rather than as a typo in the banner. The derivation predates #13429 and is untouched by it — that PR changed the sentence around this command, not the command.Why it matters more than a cosmetic path
The whole point of this banner is that the reader is already confused about why a gate exited non-zero. Handing them a command that fails for a THIRD reason is the failure mode the module exists to end, one level down.
Suggested shape
Derive the repo-relative path rather than the basename — the module already has
importerUrland can locate the repo root — so the printed command is the one the reader actually ran. The gate NAME in the headline is correct as a basename and should not change; only the command needs the real path.scripts/import-prerequisite.mjs --self-testis the place to pin it, next to the advisory pins #13429 added.Severity not judged. No gate verdict is computed from this text; it wastes the reader's next step.
Generated by Claude Code