agentopology 0.2.0 → 0.2.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 (78) hide show
  1. package/README.md +7 -5
  2. package/dist/analyzer/__tests__/observability-gap.test.d.ts +8 -0
  3. package/dist/analyzer/__tests__/observability-gap.test.d.ts.map +1 -0
  4. package/dist/analyzer/__tests__/observability-gap.test.js +132 -0
  5. package/dist/analyzer/__tests__/observability-gap.test.js.map +1 -0
  6. package/dist/analyzer/index.d.ts +1 -1
  7. package/dist/analyzer/index.d.ts.map +1 -1
  8. package/dist/analyzer/index.js +26 -0
  9. package/dist/analyzer/index.js.map +1 -1
  10. package/dist/bindings/__tests__/bindings.test.js +288 -11
  11. package/dist/bindings/__tests__/bindings.test.js.map +1 -1
  12. package/dist/bindings/__tests__/observability.test.d.ts +9 -0
  13. package/dist/bindings/__tests__/observability.test.d.ts.map +1 -0
  14. package/dist/bindings/__tests__/observability.test.js +136 -0
  15. package/dist/bindings/__tests__/observability.test.js.map +1 -0
  16. package/dist/bindings/__tests__/stub-generation.test.d.ts +16 -0
  17. package/dist/bindings/__tests__/stub-generation.test.d.ts.map +1 -0
  18. package/dist/bindings/__tests__/stub-generation.test.js +117 -0
  19. package/dist/bindings/__tests__/stub-generation.test.js.map +1 -0
  20. package/dist/bindings/claude-code.d.ts.map +1 -1
  21. package/dist/bindings/claude-code.js +159 -110
  22. package/dist/bindings/claude-code.js.map +1 -1
  23. package/dist/bindings/codex.d.ts.map +1 -1
  24. package/dist/bindings/codex.js +1 -12
  25. package/dist/bindings/codex.js.map +1 -1
  26. package/dist/bindings/cursor.d.ts.map +1 -1
  27. package/dist/bindings/cursor.js +0 -12
  28. package/dist/bindings/cursor.js.map +1 -1
  29. package/dist/bindings/gemini-cli.d.ts.map +1 -1
  30. package/dist/bindings/gemini-cli.js +1 -12
  31. package/dist/bindings/gemini-cli.js.map +1 -1
  32. package/dist/bindings/kiro.d.ts.map +1 -1
  33. package/dist/bindings/kiro.js +1 -12
  34. package/dist/bindings/kiro.js.map +1 -1
  35. package/dist/bindings/lib/__tests__/stub.test.d.ts +8 -0
  36. package/dist/bindings/lib/__tests__/stub.test.d.ts.map +1 -0
  37. package/dist/bindings/lib/__tests__/stub.test.js +66 -0
  38. package/dist/bindings/lib/__tests__/stub.test.js.map +1 -0
  39. package/dist/bindings/lib/stub.d.ts +56 -0
  40. package/dist/bindings/lib/stub.d.ts.map +1 -0
  41. package/dist/bindings/lib/stub.js +69 -0
  42. package/dist/bindings/lib/stub.js.map +1 -0
  43. package/dist/bindings/openclaw.d.ts.map +1 -1
  44. package/dist/bindings/openclaw.js +1 -12
  45. package/dist/bindings/openclaw.js.map +1 -1
  46. package/dist/bindings/types.d.ts +5 -0
  47. package/dist/bindings/types.d.ts.map +1 -1
  48. package/dist/bindings/types.js.map +1 -1
  49. package/dist/cli/index.js +89 -4
  50. package/dist/cli/index.js.map +1 -1
  51. package/dist/docs/content.d.ts.map +1 -1
  52. package/dist/docs/content.js +9 -5
  53. package/dist/docs/content.js.map +1 -1
  54. package/dist/import/__tests__/import.test.js +2 -2
  55. package/dist/import/__tests__/import.test.js.map +1 -1
  56. package/dist/parser/__tests__/parser.test.js +31 -3
  57. package/dist/parser/__tests__/parser.test.js.map +1 -1
  58. package/dist/parser/validator.d.ts.map +1 -1
  59. package/dist/parser/validator.js +28 -8
  60. package/dist/parser/validator.js.map +1 -1
  61. package/dist/scaffold/__tests__/scaffold.test.js +20 -0
  62. package/dist/scaffold/__tests__/scaffold.test.js.map +1 -1
  63. package/dist/scaffold/__tests__/settings-merge.test.d.ts +15 -0
  64. package/dist/scaffold/__tests__/settings-merge.test.d.ts.map +1 -0
  65. package/dist/scaffold/__tests__/settings-merge.test.js +127 -0
  66. package/dist/scaffold/__tests__/settings-merge.test.js.map +1 -0
  67. package/dist/scaffold/incremental.d.ts.map +1 -1
  68. package/dist/scaffold/incremental.js +11 -2
  69. package/dist/scaffold/incremental.js.map +1 -1
  70. package/dist/scaffold/merge.d.ts +16 -0
  71. package/dist/scaffold/merge.d.ts.map +1 -1
  72. package/dist/scaffold/merge.js +77 -0
  73. package/dist/scaffold/merge.js.map +1 -1
  74. package/dist/scaffold/types.d.ts +2 -0
  75. package/dist/scaffold/types.d.ts.map +1 -1
  76. package/examples/simple-pipeline-topology.html +5700 -0
  77. package/package.json +2 -1
  78. package/skill/SKILL.md +7 -7
package/README.md CHANGED
@@ -156,7 +156,7 @@ In Claude Code, type `/agentopology` — or just ask naturally:
156
156
  Say **"I want a code review team with an analyzer, security scanner, and reviewer"** — the skill:
157
157
 
158
158
  1. Generates the `.at` file with the right syntax
159
- 2. Validates it against 29 rules
159
+ 2. Validates it against 82 rules
160
160
  3. Scaffolds it to Claude Code, OpenClaw, Cursor, or any target
161
161
 
162
162
  **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.
@@ -452,13 +452,15 @@ You can `agentopology visualize` it into an interactive graph. You can hand it t
452
452
  ## CLI Reference
453
453
 
454
454
  ```
455
- agentopology validate <file> Validate an .at file
455
+ agentopology validate <file> Validate an .at file (82 rules)
456
456
  agentopology scaffold <file> --target <t> Generate platform configs
457
+ agentopology sync <file> --target <t> --dir <d> Sync platform files back to .at
458
+ agentopology import --target <t> --dir <d> Reverse-engineer platform files to .at
457
459
  agentopology visualize <file> Interactive topology graph
460
+ agentopology export <file> --format <fmt> Export as markdown, mermaid, or json
461
+ agentopology info <file> Topology analysis and suggestions
458
462
  agentopology targets List supported platforms
459
- agentopology docs [topic] Language reference
460
- agentopology info <file> Topology summary
461
- agentopology export <file> --format json Export AST as JSON
463
+ agentopology docs [topic] Language reference (42 topics)
462
464
  ```
463
465
 
464
466
  ---
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Tests for Change 2: agentopology info warns about observability gaps.
3
+ *
4
+ * If a topology has agents but no SubagentStop/Stop hook, the analyzer
5
+ * should emit a warning-level suggestion.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=observability-gap.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability-gap.test.d.ts","sourceRoot":"","sources":["../../../src/analyzer/__tests__/observability-gap.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Tests for Change 2: agentopology info warns about observability gaps.
3
+ *
4
+ * If a topology has agents but no SubagentStop/Stop hook, the analyzer
5
+ * should emit a warning-level suggestion.
6
+ */
7
+ import { describe, it, expect } from "vitest";
8
+ import { parse } from "../../parser/index.js";
9
+ import { analyze } from "../index.js";
10
+ // ---------------------------------------------------------------------------
11
+ // Topology WITHOUT any hooks — should warn
12
+ // ---------------------------------------------------------------------------
13
+ const NO_HOOKS_TOPOLOGY = `
14
+ topology no-hooks : [pipeline] {
15
+ meta { version: "1.0.0" description: "No hooks at all" }
16
+ orchestrator { model: opus handles: [start] }
17
+ action start { kind: inline }
18
+ agent worker-a { model: sonnet phase: 1 prompt { You are worker-a. } }
19
+ agent worker-b { model: haiku phase: 2 prompt { You are worker-b. } }
20
+ flow { start -> worker-a -> worker-b }
21
+ }
22
+ `;
23
+ // Topology WITH SubagentStop hook — should NOT warn
24
+ const WITH_SUBAGENT_STOP_TOPOLOGY = `
25
+ topology with-hooks : [pipeline] {
26
+ meta { version: "1.0.0" description: "Has SubagentStop hook" }
27
+ orchestrator { model: opus handles: [start] }
28
+ action start { kind: inline }
29
+ agent worker { model: sonnet phase: 1 prompt { You are worker. } }
30
+ flow { start -> worker }
31
+ hooks {
32
+ hook log-finish {
33
+ on: SubagentStop
34
+ matcher: "worker"
35
+ run: ".claude/scripts/log.sh"
36
+ type: command
37
+ }
38
+ }
39
+ }
40
+ `;
41
+ // Topology WITH Stop hook — should NOT warn
42
+ const WITH_STOP_TOPOLOGY = `
43
+ topology with-stop : [pipeline] {
44
+ meta { version: "1.0.0" description: "Has Stop hook" }
45
+ orchestrator { model: opus handles: [start] }
46
+ action start { kind: inline }
47
+ agent worker { model: sonnet phase: 1 prompt { You are worker. } }
48
+ flow { start -> worker }
49
+ hooks {
50
+ hook on-stop {
51
+ on: Stop
52
+ matcher: ""
53
+ run: ".claude/scripts/stop.sh"
54
+ type: command
55
+ }
56
+ }
57
+ }
58
+ `;
59
+ // Topology WITH enforced gate (compiles to SubagentStop) — should NOT warn
60
+ const WITH_GATE_TOPOLOGY = `
61
+ topology with-gate : [pipeline] {
62
+ meta { version: "1.0.0" description: "Has an enforced gate" }
63
+ orchestrator { model: opus handles: [start] }
64
+ action start { kind: inline }
65
+ agent worker { model: sonnet phase: 1 prompt { You are worker. } }
66
+ flow { start -> worker }
67
+ gates {
68
+ gate quality-check {
69
+ after: worker
70
+ run: "scripts/check.sh"
71
+ checks: [lint]
72
+ on-fail: halt
73
+ }
74
+ }
75
+ }
76
+ `;
77
+ // Zero-agent topology — should NOT warn
78
+ const ZERO_AGENTS_TOPOLOGY = `
79
+ topology zero-agents : [pipeline] {
80
+ meta { version: "1.0.0" description: "No agents" }
81
+ orchestrator { model: opus handles: [start, done] }
82
+ action start { kind: inline }
83
+ action done { kind: report }
84
+ flow { start -> done }
85
+ }
86
+ `;
87
+ describe("Change 2 — observability gap warning", () => {
88
+ it("warns when topology has agents but NO hooks at all", () => {
89
+ const ast = parse(NO_HOOKS_TOPOLOGY);
90
+ const result = analyze(ast);
91
+ const obsWarning = result.suggestions.find((s) => s.message.includes("Observability gap"));
92
+ expect(obsWarning).toBeDefined();
93
+ expect(obsWarning.level).toBe("warning");
94
+ });
95
+ it("warning message contains agent count", () => {
96
+ const ast = parse(NO_HOOKS_TOPOLOGY);
97
+ const result = analyze(ast);
98
+ const obsWarning = result.suggestions.find((s) => s.message.includes("Observability gap"));
99
+ expect(obsWarning.message).toContain("2");
100
+ });
101
+ it("warning message references SubagentStop", () => {
102
+ const ast = parse(NO_HOOKS_TOPOLOGY);
103
+ const result = analyze(ast);
104
+ const obsWarning = result.suggestions.find((s) => s.message.includes("Observability gap"));
105
+ expect(obsWarning.message).toContain("SubagentStop");
106
+ });
107
+ it("does NOT warn when topology has a SubagentStop hook", () => {
108
+ const ast = parse(WITH_SUBAGENT_STOP_TOPOLOGY);
109
+ const result = analyze(ast);
110
+ const obsWarning = result.suggestions.find((s) => s.message.includes("Observability gap"));
111
+ expect(obsWarning).toBeUndefined();
112
+ });
113
+ it("does NOT warn when topology has a Stop hook", () => {
114
+ const ast = parse(WITH_STOP_TOPOLOGY);
115
+ const result = analyze(ast);
116
+ const obsWarning = result.suggestions.find((s) => s.message.includes("Observability gap"));
117
+ expect(obsWarning).toBeUndefined();
118
+ });
119
+ it("does NOT warn when topology has an enforced gate (compiles to SubagentStop)", () => {
120
+ const ast = parse(WITH_GATE_TOPOLOGY);
121
+ const result = analyze(ast);
122
+ const obsWarning = result.suggestions.find((s) => s.message.includes("Observability gap"));
123
+ expect(obsWarning).toBeUndefined();
124
+ });
125
+ it("does NOT warn for zero-agent topologies", () => {
126
+ const ast = parse(ZERO_AGENTS_TOPOLOGY);
127
+ const result = analyze(ast);
128
+ const obsWarning = result.suggestions.find((s) => s.message.includes("Observability gap"));
129
+ expect(obsWarning).toBeUndefined();
130
+ });
131
+ });
132
+ //# sourceMappingURL=observability-gap.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability-gap.test.js","sourceRoot":"","sources":["../../../src/analyzer/__tests__/observability-gap.test.ts"],"names":[],"mappings":"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"}
@@ -31,7 +31,7 @@ export interface LayerInfo {
31
31
  nodes: string[];
32
32
  }
33
33
  export interface Suggestion {
34
- level: "info" | "improvement";
34
+ level: "info" | "improvement" | "warning";
35
35
  message: string;
36
36
  node?: string;
37
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,WAAW,EAOZ,MAAM,kBAAkB,CAAC;AAM1B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAsVD,wBAAgB,OAAO,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,CAuCxD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,WAAW,EAOZ,MAAM,kBAAkB,CAAC;AAM1B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClC,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,eAAe,CAAC;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAuXD,wBAAgB,OAAO,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,CAuCxD"}
@@ -289,6 +289,32 @@ function generateSuggestions(ast) {
289
289
  });
290
290
  }
291
291
  }
292
+ // Observability gap check (Change 2):
293
+ // If a topology has agents but no SubagentStop or Stop hook (global hooks or
294
+ // enforced gates — which compile to SubagentStop), per-agent finish events
295
+ // will never be captured.
296
+ const agentCount = ast.nodes.filter(isAgent).length;
297
+ if (agentCount > 0) {
298
+ const hasObsHook = (ast.hooks ?? []).some((h) => h.on === "SubagentStop" || h.on === "Stop") ||
299
+ ast.nodes.some((n) => isGate(n) && !!n.run && n.behavior !== "advisory");
300
+ if (!hasObsHook) {
301
+ const agentIds = ast.nodes.filter(isAgent).map((a) => a.id);
302
+ const exampleMatcher = agentIds.slice(0, 3).join("|") + (agentIds.length > 3 ? "|..." : "");
303
+ suggestions.push({
304
+ level: "warning",
305
+ message: `Observability gap: topology has ${agentCount} agent${agentCount !== 1 ? "s" : ""} but no SubagentStop/Stop hook. ` +
306
+ `You won't capture per-agent finish events. Consider adding:\n` +
307
+ ` hooks {\n` +
308
+ ` hook log-subagent-finish {\n` +
309
+ ` on: SubagentStop\n` +
310
+ ` matcher: "${exampleMatcher}"\n` +
311
+ ` run: ".claude/scripts/log-subagent.sh"\n` +
312
+ ` type: command\n` +
313
+ ` }\n` +
314
+ ` }`,
315
+ });
316
+ }
317
+ }
292
318
  return suggestions;
293
319
  }
294
320
  // ---------------------------------------------------------------------------
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { describe, it, expect } from "vitest";
2
2
  import { parse } from "../../parser/index.js";
3
3
  import { bindings, claudeCodeBinding, kiroBinding, cursorBinding, } from "../index.js";
4
+ import { isStubContent, STUB_MARKER } from "../lib/stub.js";
4
5
  // ---------------------------------------------------------------------------
5
6
  // Minimal but valid .at topology exercising most features
6
7
  // ---------------------------------------------------------------------------
@@ -207,8 +208,8 @@ describe("claude-code binding", () => {
207
208
  const mcp = JSON.parse(mcpFile.content);
208
209
  expect(mcp.mcpServers.filesystem).toBeDefined();
209
210
  });
210
- it("produces a context file (.claude/CONTEXT.md, never root CLAUDE.md)", () => {
211
- const contextFile = files.find((f) => f.path === ".claude/CONTEXT.md");
211
+ it("produces a context file (.claude/CLAUDE.md, never root CLAUDE.md)", () => {
212
+ const contextFile = files.find((f) => f.path === ".claude/CLAUDE.md");
212
213
  expect(contextFile).toBeDefined();
213
214
  // Must never generate root-level CLAUDE.md
214
215
  const rootClaudeMd = files.find((f) => f.path === "CLAUDE.md");
@@ -220,12 +221,12 @@ describe("claude-code binding", () => {
220
221
  expect(builderFile.content).toContain("disallowedTools:");
221
222
  expect(builderFile.content).toContain("Edit");
222
223
  });
223
- it("compiles enforced gate to settings.json PreToolUse hook", () => {
224
+ it("compiles enforced gate to settings.json SubagentStop hook with after: agent as matcher", () => {
224
225
  const settingsFile = files.find((f) => f.path === ".claude/settings.json");
225
226
  expect(settingsFile).toBeDefined();
226
227
  const settings = JSON.parse(settingsFile.content);
227
- expect(settings.hooks.PreToolUse).toBeDefined();
228
- const gateHook = settings.hooks.PreToolUse.find((h) => h.matcher === "Task" && JSON.stringify(h).includes("gate-quality-check"));
228
+ expect(settings.hooks.SubagentStop).toBeDefined();
229
+ const gateHook = settings.hooks.SubagentStop.find((h) => h.matcher === "builder" && JSON.stringify(h).includes("gate-quality-check"));
229
230
  expect(gateHook).toBeDefined();
230
231
  });
231
232
  it("does NOT compile advisory gate to settings.json hook", () => {
@@ -238,12 +239,252 @@ describe("claude-code binding", () => {
238
239
  const wrapperScript = files.find((f) => f.path.includes("gate-quality-check.sh"));
239
240
  expect(wrapperScript).toBeDefined();
240
241
  expect(wrapperScript.content).toContain("lint.sh");
241
- expect(wrapperScript.content).toContain("exit 1");
242
+ expect(wrapperScript.content).toContain("exit 2");
242
243
  });
243
244
  it("does NOT generate gate wrapper script for advisory gate", () => {
244
245
  const advisoryWrapper = files.find((f) => f.path.includes("gate-soft-review.sh"));
245
246
  expect(advisoryWrapper).toBeUndefined();
246
247
  });
248
+ it("gate stub contains the AGENTOPOLOGY_STUB marker (#4)", () => {
249
+ // The gate's `run` script is a stub generated by shellStub() in the
250
+ // shared lib. It must carry the marker so tooling can detect it.
251
+ const stub = files.find((f) => f.path.endsWith("/scripts/lint.sh"));
252
+ expect(stub).toBeDefined();
253
+ expect(stub.content).toContain(STUB_MARKER);
254
+ expect(isStubContent(stub.content)).toBe(true);
255
+ });
256
+ });
257
+ // ---------------------------------------------------------------------------
258
+ // claude-code — Issue #3: SubagentStop matcher targeting
259
+ //
260
+ // Per https://code.claude.com/docs/en/hooks.md, the SubagentStop hook's
261
+ // `matcher` field is matched against agent_type (the registered subagent
262
+ // name). Only agent and group nodes scaffold a `.claude/agents/<name>/AGENT.md`
263
+ // file and therefore register as subagent_types. Human, action, and
264
+ // orchestrator targets cannot be matched and would produce dead config that
265
+ // never fires. The scaffolder must skip those hooks (and warn) but still
266
+ // generate the wrapper script so the orchestrator can invoke it directly.
267
+ // ---------------------------------------------------------------------------
268
+ describe("claude-code binding — gate SubagentStop targeting (#3)", () => {
269
+ // Build a topology where one gate targets an agent and another targets a
270
+ // human node — proves both branches of isRegisteredSubagentType.
271
+ const GATE_TARGETING_SOURCE = `
272
+ topology gate-target-test : [pipeline] {
273
+ meta {
274
+ version: "1.0.0"
275
+ description: "Gate targeting test"
276
+ }
277
+
278
+ orchestrator { model: opus handles: [intake] }
279
+ action intake { kind: external source: "user" }
280
+
281
+ agent writer {
282
+ model: sonnet
283
+ phase: 1
284
+ tools: [Read, Write]
285
+ reads: ["workspace/input.md"]
286
+ writes: ["workspace/draft.md"]
287
+ permissions: autonomous
288
+ }
289
+
290
+ human approver {
291
+ description: "Approve the draft before publishing"
292
+ timeout: 1h
293
+ on-timeout: skip
294
+ }
295
+
296
+ agent publisher {
297
+ model: sonnet
298
+ phase: 3
299
+ tools: [Read, Bash]
300
+ reads: ["workspace/draft.md"]
301
+ writes: ["workspace/published.md"]
302
+ permissions: autonomous
303
+ }
304
+
305
+ flow {
306
+ intake -> writer
307
+ writer -> approver
308
+ approver -> publisher
309
+ }
310
+
311
+ gates {
312
+ gate gate-on-agent {
313
+ after: writer
314
+ before: approver
315
+ run: "scripts/check-draft.sh"
316
+ on-fail: bounce-back
317
+ behavior: blocking
318
+ }
319
+ gate gate-on-human {
320
+ after: approver
321
+ before: publisher
322
+ run: "scripts/check-approval.sh"
323
+ on-fail: halt
324
+ behavior: blocking
325
+ }
326
+ }
327
+ }
328
+ `;
329
+ const ast = parse(GATE_TARGETING_SOURCE);
330
+ // Capture warnings emitted during scaffold so tests can assert on them.
331
+ const originalWarn = console.warn;
332
+ const warnings = [];
333
+ console.warn = (...args) => {
334
+ warnings.push(args.map(String).join(" "));
335
+ };
336
+ let files;
337
+ try {
338
+ files = claudeCodeBinding.scaffold(ast);
339
+ }
340
+ finally {
341
+ console.warn = originalWarn;
342
+ }
343
+ const settingsFile = files.find((f) => f.path === ".claude/settings.json");
344
+ const settings = JSON.parse(settingsFile.content);
345
+ it("emits SubagentStop hook when gate.after is an agent", () => {
346
+ expect(settings.hooks.SubagentStop).toBeDefined();
347
+ const agentHook = settings.hooks.SubagentStop.find((h) => h.matcher === "writer");
348
+ expect(agentHook).toBeDefined();
349
+ expect(JSON.stringify(agentHook)).toContain("gate-gate-on-agent");
350
+ });
351
+ it("does NOT emit SubagentStop hook when gate.after is a human node", () => {
352
+ const humanHook = (settings.hooks?.SubagentStop ?? []).find((h) => h.matcher === "approver");
353
+ expect(humanHook).toBeUndefined();
354
+ });
355
+ it("warns at scaffold time when a blocking gate targets a non-agent node", () => {
356
+ const humanWarning = warnings.find((w) => w.includes("gate-on-human") && w.includes("approver"));
357
+ expect(humanWarning).toBeDefined();
358
+ expect(humanWarning).toContain("non-agent");
359
+ });
360
+ it("still generates the gate wrapper script for non-agent-targeted gate", () => {
361
+ // The wrapper must exist so the orchestrator/playbook can invoke it
362
+ // manually at the right step, even when no hook fires.
363
+ const wrapper = files.find((f) => f.path.endsWith("/scripts/gate-gate-on-human.sh"));
364
+ expect(wrapper).toBeDefined();
365
+ });
366
+ it("wrapper script for non-agent-targeted gate documents the limitation", () => {
367
+ const wrapper = files.find((f) => f.path.endsWith("/scripts/gate-gate-on-human.sh"));
368
+ expect(wrapper.content).toContain("NOT wired as a SubagentStop hook");
369
+ expect(wrapper.content).toContain("orchestrator playbook");
370
+ });
371
+ it("wrapper script for agent-targeted gate documents SubagentStop enforcement", () => {
372
+ const wrapper = files.find((f) => f.path.endsWith("/scripts/gate-gate-on-agent.sh"));
373
+ expect(wrapper.content).toContain("SubagentStop hook on agent \"writer\"");
374
+ expect(wrapper.content).toContain("Exit 2 blocks");
375
+ });
376
+ it("scaffolded hook entry uses agent name (not 'Agent' or arbitrary) as matcher", () => {
377
+ // Sanity check: matchers must be exactly the agent id, since Claude Code
378
+ // matches them against agent_type, not against the tool name.
379
+ const hooks = settings.hooks.SubagentStop ?? [];
380
+ for (const h of hooks) {
381
+ // Each matcher must correspond to an agent or group node in the AST.
382
+ const matcher = h.matcher;
383
+ expect(matcher).toBeTruthy();
384
+ const matchingNode = ast.nodes.find((n) => (n.type === "agent" || n.type === "group") && n.id === matcher);
385
+ expect(matchingNode, `matcher "${matcher}" must resolve to an agent or group node`).toBeDefined();
386
+ }
387
+ });
388
+ });
389
+ // ---------------------------------------------------------------------------
390
+ // claude-code — Integration test: youtube-flywheel.at fixture (#3)
391
+ //
392
+ // The real-world failure from agentopology-content: gates with after: human
393
+ // produced dead SubagentStop entries. This integration test pins the fix
394
+ // against the actual fixture and asserts the right hooks fire and the wrong
395
+ // ones don't.
396
+ // ---------------------------------------------------------------------------
397
+ describe("claude-code binding — youtube-flywheel integration (#3)", () => {
398
+ const YOUTUBE_FLYWHEEL_SOURCE = `
399
+ topology youtube-flywheel : [pipeline, fan-out, human-gate] {
400
+ meta { version: "1.0.0" }
401
+
402
+ orchestrator { model: opus handles: [start] }
403
+ action start { kind: inline }
404
+
405
+ agent briefer {
406
+ model: opus
407
+ phase: 4
408
+ tools: [Read, Write]
409
+ reads: ["workspace/idea.json"]
410
+ writes: ["workspace/brief.json"]
411
+ permissions: supervised
412
+ }
413
+
414
+ human approve-brief {
415
+ description: "Review the brief before render"
416
+ timeout: 8h
417
+ on-timeout: skip
418
+ }
419
+
420
+ agent renderer {
421
+ model: sonnet
422
+ phase: 6
423
+ tools: [Read, Write, Bash]
424
+ reads: ["workspace/brief.json"]
425
+ writes: ["workspace/render/"]
426
+ permissions: autonomous
427
+ }
428
+
429
+ flow {
430
+ start -> briefer
431
+ briefer -> approve-brief
432
+ approve-brief -> renderer
433
+ }
434
+
435
+ gates {
436
+ gate brief-schema-valid {
437
+ after: briefer
438
+ before: approve-brief
439
+ run: "scripts/validate-brief.sh"
440
+ on-fail: bounce-back
441
+ behavior: blocking
442
+ }
443
+ gate render-quality {
444
+ after: renderer
445
+ before: start
446
+ run: "scripts/qa-render.sh"
447
+ on-fail: bounce-back
448
+ behavior: blocking
449
+ }
450
+ gate platform-credentials {
451
+ after: approve-brief
452
+ before: renderer
453
+ run: "scripts/check-platform-auth.sh"
454
+ on-fail: halt
455
+ behavior: blocking
456
+ }
457
+ }
458
+ }
459
+ `;
460
+ const ast = parse(YOUTUBE_FLYWHEEL_SOURCE);
461
+ const originalWarn = console.warn;
462
+ const warnings = [];
463
+ console.warn = (...args) => {
464
+ warnings.push(args.map(String).join(" "));
465
+ };
466
+ let files;
467
+ try {
468
+ files = claudeCodeBinding.scaffold(ast);
469
+ }
470
+ finally {
471
+ console.warn = originalWarn;
472
+ }
473
+ const settingsFile = files.find((f) => f.path === ".claude/settings.json");
474
+ const settings = JSON.parse(settingsFile.content);
475
+ it("emits SubagentStop hooks for the two agent-targeted gates", () => {
476
+ const matchers = (settings.hooks?.SubagentStop ?? []).map((h) => h.matcher);
477
+ expect(matchers).toContain("briefer");
478
+ expect(matchers).toContain("renderer");
479
+ });
480
+ it("does NOT emit a SubagentStop hook for the gate targeting the human 'approve-brief'", () => {
481
+ const matchers = (settings.hooks?.SubagentStop ?? []).map((h) => h.matcher);
482
+ expect(matchers).not.toContain("approve-brief");
483
+ });
484
+ it("warns at scaffold time about the platform-credentials gate", () => {
485
+ const w = warnings.find((m) => m.includes("platform-credentials") && m.includes("approve-brief"));
486
+ expect(w).toBeDefined();
487
+ });
247
488
  });
248
489
  // ---------------------------------------------------------------------------
249
490
  // claude-code — Exotic features: groups, humans, circuit breakers, scale,
@@ -553,8 +794,8 @@ topology debate-test : [fan-out, debate, pipeline] {
553
794
  expect(schema).toBeDefined();
554
795
  expect(schema.content).toContain("winner");
555
796
  });
556
- it("artifacts documented in CONTEXT.md", () => {
557
- const ctx = exoticFiles.find((f) => f.path === ".claude/CONTEXT.md");
797
+ it("artifacts documented in CLAUDE.md", () => {
798
+ const ctx = exoticFiles.find((f) => f.path === ".claude/CLAUDE.md");
558
799
  expect(ctx.content).toContain("transcript");
559
800
  });
560
801
  it("skills generate SKILL.md files", () => {
@@ -571,9 +812,9 @@ topology debate-test : [fan-out, debate, pipeline] {
571
812
  expect(hook).toBeDefined();
572
813
  expect(hook.hooks[0].timeout).toBe(5000);
573
814
  });
574
- it("gate compiles to PreToolUse hook", () => {
575
- expect(settings.hooks.PreToolUse).toBeDefined();
576
- const gateHook = settings.hooks.PreToolUse.find((h) => JSON.stringify(h).includes("fact-check"));
815
+ it("gate compiles to SubagentStop hook with after: agent as matcher", () => {
816
+ expect(settings.hooks.SubagentStop).toBeDefined();
817
+ const gateHook = settings.hooks.SubagentStop.find((h) => JSON.stringify(h).includes("fact-check"));
577
818
  expect(gateHook).toBeDefined();
578
819
  });
579
820
  });
@@ -2086,4 +2327,40 @@ topology debate-test : [fan-out, debate, pipeline] {
2086
2327
  });
2087
2328
  });
2088
2329
  });
2330
+ // ---------------------------------------------------------------------------
2331
+ // Cross-binding: AGENTOPOLOGY_STUB marker uniformity (#4)
2332
+ //
2333
+ // All bindings that scaffold gate scripts must emit them via the shared
2334
+ // shellStub() util — which embeds the AGENTOPOLOGY_STUB marker. This test
2335
+ // loops over every binding and verifies that at least one stub file in its
2336
+ // scaffold output is detectable by isStubContent().
2337
+ // ---------------------------------------------------------------------------
2338
+ describe("Stub marker uniformity across bindings (#4)", () => {
2339
+ // The baseline TOPOLOGY_SOURCE at the top of this file has gate
2340
+ // `quality-check` whose `run: "scripts/lint.sh"` becomes a stub. Bindings
2341
+ // that scaffold gates (5 of 7) must produce a stub for it. The two that
2342
+ // don't (copilot-cli, cursor) have no gate-script generation and are
2343
+ // excluded.
2344
+ const stubProducers = ["claude-code", "codex", "gemini-cli", "kiro", "openclaw"];
2345
+ for (const bindingName of stubProducers) {
2346
+ it(`${bindingName} emits at least one stub with the AGENTOPOLOGY_STUB marker`, () => {
2347
+ const files = scaffoldBinding(bindingName);
2348
+ const stubs = files.filter((f) => isStubContent(f.content));
2349
+ expect(stubs.length, `${bindingName} should emit at least one stub`).toBeGreaterThan(0);
2350
+ // Every stub must contain the literal marker string (pinned by the
2351
+ // STUB_MARKER constant — see lib/stub.ts).
2352
+ for (const s of stubs) {
2353
+ expect(s.content).toContain(STUB_MARKER);
2354
+ }
2355
+ });
2356
+ }
2357
+ it("copilot-cli produces NO stubs (no shell-script scaffolds)", () => {
2358
+ // Sanity check — confirms the two non-stub-producing bindings stay
2359
+ // in their respective lanes. If this fails, copilot-cli probably
2360
+ // grew a gate-script path and needs the same marker treatment.
2361
+ const files = scaffoldBinding("copilot-cli");
2362
+ const stubs = files.filter((f) => isStubContent(f.content));
2363
+ expect(stubs).toEqual([]);
2364
+ });
2365
+ });
2089
2366
  //# sourceMappingURL=bindings.test.js.map