vigiles 8.0.0 → 9.1.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
@@ -3,40 +3,42 @@
3
3
  This file is the FRONT DOOR + a marketing asset for someone who already lives
4
4
  in Claude Code / Codex. Optimize for a phone-skimmer.
5
5
 
6
- 1. LEAD WITH BENEFITS, not mechanics or vocabulary. Say what the user GETS
7
- (a guard that can't silently fail; a CLAUDE.md that stops lying) before how.
8
- 1b. NEVER OPEN WITH A NEGATIVE, APOLOGY, OR CAVEAT. A bolded lead-in is the
9
- FIRST thing a skimmer reads, so it must be the benefit/on-ramp, never a
10
- deficiency or competitor: write "Start in plain markdown", NOT "No
11
- TypeScript?". Put the STRONGEST proof (e.g. 2/7→7/7) on its OWN line, never
12
- buried mid-paragraph, and END a section on the win, not the caveat (demote
13
- trade-offs to a trailing aside). Break run-on em-dash/semicolon chains — a
14
- paragraph is ~3 lines, one idea.
15
- 1c. LEAD WITH THE CONCRETE PAIN the reader already feels — named in THEIR
16
- situation, with the SPECIFIC silent failure, not an abstraction. "You
17
- installed plugins and wrote skills but do they actually work? A skill that
18
- never fires, a hook that blocks nothing, a CLAUDE.md full of dead refs" beats
19
- "reliability for your harness"; "a library with no tests" is the anchoring
20
- analogy. This is NOT a 1b violation: a pain about the READER's situation is a
21
- hook, not an apology — 1b bans opening with vigiles's OWN deficiency, a
22
- caveat, or a competitor, never the user's pain. SAME FOR THE SUBDOCS: open
23
- every guide with the concrete pain, THEN the "what this doc is" line + the
24
- README uplink (per docs-quality in CLAUDE.md).
25
- 2. COMPILED SPECS ARE EASY reassure, never intimidate. You rarely hand-write
26
- a .spec.ts: model-invocable skills (edit-spec / strengthen / test-harness)
27
- author + edit it, and hooks auto-compile on save. Present the typed spec as
28
- the SMOOTH, AUTO-ENFORCED next step you don't think about the natural
29
- evolution (JS→TS: gradual, strict opt-in), NEVER a wall. Markdown + inline
30
- mode work with zero TS for anyone not there yet (progressive adoption).
31
- 3. THE INSTRUMENTS stay first-class including Eval (measuring whether a skill
32
- actually helps is core, not optional). NOTE: Guard / compiled hooks is PARKED
33
- FOR LAUNCH (commented out below; see research/roadmap.md "Launch readiness")
34
- so the live set is Lint/Test/Eval ("three instruments"); re-add Guard post-HN.
35
- 4. SCANNABLE + SHORT ~200-line cap; punchy table cells, bullets, runnable
36
- blocks; benefits over jargon. Push depth into docs/ and LINK it.
37
- 5. NO INTERNAL VOCABULARY (moat / measurement-authority / flywheel) and NO
38
- research/ links — name the user benefit (see public-vs-internal-docs +
39
- readme-brevity in CLAUDE.md).
6
+ SPINE = CONCEPT 5 (proof/demo-led). Lead with REAL, screenshotable catches on
7
+ plugins people actually ship, THEN explain the mechanism. The proofs are not
8
+ illustrative every block traces to a real dogfood run captured in
9
+ research/dogfood/. HYBRID proof source (decided 2026-06-28): Proofs 1-2 are
10
+ COMMUNITY catches, anonymized (a missing SKILL.md, an AskUserQuestion-never-
11
+ available tool) official plugins don't have those silent-failure bugs. Proofs
12
+ 3-4 are OFFICIAL + NAMED: pr-review-toolkit (malformed YAML + unrestricted review
13
+ agents) and the all-37 Anthropic-official leaderboard (A→F, LSP stubs excluded).
14
+ NEVER replace a real catch with a fabricated one.
15
+
16
+ DON'T SHAME OSS: community catches are real but ANONYMIZED in public copy (no
17
+ obra/superpowers, madappgang by name)real names live only in research/dogfood/.
18
+ Punch UP at official/vendor plugins (Anthropic's own are NAMED); never name a
19
+ volunteer's repo to show its bug. Proof 3/4 don't show pr-review-toolkit's audit-
20
+ RING score (88) only the leaderboard score (52 F) — so the two never clash.
21
+
22
+ 1. LEAD WITH BENEFITS / the reader's CONCRETE PAIN, never an apology, caveat, or
23
+ competitor. A bolded lead-in is the first thing read make it the hook/win.
24
+ End a section on the win, not the trade-off. A paragraph is ≤ ~3 lines.
25
+ 2. PROOF FIRST, mechanism second. The three instruments (Lint/Test/Eval) come
26
+ AFTER the proof stack as "how it does it", not as a competing front door.
27
+ 3. SPEC-FIRST IS THE DEFAULT but easy `init` ADOPTS your CLAUDE.md into a spec,
28
+ skills edit it, you rarely hand-write .spec.ts. Give it ONE home (Quick start),
29
+ not five scattered mentions. `eject` always reverses. Inline markdown is the
30
+ zero-TS floor.
31
+ 4. Guard / compiled hooks is PARKED FOR LAUNCH (see research/roadmap.md). Live set
32
+ is Lint/Test/Eval. Do NOT make the 2/7→7/7 battery the hero — re-add post-HN.
33
+ 5. SCANNABLE + SHORT — ~200-line cap; punchy cells, bullets, runnable blocks.
34
+ Push depth into docs/ and LINK it.
35
+ 6. NO INTERNAL VOCABULARY (moat / measurement-authority / flywheel) and NO
36
+ research/ links name the user benefit.
37
+ 7. ASSETS: the hero vigiles-audit.png must be REFRESHED from a real run
38
+ (research/dogfood/audit-superpowers.html) without the dialect drift banner
39
+ before launch. (vigiles-demo.gif was removed from Proof 1 — it rendered as a
40
+ frozen half-typed terminal and was redundant with the code block; if a lint
41
+ demo returns, it belongs in the Lint section with a non-frozen asset.)
40
42
  -->
41
43
 
42
44
  <p align="center">
@@ -46,7 +48,7 @@
46
48
  <h1 align="center">vigiles</h1>
47
49
 
48
50
  <p align="center">
49
- <strong>Make the harness your AI agent runs on reliable.</strong>
51
+ <strong>The tests your AI agent harness never had.</strong>
50
52
  </p>
51
53
 
52
54
  <p align="center">
@@ -58,123 +60,107 @@
58
60
  ---
59
61
 
60
62
  **You installed a bunch of plugins and wrote a few skills — but do they actually work?**
61
- A skill that never fires, a safety hook that blocks nothing, a CLAUDE.md full of dead
62
- references — your harness fails **silently**, and you find out mid-task.
63
+ A skill that never fires, a subagent wired to a tool that doesn't exist, a CLAUDE.md
64
+ full of dead references — your harness fails **silently**, and you find out mid-task.
63
65
 
64
- **It's a library with no tests.**
66
+ **It's a library with no tests.** One command runs them — no key, no config, safe on
67
+ any repo:
65
68
 
66
- `Agent = Model + Harness` — the model gets the headlines, the harness is the half you
67
- own. vigiles[^name] makes it prove itself **before the agent ever runs** — verify, test,
68
- measure. Mostly free, no API key — real-model checks run on your **Claude Pro/Max
69
- subscription, not metered tokens**.
70
-
71
- Three instruments, adopt any:
69
+ ```bash
70
+ npx vigiles audit
71
+ ```
72
72
 
73
- | | |
74
- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
75
- | **🔎 Lint** | Your CLAUDE.md stops lying — every path, script, symbol & linter rule checked against **reality**. **[→](docs/verifying-instruction-files.md)** |
76
- | **🧪 Test** | Prove your hooks, skills & subagents do their job — **free, no API key**. **[→](docs/harness-testing.md)** |
77
- | **📊 Eval** | Know if a skill helps or just costs — **A/B on real tasks**, on your own subscription. **[→](docs/measuring-skills.md)** |
73
+ Here's what it found on real, popular plugins. ↓
78
74
 
79
- <!-- PARKED FOR LAUNCH — Guard / compiled hooks. Re-add this row + the ④ section below post-HN. See research/roadmap.md "Launch readiness".
80
- | **🛡 Guard** | A safety hook that **can't silently fail open** — write a typed function, get a guard that blocks. **[→](docs/compiled-hooks.md)** |
81
- -->
75
+ ## The report
82
76
 
83
77
  <p align="center">
84
- <img src="vigiles-demo.gif" width="720" alt="vigiles lint catching a file that moved and a script that was renamed" />
78
+ <img src="vigiles-audit.png" width="760" alt="vigiles audit report: an overall score with four category rings Truthfulness, Triggering, Structure, Tested — and fix cards" />
85
79
  </p>
86
- <!-- Regenerate the GIF: `python3 scripts/make-demo-gif.py` (output is verbatim CLI; see scripts/demo.sh for a live asciinema recording). -->
80
+ <!-- REFRESH before launch from research/dogfood/audit-superpowers.html (a real catch, no drift banner). -->
87
81
 
88
- **Two ways in** pick the pain that's yours:
82
+ Four deterministic rings, **each finding's fix inline**, and a shareable HTML report.
83
+ Like Lighthouse, `audit` is a **local report you run on your machine** — safe on any
84
+ repo (even one wired to prod), identical on every OS. **Not a CI step** (CI uses
85
+ `lint`). **[Audit a harness →](docs/for-plugin-authors.md)**
89
86
 
90
- - **Run agents on your own repo?** Start with **Lint** below, or `npx vigiles init`.
91
- - **Ship plugins to a marketplace?** **[`vigiles scan`](docs/for-plugin-authors.md)**
92
- ranks structural health with no key — see the **[plugin-author guide →](docs/for-plugin-authors.md)**.
87
+ ## Proof 1 your CLAUDE.md is lying to your agent
93
88
 
94
- **Your agent writes the spec — and you can always eject.** You rarely hand-write a
95
- `.spec.ts`: skills author it for you, **`init` adopts an existing CLAUDE.md
96
- non-destructively** (untouched until you compile), and plain markdown + inline
97
- `<!-- vigiles:enforce -->` comments work with zero TypeScript. **Claude Code and
98
- Codex** ([`vigiles/codex`](docs/harnesses.md)), or [your own
99
- harness](docs/authoring-an-adapter.md). _(New here? [the FAQ](docs/faq.md) covers the
100
- "do I write TypeScript / will it touch my files" questions.)_
89
+ ```text
90
+ Truthfulness 92
91
+ └ ✗ skills/using-debugging/SKILL.md (referenced but MISSING)
92
+ ```
101
93
 
102
- ## Quick start
94
+ A real, widely-installed plugin — its instructions send the agent to a skill file
95
+ that **isn't there**. Valid markdown, but not _true_, and your agent trusts it anyway.
103
96
 
104
- **Paste into Claude Code or Codex:**
97
+ File paths, scripts, code symbols — plus linter rules across **7 linters** (ESLint,
98
+ Ruff, Clippy + four more): each one **exists _and_ is enabled**. **[Full guide →](docs/verifying-instruction-files.md)**
99
+
100
+ ## Proof 2 — a tool your subagent silently can't call
105
101
 
106
102
  ```text
107
- Set up vigiles in this repo: run `npx vigiles init` and accept the defaults. If I
108
- already have a CLAUDE.md or AGENTS.md, adopt it into a spec and show me which
109
- references are stale. Then install the dep, compile, and write + run one harness
110
- test for a hook or skill of mine. Don't enforce a spec-per-file or add a real-model
111
- eval without asking me first.
103
+ tester Tool "AskUserQuestion" is never available to a subagent.
104
+ remove or correct it it's silently dropped from the contract.
112
105
  ```
113
106
 
114
- The same prompt works in Codex.
107
+ A real upstream subagent declares a tool the harness **silently drops**, so it loses
108
+ a capability it thinks it has. vigiles flags it _and_ hands you the one-line fix —
109
+ **free, no model.** That's the difference from a markdown linter: it checks your
110
+ harness against **reality**, not style.
115
111
 
116
- Or do it yourself:
112
+ ## Proof 3 — even the official plugins
117
113
 
118
- ```bash
119
- npx vigiles init # sets up lint + test: spec + harness test + CI + plugin
114
+ Not cherry-picked community repos — **Anthropic's own official `pr-review-toolkit`**:
115
+
116
+ ```text
117
+ ✗ silent-failure-hunter.md — frontmatter isn't valid YAML (won't parse)
118
+ ⚠ 6 review agents inherit ALL tools — a code-reviewer with Write + Bash
120
119
  ```
121
120
 
122
- Interactive in a terminal, non-interactive for agents/CI (or `--yes`).
121
+ A subagent whose YAML doesn't parse, and six review agents holding far more power than
122
+ a reviewer needs — real findings on a first-party plugin. _(We name Anthropic's own;
123
+ the community plugins above stay anonymous — punch up, don't shame volunteers.)_
123
124
 
124
- **You don't hand-write any of this your agent does.** `init` installs
125
- model-invocable skills, so a plain-English ask does the work (it edits the source
126
- and recompiles on save; you never touch it by hand):
125
+ ## Proof 4rank a whole marketplace
127
126
 
128
- - _"test my skills"_ scaffolds **and runs** a trigger/behaviour test (`test-harness`)
129
- - _"harden my rules"_ upgrades prose guidance into enforced linter rules (`strengthen`)
130
- - _"add a rule to my CLAUDE.md"_ → edits the source and recompiles (`edit-spec`)
127
+ `audit` ranks a folder of plugins by what's actually **broken** no key. Run across
128
+ **all of Anthropic's official plugins**, it flags exactly **one** real outlier no
129
+ false-positive noise (untested surfaces are advisory):
131
130
 
132
- <details>
133
- <summary>What <code>init</code> sets up</summary>
131
+ ```text
132
+ # score grade plugin
133
+ 1 100 A code-review ← 24 of 25 come back a clean A
134
+ 25 70 C pr-review-toolkit — 6 agents inherit all tools (a reviewer with Write + Bash)
135
+ ```
134
136
 
135
- - **Both lint and test** by default; scope with `--lint` / `--test`.
136
- - **Already have a CLAUDE.md / AGENTS.md? `init` adopts it** into a spec faithfully and **non-destructively** — your file is left untouched until you choose to `compile` (and `eject` undoes it).
137
- - Adds `vigiles` to `devDependencies`; installs the Claude Code plugin (skills + hooks) via the marketplace — globally, never vendored.
138
- - Wires CI as a `zernie/vigiles@v1` workflow (a composite over the same CLI) that posts a sticky PR comment + a `valid` output.
137
+ <sub>Real scores on Anthropic's own marketplace a fair tool flags the one real issue, not noise (empty LSP stubs excluded).</sub>
139
138
 
140
- Prefer to write tests yourself? They can be JS **or** TS
141
- (`*.harness.{mjs,ts}`) — run them with `npx vigiles test`.
139
+ **[Plugin-author guide →](docs/for-plugin-authors.md)**
142
140
 
143
- </details>
141
+ > **And it grades itself: 100/100, A, all four rings green.** vigiles runs `audit` on
142
+ > its own harness in CI. We eat what we cook.
144
143
 
145
- ## Lint your CLAUDE.md lies to your agent
144
+ ## How it does it three instruments
146
145
 
147
- **Your CLAUDE.md drifts the moment you refactor.** It points the agent at
148
- `src/auth/login.ts` and says run `npm run check`but the file moved six commits
149
- ago and the script was renamed. The agent trusts the stale claim and acts on
150
- fiction. `npx vigiles lint` resolves every reference against reality:
146
+ `Agent = Model + Harness`[^name]. The model gets the headlines; the **harness** is the
147
+ half you own. `audit` is the dashboard these fix and prove what it finds.
151
148
 
152
- ```text
153
- CLAUDE.md:
154
- ✗ src/auth/login.ts — no such file (renamed or moved?)
155
- ✗ npm run check — not in package.json. Did you mean: "check:types"?
156
- ✓ @typescript-eslint/no-floating-promises — exists and enabled in eslint config
157
- ```
149
+ ### 🔎 Lint — your CLAUDE.md stops lying
158
150
 
159
- File paths, scripts, code symbols plus linter rules across **7 linters**
160
- (ESLint, Ruff, Clippy + four more): each rule exists **and is enabled**.
151
+ Every path, script, symbol & linter rule resolved against reality (the catches
152
+ above). **You don't write any of it** `npx vigiles init` **adopts your existing
153
+ CLAUDE.md _and every skill and subagent_ into verified specs**, non-destructively
154
+ (untouched until you `compile`; `eject` reverses). After that, plain-English asks
155
+ edit them for you. Prefer zero new files? Plain markdown + one inline
156
+ `<!-- vigiles:enforce -->` comment lints too — no TypeScript.
157
+ **[How →](docs/verifying-instruction-files.md)**
161
158
 
162
- **Start with one inline comment no new files.** Step up to a typed `.spec.ts`
163
- (your agent writes it; it compiles to CLAUDE.md) when you want compiler-grade
164
- guarantees — and `vigiles eject` hands it back to plain markdown anytime.
165
- **[Full guide →](docs/verifying-instruction-files.md)**
159
+ ### 🧪 Testdoes the harness actually do its job?
166
160
 
167
- > **Want more? Bad states can stop compiling.** Opt in deeper and a broken
168
- > hand-off between agents becomes a build error instead of a runtime surprise
169
- > graduated like TypeScript's `strict`, on only when you want it.
170
- > **[How →](docs/compiled-hooks.md)**
171
-
172
- ## ② Test — does your harness do its job?
173
-
174
- **You wired the hook — but does it actually block?** A skill's description can fail
175
- to trigger, or hijack unrelated prompts; injected context can silently never reach
176
- the model. All of it passes a naive "did it run?" check. vigiles tests the
177
- assembled harness for real:
161
+ A hook that blocks nothing, a skill that hijacks unrelated prompts, injected context
162
+ that never reaches the model — all pass a naive "did it run?" check. Start at the
163
+ cheapest tier: a hook, called directly. **No model, no key:**
178
164
 
179
165
  ```typescript
180
166
  import { runHook } from "vigiles/testing";
@@ -187,88 +173,68 @@ const r = runHook(guard, {
187
173
  assert(r.blocked); // a red ✗ means your guard silently lets it through
188
174
  ```
189
175
 
190
- It goes well past _"did it fire?"_:
176
+ Hooks **block** · skills **trigger** (recall _and_ precision) · subagents **finish**
177
+ in the outcome they promised (no LLM judge) · **safety holds** — `interceptTools`
178
+ catches a push or paid-API call as an _attempt_, so the side effect never happens.
179
+ Almost every tier runs with **no model and no key**, on every commit.
180
+ **[How testing works →](docs/harness-testing.md)**
191
181
 
192
- - **Hooks block** what they must `runHook`, or the real agent CLI via `runHarnessTest`.
193
- - **Skills trigger** on the right prompts and stay quiet on the wrong ones — recall _and_ precision (`measureTriggerRate`).
194
- - **Behaviour is good** — score a skill's output, or A/B it on-vs-off for the real lift (`measure` / `runEval`, with significance testing).
195
- - **Safety holds** — the agent _didn't_ push to the wrong branch or hit a paid API; `interceptTools` catches the attempt so the side effect never happens.
182
+ ### 📊 Eval does a skill help, or just cost more?
196
183
 
197
- Almost every tier runs with **no model and no API key** milliseconds, on every
198
- commit; only the real-model evals need a model, on your own `claude` CLI.
199
- **[How it works →](docs/harness-testing.md)**
184
+ _"65% fewer tokens." Says who?_ vigiles A/Bs the claim on real coding tasks and reports
185
+ the **bill**, the **target it claims to move**, and the **blast radius** (did the code
186
+ still work?).
200
187
 
201
- ## Eval does it actually help, or just cost more?
188
+ **The eval you can actually afford:** promptfoo / DeepEval hit a metered API and bill
189
+ **per token, every run**. vigiles answers most questions with **no model at all**, and
190
+ runs the rest on your own **Claude Pro/Max subscription — $0 extra.**
191
+ **[Measure a skill →](docs/measuring-skills.md)**
202
192
 
203
- **"65% fewer tokens." "3× faster." Says who?** A skill claims it, a plugin promises
204
- it — stars and vibes, **zero measurement**. vigiles A/Bs the claim on real coding
205
- tasks, the harness loaded exactly as it ships, and reports the **metric triple**:
193
+ ## Quick start
206
194
 
207
- ```typescript
208
- import { measureArms } from "vigiles/testing";
195
+ **Paste into Claude Code or Codex:**
209
196
 
210
- const r = await measureArms({
211
- fixture: { "in.txt": "Implement a slug helper." },
212
- task: "Read in.txt, write slugify() to slug.js, explain. Stop.",
213
- arms: { baseline: {}, skill: { files: { "SKILL.md": THE_SKILL } } },
214
- measure: (ctx) => ({ cost: ctx.usage.costUsd, correct: check(ctx) }),
215
- });
197
+ ```text
198
+ Set up vigiles in this repo: run `npx vigiles init` and accept the defaults. If I
199
+ already have a CLAUDE.md or AGENTS.md, adopt it into a spec and show me which
200
+ references are stale. Then install the dep, compile, and write + run one harness
201
+ test for a hook or skill of mine. Don't enforce a spec-per-file or add a real-model
202
+ eval without asking me first.
216
203
  ```
217
204
 
218
- - **The bill (`costUsd`)** — weights cache ~0.1× / output 1×, so a "saved tokens" headline can't hide behind cheap cache.
219
- - **The target** — whatever the skill claims to move (output tokens, latency, tool calls), verified on its own terms.
220
- - **The blast radius** — correctness, a deterministic 1/0. A token win that breaks the code is **not a win**.
221
-
222
- **Safe to repeat.** Each real-model run is sandboxed (ephemeral dir, egress blocked
223
- or allow-listed), and `interceptTools` catches an irreversible external — a push, a
224
- paid API — as an _attempt_, never running it. **[Safety, sandboxing & FAQ →](docs/safety.md)**
225
-
226
- **The eval you can actually afford.** promptfoo / DeepEval hit a metered API and
227
- bill **per token, every run**. vigiles answers most questions with **no model at
228
- all**, and runs the rest on your own **Claude Pro/Max subscription — $0 extra**. So
229
- you can measure on every change. **[Eval a skill →](docs/measuring-skills.md)** · **[Why it's affordable →](docs/eval-architecture.md)**
205
+ Or do it yourself:
230
206
 
231
- <!-- PARKED FOR LAUNCH — Guard / compiled hooks. Re-add this whole section (and the table row above) post-HN. See research/roadmap.md "Launch readiness".
207
+ ```bash
208
+ npx vigiles init # lint + test: spec + harness test + CI + plugin
209
+ ```
232
210
 
233
- ## Guard — a safety hook that can't silently fail open
211
+ Interactive in a terminal, non-interactive for agents/CI (or `--yes`).
234
212
 
235
- **Your safety hook looks like it blocks and doesn't.** A guard is your last stop
236
- before something irreversible, but a hand-written one **fails open** without telling
237
- you. _(Already write safety hooks? This is the power tool.)_ Write a pure typed
238
- function instead; vigiles emits the exit code, the JSON, and an AST-backed matcher:
213
+ **You don't hand-write any of thisyour agent does.** `init` installs
214
+ model-invocable skills, so a plain-English ask does the work:
239
215
 
240
- ```typescript
241
- import { defineHook, tool, deny, allow } from "vigiles/hook";
242
-
243
- export default defineHook({
244
- on: "PreToolUse",
245
- match: tool("Bash"),
246
- decide: (e) =>
247
- e.command.runs("git push", { force: true })
248
- ? deny("no force-push to a protected branch")
249
- : allow(),
250
- });
251
- ```
216
+ - _"test my skills"_ → scaffolds **and runs** a trigger/behaviour test (`test-harness`)
217
+ - _"harden my rules"_ upgrades prose guidance into enforced linter rules (`strengthen`)
218
+ - _"add a rule to my CLAUDE.md"_ → edits the source and recompiles (`edit-spec`)
252
219
 
253
- **The proof:** a widely-copied OSS safety hook blocks **2/7** of the disaster
254
- battery. The compiled rewrite blocks **7/7** — measured, not asserted.
220
+ <details>
221
+ <summary>What <code>init</code> sets up</summary>
255
222
 
256
- You never hand-write the exit code or JSON field (the usual false confidence), the
257
- matcher is **AST-backed** (it catches the `cd x && git push -f` a glob misses), and
258
- the artifact is **stamped** so a later hand-edit is refused.
223
+ - **Both lint and test** by default; scope with `--lint` / `--test`.
224
+ - **Already have a CLAUDE.md / AGENTS.md, skills, or subagents? `init` adopts them all** into specs faithfully and **non-destructively** — untouched until you `compile` (and `eject` undoes it).
225
+ - Adds `vigiles` to `devDependencies`; installs the Claude Code plugin (skills + hooks) via the marketplace — globally, never vendored.
226
+ - Wires CI as a `zernie/vigiles@v1` workflow that posts a sticky PR comment + a `valid` output.
259
227
 
260
- _Scope: this fixes a hook's logic, not the harness's delivery — a subagent's tool
261
- calls still bypass any PreToolUse hook
262
- ([#34692](https://github.com/anthropics/claude-code/issues/34692)), so it's a strong
263
- default, not an unbypassable wall._
264
- **[Compiled hooks — bug classes + trade-offs →](docs/compiled-hooks.md)**
228
+ Works with **Claude Code and Codex** ([`vigiles/codex`](docs/harnesses.md)) or
229
+ [your own harness](docs/authoring-an-adapter.md). Prefer to write tests yourself?
230
+ JS **or** TS (`*.harness.{mjs,ts}`) run with `npx vigiles test`.
265
231
 
266
- -->
232
+ </details>
267
233
 
268
234
  ## FAQ
269
235
 
270
236
  - **Isn't this just a markdown linter?** No — it checks whether your instruction file is _true_ (every path/script/symbol/rule exists and is enabled), then tests and measures your harness. A style linter can't do any of that.
271
- - **Do I have to write TypeScript?** No. Lint your markdown with zero new files; when you want a spec, your agent writes it. It's gradual, like TS's `strict`.
237
+ - **Do I have to write TypeScript?** No your agent writes the spec (`init` adopts your CLAUDE.md into one). Prefer zero new files? Plain markdown lints too. Deeper compiler-grade guarantees are gradual and opt-in, like TS's `strict`.
272
238
  - **Does it overwrite my files?** No. `init` adopts an existing CLAUDE.md _non-destructively_ — untouched until you `compile`, and `eject` reverses it.
273
239
  - **Need an API key?** No for almost everything (free, every commit). Real-model evals run on your Claude Pro/Max subscription — $0 metered tokens.
274
240
  - **Non-JS repo?** `npx vigiles lint` verifies your CLAUDE.md with no install (Ruff/Clippy/Pylint/… too).
@@ -277,11 +243,11 @@ default, not an unbypassable wall._
277
243
 
278
244
  ## More
279
245
 
280
- - **[CLI →](docs/cli.md)** — every command and the plugin · **[GitHub Action →](docs/github-action.md)** run it in CI. The full **[lint rules matrix →](docs/verifying-instruction-files.md#the-validation-rules--the-full-matrix)** lives with the linting guide.
246
+ - **[CLI →](docs/cli.md)** · **[GitHub Action →](docs/github-action.md)** · the full **[lint rules matrix →](docs/verifying-instruction-files.md#the-validation-rules--the-full-matrix)** lives with the linting guide.
281
247
  - **[Skills →](docs/skills.md)** — the skills `init` installs, and how the model-invocable ones trigger.
282
- - **[Ship plugins? The plugin-author guide →](docs/for-plugin-authors.md)** — scan a draft for structural health, make your skills fire for users, then rank a whole marketplace (0–100, A–F, worst issues first) **no key**.
283
- - **[Docs index →](docs/README.md)** · **[API reference →](https://zernie.github.io/vigiles/)** · **[Related tools →](docs/related-tools.md)** (ast-grep, Dependency Cruiser, Ruler, rulesync).
284
- - **[Stability →](STABILITY.md)** — 0.x: the CLI is stable; the library API is still evolving; experimental surfaces are marked.
248
+ - **[Ship plugins? The plugin-author guide →](docs/for-plugin-authors.md)** — scan a draft, make your skills fire, rank a whole marketplace — no key.
249
+ - **[Docs index →](docs/README.md)** · **[API reference →](https://zernie.github.io/vigiles/)** · **[Related tools →](docs/related-tools.md)**.
250
+ - **[Stability →](STABILITY.md)** — 0.x: the CLI is stable; the library API is still evolving.
285
251
  - **Not for you if** you want a model/capability benchmark or runtime guardrails in the request path — vigiles is build-/CI-time.
286
252
  - Companion to [Feedback Loop Is All You Need](https://zernie.com/blog/feedback-loop-is-all-you-need).
287
253
 
@@ -0,0 +1,55 @@
1
+ import { type AgentRunner, type ModelOutputParser } from "./eval.js";
2
+ /** A reference the model proposes as machine-verifiable. */
3
+ export interface DraftedRef {
4
+ readonly kind: "enforce" | "file" | "cmd" | "dir";
5
+ readonly ref: string;
6
+ }
7
+ /** A drafted ref that failed verification — the value proof. */
8
+ export interface BrokenRef {
9
+ readonly kind: DraftedRef["kind"];
10
+ readonly ref: string;
11
+ readonly issue: string;
12
+ }
13
+ export interface AdoptabilityResult {
14
+ /** Distinct verifiable references the model found (the surface a spec would protect). */
15
+ readonly total: number;
16
+ /** How many of those are broken in this repo right now. */
17
+ readonly broken: number;
18
+ readonly brokenRefs: readonly BrokenRef[];
19
+ }
20
+ /**
21
+ * Deterministic verdict over drafted refs — the "disposes" half. Dedupes
22
+ * (kind+ref), routes each to the real cross-ref/filesystem check, and counts the
23
+ * broken. Pure: a hallucinated rule resolves to broken, never trusted as a pass.
24
+ */
25
+ export declare function verifyDraftedRefs(refs: readonly DraftedRef[], basePath: string): AdoptabilityResult;
26
+ /**
27
+ * Tolerant parse of the model's draft output into `DraftedRef[]`. The model is
28
+ * asked for a bare JSON array, but tolerate prose-wrapped / fenced output by
29
+ * extracting the outermost `[...]`. Drops any entry with an unknown kind or a
30
+ * non-string ref (the verifier is the guard, but a malformed shape is just noise).
31
+ */
32
+ export declare function parseDraftJson(text: string): DraftedRef[];
33
+ /** Options for the real model draft (the one v8-ignored seam). */
34
+ export interface DraftOptions {
35
+ readonly model?: string;
36
+ readonly cwd?: string;
37
+ readonly runner?: AgentRunner;
38
+ readonly parse?: ModelOutputParser;
39
+ }
40
+ /** Injectable drafter — the real one calls a model; tests pass a fake. */
41
+ export type Drafter = (content: string) => Promise<DraftedRef[]>;
42
+ export interface AdoptabilityTierOptions {
43
+ readonly instructionContent: string;
44
+ readonly basePath: string;
45
+ /** Injectable for tests; defaults to the real one-shot model draft. */
46
+ readonly draft?: Drafter;
47
+ }
48
+ /**
49
+ * Run the preview: draft refs from the instruction file (model), then verify them
50
+ * (deterministic). The composition root of "LLM proposes, deterministic disposes".
51
+ */
52
+ export declare function runAdoptabilityTier(opts: AdoptabilityTierOptions): Promise<AdoptabilityResult>;
53
+ /** Terminal section — the adoption invitation, not a graded ring. */
54
+ export declare function formatAdoptability(r: AdoptabilityResult, instructionFile: string): string;
55
+ //# sourceMappingURL=adoptability.d.ts.map