fix: address Copilot review round 6

- `reachableScripts` now follows every npm spelling of `run` — the
  canonical `run-script` and its `run`/`rum`/`urn` aliases — with a unit
  case, so `npm run-script validate:web` appended to `local:gate` fails
  the whole-gate check instead of slipping past it.
- docs/quality-gate.md `verify:skills` row, AGENTS.md skills rule 1 and the
  #2085 narration now describe the actual chain (`validate:guards`, reached
  by both `validate` and `local:validate`) and the qualified promise.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PsmUAZ6aLUAFqenjJKSSRp
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-09-12 20:40:44 -04:00
commit 61fcada059

View file

@ -48,6 +48,25 @@ test("reachableScripts: follows `npm run` refs and pre/post hooks (r10)", () =>
assert.ok(!reached.has("unrelated"));
});
test("reachableScripts: follows every npm spelling of `run` (#2341)", () => {
// `run-script` is the canonical command; `run`, `rum` and `urn` are its
// aliases. A chain written in any of them reaches the same scripts, so a
// guard that only followed `npm run` would let `npm run-script validate:web`
// reintroduce what it exists to forbid (Copilot).
const scripts = {
gate: "npm run-script a && npm rum b && npm urn c && npm run d",
a: "noop",
b: "noop",
c: "noop",
d: "noop",
e: "noop",
};
const reached = reachableScripts(scripts, "gate");
for (const name of ["a", "b", "c", "d"])
assert.ok(reached.has(name), `npm spelling reaching ${name}`);
assert.ok(!reached.has("e"));
});
test("reachableScripts: a `prevalidate`-hosted typecheck is reachable (r10)", () => {
const scripts = {
validate: "npm run build && npm run test",