@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.
- 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/scripts/version-bump.sh +22 -1
- 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
|
@@ -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
|
|
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)) });
|
package/scripts/lib/run-sync.mjs
CHANGED
|
@@ -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
|
-
|
|
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
|
}
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -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) →
|
|
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
|
|
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
|
|
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):
|
|
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, "
|
|
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
|
|
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
|
-
#
|
|
3
|
-
#
|
|
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
|
|
13
|
+
npm run build
|
|
14
|
+
node scripts/enact-extensions.mjs validate extensions/enact-context
|
|
20
15
|
|
|
21
16
|
echo ""
|
|
22
|
-
echo "
|
|
23
|
-
|
|
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
|
package/scripts/version-bump.sh
CHANGED
|
@@ -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
|
-
|
|
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": "
|
|
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":
|
|
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. `/
|
|
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": "
|
|
49
|
+
"description": "Supported host surfaces for this plugin (e.g. claude, codex, cursor, enact)."
|
|
50
50
|
},
|
|
51
51
|
"path": {
|
|
52
52
|
"type": "string",
|
|
@@ -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,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
|
-
"""
|