vigiles 2.0.0 → 2.1.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.
Files changed (160) hide show
  1. package/README.md +108 -131
  2. package/dist/cli.js +303 -161
  3. package/dist/compile.d.ts +1 -0
  4. package/dist/compile.js +22 -19
  5. package/dist/coverage.d.ts +56 -0
  6. package/dist/coverage.js +178 -0
  7. package/dist/doc-refs.d.ts +60 -0
  8. package/dist/doc-refs.js +246 -0
  9. package/dist/evolve.js +60 -125
  10. package/dist/frontmatter.d.ts +57 -0
  11. package/dist/frontmatter.js +190 -0
  12. package/dist/generate-schema.d.ts +51 -0
  13. package/dist/generate-schema.js +115 -0
  14. package/dist/generate-types.js +39 -1
  15. package/dist/hash.d.ts +8 -0
  16. package/dist/hash.js +16 -0
  17. package/dist/integrity.d.ts +29 -0
  18. package/dist/integrity.js +44 -0
  19. package/dist/linters.d.ts +5 -3
  20. package/dist/linters.js +116 -4
  21. package/dist/orphans.d.ts +52 -0
  22. package/dist/orphans.js +124 -0
  23. package/dist/proofs.js +22 -16
  24. package/dist/session.d.ts +97 -0
  25. package/dist/session.js +306 -0
  26. package/dist/sidecar.d.ts +35 -0
  27. package/dist/sidecar.js +102 -0
  28. package/dist/spec.d.ts +29 -9
  29. package/dist/spec.js +22 -4
  30. package/dist/test-utils.d.ts +8 -0
  31. package/dist/test-utils.js +41 -0
  32. package/dist/types.d.ts +34 -8
  33. package/dist/types.js +19 -0
  34. package/dist/validate.js +5 -3
  35. package/package.json +14 -2
  36. package/.claude/settings.json +0 -46
  37. package/.claude/settings.local.json +0 -8
  38. package/.github/workflows/ci.yml +0 -81
  39. package/.prettierignore +0 -1
  40. package/.vigiles/generated.d.ts +0 -205
  41. package/CLAUDE.md +0 -95
  42. package/CLAUDE.md.spec.ts +0 -142
  43. package/CONTRIBUTING.md +0 -121
  44. package/dist/action.d.ts.map +0 -1
  45. package/dist/action.js.map +0 -1
  46. package/dist/cli.d.ts.map +0 -1
  47. package/dist/cli.js.map +0 -1
  48. package/dist/cli.test.d.ts +0 -2
  49. package/dist/cli.test.d.ts.map +0 -1
  50. package/dist/cli.test.js +0 -650
  51. package/dist/cli.test.js.map +0 -1
  52. package/dist/compile.d.ts.map +0 -1
  53. package/dist/compile.js.map +0 -1
  54. package/dist/evolve.d.ts.map +0 -1
  55. package/dist/evolve.js.map +0 -1
  56. package/dist/freshness.d.ts +0 -67
  57. package/dist/freshness.d.ts.map +0 -1
  58. package/dist/freshness.js +0 -244
  59. package/dist/freshness.js.map +0 -1
  60. package/dist/freshness.test.d.ts +0 -2
  61. package/dist/freshness.test.d.ts.map +0 -1
  62. package/dist/freshness.test.js +0 -356
  63. package/dist/freshness.test.js.map +0 -1
  64. package/dist/generate-types.d.ts.map +0 -1
  65. package/dist/generate-types.js.map +0 -1
  66. package/dist/inline.d.ts.map +0 -1
  67. package/dist/inline.js.map +0 -1
  68. package/dist/inline.test.d.ts +0 -5
  69. package/dist/inline.test.d.ts.map +0 -1
  70. package/dist/inline.test.js +0 -152
  71. package/dist/inline.test.js.map +0 -1
  72. package/dist/linters.d.ts.map +0 -1
  73. package/dist/linters.js.map +0 -1
  74. package/dist/proofs.d.ts.map +0 -1
  75. package/dist/proofs.js.map +0 -1
  76. package/dist/proofs.test.d.ts +0 -9
  77. package/dist/proofs.test.d.ts.map +0 -1
  78. package/dist/proofs.test.js +0 -952
  79. package/dist/proofs.test.js.map +0 -1
  80. package/dist/spec.d.ts.map +0 -1
  81. package/dist/spec.js.map +0 -1
  82. package/dist/spec.test.d.ts +0 -2
  83. package/dist/spec.test.d.ts.map +0 -1
  84. package/dist/spec.test.js +0 -1222
  85. package/dist/spec.test.js.map +0 -1
  86. package/dist/types.d.ts.map +0 -1
  87. package/dist/types.js.map +0 -1
  88. package/dist/validate.d.ts.map +0 -1
  89. package/dist/validate.js.map +0 -1
  90. package/dist/validate.test.d.ts +0 -2
  91. package/dist/validate.test.d.ts.map +0 -1
  92. package/dist/validate.test.js +0 -531
  93. package/dist/validate.test.js.map +0 -1
  94. package/docs/agent-setup.md +0 -85
  95. package/docs/agent-workflows.md +0 -103
  96. package/docs/comparison.md +0 -71
  97. package/docs/freshness.md +0 -124
  98. package/docs/inline-mode.md +0 -119
  99. package/docs/linter-support.md +0 -166
  100. package/docs/spec-format.md +0 -194
  101. package/eslint.config.mjs +0 -79
  102. package/examples/CLAUDE.md +0 -54
  103. package/examples/CLAUDE.md.spec.ts +0 -65
  104. package/examples/SKILL.md +0 -50
  105. package/examples/SKILL.md.spec.ts +0 -57
  106. package/fixtures/example-project/CLAUDE.md +0 -11
  107. package/fixtures/example-project/package.json +0 -9
  108. package/fixtures/example-project/src/index.ts +0 -3
  109. package/fixtures/example-project/src/utils.test.ts +0 -2
  110. package/fixtures/example-project/src/utils.ts +0 -3
  111. package/logo.png +0 -0
  112. package/research/adoption-strategy.md +0 -111
  113. package/research/agent-integration.md +0 -145
  114. package/research/ai-code-quality.md +0 -197
  115. package/research/code-search-for-agents.md +0 -313
  116. package/research/competitive-landscape.md +0 -163
  117. package/research/doc-freshness.md +0 -516
  118. package/research/executable-specs.md +0 -368
  119. package/research/feature-ideas.md +0 -464
  120. package/research/formal-proofs-for-agents.md +0 -338
  121. package/research/fp-for-agent-harness.md +0 -150
  122. package/research/fp-for-deterministic-ai.md +0 -131
  123. package/research/self-evolving-specs.md +0 -298
  124. package/schemas/claude-md-strict.yml +0 -18
  125. package/schemas/claude-md.yml +0 -6
  126. package/schemas/skill-strict.yml +0 -12
  127. package/schemas/skill.yml +0 -5
  128. package/skills/audit-feedback-loop/SKILL.md +0 -76
  129. package/skills/edit-spec/SKILL.md +0 -131
  130. package/skills/enforce-rules-format/SKILL.md +0 -71
  131. package/skills/generate-logo/SKILL.md +0 -102
  132. package/skills/generate-rule/SKILL.md +0 -90
  133. package/skills/linter-docs/clippy.md +0 -241
  134. package/skills/linter-docs/eslint.md +0 -384
  135. package/skills/linter-docs/pylint.md +0 -288
  136. package/skills/linter-docs/rubocop.md +0 -277
  137. package/skills/linter-docs/ruff.md +0 -187
  138. package/skills/linter-docs/stylelint.md +0 -247
  139. package/skills/migrate-to-spec/SKILL.md +0 -124
  140. package/skills/pr-to-lint-rule/SKILL.md +0 -97
  141. package/skills/strengthen/SKILL.md +0 -168
  142. package/src/action.ts +0 -214
  143. package/src/cli.test.ts +0 -914
  144. package/src/cli.ts +0 -1631
  145. package/src/compile.ts +0 -691
  146. package/src/evolve.ts +0 -781
  147. package/src/freshness.test.ts +0 -449
  148. package/src/freshness.ts +0 -299
  149. package/src/generate-types.ts +0 -448
  150. package/src/inline.test.ts +0 -206
  151. package/src/inline.ts +0 -164
  152. package/src/linters.ts +0 -739
  153. package/src/proofs.test.ts +0 -1314
  154. package/src/proofs.ts +0 -849
  155. package/src/spec.test.ts +0 -1471
  156. package/src/spec.ts +0 -427
  157. package/src/types.ts +0 -117
  158. package/src/validate.test.ts +0 -701
  159. package/src/validate.ts +0 -381
  160. package/tsconfig.json +0 -23
package/README.md CHANGED
@@ -16,27 +16,9 @@
16
16
 
17
17
  ---
18
18
 
19
- You wouldn't ship code without a linter. Why ship agent instructions without one?
19
+ Your CLAUDE.md lies to your agent. Here's the fix.
20
20
 
21
- Your CLAUDE.md is a plain text file. Anyone can edit it. Nobody verifies it. The lint rule it references was disabled three months ago. The file path it mentions was renamed. The npm script it suggests was deleted. Your agent reads this, trusts it, and produces code based on lies.
22
-
23
- **Markdown can't be validated. TypeScript can.**
24
-
25
- ```bash
26
- npx vigiles init
27
- ```
28
-
29
- vigiles compiles typed TypeScript specs to instruction files (CLAUDE.md, AGENTS.md). Every linter reference is verified against your actual config — not just that it exists, but that it's enabled. Every file path is checked against the filesystem. Every command is validated against package.json. If something is stale, broken, or disabled — you find out at compile time, not when the agent silently ignores your instructions.
30
-
31
- After setup, the agent edits the spec instead of the markdown. Hooks auto-compile. Types catch typos in the editor. CI catches drift. It's self-maintaining.
32
-
33
- Not using vigiles with AI agents is like not using ESLint with JavaScript. You can do it. You can't afford to.
34
-
35
- Companion repo for [Feedback Loop Is All You Need](https://zernie.com/blog/feedback-loop-is-all-you-need).
36
-
37
- ## The Problem
38
-
39
- Hand-written CLAUDE.md files rot silently. Here's what they actually look like:
21
+ Hand-written CLAUDE.md files rot silently. Here's what a typical one looks like:
40
22
 
41
23
  ```markdown
42
24
  ## Code Style
@@ -58,43 +40,45 @@ Reads fine. Four things are wrong:
58
40
  3. `npm run typecheck` — script removed from package.json
59
41
  4. Service/test pairing — no automated check, just a hope
60
42
 
61
- The agent reads this, trusts it, and writes code based on stale claims nobody verified.
43
+ The agent reads this, trusts it, and writes code based on stale claims nobody verified. vigiles **verifies the references in your instruction files** — that each linter rule exists and is enabled, that every file path and script is real — and meets you at whatever commitment level you want.
62
44
 
63
- ## What Changes With vigiles
45
+ Three levels. Each is independently useful; adopt as far up as you like.
64
46
 
65
- ### Claude Code
47
+ ### Level 0 — inline comments (30 seconds, no new files)
66
48
 
67
- | | Without vigiles | With vigiles |
68
- | ----------------------------------- | ---------------------------- | -------------------------------------------------------------- |
69
- | **Instructions** | Hand-written CLAUDE.md | Compiled from `.spec.ts` (build artifact) |
70
- | **Linter rule references** | Trust-based (nobody checks) | Verified at compile time against real config |
71
- | **File paths** | Rot silently when renamed | `file()` references checked against filesystem |
72
- | **Commands** | Stale scripts go unnoticed | `cmd()` references checked against package.json |
73
- | **Direct edits to CLAUDE.md** | Anyone can, nobody knows | PreToolUse hook blocks edits, redirects to spec |
74
- | **Linter config changes** | CLAUDE.md drifts out of sync | PostToolUse hook auto-regenerates types |
75
- | **guidance → enforce upgrades** | Manual guesswork | `/strengthen` reads per-linter docs, suggests upgrades |
76
- | **New lint rules from PR feedback** | Copy-paste from review | `/pr-to-lint-rule` generates rule + tests + spec entry |
77
- | **CI** | Nothing to verify | `vigiles audit` catches hash drift, disabled rules, stale refs |
49
+ Add a comment to your existing CLAUDE.md and audit it:
78
50
 
79
- <details>
80
- <summary><b>Codex</b> (same compile-time checks, no hooks)</summary>
51
+ ```md
52
+ <!-- vigiles:enforce eslint/no-console "Route output through logger.ts" -->
53
+ ```
81
54
 
82
- | | Without vigiles | With vigiles |
83
- | ----------------------------- | -------------------------------- | ------------------------------------------------------- |
84
- | **Instructions** | Hand-written AGENTS.md | Compiled from `.spec.ts` |
85
- | **Linter rule references** | Trust-based | Verified at compile time |
86
- | **File paths / commands** | Rot silently | Checked at compile time |
87
- | **Direct edits to AGENTS.md** | Undetected | CI catches hash mismatch |
88
- | **Hooks / auto-compile** | Not available (no plugin system) | Not available — run `vigiles compile` manually or in CI |
89
- | **CI** | Nothing to verify | Same `vigiles audit` pipeline as Claude |
55
+ ```bash
56
+ npx vigiles audit CLAUDE.md
57
+ ```
90
58
 
91
- </details>
59
+ Each rule is checked against your real linter config — typos get closest-match suggestions, disabled rules are flagged. Zero install commitment, zero new files.
92
60
 
93
- Everything vigiles compiles and audits is **deterministic** same input, same output, no LLM in the loop. The non-deterministic parts (authoring specs, suggesting upgrades, writing custom rules) are agent skills that run outside the compilation pipeline. [Determinism breakdown and flow diagram →](docs/comparison.md)
61
+ ### Level 1YAML frontmatter (editor autocomplete, still no TypeScript)
62
+
63
+ Promote your rules into a `vigiles:` block at the top of the file:
94
64
 
95
- ## The Fix
65
+ ```yaml
66
+ ---
67
+ # yaml-language-server: $schema=./.vigiles/schema.json
68
+ vigiles:
69
+ enforce:
70
+ - rule: "@typescript-eslint/no-explicit-any"
71
+ why: "Use unknown and narrow with type guards."
72
+ - rule: eslint/no-console
73
+ why: "Route output through logger.ts"
74
+ ---
75
+ ```
96
76
 
97
- Write your conventions as TypeScript. The compiler catches the lies.
77
+ `npx vigiles generate-schema` emits a JSON Schema from your project's _actual_ enabled rules, so your editor's built-in YAML language server (VS Code, JetBrains, neovim) autocompletes rule names and red-squiggles typos — at edit time, with no TypeScript in the project. `vigiles audit` enforces the same rules in CI. [Markdown mode →](docs/markdown-mode.md)
78
+
79
+ ### Level 2 — typed spec (compiler-grade guarantees)
80
+
81
+ When you want the strongest guarantees, compile a typed spec. Every linter rule reference is verified against your real config, every file path against the filesystem, every npm script against package.json. Stale references become compile errors — caught at edit time, not when the agent silently ignores you.
98
82
 
99
83
  ```typescript
100
84
  // CLAUDE.md.spec.ts
@@ -132,53 +116,54 @@ $ npx vigiles compile
132
116
  ~180 tokens
133
117
  ```
134
118
 
135
- The spec is the source of truth. CLAUDE.md is a build artifact.
136
-
137
- ## Quick Start
119
+ At this level the spec is the source of truth and CLAUDE.md is a build artifact. The agent edits the spec — hooks auto-compile, types catch typos in the editor, CI catches drift.
138
120
 
139
- ```bash
140
- npx vigiles init
141
- ```
121
+ Companion repo for [Feedback Loop Is All You Need](https://zernie.com/blog/feedback-loop-is-all-you-need).
142
122
 
143
- That's it. One command. The wizard auto-detects your project, creates a spec, scans your linters, compiles to markdown, adds a CI step, and installs Claude Code hooks — all automatically.
123
+ ## What Changes With vigiles
144
124
 
145
- ```
146
- npx vigiles init guidance() rules, zero config
147
-
148
-
149
- agent edits spec ◄────────── hooks auto-compile (self-maintaining)
150
-
151
-
152
- npx vigiles audit full verification: hashes + linters + coverage
153
-
154
-
155
- CI catches drift stale refs, disabled rules, typos, duplicates
156
- ```
125
+ ### Claude Code
157
126
 
158
- **After install, it just works:**
127
+ | | Without vigiles | With vigiles |
128
+ | ----------------------------------- | ---------------------------- | -------------------------------------------------------------- |
129
+ | **Instructions** | Hand-written CLAUDE.md | Compiled from `.spec.ts` (build artifact) |
130
+ | **Linter rule references** | Trust-based (nobody checks) | Verified at compile time against real config |
131
+ | **File paths** | Rot silently when renamed | `file()` references checked against filesystem |
132
+ | **Commands** | Stale scripts go unnoticed | `cmd()` references checked against package.json |
133
+ | **Direct edits to CLAUDE.md** | Anyone can, nobody knows | PreToolUse hook blocks edits, redirects to spec |
134
+ | **Spec edits** | N/A | PostToolUse hook auto-compiles to markdown |
135
+ | **Linter config changes** | CLAUDE.md drifts out of sync | PostToolUse hook auto-regenerates types |
136
+ | **guidance → enforce upgrades** | Manual guesswork | `/strengthen` reads per-linter docs, suggests upgrades |
137
+ | **New lint rules from PR feedback** | Copy-paste from review | `/pr-to-lint-rule` generates rule + tests + spec entry |
138
+ | **CI** | Nothing to verify | `vigiles audit` catches hand-edits, disabled rules, stale refs |
159
139
 
160
- - Agent says "update CLAUDE.md" → plugin blocks the edit, redirects to `.spec.ts`
161
- - Agent edits the spec → plugin auto-compiles CLAUDE.md regenerated
162
- - Agent edits `eslint.config.ts` → plugin auto-regenerates types
163
- - CI runs `vigiles audit` → catches stale specs, disabled rules, missing files
140
+ <details>
141
+ <summary><b>Codex</b> (same compile-time checks, no hooks)</summary>
164
142
 
165
- ### Hesitant about a new file type? Try inline mode
143
+ | | Without vigiles | With vigiles |
144
+ | ----------------------------- | -------------------------------- | ------------------------------------------------------- |
145
+ | **Instructions** | Hand-written AGENTS.md | Compiled from `.spec.ts` |
146
+ | **Linter rule references** | Trust-based | Verified at compile time |
147
+ | **File paths / commands** | Rot silently | Checked at compile time |
148
+ | **Direct edits to AGENTS.md** | Undetected | CI catches hash mismatch |
149
+ | **Hooks / auto-compile** | Not available (no plugin system) | Not available — run `vigiles compile` manually or in CI |
150
+ | **CI** | Nothing to verify | Same `vigiles audit` pipeline as Claude |
166
151
 
167
- If a `.spec.ts` feels like too much commitment, you can adopt vigiles one rule at a time by adding HTML comments directly to your existing `CLAUDE.md`:
152
+ </details>
168
153
 
169
- ```md
170
- <!-- vigiles:enforce eslint/no-console "Route output through logger.ts" -->
171
- ```
154
+ Everything vigiles compiles and audits is **deterministic** — same input, same output, no LLM in the loop. The non-deterministic parts (authoring specs, suggesting upgrades, writing custom rules) are agent skills that run outside the compilation pipeline. [Determinism breakdown and flow diagram →](docs/comparison.md)
172
155
 
173
- Running `vigiles audit CLAUDE.md` verifies each inline rule against your real linter config with the same closest-match suggestions and disabled-rule detection as spec mode. Zero build step, zero new files, works with any project. See [docs/inline-mode.md](docs/inline-mode.md) for the format and how to graduate to spec mode later.
156
+ ## Quick Start
174
157
 
175
- **It's self-maintaining.** Add a new ESLint rule? The hook regenerates types your spec gets autocomplete for the new rule immediately. Rename a file? The compiler catches the stale reference. The setup doesn't rot because the hooks keep everything in sync.
158
+ The fastest path is markdown mode add a marker to your existing CLAUDE.md and audit it, no install or new files (see [Level 0 / Level 1](#level-0--inline-comments-30-seconds-no-new-files) above and [docs/markdown-mode.md](docs/markdown-mode.md)). When you want compiler-grade guarantees, scaffold a typed spec:
176
159
 
177
- **It evolves automatically.** Start with `guidance()` rules (zero config). When you're ready, run `/strengthen` — it reads your linter configs and per-linter reference docs to find `enforce()` upgrades. Each upgrade adds compiler-verified enforcement.
160
+ ```bash
161
+ npx vigiles init
162
+ ```
178
163
 
179
- **Already have a hand-written CLAUDE.md?** The wizard detects it and suggests migration.
164
+ The wizard auto-detects your project, creates a spec, scans your linters, compiles to markdown, adds a CI step, and installs Claude Code hooks. After install: the agent edits the spec (hooks block direct CLAUDE.md edits), the spec auto-compiles on save, and `vigiles audit` catches drift in CI.
180
165
 
181
- **Ready to enforce?** Run `npx vigiles init --strict` to set rules to `"error"` CI fails if any instruction file lacks a spec.
166
+ Start with `guidance()` rules (zero config). When you're ready, run `/strengthen` to find rules that can be upgraded to compile-verified `enforce()`. Already have a hand-written CLAUDE.md? The wizard detects it and offers migration.
182
167
 
183
168
  | Flag | Effect |
184
169
  | -------------------- | ----------------------------------------------------- |
@@ -188,17 +173,19 @@ Running `vigiles audit CLAUDE.md` verifies each inline rule against your real li
188
173
 
189
174
  Works the same for humans and agents — fully non-interactive. [Agent setup guide →](docs/agent-setup.md) | [Agent workflows →](docs/agent-workflows.md)
190
175
 
191
- ## Two Rule Types
176
+ ## Three Rule Types
192
177
 
193
178
  **`enforce()`** — delegated to a linter. vigiles verifies the rule exists in the catalog AND is enabled in your project config. A disabled rule is a compile error.
194
179
 
180
+ <!-- vigiles:ignore -->
181
+
195
182
  ```typescript
196
183
  "no-any": enforce("@typescript-eslint/no-explicit-any", "Use unknown and narrow."),
197
184
  "no-print": enforce("ruff/T201", "Use logging module."),
198
185
  "no-unwrap": enforce("clippy/unwrap_used", "Use expect() with context."),
199
186
  ```
200
187
 
201
- Supports ESLint, Stylelint, Ruff, Clippy, Pylint, and RuboCop. [Full linter support details →](docs/linter-support.md)
188
+ Supports ESLint, Stylelint, Ruff, Clippy, Pylint, RuboCop, and Cedar policies. [Full linter support details →](docs/linter-support.md)
202
189
 
203
190
  **`guidance()`** — prose advice. No mechanical enforcement, but not untracked: guidance rules participate in the monotonicity proof system. Once a rule exists, it can be strengthened ( `guidance` → `enforce` ) but never weakened or removed without an explicit allowlist. This prevents silent erosion of conventions over time.
204
191
 
@@ -206,6 +193,21 @@ Supports ESLint, Stylelint, Ruff, Clippy, Pylint, and RuboCop. [Full linter supp
206
193
  "research-first": guidance("Google unfamiliar APIs first."),
207
194
  ```
208
195
 
196
+ **`guard()`** — reactive: runs a command when watched files change. One declaration emits hooks for every supported system (Claude Code PostToolUse, husky pre-commit, etc.). Eliminates copy-pasting the same trigger across `.claude/settings.json`, `.husky/`, and CI configs.
197
+
198
+ ```typescript
199
+ "recompile-specs": guard(
200
+ { watch: "*.spec.ts", run: "npx vigiles compile" },
201
+ "Recompile instruction files when any spec changes.",
202
+ ),
203
+ "regen-types": guard(
204
+ { watch: ["eslint.config.*", "package.json"], run: "npx vigiles generate-types" },
205
+ "Regenerate types when linter config or deps change.",
206
+ ),
207
+ ```
208
+
209
+ Same monotonicity guarantees as `enforce()` — guards can't be silently removed.
210
+
209
211
  ## Verified References
210
212
 
211
213
  `file()`, `cmd()`, and `ref()` catch stale references at compile time:
@@ -218,7 +220,7 @@ export default claude({
218
220
  architecture: instructions`
219
221
  Core engine in ${file("src/compile.ts")}.
220
222
  Run ${cmd("npm test")} to verify.
221
- See ${ref("skills/deploy/SKILL.md")} for deployment.
223
+ See ${ref("skills/strengthen/SKILL.md")} for the strengthen skill.
222
224
  `,
223
225
  // If any path is stale → compile error
224
226
  },
@@ -240,14 +242,18 @@ $ npx vigiles generate-types
240
242
 
241
243
  Commit the file to git. CI can verify it's fresh: `npx vigiles generate-types --check`. [How it works →](docs/linter-support.md#generate-types)
242
244
 
245
+ For markdown frontmatter (Level 1), `vigiles generate-schema` gives the same authoring-time feedback without TypeScript: it emits a JSON Schema from your enabled rules, and your editor's YAML language server autocompletes rule names and squiggles typos. CI freshness check: `npx vigiles generate-schema --check`.
246
+
243
247
  ## CLI
244
248
 
245
249
  ```bash
246
250
  npx vigiles init [--target=X.md] # Scaffold a spec (runs full setup wizard by default)
247
251
  npx vigiles compile [files...] # Compile .spec.ts → .md
248
- npx vigiles audit [files...] # Verify hashes + linter rules + coverage + suggest upgrades
249
- npx vigiles generate-types # Emit .d.ts from project state
252
+ npx vigiles audit [files...] # Verify hashes + inline/frontmatter/spec rules + coverage
253
+ npx vigiles generate-types # Emit .d.ts from project state (for spec mode)
250
254
  npx vigiles generate-types --check # Verify .d.ts is up to date
255
+ npx vigiles generate-schema # Emit JSON Schema for vigiles: frontmatter (Level 1)
256
+ npx vigiles generate-schema --check # Verify schema.json is up to date
251
257
  ```
252
258
 
253
259
  ## GitHub Action
@@ -280,17 +286,14 @@ The plugin provides two hooks:
280
286
 
281
287
  ## Validation
282
288
 
283
- `vigiles audit` validates instruction files with three rules:
289
+ `vigiles audit` validates instruction files with four rules:
284
290
 
285
- | Rule | Default | What it checks |
286
- | -------------------- | -------- | --------------------------------------------- |
287
- | `require-spec` | `"warn"` | Every CLAUDE.md/AGENTS.md has a `.spec.ts` |
288
- | `require-skill-spec` | `"warn"` | Every SKILL.md has a `.spec.ts` |
289
- | `freshness` | `"warn"` | Compiled output matches current project state |
290
-
291
- ```bash
292
- npx vigiles audit # checks specs, hashes, freshness, coverage, duplicates
293
- ```
291
+ | Rule | Default | What it checks |
292
+ | -------------------------------------------------------- | -------- | ---------------------------------------------------------------------------- |
293
+ | [`require-spec`](docs/rules/require-spec.md) | `"warn"` | Every CLAUDE.md/AGENTS.md has a spec, inline rule, or `vigiles:` frontmatter |
294
+ | [`require-skill-spec`](docs/rules/require-skill-spec.md) | `"warn"` | Every SKILL.md has a `.spec.ts` |
295
+ | [`integrity`](docs/rules/integrity.md) | `"warn"` | Compiled markdown wasn't hand-edited (SHA-256 check) |
296
+ | [`coverage`](docs/rules/coverage.md) | `false` | Spec covers enough of the project surface |
294
297
 
295
298
  Configure in `.vigilesrc.json`:
296
299
 
@@ -298,41 +301,13 @@ Configure in `.vigilesrc.json`:
298
301
  {
299
302
  "rules": {
300
303
  "require-spec": "error",
301
- "freshness": "error"
304
+ "integrity": "error",
305
+ "coverage": ["warn", { "scripts": 50, "linterRules": 5 }]
302
306
  }
303
307
  }
304
308
  ```
305
309
 
306
- Disable per-file with an HTML comment:
307
-
308
- ```markdown
309
- <!-- vigiles-disable require-spec -->
310
-
311
- # CLAUDE.md
312
-
313
- ...
314
- ```
315
-
316
- ### Freshness
317
-
318
- The `freshness` rule detects when compiled markdown has drifted from project state — disabled linter rules, deleted files, changed configs. Three detection modes:
319
-
320
- | Mode | What it does | Cost |
321
- | -------------------- | ----------------------------------------------------------------------- | ------ |
322
- | `"strict"` (default) | Recompiles in memory, diffs output | 2-5s |
323
- | `"input-hash"` | Checks fingerprint of tracked inputs (spec, linter configs, lock files) | <100ms |
324
- | `"output-hash"` | Only detects hand-edits to compiled markdown | <1ms |
325
-
326
- Strict mode has zero false positives and zero false negatives. Input-hash mode is faster but can false-positive on config whitespace changes. Set the mode in `.vigilesrc.json`:
327
-
328
- ```json
329
- {
330
- "freshnessMode": "input-hash",
331
- "freshnessInputs": ["../../yarn.lock"]
332
- }
333
- ```
334
-
335
- In input-hash mode, vigiles auto-detects lock files across 15 ecosystems (npm, Yarn, pnpm, Bun, Bundler, Poetry, uv, PDM, pip, Cargo, Go, Composer, NuGet, SPM, Mix) and tracks them alongside linter configs, package.json, keyFiles references, and generated types. [Full details →](docs/freshness.md)
310
+ Disable per-file with `<!-- vigiles-disable require-spec -->` at the top of the markdown.
336
311
 
337
312
  ## Skills
338
313
 
@@ -365,12 +340,14 @@ Specs compile to `CLAUDE.md` by default. Set `target: "AGENTS.md"` or `target: [
365
340
 
366
341
  ## Related Tools
367
342
 
368
- vigiles doesn't try to do everything:
343
+ vigiles doesn't try to do everything. It owns one thing: compile-time verification of typed specs against real linter configs, filesystems, and package.json. Everything else, compose:
369
344
 
370
345
  - **Architectural linting** — [ast-grep](https://ast-grep.github.io/), [Dependency Cruiser](https://github.com/sverweij/dependency-cruiser), [Steiger](https://github.com/feature-sliced/steiger). Reference their rules via `enforce()`.
371
- - **File sync** — [Ruler](https://github.com/intellectronica/ruler), [rulesync](https://github.com/dyoshikawa/rulesync), [block/ai-rules](https://github.com/block/ai-rules). vigiles compiles the source; sync tools distribute.
372
- - **Markdown linting** — [markdownlint](https://github.com/DavidAnson/markdownlint). vigiles generates the markdown; structure is correct by construction.
346
+ - **File sync** across agents — [Ruler](https://github.com/intellectronica/ruler), [rulesync](https://github.com/dyoshikawa/rulesync), [block/ai-rules](https://github.com/block/ai-rules). vigiles compiles the source; sync tools distribute.
347
+ - **Markdown linting** — [markdownlint](https://github.com/DavidAnson/markdownlint). vigiles generates markdown; structure is correct by construction.
348
+ - **Code-block linting in docs** — [eslint-plugin-markdown](https://github.com/eslint/eslint-plugin-markdown) for syntax, [twoslash](https://shikijs.github.io/twoslash/) for TS type-checking.
373
349
  - **Prose quality** — [Vale](https://vale.sh). Different concern.
350
+ - **Runtime LLM rule checking** (e.g. ai-rulez `"AI-Powered Rule Enforcement"`) — opposite paradigm. Those tools send your code to a model on every check, costing tokens and giving non-reproducible verdicts. vigiles compiles once and checks deterministically forever after with `eslint`, `ruff`, `tsc`, Cedar evaluation — tools as deterministic as their inputs.
374
351
 
375
352
  ## License
376
353