vigiles 29.1.0 → 30.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.
Files changed (106) hide show
  1. package/dist/adapter-conformance.d.ts +1 -1
  2. package/dist/adapter-conformance.js +106 -25
  3. package/dist/adapter-registry.d.ts +61 -14
  4. package/dist/adapter-registry.js +78 -10
  5. package/dist/adapter.d.ts +23 -2
  6. package/dist/adapter.js +13 -1
  7. package/dist/adapters/claude-code/adapter.d.ts +32 -2
  8. package/dist/adapters/claude-code/adapter.js +44 -23
  9. package/dist/adapters/claude-code/dialect.js +87 -21
  10. package/dist/adapters/claude-code/hook-protocol.js +16 -0
  11. package/dist/adapters/claude-code/instruction-chain.d.ts +25 -0
  12. package/dist/adapters/claude-code/instruction-chain.js +626 -0
  13. package/dist/adapters/claude-code/layout.d.ts +2 -2
  14. package/dist/adapters/claude-code/layout.js +42 -8
  15. package/dist/adapters/claude-code/model-access.d.ts +41 -0
  16. package/dist/adapters/claude-code/model-access.js +46 -0
  17. package/dist/adapters/claude-code/skill-reachability.d.ts +125 -0
  18. package/dist/adapters/claude-code/skill-reachability.js +111 -0
  19. package/dist/adapters/codex/adapter.d.ts +39 -2
  20. package/dist/adapters/codex/adapter.js +29 -29
  21. package/dist/adapters/codex/dialect.js +11 -6
  22. package/dist/adapters/codex/eval.d.ts +10 -0
  23. package/dist/adapters/codex/eval.js +48 -1
  24. package/dist/adapters/codex/hook-protocol.d.ts +2 -1
  25. package/dist/adapters/codex/hook-protocol.js +10 -0
  26. package/dist/adapters/codex/instruction-chain.d.ts +40 -0
  27. package/dist/adapters/codex/instruction-chain.js +105 -0
  28. package/dist/adapters/codex/layout.d.ts +1 -1
  29. package/dist/adapters/codex/layout.js +41 -14
  30. package/dist/adapters/opencode/adapter.d.ts +33 -2
  31. package/dist/adapters/opencode/adapter.js +36 -36
  32. package/dist/adapters/opencode/dialect.js +2 -2
  33. package/dist/adapters/opencode/instruction-chain.d.ts +37 -0
  34. package/dist/adapters/opencode/instruction-chain.js +70 -0
  35. package/dist/adapters/opencode/layout.d.ts +19 -0
  36. package/dist/adapters/opencode/layout.js +34 -15
  37. package/dist/adoptability.d.ts +31 -1
  38. package/dist/adoptability.js +57 -0
  39. package/dist/cli-main.js +180 -102
  40. package/dist/core/adapter.d.ts +213 -61
  41. package/dist/core/compile.d.ts +2 -2
  42. package/dist/core/compile.js +57 -46
  43. package/dist/core/compose.d.ts +5 -3
  44. package/dist/core/compose.js +5 -3
  45. package/dist/core/config-schema.d.ts +14 -2
  46. package/dist/core/config-schema.js +20 -7
  47. package/dist/core/dialect.d.ts +54 -12
  48. package/dist/core/dialect.js +56 -0
  49. package/dist/core/eval-driver.d.ts +194 -0
  50. package/dist/core/eval-driver.js +3 -0
  51. package/dist/core/frontmatter-read.d.ts +10 -0
  52. package/dist/core/frontmatter-read.js +30 -3
  53. package/dist/core/hook-program.d.ts +27 -2
  54. package/dist/core/hook-program.js +29 -24
  55. package/dist/core/hook-protocol.d.ts +54 -0
  56. package/dist/core/install-reader.d.ts +18 -0
  57. package/dist/core/install-reader.js +88 -0
  58. package/dist/core/instruction-chain.d.ts +444 -0
  59. package/dist/core/instruction-chain.js +292 -0
  60. package/dist/core/instruction-weight.d.ts +96 -14
  61. package/dist/core/instruction-weight.js +65 -30
  62. package/dist/core/layout.d.ts +220 -33
  63. package/dist/core/layout.js +115 -1
  64. package/dist/core/lethal-trifecta.d.ts +12 -7
  65. package/dist/core/lethal-trifecta.js +13 -13
  66. package/dist/core/live-driver.d.ts +137 -0
  67. package/dist/core/live-driver.js +14 -0
  68. package/dist/core/markdown.d.ts +23 -0
  69. package/dist/core/markdown.js +77 -28
  70. package/dist/core/orphans.js +9 -7
  71. package/dist/core/settings-codec.d.ts +17 -0
  72. package/dist/core/settings-codec.js +56 -0
  73. package/dist/core/surface-discovery.d.ts +2 -2
  74. package/dist/core/surface-discovery.js +24 -12
  75. package/dist/core/surface-scopes.d.ts +26 -6
  76. package/dist/core/surface-scopes.js +52 -11
  77. package/dist/core/validate.js +16 -3
  78. package/dist/eval.d.ts +16 -108
  79. package/dist/eval.js +34 -1
  80. package/dist/harness-test.d.ts +3 -63
  81. package/dist/hook-install.d.ts +12 -1
  82. package/dist/hook-install.js +12 -1
  83. package/dist/plugin-loader.d.ts +1 -1
  84. package/dist/plugin-loader.js +43 -36
  85. package/dist/scan-behavioral.d.ts +34 -25
  86. package/dist/scan-behavioral.js +122 -58
  87. package/dist/scan-core.js +37 -18
  88. package/dist/scan-files.d.ts +1 -1
  89. package/dist/scan-files.js +53 -33
  90. package/dist/scan-trigger-suggest.d.ts +0 -21
  91. package/dist/scan-trigger-suggest.js +0 -23
  92. package/dist/scan.d.ts +4 -4
  93. package/dist/scan.js +120 -84
  94. package/dist/skill-harness.d.ts +21 -5
  95. package/dist/skill-harness.js +29 -11
  96. package/dist/surface-discovery-fs.d.ts +2 -0
  97. package/dist/surface-discovery-fs.js +108 -6
  98. package/dist/test-coverage-files.js +24 -17
  99. package/dist/test-coverage.d.ts +9 -3
  100. package/dist/test-coverage.js +32 -22
  101. package/dist/verify-plugin-guards.js +1 -1
  102. package/package.json +1 -1
  103. package/dist/skill-reachability.d.ts +0 -68
  104. package/dist/skill-reachability.js +0 -205
  105. /package/dist/{dialect-drift.d.ts → adapters/claude-code/dialect-drift.d.ts} +0 -0
  106. /package/dist/{dialect-drift.js → adapters/claude-code/dialect-drift.js} +0 -0
@@ -69,22 +69,24 @@ exports.claudeCodeDialect = {
69
69
  // budget here costs money and attention — not rules. (Codex is the opposite;
70
70
  // see its dialect, and see why `onExceed` is reported at all.)
71
71
  //
72
- // 🔴 `alwaysLoaded` IS THE POINT, and `.claude/rules/**` is in it on a
73
- // MEASUREMENT, not a doc: a consumer repo moved 225 837 characters out of
74
- // CLAUDE.md into that directory and the request cost did not move, because
75
- // the harness loads it either way. A per-file check would have called that
76
- // split a success.
72
+ // 🔴 WHICH FILES THE SUM IS TAKEN OVER IS NO LONGER A FIELD HERE. It was
73
+ // `alwaysLoaded: ["CLAUDE.md", "CLAUDE.local.md", ".claude/CLAUDE.md",
74
+ // ".claude/rules/**"]` — globs this dialect wrote and the CORE expanded by
75
+ // walking the repository, which is the defect zernie/vigiles#262 records.
76
+ // The set now comes from `claudeCodeLayout.instructionChain`, which can say
77
+ // what a glob cannot: that a `paths:`-scoped rule loads on demand, and that
78
+ // `CLAUDE.local.md` is a per-machine file that is read and never SCORED.
79
+ //
80
+ // What stays here is the harness's own NUMBER, which is a format fact: the
81
+ // rules directory counts on a MEASUREMENT, not a doc — a consumer repo moved
82
+ // 225 837 characters out of CLAUDE.md into it and the request cost did not
83
+ // move, because the harness loads it either way. A per-file check would have
84
+ // called that split a success.
77
85
  instructionBudget: {
78
86
  unit: "chars",
79
87
  limit: 40000,
80
88
  onExceed: "warns",
81
- capturedFrom: "claude-code /doctor large-file warning; .claude/rules/** measured 2026-09-16 in a consumer repo",
82
- alwaysLoaded: [
83
- "CLAUDE.md",
84
- "CLAUDE.local.md",
85
- ".claude/CLAUDE.md",
86
- ".claude/rules/**",
87
- ],
89
+ capturedFrom: "claude-code /doctor large-file warning; the rules dir measured 2026-09-16 in a consumer repo",
88
90
  },
89
91
  // The capability table — what each event CARRIES and HONOURS. Nine of the 31
90
92
  // events, each with its basis; see ./event-capability.ts. The three flat lists
@@ -95,16 +97,80 @@ exports.claudeCodeDialect = {
95
97
  // `hookSpecificOutput.permissionDecision:"deny"`; the legacy top-level
96
98
  // `decision` field is ignored there.
97
99
  permissionDecisionHookEvents: ["PreToolUse"],
98
- // Claude Code natively reads CLAUDE.md only — it does NOT auto-load AGENTS.md
99
- // (anthropics/claude-code#34235 is open; AGENTS.md works solely via an
100
- // `@AGENTS.md` import inside CLAUDE.md or a symlink). AGENTS.md is the
101
- // cross-tool standard (Codex's native target), not a CC dialect fact; vigiles's
102
- // tool-agnostic recognition of it lives in validate.ts's INSTRUCTION_FILES.
103
- instructionTargets: ["CLAUDE.md"],
100
+ // 🔴 THIS LIST GAINED `AGENTS.md` ON 2026-09-21, REVERSING WHAT STOOD HERE.
101
+ // The comment it replaces read "Claude Code natively reads CLAUDE.md only — it
102
+ // does NOT auto-load AGENTS.md (anthropics/claude-code#34235 is open; AGENTS.md
103
+ // works solely via an `@AGENTS.md` import inside CLAUDE.md or a symlink)".
104
+ // That is no longer true. Vendor, `https://code.claude.com/docs/en/memory`,
105
+ // read 2026-09-21:
106
+ //
107
+ // "Claude Code can read `AGENTS.md` as your project instructions, so a
108
+ // repository already set up for other coding agents works without adding a
109
+ // `CLAUDE.md`, an import, or a setting."
110
+ //
111
+ // "Reading `AGENTS.md` directly requires Claude Code v2.1.277 or later."
112
+ //
113
+ // The conditions under which it actually loads are NOT a dialect fact and are
114
+ // not restated here — they depend on sibling files and on settings, which is
115
+ // exactly why they live in `./instruction-chain.ts` as a method. This field
116
+ // answers the narrower question its docblock asks: which filenames does this
117
+ // harness READ as project instructions.
118
+ //
119
+ // 🔴 WHAT CHANGED WHEN `AGENTS.md` WAS ADDED — MEASURED, NOT EXPECTED, AND THE
120
+ // EXPECTED ANSWER WAS WRONG. The obvious worry is `detect`: a second target
121
+ // ought to make this adapter score a bare `AGENTS.md` repository and start
122
+ // fighting Codex for it. It does not, and cannot, because `detect` never reads
123
+ // this field — it asks the LAYOUT (`claudeCodeLayout.instructionFile`).
124
+ // Recorded by instrumenting `adapter.detect` with a call-recording predicate,
125
+ // before and after the edit:
126
+ //
127
+ // detect asked: [".claude-plugin/plugin.json", ".claude/settings.json",
128
+ // "CLAUDE.md"] — IDENTICAL both ways
129
+ // claims("AGENTS.md"): false — IDENTICAL both ways
130
+ //
131
+ // That separation is load-bearing rather than incidental: `claims` is derived
132
+ // from `layoutLocations`, and `adapter-properties.test.ts` refuses a `detect`
133
+ // that asks about a path `claims` does not cover. So a Claude Code adapter
134
+ // that detected on `AGENTS.md` would have to CLAIM it, and two registered
135
+ // adapters claiming one path is the collision `claims` exists to prevent. The
136
+ // file stays owned by Codex and merely READ here — which is the same reason
137
+ // `instruction-chain.ts` keeps `AGENTS.md` as a local constant instead of
138
+ // putting it on `PluginLayout`.
139
+ //
140
+ // THE ONE CONSUMER THAT DID CHANGE is `core/validate.ts:300`
141
+ // (`recognized = dialect?.instructionTargets ?? INSTRUCTION_FILES`), and the
142
+ // change fixes a real inconsistency. Measured on an `AGENTS.md` path:
143
+ //
144
+ // before — with the CC dialect injected: []
145
+ // before — with NO dialect: ["require-instructions-spec"]
146
+ // after — either way: ["require-instructions-spec"]
147
+ //
148
+ // i.e. injecting this dialect used to make vigiles recognise FEWER instruction
149
+ // files than its own no-dialect default, so an `AGENTS.md` that Claude Code
150
+ // really does read was linted as if it were an ordinary markdown file. Full
151
+ // unit suite with this edit alone: 4 failed / 4185 passed — the same four
152
+ // `spec.test.ts` pylint/rubocop CLI tests that fail on this branch regardless.
153
+ //
154
+ // ORDER IS PART OF THE CONTRACT: `instructionTargets[0]` is the default
155
+ // COMPILE target (`core/compile.ts:792`), and what `vigiles init` writes for
156
+ // Claude Code is still `CLAUDE.md`. `AGENTS.md` is second because this harness
157
+ // reads it, not because it authors it. `docs/adapter-api.md` already documented
158
+ // `["CLAUDE.md","AGENTS.md"]` for this adapter; the code now agrees with it.
159
+ instructionTargets: ["CLAUDE.md", "AGENTS.md"],
104
160
  pluginRootToken: "${CLAUDE_PLUGIN_ROOT}",
105
- // Claude Code reads the full SKILL.md frontmatter set (description,
106
- // disable-model-invocation, argument-hint, …).
107
- skillFrontmatter: "claude-code",
161
+ // Claude Code reads the full SKILL.md frontmatter set. Spelled out rather than
162
+ // aliased to the compiler's RENDERABLE_SKILL_FRONTMATTER_KEYS: that constant is
163
+ // "what vigiles can write", this list is "what Claude Code reads", and a new
164
+ // renderable key must not silently become a claim about the vendor.
165
+ skillFrontmatterKeys: [
166
+ "name",
167
+ "description",
168
+ "disable-model-invocation",
169
+ "context",
170
+ "argument-hint",
171
+ "allowed-tools",
172
+ "disallowed-tools",
173
+ ],
108
174
  // Tools that produce side effects in Claude Code. The complement — the
109
175
  // read-only tools — are: Read, Grep, Glob, ToolSearch, LSP, ListAgents,
110
176
  // TaskGet, TaskList, CronList. Bash (and PowerShell) are side-effecting
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.claudeCodeHookProtocol = void 0;
4
4
  const hook_condition_js_1 = require("./hook-condition.js");
5
+ const hook_install_js_1 = require("../../hook-install.js");
5
6
  exports.claudeCodeHookProtocol = {
6
7
  name: "claude-code",
7
8
  blockExitCode: 2,
@@ -41,5 +42,20 @@ exports.claudeCodeHookProtocol = {
41
42
  // at all. See ./hook-condition.ts — without it a conditional guard was reported
42
43
  // as blocking every disaster in the battery.
43
44
  condition: hook_condition_js_1.claudeCodeHookCondition,
45
+ // Claude Code NESTS: one matcher block holds a list of commands.
46
+ registration(on, matcher, command) {
47
+ const entry = matcher === undefined
48
+ ? { hooks: [{ type: "command", command }] }
49
+ : { matcher, hooks: [{ type: "command", command }] };
50
+ return { hooks: { [on]: [entry] } };
51
+ },
52
+ // Delegates to the JSON merge, which is where the measured behaviour and its
53
+ // test suite live (`hook-install.ts` / `hook-install.test.ts`). The port owns
54
+ // WHICH merge; the module owns HOW. The cast is the structural-to-concrete
55
+ // step the core cannot take: `CompiledHooks` is the application layer's type,
56
+ // and a core port may not name it.
57
+ mergeRegistrations(existing, compiled, managedBy) {
58
+ return (0, hook_install_js_1.mergeHooksJson)(existing, compiled, managedBy);
59
+ },
44
60
  };
45
61
  //# sourceMappingURL=hook-protocol.js.map
@@ -0,0 +1,25 @@
1
+ import type { InstructionChain, SettingsSource } from "../../core/instruction-chain.js";
2
+ /** Inputs the layout supplies so this module names no path of its own. */
3
+ export interface ClaudeCodeChainInput {
4
+ /** `CLAUDE.md`. */
5
+ readonly instructionFile: string;
6
+ /** `.claude`. */
7
+ readonly userSurfaceRoot: string;
8
+ /**
9
+ * The settings files, in precedence order (repo, then the local sibling),
10
+ * each with its SCOPE — a pattern out of the gitignored sibling may not
11
+ * change what a teammate on this commit is scored for.
12
+ */
13
+ readonly settingsSources: readonly SettingsSource[];
14
+ /** The layout's own codec — this module does not know the encoding. */
15
+ readonly parseSettings: (text: string) => Record<string, unknown>;
16
+ /** {@link RULE_FILE_LEAF_RE}, compiled against the rules dir. */
17
+ readonly ruleRe: RegExp;
18
+ }
19
+ /**
20
+ * `CLAUDE.md` → `CLAUDE.local.md`: the per-machine sibling, DERIVED so the two
21
+ * names cannot drift apart the way a second constant would.
22
+ */
23
+ export declare function localSiblingOf(instructionFile: string): string;
24
+ export declare function claudeCodeInstructionChain(files: Readonly<Record<string, string>>, input: ClaudeCodeChainInput): InstructionChain;
25
+ //# sourceMappingURL=instruction-chain.d.ts.map