vigiles 14.13.4 → 15.0.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.
package/README.md CHANGED
@@ -130,13 +130,14 @@ It's free and open-source, runs entirely on your machine, and never bills per to
130
130
  <img src="vigiles-audit.png" width="760" alt="vigiles audit report for my-plugin: a verdict header reading 'Two one-line fixes away from a B.' next to a C (77/100) grade, a five-category strip (Truthfulness, Triggering, Structure, Safety, Tested), ranked fix cards with '+N pts' impact badges, broken-reference findings — and, lower down and badged experimental, a 'Your rules → enforced' preview mapping a prose rule the config silently turns off" />
131
131
  </p>
132
132
 
133
- **Like Google's Lighthouse, but for your agent harness.** One command grades it A–F across five categories, leads with a plain-English verdict — _"two one-line fixes away from a B"_ — and ranks every fix by the points it buys back:
133
+ **Like Google's Lighthouse, but for your agent harness.** One command grades it A–F across six categories, leads with a plain-English verdict — _"two one-line fixes away from a B"_ — and ranks every fix by the points it buys back:
134
134
 
135
135
  - **Truthfulness** — do the references resolve?
136
136
  - **Triggering** — do skills fire, without colliding?
137
137
  - **Structure** — are tool contracts and configs valid?
138
138
  - **Safety** — any way for the agent to leak your data?
139
- - **Tested** — does the harness ship tests?
139
+ - **Tested** — does the harness ship deterministic tests?
140
+ - **Evaluated** — has anything measured whether your skills actually _fire_? (Distinct from `0`: if nothing asked, it says **not measured**.)
140
141
 
141
142
  And it closes the loop from prose to enforcement: **your rules → enforced** maps each rule you wrote to the lint rule that actually enforces it — already on, one config line away, or silently turned off (below).
142
143
 
@@ -208,8 +209,10 @@ Or run it yourself:
208
209
 
209
210
  ```bash
210
211
  npx vigiles init # sets up the typed spec for structural rules (non-destructive — eject reverses), adds CI,
211
- # installs vigiles's skills + hooks as a Claude Code plugin (in
212
- # ~/.claude/, not your repo). On Codex, skills install globally too.
212
+ # installs vigiles's skills + hooks as a Claude Code plugin. The plugin
213
+ # CONTENT goes to ~/.claude/, never your repo; init also commits a two-key
214
+ # reference to it in .claude/settings.json so teammates get prompted to
215
+ # install it rather than silently missing it. Codex: skills install globally.
213
216
  ```
214
217
 
215
218
  **Already have a harness, or a non-JS repo?** `npx vigiles init --ci-only` sets up just the CI integrity gate — nothing installed, zero conflict. **[When to use gate vs full →](docs/agent-setup.md#non-interactive-setup-agents--ci)**
@@ -230,6 +233,7 @@ The **hooks** keep it honest in-loop — nudging the agent to tag a linter-rule
230
233
  - **Both lint and test** by default; scope with `--lint` / `--test`.
231
234
  - **Already have a CLAUDE.md / AGENTS.md, skills, or subagents? `audit` and `lint` read them as-is** — nothing is moved or rewritten. For the structural rules that want a typed spec, `init` sets one up **non-destructively** (`eject` undoes it).
232
235
  - Adds `vigiles` to `devDependencies`; installs the Claude Code plugin (skills + hooks) via the marketplace — globally, never vendored.
236
+ - Declares that plugin in your repo's `.claude/settings.json` (`extraKnownMarketplaces` + `enabledPlugins`, merged into whatever is already there). This is a **reference, not content** — nothing is vendored, and it does **not** install the plugin for a teammate: an external-source plugin declared project-level [doesn't load until each person installs it](https://code.claude.com/docs/en/discover-plugins#configure-team-marketplaces). What it buys is that Claude Code **prompts** them with the install command, instead of a fresh clone silently having the npm package and none of its skills.
233
237
  - Wires CI as a `zernie/vigiles@v1` workflow (needs only read + PR-comment permissions) that posts a sticky PR comment + a `valid` output.
234
238
 
235
239
  Targets Claude Code and Codex out of the box, or [your own harness](docs/authoring-an-adapter.md). Prefer to write tests yourself? JS **or** TS (`*.harness.{mjs,ts}`) — run with `npx vigiles test`.
@@ -11,7 +11,7 @@
11
11
  * timestamp is attached by the CLI at write time, never by this pure builder, so
12
12
  * the embedded-in-HTML form stays deterministic).
13
13
  */
14
- import { type AuditScore } from "./audit-score.js";
14
+ import { type AuditScore, type AuditScoreOptions } from "./audit-score.js";
15
15
  import { type Recommendation } from "./optimize.js";
16
16
  import { type Verdict } from "./audit-verdict.js";
17
17
  import type { LedgerSummary } from "./observe.js";
@@ -20,6 +20,7 @@ import type { ScanReport, MarketplaceInfo } from "./scan.js";
20
20
  import type { PluginScore } from "./score-core.js";
21
21
  import type { RuleInventoryItem } from "./rule-inventory.js";
22
22
  import type { RuleRouting } from "./rule-routing.js";
23
+ import type { EvidenceCounts } from "./coverage-evidence.js";
23
24
  /**
24
25
  * The current schema version. Bump only on a BREAKING change to the shape.
25
26
  * v2 (2026-07-15): the rule-map `mechanism` enum value for an unrouted rule
@@ -55,7 +56,26 @@ export interface AuditInventory {
55
56
  readonly hooks: number;
56
57
  readonly commands: number;
57
58
  readonly mcp: boolean;
59
+ /** Surfaces covered by NEITHER tier — the union count (unchanged). */
58
60
  readonly untested: number;
61
+ /**
62
+ * The two tiers, carried SEPARATELY so a consumer can tell "has deterministic
63
+ * coverage, no evals" from "has neither" — a distinction the single `untested`
64
+ * count erased. `untestedHarness` is free-and-every-push work; `unevaluated` is
65
+ * paid real-model work. Additive/optional — schema version unchanged.
66
+ */
67
+ readonly untestedHarness?: number;
68
+ readonly unevaluated?: number;
69
+ /**
70
+ * HOW the covered surfaces were decided to be covered — `declared` (an explicit
71
+ * `vigiles:covers` marker), `colocated` (a test placed at the surface), or
72
+ * `mention` (the surface's path/namespace appears in a test's code). Carried in
73
+ * the product boundary because a coverage count without its derivation is not
74
+ * auditable: a repo whose coverage is entirely `mention` looks, in a bare
75
+ * number, exactly like one with real tests. Additive/optional — schema version
76
+ * unchanged.
77
+ */
78
+ readonly coverageEvidence?: EvidenceCounts;
59
79
  }
60
80
  /**
61
81
  * A surface (skill / subagent / instruction file) that EXISTS but doesn't yet
@@ -86,7 +106,7 @@ export interface Adoptable {
86
106
  */
87
107
  export interface AuditReport {
88
108
  readonly meta: AuditReportMeta;
89
- /** The five deterministic category rings + the weighted overall + grade. */
109
+ /** The six category rings + the weighted overall + grade. */
90
110
  readonly score: AuditScore;
91
111
  /**
92
112
  * The one-line verdict + per-recommendation `pointsIfFixed`, both derived by
@@ -147,7 +167,7 @@ export interface AuditReport {
147
167
  */
148
168
  readonly ruleRouting?: RuleRouting;
149
169
  }
150
- export interface BuildAuditReportOptions {
170
+ export interface BuildAuditReportOptions extends AuditScoreOptions {
151
171
  readonly harness: string;
152
172
  readonly vigilesVersion: string;
153
173
  /** The flight-recorder summary from the local ledger (omit when empty). */
@@ -53,7 +53,7 @@ function buildAdoptable(surfaces) {
53
53
  */
54
54
  function buildAuditReport(report, opts) {
55
55
  const adoptable = buildAdoptable(opts.adoptableSurfaces);
56
- const score = (0, audit_score_js_1.auditScore)(report);
56
+ const score = (0, audit_score_js_1.auditScore)(report, { firingMeasured: opts.firingMeasured });
57
57
  const recommendations = (0, optimize_js_1.optimize)(report).recommendations;
58
58
  const verdict = (0, audit_verdict_js_1.computeVerdict)({ report, score, recommendations });
59
59
  return {
@@ -78,6 +78,15 @@ function buildAuditReport(report, opts) {
78
78
  commands: report.commands,
79
79
  mcp: report.mcp,
80
80
  untested: report.untested,
81
+ ...(report.untestedHarness !== undefined
82
+ ? { untestedHarness: report.untestedHarness }
83
+ : {}),
84
+ ...(report.unevaluated !== undefined
85
+ ? { unevaluated: report.unevaluated }
86
+ : {}),
87
+ ...(report.coverageEvidence
88
+ ? { coverageEvidence: report.coverageEvidence }
89
+ : {}),
81
90
  },
82
91
  ...(report.danglingRefs.length
83
92
  ? { brokenReferences: report.danglingRefs }