agentopology 0.5.2 → 0.6.0

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 (115) hide show
  1. package/README.md +5 -5
  2. package/dist/__tests__/e2e/roundtrip.test.d.ts +16 -0
  3. package/dist/__tests__/e2e/roundtrip.test.d.ts.map +1 -0
  4. package/dist/__tests__/e2e/roundtrip.test.js +178 -0
  5. package/dist/__tests__/e2e/roundtrip.test.js.map +1 -0
  6. package/dist/__tests__/e2e/scaffold-owns.test.d.ts +10 -0
  7. package/dist/__tests__/e2e/scaffold-owns.test.d.ts.map +1 -0
  8. package/dist/__tests__/e2e/scaffold-owns.test.js +154 -0
  9. package/dist/__tests__/e2e/scaffold-owns.test.js.map +1 -0
  10. package/dist/__tests__/global-setup.d.ts +7 -0
  11. package/dist/__tests__/global-setup.d.ts.map +1 -0
  12. package/dist/__tests__/global-setup.js +16 -0
  13. package/dist/__tests__/global-setup.js.map +1 -0
  14. package/dist/__tests__/live/claude-code.live.test.d.ts +20 -0
  15. package/dist/__tests__/live/claude-code.live.test.d.ts.map +1 -0
  16. package/dist/__tests__/live/claude-code.live.test.js +136 -0
  17. package/dist/__tests__/live/claude-code.live.test.js.map +1 -0
  18. package/dist/__tests__/live/zz-debug.test.d.ts +2 -0
  19. package/dist/__tests__/live/zz-debug.test.d.ts.map +1 -0
  20. package/dist/__tests__/live/zz-debug.test.js +4 -0
  21. package/dist/__tests__/live/zz-debug.test.js.map +1 -0
  22. package/dist/__tests__/open-findings.test.d.ts +10 -0
  23. package/dist/__tests__/open-findings.test.d.ts.map +1 -0
  24. package/dist/__tests__/open-findings.test.js +37 -0
  25. package/dist/__tests__/open-findings.test.js.map +1 -0
  26. package/dist/__tests__/spec-testing-sync.test.d.ts +10 -0
  27. package/dist/__tests__/spec-testing-sync.test.d.ts.map +1 -0
  28. package/dist/__tests__/spec-testing-sync.test.js +57 -0
  29. package/dist/__tests__/spec-testing-sync.test.js.map +1 -0
  30. package/dist/bindings/__tests__/hook-command.test.d.ts +9 -0
  31. package/dist/bindings/__tests__/hook-command.test.d.ts.map +1 -0
  32. package/dist/bindings/__tests__/hook-command.test.js +88 -0
  33. package/dist/bindings/__tests__/hook-command.test.js.map +1 -0
  34. package/dist/bindings/__tests__/mod-plugin.test.d.ts +9 -0
  35. package/dist/bindings/__tests__/mod-plugin.test.d.ts.map +1 -0
  36. package/dist/bindings/__tests__/mod-plugin.test.js +164 -0
  37. package/dist/bindings/__tests__/mod-plugin.test.js.map +1 -0
  38. package/dist/bindings/claude-code.d.ts +52 -1
  39. package/dist/bindings/claude-code.d.ts.map +1 -1
  40. package/dist/bindings/claude-code.js +306 -68
  41. package/dist/bindings/claude-code.js.map +1 -1
  42. package/dist/bindings/index.d.ts +7 -0
  43. package/dist/bindings/index.d.ts.map +1 -1
  44. package/dist/bindings/index.js +26 -7
  45. package/dist/bindings/index.js.map +1 -1
  46. package/dist/bindings/types.d.ts +6 -0
  47. package/dist/bindings/types.d.ts.map +1 -1
  48. package/dist/bindings/types.js.map +1 -1
  49. package/dist/cli/__tests__/cli.test.d.ts +1 -1
  50. package/dist/cli/__tests__/cli.test.js +1 -1
  51. package/dist/cli/index.js +118 -78
  52. package/dist/cli/index.js.map +1 -1
  53. package/dist/docs/content.d.ts.map +1 -1
  54. package/dist/docs/content.js +39 -3
  55. package/dist/docs/content.js.map +1 -1
  56. package/dist/docs/teach.d.ts.map +1 -1
  57. package/dist/docs/teach.js +36 -0
  58. package/dist/docs/teach.js.map +1 -1
  59. package/dist/import/__tests__/import.test.js +21 -9
  60. package/dist/import/__tests__/import.test.js.map +1 -1
  61. package/dist/import/claude-code.d.ts.map +1 -1
  62. package/dist/import/claude-code.js +128 -44
  63. package/dist/import/claude-code.js.map +1 -1
  64. package/dist/import/serializer.d.ts.map +1 -1
  65. package/dist/import/serializer.js +10 -0
  66. package/dist/import/serializer.js.map +1 -1
  67. package/dist/parser/__tests__/mod-hooks.test.d.ts +10 -0
  68. package/dist/parser/__tests__/mod-hooks.test.d.ts.map +1 -0
  69. package/dist/parser/__tests__/mod-hooks.test.js +136 -0
  70. package/dist/parser/__tests__/mod-hooks.test.js.map +1 -0
  71. package/dist/parser/ast.d.ts +29 -2
  72. package/dist/parser/ast.d.ts.map +1 -1
  73. package/dist/parser/ast.js.map +1 -1
  74. package/dist/parser/index.d.ts +6 -1
  75. package/dist/parser/index.d.ts.map +1 -1
  76. package/dist/parser/index.js +76 -22
  77. package/dist/parser/index.js.map +1 -1
  78. package/dist/parser/paths.d.ts +15 -0
  79. package/dist/parser/paths.d.ts.map +1 -0
  80. package/dist/parser/paths.js +34 -0
  81. package/dist/parser/paths.js.map +1 -0
  82. package/dist/parser/run.d.ts +24 -0
  83. package/dist/parser/run.d.ts.map +1 -0
  84. package/dist/parser/run.js +55 -0
  85. package/dist/parser/run.js.map +1 -0
  86. package/dist/parser/validator.d.ts +12 -0
  87. package/dist/parser/validator.d.ts.map +1 -1
  88. package/dist/parser/validator.js +218 -2
  89. package/dist/parser/validator.js.map +1 -1
  90. package/dist/scaffold/__tests__/safety.test.d.ts +11 -0
  91. package/dist/scaffold/__tests__/safety.test.d.ts.map +1 -0
  92. package/dist/scaffold/__tests__/safety.test.js +184 -0
  93. package/dist/scaffold/__tests__/safety.test.js.map +1 -0
  94. package/dist/scaffold/__tests__/scaffold.test.js +2 -1
  95. package/dist/scaffold/__tests__/scaffold.test.js.map +1 -1
  96. package/dist/scaffold/__tests__/settings-merge.test.js +40 -9
  97. package/dist/scaffold/__tests__/settings-merge.test.js.map +1 -1
  98. package/dist/scaffold/incremental.d.ts +49 -13
  99. package/dist/scaffold/incremental.d.ts.map +1 -1
  100. package/dist/scaffold/incremental.js +235 -95
  101. package/dist/scaffold/incremental.js.map +1 -1
  102. package/dist/scaffold/manifest.d.ts +8 -1
  103. package/dist/scaffold/manifest.d.ts.map +1 -1
  104. package/dist/scaffold/manifest.js +32 -8
  105. package/dist/scaffold/manifest.js.map +1 -1
  106. package/dist/scaffold/merge.d.ts +15 -4
  107. package/dist/scaffold/merge.d.ts.map +1 -1
  108. package/dist/scaffold/merge.js +109 -18
  109. package/dist/scaffold/merge.js.map +1 -1
  110. package/dist/scaffold/types.d.ts +17 -0
  111. package/dist/scaffold/types.d.ts.map +1 -1
  112. package/package.json +1 -1
  113. package/spec/grammar.md +20 -4
  114. package/spec/testing.md +81 -0
  115. package/spec/validation.md +6 -2
package/README.md CHANGED
@@ -96,7 +96,7 @@ who works, when they work, and what they know when they work. One file, two ways
96
96
  ┌────────────┐
97
97
  ┌──────────────┐ │ Parser & │ scaffold ──▶ Platform configs
98
98
  │ .at file │─▶│ Validator │──┤ ├── .claude/agents/
99
- │ (you write) │ │ 93 rules │ │ ├── <topology>.workflow.js
99
+ │ (you write) │ │ 97 rules │ │ ├── <topology>.workflow.js
100
100
  └──────────────┘ └────────────┘ │ ├── .codex/ .cursor/rules/
101
101
  │ ├── .openclaw/ .github/agents/
102
102
  │ └── .kiro/ …
@@ -234,7 +234,7 @@ In Claude Code, type `/agentopology` — or just ask naturally:
234
234
  Say **"I want a code review team with an analyzer, security scanner, and reviewer"** — the skill:
235
235
 
236
236
  1. Generates the `.at` file with the right syntax
237
- 2. Validates it against 93 rules
237
+ 2. Validates it against 97 rules
238
238
  3. Scaffolds it to Claude Code, OpenClaw, Cursor, or any target
239
239
 
240
240
  **Full agent team in under 2 minutes.** No docs to read. No syntax to memorize. You describe what you want, the skill handles the rest.
@@ -566,7 +566,7 @@ import { parse, validate, bindings } from "agentopology";
566
566
  // Parse
567
567
  const ast = parse(atSource);
568
568
 
569
- // Validate (93 built-in rules, V1-V93)
569
+ // Validate (97 built-in rules, V1-V97)
570
570
  const issues = validate(ast);
571
571
 
572
572
  // Scaffold — generate platform files
@@ -624,7 +624,7 @@ You can `agentopology visualize` it into an interactive graph. You can hand it t
624
624
  | **Switch platforms** | Rewrite everything | Change `--target` |
625
625
  | **Add an agent** | Update 5-12 files across 3 tools | Add 4 lines to `.at` file |
626
626
  | **See the architecture** | Read YAML, JSON, TOML, Markdown across 6 dirs | One `.at` file. Or `visualize` it. |
627
- | **Validate** | Hope for the best | 93 built-in rules catch errors before deploy |
627
+ | **Validate** | Hope for the best | 97 built-in rules catch errors before deploy |
628
628
  | **Onboard someone** | "Read these 15 files and figure it out" | "Read this `.at` file" |
629
629
  | **Version control** | Diff 47 generated files | Diff one `.at` file |
630
630
  | **Move to a new tool** | Start over | `--target new-tool` |
@@ -646,7 +646,7 @@ You can `agentopology visualize` it into an interactive graph. You can hand it t
646
646
  ## CLI Reference
647
647
 
648
648
  ```
649
- agentopology validate <file> Validate an .at file (93 rules)
649
+ agentopology validate <file> Validate an .at file (97 rules)
650
650
  agentopology plan <file> Resolve for interpreted execution — no files written
651
651
  agentopology scaffold <file> --target <t> Generate platform configs
652
652
  agentopology sync <file> --target <t> --dir <d> Sync platform files back to .at
@@ -0,0 +1,16 @@
1
+ /**
2
+ * End to end: a system built by hand comes into .at without losing anything.
3
+ *
4
+ * The rule (Nadav, 2026-10-29): AgentTopology gives the structure; bringing a
5
+ * hand-built system into it must never delete its internals. Before this,
6
+ * import then scaffold on this repo's own .claude left 0 of 72 files
7
+ * identical, 37 missing and the rest cut down (a 404-line SKILL.md came back
8
+ * as 9 lines), and the imported .at had 22 validation errors.
9
+ *
10
+ * The fixture (fixtures/handbuilt) holds what was lost: a flat and a folder
11
+ * agent, frontmatter the language has no field for, a comma-string tools
12
+ * list, a skill with scripts and references, a command, real permissions and
13
+ * a hand-written hook.
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=roundtrip.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roundtrip.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/e2e/roundtrip.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * End to end: a system built by hand comes into .at without losing anything.
3
+ *
4
+ * The rule (Nadav, 2026-10-29): AgentTopology gives the structure; bringing a
5
+ * hand-built system into it must never delete its internals. Before this,
6
+ * import then scaffold on this repo's own .claude left 0 of 72 files
7
+ * identical, 37 missing and the rest cut down (a 404-line SKILL.md came back
8
+ * as 9 lines), and the imported .at had 22 validation errors.
9
+ *
10
+ * The fixture (fixtures/handbuilt) holds what was lost: a flat and a folder
11
+ * agent, frontmatter the language has no field for, a comma-string tools
12
+ * list, a skill with scripts and references, a command, real permissions and
13
+ * a hand-written hook.
14
+ */
15
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
16
+ import { execFileSync } from "node:child_process";
17
+ import { createHash } from "node:crypto";
18
+ import * as fs from "node:fs";
19
+ import * as os from "node:os";
20
+ import { resolve, dirname, join, relative } from "node:path";
21
+ import { fileURLToPath } from "node:url";
22
+ import { parse } from "../../parser/index.js";
23
+ import { validate } from "../../parser/validator.js";
24
+ import { claudeCodeBinding } from "../../bindings/claude-code.js";
25
+ import { deepMergeSettingsJson } from "../../scaffold/merge.js";
26
+ const here = dirname(fileURLToPath(import.meta.url));
27
+ const root = resolve(here, "../../..");
28
+ const CLI = resolve(root, "dist/cli/index.js");
29
+ const HANDBUILT = resolve(here, "fixtures/handbuilt");
30
+ function cli(args) {
31
+ try {
32
+ const out = execFileSync(process.execPath, [CLI, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
33
+ return { out, code: 0 };
34
+ }
35
+ catch (err) {
36
+ const e = err;
37
+ return { out: `${e.stdout ?? ""}${e.stderr ?? ""}`, code: e.status ?? 1 };
38
+ }
39
+ }
40
+ /** path -> sha1 of every file under dir. */
41
+ function snapshot(dir) {
42
+ const out = new Map();
43
+ const walk = (d) => {
44
+ for (const e of fs.readdirSync(d, { withFileTypes: true })) {
45
+ const p = join(d, e.name);
46
+ if (e.isDirectory())
47
+ walk(p);
48
+ else
49
+ out.set(relative(dir, p), createHash("sha1").update(fs.readFileSync(p)).digest("hex"));
50
+ }
51
+ };
52
+ walk(dir);
53
+ return out;
54
+ }
55
+ let tmp;
56
+ let project;
57
+ let at;
58
+ beforeEach(() => {
59
+ tmp = fs.mkdtempSync(join(os.tmpdir(), "at-roundtrip-"));
60
+ project = join(tmp, "project");
61
+ fs.cpSync(HANDBUILT, project, { recursive: true });
62
+ at = join(tmp, "handbuilt.at");
63
+ expect(cli(["import", "--target", "claude-code", "--dir", project, "--name", "handbuilt", "--output", tmp]).code).toBe(0);
64
+ });
65
+ afterEach(() => {
66
+ fs.rmSync(tmp, { recursive: true, force: true });
67
+ });
68
+ describe("import then scaffold loses nothing (e2e)", () => {
69
+ it("[R3] the imported .at validates with no errors", () => {
70
+ const errors = validate(parse(fs.readFileSync(at, "utf-8"))).filter((r) => r.level === "error");
71
+ expect(errors.map((e) => `[${e.rule}] ${e.message}`)).toEqual([]);
72
+ });
73
+ it("[R1] every hand-built file is still there after scaffolding the import back", () => {
74
+ const before = snapshot(project);
75
+ expect(cli(["scaffold", at, "--target", "claude-code", "--output", project]).code).toBe(0);
76
+ const after = snapshot(project);
77
+ const missing = [...before.keys()].filter((p) => !after.has(p));
78
+ expect(missing).toEqual([]);
79
+ });
80
+ it("[R2] every hand-built file is byte-identical, settings.json included", () => {
81
+ const before = snapshot(project);
82
+ cli(["scaffold", at, "--target", "claude-code", "--output", project]);
83
+ const after = snapshot(project);
84
+ const changed = [...before].filter(([p, h]) => after.get(p) !== h).map(([p]) => p);
85
+ expect(changed).toEqual([]);
86
+ });
87
+ it("[A4] even --force leaves every hand-written file byte-identical", () => {
88
+ // Two layers protect a hand-built file: scaffold keeps files it did not
89
+ // create (G1), and file: means the binding never generates them at all.
90
+ // --force removes the first layer, so this proves the second on its own.
91
+ const before = snapshot(project);
92
+ expect(cli(["scaffold", at, "--target", "claude-code", "--output", project, "--force"]).code).toBe(0);
93
+ const after = snapshot(project);
94
+ const changed = [...before].filter(([p, h]) => after.get(p) !== h).map(([p]) => p);
95
+ expect(changed).toEqual([]);
96
+ });
97
+ it("[G12] a second scaffold of the import changes nothing", () => {
98
+ cli(["scaffold", at, "--target", "claude-code", "--output", project]);
99
+ expect(cli(["scaffold", at, "--target", "claude-code", "--output", project]).out).toMatch(/ 0 created, 0 updated/);
100
+ });
101
+ it("[R4] import keeps what the language has no field for, and the real permissions", () => {
102
+ const ast = parse(fs.readFileSync(at, "utf-8"));
103
+ const reviewer = ast.nodes.find((n) => n.id === "reviewer");
104
+ expect(reviewer.file).toBe(".claude/agents/reviewer.md");
105
+ expect(reviewer.extensions?.["claude-code"]).toMatchObject({
106
+ effort: "high",
107
+ color: "purple",
108
+ });
109
+ expect(reviewer.tools).toEqual(["Read", "Grep", "Glob"]);
110
+ expect(ast.settings.allow).toContain("Read");
111
+ expect(ast.settings.ask).toEqual(["Bash(git push:*)"]);
112
+ });
113
+ it("[A4] skills, commands and agents found on disk are marked file: and never generated", () => {
114
+ const ast = parse(fs.readFileSync(at, "utf-8"));
115
+ expect(ast.skills.find((s) => s.id === "story")?.file).toBe(".claude/skills/story/SKILL.md");
116
+ expect(ast.triggers.find((t) => t.name === "ship")?.file).toBe(".claude/commands/ship.md");
117
+ const paths = claudeCodeBinding.scaffold(ast).map((f) => f.path);
118
+ expect(paths.filter((p) => p.startsWith(".claude/skills/story/"))).toEqual([]);
119
+ expect(paths).not.toContain(".claude/commands/ship.md");
120
+ expect(paths).not.toContain(".claude/agents/reviewer/AGENT.md");
121
+ expect(paths).not.toContain(".claude/agents/writer/AGENT.md");
122
+ });
123
+ it("[G13] an agent's extensions never leak into project-wide settings", () => {
124
+ cli(["scaffold", at, "--target", "claude-code", "--output", project]);
125
+ const settings = JSON.parse(fs.readFileSync(join(project, ".claude/settings.json"), "utf-8"));
126
+ expect(settings.effort).toBeUndefined();
127
+ expect(settings.color).toBeUndefined();
128
+ });
129
+ it("[G14] an imported hook and its compiled form are one hook, not two", () => {
130
+ const existing = JSON.stringify({
131
+ hooks: { PreToolUse: [{ matcher: "Bash", hooks: [{ type: "command", command: "bash .claude/hooks/guard.sh" }] }] },
132
+ });
133
+ const generated = JSON.stringify({
134
+ hooks: { PreToolUse: [{ matcher: "Bash", hooks: [{ type: "command", command: 'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/guard.sh"' }] }] },
135
+ });
136
+ const merged = JSON.parse(deepMergeSettingsJson(existing, generated));
137
+ expect(merged.hooks.PreToolUse).toHaveLength(1);
138
+ });
139
+ });
140
+ describe("an on-demand agent needs no flow path", () => {
141
+ it("[G17] V11 skips a reader or writer with invocation: manual", () => {
142
+ const src = fs.readFileSync(at, "utf-8")
143
+ .replace("agent reviewer {", 'agent reviewer {\n reads: ["drafts/"]')
144
+ .replace("agent writer {", 'agent writer {\n writes: ["drafts/"]');
145
+ expect(validate(parse(src)).filter((r) => r.rule === "V11")).toEqual([]);
146
+ });
147
+ });
148
+ describe("file: is checked, and scaffold's two overrides are separate", () => {
149
+ it("[G15] V97 refuses a file: outside the project", () => {
150
+ const src = fs.readFileSync(at, "utf-8").replace("file: .claude/agents/reviewer.md", 'file: "../elsewhere/reviewer.md"');
151
+ const errors = validate(parse(src)).filter((r) => r.rule === "V97");
152
+ expect(errors).toHaveLength(1);
153
+ });
154
+ it("[F3] --allow-invalid compiles despite errors; --force alone does not", () => {
155
+ fs.writeFileSync(at, fs.readFileSync(at, "utf-8").replace("file: .claude/agents/reviewer.md", 'file: "../x.md"'));
156
+ const forced = cli(["scaffold", at, "--target", "claude-code", "--output", project, "--force"]);
157
+ expect(forced.code).toBe(1);
158
+ expect(forced.out).toContain("Nothing was written");
159
+ const allowed = cli(["scaffold", at, "--target", "claude-code", "--output", project, "--allow-invalid"]);
160
+ expect(allowed.code).toBe(0);
161
+ // --allow-invalid does not overwrite what scaffold did not create.
162
+ expect(fs.readFileSync(join(project, ".claude/hooks/guard.sh"), "utf-8")).toContain("Blocks a push");
163
+ });
164
+ it("[C5] a hook's own script is never overwritten, even with --force, and not reported as a conflict", () => {
165
+ const { out } = cli(["scaffold", at, "--target", "claude-code", "--output", project, "--force"]);
166
+ expect(fs.readFileSync(join(project, ".claude/hooks/guard.sh"), "utf-8")).toContain("Blocks a push");
167
+ expect(out).not.toContain("guard.sh (exists");
168
+ const manifest = JSON.parse(fs.readFileSync(join(project, ".claude/.scaffold-manifest.json"), "utf-8"));
169
+ expect(manifest.files[".claude/hooks/guard.sh"]).toBeUndefined();
170
+ });
171
+ it("[G16] scaffold names a hand-written file the project lacks", () => {
172
+ fs.rmSync(join(project, ".claude/commands/ship.md"));
173
+ const { out } = cli(["scaffold", at, "--target", "claude-code", "--output", project, "--dry-run"]);
174
+ expect(out).toContain(".claude/commands/ship.md");
175
+ expect(out).toMatch(/hand-written file\(s\) named by file: are not in/);
176
+ });
177
+ });
178
+ //# sourceMappingURL=roundtrip.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roundtrip.test.js","sourceRoot":"","sources":["../../../src/__tests__/e2e/roundtrip.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AACvC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;AAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AAEtD,SAAS,GAAG,CAAC,IAAc;IACzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACpH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,GAA4D,CAAC;QACvE,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,4CAA4C;AAC5C,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE;QACzB,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3D,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC1B,IAAI,CAAC,CAAC,WAAW,EAAE;gBAAE,IAAI,CAAC,CAAC,CAAC,CAAC;;gBACxB,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9F,CAAC;IACH,CAAC,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,GAAG,CAAC;AACb,CAAC;AAED,IAAI,GAAW,CAAC;AAChB,IAAI,OAAe,CAAC;AACpB,IAAI,EAAU,CAAC;AAEf,UAAU,CAAC,GAAG,EAAE;IACd,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IACzD,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC/B,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5H,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACb,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACxD,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;QAChG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACtE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,wEAAwE;QACxE,wEAAwE;QACxE,yEAAyE;QACzE,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtG,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACtE,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACrH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,GAAG,GAAG,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAE,CAAC;QAC7D,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACzD,MAAM,CAAE,QAAqE,CAAC,UAAU,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC;YACvH,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAC;QACH,MAAM,CAAE,QAAiC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE,GAAG,EAAE;QAC7F,MAAM,GAAG,GAAG,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC7F,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC/E,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAChE,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAG,EAAE;QAC3E,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,uBAAuB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9F,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;YAC9B,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,EAAE,CAAC,EAAE;SACnH,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;YAC/B,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,mDAAmD,EAAE,CAAC,EAAE,CAAC,EAAE;SACzI,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;QACtE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC;aACrC,OAAO,CAAC,kBAAkB,EAAE,0CAA0C,CAAC;aACvE,OAAO,CAAC,gBAAgB,EAAE,yCAAyC,CAAC,CAAC;QACxE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,6DAA6D,EAAE,GAAG,EAAE;IAC3E,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,kCAAkC,EAAE,kCAAkC,CAAC,CAAC;QACzH,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,kCAAkC,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAClH,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;QAChG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC;QACzG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7B,mEAAmE;QACnE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACvG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kGAAkG,EAAE,GAAG,EAAE;QAC1G,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;QACjG,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,wBAAwB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QACrG,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,iCAAiC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QACxG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,0BAA0B,CAAC,CAAC,CAAC;QACrD,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;QACnG,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,kDAAkD,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * End to end: scaffold only changes what it owns.
3
+ *
4
+ * Each test runs the built CLI as a user would, against a temporary project
5
+ * that holds the hazards a real harness hit on 2026-10-28. Test names carry
6
+ * the guarantee id from spec/testing.md; spec-testing-sync.test.ts fails if a
7
+ * guarantee there has no test here or elsewhere.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=scaffold-owns.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold-owns.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/e2e/scaffold-owns.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * End to end: scaffold only changes what it owns.
3
+ *
4
+ * Each test runs the built CLI as a user would, against a temporary project
5
+ * that holds the hazards a real harness hit on 2026-10-28. Test names carry
6
+ * the guarantee id from spec/testing.md; spec-testing-sync.test.ts fails if a
7
+ * guarantee there has no test here or elsewhere.
8
+ */
9
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
10
+ import { execFileSync } from "node:child_process";
11
+ import * as fs from "node:fs";
12
+ import * as os from "node:os";
13
+ import { resolve, dirname, join } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
16
+ const CLI = resolve(root, "dist/cli/index.js");
17
+ const FIXTURE = resolve(dirname(fileURLToPath(import.meta.url)), "fixtures/hazards.at");
18
+ function cli(args) {
19
+ try {
20
+ const out = execFileSync(process.execPath, [CLI, ...args], {
21
+ encoding: "utf8",
22
+ stdio: ["ignore", "pipe", "pipe"],
23
+ });
24
+ return { out, code: 0 };
25
+ }
26
+ catch (err) {
27
+ const e = err;
28
+ return { out: `${e.stdout ?? ""}${e.stderr ?? ""}`, code: e.status ?? 1 };
29
+ }
30
+ }
31
+ let tmp;
32
+ let project;
33
+ let otherRepo;
34
+ let at;
35
+ const file = (rel) => join(project, rel);
36
+ const read = (rel) => fs.readFileSync(file(rel), "utf-8");
37
+ const put = (rel, content) => {
38
+ fs.mkdirSync(dirname(file(rel)), { recursive: true });
39
+ fs.writeFileSync(file(rel), content);
40
+ };
41
+ const scaffold = (...extra) => cli(["scaffold", at, "--target", "claude-code", "--output", project, ...extra]);
42
+ const USER_SETTINGS = {
43
+ permissions: { ask: ["Bash(git push:*)"], defaultMode: "acceptEdits" },
44
+ hooks: { PreToolUse: [{ matcher: "Bash", hooks: [{ type: "command", command: "bash ./my-guard.sh" }] }] },
45
+ };
46
+ beforeEach(() => {
47
+ tmp = fs.mkdtempSync(join(os.tmpdir(), "at-e2e-"));
48
+ project = join(tmp, "project");
49
+ otherRepo = join(tmp, "other-repo");
50
+ at = join(tmp, "hazards.at");
51
+ fs.copyFileSync(FIXTURE, at);
52
+ // A hand-written skill, a skill linked from another repository, and the
53
+ // user's own settings — what the content repo actually had.
54
+ put(".claude/skills/story/SKILL.md", "REAL STORY SKILL\n");
55
+ fs.mkdirSync(join(otherRepo, "the-book"), { recursive: true });
56
+ fs.writeFileSync(join(otherRepo, "the-book/SKILL.md"), "OTHER REPO BOOK\n");
57
+ fs.symlinkSync(join(otherRepo, "the-book"), file(".claude/skills/the-book"));
58
+ put(".claude/settings.json", JSON.stringify(USER_SETTINGS, null, 2));
59
+ });
60
+ afterEach(() => {
61
+ fs.rmSync(tmp, { recursive: true, force: true });
62
+ });
63
+ describe("scaffold only changes what it owns (e2e)", () => {
64
+ it("[G1] the first scaffold keeps a file it did not create", () => {
65
+ const { out, code } = scaffold();
66
+ expect(code).toBe(0);
67
+ expect(read(".claude/skills/story/SKILL.md")).toBe("REAL STORY SKILL\n");
68
+ expect(out).toContain("exists, not created by scaffold — kept");
69
+ expect(fs.existsSync(file(".claude/agents/writer/AGENT.md"))).toBe(true);
70
+ });
71
+ it("[G2] never writes through a symlink, even with --force", () => {
72
+ scaffold("--force");
73
+ expect(fs.readFileSync(join(otherRepo, "the-book/SKILL.md"), "utf-8")).toBe("OTHER REPO BOOK\n");
74
+ });
75
+ it("[G3] keeps the user's hooks, ask rules and defaultMode across runs", () => {
76
+ scaffold();
77
+ scaffold();
78
+ const settings = JSON.parse(read(".claude/settings.json"));
79
+ expect(settings.permissions.ask).toEqual(["Bash(git push:*)"]);
80
+ expect(settings.permissions.defaultMode).toBe("acceptEdits");
81
+ expect(JSON.stringify(settings.hooks)).toContain("my-guard.sh");
82
+ expect(settings.permissions.allow).toContain("Read");
83
+ });
84
+ it("[G4] a second run changes nothing", () => {
85
+ scaffold();
86
+ const { out } = scaffold();
87
+ expect(out).toMatch(/ 0 created, 0 updated, \d+ unchanged/);
88
+ });
89
+ it("[G5] --dry-run writes nothing", () => {
90
+ const before = fs.readdirSync(project, { recursive: true }).length;
91
+ expect(scaffold("--dry-run").code).toBe(0);
92
+ expect(fs.readdirSync(project, { recursive: true }).length).toBe(before);
93
+ });
94
+ it("[G6] prose in a gate's run fails validate and scaffold, and nothing is written", () => {
95
+ const prose = "pxframes gate mean >= 3.85, no frame < 3; frames 0.0 / 0.5 / 3.0 s differ";
96
+ fs.writeFileSync(at, fs.readFileSync(at, "utf-8").replace('run: "scripts/check-quality.sh"', `run: "${prose}"`));
97
+ const v = cli(["validate", at]);
98
+ expect(v.code).toBe(1);
99
+ expect(v.out).toContain("[V96]");
100
+ const s = scaffold();
101
+ expect(s.code).toBe(1);
102
+ expect(s.out).toContain("Nothing was written");
103
+ expect(fs.existsSync(file(".claude/agents"))).toBe(false);
104
+ });
105
+ it("[G7] an edited file scaffold owns is kept on the next run", () => {
106
+ scaffold();
107
+ put(".claude/CLAUDE.md", read(".claude/CLAUDE.md") + "my own note\n");
108
+ const { out } = scaffold();
109
+ expect(read(".claude/CLAUDE.md")).toContain("my own note");
110
+ expect(out).toContain(".claude/CLAUDE.md (user edited — kept)");
111
+ });
112
+ it("[G8] --prune removes untouched leftovers and keeps edited ones", () => {
113
+ scaffold();
114
+ const wrapper = ".claude/skills/hazards/scripts/gate-quality-check.sh";
115
+ const check = ".claude/skills/hazards/scripts/check-quality.sh";
116
+ expect(fs.existsSync(file(wrapper))).toBe(true);
117
+ put(check, "#!/bin/bash\n# my real check\n");
118
+ // Rename the gate and its script: both old files are now leftovers.
119
+ fs.writeFileSync(at, fs.readFileSync(at, "utf-8")
120
+ .replace("gate quality-check {", "gate quality-check-v2 {")
121
+ .replace('run: "scripts/check-quality.sh"', 'run: "scripts/check-v2.sh"'));
122
+ const { code, out } = scaffold("--prune");
123
+ expect(code, out).toBe(0);
124
+ expect(fs.existsSync(file(wrapper))).toBe(false);
125
+ expect(read(check)).toContain("my real check");
126
+ expect(out).toContain("no longer generated, but edited — kept");
127
+ });
128
+ it("[G9] a second topology in the same project keeps its own manifest", () => {
129
+ scaffold();
130
+ const other = join(tmp, "other.at");
131
+ fs.writeFileSync(other, fs.readFileSync(at, "utf-8").replace("topology hazards :", "topology other :"));
132
+ cli(["scaffold", other, "--target", "claude-code", "--output", project]);
133
+ expect(fs.existsSync(file(".claude/.scaffold-manifest.json"))).toBe(true);
134
+ expect(fs.existsSync(file(".claude/.scaffold-manifest.other.at.json"))).toBe(true);
135
+ // The first topology still owns its files: a rerun changes nothing.
136
+ expect(scaffold().out).toMatch(/ 0 created, 0 updated/);
137
+ });
138
+ });
139
+ describe("every example compiles to files Claude Code can load", () => {
140
+ const examples = fs.readdirSync(resolve(root, "examples")).filter((f) => f.endsWith(".at"));
141
+ it.each(examples)("[G10] %s: no ${…} reference reaches settings env", (name) => {
142
+ const out = join(tmp, name);
143
+ expect(cli(["scaffold", resolve(root, "examples", name), "--target", "claude-code", "--output", out]).code).toBe(0);
144
+ const settingsPath = join(out, ".claude/settings.json");
145
+ if (!fs.existsSync(settingsPath))
146
+ return;
147
+ const env = JSON.parse(fs.readFileSync(settingsPath, "utf-8")).env ?? {};
148
+ for (const [k, v] of Object.entries(env)) {
149
+ expect(String(v), `env.${k}`).not.toContain("${");
150
+ expect(k).not.toMatch(/^#/);
151
+ }
152
+ });
153
+ });
154
+ //# sourceMappingURL=scaffold-owns.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold-owns.test.js","sourceRoot":"","sources":["../../../src/__tests__/e2e/scaffold-owns.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Build once before any test runs, so tests that execute `dist/cli/index.js`
3
+ * always test the current source. They used to run whatever dist/ happened to
4
+ * be on disk — a change could pass against stale output.
5
+ */
6
+ export default function setup(): void;
7
+ //# sourceMappingURL=global-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-setup.d.ts","sourceRoot":"","sources":["../../src/__tests__/global-setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,CAAC,OAAO,UAAU,KAAK,IAAI,IAAI,CAMpC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Build once before any test runs, so tests that execute `dist/cli/index.js`
3
+ * always test the current source. They used to run whatever dist/ happened to
4
+ * be on disk — a change could pass against stale output.
5
+ */
6
+ import { execFileSync } from "node:child_process";
7
+ import { resolve, dirname } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ export default function setup() {
10
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
11
+ execFileSync(process.execPath, [resolve(root, "node_modules/typescript/bin/tsc")], {
12
+ cwd: root,
13
+ stdio: "inherit",
14
+ });
15
+ }
16
+ //# sourceMappingURL=global-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global-setup.js","sourceRoot":"","sources":["../../src/__tests__/global-setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,OAAO,UAAU,KAAK;IAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACvE,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,iCAAiC,CAAC,CAAC,EAAE;QACjF,GAAG,EAAE,IAAI;QACT,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Live: real Claude Code loads what scaffold generates.
3
+ *
4
+ * Unit tests check the files we write; only Claude Code can say whether it
5
+ * reads them. This scaffolds every example (and the hazards fixture) into a
6
+ * temporary project, starts a headless `claude -p` session there, and checks
7
+ * the session's init report: every generated agent, skill and command is
8
+ * registered, and the session itself succeeds.
9
+ *
10
+ * It found the first bug the moment it ran: settings `env` carried the literal
11
+ * text "${ANTHROPIC_API_KEY}", which Claude Code applied as the key, so every
12
+ * session in 6 of the 10 example projects failed with "Invalid API key".
13
+ *
14
+ * Opt-in, because it needs the `claude` CLI and makes one small model call per
15
+ * project: AT_LIVE=1 npx vitest run src/__tests__/live
16
+ * The session is isolated from the developer's own setup: user settings (and
17
+ * their hooks), MCP servers and session history are all left out.
18
+ */
19
+ export {};
20
+ //# sourceMappingURL=claude-code.live.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code.live.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/live/claude-code.live.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG"}