vigiles 14.3.0 → 14.4.0

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.
@@ -68,6 +68,17 @@ export declare function installCodexSkills(pluginDir: string, cwd: string): numb
68
68
  * codexEvalDriver })` dispatches through.
69
69
  */
70
70
  export declare function codexEvalAgentRunner(args: AgentRunArgs): Promise<RunOut>;
71
+ /**
72
+ * Why Codex trigger-rate is EXPERIMENTAL (not a supported measurement). Codex
73
+ * has NO skill-selection event, so `codexSkillFired` infers firing from whether
74
+ * the model READ `skills/<name>/SKILL.md` — which is wrong in BOTH directions: a
75
+ * cached/already-in-context skill isn't re-read (false NEGATIVE), and an
76
+ * exploratory read while listing isn't a real fire (false POSITIVE). So the
77
+ * number can be off either way. Deterministic `vigiles audit` is fully supported
78
+ * on Codex; only this behavioral tier is experimental until a live run measures
79
+ * the oracle's accuracy vs ground truth. See docs/harness-testing-codex.md.
80
+ */
81
+ export declare const CODEX_TRIGGER_RATE_EXPERIMENTAL: string;
71
82
  /**
72
83
  * The Codex eval driver — pass to `measureTriggerRate(spec, { evalDriver:
73
84
  * codexEvalDriver })` to run a trigger-rate eval natively on `codex exec`. Pair
@@ -27,7 +27,7 @@
27
27
  * not be re-read); pair with a behavioral/judged check for certainty.
28
28
  */
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.codexEvalDriver = void 0;
30
+ exports.codexEvalDriver = exports.CODEX_TRIGGER_RATE_EXPERIMENTAL = void 0;
31
31
  exports.parseCodexEvalRun = parseCodexEvalRun;
32
32
  exports.codexRunError = codexRunError;
33
33
  exports.codexSkillFired = codexSkillFired;
@@ -186,6 +186,20 @@ function codexEvalAgentRunner(args) {
186
186
  timeoutMs: args.timeoutMs,
187
187
  }));
188
188
  }
189
+ /**
190
+ * Why Codex trigger-rate is EXPERIMENTAL (not a supported measurement). Codex
191
+ * has NO skill-selection event, so `codexSkillFired` infers firing from whether
192
+ * the model READ `skills/<name>/SKILL.md` — which is wrong in BOTH directions: a
193
+ * cached/already-in-context skill isn't re-read (false NEGATIVE), and an
194
+ * exploratory read while listing isn't a real fire (false POSITIVE). So the
195
+ * number can be off either way. Deterministic `vigiles audit` is fully supported
196
+ * on Codex; only this behavioral tier is experimental until a live run measures
197
+ * the oracle's accuracy vs ground truth. See docs/harness-testing-codex.md.
198
+ */
199
+ exports.CODEX_TRIGGER_RATE_EXPERIMENTAL = "Codex trigger-rate is experimental — Codex has no skill-selection event, so " +
200
+ "firing is inferred from a SKILL.md read (cache → false negative, exploratory " +
201
+ "read → false positive). Treat as directional, not a measurement. Deterministic " +
202
+ "`vigiles audit` is fully supported on Codex.";
189
203
  /**
190
204
  * The Codex eval driver — pass to `measureTriggerRate(spec, { evalDriver:
191
205
  * codexEvalDriver })` to run a trigger-rate eval natively on `codex exec`. Pair
@@ -198,6 +212,8 @@ exports.codexEvalDriver = {
198
212
  // The harness identity → folded into the trigger-rate lock hash, so a report
199
213
  // recorded on Claude Code is STALE if the eval is switched to Codex (and v.v.).
200
214
  harness: "codex",
215
+ // Codex-only: the trigger-rate number is not validated (see the constant above).
216
+ experimental: exports.CODEX_TRIGGER_RATE_EXPERIMENTAL,
201
217
  };
202
218
  /**
203
219
  * Spawn real `codex exec --json` for the eval tier (real model, the user's codex
package/dist/eval.d.ts CHANGED
@@ -733,6 +733,13 @@ export interface TriggerRateReport {
733
733
  readonly errored?: number;
734
734
  /** Cost / tokens SPENT across all runs (relevant + irrelevant) — feeds the cost summary. */
735
735
  readonly usage: ArmUsage;
736
+ /**
737
+ * Present when the driver's harness measures trigger-rate on an EXPERIMENTAL
738
+ * basis (copied from {@link EvalDriver.experimental}) — the number is not
739
+ * validated and can be wrong. `formatTriggerRateReport` prints it as a loud
740
+ * caveat. Absent = a supported, trustworthy measurement (Claude Code).
741
+ */
742
+ readonly experimental?: string;
736
743
  }
737
744
  /**
738
745
  * An eval-tier transport: how to RUN a real harness turn and PARSE its output.
@@ -754,6 +761,16 @@ export interface EvalDriver {
754
761
  * `"claude-code"`, so an existing single-harness lock is unaffected.
755
762
  */
756
763
  readonly harness?: string;
764
+ /**
765
+ * When set, this driver's trigger-rate number is EXPERIMENTAL and not
766
+ * validated — the string is the human caveat explaining why (e.g. Codex has no
767
+ * skill-selection event, so firing is inferred from a SKILL.md read, which can
768
+ * be wrong in both directions). Absent = supported/trustworthy (the default,
769
+ * Claude Code). `measureTriggerRate` copies it onto the report and warns; the
770
+ * formatter prints it. Precision-first: never let a possibly-wrong number read
771
+ * as a measurement.
772
+ */
773
+ readonly experimental?: string;
757
774
  }
758
775
  /**
759
776
  * The default (Claude Code) eval driver: real `claude` + stream-json parsing.
package/dist/eval.js CHANGED
@@ -1730,7 +1730,16 @@ async function measureTriggerRateWith(spec, runner, parse = parseClaudeRun, runE
1730
1730
  */
1731
1731
  async function measureTriggerRate(spec, opts = {}) {
1732
1732
  const d = opts.evalDriver ?? exports.claudeEvalDriver;
1733
- const report = await measureTriggerRateWith(spec, d.runner, d.parse, d.runError, d.harness ?? "claude-code");
1733
+ const measured = await measureTriggerRateWith(spec, d.runner, d.parse, d.runError, d.harness ?? "claude-code");
1734
+ // Precision-first: if the driver flags its trigger-rate EXPERIMENTAL (Codex),
1735
+ // carry the caveat onto the report and warn loudly, so the number is never
1736
+ // mistaken for a validated measurement.
1737
+ const report = d.experimental
1738
+ ? { ...measured, experimental: d.experimental }
1739
+ : measured;
1740
+ if (d.experimental) {
1741
+ process.stderr.write(`⚠ EXPERIMENTAL trigger-rate on ${d.harness ?? "?"}: ${d.experimental}\n`);
1742
+ }
1734
1743
  // Surface what the run spent (tokens + API-equivalent $ + metered warning).
1735
1744
  (0, eval_cost_js_1.emitCostSummary)((0, eval_cost_js_1.costFromArm)(report.usage));
1736
1745
  // Feed the flight recorder: recall (+ precision when measured) for this skill.
@@ -1755,7 +1764,11 @@ async function measureTriggerRate(spec, opts = {}) {
1755
1764
  /** Format a trigger-rate report: overall %, then each prompt's rate. */
1756
1765
  function formatTriggerRateReport(report) {
1757
1766
  const pct = (report.rate * 100).toFixed(0);
1758
- const lines = [`trigger-rate: ${pct}% (${String(report.n)} runs)`];
1767
+ const lines = [];
1768
+ if (report.experimental) {
1769
+ lines.push(`⚠ EXPERIMENTAL — ${report.experimental}`);
1770
+ }
1771
+ lines.push(`trigger-rate: ${pct}% (${String(report.n)} runs)`);
1759
1772
  for (const p of report.perPrompt) {
1760
1773
  lines.push(` ${p.rate.toFixed(2)} ${p.prompt.slice(0, 60)}`);
1761
1774
  }
@@ -40,6 +40,13 @@ export interface BehavioralReport {
40
40
  /** False when the `claude` CLI / auth is absent — the column couldn't run. */
41
41
  readonly available: boolean;
42
42
  readonly results: readonly SkillTriggerResult[];
43
+ /**
44
+ * Set when the driving harness measures trigger-rate on an EXPERIMENTAL basis
45
+ * (copied from {@link EvalDriver.experimental}) — Codex, whose firing is
46
+ * inferred from a SKILL.md read and can be wrong. {@link formatBehavioralReport}
47
+ * prints it as a loud caveat above the numbers. Absent = supported (Claude Code).
48
+ */
49
+ readonly experimental?: string;
43
50
  }
44
51
  export interface ProbeOptions {
45
52
  readonly concurrency?: number;
@@ -165,6 +165,7 @@ async function probePluginTriggersWith(dir, promptSet, probe, opts = {}) {
165
165
  return {
166
166
  available: true,
167
167
  results: relabelTriggerArtifact(dir, probe, results),
168
+ experimental: probe.evalDriver.experimental,
168
169
  };
169
170
  }
170
171
  /** Relabel an all-zero-recall stubbed run on a hooked plugin as unmeasured (Layer 1). */
@@ -197,6 +198,11 @@ function formatBehavioralReport(b) {
197
198
  return "Behavioral (trigger-rate): no model-invocable skills to probe";
198
199
  }
199
200
  const lines = ["Behavioral (trigger-rate):"];
201
+ // Codex-only: the trigger-rate number is not validated (no skill-selection
202
+ // event → firing inferred from a SKILL.md read). Say so loudly, above the numbers.
203
+ if (b.experimental) {
204
+ lines.push(` ⚠ EXPERIMENTAL — ${b.experimental}`);
205
+ }
200
206
  for (const r of b.results) {
201
207
  if (!r.measured) {
202
208
  lines.push(` · ${r.skill} — unmeasured (${r.note ?? "skipped"})`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vigiles",
3
- "version": "14.3.0",
3
+ "version": "14.4.0",
4
4
  "description": "Lint & test the harness your AI agent runs on — verify the references in your CLAUDE.md / AGENTS.md and test that your hooks and skills actually work.",
5
5
  "keywords": [
6
6
  "claude-code",