vigiles 26.0.0 → 26.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +54 -11
- package/dist/core/compile.js +20 -6
- package/dist/hook.js +14 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1283,24 +1283,20 @@ async function checkSpecRefs(excludes, config, silent, dialect) {
|
|
|
1283
1283
|
if (!sev)
|
|
1284
1284
|
return { issues: 0, errors: 0 };
|
|
1285
1285
|
const found = [];
|
|
1286
|
+
let knownAgents;
|
|
1286
1287
|
for (const specPath of findSpecs(excludes)) {
|
|
1287
1288
|
const target = specPath.replace(/\.spec\.ts$/, "");
|
|
1288
1289
|
if (!(0, node_fs_1.existsSync)(target))
|
|
1289
1290
|
continue; // never compiled — `compile` reports it
|
|
1290
1291
|
const spec = await loadSpec(specPath);
|
|
1291
|
-
if (!spec
|
|
1292
|
+
if (!spec)
|
|
1292
1293
|
continue;
|
|
1293
1294
|
try {
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
maxTokens: config?.maxTokens,
|
|
1300
|
-
maxSectionLines: config?.maxSectionLines,
|
|
1301
|
-
catalogOnly: config?.catalogOnly,
|
|
1302
|
-
linters: config?.linters,
|
|
1303
|
-
});
|
|
1295
|
+
// Railway is the one type whose validation needs the sibling agent names;
|
|
1296
|
+
// collected lazily so a repo with no railway spec never pays for the walk.
|
|
1297
|
+
if (spec._specType === "railway")
|
|
1298
|
+
knownAgents ??= await collectAgentNames(excludes);
|
|
1299
|
+
const errors = specCompileErrors(spec, specPath, dialect, config, knownAgents ?? []);
|
|
1304
1300
|
for (const e of errors)
|
|
1305
1301
|
found.push(`${target}: ${e.message} (from ${specPath})`);
|
|
1306
1302
|
}
|
|
@@ -1319,6 +1315,53 @@ async function checkSpecRefs(excludes, config, silent, dialect) {
|
|
|
1319
1315
|
}
|
|
1320
1316
|
return { issues: found.length, errors: sev === "error" ? found.length : 0 };
|
|
1321
1317
|
}
|
|
1318
|
+
/**
|
|
1319
|
+
* The ONE spec-type dispatcher, in the only shape both directions can share:
|
|
1320
|
+
* errors, no writing. `compile` reaches its compilers through the
|
|
1321
|
+
* `compile*ToFile` wrappers (which write and print); `checkSpecRefs` reaches the
|
|
1322
|
+
* SAME compilers through this, because a read must never write.
|
|
1323
|
+
*
|
|
1324
|
+
* Why it exists (#190): `checkSpecRefs` used to call `compileClaude` directly and
|
|
1325
|
+
* skip every other spec type, so a SKILL.md / subagent / railway artifact
|
|
1326
|
+
* committed with a since-deleted reference hashed cleanly against its own header
|
|
1327
|
+
* forever — `lint` green, `compile` red. Measured on this repo:
|
|
1328
|
+
* `examples/SKILL.md.spec.ts` names `skills/enforce-rules-format/SKILL.md`, which
|
|
1329
|
+
* does not exist (the skill lives under `.claude/skills/`), and `lint` reported
|
|
1330
|
+
* `hash valid`.
|
|
1331
|
+
*
|
|
1332
|
+
* A switch rather than a per-type "ref accessor": all four compilers already
|
|
1333
|
+
* return the same `errors: CompileError[]`, so there is nothing to normalize —
|
|
1334
|
+
* only the options differ. Exhaustive over `_specType`, so a FIFTH spec type is
|
|
1335
|
+
* a tsc error here instead of a silent skip, which is the failure this closes.
|
|
1336
|
+
*/
|
|
1337
|
+
function specCompileErrors(spec, specPath, dialect, config, knownAgents) {
|
|
1338
|
+
const basePath = process.cwd();
|
|
1339
|
+
switch (spec._specType) {
|
|
1340
|
+
case "claude":
|
|
1341
|
+
return (0, compile_js_1.compileClaude)(spec, {
|
|
1342
|
+
basePath,
|
|
1343
|
+
specFile: specPath,
|
|
1344
|
+
dialect,
|
|
1345
|
+
maxRules: config?.maxRules,
|
|
1346
|
+
maxTokens: config?.maxTokens,
|
|
1347
|
+
maxSectionLines: config?.maxSectionLines,
|
|
1348
|
+
catalogOnly: config?.catalogOnly,
|
|
1349
|
+
linters: config?.linters,
|
|
1350
|
+
}).errors;
|
|
1351
|
+
case "skill":
|
|
1352
|
+
return (0, compile_js_1.compileSkill)(spec, { basePath, specFile: specPath, dialect })
|
|
1353
|
+
.errors;
|
|
1354
|
+
case "agent":
|
|
1355
|
+
return (0, compile_js_1.compileAgent)(spec, { basePath, specFile: specPath, dialect })
|
|
1356
|
+
.errors;
|
|
1357
|
+
case "railway":
|
|
1358
|
+
return (0, compile_js_1.compileRailway)(spec, { specFile: specPath, knownAgents }).errors;
|
|
1359
|
+
default:
|
|
1360
|
+
// A `pipeline` spec compiles through its underlying railway, so it has no
|
|
1361
|
+
// artifact of its own to re-derive refs for.
|
|
1362
|
+
return [];
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1322
1365
|
/**
|
|
1323
1366
|
* Write a compiled artifact. Accepts ONLY a {@link StampedMarkdown}, so a body
|
|
1324
1367
|
* that failed to compile cannot reach the disk — there is no stamp to pass.
|
package/dist/core/compile.js
CHANGED
|
@@ -690,7 +690,6 @@ function yamlScalar(value) {
|
|
|
690
690
|
function renderSkillFrontmatter(spec, profile = "claude-code") {
|
|
691
691
|
const fm = [
|
|
692
692
|
"---",
|
|
693
|
-
"",
|
|
694
693
|
`name: ${yamlScalar(spec.name)}`,
|
|
695
694
|
`description: ${yamlScalar(spec.description)}`,
|
|
696
695
|
];
|
|
@@ -724,7 +723,7 @@ function renderSkillFrontmatter(spec, profile = "claude-code") {
|
|
|
724
723
|
fm.push(`disallowed-tools: [${spec.disallowedTools.join(", ")}]`);
|
|
725
724
|
}
|
|
726
725
|
}
|
|
727
|
-
fm.push("
|
|
726
|
+
fm.push("---");
|
|
728
727
|
return fm.join("\n");
|
|
729
728
|
}
|
|
730
729
|
/**
|
|
@@ -871,7 +870,15 @@ function compileSkill(spec, options = {}) {
|
|
|
871
870
|
const warnings = checkInlineCode(sections, spec.maxInlineCodeLines ?? DEFAULT_MAX_INLINE_CODE_LINES);
|
|
872
871
|
const marker = purityMarker(spec.purity);
|
|
873
872
|
const content = renderSkillFrontmatter(spec, profile) +
|
|
874
|
-
|
|
873
|
+
// ONE newline, not two: `placeIntegrityHeader` puts the stamp AFTER the
|
|
874
|
+
// frontmatter and supplies its own blank line on each side, so a second one
|
|
875
|
+
// here becomes two blank lines in the artifact — which `prettier --check`
|
|
876
|
+
// rejects, and a freshly compiled artifact then cannot pass `npm run check`.
|
|
877
|
+
// Fixed HERE rather than in the stamper: the hash is computed over this
|
|
878
|
+
// content (compile.ts `seal`), so trimming inside `placeIntegrityHeader`
|
|
879
|
+
// would hash one string and write another — measured, it broke integrity on
|
|
880
|
+
// all three frontmatter-bearing artifacts.
|
|
881
|
+
"\n" +
|
|
875
882
|
(marker ? marker + "\n\n" : "") +
|
|
876
883
|
sections.trim() +
|
|
877
884
|
"\n";
|
|
@@ -913,7 +920,6 @@ function renderAgentFrontmatter(spec) {
|
|
|
913
920
|
// {@link yamlScalar}.
|
|
914
921
|
const fm = [
|
|
915
922
|
"---",
|
|
916
|
-
"",
|
|
917
923
|
`name: ${yamlScalar(spec.name)}`,
|
|
918
924
|
`description: ${yamlScalar(spec.description)}`,
|
|
919
925
|
];
|
|
@@ -927,7 +933,7 @@ function renderAgentFrontmatter(spec) {
|
|
|
927
933
|
if (spec.disallowedTools && spec.disallowedTools.length > 0) {
|
|
928
934
|
fm.push(`disallowedTools: ${spec.disallowedTools.join(", ")}`);
|
|
929
935
|
}
|
|
930
|
-
fm.push("
|
|
936
|
+
fm.push("---");
|
|
931
937
|
return fm.join("\n");
|
|
932
938
|
}
|
|
933
939
|
/**
|
|
@@ -1070,7 +1076,15 @@ function compileAgent(spec, options) {
|
|
|
1070
1076
|
const warnings = checkInlineCode(body, DEFAULT_MAX_INLINE_CODE_LINES);
|
|
1071
1077
|
const marker = purityMarker(spec.purity);
|
|
1072
1078
|
const content = renderAgentFrontmatter(spec) +
|
|
1073
|
-
|
|
1079
|
+
// ONE newline, not two: `placeIntegrityHeader` puts the stamp AFTER the
|
|
1080
|
+
// frontmatter and supplies its own blank line on each side, so a second one
|
|
1081
|
+
// here becomes two blank lines in the artifact — which `prettier --check`
|
|
1082
|
+
// rejects, and a freshly compiled artifact then cannot pass `npm run check`.
|
|
1083
|
+
// Fixed HERE rather than in the stamper: the hash is computed over this
|
|
1084
|
+
// content (compile.ts `seal`), so trimming inside `placeIntegrityHeader`
|
|
1085
|
+
// would hash one string and write another — measured, it broke integrity on
|
|
1086
|
+
// all three frontmatter-bearing artifacts.
|
|
1087
|
+
"\n" +
|
|
1074
1088
|
(marker ? marker + "\n\n" : "") +
|
|
1075
1089
|
body.trim() +
|
|
1076
1090
|
"\n";
|
package/dist/hook.js
CHANGED
|
@@ -133,8 +133,20 @@ Object.defineProperty(exports, "isStateWrite", { enumerable: true, get: function
|
|
|
133
133
|
Object.defineProperty(exports, "admissibleWrites", { enumerable: true, get: function () { return hook_state_js_1.admissibleWrites; } });
|
|
134
134
|
Object.defineProperty(exports, "durationSeconds", { enumerable: true, get: function () { return hook_state_js_1.durationSeconds; } });
|
|
135
135
|
Object.defineProperty(exports, "HookStateError", { enumerable: true, get: function () { return hook_state_js_1.HookStateError; } });
|
|
136
|
-
// Operation-normalized leaf extraction — the
|
|
137
|
-
//
|
|
136
|
+
// Operation-normalized leaf extraction — the primitive `runs()`, `touches()`
|
|
137
|
+
// and `pipesToShell()` match over, so a guard written against the closed
|
|
138
|
+
// vocabulary sees the OPERATION rather than the literal tokens.
|
|
139
|
+
//
|
|
140
|
+
// It is exported because `examples/harness/safe-bash-guard-v2.mjs` needs it —
|
|
141
|
+
// and that need is the finding, not the feature. v2 is an UNRUN experiment (no
|
|
142
|
+
// test executes it) covering three things the vocabulary cannot yet express: a
|
|
143
|
+
// flag with a value (`--index-url`), an env-assignment prefix, and a
|
|
144
|
+
// cross-leaf pipeline fact (`env | curl`). Reaching for this export is how a
|
|
145
|
+
// guard author escapes the closed vocabulary — the thing `checkHookImports`
|
|
146
|
+
// exists to prevent — so treat a new consumer as a request for vocabulary,
|
|
147
|
+
// not as the intended path. Measured 2026-09-03: on the 7 seeds plus every
|
|
148
|
+
// generated spelling (143 cases) v1 and v2 both block 143/143, so v2 is no
|
|
149
|
+
// longer the "hardened" one; see zernie/vigiles#193.
|
|
138
150
|
var bash_effects_js_1 = require("./core/bash-effects.js");
|
|
139
151
|
Object.defineProperty(exports, "leafCommandsNormalized", { enumerable: true, get: function () { return bash_effects_js_1.leafCommandsNormalized; } });
|
|
140
152
|
//# sourceMappingURL=hook.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vigiles",
|
|
3
|
-
"version": "26.0.
|
|
3
|
+
"version": "26.0.1",
|
|
4
4
|
"description": "Audit, test and measure the harness your AI agent runs on — grade your CLAUDE.md / AGENTS.md, skills, subagents and hooks, run them against a scripted model, and measure whether they actually fire.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|