vigiles 2.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/.claude/settings.json +46 -0
- package/.claude/settings.local.json +8 -0
- package/.claude-plugin/hooks/post-edit.sh +34 -0
- package/.claude-plugin/hooks/pre-edit.sh +40 -0
- package/.claude-plugin/hooks/session-start.sh +38 -0
- package/.claude-plugin/marketplace.json +14 -0
- package/.claude-plugin/plugin.json +47 -0
- package/.github/workflows/ci.yml +81 -0
- package/.prettierignore +1 -0
- package/.vigiles/generated.d.ts +205 -0
- package/CLAUDE.md +95 -0
- package/CLAUDE.md.spec.ts +142 -0
- package/CONTRIBUTING.md +121 -0
- package/LICENSE +21 -0
- package/README.md +377 -0
- package/action.yml +25 -0
- package/dist/action.d.ts +7 -0
- package/dist/action.d.ts.map +1 -0
- package/dist/action.js +180 -0
- package/dist/action.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1267 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.test.d.ts +2 -0
- package/dist/cli.test.d.ts.map +1 -0
- package/dist/cli.test.js +650 -0
- package/dist/cli.test.js.map +1 -0
- package/dist/compile.d.ts +101 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +503 -0
- package/dist/compile.js.map +1 -0
- package/dist/evolve.d.ts +132 -0
- package/dist/evolve.d.ts.map +1 -0
- package/dist/evolve.js +599 -0
- package/dist/evolve.js.map +1 -0
- package/dist/freshness.d.ts +67 -0
- package/dist/freshness.d.ts.map +1 -0
- package/dist/freshness.js +244 -0
- package/dist/freshness.js.map +1 -0
- package/dist/freshness.test.d.ts +2 -0
- package/dist/freshness.test.d.ts.map +1 -0
- package/dist/freshness.test.js +356 -0
- package/dist/freshness.test.js.map +1 -0
- package/dist/generate-types.d.ts +34 -0
- package/dist/generate-types.d.ts.map +1 -0
- package/dist/generate-types.js +381 -0
- package/dist/generate-types.js.map +1 -0
- package/dist/inline.d.ts +58 -0
- package/dist/inline.d.ts.map +1 -0
- package/dist/inline.js +142 -0
- package/dist/inline.js.map +1 -0
- package/dist/inline.test.d.ts +5 -0
- package/dist/inline.test.d.ts.map +1 -0
- package/dist/inline.test.js +152 -0
- package/dist/inline.test.js.map +1 -0
- package/dist/linters.d.ts +38 -0
- package/dist/linters.d.ts.map +1 -0
- package/dist/linters.js +588 -0
- package/dist/linters.js.map +1 -0
- package/dist/proofs.d.ts +272 -0
- package/dist/proofs.d.ts.map +1 -0
- package/dist/proofs.js +622 -0
- package/dist/proofs.js.map +1 -0
- package/dist/proofs.test.d.ts +9 -0
- package/dist/proofs.test.d.ts.map +1 -0
- package/dist/proofs.test.js +952 -0
- package/dist/proofs.test.js.map +1 -0
- package/dist/spec.d.ts +258 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +113 -0
- package/dist/spec.js.map +1 -0
- package/dist/spec.test.d.ts +2 -0
- package/dist/spec.test.d.ts.map +1 -0
- package/dist/spec.test.js +1222 -0
- package/dist/spec.test.js.map +1 -0
- package/dist/types.d.ts +101 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +10 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +286 -0
- package/dist/validate.js.map +1 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +531 -0
- package/dist/validate.test.js.map +1 -0
- package/docs/agent-setup.md +85 -0
- package/docs/agent-workflows.md +103 -0
- package/docs/comparison.md +71 -0
- package/docs/freshness.md +124 -0
- package/docs/inline-mode.md +119 -0
- package/docs/linter-support.md +166 -0
- package/docs/spec-format.md +194 -0
- package/eslint.config.mjs +79 -0
- package/examples/CLAUDE.md +54 -0
- package/examples/CLAUDE.md.spec.ts +65 -0
- package/examples/SKILL.md +50 -0
- package/examples/SKILL.md.spec.ts +57 -0
- package/fixtures/example-project/CLAUDE.md +11 -0
- package/fixtures/example-project/package.json +9 -0
- package/fixtures/example-project/src/index.ts +3 -0
- package/fixtures/example-project/src/utils.test.ts +2 -0
- package/fixtures/example-project/src/utils.ts +3 -0
- package/logo.png +0 -0
- package/package.json +42 -0
- package/research/adoption-strategy.md +111 -0
- package/research/agent-integration.md +145 -0
- package/research/ai-code-quality.md +197 -0
- package/research/code-search-for-agents.md +313 -0
- package/research/competitive-landscape.md +163 -0
- package/research/doc-freshness.md +516 -0
- package/research/executable-specs.md +368 -0
- package/research/feature-ideas.md +464 -0
- package/research/formal-proofs-for-agents.md +338 -0
- package/research/fp-for-agent-harness.md +150 -0
- package/research/fp-for-deterministic-ai.md +131 -0
- package/research/self-evolving-specs.md +298 -0
- package/schemas/claude-md-strict.yml +18 -0
- package/schemas/claude-md.yml +6 -0
- package/schemas/skill-strict.yml +12 -0
- package/schemas/skill.yml +5 -0
- package/skills/audit-feedback-loop/SKILL.md +76 -0
- package/skills/edit-spec/SKILL.md +131 -0
- package/skills/enforce-rules-format/SKILL.md +71 -0
- package/skills/generate-logo/SKILL.md +102 -0
- package/skills/generate-rule/SKILL.md +90 -0
- package/skills/linter-docs/clippy.md +241 -0
- package/skills/linter-docs/eslint.md +384 -0
- package/skills/linter-docs/pylint.md +288 -0
- package/skills/linter-docs/rubocop.md +277 -0
- package/skills/linter-docs/ruff.md +187 -0
- package/skills/linter-docs/stylelint.md +247 -0
- package/skills/migrate-to-spec/SKILL.md +124 -0
- package/skills/pr-to-lint-rule/SKILL.md +97 -0
- package/skills/strengthen/SKILL.md +168 -0
- package/src/action.ts +214 -0
- package/src/cli.test.ts +914 -0
- package/src/cli.ts +1631 -0
- package/src/compile.ts +691 -0
- package/src/evolve.ts +781 -0
- package/src/freshness.test.ts +449 -0
- package/src/freshness.ts +299 -0
- package/src/generate-types.ts +448 -0
- package/src/inline.test.ts +206 -0
- package/src/inline.ts +164 -0
- package/src/linters.ts +739 -0
- package/src/proofs.test.ts +1314 -0
- package/src/proofs.ts +849 -0
- package/src/spec.test.ts +1471 -0
- package/src/spec.ts +427 -0
- package/src/types.ts +117 -0
- package/src/validate.test.ts +701 -0
- package/src/validate.ts +381 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLAUDE.md specification for the vigiles project.
|
|
3
|
+
*
|
|
4
|
+
* This is the source of truth. CLAUDE.md is a compiled build artifact.
|
|
5
|
+
* Run `npm run compile:spec` to regenerate CLAUDE.md from this spec.
|
|
6
|
+
*/
|
|
7
|
+
import { claude, guidance } from "./src/spec.js";
|
|
8
|
+
|
|
9
|
+
export default claude({
|
|
10
|
+
sections: {
|
|
11
|
+
positioning: `vigiles compiles \`.spec.ts\` files to instruction files (CLAUDE.md, AGENTS.md, or any markdown target). The spec is the source of truth. The markdown is a build artifact. Nobody else does this — other tools lint markdown after the fact. vigiles eliminates the problem at the source.
|
|
12
|
+
|
|
13
|
+
The linter cross-referencing engine is the core moat: \`enforce("@typescript-eslint/no-floating-promises")\` verifies the rule exists AND is enabled in your linter config. Same for ESLint, Ruff, Clippy, Pylint, RuboCop, and Stylelint. No other tool resolves rules against 6 linter APIs.
|
|
14
|
+
|
|
15
|
+
\`generate-types\` is the second moat: scans all 6 linter APIs, package.json, and project files to emit a \`.d.ts\` with type unions. The TS compiler then PROVES references are valid at authoring time — typos become type errors, not runtime surprises.
|
|
16
|
+
|
|
17
|
+
vigiles does NOT do architectural linting. Use ast-grep, Dependency Cruiser, Steiger, or eslint-plugin-boundaries for that. vigiles can reference their rules via \`enforce()\`.`,
|
|
18
|
+
|
|
19
|
+
architecture: `Two rule types in specs:
|
|
20
|
+
|
|
21
|
+
- \`enforce()\` — delegated to external tool (linter, ast-grep, dependency-cruiser). vigiles verifies the rule exists and is enabled.
|
|
22
|
+
- \`guidance()\` — prose only, compiles to \`**Guidance only**\` in markdown.
|
|
23
|
+
|
|
24
|
+
Architectural linting (file pairing, import boundaries, AST patterns) belongs in external tools — reference them via \`enforce()\`.
|
|
25
|
+
|
|
26
|
+
Template literal types ensure linter names (\`eslint/\`, \`ruff/\`, etc.) are type-safe. Branded types (\`VerifiedPath\`, \`VerifiedCmd\`, \`VerifiedRef\`) distinguish verified references from raw strings.
|
|
27
|
+
|
|
28
|
+
Compilation: spec.ts → compiler reads spec, validates references (file paths via existsSync, npm scripts via package.json, linter rules via linter APIs), generates markdown with SHA-256 integrity hash.
|
|
29
|
+
|
|
30
|
+
Core modules: \`src/spec.ts\` (types + builders), \`src/compile.ts\` (compiler), \`src/linters.ts\` (6-linter cross-referencing engine), \`src/generate-types.ts\` (type generator), \`src/proofs.ts\` (proof algorithms for self-evolving specs), \`src/evolve.ts\` (evolution engine).`,
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
keyFiles: {
|
|
34
|
+
"src/spec.ts":
|
|
35
|
+
"Type system and builder functions (enforce, guidance, claude, skill, file, cmd, ref)",
|
|
36
|
+
"src/compile.ts":
|
|
37
|
+
"Compiler: spec → markdown with SHA-256 hash, linter verification, reference validation",
|
|
38
|
+
"src/linters.ts":
|
|
39
|
+
"Linter cross-referencing engine (ESLint, Stylelint, Ruff, Clippy, Pylint, RuboCop)",
|
|
40
|
+
"src/generate-types.ts":
|
|
41
|
+
"Type generator: scans linters/package.json/filesystem → emits .d.ts",
|
|
42
|
+
"src/cli.ts":
|
|
43
|
+
"CLI: init, compile, audit (3 primary commands + generate-types plumbing)",
|
|
44
|
+
"src/inline.ts":
|
|
45
|
+
"Inline-mode parser: `<!-- vigiles:enforce ... -->` comments in markdown for gradual adoption",
|
|
46
|
+
"src/action.ts": "GitHub Action wrapper",
|
|
47
|
+
"src/spec.test.ts": "Spec + compiler test suite (node:test)",
|
|
48
|
+
"src/validate.test.ts": "Validation test suite (node:test)",
|
|
49
|
+
"src/cli.test.ts": "CLI integration + E2E test suite (node:test)",
|
|
50
|
+
"src/freshness.ts":
|
|
51
|
+
"Freshness detection: lock file detection, input discovery, hash computation, staleness checks",
|
|
52
|
+
"src/freshness.test.ts":
|
|
53
|
+
"Freshness test suite: lock files (15 ecosystems), input discovery, hash computation, staleness",
|
|
54
|
+
"src/proofs.ts":
|
|
55
|
+
"Deterministic proof algorithms (monotonicity lattice, NCD, Bloom filter, Merkle DAG, fixed-point, property testing)",
|
|
56
|
+
"src/evolve.ts":
|
|
57
|
+
"Evolution engine: mutation operators, fitness function, proof-gated selection",
|
|
58
|
+
"src/proofs.test.ts": "Proof system + evolution engine tests (node:test)",
|
|
59
|
+
"CLAUDE.md.spec.ts": "This file — the source of truth for CLAUDE.md",
|
|
60
|
+
"examples/SKILL.md.spec.ts": "Example SKILL.md spec",
|
|
61
|
+
"research/adoption-strategy.md":
|
|
62
|
+
"Adoption strategy: zero-config setup, progressive enforcement, agent workflows",
|
|
63
|
+
"research/competitive-landscape.md":
|
|
64
|
+
"Competitive landscape: rule-porter, rulesync, vibe-cli, Ruler",
|
|
65
|
+
"research/executable-specs.md": "Design doc: executable spec system",
|
|
66
|
+
"research/feature-ideas.md":
|
|
67
|
+
"Feature ideas: plugin API, custom rules, exhaustive coverage",
|
|
68
|
+
"research/ai-code-quality.md": "Research: AI code quality patterns",
|
|
69
|
+
"research/self-evolving-specs.md":
|
|
70
|
+
"Design doc: self-evolving spec system (proofs, Merkle history, evolution engine)",
|
|
71
|
+
"research/code-search-for-agents.md":
|
|
72
|
+
"Research: code search approaches (grep vs embeddings vs AST-grep)",
|
|
73
|
+
"research/doc-freshness.md":
|
|
74
|
+
"Research: input fingerprinting, TOC manifests, and stale spec detection",
|
|
75
|
+
"docs/agent-workflows.md":
|
|
76
|
+
"Agent-specific workflows (Claude Code, Codex, multi-agent, Cursor)",
|
|
77
|
+
"docs/agent-setup.md":
|
|
78
|
+
"Non-interactive agent setup guide (hooks via settings.json)",
|
|
79
|
+
"docs/spec-format.md": "Spec format reference (target, sections, rules)",
|
|
80
|
+
"docs/linter-support.md":
|
|
81
|
+
"Linter support details (6 linters + generate-types)",
|
|
82
|
+
"docs/comparison.md":
|
|
83
|
+
"Before/after tables (Claude Code, Codex), determinism breakdown, flow diagram",
|
|
84
|
+
"docs/freshness.md":
|
|
85
|
+
"Freshness detection: strict/input-hash/output-hash modes, lock file detection, input fingerprinting",
|
|
86
|
+
"docs/inline-mode.md":
|
|
87
|
+
"Inline mode: `<!-- vigiles:enforce ... -->` comments for gradual adoption without a .spec.ts",
|
|
88
|
+
"skills/linter-docs/eslint.md":
|
|
89
|
+
"ESLint reference: plugin table, AST selectors, type-aware rules, auto-fix, edge cases",
|
|
90
|
+
"skills/linter-docs/rubocop.md":
|
|
91
|
+
"RuboCop reference: gem table, node pattern DSL, auto-correct, custom cops",
|
|
92
|
+
"skills/linter-docs/pylint.md":
|
|
93
|
+
"Pylint reference: plugin table, astroid AST, type inference, custom checkers",
|
|
94
|
+
"skills/linter-docs/ruff.md":
|
|
95
|
+
"Ruff reference: 800+ reimplemented rules, rule selection, auto-fix, pyproject.toml config",
|
|
96
|
+
"skills/linter-docs/stylelint.md":
|
|
97
|
+
"Stylelint reference: plugin table, PostCSS AST, custom rules, CSS-in-JS, SCSS",
|
|
98
|
+
"skills/strengthen/SKILL.md":
|
|
99
|
+
"Strengthen skill: upgrade guidance() → enforce() by finding existing linter rules",
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
commands: {
|
|
103
|
+
"npm run build": "Compile TypeScript to dist/",
|
|
104
|
+
"npm test": "Build and run all tests",
|
|
105
|
+
"npm run fmt": "Format with prettier",
|
|
106
|
+
"npm run fmt:check": "Check formatting",
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
rules: {
|
|
110
|
+
"never-skip-tests": guidance(
|
|
111
|
+
"All tests must pass. If a test requires a CLI tool (pylint, rubocop, ruff, clippy), install the tool, don't skip the test.",
|
|
112
|
+
),
|
|
113
|
+
|
|
114
|
+
"zero-config-by-default": guidance(
|
|
115
|
+
"`vigiles compile` should work with just a .spec.ts file. Config exists only for overrides (maxRules, maxTokens).",
|
|
116
|
+
),
|
|
117
|
+
|
|
118
|
+
"dont-reimplement-linters": guidance(
|
|
119
|
+
"Architectural linting belongs in ast-grep/Dependency Cruiser/Steiger. Per-file code rules belong in ESLint/Ruff/Clippy. vigiles owns: spec compilation, linter cross-referencing, type generation, stale reference detection, and proof-based spec evolution.",
|
|
120
|
+
),
|
|
121
|
+
|
|
122
|
+
"smooth-adoption": guidance(
|
|
123
|
+
"`npx vigiles init && npx skills add zernie/vigiles` must work on first run with zero config. The wizard auto-detects the project, creates specs, generates types, compiles, and wires CI. After install the agent edits specs automatically — no workflow change required. Start permissive (guidance rules, `require-spec: false` available), tighten over time. Hesitant adopters can use inline mode (`<!-- vigiles:enforce ... -->` comments) without a .spec.ts — see `docs/inline-mode.md`. See `research/adoption-strategy.md`.",
|
|
124
|
+
),
|
|
125
|
+
|
|
126
|
+
"format-before-commit": guidance(
|
|
127
|
+
"Run `npm run fmt:check` before committing. Inline code spans in markdown need surrounding spaces to render correctly.",
|
|
128
|
+
),
|
|
129
|
+
|
|
130
|
+
"progressive-adoption": guidance(
|
|
131
|
+
"vigiles must be adoptable incrementally, like TypeScript. Three on-ramps, zero friction: (1) inline mode — add `<!-- vigiles:enforce ... -->` comments to an existing CLAUDE.md, no new files; (2) spec mode with `guidance()` only — `npx vigiles init` creates a .spec.ts, compiles to markdown, zero linter setup; (3) strict mode — `enforce()` rules, CI gating, `--strict` flag. Each level adds value without requiring the next. Never gate basic functionality on advanced setup. README examples should always show the simplest path first.",
|
|
132
|
+
),
|
|
133
|
+
|
|
134
|
+
"no-session-links": guidance(
|
|
135
|
+
"This is a public repo. Claude Code session URLs are private and must not appear in commits or PRs.",
|
|
136
|
+
),
|
|
137
|
+
|
|
138
|
+
"readme-brevity": guidance(
|
|
139
|
+
"README.md should be a concise pitch + quick start, not a reference manual. Extract detailed sections into docs/ and link with `[Details →](docs/X.md)`. Target ~300 lines max.",
|
|
140
|
+
),
|
|
141
|
+
},
|
|
142
|
+
});
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Contributing to vigiles
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in contributing! This guide covers everything you need to get started.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- **Node.js** 20+
|
|
8
|
+
- **npm** 10+
|
|
9
|
+
- For full test coverage, you'll also need these linter CLIs on your PATH:
|
|
10
|
+
- `ruff` and `pylint` (Python)
|
|
11
|
+
- `rubocop` (Ruby)
|
|
12
|
+
- `cargo` with `clippy` (Rust)
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
git clone https://github.com/zernie/vigiles.git
|
|
18
|
+
cd vigiles
|
|
19
|
+
npm install
|
|
20
|
+
npm run build
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Project structure
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
src/
|
|
27
|
+
types.ts Type definitions (interfaces, type aliases)
|
|
28
|
+
validate.ts Core validation engine (parsing, config, linter checks)
|
|
29
|
+
action.ts GitHub Action wrapper (reads env vars, calls validatePaths)
|
|
30
|
+
cli.ts CLI entry point (arg parsing, output formatting)
|
|
31
|
+
validate.test.ts Test suite (node:test)
|
|
32
|
+
schemas/ Built-in mdschema YAML presets
|
|
33
|
+
skills/ Claude Code skills (enforce-rules-format, audit-feedback-loop, pr-to-lint-rule)
|
|
34
|
+
dist/ Compiled JavaScript output (git-ignored)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Development workflow
|
|
38
|
+
|
|
39
|
+
### Build
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm run build # Compile TypeScript → dist/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Test
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm test # Build + run all tests
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Tests use Node.js built-in test runner (`node:test`) and `node:assert/strict`. No extra test framework needed.
|
|
52
|
+
|
|
53
|
+
### Format
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm run fmt # Auto-format with Prettier
|
|
57
|
+
npm run fmt:check # Check formatting (CI uses this)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Type check
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx tsc --noEmit # Type-check without emitting
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Run locally
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npx vigiles CLAUDE.md # Validate a file
|
|
70
|
+
npx vigiles --markers=headings,checkboxes . # Custom markers
|
|
71
|
+
npx vigiles # Auto-discover instruction files
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## TypeScript conventions
|
|
75
|
+
|
|
76
|
+
This project uses **TypeScript strict mode** with these compiler options enabled:
|
|
77
|
+
|
|
78
|
+
- `strict: true` (includes `strictNullChecks`, `noImplicitAny`, etc.)
|
|
79
|
+
- `noUncheckedIndexedAccess: true`
|
|
80
|
+
- `noUnusedLocals: true`
|
|
81
|
+
- `noUnusedParameters: true`
|
|
82
|
+
|
|
83
|
+
### Guidelines
|
|
84
|
+
|
|
85
|
+
- **Explicit types** on all exported function signatures (parameters and return types).
|
|
86
|
+
- **No `any`** — use `unknown` and narrow with type guards when the type is truly unknown.
|
|
87
|
+
- Import types with `import type { ... }` when only used in type positions.
|
|
88
|
+
- Use `.js` extensions in import paths (required by Node16 module resolution).
|
|
89
|
+
- Keep the single-file core architecture — `validate.ts` contains all validation logic.
|
|
90
|
+
|
|
91
|
+
## Adding a new validation rule
|
|
92
|
+
|
|
93
|
+
1. Add the rule name and default value to `RulesConfig` in `src/types.ts`.
|
|
94
|
+
2. Add the default to `RULE_PACKS` in `src/validate.ts`.
|
|
95
|
+
3. Implement the check inside the `validate()` function.
|
|
96
|
+
4. Add tests in `src/validate.test.ts`.
|
|
97
|
+
5. Document the rule in `README.md` and `CLAUDE.md`.
|
|
98
|
+
|
|
99
|
+
## Adding a new linter resolver
|
|
100
|
+
|
|
101
|
+
1. Add a Node API resolver to `LINTER_RESOLVERS` (if the linter has a Node API).
|
|
102
|
+
2. Or add a CLI checker to `CLI_RULE_CHECKS` and map it in `CLI_TOOL_FOR_LINTER`.
|
|
103
|
+
3. Optionally add a config-enabled checker to `LINTER_CONFIG_CHECKERS`.
|
|
104
|
+
4. Add tests covering both existing and nonexistent rules.
|
|
105
|
+
|
|
106
|
+
## Pull requests
|
|
107
|
+
|
|
108
|
+
- Keep PRs focused — one feature or fix per PR.
|
|
109
|
+
- All tests must pass (`npm test`).
|
|
110
|
+
- Code must compile without errors (`npx tsc --noEmit`).
|
|
111
|
+
- Code must be formatted (`npm run fmt:check`).
|
|
112
|
+
- Update `CLAUDE.md` if you change exported APIs or add new rules.
|
|
113
|
+
- Write descriptive commit messages explaining _why_, not just _what_.
|
|
114
|
+
|
|
115
|
+
## Architecture decisions
|
|
116
|
+
|
|
117
|
+
- **Single-file core**: All validation logic lives in `validate.ts` for portability and minimal dependency surface.
|
|
118
|
+
- **Zero config by default**: vigiles works out of the box. Config exists only for overrides.
|
|
119
|
+
- **Two rule packs**: `"recommended"` (permissive defaults) and `"strict"` (tighter constraints).
|
|
120
|
+
- **Linter auto-detection**: No need to declare which linters you use — vigiles discovers them.
|
|
121
|
+
- **Agent auto-discovery**: Detects AI coding tools by their config directories and validates their instruction files exist.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 vigiles contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="logo.png" width="140" alt="vigiles logo" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">vigiles</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<em>Quis custodiet ipsos custodes?</em> — Who watches the watchmen?
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/vigiles"><img src="https://img.shields.io/npm/v/vigiles?color=orange" alt="npm version" /></a>
|
|
13
|
+
<a href="https://github.com/zernie/vigiles/actions"><img src="https://img.shields.io/github/actions/workflow/status/zernie/vigiles/ci.yml?branch=main" alt="CI" /></a>
|
|
14
|
+
<a href="https://github.com/zernie/vigiles/blob/main/LICENSE"><img src="https://img.shields.io/github/license/zernie/vigiles" alt="License" /></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
You wouldn't ship code without a linter. Why ship agent instructions without one?
|
|
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:
|
|
40
|
+
|
|
41
|
+
```markdown
|
|
42
|
+
## Code Style
|
|
43
|
+
|
|
44
|
+
Never use `any` — the `@typescript-eslint/no-explicit-any` rule
|
|
45
|
+
catches this. Always use `unknown` and narrow with type guards.
|
|
46
|
+
See `src/utils/type-helpers.ts` for project utilities.
|
|
47
|
+
|
|
48
|
+
## Testing
|
|
49
|
+
|
|
50
|
+
Run `npm run typecheck` before submitting. Every service in
|
|
51
|
+
src/services/ should have a corresponding test file.
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Reads fine. Four things are wrong:
|
|
55
|
+
|
|
56
|
+
1. `@typescript-eslint/no-explicit-any` — disabled to unblock a deadline, never re-enabled
|
|
57
|
+
2. `src/utils/type-helpers.ts` — renamed to `src/utils/narrowing.ts` last quarter
|
|
58
|
+
3. `npm run typecheck` — script removed from package.json
|
|
59
|
+
4. Service/test pairing — no automated check, just a hope
|
|
60
|
+
|
|
61
|
+
The agent reads this, trusts it, and writes code based on stale claims nobody verified.
|
|
62
|
+
|
|
63
|
+
## What Changes With vigiles
|
|
64
|
+
|
|
65
|
+
### Claude Code
|
|
66
|
+
|
|
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 |
|
|
78
|
+
|
|
79
|
+
<details>
|
|
80
|
+
<summary><b>Codex</b> (same compile-time checks, no hooks)</summary>
|
|
81
|
+
|
|
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 |
|
|
90
|
+
|
|
91
|
+
</details>
|
|
92
|
+
|
|
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)
|
|
94
|
+
|
|
95
|
+
## The Fix
|
|
96
|
+
|
|
97
|
+
Write your conventions as TypeScript. The compiler catches the lies.
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// CLAUDE.md.spec.ts
|
|
101
|
+
import { claude, enforce, guidance } from "vigiles/spec";
|
|
102
|
+
|
|
103
|
+
export default claude({
|
|
104
|
+
commands: {
|
|
105
|
+
"npm run build": "Compile TypeScript to dist/",
|
|
106
|
+
"npm test": "Build and run all tests",
|
|
107
|
+
// ✗ "npm run typecheck" → compile error: script not in package.json
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
keyFiles: {
|
|
111
|
+
"src/utils/narrowing.ts": "Type guard utilities",
|
|
112
|
+
// ✗ "src/utils/type-helpers.ts" → compile error: file not found
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
rules: {
|
|
116
|
+
"no-explicit-any": enforce(
|
|
117
|
+
"@typescript-eslint/no-explicit-any",
|
|
118
|
+
"Use unknown and narrow with type guards.",
|
|
119
|
+
),
|
|
120
|
+
// ✗ if rule is disabled in config → compile error
|
|
121
|
+
|
|
122
|
+
"research-first": guidance("Google unfamiliar APIs first."),
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
$ npx vigiles compile
|
|
129
|
+
|
|
130
|
+
✓ CLAUDE.md.spec.ts → CLAUDE.md
|
|
131
|
+
2 rules (1 linter-verified, 1 guidance)
|
|
132
|
+
~180 tokens
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The spec is the source of truth. CLAUDE.md is a build artifact.
|
|
136
|
+
|
|
137
|
+
## Quick Start
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npx vigiles init
|
|
141
|
+
```
|
|
142
|
+
|
|
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.
|
|
144
|
+
|
|
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
|
+
```
|
|
157
|
+
|
|
158
|
+
**After install, it just works:**
|
|
159
|
+
|
|
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
|
|
164
|
+
|
|
165
|
+
### Hesitant about a new file type? Try inline mode
|
|
166
|
+
|
|
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`:
|
|
168
|
+
|
|
169
|
+
```md
|
|
170
|
+
<!-- vigiles:enforce eslint/no-console "Route output through logger.ts" -->
|
|
171
|
+
```
|
|
172
|
+
|
|
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.
|
|
174
|
+
|
|
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.
|
|
176
|
+
|
|
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.
|
|
178
|
+
|
|
179
|
+
**Already have a hand-written CLAUDE.md?** The wizard detects it and suggests migration.
|
|
180
|
+
|
|
181
|
+
**Ready to enforce?** Run `npx vigiles init --strict` to set rules to `"error"` — CI fails if any instruction file lacks a spec.
|
|
182
|
+
|
|
183
|
+
| Flag | Effect |
|
|
184
|
+
| -------------------- | ----------------------------------------------------- |
|
|
185
|
+
| `--strict` | Sets require-spec and require-skill-spec to `"error"` |
|
|
186
|
+
| `--target=AGENTS.md` | Creates AGENTS.md spec instead of CLAUDE.md |
|
|
187
|
+
| `--no-gha` | Skip adding CI step to GHA workflow |
|
|
188
|
+
|
|
189
|
+
Works the same for humans and agents — fully non-interactive. [Agent setup guide →](docs/agent-setup.md) | [Agent workflows →](docs/agent-workflows.md)
|
|
190
|
+
|
|
191
|
+
## Two Rule Types
|
|
192
|
+
|
|
193
|
+
**`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
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
"no-any": enforce("@typescript-eslint/no-explicit-any", "Use unknown and narrow."),
|
|
197
|
+
"no-print": enforce("ruff/T201", "Use logging module."),
|
|
198
|
+
"no-unwrap": enforce("clippy/unwrap_used", "Use expect() with context."),
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Supports ESLint, Stylelint, Ruff, Clippy, Pylint, and RuboCop. [Full linter support details →](docs/linter-support.md)
|
|
202
|
+
|
|
203
|
+
**`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
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
"research-first": guidance("Google unfamiliar APIs first."),
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Verified References
|
|
210
|
+
|
|
211
|
+
`file()`, `cmd()`, and `ref()` catch stale references at compile time:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { claude, file, cmd, ref, instructions } from "vigiles/spec";
|
|
215
|
+
|
|
216
|
+
export default claude({
|
|
217
|
+
sections: {
|
|
218
|
+
architecture: instructions`
|
|
219
|
+
Core engine in ${file("src/compile.ts")}.
|
|
220
|
+
Run ${cmd("npm test")} to verify.
|
|
221
|
+
See ${ref("skills/deploy/SKILL.md")} for deployment.
|
|
222
|
+
`,
|
|
223
|
+
// If any path is stale → compile error
|
|
224
|
+
},
|
|
225
|
+
// ...
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Skill specs use the same helpers for verified references inside instructions. [Full spec format →](docs/spec-format.md)
|
|
230
|
+
|
|
231
|
+
## Type-Safe Rule References
|
|
232
|
+
|
|
233
|
+
`vigiles generate-types` scans your linter configs and emits `.vigiles/generated.d.ts`. With this file, `enforce("eslint/no-consolee")` is a red squiggle in your editor — a typo caught at authoring time, not a runtime surprise. Without it, everything falls back to broad types and still works.
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
$ npx vigiles generate-types
|
|
237
|
+
eslint: 64 enabled rules | ruff: 12 | npm scripts: 5 | project files: 42
|
|
238
|
+
✓ Generated .vigiles/generated.d.ts
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
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
|
+
|
|
243
|
+
## CLI
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
npx vigiles init [--target=X.md] # Scaffold a spec (runs full setup wizard by default)
|
|
247
|
+
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
|
|
250
|
+
npx vigiles generate-types --check # Verify .d.ts is up to date
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## GitHub Action
|
|
254
|
+
|
|
255
|
+
```yaml
|
|
256
|
+
- uses: zernie/vigiles@main # runs `audit` by default
|
|
257
|
+
- uses: zernie/vigiles@main
|
|
258
|
+
with:
|
|
259
|
+
command: compile # compile specs in CI
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
To verify generated types are fresh in CI:
|
|
263
|
+
|
|
264
|
+
```yaml
|
|
265
|
+
- run: npx vigiles generate-types --check
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Claude Code Plugin
|
|
269
|
+
|
|
270
|
+
**Install the plugin.** Without it, you're responsible for manually running `compile` and `generate-types`. With it, the agent works with fresh instruction files automatically.
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npx skills add zernie/vigiles
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The plugin provides two hooks:
|
|
277
|
+
|
|
278
|
+
- **PreToolUse** (Edit/Write) — blocks direct edits to compiled `.md` files and redirects the agent to the `.spec.ts` source
|
|
279
|
+
- **PostToolUse** (Edit/Write) — auto-runs `generate-types` on linter config changes, `compile` on `.spec.ts` changes
|
|
280
|
+
|
|
281
|
+
## Validation
|
|
282
|
+
|
|
283
|
+
`vigiles audit` validates instruction files with three rules:
|
|
284
|
+
|
|
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
|
+
```
|
|
294
|
+
|
|
295
|
+
Configure in `.vigilesrc.json`:
|
|
296
|
+
|
|
297
|
+
```json
|
|
298
|
+
{
|
|
299
|
+
"rules": {
|
|
300
|
+
"require-spec": "error",
|
|
301
|
+
"freshness": "error"
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
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)
|
|
336
|
+
|
|
337
|
+
## Skills
|
|
338
|
+
|
|
339
|
+
Install with [Vercel Skills](https://github.com/vercel-labs/skills): `npx skills add zernie/vigiles`
|
|
340
|
+
|
|
341
|
+
| Skill | What it does |
|
|
342
|
+
| ---------------------- | ----------------------------------------------------------------------- |
|
|
343
|
+
| `strengthen` | Upgrade `guidance()` → `enforce()` using linter-specific reference docs |
|
|
344
|
+
| `edit-spec` | Edit a spec file — guided workflow with compile step |
|
|
345
|
+
| `migrate-to-spec` | Convert a hand-written CLAUDE.md to a typed `.spec.ts` |
|
|
346
|
+
| `generate-rule` | Add a new `enforce()` / `guidance()` rule to a spec |
|
|
347
|
+
| `pr-to-lint-rule` | Turn a recurring PR review comment into a lint rule + spec entry |
|
|
348
|
+
| `enforce-rules-format` | Validate all rules have enforcement classification |
|
|
349
|
+
| `audit-feedback-loop` | Score your repo's feedback loop maturity |
|
|
350
|
+
|
|
351
|
+
## Maturity Levels
|
|
352
|
+
|
|
353
|
+
From [Feedback Loop Is All You Need](https://zernie.com/blog/feedback-loop-is-all-you-need):
|
|
354
|
+
|
|
355
|
+
| Level | Name | What it means |
|
|
356
|
+
| ----- | -------------------- | ------------------------------------------------------------------- |
|
|
357
|
+
| 0 | Vibes | No CI, no linters, no CLAUDE.md |
|
|
358
|
+
| 1 | Guardrails | CI + standard linters, no custom rules |
|
|
359
|
+
| 2 | Architecture as Code | Custom lint rules + enforced CLAUDE.md |
|
|
360
|
+
| 3 | The Organism | CI + custom rules + visual tests + observability + scheduled agents |
|
|
361
|
+
|
|
362
|
+
## Output Targets
|
|
363
|
+
|
|
364
|
+
Specs compile to `CLAUDE.md` by default. Set `target: "AGENTS.md"` or `target: ["CLAUDE.md", "AGENTS.md"]` for multiple outputs from one spec. For non-markdown formats (`.cursorrules`, Copilot), use [rule-porter](https://github.com/nichochar/rule-porter) or [rulesync](https://github.com/dyoshikawa/rulesync) to convert. [Spec format →](docs/spec-format.md)
|
|
365
|
+
|
|
366
|
+
## Related Tools
|
|
367
|
+
|
|
368
|
+
vigiles doesn't try to do everything:
|
|
369
|
+
|
|
370
|
+
- **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.
|
|
373
|
+
- **Prose quality** — [Vale](https://vale.sh). Different concern.
|
|
374
|
+
|
|
375
|
+
## License
|
|
376
|
+
|
|
377
|
+
[MIT](LICENSE)
|