@ludecker/aaac 1.1.0 → 1.1.2

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 (40) hide show
  1. package/package.json +1 -1
  2. package/src/generators/generate-commands.mjs +17 -9
  3. package/src/run-engine/advance-phase.mjs +152 -1
  4. package/src/run-engine/capability-evidence.mjs +460 -0
  5. package/src/run-engine/gate-write.mjs +14 -2
  6. package/src/run-engine/init-run.mjs +92 -1
  7. package/src/run-engine/lib.mjs +38 -0
  8. package/src/run-engine/record-task.mjs +7 -1
  9. package/src/run-engine/stop-check.mjs +7 -1
  10. package/src/run-engine/verify-website-build.mjs +185 -0
  11. package/templates/cursor/aaac/capabilities/promotion-rules.json +64 -0
  12. package/templates/cursor/aaac/capabilities/registry.json +11 -11
  13. package/templates/cursor/aaac/dispatch.md +2 -2
  14. package/templates/cursor/aaac/enforcement.json +6 -3
  15. package/templates/cursor/aaac/governance/gates.json +3 -1
  16. package/templates/cursor/aaac/graph.project.yaml +4 -204
  17. package/templates/cursor/aaac/layers.md +3 -0
  18. package/templates/cursor/aaac/observability/telemetry.yaml +3 -0
  19. package/templates/cursor/aaac/ontology.md +17 -32
  20. package/templates/cursor/aaac/project.config.json +4 -1
  21. package/templates/cursor/aaac/run/schema.json +5 -1
  22. package/templates/cursor/aaac/scripts/run-engine/advance-phase.mjs +152 -1
  23. package/templates/cursor/aaac/scripts/run-engine/capability-evidence.mjs +460 -0
  24. package/templates/cursor/aaac/scripts/run-engine/gate-write.mjs +14 -2
  25. package/templates/cursor/aaac/scripts/run-engine/init-run.mjs +92 -1
  26. package/templates/cursor/aaac/scripts/run-engine/lib.mjs +38 -0
  27. package/templates/cursor/aaac/scripts/run-engine/record-task.mjs +7 -1
  28. package/templates/cursor/aaac/scripts/run-engine/stop-check.mjs +7 -1
  29. package/templates/cursor/aaac/scripts/run-engine/verify-website-build.mjs +185 -0
  30. package/templates/cursor/aaac/state/capability-stats.json +5 -0
  31. package/templates/cursor/agents/playwright-check-run.md +8 -26
  32. package/templates/cursor/agents/release-git.md +2 -2
  33. package/templates/cursor/agents/unit-test-run.md +3 -7
  34. package/templates/cursor/skills/shared/governance/implementation/SKILL.md +25 -396
  35. package/templates/cursor/skills/shared/platform-release/SKILL.md +22 -19
  36. package/templates/cursor/skills/shared/platform-release/orchestrator/contract.yaml +27 -7
  37. package/templates/cursor/skills/shared/testing/SKILL.md +5 -0
  38. package/templates/cursor/skills/shared/verbs/check/orchestrator/SKILL.md +1 -1
  39. package/templates/cursor/skills/shared/verification/SKILL.md +2 -1
  40. package/templates/docs/agentic_architecture.md +163 -60
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Verify app static assets + production build (project overlay).
4
+ * Skips when `.cursor/aaac/project.config.json` has `verify.enabled: false`.
5
+ *
6
+ * Usage:
7
+ * node verify-website-build.mjs [--run-id <run_id>] [--skip-build]
8
+ */
9
+ import fs from "fs";
10
+ import path from "path";
11
+ import { spawnSync } from "child_process";
12
+ import { runDir, isoNow, writeJson, readJson } from "./lib.mjs";
13
+
14
+ const PROJECT_ROOT = process.cwd();
15
+
16
+ const args = process.argv.slice(2);
17
+ const runIdIdx = args.indexOf("--run-id");
18
+ const runId = runIdIdx >= 0 ? args[runIdIdx + 1] : null;
19
+ const skipBuild = args.includes("--skip-build");
20
+
21
+ function loadVerifyConfig() {
22
+ const configPath = path.join(PROJECT_ROOT, ".cursor/aaac/project.config.json");
23
+ const config = readJson(configPath, { verify: { enabled: false } });
24
+ const verify = config.verify ?? { enabled: false };
25
+ if (!verify.enabled) {
26
+ return { enabled: false };
27
+ }
28
+ const appRootRel = verify.app_root ?? "apps/website";
29
+ const indexRel =
30
+ verify.index_html ?? path.join(appRootRel, "index.html").replace(/\\/g, "/");
31
+ const appRoot = path.join(PROJECT_ROOT, appRootRel);
32
+ const indexHtml = path.join(PROJECT_ROOT, indexRel);
33
+ const build = verify.build ?? { command: "pnpm", args: ["run", "build"] };
34
+ return { enabled: true, appRoot, indexHtml, build, appRootRel };
35
+ }
36
+
37
+ const verifyConfig = loadVerifyConfig();
38
+
39
+ const results = {
40
+ status: "pass",
41
+ checked_at: isoNow(),
42
+ static_assets: { status: "pass", missing: [] },
43
+ build: {
44
+ status: skipBuild ? "skipped" : "pending",
45
+ command: null,
46
+ },
47
+ verify_config: verifyConfig.enabled ? "enabled" : "disabled",
48
+ };
49
+
50
+ function fail(section, detail) {
51
+ results.status = "fail";
52
+ if (section === "static_assets") {
53
+ results.static_assets.status = "fail";
54
+ results.static_assets.missing.push(detail);
55
+ } else if (section === "build") {
56
+ results.build.status = "fail";
57
+ results.build.detail = detail;
58
+ }
59
+ console.error(`[verify-website-build] FAIL ${section}: ${detail}`);
60
+ }
61
+
62
+ function resolveRootAsset(assetPath, websiteRoot, appRootRel) {
63
+ const rel = assetPath.replace(/^\//, "");
64
+ const candidates = [
65
+ path.join(websiteRoot, "public", rel),
66
+ path.join(websiteRoot, rel),
67
+ ];
68
+ for (const candidate of candidates) {
69
+ if (fs.existsSync(candidate)) {
70
+ return candidate;
71
+ }
72
+ }
73
+ return null;
74
+ }
75
+
76
+ function checkStaticAssets(indexHtml, websiteRoot, appRootRel) {
77
+ if (!fs.existsSync(indexHtml)) {
78
+ fail("static_assets", `missing index.html at ${indexHtml}`);
79
+ return;
80
+ }
81
+
82
+ const html = fs.readFileSync(indexHtml, "utf8");
83
+ const rootRefs = [
84
+ ...html.matchAll(/\b(?:href|src)="(\/[^"#?]+)"/g),
85
+ ].map((match) => match[1]);
86
+
87
+ const seen = new Set();
88
+ for (const ref of rootRefs) {
89
+ if (seen.has(ref) || ref.startsWith("//")) continue;
90
+ seen.add(ref);
91
+
92
+ const resolved = resolveRootAsset(ref, websiteRoot, appRootRel);
93
+ if (!resolved) {
94
+ fail(
95
+ "static_assets",
96
+ `${ref} not found under ${appRootRel}/public/ or ${appRootRel}/`,
97
+ );
98
+ }
99
+ }
100
+ }
101
+
102
+ function runBuild(build) {
103
+ if (skipBuild) return;
104
+
105
+ const command = build.command ?? "pnpm";
106
+ const buildArgs = build.args ?? ["run", "build"];
107
+ results.build.command = [command, ...buildArgs].join(" ");
108
+
109
+ const proc = spawnSync(command, buildArgs, {
110
+ cwd: build.cwd ? path.join(PROJECT_ROOT, build.cwd) : PROJECT_ROOT,
111
+ encoding: "utf8",
112
+ env: { ...process.env, CI: "1" },
113
+ });
114
+
115
+ if (proc.status !== 0) {
116
+ const detail = [proc.stderr, proc.stdout].filter(Boolean).join("\n").trim();
117
+ results.build.status = "fail";
118
+ results.build.exit_code = proc.status ?? 1;
119
+ fail("build", detail || `exit ${proc.status}`);
120
+ return;
121
+ }
122
+
123
+ results.build.status = "pass";
124
+ results.build.exit_code = 0;
125
+ }
126
+
127
+ function writeArtifact() {
128
+ if (!runId) return;
129
+
130
+ const artifactDir = path.join(runDir(runId), "artifacts");
131
+ fs.mkdirSync(artifactDir, { recursive: true });
132
+
133
+ const yaml = [
134
+ `status: ${results.status}`,
135
+ `checked_at: ${results.checked_at}`,
136
+ `verify_config: ${results.verify_config}`,
137
+ "static_assets:",
138
+ ` status: ${results.static_assets.status}`,
139
+ ` missing: ${JSON.stringify(results.static_assets.missing)}`,
140
+ "build:",
141
+ ` status: ${results.build.status}`,
142
+ results.build.command ? ` command: ${JSON.stringify(results.build.command)}` : null,
143
+ results.build.exit_code != null ? ` exit_code: ${results.build.exit_code}` : null,
144
+ results.build.detail ? ` detail: ${JSON.stringify(results.build.detail)}` : null,
145
+ ]
146
+ .filter(Boolean)
147
+ .join("\n");
148
+
149
+ fs.writeFileSync(path.join(artifactDir, "verify.yaml"), `${yaml}\n`);
150
+
151
+ const manifestPath = path.join(runDir(runId), "run.json");
152
+ try {
153
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
154
+ manifest.artifacts = manifest.artifacts ?? {};
155
+ manifest.artifacts.verify = results;
156
+ manifest.updated_at = isoNow();
157
+ writeJson(manifestPath, manifest);
158
+ } catch {
159
+ // run.json may not exist in standalone invocations
160
+ }
161
+ }
162
+
163
+ if (!verifyConfig.enabled) {
164
+ results.static_assets.status = "skipped";
165
+ results.build.status = "skipped";
166
+ results.build.command = null;
167
+ writeArtifact();
168
+ console.log(JSON.stringify({ ok: true, skipped: true, reason: "verify.disabled", ...results }));
169
+ process.exit(0);
170
+ }
171
+
172
+ results.build.command = skipBuild
173
+ ? null
174
+ : [verifyConfig.build.command, ...(verifyConfig.build.args ?? [])].join(" ");
175
+
176
+ checkStaticAssets(
177
+ verifyConfig.indexHtml,
178
+ verifyConfig.appRoot,
179
+ verifyConfig.appRootRel,
180
+ );
181
+ runBuild(verifyConfig.build);
182
+ writeArtifact();
183
+
184
+ console.log(JSON.stringify({ ok: results.status === "pass", ...results }));
185
+ process.exit(results.status === "pass" ? 0 : 1);
@@ -0,0 +1,5 @@
1
+ {
2
+ "version": 1,
3
+ "updated_at": null,
4
+ "capabilities": {}
5
+ }
@@ -2,43 +2,25 @@
2
2
 
3
3
  ## Role
4
4
 
5
- Run AAAC verb contract Playwright checks and optional public-site smoke during verify.
5
+ Run Playwright E2E checks from domain inventory during verify.
6
6
 
7
7
  ## When
8
8
 
9
- **Verify phase** for commands whose verb is `create`, `update`, or `fix` (including aliases such as `fix-module`, `create-component`, `update-module`).
9
+ **Verify phase** for `create`, `update`, or `fix` verbs when inventory lists Playwright targets.
10
10
 
11
- **Report phase** for commands whose verb is `check` (including `check-module`, `check-component`, …) — readonly; contract checks only.
11
+ **Report phase** for `check` verbs when project defines contract E2E specs.
12
12
 
13
- Contract checks always run. Browser smoke runs only when `PLAYWRIGHT_BASE_URL` is set.
13
+ Browser smoke runs only when `PLAYWRIGHT_BASE_URL` is set.
14
14
 
15
15
  ## Commands
16
16
 
17
- From repo root:
17
+ Use the command from domain inventory. Example:
18
18
 
19
19
  ```bash
20
- pnpm --filter @ludecker/aaac test:e2e
20
+ pnpm exec playwright test
21
+ PLAYWRIGHT_BASE_URL=http://localhost:3000 pnpm exec playwright test
21
22
  ```
22
23
 
23
- Optional website smoke (dev server or deployed URL):
24
-
25
- ```bash
26
- PLAYWRIGHT_BASE_URL=http://localhost:3000 pnpm --filter @ludecker/aaac test:e2e
27
- ```
28
-
29
- Interactive debugging:
30
-
31
- ```bash
32
- pnpm --filter @ludecker/aaac test:e2e:ui
33
- ```
34
-
35
- ## What passes
36
-
37
- - `runtime-registry.json` command entries match `graph.yaml` `verb_runtime` for the command verb
38
- - Fix verb includes `investigate_swarm` and `root_cause` before `plan`
39
- - Check verb has no `execute` or `plan` — pending matches `verb_runtime.check`
40
- - Skipped browser tests when `PLAYWRIGHT_BASE_URL` is unset (CI default)
41
-
42
24
  ## Return
43
25
 
44
- Exit code, failing spec file names, contract mismatch details (command vs `verb_runtime`), browser smoke failures with route and status.
26
+ Exit code, failing spec file names, browser smoke failures with route and status.
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Role
6
6
 
7
- Commit and push all pending work to `main` for the Lüdecker monorepo.
7
+ Commit and push all pending work to the default branch for this repository.
8
8
 
9
9
  ## Inputs (from orchestrator)
10
10
 
@@ -16,7 +16,7 @@ Commit and push all pending work to `main` for the Lüdecker monorepo.
16
16
 
17
17
  Follow [ship-procedure.md § Git](../skills/shared/platform-release/ship-procedure.md).
18
18
 
19
- **Repo check:** `git rev-parse --show-toplevel` must be the ludecker monorepo.
19
+ **Repo check:** `git rev-parse --show-toplevel` must be the project root (not a subdirectory).
20
20
 
21
21
  ## Return
22
22
 
@@ -4,15 +4,11 @@
4
4
 
5
5
  Run targeted tests for paths from domain inventory. Report pass/fail with test names.
6
6
 
7
- ## Lüdecker defaults
7
+ ## Defaults
8
8
 
9
- From repo root:
9
+ From repo root, use the test command in domain inventory when listed (e.g. `pnpm test`, `npm test`, `cargo test`).
10
10
 
11
- ```bash
12
- pnpm typecheck
13
- ```
14
-
15
- If domain inventory lists vitest/jest targets, run those instead.
11
+ If no inventory entry, run the project's root `package.json` `test` or `typecheck` script when present.
16
12
 
17
13
  ## Return
18
14