vigiles 2.0.0 → 2.2.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.
Files changed (184) hide show
  1. package/README.md +182 -134
  2. package/dist/action-gate.d.ts +28 -0
  3. package/dist/action-gate.js +73 -0
  4. package/dist/cli.js +705 -230
  5. package/dist/community-skills.d.ts +22 -0
  6. package/dist/community-skills.js +86 -0
  7. package/dist/compile-generator.d.ts +48 -0
  8. package/dist/compile-generator.js +322 -0
  9. package/dist/compile.d.ts +4 -0
  10. package/dist/compile.js +239 -45
  11. package/dist/coverage.d.ts +56 -0
  12. package/dist/coverage.js +178 -0
  13. package/dist/doc-refs.d.ts +60 -0
  14. package/dist/doc-refs.js +246 -0
  15. package/dist/eval.d.ts +62 -0
  16. package/dist/eval.js +174 -0
  17. package/dist/evolve.js +60 -125
  18. package/dist/frontmatter.d.ts +75 -0
  19. package/dist/frontmatter.js +263 -0
  20. package/dist/generate-schema.d.ts +51 -0
  21. package/dist/generate-schema.js +125 -0
  22. package/dist/generate-types.js +39 -1
  23. package/dist/harness-test.d.ts +38 -0
  24. package/dist/harness-test.js +129 -0
  25. package/dist/hash.d.ts +8 -0
  26. package/dist/hash.js +16 -0
  27. package/dist/inline.d.ts +22 -4
  28. package/dist/inline.js +60 -13
  29. package/dist/integrity.d.ts +29 -0
  30. package/dist/integrity.js +44 -0
  31. package/dist/linters.d.ts +5 -3
  32. package/dist/linters.js +144 -4
  33. package/dist/mock-model.d.ts +31 -0
  34. package/dist/mock-model.js +189 -0
  35. package/dist/orphans.d.ts +52 -0
  36. package/dist/orphans.js +124 -0
  37. package/dist/proofs.js +22 -16
  38. package/dist/refs.d.ts +44 -0
  39. package/dist/refs.js +144 -0
  40. package/dist/session.d.ts +97 -0
  41. package/dist/session.js +306 -0
  42. package/dist/sidecar.d.ts +35 -0
  43. package/dist/sidecar.js +102 -0
  44. package/dist/skill-driver.d.ts +77 -0
  45. package/dist/skill-driver.js +76 -0
  46. package/dist/skill-runtime.d.ts +101 -0
  47. package/dist/skill-runtime.js +289 -0
  48. package/dist/skill-test.d.ts +47 -0
  49. package/dist/skill-test.js +77 -0
  50. package/dist/spec.d.ts +119 -13
  51. package/dist/spec.js +51 -4
  52. package/dist/symbols.d.ts +30 -0
  53. package/dist/symbols.js +142 -0
  54. package/dist/test-utils.d.ts +8 -0
  55. package/dist/test-utils.js +41 -0
  56. package/dist/types.d.ts +34 -8
  57. package/dist/types.js +19 -0
  58. package/dist/validate.js +5 -3
  59. package/package.json +26 -5
  60. package/.claude/settings.json +0 -46
  61. package/.claude/settings.local.json +0 -8
  62. package/.github/workflows/ci.yml +0 -81
  63. package/.prettierignore +0 -1
  64. package/.vigiles/generated.d.ts +0 -205
  65. package/CLAUDE.md +0 -95
  66. package/CLAUDE.md.spec.ts +0 -142
  67. package/CONTRIBUTING.md +0 -121
  68. package/dist/action.d.ts.map +0 -1
  69. package/dist/action.js.map +0 -1
  70. package/dist/cli.d.ts.map +0 -1
  71. package/dist/cli.js.map +0 -1
  72. package/dist/cli.test.d.ts +0 -2
  73. package/dist/cli.test.d.ts.map +0 -1
  74. package/dist/cli.test.js +0 -650
  75. package/dist/cli.test.js.map +0 -1
  76. package/dist/compile.d.ts.map +0 -1
  77. package/dist/compile.js.map +0 -1
  78. package/dist/evolve.d.ts.map +0 -1
  79. package/dist/evolve.js.map +0 -1
  80. package/dist/freshness.d.ts +0 -67
  81. package/dist/freshness.d.ts.map +0 -1
  82. package/dist/freshness.js +0 -244
  83. package/dist/freshness.js.map +0 -1
  84. package/dist/freshness.test.d.ts +0 -2
  85. package/dist/freshness.test.d.ts.map +0 -1
  86. package/dist/freshness.test.js +0 -356
  87. package/dist/freshness.test.js.map +0 -1
  88. package/dist/generate-types.d.ts.map +0 -1
  89. package/dist/generate-types.js.map +0 -1
  90. package/dist/inline.d.ts.map +0 -1
  91. package/dist/inline.js.map +0 -1
  92. package/dist/inline.test.d.ts +0 -5
  93. package/dist/inline.test.d.ts.map +0 -1
  94. package/dist/inline.test.js +0 -152
  95. package/dist/inline.test.js.map +0 -1
  96. package/dist/linters.d.ts.map +0 -1
  97. package/dist/linters.js.map +0 -1
  98. package/dist/proofs.d.ts.map +0 -1
  99. package/dist/proofs.js.map +0 -1
  100. package/dist/proofs.test.d.ts +0 -9
  101. package/dist/proofs.test.d.ts.map +0 -1
  102. package/dist/proofs.test.js +0 -952
  103. package/dist/proofs.test.js.map +0 -1
  104. package/dist/spec.d.ts.map +0 -1
  105. package/dist/spec.js.map +0 -1
  106. package/dist/spec.test.d.ts +0 -2
  107. package/dist/spec.test.d.ts.map +0 -1
  108. package/dist/spec.test.js +0 -1222
  109. package/dist/spec.test.js.map +0 -1
  110. package/dist/types.d.ts.map +0 -1
  111. package/dist/types.js.map +0 -1
  112. package/dist/validate.d.ts.map +0 -1
  113. package/dist/validate.js.map +0 -1
  114. package/dist/validate.test.d.ts +0 -2
  115. package/dist/validate.test.d.ts.map +0 -1
  116. package/dist/validate.test.js +0 -531
  117. package/dist/validate.test.js.map +0 -1
  118. package/docs/agent-setup.md +0 -85
  119. package/docs/agent-workflows.md +0 -103
  120. package/docs/comparison.md +0 -71
  121. package/docs/freshness.md +0 -124
  122. package/docs/inline-mode.md +0 -119
  123. package/docs/linter-support.md +0 -166
  124. package/docs/spec-format.md +0 -194
  125. package/eslint.config.mjs +0 -79
  126. package/examples/CLAUDE.md +0 -54
  127. package/examples/CLAUDE.md.spec.ts +0 -65
  128. package/examples/SKILL.md +0 -50
  129. package/examples/SKILL.md.spec.ts +0 -57
  130. package/fixtures/example-project/CLAUDE.md +0 -11
  131. package/fixtures/example-project/package.json +0 -9
  132. package/fixtures/example-project/src/index.ts +0 -3
  133. package/fixtures/example-project/src/utils.test.ts +0 -2
  134. package/fixtures/example-project/src/utils.ts +0 -3
  135. package/logo.png +0 -0
  136. package/research/adoption-strategy.md +0 -111
  137. package/research/agent-integration.md +0 -145
  138. package/research/ai-code-quality.md +0 -197
  139. package/research/code-search-for-agents.md +0 -313
  140. package/research/competitive-landscape.md +0 -163
  141. package/research/doc-freshness.md +0 -516
  142. package/research/executable-specs.md +0 -368
  143. package/research/feature-ideas.md +0 -464
  144. package/research/formal-proofs-for-agents.md +0 -338
  145. package/research/fp-for-agent-harness.md +0 -150
  146. package/research/fp-for-deterministic-ai.md +0 -131
  147. package/research/self-evolving-specs.md +0 -298
  148. package/schemas/claude-md-strict.yml +0 -18
  149. package/schemas/claude-md.yml +0 -6
  150. package/schemas/skill-strict.yml +0 -12
  151. package/schemas/skill.yml +0 -5
  152. package/skills/audit-feedback-loop/SKILL.md +0 -76
  153. package/skills/edit-spec/SKILL.md +0 -131
  154. package/skills/enforce-rules-format/SKILL.md +0 -71
  155. package/skills/generate-logo/SKILL.md +0 -102
  156. package/skills/generate-rule/SKILL.md +0 -90
  157. package/skills/linter-docs/clippy.md +0 -241
  158. package/skills/linter-docs/eslint.md +0 -384
  159. package/skills/linter-docs/pylint.md +0 -288
  160. package/skills/linter-docs/rubocop.md +0 -277
  161. package/skills/linter-docs/ruff.md +0 -187
  162. package/skills/linter-docs/stylelint.md +0 -247
  163. package/skills/migrate-to-spec/SKILL.md +0 -124
  164. package/skills/pr-to-lint-rule/SKILL.md +0 -97
  165. package/skills/strengthen/SKILL.md +0 -168
  166. package/src/action.ts +0 -214
  167. package/src/cli.test.ts +0 -914
  168. package/src/cli.ts +0 -1631
  169. package/src/compile.ts +0 -691
  170. package/src/evolve.ts +0 -781
  171. package/src/freshness.test.ts +0 -449
  172. package/src/freshness.ts +0 -299
  173. package/src/generate-types.ts +0 -448
  174. package/src/inline.test.ts +0 -206
  175. package/src/inline.ts +0 -164
  176. package/src/linters.ts +0 -739
  177. package/src/proofs.test.ts +0 -1314
  178. package/src/proofs.ts +0 -849
  179. package/src/spec.test.ts +0 -1471
  180. package/src/spec.ts +0 -427
  181. package/src/types.ts +0 -117
  182. package/src/validate.test.ts +0 -701
  183. package/src/validate.ts +0 -381
  184. package/tsconfig.json +0 -23
@@ -1,194 +0,0 @@
1
- # Spec Format Reference
2
-
3
- vigiles specs are TypeScript files (`*.spec.ts`) that compile to markdown instruction files. The spec is the source of truth; the markdown is a build artifact.
4
-
5
- ## CLAUDE.md Specs
6
-
7
- Use `claude()` to define a CLAUDE.md spec. Export it as the default export.
8
-
9
- ```ts
10
- import { claude, enforce, guidance, file, cmd, ref, instructions } from "vigiles";
11
-
12
- export default claude({
13
- target: "CLAUDE.md", // or "AGENTS.md", or ["CLAUDE.md", "AGENTS.md"]
14
- sections: { ... },
15
- keyFiles: { ... },
16
- commands: { ... },
17
- rules: { ... },
18
- maxSectionLines: 30, // optional: cap per-section line count
19
- });
20
- ```
21
-
22
- ### `target`
23
-
24
- `string | string[]` -- Output filename(s). Defaults to `"CLAUDE.md"`. Also used as the `# Heading` in compiled output. Pass an array to compile one spec to multiple targets:
25
-
26
- ```ts
27
- target: ["CLAUDE.md", "AGENTS.md"], // emits both from one spec
28
- ```
29
-
30
- ### `sections`
31
-
32
- `Record<string, string | InstructionFragment[]>` -- Named prose sections. Each key becomes a `## Heading` in the compiled output (first letter uppercased). Values are either plain strings or tagged templates via `instructions` with embedded `file()`, `cmd()`, and `ref()` references.
33
-
34
- ```ts
35
- sections: {
36
- architecture: `Two rule types: enforce() and guidance().`,
37
- setup: instructions`See ${file("docs/setup.md")} and run ${cmd("npm install")}.`,
38
- }
39
- ```
40
-
41
- ### `keyFiles`
42
-
43
- `Record<string, string>` -- File paths mapped to descriptions. Each path is verified via `existsSync` at compile time. Compiles to a bullet list under `## Key Files`.
44
-
45
- ```ts
46
- keyFiles: {
47
- "src/spec.ts": "Type system and builder functions",
48
- "src/compile.ts": "Compiler: spec to markdown with SHA-256 hash",
49
- }
50
- ```
51
-
52
- ### `commands`
53
-
54
- `Record<string, string>` -- Commands mapped to descriptions. `npm run <script>` and `npm <lifecycle>` commands are verified against `package.json` scripts at compile time. Compiles to a bullet list under `## Commands`.
55
-
56
- ```ts
57
- commands: {
58
- "npm run build": "Compile TypeScript to dist/",
59
- "npm test": "Build and run all tests",
60
- }
61
- ```
62
-
63
- ### `rules`
64
-
65
- `Record<string, Rule>` -- Rule ID mapped to an `enforce()` or `guidance()` rule. The ID is kebab-cased by convention and is converted to a Title Case `### Heading` in compiled output. See [Rule Types](#rule-types) below.
66
-
67
- ## SKILL.md Specs
68
-
69
- Use `skill()` to define a SKILL.md spec. Compiles to markdown with YAML frontmatter.
70
-
71
- ```ts
72
- import { skill, file, cmd, ref, instructions } from "vigiles";
73
-
74
- export default skill({
75
- name: "pr-to-lint-rule",
76
- description: "Convert PR feedback into an automated lint rule",
77
- argumentHint: "<description of recurring PR feedback>",
78
- disableModelInvocation: true,
79
- body: instructions`
80
- Check ${file("eslint.config.ts")} for existing rules.
81
- Run ${cmd("npm test")} to verify.
82
- See ${ref("skills/other/SKILL.md")} for format.
83
- `,
84
- });
85
- ```
86
-
87
- | Field | Type | Required | Description |
88
- | ------------------------ | --------------------------------- | -------- | --------------------------------------------------- |
89
- | `name` | `string` | yes | Skill name (used in YAML frontmatter) |
90
- | `description` | `string` | yes | Short description (frontmatter) |
91
- | `argumentHint` | `string` | no | Hint for the argument (frontmatter) |
92
- | `disableModelInvocation` | `boolean` | no | Disable model invocation flag (frontmatter) |
93
- | `body` | `string \| InstructionFragment[]` | yes | Instruction body -- plain string or tagged template |
94
-
95
- ## Reference Helpers
96
-
97
- Reference helpers create branded types that the compiler validates at compile time.
98
-
99
- ### `file(path)`
100
-
101
- Returns a `FileRef` containing a `VerifiedPath`. The path is verified to exist via `existsSync` at compile time. Compiles to a backtick path in markdown: `` `path/to/file.ts` ``.
102
-
103
- ### `cmd(command)`
104
-
105
- Returns a `CmdRef` containing a `VerifiedCmd`. For npm commands, the script is verified against `package.json` at compile time. Compiles to a backtick command: `` `npm run build` ``.
106
-
107
- ### `ref(path)`
108
-
109
- Returns a `SkillRef` containing a `VerifiedRef`. The path is verified to exist at compile time. Compiles to a markdown link: `[dirname](path)`.
110
-
111
- ### `instructions`
112
-
113
- Tagged template literal that interleaves strings and refs. Use it for `sections` values in `claude()` or the `body` of `skill()`.
114
-
115
- ```ts
116
- instructions`Check ${file("tsconfig.json")} then run ${cmd("npm test")}.`;
117
- // Returns InstructionFragment[] -- the compiler renders and validates each ref.
118
- ```
119
-
120
- ## Rule Types
121
-
122
- ### `enforce(linterRule, why)`
123
-
124
- Declares a rule delegated to an external linter. The `linterRule` accepts template literal types:
125
-
126
- - `${BuiltinLinter}/${string}` where BuiltinLinter is `eslint`, `stylelint`, `ruff`, `clippy`, `pylint`, or `rubocop`
127
- - `@${scope}/${rule}` for scoped ESLint plugins (e.g., `@typescript-eslint/no-explicit-any`)
128
-
129
- At compile time, vigiles verifies the rule exists in the linter's catalog and is enabled in the project's config. Compiles to `**Enforced by:** ` followed by the linter rule in backticks.
130
-
131
- ```ts
132
- rules: {
133
- "no-console-log": enforce("eslint/no-console", "Use structured logger."),
134
- "no-print": enforce("ruff/T201", "Use logging module."),
135
- }
136
- ```
137
-
138
- ### `guidance(text)`
139
-
140
- Declares a prose-only rule with no mechanical enforcement. Guidance rules still 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.
141
-
142
- ```ts
143
- rules: {
144
- "prefer-composition": guidance("Prefer composition over inheritance."),
145
- }
146
- ```
147
-
148
- Compiles to: `**Guidance only** -- <text>`.
149
-
150
- ## Branded Types
151
-
152
- `VerifiedPath`, `VerifiedCmd`, and `VerifiedRef` are branded string types (`string & { readonly [__brand]: "..." }`). They distinguish compiler-verified references from raw strings.
153
-
154
- - `file()` produces `FileRef` containing `VerifiedPath`
155
- - `cmd()` produces `CmdRef` containing `VerifiedCmd`
156
- - `ref()` produces `SkillRef` containing `VerifiedRef`
157
-
158
- The compiler only accepts these branded types in path-sensitive positions. This prevents passing unverified strings where a verified reference is expected -- the TypeScript compiler catches the error at authoring time.
159
-
160
- ## Configuration
161
-
162
- Create `vigiles.config.ts` with `defineConfig()`:
163
-
164
- ```ts
165
- import { defineConfig } from "vigiles";
166
-
167
- export default defineConfig({
168
- specs: "**/*.spec.ts", // glob pattern for spec discovery (default: "**/*.spec.ts")
169
- discover: true, // auto-discover linter rules for coverage reporting
170
- maxRules: 50, // maximum rules per spec file
171
- maxTokens: 2000, // maximum estimated tokens for compiled output (~4 chars/token)
172
- });
173
- ```
174
-
175
- | Option | Type | Description |
176
- | ----------- | --------- | ------------------------------------------------------- |
177
- | `specs` | `string` | Glob pattern to discover spec files |
178
- | `discover` | `boolean` | Auto-discover linter rules for coverage reporting |
179
- | `maxRules` | `number` | Compilation fails if a spec exceeds this rule count |
180
- | `maxTokens` | `number` | Compilation fails if estimated tokens exceed this limit |
181
-
182
- ## Hash Verification
183
-
184
- Every compiled file starts with a SHA-256 integrity hash comment:
185
-
186
- ```
187
- <!-- vigiles:sha256:a1b2c3d4e5f67890 compiled from CLAUDE.md.spec.ts -->
188
- ```
189
-
190
- The hash covers the full compiled content (excluding the hash line itself), truncated to 16 hex characters.
191
-
192
- ### `vigiles audit`
193
-
194
- Verifies that each compiled file's hash matches its content, reports linter rule coverage gaps, and suggests guidance rules that could be upgraded to `enforce()`. If someone manually edits the markdown, the hash will no longer match, and `vigiles audit` reports the file as modified. This ensures the spec remains the source of truth.
package/eslint.config.mjs DELETED
@@ -1,79 +0,0 @@
1
- import eslint from "@eslint/js";
2
- import tseslint from "@typescript-eslint/eslint-plugin";
3
- import tsparser from "@typescript-eslint/parser";
4
- import sonarjs from "eslint-plugin-sonarjs";
5
- import globals from "globals";
6
-
7
- export default [
8
- {
9
- ignores: ["dist/", "node_modules/"],
10
- },
11
- eslint.configs.recommended,
12
- {
13
- files: ["src/**/*.ts"],
14
- languageOptions: {
15
- parser: tsparser,
16
- globals: {
17
- ...globals.node,
18
- },
19
- parserOptions: {
20
- projectService: true,
21
- tsconfigRootDir: import.meta.dirname,
22
- },
23
- },
24
- plugins: {
25
- "@typescript-eslint": tseslint,
26
- sonarjs,
27
- },
28
- rules: {
29
- ...tseslint.configs["strict-type-checked"]?.rules,
30
- // TypeScript handles these better than ESLint
31
- "no-undef": "off",
32
- "no-unused-vars": "off",
33
- // Allow unused vars prefixed with _
34
- "@typescript-eslint/no-unused-vars": [
35
- "error",
36
- { argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
37
- ],
38
- // We use createRequire legitimately for linter detection
39
- "@typescript-eslint/no-require-imports": "off",
40
- // Relax some strict rules that are too noisy for this codebase
41
- "@typescript-eslint/restrict-template-expressions": "off",
42
- "@typescript-eslint/no-unnecessary-condition": "off",
43
- // Ban non-null assertions — use proper narrowing instead
44
- "@typescript-eslint/no-non-null-assertion": "error",
45
-
46
- // --- Complexity rules ---
47
- complexity: ["warn", { max: 15 }],
48
- "max-depth": ["warn", { max: 4 }],
49
- "max-lines-per-function": [
50
- "warn",
51
- { max: 80, skipBlankLines: true, skipComments: true },
52
- ],
53
- "max-params": ["warn", { max: 4 }],
54
-
55
- // --- SonarJS ---
56
- "sonarjs/cognitive-complexity": ["warn", 15],
57
- "sonarjs/no-duplicate-string": ["warn", { threshold: 4 }],
58
- "sonarjs/no-identical-functions": "warn",
59
- "sonarjs/no-duplicated-branches": "warn",
60
- "sonarjs/no-identical-conditions": "error",
61
- "sonarjs/no-identical-expressions": "error",
62
- "sonarjs/no-nested-conditional": "warn",
63
- "sonarjs/nested-control-flow": ["warn", { maximumNestingLevel: 3 }],
64
- },
65
- },
66
- // Test files: relax promise, assertion, and complexity rules
67
- {
68
- files: ["src/**/*.test.ts"],
69
- rules: {
70
- // node:test describe/it return promises that don't need to be awaited
71
- "@typescript-eslint/no-floating-promises": "off",
72
- "@typescript-eslint/no-unnecessary-type-assertion": "off",
73
- // Tests are naturally longer and more repetitive
74
- "max-lines-per-function": "off",
75
- "sonarjs/no-duplicate-string": "off",
76
- "sonarjs/no-identical-functions": "off",
77
- },
78
- },
79
- ];
@@ -1,54 +0,0 @@
1
- <!-- vigiles:sha256:f683550dbdfab721 compiled from examples/CLAUDE.md.spec.ts -->
2
-
3
- # CLAUDE.md
4
-
5
- ## Positioning
6
-
7
- 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.
8
-
9
- 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.
10
-
11
- `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.
12
-
13
- ## Architecture
14
-
15
- Three rule types in specs: `enforce()` (delegated to external tool), `check()` (vigiles-owned filesystem assertion), `guidance()` (prose only).
16
-
17
- 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).
18
-
19
- ## Key Files
20
-
21
- - `src/spec.ts` — Type system and builder functions
22
- - `src/compile.ts` — Compiler: spec → markdown with SHA-256 hash
23
- - `src/linters.ts` — Linter cross-referencing engine (6 linters)
24
- - `src/generate-types.ts` — Type generator: project state → .d.ts
25
- - `src/cli.ts` — CLI: compile, check, init, generate-types, discover, adopt
26
-
27
- ## Commands
28
-
29
- - `npm run build` — Compile TypeScript to dist/
30
- - `npm test` — Build and run all tests
31
- - `npm run fmt` — Format with prettier
32
- - `npm run fmt:check` — Check formatting
33
-
34
- ## Rules
35
-
36
- ### Zero Config By Default
37
-
38
- **Guidance only** — vigiles compile should work with just a .spec.ts file. Config exists only for overrides (maxRules, maxTokens, catalogOnly).
39
-
40
- ### Never Skip Tests
41
-
42
- **Guidance only** — All tests must pass. If a test requires a CLI tool (pylint, rubocop, ruff, clippy), install the tool, don't skip the test.
43
-
44
- ### Dont Reimplement Linters
45
-
46
- **Guidance only** — Architectural linting belongs in ast-grep/Dependency Cruiser/Steiger. Per-file code rules belong in ESLint/Ruff/Clippy. vigiles owns: compilation, linter cross-referencing, type generation, filesystem assertions, and stale reference detection.
47
-
48
- ### Format Before Commit
49
-
50
- **Guidance only** — Run `npm run fmt:check` before committing. Inline code spans in markdown need surrounding spaces to render correctly.
51
-
52
- ### No Session Links
53
-
54
- **Guidance only** — This is a public repo. Claude Code session URLs are private and must not appear in commits or PRs.
@@ -1,65 +0,0 @@
1
- /**
2
- * Example: CLAUDE.md specification for the vigiles project itself.
3
- *
4
- * This is the source of truth. CLAUDE.md is a compiled build artifact.
5
- * Run `vigiles compile` to generate 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.
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.
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
- architecture: `Three rule types in specs: \`enforce()\` (delegated to external tool), \`check()\` (vigiles-owned filesystem assertion), \`guidance()\` (prose only).
18
-
19
- 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).`,
20
- },
21
-
22
- keyFiles: {
23
- "src/spec.ts": "Type system and builder functions",
24
- "src/compile.ts": "Compiler: spec → markdown with SHA-256 hash",
25
- "src/linters.ts": "Linter cross-referencing engine (6 linters)",
26
- "src/generate-types.ts": "Type generator: project state → .d.ts",
27
- "src/cli.ts": "CLI: compile, check, init, generate-types, discover, adopt",
28
- },
29
-
30
- commands: {
31
- "npm run build": "Compile TypeScript to dist/",
32
- "npm test": "Build and run all tests",
33
- "npm run fmt": "Format with prettier",
34
- "npm run fmt:check": "Check formatting",
35
- },
36
-
37
- rules: {
38
- "zero-config-by-default": guidance(
39
- "vigiles compile should work with just a .spec.ts file. Config exists only for overrides (maxRules, maxTokens, catalogOnly).",
40
- ),
41
-
42
- "never-skip-tests": guidance(
43
- "All tests must pass. If a test requires a CLI tool (pylint, rubocop, ruff, clippy), install the tool, don't skip the test.",
44
- ),
45
-
46
- "dont-reimplement-linters": guidance(
47
- "Architectural linting belongs in ast-grep/Dependency Cruiser/Steiger. Per-file code rules belong in ESLint/Ruff/Clippy. vigiles owns: compilation, linter cross-referencing, type generation, filesystem assertions, and stale reference detection.",
48
- ),
49
-
50
- "format-before-commit": guidance(
51
- "Run `npm run fmt:check` before committing. Inline code spans in markdown need surrounding spaces to render correctly.",
52
- ),
53
-
54
- "no-session-links": guidance(
55
- "This is a public repo. Claude Code session URLs are private and must not appear in commits or PRs.",
56
- ),
57
-
58
- // Example: check() rule (commented out because this is a demo spec,
59
- // not the project's actual spec — see root CLAUDE.md.spec.ts)
60
- // "test-file-pairing": check(
61
- // every("src/**/!(*test|*spec).ts").has("{name}.test.ts"),
62
- // "Every source module should have a corresponding test file.",
63
- // ),
64
- },
65
- });
package/examples/SKILL.md DELETED
@@ -1,50 +0,0 @@
1
- <!-- vigiles:sha256:da271d5e41e8e90e compiled from examples/SKILL.md.spec.ts -->
2
-
3
- ---
4
-
5
- name: pr-to-lint-rule
6
- description: Convert a recurring PR review comment into an automated lint rule with tests and CLAUDE.md annotation
7
- disable-model-invocation: true
8
- argument-hint: <description of recurring PR feedback>
9
-
10
- ---
11
-
12
- Convert a recurring PR review comment into an automated lint rule.
13
-
14
- ## Arguments
15
-
16
- $ARGUMENTS — A natural language description of the pattern to enforce. Examples:
17
-
18
- - "we keep telling people not to import directly from antd, use our design system barrel file instead"
19
- - "people forget to use our custom logger instead of console.log"
20
- - "don't use unwrap() in production code, use expect() or proper error handling"
21
- - "API route handlers must use the withAuth wrapper"
22
-
23
- ## Instructions
24
-
25
- You are generating an automated lint rule from a recurring code review pattern. Follow these steps:
26
-
27
- ### Step 1: Detect the Project Language and Toolchain
28
-
29
- Look at the repository to determine:
30
-
31
- - **Primary language** (JS/TS, Python, Rust, Go, Ruby, etc.)
32
- - **Linter in use** (ESLint, Ruff, Clippy, golangci-lint, RuboCop, etc.)
33
- - **Testing framework** (Vitest, Jest, pytest, cargo test, etc.)
34
- - **Existing custom rules** (to match conventions)
35
-
36
- **If the language or linter cannot be confidently detected**, **ask the user** which language and linter to target before generating anything.
37
-
38
- ### Step 2: Generate the Lint Rule
39
-
40
- Based on the detected (or user-specified) language, generate the appropriate rule type.
41
-
42
- For JavaScript/TypeScript, generate an ESLint rule using the AST visitor pattern with `meta` and `create(context)`.
43
-
44
- ### Step 3: Update `CLAUDE.md`
45
-
46
- Add the annotation block. See [enforce-rules-format](skills/enforce-rules-format/SKILL.md) for the correct format.
47
-
48
- ### Step 4: Verify
49
-
50
- Run `npm test` to ensure the new rule and tests pass.
@@ -1,57 +0,0 @@
1
- /**
2
- * Example: SKILL.md specification for the pr-to-lint-rule skill.
3
- *
4
- * This is the source of truth. SKILL.md is a compiled build artifact.
5
- * Run `vigiles compile` to generate SKILL.md from this spec.
6
- */
7
- import { skill, file, cmd, ref, instructions } from "../src/spec.js";
8
-
9
- export default skill({
10
- name: "pr-to-lint-rule",
11
- description:
12
- "Convert a recurring PR review comment into an automated lint rule with tests and CLAUDE.md annotation",
13
- disableModelInvocation: true,
14
- argumentHint: "<description of recurring PR feedback>",
15
-
16
- body: instructions`
17
- Convert a recurring PR review comment into an automated lint rule.
18
-
19
- ## Arguments
20
-
21
- $ARGUMENTS — A natural language description of the pattern to enforce. Examples:
22
-
23
- - "we keep telling people not to import directly from antd, use our design system barrel file instead"
24
- - "people forget to use our custom logger instead of console.log"
25
- - "don't use unwrap() in production code, use expect() or proper error handling"
26
- - "API route handlers must use the withAuth wrapper"
27
-
28
- ## Instructions
29
-
30
- You are generating an automated lint rule from a recurring code review pattern. Follow these steps:
31
-
32
- ### Step 1: Detect the Project Language and Toolchain
33
-
34
- Look at the repository to determine:
35
-
36
- - **Primary language** (JS/TS, Python, Rust, Go, Ruby, etc.)
37
- - **Linter in use** (ESLint, Ruff, Clippy, golangci-lint, RuboCop, etc.)
38
- - **Testing framework** (Vitest, Jest, pytest, cargo test, etc.)
39
- - **Existing custom rules** (to match conventions)
40
-
41
- **If the language or linter cannot be confidently detected**, **ask the user** which language and linter to target before generating anything.
42
-
43
- ### Step 2: Generate the Lint Rule
44
-
45
- Based on the detected (or user-specified) language, generate the appropriate rule type.
46
-
47
- For JavaScript/TypeScript, generate an ESLint rule using the AST visitor pattern with \`meta\` and \`create(context)\`.
48
-
49
- ### Step 3: Update ${file("CLAUDE.md")}
50
-
51
- Add the annotation block. See ${ref("skills/enforce-rules-format/SKILL.md")} for the correct format.
52
-
53
- ### Step 4: Verify
54
-
55
- Run ${cmd("npm test")} to ensure the new rule and tests pass.
56
- `,
57
- });
@@ -1,11 +0,0 @@
1
- <!-- vigiles-disable require-spec -->
2
-
3
- # CLAUDE.md
4
-
5
- ## Code Style
6
-
7
- Use TypeScript strict mode. Never use `any`.
8
-
9
- ## Testing
10
-
11
- Run `npm test` before submitting. Every file in src/ should have tests.
@@ -1,9 +0,0 @@
1
- {
2
- "name": "example-project",
3
- "version": "1.0.0",
4
- "scripts": {
5
- "build": "echo build",
6
- "test": "echo test",
7
- "lint": "echo lint"
8
- }
9
- }
@@ -1,3 +0,0 @@
1
- export function greet(name: string): string {
2
- return `Hello, ${name}!`;
3
- }
@@ -1,2 +0,0 @@
1
- import { capitalize } from "./utils";
2
- console.assert(capitalize("hello") === "Hello");
@@ -1,3 +0,0 @@
1
- export function capitalize(s: string): string {
2
- return s.charAt(0).toUpperCase() + s.slice(1);
3
- }
package/logo.png DELETED
Binary file
@@ -1,111 +0,0 @@
1
- # vigiles Adoption Strategy
2
-
3
- Goal: **`npx vigiles setup && npx skills add zernie/vigiles` works on first run with zero config. The agent starts editing specs automatically — no workflow change required. Start permissive, tighten over time.**
4
-
5
- ### Adoption Principles
6
-
7
- 1. **Works on first run.** Setup must succeed in any project without configuration. Auto-detect everything. Create reasonable defaults. Don't block on missing tools.
8
- 2. **Zero workflow change.** After plugin install, the agent edits specs instead of markdown. The user doesn't need to learn a new workflow — they say "update CLAUDE.md" and the plugin handles the redirect.
9
- 3. **Start permissive, tighten later.** First run creates `guidance()` rules (no enforcement). User upgrades to `enforce()` as they add linter rules. `require-spec: false` available for incremental migration.
10
- 4. **Every surface tells you the next step.** `vigiles check` says "run setup." The hook says "edit the spec." The wizard says "install the plugin." No dead ends.
11
-
12
- ---
13
-
14
- ## Scope: What vigiles Does vs. Doesn't
15
-
16
- vigiles compiles typed TypeScript specs to **markdown instruction files** (CLAUDE.md, AGENTS.md). It verifies linter rules, file paths, and commands at compile time. The compiled markdown is the artifact.
17
-
18
- **vigiles handles:** CLAUDE.md (Claude Code), AGENTS.md (Codex, GitHub Copilot, any agent that reads AGENTS.md). These are both plain markdown — same compiler, same validation, different `target`.
19
-
20
- **vigiles does NOT handle:** `.cursorrules`, `.copilot-instructions.md`, Windsurf format, or any non-markdown target. These have different structures. Use [rule-porter](https://github.com/nichochar/rule-porter) or [rulesync](https://github.com/dyoshikawa/rulesync) to convert compiled markdown to those formats. vigiles is the source; sync tools are the distribution layer.
21
-
22
- **No symlinks needed.** AGENTS.md is a first-class target via `target: "AGENTS.md"` or `target: ["CLAUDE.md", "AGENTS.md"]`. The compiler outputs both from one spec.
23
-
24
- ---
25
-
26
- ## The Setup Wizard
27
-
28
- `npx vigiles setup` is the single entry point. It does everything:
29
-
30
- 1. **Creates spec** — scaffolds `CLAUDE.md.spec.ts` (or `--target=AGENTS.md` variant)
31
- 2. **Generates types** — scans linters, package.json, project files → `.vigiles/generated.d.ts`
32
- 3. **Compiles** — spec → markdown with SHA-256 hash
33
- 4. **Adds CI step** — finds existing GHA workflow and appends `vigiles check` + `generate-types --check`
34
- 5. **Prompts plugin install** — prints `npx skills add zernie/vigiles` with explanation
35
-
36
- After setup, the user edits the spec, runs `vigiles compile`, and commits. The plugin handles everything else automatically.
37
-
38
- ---
39
-
40
- ## Adoption Levels
41
-
42
- ### Level 0: Discovery
43
-
44
- User runs `npx vigiles check` on an existing repo. `require-spec` fires: "No spec file found. Run `npx vigiles setup`." First nudge.
45
-
46
- ### Level 1: Setup
47
-
48
- ```bash
49
- npx vigiles setup
50
- ```
51
-
52
- One command. Creates spec, types, compiled markdown, CI step. The user has a working pipeline in under a minute.
53
-
54
- ### Level 2: Plugin
55
-
56
- ```bash
57
- npx skills add zernie/vigiles
58
- ```
59
-
60
- Two hooks activate:
61
-
62
- - **PreToolUse**: Blocks direct edits to compiled `.md` files. Agent gets redirected to `.spec.ts`.
63
- - **PostToolUse**: Auto-runs `generate-types` on config changes, `compile` on spec changes.
64
-
65
- ### Level 3: Multi-Target
66
-
67
- ```typescript
68
- export default claude({
69
- target: ["CLAUDE.md", "AGENTS.md"],
70
- rules: { ... },
71
- });
72
- ```
73
-
74
- One spec, multiple outputs. For non-markdown formats, pipe through rule-porter.
75
-
76
- ### Level 4: Type Narrowing
77
-
78
- Commit `.vigiles/generated.d.ts`. Now `enforce("eslint/no-consolee")` is a type error in the editor. Types narrow `enforce()`, `file()`, `cmd()` via declaration merging.
79
-
80
- ---
81
-
82
- ## Pain Points (Updated)
83
-
84
- | Pain Point | Status | Resolution |
85
- | --------------------------------- | --------- | ----------------------------------------------- |
86
- | Multi-step installation | Fixed | `vigiles setup` does everything |
87
- | No CI integration from wizard | Fixed | Wizard auto-adds GHA step |
88
- | Plugin not mentioned as important | Fixed | README and wizard both prompt it |
89
- | Agent edits compiled .md directly | Fixed | PreToolUse hook blocks with redirect |
90
- | Cursor/Windsurf support | Won't fix | Out of scope — use sync tools |
91
- | Codex / AGENTS.md | Fixed | First-class target |
92
- | No interactive mode for agents | Open | `vigiles setup` works non-interactively already |
93
-
94
- ## README Structure
95
-
96
- The README should have:
97
-
98
- 1. **Hook** — one compelling sentence
99
- 2. **Problem** — realistic example of rot
100
- 3. **Fix** — the spec that catches it
101
- 4. **Quick Start** — `npx vigiles setup` (one command)
102
- 5. **Three Rule Types** — enforce/check/guidance
103
- 6. **Verified References** — file/cmd/ref
104
- 7. **Type-Safe Rule References** — generate-types + narrowing
105
- 8. **CLI** — reference for all commands
106
- 9. **GitHub Action** — CI snippet
107
- 10. **Plugin** — what it does, install command
108
- 11. **Output Targets** — CLAUDE.md, AGENTS.md, multi-target
109
- 12. **Related Tools** — sync tools for non-markdown formats
110
-
111
- No separate installation steps. The wizard IS the installation.