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
package/src/validate.ts DELETED
@@ -1,381 +0,0 @@
1
- import { readFileSync, lstatSync, existsSync } from "node:fs";
2
- import { globSync } from "glob";
3
- import { resolve, basename as pathBasename } from "node:path";
4
- import { cosmiconfigSync } from "cosmiconfig";
5
-
6
- import { hasInlineRules } from "./inline.js";
7
-
8
- import type {
9
- ParsedRule,
10
- ValidationError,
11
- ValidationResult,
12
- ReadResult,
13
- FileResult,
14
- ValidatePathsResult,
15
- RulesConfig,
16
- VigilesConfig,
17
- MarkerType,
18
- ParseOptions,
19
- ValidateOptions,
20
- ValidatePathsOptions,
21
- ReadOptions,
22
- } from "./types.js";
23
-
24
- // Re-export all types for consumers
25
- export type {
26
- ParsedRule,
27
- ValidationError,
28
- ValidationResult,
29
- ReadResult,
30
- FileResult,
31
- ValidatePathsResult,
32
- RulesConfig,
33
- VigilesConfig,
34
- MarkerType,
35
- ParseOptions,
36
- ValidateOptions,
37
- ValidatePathsOptions,
38
- ReadOptions,
39
- };
40
-
41
- // ---------------------------------------------------------------------------
42
- // Constants & regex
43
- // ---------------------------------------------------------------------------
44
-
45
- const GUIDANCE_RE = /\*\*Guidance only\*\*/;
46
- const DISABLE_RE = /<!--\s*vigiles-disable\s*-->/;
47
- const RULE_HEADER_RE = /^###\s+(.+)$/;
48
- const CHECKBOX_RE = /^- \[([ xX])\]\s+(.+)$/;
49
-
50
- const VALID_MARKERS: readonly MarkerType[] = ["headings", "checkboxes"];
51
-
52
- // ---------------------------------------------------------------------------
53
- // Default config
54
- // ---------------------------------------------------------------------------
55
-
56
- const DEFAULT_FILES: string[] = ["CLAUDE.md"];
57
-
58
- const DEFAULT_RULES: Required<RulesConfig> = {
59
- "require-spec": "warn",
60
- "require-skill-spec": "warn",
61
- freshness: "warn",
62
- };
63
-
64
- const DEFAULT_CONFIG: VigilesConfig = {
65
- ruleMarkers: ["headings", "checkboxes"],
66
- rules: DEFAULT_RULES,
67
- files: DEFAULT_FILES,
68
- };
69
-
70
- // ---------------------------------------------------------------------------
71
- // Instruction file discovery
72
- // ---------------------------------------------------------------------------
73
-
74
- export function findInstructionFiles(
75
- cwd: string = process.cwd(),
76
- configFiles?: string[],
77
- ): string[] {
78
- const candidates = configFiles ?? DEFAULT_FILES;
79
- return candidates.filter((f) => existsSync(resolve(cwd, f)));
80
- }
81
-
82
- // ---------------------------------------------------------------------------
83
- // Config loading
84
- // ---------------------------------------------------------------------------
85
-
86
- export function loadConfig(): VigilesConfig {
87
- try {
88
- const explorer = cosmiconfigSync("vigiles", {
89
- searchPlaces: [".vigilesrc.json"],
90
- mergeSearchPlaces: false,
91
- });
92
- const result = explorer.search();
93
- if (!result?.config) return { ...DEFAULT_CONFIG };
94
-
95
- const userConfig = result.config as Partial<VigilesConfig> & {
96
- rules?: Partial<RulesConfig>;
97
- };
98
-
99
- const config: VigilesConfig = {
100
- ...DEFAULT_CONFIG,
101
- ...userConfig,
102
- rules: { ...DEFAULT_RULES, ...userConfig.rules },
103
- files: Array.isArray(userConfig.files) ? userConfig.files : DEFAULT_FILES,
104
- };
105
-
106
- if (
107
- !Array.isArray(config.ruleMarkers) ||
108
- !config.ruleMarkers.every((m): m is MarkerType =>
109
- (VALID_MARKERS as readonly string[]).includes(m),
110
- )
111
- ) {
112
- console.warn(
113
- `Invalid ruleMarkers in config: ${JSON.stringify(config.ruleMarkers)}. Using default.`,
114
- );
115
- config.ruleMarkers = [...DEFAULT_CONFIG.ruleMarkers];
116
- }
117
-
118
- return config;
119
- } catch {
120
- return { ...DEFAULT_CONFIG };
121
- }
122
- }
123
-
124
- // ---------------------------------------------------------------------------
125
- // Parsing
126
- // ---------------------------------------------------------------------------
127
-
128
- export function parseRules(
129
- content: string,
130
- { ruleMarkers }: ParseOptions = {},
131
- ): ParsedRule[] {
132
- const markers = ruleMarkers ?? DEFAULT_CONFIG.ruleMarkers;
133
- const lines = content.split("\n");
134
- const rules: ParsedRule[] = [];
135
-
136
- let currentRule: ParsedRule | null = null;
137
-
138
- for (let i = 0; i < lines.length; i++) {
139
- const line = lines[i];
140
- const headerMatch = markers.includes("headings")
141
- ? line.match(RULE_HEADER_RE)
142
- : null;
143
- const checkboxMatch = markers.includes("checkboxes")
144
- ? line.match(CHECKBOX_RE)
145
- : null;
146
-
147
- if (headerMatch ?? checkboxMatch) {
148
- if (currentRule) {
149
- rules.push(currentRule);
150
- }
151
- const title = headerMatch
152
- ? headerMatch[1].trim()
153
- : (checkboxMatch as RegExpMatchArray)[2].trim();
154
- currentRule = {
155
- title,
156
- line: i + 1,
157
- enforcement: "missing",
158
- enforcedBy: null,
159
- };
160
- continue;
161
- }
162
-
163
- if (!currentRule || currentRule.enforcement !== "missing") continue;
164
-
165
- const enforcedMatch = line.match(/\*\*Enforced by:\*\*\s*`([^`]+)`/);
166
- if (enforcedMatch) {
167
- currentRule.enforcement = "enforced";
168
- currentRule.enforcedBy = enforcedMatch[1] ?? null;
169
- continue;
170
- }
171
-
172
- if (GUIDANCE_RE.test(line)) {
173
- currentRule.enforcement = "guidance";
174
- continue;
175
- }
176
-
177
- if (DISABLE_RE.test(line)) {
178
- currentRule.enforcement = "disabled";
179
- continue;
180
- }
181
- }
182
-
183
- if (currentRule) {
184
- rules.push(currentRule);
185
- }
186
-
187
- return rules;
188
- }
189
-
190
- // ---------------------------------------------------------------------------
191
- // Core validation
192
- // ---------------------------------------------------------------------------
193
-
194
- export function validate(
195
- content: string,
196
- { ruleMarkers, rules: rulesConfig, filePath }: ValidateOptions = {},
197
- ): ValidationResult {
198
- const activeRules = rulesConfig ?? DEFAULT_RULES;
199
- const parsedRules = parseRules(content, { ruleMarkers });
200
- const enforced = parsedRules.filter(
201
- (r) => r.enforcement === "enforced",
202
- ).length;
203
- const guidanceOnly = parsedRules.filter(
204
- (r) => r.enforcement === "guidance",
205
- ).length;
206
- const disabled = parsedRules.filter(
207
- (r) => r.enforcement === "disabled",
208
- ).length;
209
- const missingCount = parsedRules.filter(
210
- (r) => r.enforcement === "missing",
211
- ).length;
212
-
213
- const errors: ValidationError[] = [];
214
- const warnings: ValidationError[] = [];
215
- const disableComment = /<!--\s*vigiles-disable\s+require-spec\s*-->/;
216
-
217
- if (filePath) {
218
- const basename = pathBasename(filePath);
219
- const isInstruction = basename === "CLAUDE.md" || basename === "AGENTS.md";
220
- const isSkill = basename === "SKILL.md";
221
-
222
- // --- require-spec (CLAUDE.md / AGENTS.md) ---
223
- const specSeverity = activeRules["require-spec"];
224
- if (specSeverity && isInstruction && !disableComment.test(content)) {
225
- const specPath = filePath + ".spec.ts";
226
- // Inline mode counts as a spec — any parseable
227
- // `<!-- vigiles:enforce ... -->` comment means the file is
228
- // verified on `vigiles audit` even without a .spec.ts sibling.
229
- // Delegate to the real parser so a malformed marker can't
230
- // satisfy require-spec with a rule that audit can't verify.
231
- const hasInline = hasInlineRules(content);
232
- if (!existsSync(specPath) && !hasInline) {
233
- const msg: ValidationError = {
234
- rule: "require-spec",
235
- message: `No spec file found for "${filePath}". Expected "${specPath}". Run \`npx vigiles init --target=${filePath}\` to create one, add inline \`<!-- vigiles:enforce ... -->\` comments, or disable with <!-- vigiles-disable require-spec -->.`,
236
- line: 1,
237
- };
238
- if (specSeverity === "error") {
239
- errors.push(msg);
240
- } else {
241
- warnings.push(msg);
242
- }
243
- }
244
- }
245
-
246
- // --- require-skill-spec (SKILL.md) ---
247
- const skillSeverity = activeRules["require-skill-spec"];
248
- if (skillSeverity && isSkill && !disableComment.test(content)) {
249
- const specPath = filePath + ".spec.ts";
250
- if (!existsSync(specPath)) {
251
- const msg: ValidationError = {
252
- rule: "require-skill-spec",
253
- message: `No spec file found for "${filePath}". Expected "${specPath}".`,
254
- line: 1,
255
- };
256
- if (skillSeverity === "error") {
257
- errors.push(msg);
258
- } else {
259
- warnings.push(msg);
260
- }
261
- }
262
- }
263
- }
264
-
265
- return {
266
- rules: parsedRules,
267
- enforced,
268
- guidanceOnly,
269
- disabled,
270
- missing: missingCount,
271
- total: parsedRules.length,
272
- errors,
273
- warnings,
274
- valid: errors.length === 0,
275
- };
276
- }
277
-
278
- // ---------------------------------------------------------------------------
279
- // File reading
280
- // ---------------------------------------------------------------------------
281
-
282
- export function readInstructionFile(
283
- filePath: string,
284
- options: ReadOptions = {},
285
- ): ReadResult {
286
- try {
287
- const stat = lstatSync(filePath);
288
- if (stat.isSymbolicLink() && !options.followSymlinks) {
289
- return {
290
- content: null,
291
- skipped: true,
292
- reason: `${filePath} is a symlink (use --follow-symlinks to include)`,
293
- };
294
- }
295
- } catch {
296
- return {
297
- content: null,
298
- skipped: false,
299
- reason: `File not found: ${filePath}`,
300
- };
301
- }
302
-
303
- try {
304
- return {
305
- content: readFileSync(filePath, "utf-8"),
306
- skipped: false,
307
- reason: null,
308
- };
309
- } catch {
310
- return {
311
- content: null,
312
- skipped: false,
313
- reason: `Could not read: ${filePath}`,
314
- };
315
- }
316
- }
317
-
318
- // ---------------------------------------------------------------------------
319
- // Glob expansion
320
- // ---------------------------------------------------------------------------
321
-
322
- export function expandGlobs(patterns: string[]): string[] {
323
- const GLOB_CHARS = /[*?{[]/;
324
- const paths: string[] = [];
325
-
326
- for (const pattern of patterns) {
327
- if (GLOB_CHARS.test(pattern)) {
328
- const matches = globSync(pattern, { cwd: process.cwd() });
329
- for (const match of matches.sort()) {
330
- paths.push(resolve(match));
331
- }
332
- } else {
333
- paths.push(pattern);
334
- }
335
- }
336
-
337
- return paths;
338
- }
339
-
340
- // ---------------------------------------------------------------------------
341
- // Multi-file validation
342
- // ---------------------------------------------------------------------------
343
-
344
- export function validatePaths(
345
- paths: string[],
346
- {
347
- followSymlinks = false,
348
- ruleMarkers,
349
- rules: rulesConfig,
350
- }: ValidatePathsOptions = {},
351
- ): ValidatePathsResult {
352
- const fileResults: FileResult[] = [];
353
- let allValid = true;
354
-
355
- for (const filePath of paths) {
356
- const { content, skipped, reason } = readInstructionFile(filePath, {
357
- followSymlinks,
358
- });
359
-
360
- if (skipped || content === null) {
361
- fileResults.push({
362
- path: filePath,
363
- skipped,
364
- reason,
365
- result: null,
366
- });
367
- if (!skipped) allValid = false;
368
- continue;
369
- }
370
-
371
- const result = validate(content, {
372
- ruleMarkers,
373
- rules: rulesConfig,
374
- filePath,
375
- });
376
- fileResults.push({ path: filePath, skipped: false, reason: null, result });
377
- if (!result.valid) allValid = false;
378
- }
379
-
380
- return { fileResults, valid: allValid };
381
- }
package/tsconfig.json DELETED
@@ -1,23 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "Node16",
5
- "moduleResolution": "Node16",
6
- "outDir": "dist",
7
- "rootDir": "src",
8
- "declaration": true,
9
- "declarationMap": true,
10
- "sourceMap": true,
11
- "strict": true,
12
- "noUncheckedIndexedAccess": false,
13
- "noUnusedLocals": true,
14
- "noUnusedParameters": true,
15
- "exactOptionalPropertyTypes": false,
16
- "forceConsistentCasingInFileNames": true,
17
- "skipLibCheck": true,
18
- "esModuleInterop": true,
19
- "resolveJsonModule": true
20
- },
21
- "include": ["src/**/*.ts"],
22
- "exclude": ["node_modules", "dist"]
23
- }