@ludecker/aaac 1.0.0 → 1.1.1

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 (92) hide show
  1. package/README.md +4 -3
  2. package/package.json +13 -1
  3. package/src/cli.mjs +39 -5
  4. package/src/generators/generate-commands.mjs +120 -3
  5. package/src/generators/generate-graph.mjs +17 -0
  6. package/src/lib/install.mjs +1 -0
  7. package/src/lib/run-engine-paths.mjs +33 -0
  8. package/src/run-engine/advance-phase.mjs +343 -0
  9. package/src/run-engine/capability-evidence.mjs +460 -0
  10. package/src/run-engine/debug-run.mjs +38 -0
  11. package/src/run-engine/gate-write.mjs +95 -0
  12. package/src/run-engine/init-run.mjs +215 -0
  13. package/src/run-engine/lib.mjs +141 -0
  14. package/src/run-engine/log-dump.mjs +76 -0
  15. package/src/run-engine/log-trace.mjs +18 -0
  16. package/src/run-engine/log.mjs +343 -0
  17. package/src/run-engine/record-task.mjs +56 -0
  18. package/src/run-engine/stop-check.mjs +55 -0
  19. package/src/run-engine/verify-website-build.mjs +148 -0
  20. package/templates/cursor/aaac/capabilities/promotion-rules.json +64 -0
  21. package/templates/cursor/aaac/capabilities/registry.json +17 -15
  22. package/templates/cursor/aaac/complexity.yaml +98 -0
  23. package/templates/cursor/aaac/contracts/commands/fix-bug.yaml +10 -3
  24. package/templates/cursor/aaac/contracts/commands/fix-module.yaml +41 -0
  25. package/templates/cursor/aaac/contracts/skills/investigation.yaml +22 -1
  26. package/templates/cursor/aaac/contracts/skills/planning.yaml +17 -0
  27. package/templates/cursor/aaac/contracts/skills/validation.yaml +9 -1
  28. package/templates/cursor/aaac/dispatch.md +31 -6
  29. package/templates/cursor/aaac/enforcement.json +25 -0
  30. package/templates/cursor/aaac/fitness-functions.yaml +8 -0
  31. package/templates/cursor/aaac/governance/gates.json +6 -2
  32. package/templates/cursor/aaac/graph.project.yaml +237 -5
  33. package/templates/cursor/aaac/layers.md +6 -1
  34. package/templates/cursor/aaac/lifecycle/lifecycle.json +41 -1
  35. package/templates/cursor/aaac/lifecycle/phases.json +1 -0
  36. package/templates/cursor/aaac/observability/telemetry.yaml +63 -0
  37. package/templates/cursor/aaac/observability/verb-debug.yaml +170 -0
  38. package/templates/cursor/aaac/ontology.json +10 -1
  39. package/templates/cursor/aaac/run/RUN.md +2 -0
  40. package/templates/cursor/aaac/run/schema.json +11 -0
  41. package/templates/cursor/aaac/scripts/generate-runtime-registry.mjs +115 -0
  42. package/templates/cursor/aaac/scripts/run-engine/advance-phase.mjs +343 -0
  43. package/templates/cursor/aaac/scripts/run-engine/capability-evidence.mjs +460 -0
  44. package/templates/cursor/aaac/scripts/run-engine/debug-run.mjs +38 -0
  45. package/templates/cursor/aaac/scripts/run-engine/gate-write.mjs +95 -0
  46. package/templates/cursor/aaac/scripts/run-engine/init-run.mjs +215 -0
  47. package/templates/cursor/aaac/scripts/run-engine/lib.mjs +141 -0
  48. package/templates/cursor/aaac/scripts/run-engine/log-dump.mjs +76 -0
  49. package/templates/cursor/aaac/scripts/run-engine/log-trace.mjs +18 -0
  50. package/templates/cursor/aaac/scripts/run-engine/log.mjs +343 -0
  51. package/templates/cursor/aaac/scripts/run-engine/record-task.mjs +56 -0
  52. package/templates/cursor/aaac/scripts/run-engine/stop-check.mjs +55 -0
  53. package/templates/cursor/aaac/scripts/run-engine/verify-website-build.mjs +148 -0
  54. package/templates/cursor/aaac/state/capability-stats.json +5 -0
  55. package/templates/cursor/agents/aaac-log-debug.md +72 -0
  56. package/templates/cursor/agents/fix-code-path.md +27 -0
  57. package/templates/cursor/agents/fix-hypothesis-validate.md +26 -0
  58. package/templates/cursor/agents/fix-inventory-confirm.md +22 -0
  59. package/templates/cursor/agents/fix-recent-changes.md +22 -0
  60. package/templates/cursor/agents/fix-regression-scope.md +27 -0
  61. package/templates/cursor/agents/fix-repro-verify.md +21 -0
  62. package/templates/cursor/agents/fix-repro.md +29 -0
  63. package/templates/cursor/agents/fix-runtime-evidence.md +22 -0
  64. package/templates/cursor/agents/fix-test-failures.md +23 -0
  65. package/templates/cursor/agents/playwright-check-run.md +44 -0
  66. package/templates/cursor/hooks/aaac-before-submit.sh +3 -0
  67. package/templates/cursor/hooks/aaac-pre-tool.sh +4 -0
  68. package/templates/cursor/hooks/aaac-stop.sh +3 -0
  69. package/templates/cursor/hooks/aaac-subagent-start.sh +3 -0
  70. package/templates/cursor/hooks.json +30 -0
  71. package/templates/cursor/policies/minimal-complexity.md +101 -0
  72. package/templates/cursor/rules/aaac-enforcement.mdc +42 -0
  73. package/templates/cursor/skills/shared/execution/SKILL.md +1 -1
  74. package/templates/cursor/skills/shared/fitness-functions/SKILL.md +23 -7
  75. package/templates/cursor/skills/shared/investigation/SKILL.md +91 -18
  76. package/templates/cursor/skills/shared/investigation/orchestrator/SKILL.md +12 -4
  77. package/templates/cursor/skills/shared/planning/SKILL.md +74 -8
  78. package/templates/cursor/skills/shared/platform-release/SKILL.md +22 -19
  79. package/templates/cursor/skills/shared/platform-release/orchestrator/contract.yaml +27 -7
  80. package/templates/cursor/skills/shared/reporting/SKILL.md +2 -1
  81. package/templates/cursor/skills/shared/root-cause/SKILL.md +14 -3
  82. package/templates/cursor/skills/shared/testing/SKILL.md +31 -5
  83. package/templates/cursor/skills/shared/validation/SKILL.md +48 -13
  84. package/templates/cursor/skills/shared/verbs/_dispatch-utils.md +20 -1
  85. package/templates/cursor/skills/shared/verbs/_lifecycle.md +3 -2
  86. package/templates/cursor/skills/shared/verbs/check/orchestrator/SKILL.md +4 -1
  87. package/templates/cursor/skills/shared/verbs/create/orchestrator/SKILL.md +2 -2
  88. package/templates/cursor/skills/shared/verbs/fix/orchestrator/SKILL.md +21 -11
  89. package/templates/cursor/skills/shared/verbs/fix/orchestrator/contract.yaml +19 -4
  90. package/templates/cursor/skills/shared/verbs/update/orchestrator/SKILL.md +2 -2
  91. package/templates/cursor/skills/shared/verification/SKILL.md +3 -0
  92. package/templates/docs/agentic_architecture.md +236 -53
package/README.md CHANGED
@@ -24,7 +24,8 @@ npx @ludecker/aaac@latest init --yes --dir /path/to/your/repo
24
24
 
25
25
  ## What you get
26
26
 
27
- - `.cursor/aaac/`ontology, graph, lifecycle, run model, generators config
27
+ - `.cursor/hooks.json`runtime enforcement (enable in Cursor Settings → Hooks)
28
+ - `.cursor/aaac/` — ontology, graph, lifecycle, run model, enforcement
28
29
  - `.cursor/skills/shared/` — full pipeline (discovery → execute → verify → report)
29
30
  - `.cursor/agents/` — 13 generic subagent specs
30
31
  - `.cursor/commands/` — ~130 generated slash commands
@@ -53,8 +54,8 @@ Authenticate with a registry token in `.npmrc` (used by pnpm, not the `npm` CLI)
53
54
 
54
55
  ```bash
55
56
  pnpm --filter @ludecker/aaac publish --access public --no-git-checks
56
- git tag aaac-v1.0.0
57
- git push origin aaac-v1.0.0
57
+ git tag aaac-v1.1.0
58
+ git push origin aaac-v1.1.0
58
59
  ```
59
60
 
60
61
  CI publishes on `aaac-v*` tags via `.github/workflows/publish-aaac.yml` (`NPM_TOKEN` secret).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ludecker/aaac",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Agentic Architecture as Code (AAAC) — installable Cursor agent framework",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,10 +29,22 @@
29
29
  "src/",
30
30
  "templates/"
31
31
  ],
32
+ "devDependencies": {
33
+ "@playwright/test": "^1.52.0",
34
+ "vitest": "^3.2.4",
35
+ "yaml": "^2.8.0"
36
+ },
32
37
  "engines": {
33
38
  "node": ">=18"
34
39
  },
35
40
  "publishConfig": {
36
41
  "access": "public"
42
+ },
43
+ "scripts": {
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "test:node": "node --test tests/log.test.mjs",
47
+ "test:e2e": "pnpm exec playwright test",
48
+ "test:e2e:ui": "pnpm exec playwright test --ui"
37
49
  }
38
50
  }
package/src/cli.mjs CHANGED
@@ -4,6 +4,7 @@ import path from "path";
4
4
  import { parseArgs } from "./lib/paths.mjs";
5
5
  import { installAaac, runGenerators } from "./lib/install.mjs";
6
6
  import { resolveCursorRoot } from "./lib/paths.mjs";
7
+ import { runEngineScript } from "./lib/run-engine-paths.mjs";
7
8
 
8
9
  function printHelp() {
9
10
  console.log(`@ludecker/aaac — Agentic Architecture as Code
@@ -15,7 +16,9 @@ Usage:
15
16
 
16
17
  Commands:
17
18
  init Copy AAAC kernel into .cursor/ and docs/ (default)
18
- generate Regenerate graph.yaml and commands from ontology
19
+ generate Regenerate graph.yaml and commands from ontology
20
+ log-dump Print Run manifest log + decisions
21
+ debug-run One-shot Run status summary
19
22
 
20
23
  Options:
21
24
  --dir <path> Target project directory (default: cwd)
@@ -89,10 +92,11 @@ AAAC installed.
89
92
  docs/ → ${docsDest}
90
93
 
91
94
  Next steps:
92
- 1. Open the project in Cursor
93
- 2. Create ${options.docsRoot}/master_rules.md and ${options.docsRoot}/architecture.md if missing
94
- 3. Try /review-architecture or /check-architecture
95
- 4. Read ${options.docsRoot}/agentic_architecture.md Part 2 for adding domains
95
+ 1. Enable Cursor Hooks (Settings → Hooks) and restart Cursor
96
+ 2. Open the project in Cursor
97
+ 3. Create ${options.docsRoot}/master_rules.md and ${options.docsRoot}/architecture.md if missing
98
+ 4. Try /review-architecture or /check-architecture
99
+ 5. Read ${options.docsRoot}/agentic_architecture.md — Part 2 for adding domains
96
100
 
97
101
  Regenerate after ontology changes:
98
102
  pnpm dlx @ludecker/aaac@latest generate
@@ -108,6 +112,28 @@ function cmdGenerate(args) {
108
112
  console.log("Done.");
109
113
  }
110
114
 
115
+ function cmdLogDump(args, argv) {
116
+ const targetDir = args.dir ? path.resolve(args.dir) : process.cwd();
117
+ const passthrough = argv.filter((a) => a !== "log-dump" && a !== "--dir");
118
+ const runIdx = passthrough.findIndex((a) => !a.startsWith("-"));
119
+ if (runIdx === -1) {
120
+ console.error("Usage: aaac log-dump <run_id> [--level debug] [--format timeline|json|pretty] [--dir <path>]");
121
+ process.exit(1);
122
+ }
123
+ runEngineScript("log-dump.mjs", passthrough.slice(runIdx), targetDir);
124
+ }
125
+
126
+ function cmdDebugRun(args, argv) {
127
+ const targetDir = args.dir ? path.resolve(args.dir) : process.cwd();
128
+ const passthrough = argv.filter((a) => a !== "debug-run" && a !== "--dir");
129
+ const runIdx = passthrough.findIndex((a) => !a.startsWith("-"));
130
+ if (runIdx === -1) {
131
+ console.error("Usage: aaac debug-run <run_id> [--json] [--dir <path>]");
132
+ process.exit(1);
133
+ }
134
+ runEngineScript("debug-run.mjs", passthrough.slice(runIdx), targetDir);
135
+ }
136
+
111
137
  async function main() {
112
138
  const argv = process.argv.slice(2);
113
139
  if (argv.includes("--help") || argv.includes("-h")) {
@@ -126,6 +152,14 @@ async function main() {
126
152
  cmdGenerate(args);
127
153
  return;
128
154
  }
155
+ if (sub === "log-dump") {
156
+ cmdLogDump(args, argv);
157
+ return;
158
+ }
159
+ if (sub === "debug-run") {
160
+ cmdDebugRun(args, argv);
161
+ return;
162
+ }
129
163
 
130
164
  console.error(`Unknown command: ${sub}`);
131
165
  printHelp();
@@ -34,6 +34,105 @@ const invalid = new Set(invalid_pairs.map(([v, o]) => `${v}-${o}`));
34
34
 
35
35
  const KEEP_EXTRA = new Set(projectConfig.manual_commands ?? []);
36
36
 
37
+ const CONTENT_WRITER_CANONICAL = "write-article";
38
+ const FIX_MODULE_CANONICAL = "fix-module";
39
+
40
+ function isFixCommand(cmd, entry) {
41
+ const canonical = entry?.alias ?? cmd;
42
+ return (
43
+ canonical === FIX_MODULE_CANONICAL ||
44
+ canonical === "fix-bug" ||
45
+ cmd === "module-fix" ||
46
+ cmd === "bug-fix"
47
+ );
48
+ }
49
+
50
+ function writeFixCmd(cmd, entry = null) {
51
+ const canonical = entry?.alias ?? cmd;
52
+ const isBug = canonical === "fix-bug" || cmd === "bug-fix";
53
+ const resolver = isBug ? "fix-bug-by-slug" : "fix-domain-by-slug";
54
+ const domainRequired = isBug
55
+ ? "Domain slug **recommended** (`cms`, `ui`, `database`, `aaac`)."
56
+ : "**Domain slug required** (`cms`, `ui`, `database`, `aaac`).";
57
+ const aliasLine =
58
+ cmd !== canonical
59
+ ? `\n\n> Alias → \`/${canonical}\`. See [${canonical}.md](${canonical}.md).\n`
60
+ : isBug
61
+ ? "\n\nAliases: `/bug-fix` → same command.\n"
62
+ : "\n\nAliases: `/module-fix` → same command.\n";
63
+ const body = `# ${cmd}
64
+
65
+ AAAC: \`/${cmd} <domain> "<intent>"\`
66
+
67
+ **Layer:** ${isBug ? "product" : "code"}
68
+ **Repair something broken** a **${isBug ? "bug" : "module"}** — full fix swarm (discovery + 7-agent investigate_swarm + root cause + gates + repro verify).${aliasLine}
69
+
70
+ ## Dispatch
71
+
72
+ 1. [.cursor/aaac/dispatch.md](../aaac/dispatch.md)
73
+ 2. [.cursor/aaac/graph.yaml](../aaac/graph.yaml) — **\`${canonical}\`**
74
+ 3. resolver **\`${resolver}\`** → \`cms-fix-bug\` | \`ui-fix-bug\` | \`database-fix-bug\` | \`aaac-fix-bug\`
75
+ 4. [investigation/SKILL.md](../skills/shared/investigation/SKILL.md) Mode A + domain \`fix_mode\`
76
+
77
+ ${domainRequired}
78
+
79
+ ## Swarm (mandatory)
80
+
81
+ | Phase | Agents | Parallel |
82
+ |-------|--------|----------|
83
+ | discover | discovery-inventory, discovery-boundaries, discovery-ssot | 4–6 |
84
+ | investigate_swarm | fix-repro, fix-code-path, fix-recent-changes, fix-test-failures, fix-regression-scope, fix-runtime-evidence, fix-inventory-confirm | **7** |
85
+ | root_cause | parent + optional fix-hypothesis-validate | 0–1 |
86
+ | verify | fix-repro-verify, unit-test-run, fallow-check-changed | **3** |
87
+
88
+ Contract: [${canonical}.yaml](../aaac/contracts/commands/${canonical}.yaml)
89
+
90
+ ## Example
91
+
92
+ \`\`\`text
93
+ /${cmd} cms "Getting Started nav missing published guides"
94
+ /${cmd} ui "DocsNav section state lost on route change"
95
+ \`\`\`
96
+ `;
97
+ fs.writeFileSync(path.join(commandsDir, `${cmd}.md`), body);
98
+ }
99
+
100
+ function isContentWriter(cmd, entry) {
101
+ const canonical = entry?.alias ?? cmd;
102
+ return canonical === CONTENT_WRITER_CANONICAL;
103
+ }
104
+
105
+ function writeContentWriterCmd(cmd, entry = null) {
106
+ const aliasLine =
107
+ cmd !== CONTENT_WRITER_CANONICAL
108
+ ? `\n\n> Alias → \`/${CONTENT_WRITER_CANONICAL}\`. See [write-article.md](write-article.md).\n`
109
+ : "";
110
+ const body = `# ${cmd}
111
+
112
+ CMS writer — research swarm + agents, any \`article_type\`, persist to Supabase.${aliasLine}
113
+
114
+ ## Syntax
115
+
116
+ \`\`\`text
117
+ /${CONTENT_WRITER_CANONICAL} <type>, <title> [flags]
118
+ \`\`\`
119
+
120
+ Types: \`article\`, \`guide\`, \`skill\`, \`tool\`, \`command\`, \`subagent\`, \`diagram\`
121
+
122
+ Flags: \`--publish\`, \`--dry-run\`, \`--update\`, \`--tags "a, b"\`
123
+
124
+ ## Dispatch
125
+
126
+ 1. [.cursor/aaac/dispatch.md](../aaac/dispatch.md)
127
+ 2. [.cursor/aaac/graph.yaml](../aaac/graph.yaml) — **\`${CONTENT_WRITER_CANONICAL}\`**
128
+ 3. Run workflow \`write-article\` → [domains/content/write/orchestrator](../domains/content/write/orchestrator/SKILL.md)
129
+ 4. [write-article skill](../skills/write-article/SKILL.md)
130
+
131
+ Full reference: [write-article.md](write-article.md)
132
+ `;
133
+ fs.writeFileSync(path.join(commandsDir, `${cmd}.md`), body);
134
+ }
135
+
37
136
  const EXCEPTION_CMD = {
38
137
  "fix-bug": {
39
138
  layer: "product",
@@ -43,6 +142,10 @@ const EXCEPTION_CMD = {
43
142
  layer: "system",
44
143
  description: "production incident investigation",
45
144
  },
145
+ "publish-aaac": {
146
+ layer: "product",
147
+ description: "npm publish @ludecker/aaac with init smoke test and git tag",
148
+ },
46
149
  };
47
150
 
48
151
  function objectMeta(object, cmd) {
@@ -63,7 +166,9 @@ function orchestratorHint(cmd, entry) {
63
166
  const fallback =
64
167
  cmd === "fix-bug"
65
168
  ? " — unknown slug → `verb-fix` + object `feature`"
66
- : "";
169
+ : cmd === "fix-module"
170
+ ? " — unknown slug → `verb-fix` + object `module`"
171
+ : "";
67
172
  return `resolver \`${entry.resolver}\`${fallback}`;
68
173
  }
69
174
  const verb = cmd.split("-")[0];
@@ -74,6 +179,7 @@ function orchestratorHint(cmd, entry) {
74
179
  "review-incident",
75
180
  "test-function",
76
181
  "release-app",
182
+ "aaac-publish",
77
183
  "write-article",
78
184
  ]);
79
185
  if (cmd === "update-architecture" || (orch && dedicated.has(orch))) {
@@ -85,7 +191,7 @@ function orchestratorHint(cmd, entry) {
85
191
  }
86
192
 
87
193
  function domainLine(cmd) {
88
- if (cmd === "review-incident" || cmd.endsWith("-function")) {
194
+ if (cmd === "review-incident" || cmd.endsWith("-function") || cmd === "publish-aaac") {
89
195
  return "Domain optional.";
90
196
  }
91
197
  if (cmd.endsWith("-domain") || cmd.endsWith("-module")) {
@@ -95,6 +201,14 @@ function domainLine(cmd) {
95
201
  }
96
202
 
97
203
  function writeCmd(cmd, entry = null) {
204
+ if (isContentWriter(cmd, entry)) {
205
+ writeContentWriterCmd(cmd, entry);
206
+ return;
207
+ }
208
+ if (isFixCommand(cmd, entry)) {
209
+ writeFixCmd(cmd, entry);
210
+ return;
211
+ }
98
212
  const parts = cmd.split("-");
99
213
  const verb = parts[0];
100
214
  let object = parts.slice(1).join("-");
@@ -108,7 +222,9 @@ function writeCmd(cmd, entry = null) {
108
222
  ? ` (alias \`${cmd}\` → \`${entry.alias}\`)`
109
223
  : "";
110
224
  const domainArg =
111
- cmd === "review-incident" || cmd.endsWith("-function") ? "" : " <domain>";
225
+ cmd === "review-incident" || cmd.endsWith("-function") || cmd === "publish-aaac"
226
+ ? ""
227
+ : " <domain>";
112
228
  const layerLine = layer ? `**Layer:** ${layer} \n` : "";
113
229
  const body = `# ${cmd}
114
230
 
@@ -130,6 +246,7 @@ ${domainLine(cmd)}
130
246
  const written = new Set();
131
247
 
132
248
  for (const [cmd, entry] of Object.entries(command_overrides)) {
249
+ if (KEEP_EXTRA.has(`${cmd}.md`)) continue;
133
250
  writeCmd(cmd, entry);
134
251
  written.add(cmd);
135
252
  }
@@ -148,6 +148,13 @@ const governanceGateStacksBlock = Object.entries(gates.stacks ?? {})
148
148
  .map(([name, phases]) => ` ${name}: [${phases.join(", ")}]`)
149
149
  .join("\n");
150
150
 
151
+ const commandWorkflowsBlock = Object.entries(lifecycle.workflows ?? {})
152
+ .map(([cmd, def]) => {
153
+ const phases = composeRuntimePhases(def);
154
+ return ` ${cmd}: [${phases.join(", ")}]`;
155
+ })
156
+ .join("\n");
157
+
151
158
  const layerComment = Object.entries(data.layers ?? {})
152
159
  .sort((a, b) => a[1].order - b[1].order)
153
160
  .map(([name, L]) => `# ${name}: ${L.objects.join(", ")}`)
@@ -207,6 +214,10 @@ ${governanceGateStacksBlock}
207
214
  verb_runtime:
208
215
  ${verbRuntimeBlock}
209
216
 
217
+ # Exception commands — not verb×object; use for Run.pending when command matches
218
+ command_workflows:
219
+ ${commandWorkflowsBlock}
220
+
210
221
  confidence:
211
222
  ${confidenceBlock}
212
223
 
@@ -220,6 +231,7 @@ ${maturityRulesBlock}
220
231
  lifecycle: aaac/lifecycle/lifecycle.json
221
232
  lifecycle_phases: aaac/lifecycle/phases.json
222
233
  governance_gates: aaac/governance/gates.json
234
+ complexity: aaac/complexity.yaml
223
235
  run: aaac/run/schema.json
224
236
  capabilities: aaac/capabilities/registry.json
225
237
  dependencies: aaac/dependencies.yaml
@@ -240,3 +252,8 @@ if (tail.includes(INJECT_MARKER)) {
240
252
  const out = `${header}${commandsBlock}\n\n${tail}\n`;
241
253
  fs.writeFileSync(path.join(aaac, "graph.yaml"), out);
242
254
  console.log("Wrote graph.yaml");
255
+
256
+ const registryScript = path.join(aaac, "scripts", "generate-runtime-registry.mjs");
257
+ if (fs.existsSync(registryScript)) {
258
+ execSync(`${process.execPath} "${registryScript}"`, { stdio: "inherit" });
259
+ }
@@ -55,6 +55,7 @@ export function installAaac({
55
55
  copyDirRecursive(cursorSrc, cursorDest);
56
56
  ensureDir(path.join(cursorDest, "commands"));
57
57
  ensureDir(path.join(aaacDest, "state", "runs"));
58
+ ensureDir(path.join(aaacDest, "state", "active-runs"));
58
59
 
59
60
  const docsDest = path.join(resolvedTarget, docsRoot);
60
61
  ensureDir(docsDest);
@@ -0,0 +1,33 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { spawnSync } from "child_process";
4
+ import { fileURLToPath } from "url";
5
+
6
+ const packageRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
7
+
8
+ export function resolveRunEngineScript(scriptName, targetDir = process.cwd()) {
9
+ const projectScript = path.join(
10
+ targetDir,
11
+ ".cursor",
12
+ "aaac",
13
+ "scripts",
14
+ "run-engine",
15
+ scriptName,
16
+ );
17
+ if (fs.existsSync(projectScript)) return projectScript;
18
+ const bundled = path.join(packageRoot, "src", "run-engine", scriptName);
19
+ if (fs.existsSync(bundled)) return bundled;
20
+ throw new Error(`Run engine script not found: ${scriptName}`);
21
+ }
22
+
23
+ export function runEngineScript(scriptName, argv, targetDir = process.cwd()) {
24
+ const scriptPath = resolveRunEngineScript(scriptName, targetDir);
25
+ const result = spawnSync(process.execPath, [scriptPath, ...argv], {
26
+ stdio: "inherit",
27
+ cwd: targetDir,
28
+ env: process.env,
29
+ });
30
+ if (result.status !== 0) {
31
+ process.exit(result.status ?? 1);
32
+ }
33
+ }