@ludecker/aaac 1.1.1 → 1.1.3

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 (34) hide show
  1. package/README.md +5 -3
  2. package/package.json +1 -1
  3. package/src/cli.mjs +10 -9
  4. package/src/generators/generate-commands.mjs +17 -9
  5. package/src/run-engine/advance-phase.mjs +2 -2
  6. package/src/run-engine/gate-write.mjs +14 -2
  7. package/src/run-engine/init-run.mjs +41 -0
  8. package/src/run-engine/lib.mjs +33 -0
  9. package/src/run-engine/record-task.mjs +7 -1
  10. package/src/run-engine/stop-check.mjs +7 -1
  11. package/src/run-engine/verify-website-build.mjs +67 -30
  12. package/templates/cursor/aaac/capabilities/registry.json +14 -16
  13. package/templates/cursor/aaac/graph.project.yaml +4 -204
  14. package/templates/cursor/aaac/ontology.md +17 -32
  15. package/templates/cursor/aaac/project.config.json +4 -1
  16. package/templates/cursor/aaac/run/schema.json +3 -1
  17. package/templates/cursor/aaac/scripts/run-engine/advance-phase.mjs +2 -2
  18. package/templates/cursor/aaac/scripts/run-engine/gate-write.mjs +14 -2
  19. package/templates/cursor/aaac/scripts/run-engine/init-run.mjs +41 -0
  20. package/templates/cursor/aaac/scripts/run-engine/lib.mjs +33 -0
  21. package/templates/cursor/aaac/scripts/run-engine/record-task.mjs +7 -1
  22. package/templates/cursor/aaac/scripts/run-engine/stop-check.mjs +7 -1
  23. package/templates/cursor/aaac/scripts/run-engine/verify-website-build.mjs +67 -30
  24. package/templates/cursor/agents/playwright-check-run.md +8 -26
  25. package/templates/cursor/agents/release-git.md +2 -2
  26. package/templates/cursor/agents/unit-test-run.md +3 -7
  27. package/templates/cursor/rules/aaac-enforcement.mdc +2 -2
  28. package/templates/cursor/skills/shared/governance/implementation/SKILL.md +25 -396
  29. package/templates/cursor/skills/shared/testing/SKILL.md +2 -2
  30. package/templates/cursor/skills/shared/verbs/check/orchestrator/SKILL.md +1 -1
  31. package/templates/cursor/skills/shared/verification/SKILL.md +2 -2
  32. package/templates/docs/agentic_architecture.md +91 -166
  33. package/templates/docs/architecture.md +44 -2
  34. package/templates/docs/master_rules.md +26 -2
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Verify website static assets + production build.
4
- * Used by advance-phase on create/update/fix verify completion.
3
+ * Verify app static assets + production build (project overlay).
4
+ * Skips when `.cursor/aaac/project.config.json` has `verify.enabled: false`.
5
5
  *
6
6
  * Usage:
7
7
  * node verify-website-build.mjs [--run-id <run_id>] [--skip-build]
@@ -9,23 +9,42 @@
9
9
  import fs from "fs";
10
10
  import path from "path";
11
11
  import { spawnSync } from "child_process";
12
- import { fileURLToPath } from "url";
13
- import { REPO_ROOT, runDir, isoNow, writeJson } from "./lib.mjs";
12
+ import { runDir, isoNow, writeJson, readJson } from "./lib.mjs";
14
13
 
15
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
- const WEBSITE_ROOT = path.join(REPO_ROOT, "apps/website");
17
- const INDEX_HTML = path.join(WEBSITE_ROOT, "index.html");
14
+ const PROJECT_ROOT = process.cwd();
18
15
 
19
16
  const args = process.argv.slice(2);
20
17
  const runIdIdx = args.indexOf("--run-id");
21
18
  const runId = runIdIdx >= 0 ? args[runIdIdx + 1] : null;
22
19
  const skipBuild = args.includes("--skip-build");
23
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
+
24
39
  const results = {
25
40
  status: "pass",
26
41
  checked_at: isoNow(),
27
42
  static_assets: { status: "pass", missing: [] },
28
- build: { status: skipBuild ? "skipped" : "pending", command: "pnpm --filter @ludecker/website build" },
43
+ build: {
44
+ status: skipBuild ? "skipped" : "pending",
45
+ command: null,
46
+ },
47
+ verify_config: verifyConfig.enabled ? "enabled" : "disabled",
29
48
  };
30
49
 
31
50
  function fail(section, detail) {
@@ -40,11 +59,11 @@ function fail(section, detail) {
40
59
  console.error(`[verify-website-build] FAIL ${section}: ${detail}`);
41
60
  }
42
61
 
43
- function resolveRootAsset(assetPath) {
62
+ function resolveRootAsset(assetPath, websiteRoot, appRootRel) {
44
63
  const rel = assetPath.replace(/^\//, "");
45
64
  const candidates = [
46
- path.join(WEBSITE_ROOT, "public", rel),
47
- path.join(WEBSITE_ROOT, rel),
65
+ path.join(websiteRoot, "public", rel),
66
+ path.join(websiteRoot, rel),
48
67
  ];
49
68
  for (const candidate of candidates) {
50
69
  if (fs.existsSync(candidate)) {
@@ -54,13 +73,13 @@ function resolveRootAsset(assetPath) {
54
73
  return null;
55
74
  }
56
75
 
57
- function checkStaticAssets() {
58
- if (!fs.existsSync(INDEX_HTML)) {
59
- fail("static_assets", `missing index.html at ${INDEX_HTML}`);
76
+ function checkStaticAssets(indexHtml, websiteRoot, appRootRel) {
77
+ if (!fs.existsSync(indexHtml)) {
78
+ fail("static_assets", `missing index.html at ${indexHtml}`);
60
79
  return;
61
80
  }
62
81
 
63
- const html = fs.readFileSync(INDEX_HTML, "utf8");
82
+ const html = fs.readFileSync(indexHtml, "utf8");
64
83
  const rootRefs = [
65
84
  ...html.matchAll(/\b(?:href|src)="(\/[^"#?]+)"/g),
66
85
  ].map((match) => match[1]);
@@ -70,28 +89,28 @@ function checkStaticAssets() {
70
89
  if (seen.has(ref) || ref.startsWith("//")) continue;
71
90
  seen.add(ref);
72
91
 
73
- const resolved = resolveRootAsset(ref);
92
+ const resolved = resolveRootAsset(ref, websiteRoot, appRootRel);
74
93
  if (!resolved) {
75
94
  fail(
76
95
  "static_assets",
77
- `${ref} not found under apps/website/public/ or apps/website/ (Vite dev resolves root paths to project root)`,
96
+ `${ref} not found under ${appRootRel}/public/ or ${appRootRel}/`,
78
97
  );
79
98
  }
80
99
  }
81
100
  }
82
101
 
83
- function runBuild() {
102
+ function runBuild(build) {
84
103
  if (skipBuild) return;
85
104
 
86
- const proc = spawnSync(
87
- "pnpm",
88
- ["--filter", "@ludecker/website", "build"],
89
- {
90
- cwd: REPO_ROOT,
91
- encoding: "utf8",
92
- env: { ...process.env, CI: "1" },
93
- },
94
- );
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
+ });
95
114
 
96
115
  if (proc.status !== 0) {
97
116
  const detail = [proc.stderr, proc.stdout].filter(Boolean).join("\n").trim();
@@ -114,12 +133,13 @@ function writeArtifact() {
114
133
  const yaml = [
115
134
  `status: ${results.status}`,
116
135
  `checked_at: ${results.checked_at}`,
136
+ `verify_config: ${results.verify_config}`,
117
137
  "static_assets:",
118
138
  ` status: ${results.static_assets.status}`,
119
139
  ` missing: ${JSON.stringify(results.static_assets.missing)}`,
120
140
  "build:",
121
141
  ` status: ${results.build.status}`,
122
- ` command: ${JSON.stringify(results.build.command)}`,
142
+ results.build.command ? ` command: ${JSON.stringify(results.build.command)}` : null,
123
143
  results.build.exit_code != null ? ` exit_code: ${results.build.exit_code}` : null,
124
144
  results.build.detail ? ` detail: ${JSON.stringify(results.build.detail)}` : null,
125
145
  ]
@@ -140,8 +160,25 @@ function writeArtifact() {
140
160
  }
141
161
  }
142
162
 
143
- checkStaticAssets();
144
- runBuild();
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);
145
182
  writeArtifact();
146
183
 
147
184
  console.log(JSON.stringify({ ok: results.status === "pass", ...results }));
@@ -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
 
@@ -11,8 +11,8 @@ Every AAAC slash command (`/fix-module`, `/update-module`, `/write-article`, …
11
11
 
12
12
  ## Prerequisites
13
13
 
14
- 1. **Cursor Hooks enabled** — Settings → Hooks; restart Cursor after `.cursor/hooks.json` changes
15
- 2. **Registry current** — `node .cursor/aaac/generate-graph.mjs`
14
+ 1. **Project opened in Cursor** — `.cursor/hooks.json` is installed by `init`; hooks run when the project is open
15
+ 2. **Registry current** — after ontology edits: `npx @ludecker/aaac@latest generate`
16
16
 
17
17
  ## Hook behavior (automatic)
18
18