vigiles 15.0.2 → 15.0.3
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/adapters/claude-code/layout.js +3 -0
- package/dist/adapters/claude-code/run-scripts.d.ts +21 -9
- package/dist/adapters/claude-code/run-scripts.js +33 -22
- package/dist/adapters/codex/driver.js +3 -1
- package/dist/adapters/codex/eval.js +5 -0
- package/dist/audit-score.js +32 -6
- package/dist/check-count.d.ts +62 -3
- package/dist/check-count.js +123 -5
- package/dist/check.d.ts +55 -0
- package/dist/check.js +91 -0
- package/dist/cli.js +456 -54
- package/dist/core/bash-effects.d.ts +41 -0
- package/dist/core/bash-effects.js +278 -0
- package/dist/core/foreign-runner.d.ts +185 -0
- package/dist/core/foreign-runner.js +228 -0
- package/dist/core/harness-driver.d.ts +18 -1
- package/dist/core/hook-program.d.ts +319 -20
- package/dist/core/hook-program.js +743 -49
- package/dist/core/layout.d.ts +13 -0
- package/dist/core/lethal-trifecta.d.ts +93 -0
- package/dist/core/lethal-trifecta.js +409 -65
- package/dist/core/markdown.d.ts +32 -0
- package/dist/core/markdown.js +36 -0
- package/dist/core/merge-conflict.d.ts +50 -0
- package/dist/core/merge-conflict.js +84 -0
- package/dist/core/test-file-ext.d.ts +80 -0
- package/dist/core/test-file-ext.js +90 -0
- package/dist/core/types.d.ts +11 -0
- package/dist/coverage-artifact.d.ts +383 -0
- package/dist/coverage-artifact.js +586 -0
- package/dist/coverage-evidence.d.ts +87 -79
- package/dist/coverage-evidence.js +212 -211
- package/dist/coverage-probe.d.ts +125 -0
- package/dist/coverage-probe.js +700 -0
- package/dist/doc-commands.d.ts +119 -0
- package/dist/doc-commands.js +158 -0
- package/dist/eval-lock.d.ts +9 -0
- package/dist/eval-lock.js +14 -2
- package/dist/eval.js +28 -0
- package/dist/fs-walk.d.ts +80 -0
- package/dist/fs-walk.js +148 -0
- package/dist/harness-assert.js +42 -3
- package/dist/harness-test.js +31 -2
- package/dist/judge.js +4 -0
- package/dist/leaderboard.d.ts +16 -1
- package/dist/leaderboard.js +19 -2
- package/dist/load-hook.js +6 -1
- package/dist/mock-model.d.ts +58 -4
- package/dist/mock-model.js +133 -5
- package/dist/observe.d.ts +1 -1
- package/dist/observe.js +44 -1
- package/dist/plugin-loader.js +52 -13
- package/dist/run-hook.d.ts +58 -0
- package/dist/run-hook.js +70 -0
- package/dist/run-script.js +75 -0
- package/dist/scaffold-test.d.ts +3 -0
- package/dist/scaffold-test.js +10 -5
- package/dist/scan-behavioral.js +4 -0
- package/dist/scan-core.d.ts +22 -0
- package/dist/scan-core.js +46 -14
- package/dist/scan-files.js +19 -2
- package/dist/scan.d.ts +22 -5
- package/dist/scan.js +67 -13
- package/dist/skill-contract.d.ts +46 -0
- package/dist/skill-contract.js +201 -0
- package/dist/skill-refs.d.ts +67 -0
- package/dist/skill-refs.js +117 -0
- package/dist/test-coverage-files.d.ts +7 -1
- package/dist/test-coverage-files.js +66 -55
- package/dist/test-coverage.d.ts +155 -19
- package/dist/test-coverage.js +430 -91
- package/dist/testing.d.ts +8 -2
- package/dist/testing.js +19 -1
- package/dist/trigger-containment.d.ts +85 -0
- package/dist/trigger-containment.js +125 -0
- package/dist/ts-runner-caps.d.ts +16 -0
- package/dist/ts-runner-caps.js +43 -0
- package/dist/unit.d.ts +2 -2
- package/dist/unit.js +2 -1
- package/hooks/eval-lock-nudge.sh +14 -6
- package/package.json +2 -2
- package/skills/test-harness/SKILL.md +68 -2
package/dist/check.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.assertChecks = assertChecks;
|
|
|
5
5
|
exports.tool = tool;
|
|
6
6
|
exports.toolWith = toolWith;
|
|
7
7
|
exports.notTool = notTool;
|
|
8
|
+
exports.onlyTools = onlyTools;
|
|
8
9
|
exports.skill = skill;
|
|
9
10
|
exports.output = output;
|
|
10
11
|
exports.hookFired = hookFired;
|
|
@@ -57,6 +58,15 @@ const no = (message) => ({
|
|
|
57
58
|
score: 0,
|
|
58
59
|
message,
|
|
59
60
|
});
|
|
61
|
+
/**
|
|
62
|
+
* `Bash(git:*)` → `Bash`. A declaration may carry a restriction; a trace never
|
|
63
|
+
* does, so the two only meet on the base name. Same one-liner as
|
|
64
|
+
* `core/tool-contract.ts` / `core/lethal-trifecta.ts`, kept local because the
|
|
65
|
+
* testing pillar does not otherwise depend on the linting core.
|
|
66
|
+
*/
|
|
67
|
+
function baseTool(raw) {
|
|
68
|
+
return raw.split("(")[0].trim();
|
|
69
|
+
}
|
|
60
70
|
function distinctToolNames(calls) {
|
|
61
71
|
const names = [...new Set(calls.map((c) => c.name))];
|
|
62
72
|
return names.length > 0 ? `[${names.join(", ")}]` : "no tools";
|
|
@@ -135,6 +145,87 @@ function notTool(name, args) {
|
|
|
135
145
|
: { kind: "notTool", name },
|
|
136
146
|
};
|
|
137
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* The agent used **only** tools drawn from `allowed` — the white-list, and the
|
|
150
|
+
* missing half of a symmetry the file surface already has:
|
|
151
|
+
*
|
|
152
|
+
* | | "not this one" | "nothing but these" |
|
|
153
|
+
* | ----- | --------------- | ---------------------- |
|
|
154
|
+
* | files | `assertNoWrite` | `assertWroteOnly` |
|
|
155
|
+
* | tools | {@link notTool} | **`onlyTools`** (this) |
|
|
156
|
+
*
|
|
157
|
+
* Why the asymmetry mattered: `notTool` can only forbid the calls the test
|
|
158
|
+
* author thought of, and the set of undeclared tools is unbounded — so "this
|
|
159
|
+
* skill stayed inside the tools it declares" was not expressible, which is
|
|
160
|
+
* exactly the claim a `SKILL.md` frontmatter makes in prose. See
|
|
161
|
+
* `skillContract`, which builds this check from that declaration.
|
|
162
|
+
*
|
|
163
|
+
* **Fails closed on an empty trace.** A `Trace` records tool calls only when the
|
|
164
|
+
* run captured the stream (`transcript: true` on the harness tier; always on the
|
|
165
|
+
* eval tier), so an uncaptured run is indistinguishable from a tool-free one —
|
|
166
|
+
* and passing it would assert nothing. Same discipline as `assertWroteOnly`
|
|
167
|
+
* refusing a result that never recorded writes: "we didn't look" is not "it was
|
|
168
|
+
* clean".
|
|
169
|
+
*
|
|
170
|
+
* 🔴 A `Tool(restriction)` DECLARATION IS MATCHED BY ITS BASE NAME. `allowed-tools:
|
|
171
|
+
* Bash(git:*)` is the ordinary way to write a narrow grant, and `skillContract`
|
|
172
|
+
* hands that literal string here — while a trace only ever carries the base name
|
|
173
|
+
* `Bash`, because that is the tool the harness reports. Set membership therefore
|
|
174
|
+
* missed, and every legitimate `Bash` call was reported as outside the declared
|
|
175
|
+
* surface, against a declaration that literally lists Bash (measured 2026-08-11:
|
|
176
|
+
* `agent used tool(s) outside its declared set: Bash (declared: Bash(git:*),
|
|
177
|
+
* Read, Skill)`). A check that fires on its own happy path gets deleted, not
|
|
178
|
+
* debugged — and it would fire on exactly the authors who narrowed their grant.
|
|
179
|
+
*
|
|
180
|
+
* ⚠️ AND THE RESTRICTION ITSELF IS NOT VERIFIED HERE, deliberately. A trace names
|
|
181
|
+
* the tool, not the grant it was matched against, so `Bash(git:*)` can be held to
|
|
182
|
+
* "no tool outside the declared set" and no further; whether the command really
|
|
183
|
+
* was a `git` one is a claim this layer has no evidence for. Narrowing beyond the
|
|
184
|
+
* base name is `disallowed-tools:` + `lethal-trifecta`'s job (see
|
|
185
|
+
* `skill-contract.ts`), which reads the grant instead of the run. The same
|
|
186
|
+
* `split("(")` normalization the rest of the codebase already applies to tool
|
|
187
|
+
* declarations — `core/tool-contract.ts`, `core/lethal-trifecta.ts`,
|
|
188
|
+
* `core/delegation-trifecta.ts`.
|
|
189
|
+
*
|
|
190
|
+
* ⚠️ SPANS THE WHOLE TRACE, deliberately. It answers "did this RUN stay inside
|
|
191
|
+
* these tools?", which is the right question for a harness that drives one thing.
|
|
192
|
+
* It is the wrong question when the trace has setup calls before the surface
|
|
193
|
+
* under test activated, drives several skills, or dispatches a subagent whose
|
|
194
|
+
* nested calls the parser folds into the same flat list — and reporting those as
|
|
195
|
+
* a violation is an accusation about the wrong code.
|
|
196
|
+
*
|
|
197
|
+
* `skillContract` therefore does NOT use this directly: it wraps it in a window
|
|
198
|
+
* bounded by its own `Skill` activation (see `duringSkill` in
|
|
199
|
+
* `src/skill-contract.ts`). If you are checking one skill, prefer the contract;
|
|
200
|
+
* reach for this when the claim really is about the whole run.
|
|
201
|
+
*/
|
|
202
|
+
function onlyTools(allowed) {
|
|
203
|
+
const allow = new Set(allowed.map(baseTool));
|
|
204
|
+
// The declaration is echoed VERBATIM: an author who wrote `Bash(git:*)` must
|
|
205
|
+
// read back what they wrote, not the normalized form the matching used.
|
|
206
|
+
const declared = [...new Set(allowed)].join(", ") || "none";
|
|
207
|
+
return {
|
|
208
|
+
kind: "onlyTools",
|
|
209
|
+
eval: (t) => {
|
|
210
|
+
if (t.toolCalls.length === 0)
|
|
211
|
+
return no(`onlyTools cannot run: this trace recorded no tool calls, so passing ` +
|
|
212
|
+
`it would assert nothing. Tool calls are parsed from the stream — ` +
|
|
213
|
+
`pass \`transcript: true\` on the harness tier (the eval tier always ` +
|
|
214
|
+
`captures it). If the run genuinely used no tools there is no tool ` +
|
|
215
|
+
`surface to constrain, and this check does not apply.`);
|
|
216
|
+
// Report EVERY distinct offender, not just the first: a skill reaching for
|
|
217
|
+
// three undeclared tools should not take three runs to discover that.
|
|
218
|
+
const offenders = [
|
|
219
|
+
...new Set(t.toolCalls.map((c) => c.name).filter((name) => !allow.has(name))),
|
|
220
|
+
];
|
|
221
|
+
if (offenders.length === 0)
|
|
222
|
+
return ok(`agent used only declared tool(s): ${declared}`);
|
|
223
|
+
return no(`agent used tool(s) outside its declared set: ${offenders.join(", ")} ` +
|
|
224
|
+
`(declared: ${declared})`);
|
|
225
|
+
},
|
|
226
|
+
toJSON: () => ({ kind: "onlyTools", allowed: [...allowed] }),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
138
229
|
/** A skill resolved to this id (`<plugin>:<skill>`) without erroring. */
|
|
139
230
|
function skill(id) {
|
|
140
231
|
return {
|