vigiles 33.2.0 → 34.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/README.md +3 -2
- package/action.yml +45 -8
- package/dist/adapter.d.ts +1 -1
- package/dist/adapters/claude-code/runtime.js +70 -0
- package/dist/adapters/claude-code/skill-reachability.d.ts +42 -21
- package/dist/adapters/claude-code/skill-reachability.js +91 -28
- package/dist/cli-flag-check.js +1 -0
- package/dist/cli-main.js +401 -21
- package/dist/core/adapter.d.ts +7 -0
- package/dist/core/config-schema.d.ts +53 -34
- package/dist/core/config-schema.js +42 -0
- package/dist/core/install-reader.js +15 -0
- package/dist/core/layout.d.ts +10 -0
- package/dist/core/layout.js +17 -0
- package/dist/core/presets.d.ts +44 -0
- package/dist/core/presets.js +44 -0
- package/dist/core/run-env.d.ts +50 -0
- package/dist/core/run-env.js +51 -0
- package/dist/core/runtime.d.ts +44 -0
- package/dist/core/skill-link-target.d.ts +20 -0
- package/dist/core/skill-link-target.js +33 -0
- package/dist/core/validate.js +1 -1
- package/dist/eval.d.ts +39 -39
- package/dist/eval.js +62 -115
- package/dist/harness-test.d.ts +35 -0
- package/dist/harness-test.js +49 -7
- package/dist/output-style-arms.js +7 -2
- package/dist/plugin-declaration.d.ts +6 -6
- package/dist/plugin-declaration.js +6 -6
- package/dist/setup-plan.d.ts +142 -34
- package/dist/setup-plan.js +235 -135
- package/dist/skill-links.d.ts +183 -0
- package/dist/skill-links.js +255 -0
- package/dist/test-coverage.js +37 -1
- package/dist/vigilesrc.schema.json +6 -0
- package/package.json +1 -1
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
* boundary is deliberate: plugins "can execute arbitrary code on your machine
|
|
18
18
|
* with your user privileges", so a repo is not allowed to install one for you.
|
|
19
19
|
*
|
|
20
|
-
* The declaration buys exactly one thing
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
20
|
+
* The declaration buys exactly one thing: a collaborator who clones the repo is
|
|
21
|
+
* told the project wants this plugin, with the command that installs it.
|
|
22
|
+
* **Silent absence becomes a prompt.** It does not become a working install. What
|
|
23
|
+
* the plugin adds on their machine is the HOOKS; the SKILLS do not depend on it
|
|
24
|
+
* any more — `init` links them into `.claude/skills/` (`./skill-links.ts`), and
|
|
25
|
+
* the links travel with the clone.
|
|
26
26
|
*
|
|
27
27
|
* Nothing is vendored: what lands in the repo is a *reference* (a marketplace
|
|
28
28
|
* source plus an enabled flag). The plugin content still lives in the global
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
* boundary is deliberate: plugins "can execute arbitrary code on your machine
|
|
19
19
|
* with your user privileges", so a repo is not allowed to install one for you.
|
|
20
20
|
*
|
|
21
|
-
* The declaration buys exactly one thing
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
21
|
+
* The declaration buys exactly one thing: a collaborator who clones the repo is
|
|
22
|
+
* told the project wants this plugin, with the command that installs it.
|
|
23
|
+
* **Silent absence becomes a prompt.** It does not become a working install. What
|
|
24
|
+
* the plugin adds on their machine is the HOOKS; the SKILLS do not depend on it
|
|
25
|
+
* any more — `init` links them into `.claude/skills/` (`./skill-links.ts`), and
|
|
26
|
+
* the links travel with the clone.
|
|
27
27
|
*
|
|
28
28
|
* Nothing is vendored: what lands in the repo is a *reference* (a marketplace
|
|
29
29
|
* source plus an enabled flag). The plugin content still lives in the global
|
package/dist/setup-plan.d.ts
CHANGED
|
@@ -16,7 +16,10 @@ export interface SetupPlan {
|
|
|
16
16
|
test: boolean;
|
|
17
17
|
/** Wire CI (the `zernie/vigiles@v1` Action; creates a workflow if none). */
|
|
18
18
|
gha: boolean;
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Install vigiles's skills + hooks for the agent: the skills LINKED into the
|
|
21
|
+
* repo (every clone), the Claude Code hooks via the per-machine plugin.
|
|
22
|
+
*/
|
|
20
23
|
plugin: boolean;
|
|
21
24
|
/**
|
|
22
25
|
* Adopt/scaffold the instruction file(s) into typed `.spec.ts` (the compiled
|
|
@@ -74,6 +77,11 @@ export interface ParsedSetupArgs {
|
|
|
74
77
|
* DISCOVERY row of `cohesive-feature-delivery`.
|
|
75
78
|
*/
|
|
76
79
|
ciOnly: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* `--full` — run the whole setup even on a repo that already uses vigiles.
|
|
82
|
+
* Without it, a re-run there is the minimal one (see {@link rerunScope}).
|
|
83
|
+
*/
|
|
84
|
+
full: boolean;
|
|
77
85
|
}
|
|
78
86
|
/** Parse `init` args into the choices the user pinned. The two pillars are
|
|
79
87
|
* selected with `--lint` / `--test`. */
|
|
@@ -84,29 +92,6 @@ export declare function parseSetupArgs(args: readonly string[]): ParsedSetupArgs
|
|
|
84
92
|
* raw files WITHOUT scaffolding a spec (gate-first-adoption). Non-interactive
|
|
85
93
|
* behaviour is unchanged: bare `init` (lint on) scaffolds as before. */
|
|
86
94
|
export declare function defaultPlan(strict?: boolean): SetupPlan;
|
|
87
|
-
/**
|
|
88
|
-
* Pure config-merge for what `vigiles init` writes to `.vigilesrc.json`: record
|
|
89
|
-
* the `harness` if absent, add strict rule severities if `--strict`, NEVER
|
|
90
|
-
* clobber an existing key. Returns the merged config, or `null` when nothing
|
|
91
|
-
* changed (so the IO layer skips the write). The IO (read/parse/write + the
|
|
92
|
-
* malformed-file guard) stays in cli.ts.
|
|
93
|
-
*/
|
|
94
|
-
/**
|
|
95
|
-
* The structural rules `init` gates BY DEFAULT (severity `error`, so a broken
|
|
96
|
-
* surface fails `vigiles lint`). Every one is HIGH-PRECISION / FP-safe — it fires
|
|
97
|
-
* only on a genuine defect (a never-available/typo'd tool, a subagent missing
|
|
98
|
-
* `name`/`description`, a typo'd hook event, a dead hook script, a broken MCP
|
|
99
|
-
* ref, two skills that collide in the selector) — so a well-formed plugin stays
|
|
100
|
-
* green and catching real breakage out of the box never cries wolf.
|
|
101
|
-
*
|
|
102
|
-
* Deliberately EXCLUDES `require-instructions-spec` and the workflow-forcing rules:
|
|
103
|
-
* those make a CLEAN repo fail (you simply haven't written the spec/test yet), so
|
|
104
|
-
* they stay opt-in under `--strict` (progressive adoption — see
|
|
105
|
-
* `STRICT_EXTRA_RULES`).
|
|
106
|
-
*
|
|
107
|
-
* This is the **`structural`** rule group (see research/install-enforcement-dx.md).
|
|
108
|
-
*/
|
|
109
|
-
export declare const STRUCTURAL_RULES: readonly ["subagent-tool-contract", "subagent-frontmatter", "hook-events", "hook-script-exists", "mcp-config", "mcp-tool-resolves", "mcp-hook-target-resolves", "disallowed-tools-contract", "description-overlap"];
|
|
110
95
|
/**
|
|
111
96
|
* The **`workflow`** group — the WORKFLOW-FORCING / opinionated tier `--strict`
|
|
112
97
|
* gates, which a clean repo can still fail because you haven't done the work yet:
|
|
@@ -132,7 +117,24 @@ export declare const WORKFLOW_RULES: readonly ["require-instructions-spec", "unt
|
|
|
132
117
|
* (research/install-enforcement-dx.md).
|
|
133
118
|
*/
|
|
134
119
|
export declare const NUDGE_RULES: readonly ["skill-description-budget", "frontmatter-valid", "skill-frontmatter", "prefer-compiled-hooks", "unmarked-refs", "lethal-trifecta", "skill-resource-resolves", "skill-missing-fence", "plugin-dir-layout", "delegation-trifecta", "hook-block-ineffective", "hook-matcher", "doc-refs"];
|
|
135
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Pure config-merge for what `vigiles init` writes to `.vigilesrc.json`: record
|
|
122
|
+
* the harnesses if absent, gate the structural rules by EXTENDING the
|
|
123
|
+
* `vigiles:recommended` preset (never by writing each rule), add the workflow
|
|
124
|
+
* rules on `--strict`, and NEVER clobber an existing key or severity. Returns
|
|
125
|
+
* the merged config, or `null` when nothing changed (so the IO layer skips the
|
|
126
|
+
* write). The IO (read/parse/write + the malformed-file guard) stays in cli.ts.
|
|
127
|
+
*
|
|
128
|
+
* 🔴 THE PRESET, NOT NINE LINES (#338). Written lines are a snapshot of the
|
|
129
|
+
* structural group on the day `init` ran, so a repo adopted earlier never got a
|
|
130
|
+
* rule added to the group later; the preset is resolved by the loader on every
|
|
131
|
+
* run (`src/core/presets.ts`).
|
|
132
|
+
*
|
|
133
|
+
* `--report-only` is the exception and stays EXPLICIT: it promises that nothing
|
|
134
|
+
* fails CI, and extending a preset that later gains a rule at `error` would
|
|
135
|
+
* break that promise on an upgrade. So it writes the same rules at `warn`.
|
|
136
|
+
*/
|
|
137
|
+
export declare function mergeProjectConfig(existing: Readonly<Record<string, unknown>>, opts: Readonly<{
|
|
136
138
|
/** Canonical harness names this repo targets, in the order to declare them. */
|
|
137
139
|
harnesses: readonly string[];
|
|
138
140
|
strict: boolean;
|
|
@@ -141,7 +143,7 @@ export declare function mergeProjectConfig(existing: Record<string, unknown>, op
|
|
|
141
143
|
* concern, so a test-only setup (`init --test` / `--no-lint`) records the
|
|
142
144
|
* harness but writes NO lint rules. */
|
|
143
145
|
lint?: boolean;
|
|
144
|
-
}): Record<string, unknown> | null;
|
|
146
|
+
}>): Record<string, unknown> | null;
|
|
145
147
|
/**
|
|
146
148
|
* Whether to drop into interactive prompts: a human at a TTY who passed neither
|
|
147
149
|
* `--yes` nor an explicit `--target`, and who hasn't already pinned every choice
|
|
@@ -193,15 +195,18 @@ export interface InstallPlan {
|
|
|
193
195
|
notes: string[];
|
|
194
196
|
/** Whether this method writes files into the consumer's repo (vendoring). */
|
|
195
197
|
vendors: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Link the package's shipped skills into the repo's skills home
|
|
200
|
+
* (`src/skill-links.ts`). True only where the vendor documents following a
|
|
201
|
+
* symlinked skill folder — a link the harness skips is a silent absence.
|
|
202
|
+
*/
|
|
203
|
+
linkSkills: boolean;
|
|
204
|
+
/**
|
|
205
|
+
* The global install carries HOOKS as well as skills, so linked skills do not
|
|
206
|
+
* replace it (see {@link shouldRunGlobalInstall}).
|
|
207
|
+
*/
|
|
208
|
+
globalInstallCarriesHooks: boolean;
|
|
196
209
|
}
|
|
197
|
-
/** Per-harness install plan. `hasClaude` gates the auto-run `claude plugin` CLI
|
|
198
|
-
* (else the same two steps are printed as `/plugin` slash commands).
|
|
199
|
-
*
|
|
200
|
-
* Both methods install GLOBALLY, never into the repo: Claude through its plugin
|
|
201
|
-
* marketplace (~/.claude/plugins/), Codex through the cross-agent `skills` CLI
|
|
202
|
-
* with `-g -y` (the global store ~/.agents/skills/, which Codex reads). Codex
|
|
203
|
-
* gets the skills but NOT hooks — Codex hook wiring (.codex/config.toml [hooks])
|
|
204
|
-
* is not automated yet. */
|
|
205
210
|
/**
|
|
206
211
|
* The SHIPPED consumer skills (the `skills/` dir, published via `plugin.json`) —
|
|
207
212
|
* the ONLY ones a user's install should get. The cross-agent `skills` CLI would
|
|
@@ -212,9 +217,43 @@ export interface InstallPlan {
|
|
|
212
217
|
* dogfood test in `src/adapters/claude-code/skills-dogfood.test.ts`.
|
|
213
218
|
*/
|
|
214
219
|
export declare const SHIPPED_SKILLS: readonly ["adopt-spec", "debug-my-harness", "edit-spec", "linter-docs", "strengthen", "test-harness"];
|
|
220
|
+
/**
|
|
221
|
+
* Per-harness install plan. `hasClaude` gates the auto-run `claude plugin` CLI
|
|
222
|
+
* (else the same two steps are printed as `/plugin` slash commands).
|
|
223
|
+
*
|
|
224
|
+
* TWO CARRIERS, by what each one reaches. The SKILLS are linked into the repo
|
|
225
|
+
* (`linkSkills`), so every clone and container has them after `npm install`. The
|
|
226
|
+
* GLOBAL installs reach one machine: Claude Code's plugin (~/.claude/plugins/)
|
|
227
|
+
* is still the only carrier of vigiles's Claude Code HOOKS, so it always runs;
|
|
228
|
+
* Codex's `skills` CLI install (~/.agents/skills/) carries skills only, so it
|
|
229
|
+
* runs only when the links could not be made (no `package.json` to install
|
|
230
|
+
* into). Codex's nudge hooks are written into `.codex/config.toml` directly.
|
|
231
|
+
*
|
|
232
|
+
* THE CODEX GLOBAL COMMAND. The cross-agent `skills` CLI with `-g -y` installs
|
|
233
|
+
* to the global store ~/.agents/skills/ (NOT the repo, and NOT ~/.codex/ —
|
|
234
|
+
* verified against the real CLI). It is scoped to the SHIPPED skills with `-s`
|
|
235
|
+
* — without it the `skills` CLI installs EVERY SKILL.md in the repo, leaking
|
|
236
|
+
* the contributor-only .claude/skills/ into the user's global store
|
|
237
|
+
* (#dogfood-I2; confirmed — the CLI's `-l` list shows 17 skills for this repo,
|
|
238
|
+
* incl. .claude/skills). The `-s` parser is SPACE-separated (it consumes
|
|
239
|
+
* consecutive non-dash args), NOT comma-separated — a comma list is read as one
|
|
240
|
+
* literal skill name, matches nothing, and the install exits 1 (verified against
|
|
241
|
+
* the real `skills@1.5.20` arg parser).
|
|
242
|
+
*/
|
|
215
243
|
export declare function planPluginInstall(harnesses: readonly string[], opts: {
|
|
216
244
|
hasClaude: boolean;
|
|
217
245
|
}): InstallPlan[];
|
|
246
|
+
/**
|
|
247
|
+
* Run a plan's GLOBAL install, given whether the skills were linked into the
|
|
248
|
+
* repo? Skip it only when linked skills make it redundant — when it carries
|
|
249
|
+
* nothing but skills. Running it anyway would list every skill twice (Codex:
|
|
250
|
+
* "If two skills share the same `name`, Codex doesn't merge them; both can
|
|
251
|
+
* appear in skill selectors"). Claude Code's plugin carries the hooks, so it
|
|
252
|
+
* always runs; its skills are namespaced `vigiles:<name>` and load beside the
|
|
253
|
+
* linked `<name>` (a known, documented duplicate until the hooks move into the
|
|
254
|
+
* repo too).
|
|
255
|
+
*/
|
|
256
|
+
export declare function shouldRunGlobalInstall(plan: Readonly<Pick<InstallPlan, "globalInstallCarriesHooks">>, skillsLinked: boolean): boolean;
|
|
218
257
|
/** One vigiles-managed Codex hook: a `[[hooks.<event>]]` entry. */
|
|
219
258
|
export interface CodexPluginHook {
|
|
220
259
|
readonly event: string;
|
|
@@ -252,6 +291,75 @@ export declare function codexPluginHooks(): CodexPluginHook[];
|
|
|
252
291
|
* (and every other config key) untouched. Returns a new object.
|
|
253
292
|
*/
|
|
254
293
|
export declare function applyCodexPluginHooks(existing: Record<string, unknown>): Record<string, unknown>;
|
|
294
|
+
/**
|
|
295
|
+
* Whether this repo already uses vigiles, decided from what is ON DISK.
|
|
296
|
+
*
|
|
297
|
+
* 🔴 THE SIGNAL IS `.vigilesrc.json` OR A SPEC NEXT TO AN INSTRUCTION FILE, and
|
|
298
|
+
* deliberately NOT a `vigiles` devDependency: the documented first step on a new
|
|
299
|
+
* repo can be `npm i -D vigiles` followed by `npx vigiles init`, and that run
|
|
300
|
+
* must still be the full setup. Every `init` writes `.vigilesrc.json` (it records
|
|
301
|
+
* the harnesses even on a test-only run), and a hand-written one means the owner
|
|
302
|
+
* has already configured vigiles. A spec beside `CLAUDE.md`/`AGENTS.md` covers a
|
|
303
|
+
* repo adopted before the config file existed.
|
|
304
|
+
*/
|
|
305
|
+
export type AdoptionState = {
|
|
306
|
+
readonly kind: "fresh";
|
|
307
|
+
} | {
|
|
308
|
+
readonly kind: "adopted";
|
|
309
|
+
readonly evidence: string;
|
|
310
|
+
};
|
|
311
|
+
/** {@link AdoptionState} from the two disk facts that decide it. */
|
|
312
|
+
export declare function adoptionState(facts: Readonly<{
|
|
313
|
+
hasConfig: boolean;
|
|
314
|
+
specs: readonly string[];
|
|
315
|
+
}>): AdoptionState;
|
|
316
|
+
/**
|
|
317
|
+
* Which setup a run performs: the full one, or the minimal re-run (#338).
|
|
318
|
+
*
|
|
319
|
+
* MINIMAL only when the repo is adopted AND the run named nothing that asks for
|
|
320
|
+
* more. A flag that selects or widens the setup (`--full`, `--strict`,
|
|
321
|
+
* `--ci-only`, `--report-only`, `--force`, `--target=`, a positive `--lint` /
|
|
322
|
+
* `--test`) is an explicit request and keeps today's behaviour; the narrowing
|
|
323
|
+
* flags (`--no-*`, `--harness=`, `--yes`) do not, because they can only make a
|
|
324
|
+
* run do less.
|
|
325
|
+
*/
|
|
326
|
+
export declare function rerunScope(parsed: Readonly<ParsedSetupArgs>, state: AdoptionState): "full" | "minimal";
|
|
327
|
+
/**
|
|
328
|
+
* The `devDependencies` a minimal re-run writes, or null to leave package.json
|
|
329
|
+
* alone. It ADDS vigiles when no dependency field declares it and never edits an
|
|
330
|
+
* existing declaration: rewriting `^33.3.0` to `^33` loosens a pin the owner
|
|
331
|
+
* chose, and moving it between fields is a decision, not a missing piece.
|
|
332
|
+
*/
|
|
333
|
+
export declare function missingVigilesDevDep(pkg: Readonly<{
|
|
334
|
+
dependencies?: Readonly<Record<string, string>>;
|
|
335
|
+
devDependencies?: Readonly<Record<string, string>>;
|
|
336
|
+
}>, spec: string): Readonly<Record<string, string>> | null;
|
|
337
|
+
/** What a full setup would add on an adopted repo — the facts that decide it. */
|
|
338
|
+
export interface FullSetupGap {
|
|
339
|
+
/** `.github/workflows/vigiles.yml` is absent (and CI wiring is not opted out). */
|
|
340
|
+
readonly workflow: boolean;
|
|
341
|
+
/** `.vigilesrc.json`: absent, present without the preset, or already extending it. */
|
|
342
|
+
readonly config: "missing" | "no-preset" | "has-preset";
|
|
343
|
+
/** `vigiles.harness.mjs` is absent (and the test layer is not opted out). */
|
|
344
|
+
readonly harnessTest: boolean;
|
|
345
|
+
/** Instruction files and surfaces a full setup would adopt into a spec. */
|
|
346
|
+
readonly unspecced: readonly string[];
|
|
347
|
+
/** `.vigiles/generated.d.ts` / `.vigiles/schema.json` would be created. */
|
|
348
|
+
readonly generated: boolean;
|
|
349
|
+
/** The global plugin install / hook wiring a full setup would run, one line each. */
|
|
350
|
+
readonly installs: readonly string[];
|
|
351
|
+
/** The devDependency rewrite a full setup would make, if any. */
|
|
352
|
+
readonly devDep: Readonly<{
|
|
353
|
+
from: string;
|
|
354
|
+
to: string;
|
|
355
|
+
}> | null;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* The lines a minimal re-run prints about what it did NOT do: each thing a full
|
|
359
|
+
* setup would add here, then the flag that does it. Empty when nothing is
|
|
360
|
+
* missing, so a fully set-up repo is not told to run anything.
|
|
361
|
+
*/
|
|
362
|
+
export declare function fullSetupFollowUps(gap: FullSetupGap): readonly string[];
|
|
255
363
|
/**
|
|
256
364
|
* Resolve the final plan: defaults, then flags, then interactive answers (each
|
|
257
365
|
* layer overrides the previous only where it has an opinion). `--target` pins a
|