@amsterdamdatalabs/enact-extensions 0.1.12 → 0.1.25

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 (148) hide show
  1. package/README.md +11 -12
  2. package/dist/create/enact.js +1 -1
  3. package/dist/create/enact.js.map +1 -1
  4. package/dist/create/index.d.ts +4 -3
  5. package/dist/create/index.d.ts.map +1 -1
  6. package/dist/create/index.js +9 -2
  7. package/dist/create/index.js.map +1 -1
  8. package/dist/index.d.ts +8 -6
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +4 -3
  11. package/dist/index.js.map +1 -1
  12. package/dist/install.d.ts +5 -0
  13. package/dist/install.d.ts.map +1 -1
  14. package/dist/install.js +10 -3
  15. package/dist/install.js.map +1 -1
  16. package/dist/internal/agents.d.ts +6 -1
  17. package/dist/internal/agents.d.ts.map +1 -1
  18. package/dist/internal/agents.js +8 -4
  19. package/dist/internal/agents.js.map +1 -1
  20. package/dist/internal/claude.d.ts +24 -0
  21. package/dist/internal/claude.d.ts.map +1 -1
  22. package/dist/internal/claude.js +99 -0
  23. package/dist/internal/claude.js.map +1 -1
  24. package/dist/internal/platform.d.ts +3 -1
  25. package/dist/internal/platform.d.ts.map +1 -1
  26. package/dist/internal/platform.js +7 -1
  27. package/dist/internal/platform.js.map +1 -1
  28. package/dist/internal/types.d.ts +2 -1
  29. package/dist/internal/types.d.ts.map +1 -1
  30. package/dist/principles.d.ts +28 -0
  31. package/dist/principles.d.ts.map +1 -0
  32. package/dist/principles.js +159 -0
  33. package/dist/principles.js.map +1 -0
  34. package/extensions/dev-state/.agents/plugin.json +2 -1
  35. package/extensions/enact-context/.agents/plugin.json +2 -1
  36. package/extensions/enact-context/hooks/hooks.json +0 -10
  37. package/extensions/enact-context/skills/enact-context/SKILL.md +14 -12
  38. package/extensions/enact-context/skills/enact-context/scripts/install.sh +7 -7
  39. package/extensions/enact-core/.agents/plugin.json +2 -1
  40. package/extensions/enact-core/OPERATING-PRINCIPLES.md +7 -0
  41. package/extensions/enact-core/hooks/hooks.json +12 -0
  42. package/extensions/enact-evolve/.agents/plugin.json +47 -0
  43. package/extensions/enact-evolve/agents/evolve-session-analyst.toml +37 -0
  44. package/extensions/enact-evolve/skills/session-analysis/SKILL.md +98 -0
  45. package/extensions/enact-evolve/skills/session-analysis/scripts/run-evolve-analysis.sh +343 -0
  46. package/extensions/enact-factory/.agents/plugin.json +2 -2
  47. package/extensions/enact-factory/agents/architect.toml +9 -5
  48. package/extensions/enact-factory/agents/code-reviewer.toml +9 -5
  49. package/extensions/enact-factory/agents/critic.toml +9 -5
  50. package/extensions/enact-factory/agents/executor.toml +4 -1
  51. package/extensions/enact-factory/agents/explore.toml +4 -1
  52. package/extensions/enact-factory/agents/planner.toml +4 -1
  53. package/extensions/enact-factory/agents/verifier.toml +9 -5
  54. package/extensions/enact-factory/skills/advisor/SKILL.md +82 -0
  55. package/extensions/enact-factory/skills/ai-slop-cleaner/SKILL.md +6 -1
  56. package/extensions/enact-factory/skills/autonomous-runner/SKILL.md +347 -0
  57. package/extensions/enact-factory/skills/azdo-ci-strategy/SKILL.md +42 -15
  58. package/extensions/enact-factory/skills/committee/SKILL.md +80 -0
  59. package/extensions/enact-factory/skills/deep-interview/SKILL.md +9 -13
  60. package/extensions/enact-factory/skills/drive-loop/SKILL.md +161 -31
  61. package/extensions/enact-factory/skills/drive-loop/references/contract-schema.md +26 -6
  62. package/extensions/enact-factory/skills/handoff/SKILL.md +72 -0
  63. package/extensions/enact-factory/skills/hyperplan/SKILL.md +11 -3
  64. package/extensions/enact-factory/skills/looplan/SKILL.md +34 -17
  65. package/extensions/enact-factory/skills/plan/SKILL.md +40 -8
  66. package/extensions/enact-factory/skills/remove-deadcode/SKILL.md +6 -1
  67. package/extensions/enact-factory/skills/research/SKILL.md +14 -4
  68. package/extensions/enact-factory/skills/review/SKILL.md +21 -2
  69. package/extensions/enact-factory/skills/security-research/SKILL.md +5 -2
  70. package/extensions/enact-factory/skills/tdd/SKILL.md +7 -1
  71. package/extensions/enact-factory/skills/testing-strategy/SKILL.md +5 -0
  72. package/extensions/enact-factory/skills/trace/SKILL.md +5 -0
  73. package/extensions/enact-factory/skills/ultraqa/SKILL.md +21 -15
  74. package/extensions/enact-factory/skills/work-with-workitem/SKILL.md +5 -0
  75. package/extensions/enact-factory/skills/workitem-triage/SKILL.md +5 -0
  76. package/extensions/enact-loop/.agents/plugin.json +5 -4
  77. package/extensions/enact-loop/scripts/validate.mjs +123 -0
  78. package/extensions/enact-loop/skills/enact-loop/SKILL.md +189 -30
  79. package/extensions/enact-wiki/.agents/plugin.json +2 -1
  80. package/extensions/net-revenue-management/.agents/plugin.json +2 -1
  81. package/extensions/plugin-dev/.agents/plugin.json +2 -1
  82. package/extensions/plugin-dev/skills/start/SKILL.md +3 -3
  83. package/package.json +1 -1
  84. package/scripts/check-hooks.mjs +5 -5
  85. package/scripts/check-principles.mjs +19 -4
  86. package/scripts/enact-extensions.mjs +237 -90
  87. package/scripts/lib/hooks.mjs +61 -217
  88. package/scripts/lib/migrate-artifacts.mjs +144 -0
  89. package/scripts/lib/principles.mjs +109 -0
  90. package/scripts/lib/provision-mcp.mjs +1 -1
  91. package/scripts/lib/run-install.mjs +72 -2
  92. package/scripts/lib/run-prune.mjs +23 -2
  93. package/scripts/lib/run-sync.mjs +4 -1
  94. package/scripts/postinstall.mjs +6 -6
  95. package/scripts/setup-enact-context.sh +20 -15
  96. package/scripts/version-bump.sh +22 -1
  97. package/spec/codex.json +5 -0
  98. package/spec/enact.json +3 -3
  99. package/spec/enact.md +1 -4
  100. package/spec/index.json +1 -1
  101. package/extensions/enact-factory/hooks/hooks.json +0 -14
  102. package/extensions/enact-operator/.agents/plugin.json +0 -56
  103. package/extensions/enact-operator/.app.json +0 -3
  104. package/extensions/enact-operator/.mcp.json +0 -10
  105. package/extensions/enact-operator/_taxonomy.md +0 -86
  106. package/extensions/enact-operator/agents/README.md +0 -5
  107. package/extensions/enact-operator/agents/architect.toml +0 -25
  108. package/extensions/enact-operator/agents/code-reviewer.toml +0 -24
  109. package/extensions/enact-operator/agents/critic.toml +0 -30
  110. package/extensions/enact-operator/agents/executor.toml +0 -24
  111. package/extensions/enact-operator/agents/explore.toml +0 -23
  112. package/extensions/enact-operator/agents/planner.toml +0 -24
  113. package/extensions/enact-operator/agents/verifier.toml +0 -24
  114. package/extensions/enact-operator/docs/skill-variants.md +0 -44
  115. package/extensions/enact-operator/hooks/hooks.json +0 -91
  116. package/extensions/enact-operator/skills/ai-slop-cleaner/SKILL.md +0 -50
  117. package/extensions/enact-operator/skills/analyze/SKILL.md +0 -91
  118. package/extensions/enact-operator/skills/ask/SKILL.md +0 -47
  119. package/extensions/enact-operator/skills/autopilot/SKILL.md +0 -170
  120. package/extensions/enact-operator/skills/autoresearch-goal/SKILL.md +0 -79
  121. package/extensions/enact-operator/skills/cancel/SKILL.md +0 -99
  122. package/extensions/enact-operator/skills/configure-notifications/SKILL.md +0 -77
  123. package/extensions/enact-operator/skills/deep-interview/SKILL.md +0 -80
  124. package/extensions/enact-operator/skills/doctor/SKILL.md +0 -48
  125. package/extensions/enact-operator/skills/hud/SKILL.md +0 -49
  126. package/extensions/enact-operator/skills/hyperplan/SKILL.md +0 -47
  127. package/extensions/enact-operator/skills/plan/SKILL.md +0 -78
  128. package/extensions/enact-operator/skills/ralph/SKILL.md +0 -201
  129. package/extensions/enact-operator/skills/ralph/gemini.md +0 -18
  130. package/extensions/enact-operator/skills/ralplan/SKILL.md +0 -151
  131. package/extensions/enact-operator/skills/remove-deadcode/SKILL.md +0 -45
  132. package/extensions/enact-operator/skills/research/SKILL.md +0 -74
  133. package/extensions/enact-operator/skills/review/SKILL.md +0 -58
  134. package/extensions/enact-operator/skills/security-research/SKILL.md +0 -54
  135. package/extensions/enact-operator/skills/setup/SKILL.md +0 -91
  136. package/extensions/enact-operator/skills/setup/scripts/install.sh +0 -50
  137. package/extensions/enact-operator/skills/skill/SKILL.md +0 -82
  138. package/extensions/enact-operator/skills/tdd/SKILL.md +0 -59
  139. package/extensions/enact-operator/skills/team/SKILL.md +0 -199
  140. package/extensions/enact-operator/skills/trace/SKILL.md +0 -41
  141. package/extensions/enact-operator/skills/ultragoal/SKILL.md +0 -99
  142. package/extensions/enact-operator/skills/ultraqa/SKILL.md +0 -113
  143. package/extensions/enact-operator/skills/ultrawork/SKILL.md +0 -145
  144. package/extensions/enact-operator/skills/ultrawork/planner.md +0 -28
  145. package/extensions/enact-operator/skills/wiki/SKILL.md +0 -41
  146. package/extensions/enact-operator/skills/work-with-workitem/SKILL.md +0 -51
  147. /package/extensions/{enact-operator → enact-evolve}/assets/icon.png +0 -0
  148. /package/extensions/{enact-operator → enact-evolve}/assets/logo.png +0 -0
@@ -2,6 +2,7 @@ import { dirname, join } from "node:path";
2
2
  import { homedir } from "node:os";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import {
5
+ activateClaudePlugin,
5
6
  installPluginBundle,
6
7
  installClaudePluginBundle,
7
8
  installCursorPluginBundle,
@@ -13,7 +14,7 @@ import {
13
14
  import { appendEntry } from "./ledger.mjs";
14
15
  import { bundleHash } from "./bundle-hash.mjs";
15
16
  import { provisionMcp, summarizeProvision } from "./provision-mcp.mjs";
16
- import { registerPluginHooks, removePluginHooks } from "./hooks.mjs";
17
+ import { registerPluginHooks, removeHook, removePluginHooks } from "./hooks.mjs";
17
18
  import { assertSupportedHookEvents } from "../../dist/index.js";
18
19
 
19
20
  // scope: "global" (default) -> the agent's default home (~/.codex, ~/.enact/agent, ~/.claude, ~/.cursor, ~/.agents)
@@ -198,6 +199,33 @@ function readJsonIfExists(path) {
198
199
  }
199
200
  }
200
201
 
202
+ function readCanonicalManifest(pluginRoot) {
203
+ return readJsonIfExists(join(pluginRoot, ".agents", "plugin.json"));
204
+ }
205
+
206
+ function supportedHostSurfaces(pluginRoot) {
207
+ const manifest = readCanonicalManifest(pluginRoot);
208
+ const rawTargets = manifest?.targets;
209
+ if (!Array.isArray(rawTargets)) return [...ALL_PLATFORMS];
210
+ return rawTargets.filter((target) => ALL_PLATFORMS.includes(target));
211
+ }
212
+
213
+ function assertRequestedPlatformsSupported(pluginRoot, requestedPlatforms) {
214
+ const supported = supportedHostSurfaces(pluginRoot);
215
+ const unsupported = requestedPlatforms.filter(
216
+ (platform) => ALL_PLATFORMS.includes(platform) && !supported.includes(platform),
217
+ );
218
+ if (unsupported.length === 0) return;
219
+
220
+ const manifest = readCanonicalManifest(pluginRoot);
221
+ const pluginName = typeof manifest?.name === "string" ? manifest.name : pluginRoot.split("/").pop();
222
+ const supportedLabel = supported.length > 0 ? supported.join(", ") : "(none)";
223
+ throw new Error(
224
+ `Plugin ${pluginName} does not target host surface(s): ${unsupported.join(", ")}. ` +
225
+ `Supported host surfaces: ${supportedLabel}`,
226
+ );
227
+ }
228
+
201
229
  function readPluginHookConfig(pluginRoot) {
202
230
  const manifest = readJsonIfExists(join(pluginRoot, ".agents", "plugin.json"));
203
231
  const hooksPath = typeof manifest?.hooks === "string" ? manifest.hooks : null;
@@ -206,9 +234,16 @@ function readPluginHookConfig(pluginRoot) {
206
234
  return readJsonIfExists(join(pluginRoot, normalized));
207
235
  }
208
236
 
237
+ function hookConfigHasEntries(hookConfig) {
238
+ const hooks = hookConfig?.hooks;
239
+ if (!hooks || typeof hooks !== "object" || Array.isArray(hooks)) return false;
240
+ return Object.values(hooks).some((entries) => Array.isArray(entries) && entries.length > 0);
241
+ }
242
+
209
243
  function registerInstalledPluginHooks(pluginRoot, platform, result, homes, options) {
210
244
  // codex reads hooks from the installed plugin bundle (no config.toml
211
- // registration); cursor likewise. claude/enact register into their config.
245
+ // registration); cursor likewise. claude/enact stay in the reconcile path
246
+ // only so removePluginHooks can clean legacy scattered runtime hooks.
212
247
  if (!["claude", "cursor", "enact"].includes(platform)) return;
213
248
  const hookConfig = readPluginHookConfig(pluginRoot);
214
249
  const name = result?.name ?? result?.results?.[0]?.name;
@@ -235,6 +270,20 @@ function registerInstalledPluginHooks(pluginRoot, platform, result, homes, optio
235
270
  }
236
271
  }
237
272
 
273
+ function activateInstalledClaudePlugin(pluginRoot, result, homes, options) {
274
+ const hookConfig = readPluginHookConfig(pluginRoot);
275
+ if (!hookConfigHasEntries(hookConfig)) return;
276
+ const pluginId = `${result.name}@${result.marketplaceName ?? (options.marketplaceName ?? "enact-os-plugins")}`;
277
+ const activation = activateClaudePlugin(
278
+ homes.claudeHome,
279
+ pluginId,
280
+ result.marketplaceDir,
281
+ homes.scope,
282
+ options.claudeExec,
283
+ );
284
+ console.log(`claude plugin ${activation.action} -> ${pluginId}`);
285
+ }
286
+
238
287
  function removeLegacyCodexPluginHooks(name, result, homes, options) {
239
288
  if (!name) return;
240
289
 
@@ -261,6 +310,21 @@ function removeLegacyCodexPluginHooks(name, result, homes, options) {
261
310
  }
262
311
  }
263
312
 
313
+ function removeLegacyStandaloneDriftHook(platform, name, homes, options) {
314
+ if (name !== "enact-core") return;
315
+ const hookResult = removeHook(platform, {
316
+ claudeHome: homes.claudeHome,
317
+ codexHome: homes.codexHome,
318
+ cursorHome: homes.cursorHome,
319
+ enactHome: homes.enactHome,
320
+ local: homes.scope === "local",
321
+ cwd: options.cwd ?? process.cwd(),
322
+ });
323
+ if (hookResult.result === "removed") {
324
+ console.log(`removed legacy drift hook for ${name} on ${platform} -> ${hookResult.location}`);
325
+ }
326
+ }
327
+
264
328
  // Append one install entry per installed target in a single-platform result.
265
329
  // Tolerant of every result shape (single platform, shared, codex multi-home).
266
330
  // `hash` is the pre-computed bundle hash (or null) for this install invocation.
@@ -318,6 +382,10 @@ function runSinglePlatform(pluginRoot, platform, homes, options, hash) {
318
382
  target.log(result);
319
383
  recordInstall(platform, result, homes, options, hash);
320
384
  registerInstalledPluginHooks(pluginRoot, platform, result, homes, options);
385
+ removeLegacyStandaloneDriftHook(platform, result?.name, homes, options);
386
+ if (platform === "claude") {
387
+ activateInstalledClaudePlugin(pluginRoot, result, homes, options);
388
+ }
321
389
  return result;
322
390
  }
323
391
 
@@ -337,6 +405,7 @@ function runSinglePlatform(pluginRoot, platform, homes, options, hash) {
337
405
  }
338
406
  recordInstall("codex", result, homes, options, hash);
339
407
  removeLegacyCodexPluginHooks(result.results[0]?.name, result, homes, options);
408
+ removeLegacyStandaloneDriftHook("codex", result.results[0]?.name, homes, options);
340
409
  return result;
341
410
  }
342
411
 
@@ -375,6 +444,7 @@ export function runInstall(pluginRoot, options = {}) {
375
444
  assertSupportedHookEvents(pluginRoot);
376
445
 
377
446
  const platforms = parsePlatforms(options.platform);
447
+ assertRequestedPlatformsSupported(pluginRoot, platforms);
378
448
  const homes = resolveHomes(options);
379
449
  console.log(`install scope: ${homes.scope}${homes.scope === "local" ? ` (${process.cwd()})` : ""}`);
380
450
 
@@ -3,7 +3,7 @@ import { homedir } from "node:os";
3
3
  import { cwd as processCwd } from "node:process";
4
4
  import { dirname, join, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
- import { listInstalled } from "./ledger.mjs";
6
+ import { appendEntry, listInstalled } from "./ledger.mjs";
7
7
  import { parsePlatforms, runUninstall } from "./run-uninstall.mjs";
8
8
 
9
9
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -21,6 +21,10 @@ function sourceBundleExists(name, sourceRoots) {
21
21
  return sourceRoots.some((root) => existsSync(join(root, name, ".agents", "plugin.json")));
22
22
  }
23
23
 
24
+ function installedSurfaceExists(entry) {
25
+ return Boolean(entry.path) && existsSync(entry.path);
26
+ }
27
+
24
28
  function homeOptionForPlatform(platform) {
25
29
  switch (platform) {
26
30
  case "codex": return "codexHome";
@@ -32,6 +36,22 @@ function homeOptionForPlatform(platform) {
32
36
  }
33
37
  }
34
38
 
39
+ function recordPruneTombstone(entry, ledgerHome, marketplaceName) {
40
+ appendEntry(
41
+ {
42
+ action: "uninstall",
43
+ name: entry.name,
44
+ version: entry.version ?? "0.0.0",
45
+ platform: entry.platform,
46
+ scope: entry.scope,
47
+ home: entry.home,
48
+ path: entry.path,
49
+ marketplaceName: entry.marketplaceName ?? marketplaceName,
50
+ },
51
+ { home: ledgerHome },
52
+ );
53
+ }
54
+
35
55
  export function runPrune(options = {}) {
36
56
  const cwd = options.cwd ?? processCwd();
37
57
  const ledgerHome = options.ledgerHome ?? options.home ?? homedir();
@@ -43,7 +63,7 @@ export function runPrune(options = {}) {
43
63
  const candidates = installed
44
64
  .filter((entry) => platforms.has(entry.platform))
45
65
  .filter((entry) => entry.marketplaceName === marketplaceName)
46
- .filter((entry) => !sourceBundleExists(entry.name, sourceRoots));
66
+ .filter((entry) => !sourceBundleExists(entry.name, sourceRoots) || !installedSurfaceExists(entry));
47
67
 
48
68
  const pruned = [];
49
69
  const failed = [];
@@ -63,6 +83,7 @@ export function runPrune(options = {}) {
63
83
  ledgerHome,
64
84
  version: entry.version,
65
85
  });
86
+ recordPruneTombstone(entry, ledgerHome, marketplaceName);
66
87
  pruned.push(entry);
67
88
  } catch (err) {
68
89
  failed.push({ entry, error: err instanceof Error ? err : new Error(String(err)) });
@@ -26,7 +26,10 @@ export function runSync(pluginRoot, { name } = {}) {
26
26
 
27
27
  const results = syncPlatformManifests(pluginRoot, enact);
28
28
  for (const r of results) {
29
- console.log(`${r.written ? "wrote" : "skip"} ${r.manifestPath}`);
29
+ const generatedProjectionNote = /(^|\/)\.(claude|codex|cursor)-plugin\//.test(r.manifestPath)
30
+ ? " (generated preview only; normal install uses enact-extensions install)"
31
+ : "";
32
+ console.log(`${r.written ? "wrote" : "skip"} ${r.manifestPath}${generatedProjectionNote}`);
30
33
  }
31
34
  return results;
32
35
  }
@@ -6,7 +6,7 @@
6
6
  * - If NOT a TTY → print one-line notice and exit 0. NEVER hang.
7
7
  * - If CI env var is set → print one-line notice and exit 0.
8
8
  * - If ENACT_EXTENSIONS_NO_POSTINSTALL is set → print one-line notice and exit 0.
9
- * - If interactive TTY (and not CI) → run `hooks setup` interactive picker.
9
+ * - If interactive TTY (and not CI) → install `enact-core` across host surfaces.
10
10
  * - Entire script is wrapped in try/catch → ALWAYS process.exit(0).
11
11
  * A postinstall that throws would break `npm ci` in CI.
12
12
  *
@@ -14,7 +14,7 @@
14
14
  * - Docker CI environments (CI=1, no TTY)
15
15
  * - npm ci / npm install in CI pipelines
16
16
  * - Automated install tooling (pipes, scripts)
17
- * - Developer machines with interactive TTY (triggers the interactive picker)
17
+ * - Developer machines with interactive TTY (triggers enact-core install)
18
18
  */
19
19
 
20
20
  try {
@@ -24,7 +24,7 @@ try {
24
24
  const isNoPostinstall = !!(env.ENACT_EXTENSIONS_NO_POSTINSTALL);
25
25
  const isTTY = !!(stdin.isTTY);
26
26
 
27
- const NOTICE = `Run \`enact-extensions hooks setup\` to enable session-start drift checks.\n`;
27
+ const NOTICE = `Run \`enact-extensions install enact-core --platform all\` to enable session-start drift checks.\n`;
28
28
 
29
29
  if (!isTTY || isCI || isNoPostinstall) {
30
30
  // Non-interactive or CI: print notice and exit immediately.
@@ -32,7 +32,7 @@ try {
32
32
  process.exit(0);
33
33
  }
34
34
 
35
- // Interactive TTY (non-CI): run the hooks setup interactive picker via CLI.
35
+ // Interactive TTY (non-CI): install enact-core, which now owns SessionStart.
36
36
  // We spawn a child process rather than importing directly to keep postinstall
37
37
  // isolated from any import-time side-effects in the CLI modules.
38
38
  const { spawnSync } = await import("node:child_process");
@@ -44,7 +44,7 @@ try {
44
44
 
45
45
  // Spawn with stdio inherited so the interactive readline prompt is visible.
46
46
  // We spawn and ignore the exit code — postinstall must always exit 0.
47
- spawnSync(process.execPath, [CLI, "hooks", "setup"], {
47
+ spawnSync(process.execPath, [CLI, "install", "enact-core", "--platform", "all"], {
48
48
  stdio: "inherit",
49
49
  env: { ...process.env },
50
50
  });
@@ -54,7 +54,7 @@ try {
54
54
  // Printing to stderr is best-effort (safe to fail).
55
55
  try {
56
56
  process.stderr.write(
57
- "[enact-extensions postinstall] Non-fatal error during hook setup. Run `enact-extensions hooks setup` manually.\n",
57
+ "[enact-extensions postinstall] Non-fatal error during enact-core install. Run `enact-extensions install enact-core --platform all` manually.\n",
58
58
  );
59
59
  } catch {
60
60
  // Even stderr.write failed — just exit 0.
@@ -1,23 +1,28 @@
1
1
  #!/usr/bin/env bash
2
- # Wire enact-context setup into the enact-extensions workspace.
3
- # Validates the plugin-dev bundle then runs consolidated agent setup.
2
+ # Install enact-context through the enact-extensions plugin system.
3
+ #
4
+ # This intentionally does NOT run `enact-context setup` or `doctor --fix`.
5
+ # Those commands write direct host artifacts such as ~/.codex/AGENTS.md,
6
+ # ~/.codex/hooks.json, and ~/.codex/skills/enact-context, bypassing plugin
7
+ # enable/disable and uninstall semantics.
4
8
  set -euo pipefail
5
9
 
6
10
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
7
- REPO_ROOT="$(cd "$ROOT/.." && pwd)"
8
-
9
- if ! command -v enact-context >/dev/null 2>&1; then
10
- if [[ -x "$REPO_ROOT/enact-context/rust/target/release/enact-context" ]]; then
11
- export PATH="$REPO_ROOT/enact-context/rust/target/release:$PATH"
12
- else
13
- echo "enact-context binary not found on PATH" >&2
14
- exit 1
15
- fi
16
- fi
17
11
 
18
12
  cd "$ROOT"
19
- npm run validate
13
+ npm run build
14
+ node scripts/enact-extensions.mjs validate extensions/enact-context
20
15
 
21
16
  echo ""
22
- echo "Running enact-context setup (claude, codex, opencode, enact, zed)..."
23
- enact-context setup "$@"
17
+ echo "Installing enact-context via enact-extensions plugin registration..."
18
+ if [[ " $* " == *" --platform "* ]]; then
19
+ node scripts/enact-extensions.mjs install enact-context "$@"
20
+ else
21
+ node scripts/enact-extensions.mjs install enact-context --platform "${ENACT_CONTEXT_PLATFORM:-codex}" "$@"
22
+ fi
23
+
24
+ if ! command -v enact-context >/dev/null 2>&1; then
25
+ echo ""
26
+ echo "Note: enact-context runtime binary is not on PATH."
27
+ echo "Install the runtime separately; do not use 'enact-context setup' for Codex registration."
28
+ fi
@@ -52,6 +52,7 @@ CURRENT_BRANCH=""
52
52
  INTEGRATION_BRANCH="integration"
53
53
  DRY_RUN=false
54
54
  DO_PUSH=false
55
+ INTEGRATION_MODE=false
55
56
 
56
57
  # ─────────────────────────────────────────────────────────────────────────────
57
58
  usage() {
@@ -121,6 +122,7 @@ parse_args() {
121
122
  -f|--file) VERSION_FILE="${2:?'--file requires a path'}"; file_given=true; shift 2 ;;
122
123
  -b|--branch) INTEGRATION_BRANCH="${2:?'--branch requires a name'}"; shift 2 ;;
123
124
  --push) DO_PUSH=true; shift ;;
125
+ --integration) INTEGRATION_MODE=true; shift ;;
124
126
  -n|--dry-run) DRY_RUN=true; shift ;;
125
127
  -h|--help) usage ;;
126
128
  *) die "Unknown option: '$1'. Run with --help." ;;
@@ -354,6 +356,19 @@ validate_branch() {
354
356
  info "Detached HEAD — branch from env: ${branch}"
355
357
  fi
356
358
 
359
+ # Integration mode: the bump runs on the integration build AFTER a PR merges
360
+ # and pushes the bump commit directly back to integration (the build service
361
+ # has "bypass policies when pushing"). The ***NO_CI*** commit message stops it
362
+ # from re-triggering. This avoids the pre-merge feature-branch bump that
363
+ # re-validated the PR (double pipeline run).
364
+ if $INTEGRATION_MODE; then
365
+ [[ "$branch" == "$INTEGRATION_BRANCH" ]] || \
366
+ die "Integration mode expects branch '${INTEGRATION_BRANCH}', currently on '${branch}'."
367
+ ok "On integration branch '${branch}' (integration mode — bump pushes directly)."
368
+ CURRENT_BRANCH="$branch"
369
+ return
370
+ fi
371
+
357
372
  [[ "$branch" =~ ^(feat|fix)/ ]] || \
358
373
  die "Expected a feat/* or fix/* branch, currently on '${branch}'. Version bump runs on feature branches before PR merge."
359
374
 
@@ -432,7 +447,13 @@ main() {
432
447
  parse_args "$@"
433
448
  resolve_manifest
434
449
  validate_branch
435
- validate_version_unchanged # exits 0 silently if version was manually bumped
450
+ if $INTEGRATION_MODE; then
451
+ # On integration we bump once per merge; the manual-bump guard (compare vs
452
+ # origin/integration) does not apply on integration itself.
453
+ CURRENT_VERSION="$(get_version)" || die "Cannot read current version from manifest."
454
+ else
455
+ validate_version_unchanged # exits 0 silently if version was manually bumped
456
+ fi
436
457
 
437
458
  local new_version
438
459
  new_version="$(bump_patch "$CURRENT_VERSION")"
package/spec/codex.json CHANGED
@@ -69,6 +69,11 @@
69
69
  "description": "Relative path to the skills directory.",
70
70
  "default": "./skills/"
71
71
  },
72
+ "agents": {
73
+ "type": "string",
74
+ "description": "Relative path to the canonical TOML agents directory.",
75
+ "default": "./agents/"
76
+ },
72
77
  "mcpServers": {
73
78
  "type": "string",
74
79
  "description": "Relative path to the .mcp.json MCP server configuration file.",
package/spec/enact.json CHANGED
@@ -52,13 +52,13 @@
52
52
  },
53
53
  "targets": {
54
54
  "type": "array",
55
- "description": "Agent platforms this plugin is built for. Drives platform-specific manifest generation.",
55
+ "description": "Supported install surfaces for this plugin. The canonical .agents/plugin.json is the Enact surface; claude/codex/cursor are derived projections.",
56
56
  "items": {
57
57
  "type": "string",
58
- "enum": ["claude", "codex", "cursor"]
58
+ "enum": ["claude", "codex", "cursor", "enact"]
59
59
  },
60
60
  "uniqueItems": true,
61
- "minItems": 1
61
+ "minItems": 0
62
62
  },
63
63
  "skills": {
64
64
  "type": "string",
package/spec/enact.md CHANGED
@@ -10,14 +10,13 @@ Extend what Enact can do, for example:
10
10
  - Install the enact-context plugin to give agents deep code intelligence and semantic search.
11
11
  - Install the enact-wiki plugin to persist knowledge across sessions and projects.
12
12
  - Install the enact-loop plugin to run durable contract-verified work with independent judgment grading.
13
- - Install the enact-operator plugin for the full operator surface (team orchestration, HUD, doctor, and oversight tools).
14
13
 
15
14
  A plugin can contain:
16
15
 
17
16
  - **Skills:** reusable instructions for specific kinds of work. Agents load
18
17
  them on demand so they follow the right steps and use the right references
19
18
  or helper scripts for a task.
20
- - **Slash commands:** named commands invoked directly by the user (e.g. `/enact-operator:setup`)
19
+ - **Slash commands:** named commands invoked directly by the user (e.g. `/plugin-name:command-name`)
21
20
  to trigger specific workflows without relying on automatic skill selection.
22
21
  - **MCP servers:** services that give agents access to additional tools or
23
22
  shared information, often from systems outside the local project.
@@ -90,8 +89,6 @@ If you want to keep a plugin installed but turn it off, set its entry in
90
89
  enabled = false
91
90
  ```
92
91
 
93
- > **Note:** enact-operator is also available in the registry for teams that need the full operator surface (HUD, doctor, team orchestration, oversight). enact-loop is the recommended default for contract-verified loop work.
94
-
95
92
  ## Build your own plugin
96
93
 
97
94
  Plugins live in a directory containing an `.agents/` folder with a `plugin.json`
package/spec/index.json CHANGED
@@ -46,7 +46,7 @@
46
46
  "targets": {
47
47
  "type": "array",
48
48
  "items": { "type": "string" },
49
- "description": "Agent platforms this plugin targets (e.g. claude, codex, cursor)."
49
+ "description": "Supported host surfaces for this plugin (e.g. claude, codex, cursor, enact)."
50
50
  },
51
51
  "path": {
52
52
  "type": "string",
@@ -1,14 +0,0 @@
1
- {
2
- "hooks": {
3
- "UserPromptSubmit": [
4
- {
5
- "hooks": [
6
- {
7
- "type": "command",
8
- "command": "enact-factory hook user-prompt-submit"
9
- }
10
- ]
11
- }
12
- ]
13
- }
14
- }
@@ -1,56 +0,0 @@
1
- {
2
- "name": "enact-operator",
3
- "version": "0.1.0",
4
- "description": "First-party Enact Operator plugin surfaces for skills, commands, agents, MCP, and runtime hook registrations.",
5
- "author": {
6
- "name": "amsterdamdatalabs"
7
- },
8
- "homepage": "https://amsterdamdatalabs.com",
9
- "repository": "https://dev.azure.com/amsterdamdatalabs/Enact/_git/enact-operator",
10
- "license": "UNLICENSED",
11
- "keywords": [
12
- "enact",
13
- "operator",
14
- "orchestration",
15
- "workflow"
16
- ],
17
- "targets": [
18
- "claude",
19
- "codex",
20
- "cursor"
21
- ],
22
- "skills": "./skills/",
23
- "agents": "./agents/",
24
- "mcpServers": "./.mcp.json",
25
- "apps": "./.app.json",
26
- "interface": {
27
- "displayName": "Enact Operator",
28
- "shortDescription": "Installable surfaces for Enact Operator workflows.",
29
- "longDescription": "Bundles the operator-owned Enact catalog. enact-extensions owns install, registration, hook wiring, enable/disable, status, and uninstall. Hook registrations call stable enact-operator runtime commands such as enact-operator hook user-prompt-submit; hook implementations stay in the enact-operator package.",
30
- "developerName": "enact-operator",
31
- "category": "Developer Tools",
32
- "composerIcon": "./assets/icon.png",
33
- "logo": "./assets/logo.png",
34
- "capabilities": [
35
- "skills",
36
- "slash commands",
37
- "operator workflows",
38
- "team orchestration",
39
- "operator setup",
40
- "doctor and readiness audits",
41
- "plan and execution workflows",
42
- "review and QA workflows",
43
- "federated context and memory workflows"
44
- ]
45
- },
46
- "operator": {
47
- "firstParty": true,
48
- "bundledMcpProviders": [
49
- "enact-factory",
50
- "enact-context",
51
- "enact-wiki"
52
- ],
53
- "operatorScope": "project"
54
- },
55
- "hooks": "./hooks/hooks.json"
56
- }
@@ -1,3 +0,0 @@
1
- {
2
- "apps": {}
3
- }
@@ -1,10 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "enact-operator": {
4
- "command": "enact-operator",
5
- "args": [
6
- "mcp"
7
- ]
8
- }
9
- }
10
- }
@@ -1,86 +0,0 @@
1
- # Enact Operator Extension Taxonomy
2
-
3
- `extensions/` has three extension tiers. Each entry belongs to exactly one tier.
4
-
5
- ## Pure skills
6
-
7
- Pure skills live at `extensions/skills/<name>/SKILL.md`.
8
-
9
- - No MCP tool surface
10
- - No persisted lane state
11
- - Prompt/context guidance only
12
-
13
- Current pure skills:
14
-
15
- - `ai-slop-cleaner`
16
- - `analyze`
17
- - `ask`
18
- - `autoresearch-goal`
19
- - `cancel`
20
- - `configure-notifications`
21
- - `deep-interview`
22
- - `doctor`
23
- - `hud`
24
- - `hyperplan`
25
- - `plan`
26
- - `remove-deadcode`
27
- - `research`
28
- - `review`
29
- - `security-research`
30
- - `setup`
31
- - `skill`
32
- - `tdd`
33
- - `trace`
34
- - `wiki`
35
- - `work-with-workitem`
36
-
37
- ## Agents
38
-
39
- Codex subagents live at `extensions/agents/*.toml`.
40
-
41
- - Stateless worker contracts
42
- - Dispatched through Codex subagents
43
- - Installed into the Codex agents directory by setup
44
-
45
- The old exact-name collisions `architect`, `executor`, and `reviewer` were removed from `extensions/skills/` once their Codex agent TOMLs existed. The remaining helper surfaces such as `plan`, `review`, `research`, `trace`, and `analyze` are pure skills, not agent files.
46
-
47
- ## Operator lanes
48
-
49
- Operator lanes remain under `extensions/skills/<name>/SKILL.md`, but they are explicitly tagged with:
50
-
51
- - `lane: true`
52
- - `mcpToolPrefix: operator_<lane>_`
53
-
54
- Lanes add:
55
-
56
- - MCP tool surfaces
57
- - persisted operator state
58
- - runtime lifecycle semantics
59
-
60
- **Classification rule:** an entry is a **root lane** if and only if it has both (a) a durable operator state file under `.enact/operator/state/` AND (b) an `mcpToolPrefix` field in its `SKILL.md` frontmatter. Any entry that satisfies only one criterion, or neither, is a wrapper or continuity overlay, not a root lane.
61
-
62
- ### Root lanes
63
-
64
- Root lanes are the four autonomous runtime execution lanes that the scheduler assigns tasks to. Each has a durable state file and its own `mcpToolPrefix`.
65
-
66
- - `ralph`
67
- - `ultrawork`
68
- - `team`
69
- - `autopilot`
70
-
71
- ### Continuity overlays
72
-
73
- Continuity overlays have an MCP surface and durable state, but serve as multi-session goal artifacts that wrap one or more root lanes rather than acting as independent scheduler candidates.
74
-
75
- - `ultragoal`
76
-
77
- ### Wrappers
78
-
79
- Wrappers delegate execution to a root lane (typically ralph) and carry no independent durable state file of their own.
80
-
81
- - `ralplan`
82
- - `ultraqa`
83
-
84
- ## Disambiguation rule
85
-
86
- No entry may straddle tiers. If a surface needs Codex subagent dispatch, it belongs in `extensions/agents/`. If it needs Operator MCP tools and durable state, it is a lane. Everything else is a pure skill.
@@ -1,5 +0,0 @@
1
- # Enact Operator Agents
2
-
3
- Codex-compatible agent TOMLs live in this directory.
4
-
5
- The taxonomy contract is documented in [`../_taxonomy.md`](../_taxonomy.md). During the active migration, the legacy agent-style skill directories in `../skills/` are the source material for the TOML ports that land here.
@@ -1,25 +0,0 @@
1
- name = "architect"
2
- description = "Architectural review and GO/NO-GO verdict with evidence pointers"
3
- model = "gpt-5.3-codex"
4
- model_reasoning_effort = "high"
5
- sandbox_mode = "danger-full-access"
6
- developer_instructions = """
7
- You are the Enact Operator architect agent.
8
-
9
- Role:
10
- - Read-only architectural reviewer.
11
- - Diagnose root causes from code and docs already on disk.
12
- - Produce a GO or NO-GO verdict with concrete evidence pointers.
13
-
14
- Rules:
15
- - Never edit files.
16
- - Never speculate when you can read the source.
17
- - Cite exact file paths and line references for material claims.
18
- - Call out tradeoffs, not just the favored direction.
19
-
20
- Output contract:
21
- - verdict: GO or NO-GO
22
- - reasons: concise bullet list
23
- - evidencePointers: file references
24
- - tradeoffs: short list
25
- """
@@ -1,24 +0,0 @@
1
- name = "code-reviewer"
2
- description = "Binding code review pass enforcing unconditional approval or actionable findings"
3
- model = "gpt-5.3-codex"
4
- model_reasoning_effort = "high"
5
- sandbox_mode = "danger-full-access"
6
- developer_instructions = """
7
- You are the Enact Operator code-reviewer agent.
8
-
9
- Role:
10
- - Perform the binding review pass after an implementation batch.
11
- - Prioritize correctness, regressions, and missing verification over style.
12
-
13
- Rules:
14
- - Never edit files.
15
- - Review only from the actual diff and surrounding code.
16
- - Every finding must cite a file reference and explain impact.
17
- - If no actionable issues remain, emit the token UNCONDITIONAL_APPROVE.
18
- - Otherwise, return a blocking verdict with the findings ordered by severity.
19
-
20
- Output contract:
21
- - verdict: UNCONDITIONAL_APPROVE or REQUEST_CHANGES
22
- - findings: severity-ordered list with evidence
23
- - residual_risks: optional short list
24
- """