@ludecker/aaac 1.1.1 → 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.
- package/package.json +1 -1
- package/src/generators/generate-commands.mjs +17 -9
- package/src/run-engine/advance-phase.mjs +2 -2
- package/src/run-engine/gate-write.mjs +14 -2
- package/src/run-engine/init-run.mjs +41 -0
- package/src/run-engine/lib.mjs +33 -0
- package/src/run-engine/record-task.mjs +7 -1
- package/src/run-engine/stop-check.mjs +7 -1
- package/src/run-engine/verify-website-build.mjs +67 -30
- package/templates/cursor/aaac/capabilities/registry.json +14 -16
- package/templates/cursor/aaac/graph.project.yaml +4 -204
- package/templates/cursor/aaac/ontology.md +17 -32
- package/templates/cursor/aaac/project.config.json +4 -1
- package/templates/cursor/aaac/run/schema.json +3 -1
- package/templates/cursor/aaac/scripts/run-engine/advance-phase.mjs +2 -2
- package/templates/cursor/aaac/scripts/run-engine/gate-write.mjs +14 -2
- package/templates/cursor/aaac/scripts/run-engine/init-run.mjs +41 -0
- package/templates/cursor/aaac/scripts/run-engine/lib.mjs +33 -0
- package/templates/cursor/aaac/scripts/run-engine/record-task.mjs +7 -1
- package/templates/cursor/aaac/scripts/run-engine/stop-check.mjs +7 -1
- package/templates/cursor/aaac/scripts/run-engine/verify-website-build.mjs +67 -30
- package/templates/cursor/agents/playwright-check-run.md +8 -26
- package/templates/cursor/agents/release-git.md +2 -2
- package/templates/cursor/agents/unit-test-run.md +3 -7
- package/templates/cursor/skills/shared/governance/implementation/SKILL.md +25 -396
- package/templates/cursor/skills/shared/testing/SKILL.md +2 -2
- package/templates/cursor/skills/shared/verbs/check/orchestrator/SKILL.md +1 -1
- package/templates/cursor/skills/shared/verification/SKILL.md +2 -2
- package/templates/docs/agentic_architecture.md +86 -166
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Verify
|
|
4
|
-
*
|
|
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 {
|
|
13
|
-
import { REPO_ROOT, runDir, isoNow, writeJson } from "./lib.mjs";
|
|
12
|
+
import { runDir, isoNow, writeJson, readJson } from "./lib.mjs";
|
|
14
13
|
|
|
15
|
-
const
|
|
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: {
|
|
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(
|
|
47
|
-
path.join(
|
|
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(
|
|
59
|
-
fail("static_assets", `missing index.html at ${
|
|
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(
|
|
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
|
|
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
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
144
|
-
|
|
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
|
|
5
|
+
Run Playwright E2E checks from domain inventory during verify.
|
|
6
6
|
|
|
7
7
|
## When
|
|
8
8
|
|
|
9
|
-
**Verify phase** for
|
|
9
|
+
**Verify phase** for `create`, `update`, or `fix` verbs when inventory lists Playwright targets.
|
|
10
10
|
|
|
11
|
-
**Report phase** for
|
|
11
|
+
**Report phase** for `check` verbs when project defines contract E2E specs.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Browser smoke runs only when `PLAYWRIGHT_BASE_URL` is set.
|
|
14
14
|
|
|
15
15
|
## Commands
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Use the command from domain inventory. Example:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
pnpm
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
|