@amsterdamdatalabs/enact-extensions 0.1.12 → 0.1.24
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 +11 -12
- package/dist/create/enact.js +1 -1
- package/dist/create/enact.js.map +1 -1
- package/dist/create/index.d.ts +4 -3
- package/dist/create/index.d.ts.map +1 -1
- package/dist/create/index.js +9 -2
- package/dist/create/index.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/install.d.ts +5 -0
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +10 -3
- package/dist/install.js.map +1 -1
- package/dist/internal/agents.d.ts +6 -1
- package/dist/internal/agents.d.ts.map +1 -1
- package/dist/internal/agents.js +8 -4
- package/dist/internal/agents.js.map +1 -1
- package/dist/internal/claude.d.ts +24 -0
- package/dist/internal/claude.d.ts.map +1 -1
- package/dist/internal/claude.js +99 -0
- package/dist/internal/claude.js.map +1 -1
- package/dist/internal/platform.d.ts +3 -1
- package/dist/internal/platform.d.ts.map +1 -1
- package/dist/internal/platform.js +7 -1
- package/dist/internal/platform.js.map +1 -1
- package/dist/internal/types.d.ts +2 -1
- package/dist/internal/types.d.ts.map +1 -1
- package/dist/principles.d.ts +28 -0
- package/dist/principles.d.ts.map +1 -0
- package/dist/principles.js +159 -0
- package/dist/principles.js.map +1 -0
- package/extensions/dev-state/.agents/plugin.json +2 -1
- package/extensions/enact-context/.agents/plugin.json +2 -1
- package/extensions/enact-context/hooks/hooks.json +0 -10
- package/extensions/enact-context/skills/enact-context/SKILL.md +14 -12
- package/extensions/enact-context/skills/enact-context/scripts/install.sh +7 -7
- package/extensions/enact-core/.agents/plugin.json +2 -1
- package/extensions/enact-core/OPERATING-PRINCIPLES.md +7 -0
- package/extensions/enact-core/hooks/hooks.json +12 -0
- package/extensions/enact-evolve/.agents/plugin.json +47 -0
- package/extensions/enact-evolve/agents/evolve-session-analyst.toml +37 -0
- package/extensions/enact-evolve/skills/session-analysis/SKILL.md +98 -0
- package/extensions/enact-evolve/skills/session-analysis/scripts/run-evolve-analysis.sh +343 -0
- package/extensions/enact-factory/.agents/plugin.json +2 -2
- package/extensions/enact-factory/agents/architect.toml +9 -5
- package/extensions/enact-factory/agents/code-reviewer.toml +9 -5
- package/extensions/enact-factory/agents/critic.toml +9 -5
- package/extensions/enact-factory/agents/executor.toml +4 -1
- package/extensions/enact-factory/agents/explore.toml +4 -1
- package/extensions/enact-factory/agents/planner.toml +4 -1
- package/extensions/enact-factory/agents/verifier.toml +9 -5
- package/extensions/enact-factory/skills/advisor/SKILL.md +82 -0
- package/extensions/enact-factory/skills/ai-slop-cleaner/SKILL.md +6 -1
- package/extensions/enact-factory/skills/autonomous-runner/SKILL.md +347 -0
- package/extensions/enact-factory/skills/azdo-ci-strategy/SKILL.md +42 -15
- package/extensions/enact-factory/skills/committee/SKILL.md +80 -0
- package/extensions/enact-factory/skills/deep-interview/SKILL.md +9 -13
- package/extensions/enact-factory/skills/drive-loop/SKILL.md +161 -31
- package/extensions/enact-factory/skills/drive-loop/references/contract-schema.md +26 -6
- package/extensions/enact-factory/skills/handoff/SKILL.md +72 -0
- package/extensions/enact-factory/skills/hyperplan/SKILL.md +11 -3
- package/extensions/enact-factory/skills/looplan/SKILL.md +34 -17
- package/extensions/enact-factory/skills/plan/SKILL.md +40 -8
- package/extensions/enact-factory/skills/remove-deadcode/SKILL.md +6 -1
- package/extensions/enact-factory/skills/research/SKILL.md +14 -4
- package/extensions/enact-factory/skills/review/SKILL.md +21 -2
- package/extensions/enact-factory/skills/security-research/SKILL.md +5 -2
- package/extensions/enact-factory/skills/tdd/SKILL.md +7 -1
- package/extensions/enact-factory/skills/testing-strategy/SKILL.md +5 -0
- package/extensions/enact-factory/skills/trace/SKILL.md +5 -0
- package/extensions/enact-factory/skills/ultraqa/SKILL.md +21 -15
- package/extensions/enact-factory/skills/work-with-workitem/SKILL.md +5 -0
- package/extensions/enact-factory/skills/workitem-triage/SKILL.md +5 -0
- package/extensions/enact-loop/.agents/plugin.json +5 -4
- package/extensions/enact-loop/scripts/validate.mjs +123 -0
- package/extensions/enact-loop/skills/enact-loop/SKILL.md +189 -30
- package/extensions/enact-wiki/.agents/plugin.json +2 -1
- package/extensions/net-revenue-management/.agents/plugin.json +2 -1
- package/extensions/plugin-dev/.agents/plugin.json +2 -1
- package/extensions/plugin-dev/skills/start/SKILL.md +3 -3
- package/package.json +1 -1
- package/scripts/check-hooks.mjs +5 -5
- package/scripts/check-principles.mjs +19 -4
- package/scripts/enact-extensions.mjs +237 -90
- package/scripts/lib/hooks.mjs +61 -217
- package/scripts/lib/migrate-artifacts.mjs +144 -0
- package/scripts/lib/principles.mjs +109 -0
- package/scripts/lib/provision-mcp.mjs +1 -1
- package/scripts/lib/run-install.mjs +72 -2
- package/scripts/lib/run-prune.mjs +23 -2
- package/scripts/lib/run-sync.mjs +4 -1
- package/scripts/postinstall.mjs +6 -6
- package/scripts/setup-enact-context.sh +20 -15
- package/spec/codex.json +5 -0
- package/spec/enact.json +3 -3
- package/spec/enact.md +1 -4
- package/spec/index.json +1 -1
- package/extensions/enact-factory/hooks/hooks.json +0 -14
- package/extensions/enact-operator/.agents/plugin.json +0 -56
- package/extensions/enact-operator/.app.json +0 -3
- package/extensions/enact-operator/.mcp.json +0 -10
- package/extensions/enact-operator/_taxonomy.md +0 -86
- package/extensions/enact-operator/agents/README.md +0 -5
- package/extensions/enact-operator/agents/architect.toml +0 -25
- package/extensions/enact-operator/agents/code-reviewer.toml +0 -24
- package/extensions/enact-operator/agents/critic.toml +0 -30
- package/extensions/enact-operator/agents/executor.toml +0 -24
- package/extensions/enact-operator/agents/explore.toml +0 -23
- package/extensions/enact-operator/agents/planner.toml +0 -24
- package/extensions/enact-operator/agents/verifier.toml +0 -24
- package/extensions/enact-operator/docs/skill-variants.md +0 -44
- package/extensions/enact-operator/hooks/hooks.json +0 -91
- package/extensions/enact-operator/skills/ai-slop-cleaner/SKILL.md +0 -50
- package/extensions/enact-operator/skills/analyze/SKILL.md +0 -91
- package/extensions/enact-operator/skills/ask/SKILL.md +0 -47
- package/extensions/enact-operator/skills/autopilot/SKILL.md +0 -170
- package/extensions/enact-operator/skills/autoresearch-goal/SKILL.md +0 -79
- package/extensions/enact-operator/skills/cancel/SKILL.md +0 -99
- package/extensions/enact-operator/skills/configure-notifications/SKILL.md +0 -77
- package/extensions/enact-operator/skills/deep-interview/SKILL.md +0 -80
- package/extensions/enact-operator/skills/doctor/SKILL.md +0 -48
- package/extensions/enact-operator/skills/hud/SKILL.md +0 -49
- package/extensions/enact-operator/skills/hyperplan/SKILL.md +0 -47
- package/extensions/enact-operator/skills/plan/SKILL.md +0 -78
- package/extensions/enact-operator/skills/ralph/SKILL.md +0 -201
- package/extensions/enact-operator/skills/ralph/gemini.md +0 -18
- package/extensions/enact-operator/skills/ralplan/SKILL.md +0 -151
- package/extensions/enact-operator/skills/remove-deadcode/SKILL.md +0 -45
- package/extensions/enact-operator/skills/research/SKILL.md +0 -74
- package/extensions/enact-operator/skills/review/SKILL.md +0 -58
- package/extensions/enact-operator/skills/security-research/SKILL.md +0 -54
- package/extensions/enact-operator/skills/setup/SKILL.md +0 -91
- package/extensions/enact-operator/skills/setup/scripts/install.sh +0 -50
- package/extensions/enact-operator/skills/skill/SKILL.md +0 -82
- package/extensions/enact-operator/skills/tdd/SKILL.md +0 -59
- package/extensions/enact-operator/skills/team/SKILL.md +0 -199
- package/extensions/enact-operator/skills/trace/SKILL.md +0 -41
- package/extensions/enact-operator/skills/ultragoal/SKILL.md +0 -99
- package/extensions/enact-operator/skills/ultraqa/SKILL.md +0 -113
- package/extensions/enact-operator/skills/ultrawork/SKILL.md +0 -145
- package/extensions/enact-operator/skills/ultrawork/planner.md +0 -28
- package/extensions/enact-operator/skills/wiki/SKILL.md +0 -41
- package/extensions/enact-operator/skills/work-with-workitem/SKILL.md +0 -51
- /package/extensions/{enact-operator → enact-evolve}/assets/icon.png +0 -0
- /package/extensions/{enact-operator → enact-evolve}/assets/logo.png +0 -0
|
@@ -11,8 +11,15 @@ import { runPrune } from "./lib/run-prune.mjs";
|
|
|
11
11
|
import { runUninstall } from "./lib/run-uninstall.mjs";
|
|
12
12
|
import { readLedger } from "./lib/ledger.mjs";
|
|
13
13
|
import { computeOutdated } from "./lib/outdated.mjs";
|
|
14
|
+
import { migrateGlobalArtifacts } from "./lib/migrate-artifacts.mjs";
|
|
14
15
|
import { startServer, resolveServePort } from "./lib/serve.mjs";
|
|
15
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
setupPrinciples,
|
|
18
|
+
removePrinciples,
|
|
19
|
+
checkPrinciples,
|
|
20
|
+
runDoctor,
|
|
21
|
+
SUPPORTED_PRINCIPLES_SURFACES,
|
|
22
|
+
} from "./lib/principles.mjs";
|
|
16
23
|
import { dirname, join, resolve } from "node:path";
|
|
17
24
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
18
25
|
import { fileURLToPath } from "node:url";
|
|
@@ -36,6 +43,8 @@ Usage:
|
|
|
36
43
|
enact-extensions log --json Emit the raw ledger array as JSON
|
|
37
44
|
enact-extensions outdated Report freshness drift: installed vs canonical source (per plugin+surface)
|
|
38
45
|
enact-extensions outdated --json Emit JSON array [{name, platform, scope, home, status, installedHash, currentHash, version}]
|
|
46
|
+
enact-extensions migrate-artifacts [--dry-run] [--json]
|
|
47
|
+
Rename legacy factory/loop markdown artifacts to YYMMDDHH-<slug>.md
|
|
39
48
|
enact-extensions update <name> Refresh an outdated plugin on every surface it is installed on (ledger-driven)
|
|
40
49
|
enact-extensions update --all Refresh EVERY outdated plugin/surface
|
|
41
50
|
enact-extensions update <name> --dry-run Show what would be refreshed; change nothing
|
|
@@ -68,17 +77,14 @@ Usage:
|
|
|
68
77
|
enact-extensions uninstall [path|name] --platform all Uninstall from every plugin platform
|
|
69
78
|
enact-extensions uninstall [path|name] --platform claude,cursor Uninstall from a subset of platforms
|
|
70
79
|
enact-extensions serve [--port N] [--prod] [--host 127.0.0.1] [--open] Start the localhost management UI + API (dev 43217 / prod 53217)
|
|
71
|
-
enact-extensions
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
enact-extensions
|
|
78
|
-
|
|
79
|
-
enact-extensions hooks setup --all --remove Remove the drift hook from all surfaces
|
|
80
|
-
enact-extensions hooks setup --surfaces claude --local Register using project-local home (under cwd)
|
|
81
|
-
enact-extensions hooks setup Interactive surface picker (TTY only)
|
|
80
|
+
enact-extensions principles setup [--surfaces <list>|--all] [--remove] [--local]
|
|
81
|
+
Inject (or remove) the enact-core operating-principles block
|
|
82
|
+
into host agent files (CLAUDE.md / AGENTS.md).
|
|
83
|
+
enact-extensions principles check [--surfaces <list>|--all] [--local] [--json]
|
|
84
|
+
Report principles block drift per surface (present/missing/stale).
|
|
85
|
+
Use principles setup or doctor --fix to remediate. Not npm run check:principles.
|
|
86
|
+
enact-extensions doctor [--fix] [--surfaces <list>|--all] [--local] [--json]
|
|
87
|
+
Check operating-principles block drift per surface; --fix applies blocks.
|
|
82
88
|
enact-extensions -v | --version Print version and exit
|
|
83
89
|
|
|
84
90
|
Options:
|
|
@@ -198,6 +204,8 @@ function parseArgs(argv) {
|
|
|
198
204
|
options.surfaces = argv[++i].split(",").map((s) => s.trim()).filter(Boolean);
|
|
199
205
|
} else if (arg === "--remove") {
|
|
200
206
|
options.remove = true;
|
|
207
|
+
} else if (arg === "--fix") {
|
|
208
|
+
options.fix = true;
|
|
201
209
|
} else if (arg === "-h" || arg === "--help") {
|
|
202
210
|
positional.push("help");
|
|
203
211
|
} else if (!arg.startsWith("-")) {
|
|
@@ -227,83 +235,81 @@ if (!command || command === "help") {
|
|
|
227
235
|
// Surfaces: claude, codex, cursor, enact
|
|
228
236
|
// Registration is idempotent and reversible.
|
|
229
237
|
// ---------------------------------------------------------------------------
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
238
|
+
// ---------------------------------------------------------------------------
|
|
239
|
+
// `principles` command — inject or check operating-principles blocks in host files.
|
|
240
|
+
//
|
|
241
|
+
// Surfaces: claude, codex, cursor, enact
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
if (command === "principles") {
|
|
233
244
|
const subCommand = path ?? "setup";
|
|
234
245
|
|
|
235
|
-
if (subCommand !== "setup") {
|
|
236
|
-
process.stderr.write(
|
|
246
|
+
if (subCommand !== "setup" && subCommand !== "check") {
|
|
247
|
+
process.stderr.write(
|
|
248
|
+
`[enact-extensions principles] Unknown sub-command: ${subCommand}. Use 'setup' or 'check'.\n`,
|
|
249
|
+
);
|
|
237
250
|
process.exit(1);
|
|
238
251
|
}
|
|
239
252
|
|
|
240
253
|
const isRemove = options.remove ?? false;
|
|
241
254
|
const isLocal = options.scope === "local";
|
|
242
255
|
const cwd = processCwd();
|
|
256
|
+
const surfacesList = SUPPORTED_PRINCIPLES_SURFACES;
|
|
243
257
|
|
|
244
|
-
// Determine which surfaces to act on.
|
|
245
258
|
let surfaces = [];
|
|
246
259
|
if (options.all) {
|
|
247
|
-
surfaces = [...
|
|
260
|
+
surfaces = [...surfacesList];
|
|
248
261
|
} else if (options.surfaces && options.surfaces.length > 0) {
|
|
249
|
-
|
|
250
|
-
const invalid = options.surfaces.filter((s) => !SUPPORTED_SURFACES.includes(s));
|
|
262
|
+
const invalid = options.surfaces.filter((s) => !surfacesList.includes(s));
|
|
251
263
|
if (invalid.length > 0) {
|
|
252
|
-
process.stderr.write(
|
|
264
|
+
process.stderr.write(
|
|
265
|
+
`[enact-extensions principles] Unknown surface(s): ${invalid.join(", ")}. Valid: ${surfacesList.join(", ")}\n`,
|
|
266
|
+
);
|
|
253
267
|
process.exit(1);
|
|
254
268
|
}
|
|
255
269
|
surfaces = options.surfaces;
|
|
256
|
-
} else {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const { createInterface } = await import("node:readline");
|
|
261
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
270
|
+
} else if (subCommand === "setup" && process.stdin.isTTY) {
|
|
271
|
+
const { createInterface } = await import("node:readline");
|
|
272
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
273
|
+
const question = (prompt) => new Promise((resolve) => rl.question(prompt, resolve));
|
|
262
274
|
|
|
263
|
-
|
|
275
|
+
process.stdout.write(`\nenact-extensions principles setup — interactive surface picker\n`);
|
|
276
|
+
process.stdout.write(`Available surfaces: ${surfacesList.map((s, i) => `${i + 1}. ${s}`).join(", ")}\n`);
|
|
277
|
+
process.stdout.write(`Enter surface names or numbers (comma-separated), or 'all':\n`);
|
|
264
278
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
process.stdout.write(`Enter surface names or numbers (comma-separated), or 'all':\n`);
|
|
279
|
+
const answer = await question("> ");
|
|
280
|
+
rl.close();
|
|
268
281
|
|
|
269
|
-
|
|
270
|
-
|
|
282
|
+
if (answer.trim().toLowerCase() === "all") {
|
|
283
|
+
surfaces = [...surfacesList];
|
|
284
|
+
} else {
|
|
285
|
+
surfaces = answer
|
|
286
|
+
.split(",")
|
|
287
|
+
.map((s) => s.trim())
|
|
288
|
+
.filter(Boolean)
|
|
289
|
+
.map((s) => {
|
|
290
|
+
const idx = parseInt(s, 10);
|
|
291
|
+
if (!isNaN(idx) && idx >= 1 && idx <= surfacesList.length) {
|
|
292
|
+
return surfacesList[idx - 1];
|
|
293
|
+
}
|
|
294
|
+
return s.toLowerCase();
|
|
295
|
+
})
|
|
296
|
+
.filter((s) => surfacesList.includes(s));
|
|
271
297
|
|
|
272
|
-
if (
|
|
273
|
-
surfaces
|
|
274
|
-
|
|
275
|
-
surfaces = answer
|
|
276
|
-
.split(",")
|
|
277
|
-
.map((s) => s.trim())
|
|
278
|
-
.filter(Boolean)
|
|
279
|
-
.map((s) => {
|
|
280
|
-
// Allow numeric selection.
|
|
281
|
-
const idx = parseInt(s, 10);
|
|
282
|
-
if (!isNaN(idx) && idx >= 1 && idx <= SUPPORTED_SURFACES.length) {
|
|
283
|
-
return SUPPORTED_SURFACES[idx - 1];
|
|
284
|
-
}
|
|
285
|
-
return s.toLowerCase();
|
|
286
|
-
})
|
|
287
|
-
.filter((s) => SUPPORTED_SURFACES.includes(s));
|
|
288
|
-
|
|
289
|
-
if (surfaces.length === 0) {
|
|
290
|
-
process.stderr.write(`[enact-extensions hooks] No valid surfaces selected. Exiting.\n`);
|
|
291
|
-
process.exit(0);
|
|
292
|
-
}
|
|
298
|
+
if (surfaces.length === 0) {
|
|
299
|
+
process.stderr.write(`[enact-extensions principles] No valid surfaces selected. Exiting.\n`);
|
|
300
|
+
process.exit(0);
|
|
293
301
|
}
|
|
294
|
-
} else {
|
|
295
|
-
// Non-TTY, no surface flags → print notice and exit 0.
|
|
296
|
-
process.stdout.write(
|
|
297
|
-
`[enact-extensions hooks] No surface specified. Run with --surfaces or --all:\n` +
|
|
298
|
-
` enact-extensions hooks setup --surfaces claude,codex\n` +
|
|
299
|
-
` enact-extensions hooks setup --all\n`,
|
|
300
|
-
);
|
|
301
|
-
process.exit(0);
|
|
302
302
|
}
|
|
303
|
+
} else {
|
|
304
|
+
process.stdout.write(
|
|
305
|
+
`[enact-extensions principles] No surface specified. Run with --surfaces or --all:\n` +
|
|
306
|
+
` enact-extensions principles ${subCommand} --surfaces claude,codex\n` +
|
|
307
|
+
` enact-extensions principles ${subCommand} --all\n`,
|
|
308
|
+
);
|
|
309
|
+
process.exit(0);
|
|
303
310
|
}
|
|
304
311
|
|
|
305
|
-
|
|
306
|
-
const hookOpts = {
|
|
312
|
+
const principleOpts = {
|
|
307
313
|
claudeHome: options.claudeHome,
|
|
308
314
|
codexHome: options.codexHome,
|
|
309
315
|
cursorHome: options.cursorHome,
|
|
@@ -312,37 +318,126 @@ if (command === "hooks") {
|
|
|
312
318
|
cwd,
|
|
313
319
|
};
|
|
314
320
|
|
|
321
|
+
let exitCode = 0;
|
|
322
|
+
|
|
323
|
+
if (subCommand === "check") {
|
|
324
|
+
const rows = [];
|
|
325
|
+
for (const surface of surfaces) {
|
|
326
|
+
try {
|
|
327
|
+
const res = checkPrinciples(surface, principleOpts);
|
|
328
|
+
rows.push(res);
|
|
329
|
+
if (!options.json) {
|
|
330
|
+
process.stdout.write(
|
|
331
|
+
` [principles] ${surface}: ${res.status} → ${res.path}\n`,
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
} catch (err) {
|
|
335
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
336
|
+
rows.push({ surface, path: "", status: "error", error: message });
|
|
337
|
+
process.stderr.write(` [principles] ${surface}: error — ${message}\n`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (options.json) {
|
|
342
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
process.exit(0);
|
|
346
|
+
}
|
|
347
|
+
|
|
315
348
|
for (const surface of surfaces) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
349
|
+
try {
|
|
350
|
+
const res = isRemove
|
|
351
|
+
? removePrinciples(surface, principleOpts)
|
|
352
|
+
: setupPrinciples(surface, principleOpts);
|
|
353
|
+
|
|
354
|
+
if (res.result === "applied") {
|
|
355
|
+
process.stdout.write(
|
|
356
|
+
` [principles] ${surface}: applied (${res.action}) → ${res.path}\n`,
|
|
357
|
+
);
|
|
358
|
+
} else if (res.result === "already_present") {
|
|
359
|
+
process.stdout.write(
|
|
360
|
+
` [principles] ${surface}: already present (noop) → ${res.path}\n`,
|
|
361
|
+
);
|
|
362
|
+
} else if (res.result === "removed") {
|
|
363
|
+
process.stdout.write(` [principles] ${surface}: removed → ${res.path}\n`);
|
|
364
|
+
} else if (res.result === "not_found") {
|
|
365
|
+
process.stdout.write(
|
|
366
|
+
` [principles] ${surface}: not found (nothing to remove) → ${res.path}\n`,
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
} catch (err) {
|
|
370
|
+
exitCode = 1;
|
|
371
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
372
|
+
process.stderr.write(` [principles] ${surface}: error — ${message}\n`);
|
|
321
373
|
}
|
|
374
|
+
}
|
|
322
375
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
376
|
+
process.exit(exitCode);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// ---------------------------------------------------------------------------
|
|
380
|
+
// `doctor` command — check (and optionally fix) operating-principles drift.
|
|
381
|
+
//
|
|
382
|
+
// Surfaces: claude, codex, cursor, enact (defaults to all when omitted)
|
|
383
|
+
// ---------------------------------------------------------------------------
|
|
384
|
+
if (command === "doctor") {
|
|
385
|
+
const isFix = options.fix ?? false;
|
|
386
|
+
const isLocal = options.scope === "local";
|
|
387
|
+
const cwd = processCwd();
|
|
388
|
+
const surfacesList = SUPPORTED_PRINCIPLES_SURFACES;
|
|
389
|
+
|
|
390
|
+
let surfaces = [];
|
|
391
|
+
if (options.all || !options.surfaces || options.surfaces.length === 0) {
|
|
392
|
+
surfaces = [...surfacesList];
|
|
393
|
+
} else {
|
|
394
|
+
const invalid = options.surfaces.filter((s) => !surfacesList.includes(s));
|
|
395
|
+
if (invalid.length > 0) {
|
|
396
|
+
process.stderr.write(
|
|
397
|
+
`[enact-extensions doctor] Unknown surface(s): ${invalid.join(", ")}. Valid: ${surfacesList.join(", ")}\n`,
|
|
398
|
+
);
|
|
399
|
+
process.exit(1);
|
|
338
400
|
}
|
|
401
|
+
surfaces = options.surfaces;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const principleOpts = {
|
|
405
|
+
claudeHome: options.claudeHome,
|
|
406
|
+
codexHome: options.codexHome,
|
|
407
|
+
cursorHome: options.cursorHome,
|
|
408
|
+
enactHome: options.enactHome,
|
|
409
|
+
local: isLocal,
|
|
410
|
+
cwd,
|
|
411
|
+
fix: isFix,
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
const { rows, exitCode } = runDoctor(surfaces, principleOpts);
|
|
339
415
|
|
|
340
|
-
|
|
341
|
-
|
|
416
|
+
if (!options.json) {
|
|
417
|
+
for (const row of rows) {
|
|
418
|
+
if (row.error) {
|
|
419
|
+
process.stderr.write(` [doctor] ${row.surface}: error — ${row.error}\n`);
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
if (isFix) {
|
|
423
|
+
const note = row.result === "already_present"
|
|
424
|
+
? "already present (noop)"
|
|
425
|
+
: `fixed (${row.action ?? row.result})`;
|
|
426
|
+
process.stdout.write(` [doctor] ${row.surface}: ${row.status} — ${note} → ${row.path}\n`);
|
|
427
|
+
} else {
|
|
428
|
+
process.stdout.write(` [doctor] ${row.surface}: ${row.status} → ${row.path}\n`);
|
|
429
|
+
}
|
|
342
430
|
}
|
|
431
|
+
if (!isFix && exitCode !== 0) {
|
|
432
|
+
process.stderr.write(
|
|
433
|
+
`[enact-extensions doctor] Drift detected. Fix with: enact-extensions doctor --fix --all\n`,
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
} else {
|
|
437
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
343
438
|
}
|
|
344
439
|
|
|
345
|
-
process.exit(
|
|
440
|
+
process.exit(exitCode);
|
|
346
441
|
}
|
|
347
442
|
|
|
348
443
|
// ---------------------------------------------------------------------------
|
|
@@ -615,6 +710,39 @@ if (command === "outdated") {
|
|
|
615
710
|
}
|
|
616
711
|
|
|
617
712
|
// ---------------------------------------------------------------------------
|
|
713
|
+
// `migrate-artifacts` command — rename legacy global markdown artifacts.
|
|
714
|
+
if (command === "migrate-artifacts") {
|
|
715
|
+
try {
|
|
716
|
+
const report = migrateGlobalArtifacts({ dryRun: Boolean(options.dryRun) });
|
|
717
|
+
if (options.json) {
|
|
718
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
719
|
+
} else {
|
|
720
|
+
const factoryRenamed = report.factory.flatMap((entry) => entry.renamed);
|
|
721
|
+
const loopRenamed = report.loop.flatMap((entry) => entry.renamed);
|
|
722
|
+
if (factoryRenamed.length === 0 && loopRenamed.length === 0) {
|
|
723
|
+
process.stdout.write("✓ no legacy markdown artifacts to migrate\n");
|
|
724
|
+
}
|
|
725
|
+
for (const { from, to } of factoryRenamed) {
|
|
726
|
+
process.stdout.write(`✓ factory ${from} → ${to}\n`);
|
|
727
|
+
}
|
|
728
|
+
for (const { from, to } of loopRenamed) {
|
|
729
|
+
process.stdout.write(`✓ loop ${from} → ${to}\n`);
|
|
730
|
+
}
|
|
731
|
+
if (report.fallbacks.length > 0) {
|
|
732
|
+
process.stderr.write(
|
|
733
|
+
`· ${report.fallbacks.length} ISO-date rename(s) used hour fallback — see --json for details\n`,
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
process.exit(0);
|
|
738
|
+
} catch (err) {
|
|
739
|
+
process.stderr.write(
|
|
740
|
+
`[enact-extensions migrate-artifacts] Error: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
741
|
+
);
|
|
742
|
+
process.exit(1);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
618
746
|
// `update` command — refresh outdated installed plugins, driven by the ledger.
|
|
619
747
|
//
|
|
620
748
|
// Re-installs each OUTDATED (plugin, surface, home) to the EXACT surface + home
|
|
@@ -803,6 +931,9 @@ if (command === "serve") {
|
|
|
803
931
|
// `hook` command — execute a hook handler by name, reading JSON from stdin.
|
|
804
932
|
//
|
|
805
933
|
// Currently supported sub-commands:
|
|
934
|
+
// enact-extensions hook session-start
|
|
935
|
+
// Runs the advisory drift-check and prints a single line only when plugin
|
|
936
|
+
// surfaces are outdated.
|
|
806
937
|
// enact-extensions hook user-prompt-submit
|
|
807
938
|
// Reads a UserPromptSubmit hook payload from stdin, extracts the prompt,
|
|
808
939
|
// builds the skill catalog from the bundled extensions dir, routes the
|
|
@@ -816,10 +947,10 @@ if (command === "serve") {
|
|
|
816
947
|
if (command === "hook") {
|
|
817
948
|
const subCommand = path; // positional[1]
|
|
818
949
|
|
|
819
|
-
if (subCommand !== "user-prompt-submit") {
|
|
950
|
+
if (subCommand !== "user-prompt-submit" && subCommand !== "session-start") {
|
|
820
951
|
process.stderr.write(
|
|
821
952
|
`[enact-extensions hook] Unknown sub-command: ${subCommand ?? "(none)"}. ` +
|
|
822
|
-
`Supported: user-prompt-submit\n`,
|
|
953
|
+
`Supported: session-start, user-prompt-submit\n`,
|
|
823
954
|
);
|
|
824
955
|
process.stdout.write(JSON.stringify({ continue: true }) + "\n");
|
|
825
956
|
process.exit(0);
|
|
@@ -827,6 +958,22 @@ if (command === "hook") {
|
|
|
827
958
|
|
|
828
959
|
// Async IIFE: stdin reading and dynamic import require async context.
|
|
829
960
|
(async () => {
|
|
961
|
+
if (subCommand === "session-start") {
|
|
962
|
+
try {
|
|
963
|
+
const { computeOutdated } = await import("./lib/outdated.mjs");
|
|
964
|
+
const outdated = (computeOutdated() ?? []).filter((entry) => entry?.status === "outdated");
|
|
965
|
+
if (outdated.length > 0) {
|
|
966
|
+
const pairs = outdated.map((entry) => `${entry.name}/${entry.platform}`).join(", ");
|
|
967
|
+
process.stdout.write(
|
|
968
|
+
`[enact-extensions] ${outdated.length} plugin surface${outdated.length === 1 ? "" : "s"} outdated: ${pairs}. Run: enact-extensions update --all\n`,
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
} catch {
|
|
972
|
+
// Fail-silent for session-start hooks.
|
|
973
|
+
}
|
|
974
|
+
process.exit(0);
|
|
975
|
+
}
|
|
976
|
+
|
|
830
977
|
// Read stdin to get the hook payload JSON.
|
|
831
978
|
let payload;
|
|
832
979
|
try {
|