agentopology 0.2.4 → 0.3.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 (64) hide show
  1. package/README.md +92 -10
  2. package/dist/bindings/__tests__/bindings.test.js +2 -2
  3. package/dist/bindings/__tests__/claude-code-hybrid.test.d.ts +2 -0
  4. package/dist/bindings/__tests__/claude-code-hybrid.test.d.ts.map +1 -0
  5. package/dist/bindings/__tests__/claude-code-hybrid.test.js +152 -0
  6. package/dist/bindings/__tests__/claude-code-hybrid.test.js.map +1 -0
  7. package/dist/bindings/__tests__/claude-workflow.test.d.ts +2 -0
  8. package/dist/bindings/__tests__/claude-workflow.test.d.ts.map +1 -0
  9. package/dist/bindings/__tests__/claude-workflow.test.js +204 -0
  10. package/dist/bindings/__tests__/claude-workflow.test.js.map +1 -0
  11. package/dist/bindings/__tests__/hybrid-e2e.test.d.ts +15 -0
  12. package/dist/bindings/__tests__/hybrid-e2e.test.d.ts.map +1 -0
  13. package/dist/bindings/__tests__/hybrid-e2e.test.js +94 -0
  14. package/dist/bindings/__tests__/hybrid-e2e.test.js.map +1 -0
  15. package/dist/bindings/claude-code.d.ts.map +1 -1
  16. package/dist/bindings/claude-code.js +407 -3
  17. package/dist/bindings/claude-code.js.map +1 -1
  18. package/dist/bindings/claude-workflow.d.ts +28 -0
  19. package/dist/bindings/claude-workflow.d.ts.map +1 -0
  20. package/dist/bindings/claude-workflow.js +684 -0
  21. package/dist/bindings/claude-workflow.js.map +1 -0
  22. package/dist/bindings/index.d.ts +1 -0
  23. package/dist/bindings/index.d.ts.map +1 -1
  24. package/dist/bindings/index.js +3 -0
  25. package/dist/bindings/index.js.map +1 -1
  26. package/dist/bindings/lib/seam.d.ts +35 -0
  27. package/dist/bindings/lib/seam.d.ts.map +1 -0
  28. package/dist/bindings/lib/seam.js +42 -0
  29. package/dist/bindings/lib/seam.js.map +1 -0
  30. package/dist/cli/index.js +195 -2
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/parser/__tests__/parser.test.js +170 -0
  33. package/dist/parser/__tests__/parser.test.js.map +1 -1
  34. package/dist/parser/ast.d.ts +39 -0
  35. package/dist/parser/ast.d.ts.map +1 -1
  36. package/dist/parser/index.d.ts.map +1 -1
  37. package/dist/parser/index.js +58 -2
  38. package/dist/parser/index.js.map +1 -1
  39. package/dist/parser/validator.d.ts.map +1 -1
  40. package/dist/parser/validator.js +66 -3
  41. package/dist/parser/validator.js.map +1 -1
  42. package/dist/visualizer/__tests__/brain.test.d.ts +2 -0
  43. package/dist/visualizer/__tests__/brain.test.d.ts.map +1 -0
  44. package/dist/visualizer/__tests__/brain.test.js +138 -0
  45. package/dist/visualizer/__tests__/brain.test.js.map +1 -0
  46. package/dist/visualizer/__tests__/topology-brain-link.test.d.ts +2 -0
  47. package/dist/visualizer/__tests__/topology-brain-link.test.d.ts.map +1 -0
  48. package/dist/visualizer/__tests__/topology-brain-link.test.js +41 -0
  49. package/dist/visualizer/__tests__/topology-brain-link.test.js.map +1 -0
  50. package/dist/visualizer/brain.d.ts +97 -0
  51. package/dist/visualizer/brain.d.ts.map +1 -0
  52. package/dist/visualizer/brain.js +473 -0
  53. package/dist/visualizer/brain.js.map +1 -0
  54. package/dist/visualizer/index.d.ts +19 -1
  55. package/dist/visualizer/index.d.ts.map +1 -1
  56. package/dist/visualizer/index.js +26 -11
  57. package/dist/visualizer/index.js.map +1 -1
  58. package/examples/company-brain-team.at +241 -0
  59. package/examples/company-brain.at +104 -0
  60. package/examples/logos/gmail.svg +1 -0
  61. package/examples/logos/slack.svg +1 -0
  62. package/examples/matchmat-ship.at +249 -0
  63. package/package.json +1 -1
  64. package/spec/grammar.md +42 -3
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  <h1 align="center">AgenTopology</h1>
2
2
 
3
3
  <p align="center">
4
- <strong>The Terraform for AI agents.</strong><br/>
5
- Define your agent team once. Deploy to any platform.
4
+ <strong>Harness as code.</strong> The Terraform for AI agents.<br/>
5
+ Define your agent team — and its memory — once. Deploy to any platform.
6
6
  </p>
7
7
 
8
8
  <p align="center">
@@ -12,7 +12,7 @@
12
12
  </p>
13
13
 
14
14
  <p align="center">
15
- <strong>Claude Code</strong> · <strong>OpenClaw</strong> · <strong>Codex</strong> · <strong>Cursor</strong> · <strong>Gemini CLI</strong> · <strong>Copilot</strong> · <strong>Kiro</strong>
15
+ <strong>Claude Code</strong> · <strong>Claude Workflow</strong> · <strong>OpenClaw</strong> · <strong>Codex</strong> · <strong>Cursor</strong> · <strong>Gemini CLI</strong> · <strong>Copilot</strong> · <strong>Kiro</strong>
16
16
  </p>
17
17
 
18
18
  <p align="center">
@@ -54,18 +54,32 @@ topology code-review : [pipeline] {
54
54
  ```
55
55
 
56
56
  ```bash
57
- agentopology scaffold my-team.at --target claude-code # → .claude/agents/
58
- agentopology scaffold my-team.at --target openclaw # → .openclaw/soul.md
59
- agentopology scaffold my-team.at --target codex # → .codex/
60
- agentopology scaffold my-team.at --target cursor # → .cursor/rules/
57
+ agentopology scaffold my-team.at --target claude-code # → .claude/agents/
58
+ agentopology scaffold my-team.at --target claude-workflow # → my-team.workflow.js (+ SEAM/README/LOSSY-REPORT)
59
+ agentopology scaffold my-team.at --target openclaw # → .openclaw/soul.md
60
+ agentopology scaffold my-team.at --target codex # → .codex/
61
+ agentopology scaffold my-team.at --target cursor # → .cursor/rules/
61
62
  ```
62
63
 
63
- One file. Seven platforms. The topology IS the documentation.
64
+ One file. Every platform. The topology IS the documentation.
64
65
 
65
66
  <p align="center">
66
67
  <img src="docs/visualizer-preview.png" alt="AgenTopology Visualizer" width="900" />
67
68
  </p>
68
69
 
70
+ ### Hybrid: host + embedded workflow
71
+
72
+ One `.at` topology can compile to **two coupled targets at once**. `claude-code` is the **host** — the event-driven layer that owns agents, hooks, the Blackboard, concurrent observability, and the human/gate/branching nodes. `claude-workflow` is the embedded **deterministic rung** — the parallel fan-out phases, compiled into a Claude Workflow tool script. The host launches the rung and observes its Blackboard writes live (via a `PostToolUse` hook), so you get concurrent observability the Workflow runtime can't do on its own.
73
+
74
+ Mark a phase for the rung with `extensions { claude-workflow { execution: workflow } }`, then scaffold both:
75
+
76
+ ```bash
77
+ agentopology scaffold my-team.at --target claude-code # the host
78
+ agentopology scaffold my-team.at --target claude-workflow # the embedded rung
79
+ ```
80
+
81
+ The hybrid is opt-in — a topology with no `execution: workflow` marker compiles to pure `claude-code`, unchanged. See [docs/AT_VS_WORKFLOW_STRATEGY.md](docs/AT_VS_WORKFLOW_STRATEGY.md) for why.
82
+
69
83
  ---
70
84
 
71
85
  ## What It Does
@@ -78,6 +92,7 @@ AgenTopology is a **declarative language** (`.at` files) and a **CLI compiler**
78
92
  │ (you write) │ │ Validator │ │ (auto-generated) │
79
93
  └──────────────┘ └────────────┘ └─────────────────────┘
80
94
  ├── .claude/agents/
95
+ ├── <topology>.workflow.js
81
96
  ├── .openclaw/
82
97
  ├── .codex/
83
98
  ├── .cursor/rules/
@@ -244,7 +259,8 @@ This defines three agents, their tools and memory, a quality gate, and a flow wi
244
259
 
245
260
  | Target | Command | What It Generates |
246
261
  |--------|---------|-------------------|
247
- | **Claude Code** | `--target claude-code` | `.claude/agents/`, `.claude/skills/`, `.mcp.json`, `.claude/settings.json` |
262
+ | **Claude Code** | `--target claude-code` | `.claude/agents/`, `.claude/skills/`, `.mcp.json`, `.claude/settings.json` (the event-driven host) |
263
+ | **Claude Workflow** | `--target claude-workflow` | `<topology>.workflow.js` (deterministic fan-out rung) + `-SEAM.md`, `-README.md`, `-LOSSY-REPORT.md` |
248
264
  | **OpenClaw** | `--target openclaw` | `.openclaw/soul.md`, `.openclaw/skills/`, `.openclaw/config.json` |
249
265
  | **Codex** | `--target codex` | `.codex/config.toml`, `AGENTS.md` |
250
266
  | **Cursor** | `--target cursor` | `.cursor/rules/*.mdc`, `.cursor/mcp.json`, `.cursor/hooks.json` |
@@ -348,6 +364,36 @@ mcp-servers {
348
364
  }
349
365
  ```
350
366
 
367
+ </td>
368
+ </tr>
369
+ <tr>
370
+ <td>
371
+
372
+ **Company Brain** — agent-maintained, Obsidian-portable
373
+ ```
374
+ store brain {
375
+ type: brain # markdown, no DB
376
+ path: "brain/"
377
+ format: obsidian # ports both ways
378
+ }
379
+ agent librarian {
380
+ custodian-of: [brain] # owns its upkeep
381
+ }
382
+ ```
383
+
384
+ </td>
385
+ <td>
386
+
387
+ **Provenance styling** — color the graph by source
388
+ ```
389
+ store brain {
390
+ sources {
391
+ gmail { color: "#EA4335" icon: "./gmail.svg" }
392
+ slack { color: "#4A154B" }
393
+ }
394
+ }
395
+ ```
396
+
351
397
  </td>
352
398
  </tr>
353
399
  </table>
@@ -373,6 +419,39 @@ In Claude Code, this compiles to a **file-based protocol** — a shared transcri
373
419
 
374
420
  ---
375
421
 
422
+ ## Company Brain — Knowledge That Builds Itself
423
+
424
+ A **brain** is a folder of linked markdown that agents maintain, not you. It's the [Obsidian](https://obsidian.md) graph model — notes connected by `[[wikilinks]]` and `#tags` — but **agent-maintained instead of hand-curated**.
425
+
426
+ ```
427
+ store brain {
428
+ type: brain # file-native: markdown, no database, no embeddings
429
+ path: "brain/"
430
+ format: obsidian # ports both ways — open it in Obsidian, the graph just works
431
+ }
432
+
433
+ agent librarian {
434
+ custodian-of: [brain] { # OWNS the brain's upkeep, not just read access
435
+ does: [link, tag, index, dedupe]
436
+ }
437
+ }
438
+ ```
439
+
440
+ - **Custodian agents** own a memory layer. Drop a note in, the librarian wires it into the graph — resolving `[[links]]`, assigning `#tags`, updating hub notes. Humans drop; agents wire.
441
+ - **Ingester agents** feed it from anywhere. One agent per source (Gmail, Slack, calendar) writes raw notes; the librarian links them. See [`examples/company-brain-team.at`](examples/company-brain-team.at).
442
+ - **Pure markdown, zero infrastructure.** No vector DB, no MCP server. Coding agents retrieve with `grep`. The whole brain is a folder you can `git clone`.
443
+ - **100% Obsidian-compatible.** The vault *is* an Obsidian vault — agents build it, you open it in Obsidian for the graph view. Or use our built-in graph viewer (below) and skip Obsidian entirely.
444
+
445
+ **See it without Obsidian** — render any brain vault as an interactive graph in a single self-contained HTML file:
446
+
447
+ ```bash
448
+ agentopology visualize-brain brain/
449
+ ```
450
+
451
+ Nodes are colored by what they *are* (person / org / topic) and by where they *came from* (declare `sources { gmail { color, icon } }` and notes from Gmail render in Gmail red with the logo). When you `visualize` a topology that owns brains, the two graphs **cross-link** — jump from the team diagram to its brain and back.
452
+
453
+ This is **brain as code**: you declare the brain's architecture — its layers, its custodians, its sources — the same way you declare the agent team. See [`docs/company-brain.md`](docs/company-brain.md) for the full walkthrough.
454
+
376
455
  ---
377
456
 
378
457
  ## Programmatic API
@@ -446,6 +525,8 @@ You can `agentopology visualize` it into an interactive graph. You can hand it t
446
525
  - [`data-processing.at`](examples/data-processing.at) — ETL pipeline with batch processing and metering
447
526
  - [`scheduled-monitor.at`](examples/scheduled-monitor.at) — Monitoring system with scheduled health checks
448
527
  - [`openclaw-assistant.at`](examples/openclaw-assistant.at) — Customer support with routing and scheduling
528
+ - [`company-brain.at`](examples/company-brain.at) — A plug-and-play company brain (librarian + researcher)
529
+ - [`company-brain-team.at`](examples/company-brain-team.at) — A team that ingests (Gmail/Slack/calendar), wires, and audits a brain
449
530
 
450
531
  ---
451
532
 
@@ -456,7 +537,8 @@ agentopology validate <file> Validate an .at file (82 rules)
456
537
  agentopology scaffold <file> --target <t> Generate platform configs
457
538
  agentopology sync <file> --target <t> --dir <d> Sync platform files back to .at
458
539
  agentopology import --target <t> --dir <d> Reverse-engineer platform files to .at
459
- agentopology visualize <file> Interactive topology graph
540
+ agentopology visualize <file> Interactive topology graph (+ cross-links any brains)
541
+ agentopology visualize-brain <folder> Render a brain vault as an Obsidian-style graph (no Obsidian)
460
542
  agentopology export <file> --format <fmt> Export as markdown, mermaid, or json
461
543
  agentopology info <file> Topology analysis and suggestions
462
544
  agentopology targets List supported platforms
@@ -156,8 +156,8 @@ function assertStructuralInvariants(files) {
156
156
  // Registry tests
157
157
  // ---------------------------------------------------------------------------
158
158
  describe("Binding registry", () => {
159
- it("contains all 7 bindings", () => {
160
- expect(Object.keys(bindings)).toHaveLength(7);
159
+ it("contains all 8 bindings", () => {
160
+ expect(Object.keys(bindings)).toHaveLength(8);
161
161
  });
162
162
  it("all bindings have a name and description", () => {
163
163
  for (const [key, binding] of Object.entries(bindings)) {
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=claude-code-hybrid.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-hybrid.test.d.ts","sourceRoot":"","sources":["../../../src/bindings/__tests__/claude-code-hybrid.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,152 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import path from "node:path";
5
+ import { parse } from "../../parser/index.js";
6
+ import { claudeCodeBinding, claudeWorkflowBinding } from "../index.js";
7
+ // ---------------------------------------------------------------------------
8
+ // Hybrid-awareness of the claude-code binding (host half of the host+workflow
9
+ // model). Fixture: examples/matchmat-ship.at — builder (phase 2) is
10
+ // execution:workflow; phases 1 & 3 + the human node are host-side.
11
+ // ---------------------------------------------------------------------------
12
+ const here = path.dirname(fileURLToPath(import.meta.url));
13
+ const fixturePath = path.resolve(here, "../../../examples/matchmat-ship.at");
14
+ const source = readFileSync(fixturePath, "utf-8");
15
+ const ast = parse(source);
16
+ const files = claudeCodeBinding.scaffold(ast);
17
+ function find(suffix) {
18
+ return files.find((f) => f.path.endsWith(suffix));
19
+ }
20
+ describe("claude-code binding — HYBRID awareness (matchmat-ship)", () => {
21
+ // (a) workflow-marked agent (builder) is NOT emitted as a host subagent.
22
+ it("does NOT emit .claude/agents/builder/AGENT.md (builder is execution:workflow)", () => {
23
+ const builderAgent = files.find((f) => f.path === ".claude/agents/builder/AGENT.md");
24
+ expect(builderAgent).toBeUndefined();
25
+ });
26
+ // (b) host phase-1 + phase-3 agents ARE still emitted as subagents.
27
+ it("still emits AGENT.md for host phase-1 and phase-3 agents", () => {
28
+ const expected = [
29
+ ".claude/agents/contract-scout/AGENT.md",
30
+ ".claude/agents/blast-radius-mapper/AGENT.md",
31
+ ".claude/agents/boundary-drafter/AGENT.md",
32
+ ".claude/agents/security-verifier/AGENT.md",
33
+ ".claude/agents/contract-verifier/AGENT.md",
34
+ ".claude/agents/closed-loop-verifier/AGENT.md",
35
+ ];
36
+ for (const p of expected) {
37
+ expect(files.find((f) => f.path === p), `expected ${p} to be emitted`).toBeDefined();
38
+ }
39
+ });
40
+ // (c) a launch-workflow stub/skill artifact for the build phase IS emitted.
41
+ it("emits a launch-<phase>-workflow.sh stub for the workflow phase", () => {
42
+ const launch = find("launch-builder-workflow.sh");
43
+ expect(launch).toBeDefined();
44
+ expect(launch.path).toBe(".claude/skills/matchmat-ship/scripts/launch-builder-workflow.sh");
45
+ expect(launch.executable).toBe(true);
46
+ // It's a detectable scaffold stub.
47
+ expect(launch.content).toContain("# AGENTOPOLOGY_STUB");
48
+ // It documents launching the SAME workflow.js filename the sibling binding emits.
49
+ expect(launch.content).toContain("matchmat-ship.workflow.js");
50
+ expect(launch.content).toContain("/workflow matchmat-ship.workflow.js");
51
+ // It points at the shared Blackboard root + the seam doc.
52
+ expect(launch.content).toContain("workspace/");
53
+ expect(launch.content).toContain("matchmat-ship-SEAM.md");
54
+ });
55
+ // (d) CLAUDE.md carries the hybrid run-order block referencing the workflow.js.
56
+ it("emits a Hybrid run order block in CLAUDE.md referencing the workflow.js", () => {
57
+ const ctx = files.find((f) => f.path === ".claude/CLAUDE.md");
58
+ expect(ctx).toBeDefined();
59
+ expect(ctx.content).toContain("## Hybrid run order");
60
+ expect(ctx.content).toContain("matchmat-ship.workflow.js");
61
+ expect(ctx.content).toContain("Host launches");
62
+ // host phases described as in-session; workflow phase described as launched.
63
+ expect(ctx.content).toContain("phase 1 (contract-scout, blast-radius-mapper, boundary-drafter)");
64
+ expect(ctx.content).toContain("phase 2 (builder)");
65
+ expect(ctx.content).toContain("phase 3 (security-verifier, contract-verifier, closed-loop-verifier)");
66
+ // points at the seam doc both bindings honor.
67
+ expect(ctx.content).toContain("matchmat-ship-SEAM.md");
68
+ });
69
+ it("also mirrors the Hybrid run order block into the topology SKILL.md", () => {
70
+ const skill = files.find((f) => f.path === ".claude/skills/matchmat-ship/SKILL.md");
71
+ expect(skill).toBeDefined();
72
+ expect(skill.content).toContain("## Hybrid run order");
73
+ expect(skill.content).toContain("matchmat-ship.workflow.js");
74
+ });
75
+ // (e) the observe-hook is in settings.json (host-layer concurrent observer).
76
+ it("emits a PostToolUse(Write) observe-blackboard hook in settings.json", () => {
77
+ const settings = files.find((f) => f.path === ".claude/settings.json");
78
+ expect(settings).toBeDefined();
79
+ const parsed = JSON.parse(settings.content);
80
+ const postToolUse = parsed.hooks?.PostToolUse;
81
+ expect(postToolUse, "PostToolUse hooks present").toBeDefined();
82
+ const observe = postToolUse.find((h) => h.matcher === "Write" && h.hooks.some((x) => x.command.includes("observe-blackboard.sh")));
83
+ expect(observe, "observe-blackboard PostToolUse(Write) hook present").toBeDefined();
84
+ });
85
+ it("emits the observe-blackboard.sh script the hook points at", () => {
86
+ const observe = find("observe-blackboard.sh");
87
+ expect(observe).toBeDefined();
88
+ expect(observe.path).toBe(".claude/skills/matchmat-ship/scripts/observe-blackboard.sh");
89
+ expect(observe.executable).toBe(true);
90
+ expect(observe.content).toContain("# AGENTOPOLOGY_STUB");
91
+ // documents the Blackboard root it watches.
92
+ expect(observe.content).toContain("workspace/");
93
+ });
94
+ });
95
+ describe("claude-code binding — non-hybrid topologies are unaffected", () => {
96
+ // A topology with no execution:workflow agent must not get any hybrid artifacts.
97
+ const plain = parse(`topology plain-pipe : [pipeline] {
98
+ roles { worker: "do the work" }
99
+ agent worker { role: worker phase: 1 prompt { Do the thing. } }
100
+ flow { worker -> worker }
101
+ }`);
102
+ const plainFiles = claudeCodeBinding.scaffold(plain);
103
+ it("still emits the agent AGENT.md (no workflow seam)", () => {
104
+ expect(plainFiles.find((f) => f.path === ".claude/agents/worker/AGENT.md")).toBeDefined();
105
+ });
106
+ it("emits no launch-*-workflow.sh stub", () => {
107
+ expect(plainFiles.find((f) => f.path.includes("launch-") && f.path.endsWith("-workflow.sh"))).toBeUndefined();
108
+ });
109
+ it("emits no Hybrid run order block", () => {
110
+ const ctx = plainFiles.find((f) => f.path === ".claude/CLAUDE.md");
111
+ if (ctx)
112
+ expect(ctx.content).not.toContain("## Hybrid run order");
113
+ });
114
+ it("emits no synthesized observe-blackboard hook (no Blackboard)", () => {
115
+ expect(plainFiles.find((f) => f.path.endsWith("observe-blackboard.sh"))).toBeUndefined();
116
+ });
117
+ });
118
+ describe("claude-code + claude-workflow — the two bindings AGREE on the seam", () => {
119
+ const hostFiles = claudeCodeBinding.scaffold(ast);
120
+ const wfFiles = claudeWorkflowBinding.scaffold(ast);
121
+ it("host omits builder/AGENT.md while the workflow.js OWNS builder", () => {
122
+ expect(hostFiles.find((f) => f.path === ".claude/agents/builder/AGENT.md")).toBeUndefined();
123
+ const wf = wfFiles.find((f) => f.path.endsWith(".workflow.js"));
124
+ expect(wf).toBeDefined();
125
+ expect(wf.content).toContain("{ phase: 2, agents: ['builder'] }");
126
+ });
127
+ it("both reference the same workflow.js filename", () => {
128
+ const wf = wfFiles.find((f) => f.path.endsWith(".workflow.js"));
129
+ expect(wf.path).toBe("matchmat-ship.workflow.js");
130
+ const ctx = hostFiles.find((f) => f.path === ".claude/CLAUDE.md");
131
+ expect(ctx.content).toContain("matchmat-ship.workflow.js");
132
+ });
133
+ it("both reference the same Blackboard workspace root and SEAM doc", () => {
134
+ const seam = wfFiles.find((f) => f.path.endsWith("-SEAM.md"));
135
+ const ctx = hostFiles.find((f) => f.path === ".claude/CLAUDE.md");
136
+ // workspace root
137
+ expect(seam.content).toContain("`workspace/`");
138
+ expect(ctx.content).toContain("`workspace/`");
139
+ // seam doc filename
140
+ expect(seam.path).toBe("matchmat-ship-SEAM.md");
141
+ expect(ctx.content).toContain("matchmat-ship-SEAM.md");
142
+ });
143
+ it("both use the same 'Host launches ... LIVE' run-order phrasing", () => {
144
+ const seam = wfFiles.find((f) => f.path.endsWith("-SEAM.md"));
145
+ const ctx = hostFiles.find((f) => f.path === ".claude/CLAUDE.md");
146
+ expect(seam.content).toContain("Host launches");
147
+ expect(ctx.content).toContain("Host launches");
148
+ expect(seam.content).toContain("observe those writes LIVE");
149
+ expect(ctx.content).toContain("observe those writes LIVE");
150
+ });
151
+ });
152
+ //# sourceMappingURL=claude-code-hybrid.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-code-hybrid.test.js","sourceRoot":"","sources":["../../../src/bindings/__tests__/claude-code-hybrid.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=claude-workflow.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-workflow.test.d.ts","sourceRoot":"","sources":["../../../src/bindings/__tests__/claude-workflow.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,204 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { readFileSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import path from "node:path";
5
+ import { parse } from "../../parser/index.js";
6
+ import { bindings, claudeWorkflowBinding } from "../index.js";
7
+ // ---------------------------------------------------------------------------
8
+ // Fixture: the dogfood topology (examples/matchmat-ship.at)
9
+ // ---------------------------------------------------------------------------
10
+ const here = path.dirname(fileURLToPath(import.meta.url));
11
+ const fixturePath = path.resolve(here, "../../../examples/matchmat-ship.at");
12
+ const source = readFileSync(fixturePath, "utf-8");
13
+ const ast = parse(source);
14
+ const files = claudeWorkflowBinding.scaffold(ast);
15
+ function find(suffix) {
16
+ return files.find((f) => f.path.endsWith(suffix));
17
+ }
18
+ describe("claude-workflow binding — registry", () => {
19
+ it("is registered under the 'claude-workflow' key with a matching name", () => {
20
+ expect(bindings["claude-workflow"]).toBeDefined();
21
+ expect(bindings["claude-workflow"].name).toBe("claude-workflow");
22
+ });
23
+ it("scaffold returns a non-empty array of GeneratedFile", () => {
24
+ expect(files.length).toBeGreaterThan(0);
25
+ for (const f of files) {
26
+ expect(f.path).toBeTruthy();
27
+ expect(typeof f.content).toBe("string");
28
+ }
29
+ });
30
+ });
31
+ describe("claude-workflow binding — workflow.js emission (matchmat-ship)", () => {
32
+ // (a) a *.workflow.js file is emitted
33
+ it("emits a <topology>.workflow.js file", () => {
34
+ const wf = find(".workflow.js");
35
+ expect(wf).toBeDefined();
36
+ expect(wf.path).toBe("matchmat-ship.workflow.js");
37
+ });
38
+ const wf = find(".workflow.js");
39
+ // (b) STRICT SEAM: meta.phases contains ONLY the workflow-marked phase (2 / builder).
40
+ it("contains `export const meta` as a pure literal with ONLY the workflow-marked phase", () => {
41
+ expect(wf.content).toContain("export const meta");
42
+ expect(wf.content).toContain("phases:");
43
+ // The meta literal must not contain computed/nondeterministic values
44
+ expect(wf.content).not.toContain("Date.now");
45
+ expect(wf.content).not.toContain("Math.random");
46
+ // Only phase 2 (builder) — not phase 1 or 3.
47
+ expect(wf.content).toContain("{ phase: 2, agents: ['builder'] }");
48
+ expect(wf.content).not.toContain("phase: 1");
49
+ expect(wf.content).not.toContain("phase: 3");
50
+ });
51
+ it("uses parallel(...) for the builder fan-out", () => {
52
+ expect(wf.content).toContain("parallel(");
53
+ });
54
+ it("uses phase() to title the workflow phase", () => {
55
+ expect(wf.content).toContain("phase('Phase 2')");
56
+ });
57
+ it("compiles ONLY the builder (scaled) phase with isolation:'worktree'", () => {
58
+ expect(wf.content).toContain("isolation: 'worktree'");
59
+ // builder has scale {max: 6} → deterministic Array.from fan-out, no random
60
+ expect(wf.content).toContain("Array.from({ length: 6 }");
61
+ expect(wf.content).toMatch(/label: `builder-\$\{i\}`/);
62
+ });
63
+ // STRICT SEAM: the host-side verifier phase (3) must NOT be in the workflow.js.
64
+ it("does NOT contain the host phase-1 agents (contract-scout, blast-radius-mapper, boundary-drafter)", () => {
65
+ expect(wf.content).not.toContain("contract-scout");
66
+ expect(wf.content).not.toContain("blast-radius-mapper");
67
+ expect(wf.content).not.toContain("'boundary-drafter'");
68
+ });
69
+ it("does NOT contain the host phase-3 verifier agents (security-verifier, etc.)", () => {
70
+ expect(wf.content).not.toContain("security-verifier");
71
+ expect(wf.content).not.toContain("contract-verifier");
72
+ expect(wf.content).not.toContain("closed-loop-verifier");
73
+ });
74
+ it("does NOT contain a verifier verdict schema (phase 3 is HOST-side)", () => {
75
+ // The verdict enum belongs to the phase-3 verifiers, which are host-side now.
76
+ expect(wf.content).not.toContain("verdict:");
77
+ });
78
+ it("embeds the builder's Blackboard read/write paths in its prompt (no filesystem)", () => {
79
+ // builder reads contract-delta/blast-radius/contracts-touched, writes build-report.
80
+ expect(wf.content).toContain("workspace/contract-delta.md");
81
+ expect(wf.content).toContain("workspace/build-report.md");
82
+ });
83
+ // STRICT SEAM: verify-gate is between phase 3 and ship-report (host) → NOT in the workflow.
84
+ it("does NOT contain the host-side verify-gate (it sits outside the workflow span)", () => {
85
+ expect(wf.content).not.toContain("bounce-back");
86
+ expect(wf.content).not.toContain("verify-gate");
87
+ expect(wf.content).not.toContain("for (let attempt");
88
+ });
89
+ // (d) the workflow.js does NOT contain the human node — neither as an agent nor a boundary block.
90
+ it("does NOT contain the human 'promote' node as an agent() call", () => {
91
+ expect(wf.content).not.toMatch(/agent\([^)]*label: 'promote'/);
92
+ // Strict seam: the human is host-side downstream — no in-script HUMAN BOUNDARY block.
93
+ expect(wf.content).not.toContain("HUMAN BOUNDARY");
94
+ // It is still surfaced loud as an UNREPRESENTABLE comment, though.
95
+ expect(wf.content).toContain("UNREPRESENTABLE: human 'promote'");
96
+ });
97
+ });
98
+ describe("claude-workflow binding — human split (matchmat-ship)", () => {
99
+ // (c) a human-split README is emitted (topology has a `human promote` node)
100
+ it("emits a <topology>-README.md documenting the human handoff", () => {
101
+ const readme = find("-README.md");
102
+ expect(readme).toBeDefined();
103
+ expect(readme.path).toBe("matchmat-ship-README.md");
104
+ expect(readme.content).toContain("promote");
105
+ expect(readme.content.toLowerCase()).toContain("human");
106
+ expect(readme.content.toLowerCase()).toContain("downstream");
107
+ });
108
+ it("notes regression is a separate downstream workflow", () => {
109
+ const readme = find("-README.md");
110
+ expect(readme.content.toLowerCase()).toContain("separate");
111
+ });
112
+ });
113
+ describe("claude-workflow binding — LOSSY report (matchmat-ship)", () => {
114
+ it("emits a <topology>-LOSSY-REPORT.md", () => {
115
+ const report = find("-LOSSY-REPORT.md");
116
+ expect(report).toBeDefined();
117
+ expect(report.path).toBe("matchmat-ship-LOSSY-REPORT.md");
118
+ });
119
+ it("classifies the human node as UNREPRESENTABLE", () => {
120
+ const report = find("-LOSSY-REPORT.md");
121
+ expect(report.content).toContain("UNREPRESENTABLE");
122
+ expect(report.content).toContain("human");
123
+ });
124
+ it("classifies the host-side verify-gate as LOSSY (not in the workflow.js)", () => {
125
+ const report = find("-LOSSY-REPORT.md");
126
+ expect(report.content).toContain("verify-gate");
127
+ expect(report.content).toContain("HOST-side");
128
+ });
129
+ it("classifies agent.scale as LOSSY", () => {
130
+ const report = find("-LOSSY-REPORT.md");
131
+ expect(report.content).toContain("LOSSY");
132
+ expect(report.content).toContain("agent.scale");
133
+ });
134
+ // STRICT SEAM: phases 1 & 3 are correct HOST phases, NOT 'folded-in lossy' entries.
135
+ it("does NOT contain 'execution:host' folded-in LOSSY entries (strict seam)", () => {
136
+ const report = find("-LOSSY-REPORT.md");
137
+ expect(report.content).not.toContain("execution:host");
138
+ expect(report.content).not.toContain("folded");
139
+ });
140
+ });
141
+ describe("claude-workflow binding — Blackboard seam contract (matchmat-ship)", () => {
142
+ it("emits a <topology>-SEAM.md describing the file-based hand-off", () => {
143
+ const seam = find("-SEAM.md");
144
+ expect(seam).toBeDefined();
145
+ expect(seam.path).toBe("matchmat-ship-SEAM.md");
146
+ });
147
+ it("documents the workspace root and per-agent reads/writes", () => {
148
+ const seam = find("-SEAM.md");
149
+ expect(seam.content).toContain("workspace/");
150
+ expect(seam.content).toContain("builder");
151
+ expect(seam.content).toContain("contract-delta.md");
152
+ });
153
+ it("states the host .claude/ files are emitted by the claude-code binding, not this one", () => {
154
+ const seam = find("-SEAM.md");
155
+ expect(seam.content).toContain("claude-code");
156
+ });
157
+ it("documents the strict run order: host phase 1 → launch workflow build → host phase 3/gate → human promote", () => {
158
+ const seam = find("-SEAM.md");
159
+ expect(seam.content).toContain("STRICT SEAM");
160
+ // The workflow rung is the build; host runs the surrounding phases.
161
+ expect(seam.content).toContain("Host launches `matchmat-ship.workflow.js`");
162
+ expect(seam.content).toContain("build rung");
163
+ expect(seam.content).toContain("phase 1 (contract-scout");
164
+ expect(seam.content).toContain("phase 3 (security-verifier");
165
+ expect(seam.content).toContain("human `promote`");
166
+ });
167
+ });
168
+ describe("claude-workflow binding — UNREPRESENTABLE never dropped silently", () => {
169
+ const wf = find(".workflow.js");
170
+ it("surfaces UNREPRESENTABLE primitives as in-script comments", () => {
171
+ expect(wf.content).toContain("// UNREPRESENTABLE:");
172
+ });
173
+ });
174
+ // ---------------------------------------------------------------------------
175
+ // Edge case: a topology with NO seam marker → no workflow.js, loud note
176
+ // ---------------------------------------------------------------------------
177
+ describe("claude-workflow binding — no execution:workflow marker", () => {
178
+ const NO_SEAM = `
179
+ topology no-seam : [pipeline] {
180
+ meta { version: "1.0.0" description: "no workflow phase" }
181
+ orchestrator { model: opus handles: [intake] }
182
+ action intake { kind: external source: "user" }
183
+ agent solo {
184
+ model: sonnet
185
+ phase: 1
186
+ tools: [Read, Write]
187
+ reads: ["workspace/in.md"]
188
+ writes: ["workspace/out.md"]
189
+ permissions: autonomous
190
+ }
191
+ flow { intake -> solo }
192
+ }
193
+ `;
194
+ const noSeamAst = parse(NO_SEAM);
195
+ const noSeamFiles = claudeWorkflowBinding.scaffold(noSeamAst);
196
+ it("emits no workflow.js but still emits a LOSSY report explaining why", () => {
197
+ const wf = noSeamFiles.find((f) => f.path.endsWith(".workflow.js"));
198
+ expect(wf).toBeUndefined();
199
+ const report = noSeamFiles.find((f) => f.path.endsWith("-LOSSY-REPORT.md"));
200
+ expect(report).toBeDefined();
201
+ expect(report.content).toContain("execution");
202
+ });
203
+ });
204
+ //# sourceMappingURL=claude-workflow.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-workflow.test.js","sourceRoot":"","sources":["../../../src/bindings/__tests__/claude-workflow.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hybrid end-to-end test.
3
+ *
4
+ * Unit tests check each binding in isolation. THIS test compiles BOTH bindings
5
+ * from the SAME .at file and proves they COMPOSE into one coherent hybrid:
6
+ * - the host (claude-code) and the rung (claude-workflow) partition the agents
7
+ * with no overlap and no gap,
8
+ * - they agree on the seam (workflow filename, Blackboard root, SEAM doc),
9
+ * - the generated workflow.js is syntactically valid JavaScript,
10
+ * - nothing is silently dropped (the LOSSY report exists).
11
+ *
12
+ * This is the real "does the hybrid work end to end" gate.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=hybrid-e2e.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid-e2e.test.d.ts","sourceRoot":"","sources":["../../../src/bindings/__tests__/hybrid-e2e.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}