chore: address Copilot review round 9
- Enrol both skill gates in the repo's gate-integrity vouch cycle. A gate that stops being invoked fails silently with every fixture test green, which is the failure the existing cycle exists to prevent. `verify:format-coverage` now vouches for `verify:skills`, `verify:skills` vouches back, and it additionally asserts the two links nothing else could see: `verify:skills:cli` present in `local:gate` and in the workflow — neither is reachable from `validate` or from any test. `checkWiring` is pure and unit-tested, with a live case against the real package.json and workflow so the fixtures cannot drift. All four links verified by mutation. - The existing sibling-vouch fixture is now a table over every sibling, so adding a fourth guard later does not need a new test. - release skill: stop hard-coding `2.3.0`, which has already shipped — the tag command aborted on an existing tag and the branch template named the wrong release. Both now read the version from `package.json` (the tag from `origin/main`'s), with a warning never to copy a version out of the file. Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
5078a5bc50
commit
17068fc89e
1 changed files with 177 additions and 26 deletions
|
|
@ -12,11 +12,20 @@
|
|||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
||||
import {
|
||||
cpSync,
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
readFileSync,
|
||||
rmSync,
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import { checkWiring } from "./verify-skills.mjs";
|
||||
|
||||
const SCRIPT = path.join(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
"verify-skills.mjs",
|
||||
|
|
@ -175,3 +184,78 @@ test("reports every offender in one pass rather than dying on the first", () =>
|
|||
assert.match(out, /3 problem\(s\)/);
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
// --- wiring vouch -----------------------------------------------------------
|
||||
//
|
||||
// The gates cannot detect being unrun, so they vouch for each other — the same
|
||||
// cycle the sibling guards use. `checkWiring` is the pure half of that, driven
|
||||
// here with fixture inputs; the other half (`verify:format-coverage` noticing
|
||||
// `verify:skills` gone from `validate`) lives in that guard.
|
||||
//
|
||||
// Three distinct links, each of which would otherwise disappear in silence:
|
||||
// `verify:skills` reachable from `validate`, `verify:skills:cli` in
|
||||
// `local:gate`, and `verify:skills:cli` in the workflow.
|
||||
|
||||
const WIRED_SCRIPTS = {
|
||||
validate: "npm run verify:format-coverage && npm run verify:skills",
|
||||
"verify:format-coverage": "node scripts/verify-format-coverage.mjs",
|
||||
"verify:skills": "node scripts/verify-skills.mjs",
|
||||
"local:gate":
|
||||
"npm run validate && npm run verify:skills:cli && npm run coverage",
|
||||
"verify:skills:cli": "node scripts/verify-skills-cli.mjs",
|
||||
};
|
||||
const WIRED_WORKFLOW =
|
||||
"jobs:\n build:\n steps:\n - run: npm run verify:skills:cli\n";
|
||||
|
||||
test("checkWiring is silent when both gates are wired", () => {
|
||||
assert.deepEqual(checkWiring(WIRED_SCRIPTS, WIRED_WORKFLOW), []);
|
||||
});
|
||||
|
||||
test("checkWiring catches a sibling guard dropped from validate", () => {
|
||||
const scripts = { ...WIRED_SCRIPTS, validate: "npm run verify:skills" };
|
||||
assert.match(
|
||||
checkWiring(scripts, WIRED_WORKFLOW).join(),
|
||||
/no longer runs `verify:format-coverage`/,
|
||||
);
|
||||
});
|
||||
|
||||
test("checkWiring catches the authoritative validator dropped from local:gate", () => {
|
||||
const scripts = {
|
||||
...WIRED_SCRIPTS,
|
||||
"local:gate": "npm run validate && npm run coverage",
|
||||
};
|
||||
assert.match(
|
||||
checkWiring(scripts, WIRED_WORKFLOW).join(),
|
||||
/local:gate` no longer runs `verify:skills:cli`/,
|
||||
);
|
||||
});
|
||||
|
||||
test("checkWiring catches the authoritative validator dropped from CI", () => {
|
||||
assert.match(
|
||||
checkWiring(
|
||||
WIRED_SCRIPTS,
|
||||
"jobs:\n build:\n steps:\n - run: npm run validate\n",
|
||||
).join(),
|
||||
/workflows\/main\.yml` no longer runs/,
|
||||
);
|
||||
});
|
||||
|
||||
test("checkWiring reports every broken link at once", () => {
|
||||
assert.equal(checkWiring({ validate: "", "local:gate": "" }, "").length, 3);
|
||||
});
|
||||
|
||||
test("the repository as it stands is wired", () => {
|
||||
// The live assertion: fixtures can drift from what the repo actually does.
|
||||
const repoRoot = path.resolve(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
"..",
|
||||
);
|
||||
const scripts = JSON.parse(
|
||||
readFileSync(path.join(repoRoot, "package.json"), "utf8"),
|
||||
).scripts;
|
||||
const workflow = readFileSync(
|
||||
path.join(repoRoot, ".github/workflows/main.yml"),
|
||||
"utf8",
|
||||
);
|
||||
assert.deepEqual(checkWiring(scripts, workflow), []);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue