agentopology 0.6.0 → 0.8.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.
- package/README.md +5 -5
- package/dist/__tests__/e2e/compile.test.d.ts +12 -0
- package/dist/__tests__/e2e/compile.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/compile.test.js +287 -0
- package/dist/__tests__/e2e/compile.test.js.map +1 -0
- package/dist/__tests__/e2e/roundtrip.test.js +2 -4
- package/dist/__tests__/e2e/roundtrip.test.js.map +1 -1
- package/dist/__tests__/e2e/scaffold-owns.test.js +12 -3
- package/dist/__tests__/e2e/scaffold-owns.test.js.map +1 -1
- package/dist/__tests__/e2e/sync-cycle.test.d.ts +10 -0
- package/dist/__tests__/e2e/sync-cycle.test.d.ts.map +1 -0
- package/dist/__tests__/e2e/sync-cycle.test.js +49 -0
- package/dist/__tests__/e2e/sync-cycle.test.js.map +1 -0
- package/dist/__tests__/live/claude-code.live.test.js +73 -4
- package/dist/__tests__/live/claude-code.live.test.js.map +1 -1
- package/dist/__tests__/open-findings.test.js +4 -25
- package/dist/__tests__/open-findings.test.js.map +1 -1
- package/dist/bindings/__tests__/bindings.test.js +19 -19
- package/dist/bindings/__tests__/bindings.test.js.map +1 -1
- package/dist/bindings/__tests__/claude-code-hybrid.test.js +5 -5
- package/dist/bindings/__tests__/claude-code-hybrid.test.js.map +1 -1
- package/dist/bindings/__tests__/hybrid-e2e.test.js +1 -1
- package/dist/bindings/__tests__/hybrid-e2e.test.js.map +1 -1
- package/dist/bindings/claude-code.d.ts +6 -8
- package/dist/bindings/claude-code.d.ts.map +1 -1
- package/dist/bindings/claude-code.js +492 -196
- package/dist/bindings/claude-code.js.map +1 -1
- package/dist/bindings/lib/prompt-fence.d.ts +22 -0
- package/dist/bindings/lib/prompt-fence.d.ts.map +1 -0
- package/dist/bindings/lib/prompt-fence.js +29 -0
- package/dist/bindings/lib/prompt-fence.js.map +1 -0
- package/dist/cli/index.js +9 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/docs/teach.d.ts.map +1 -1
- package/dist/docs/teach.js +10 -0
- package/dist/docs/teach.js.map +1 -1
- package/dist/import/claude-code.d.ts.map +1 -1
- package/dist/import/claude-code.js +21 -5
- package/dist/import/claude-code.js.map +1 -1
- package/dist/import/serializer.d.ts.map +1 -1
- package/dist/import/serializer.js +44 -3
- package/dist/import/serializer.js.map +1 -1
- package/dist/parser/__tests__/mod-hooks.test.js +1 -1
- package/dist/parser/__tests__/mod-hooks.test.js.map +1 -1
- package/dist/parser/ast.d.ts +46 -3
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/ast.js.map +1 -1
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +60 -3
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/run.d.ts +23 -2
- package/dist/parser/run.d.ts.map +1 -1
- package/dist/parser/run.js +39 -3
- package/dist/parser/run.js.map +1 -1
- package/dist/parser/validator.d.ts +1 -1
- package/dist/parser/validator.d.ts.map +1 -1
- package/dist/parser/validator.js +131 -3
- package/dist/parser/validator.js.map +1 -1
- package/dist/scaffold/diff.d.ts +17 -0
- package/dist/scaffold/diff.d.ts.map +1 -0
- package/dist/scaffold/diff.js +66 -0
- package/dist/scaffold/diff.js.map +1 -0
- package/dist/scaffold/merge.d.ts.map +1 -1
- package/dist/scaffold/merge.js +14 -0
- package/dist/scaffold/merge.js.map +1 -1
- package/dist/sync/index.d.ts +1 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +40 -2
- package/dist/sync/index.js.map +1 -1
- package/package.json +1 -1
- package/spec/grammar.md +28 -2
- package/spec/testing.md +35 -25
- package/spec/validation.md +5 -1
|
@@ -43,15 +43,15 @@ function claudeBin() {
|
|
|
43
43
|
}
|
|
44
44
|
return "claude";
|
|
45
45
|
}
|
|
46
|
-
function runClaude(cwd) {
|
|
46
|
+
function runClaude(cwd, prompt = "Reply with the single word OK.", maxTurns = 1) {
|
|
47
47
|
const proc = spawnSync(claudeBin(), [
|
|
48
48
|
"-p",
|
|
49
|
-
|
|
49
|
+
prompt,
|
|
50
50
|
"--setting-sources", "project,local",
|
|
51
51
|
"--strict-mcp-config",
|
|
52
52
|
"--no-session-persistence",
|
|
53
53
|
"--model", "haiku",
|
|
54
|
-
"--max-turns",
|
|
54
|
+
"--max-turns", String(maxTurns),
|
|
55
55
|
"--output-format", "stream-json",
|
|
56
56
|
"--verbose",
|
|
57
57
|
], { cwd, encoding: "utf8", timeout: 180_000 });
|
|
@@ -62,7 +62,7 @@ function runClaude(cwd) {
|
|
|
62
62
|
if (!init || !result) {
|
|
63
63
|
throw new Error(`claude produced no init/result (exit ${proc.status}): ${proc.stderr}`);
|
|
64
64
|
}
|
|
65
|
-
return { init, result, stderr: proc.stderr ?? "" };
|
|
65
|
+
return { init, result, stderr: proc.stderr ?? "", events };
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
68
|
* `name:` from a generated agent file's frontmatter, or null when it has none.
|
|
@@ -133,4 +133,73 @@ describe.skipIf(!LIVE)("[L2] Claude Code loads a hand-built project after import
|
|
|
133
133
|
}
|
|
134
134
|
}, 200_000);
|
|
135
135
|
});
|
|
136
|
+
describe.skipIf(!LIVE)("[L3] Claude Code reads the phase-3 constructs as meant", () => {
|
|
137
|
+
it("compile.at: a manual agent registers, and a prompt hook fires", () => {
|
|
138
|
+
const project = fs.mkdtempSync(join(os.tmpdir(), "at-live-compile-"));
|
|
139
|
+
try {
|
|
140
|
+
execFileSync(process.execPath, [CLI, "scaffold", resolve(here, "../e2e/fixtures/compile.at"), "--target", "claude-code", "--output", project], {
|
|
141
|
+
stdio: "ignore",
|
|
142
|
+
});
|
|
143
|
+
const run = runClaude(project);
|
|
144
|
+
// drafter carries a regex matcher and a prompt hook in its frontmatter: a
|
|
145
|
+
// YAML error there would drop it. auditor is manual: without a
|
|
146
|
+
// description Claude Code skipped it.
|
|
147
|
+
expect(run.init.agents).toEqual(expect.arrayContaining(["drafter", "auditor"]));
|
|
148
|
+
// runs: fork and runs: inline are skills, not agents (M1); auditor's new
|
|
149
|
+
// frontmatter (color, initialPrompt, omitClaudeMd, effort) still loads (F1)
|
|
150
|
+
expect(run.init.skills).toEqual(expect.arrayContaining(["critic", "tidy"]));
|
|
151
|
+
// tone has paths: ["drafts/**/*.md"]: Claude Code holds a path-scoped
|
|
152
|
+
// skill back until matching files are in play, so the field is honoured
|
|
153
|
+
expect(run.init.skills).not.toContain("tone");
|
|
154
|
+
expect(run.init.agents).not.toContain("critic");
|
|
155
|
+
// The fixture's Stop prompt hook asks for a summary; "OK" is not one, so
|
|
156
|
+
// Claude Code feeds the hook's verdict back: proof the prompt handler ran
|
|
157
|
+
// (as a command it would have failed to execute).
|
|
158
|
+
const fed = run.events.some((e) => e.type === "user" && JSON.stringify(e).includes("Stop hook feedback"));
|
|
159
|
+
expect(fed, "the Stop prompt hook did not run").toBe(true);
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
fs.rmSync(project, { recursive: true, force: true });
|
|
163
|
+
}
|
|
164
|
+
}, 200_000);
|
|
165
|
+
});
|
|
166
|
+
describe.skipIf(!LIVE)("[L4] Claude Code enforces a gate and an approval step before launching an agent", () => {
|
|
167
|
+
const launch = "Launch the drafter subagent with the task: write one line about tea. Do nothing else.";
|
|
168
|
+
const toolResults = (run) => JSON.stringify(run.events.filter((e) => e.type === "user"));
|
|
169
|
+
it.each([
|
|
170
|
+
["a failing gate blocks the launch", "#!/usr/bin/env bash\necho 'brief missing' >&2\nexit 1\n", "Gate 'brief-check' FAILED"],
|
|
171
|
+
["a passing gate reaches the approval step, which asks (headless: denies with its reason)", "#!/usr/bin/env bash\nexit 0\n", 'Approval step \\"approve\\"'],
|
|
172
|
+
])("%s", (_name, gateScript, expected) => {
|
|
173
|
+
const project = fs.mkdtempSync(join(os.tmpdir(), "at-live-before-"));
|
|
174
|
+
try {
|
|
175
|
+
execFileSync(process.execPath, [CLI, "scaffold", resolve(here, "../e2e/fixtures/compile.at"), "--target", "claude-code", "--output", project], {
|
|
176
|
+
stdio: "ignore",
|
|
177
|
+
});
|
|
178
|
+
fs.writeFileSync(join(project, ".claude/skills/compile/scripts/brief-check.sh"), gateScript);
|
|
179
|
+
const run = runClaude(project, launch, 2);
|
|
180
|
+
const launched = run.events.some((e) => e.type === "assistant" && JSON.stringify(e).includes('"subagent_type":"drafter"'));
|
|
181
|
+
expect(launched, "the model never tried to launch drafter").toBe(true);
|
|
182
|
+
expect(toolResults(run)).toContain(expected);
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
fs.rmSync(project, { recursive: true, force: true });
|
|
186
|
+
}
|
|
187
|
+
}, 200_000);
|
|
188
|
+
});
|
|
189
|
+
describe.skipIf(!LIVE)("[L5] Claude Code loads the topology context from .claude/rules", () => {
|
|
190
|
+
it("compile.at: a line in .claude/rules/compile.md reaches the session", () => {
|
|
191
|
+
const project = fs.mkdtempSync(join(os.tmpdir(), "at-live-rules-"));
|
|
192
|
+
try {
|
|
193
|
+
execFileSync(process.execPath, [CLI, "scaffold", resolve(here, "../e2e/fixtures/compile.at"), "--target", "claude-code", "--output", project], {
|
|
194
|
+
stdio: "ignore",
|
|
195
|
+
});
|
|
196
|
+
fs.appendFileSync(join(project, ".claude/rules/compile.md"), "\nThe project codeword is TEAPOT-7731.\n");
|
|
197
|
+
const run = runClaude(project, "Without using any tools: what is the project codeword? Reply with just the codeword, or NONE.");
|
|
198
|
+
expect(run.result.result ?? JSON.stringify(run.events)).toContain("TEAPOT-7731");
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
fs.rmSync(project, { recursive: true, force: true });
|
|
202
|
+
}
|
|
203
|
+
}, 200_000);
|
|
204
|
+
});
|
|
136
205
|
//# sourceMappingURL=claude-code.live.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.live.test.js","sourceRoot":"","sources":["../../../src/__tests__/live/claude-code.live.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC7D,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;AAEzC,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;AAE/C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,GAAG,CAAC;AAEzC;;;;GAIG;AACH,SAAS,SAAS;IAChB,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IAChE,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,IAAI,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;YAAE,SAAS;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IACjD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-code.live.test.js","sourceRoot":"","sources":["../../../src/__tests__/live/claude-code.live.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,30 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { describe, it } from "vitest";
|
|
10
10
|
describe("open findings (spec/testing.md)", () => {
|
|
11
|
-
it.todo("[
|
|
12
|
-
it.todo("[
|
|
13
|
-
it.todo("[
|
|
14
|
-
it.todo("[
|
|
15
|
-
it.todo("[B4] Schedule scripts call the wrong action path; `every:` becomes a commented-out cron line");
|
|
16
|
-
it.todo("[H1] Human nodes compile to frontmatter-less AGENT.md files that Claude Code ignores; they should be an approval step");
|
|
17
|
-
it.todo("[N4] `.mcp.json` drops `type`, so a url server is skipped");
|
|
18
|
-
it.todo("[N5] `type: prompt` hooks are emitted as commands");
|
|
19
|
-
it.todo("[N6] Universal events (AgentStop, ToolUse, Error) are emitted unmapped, so the hook never fires");
|
|
20
|
-
it.todo("[N7] MCP tool names: whole-server and dotted names mis-converted; permissions not converted");
|
|
21
|
-
it.todo("[N8] V27 accepts `confirm` and `bypass`, emitted as invalid `permissionMode`");
|
|
22
|
-
it.todo("[N9] A hook matcher with a regex breaks the agent file's YAML");
|
|
23
|
-
it.todo("[N10] `invocation: manual` drops the description, so the agent is not registered");
|
|
24
|
-
it.todo("[N14] `settings.ask` is parsed but never emitted");
|
|
25
|
-
it.todo("[N16] Model ids are not checked per target");
|
|
26
|
-
it.todo("[N17] Unquoted YAML scalars change type (`yes` becomes `true`)");
|
|
27
|
-
it.todo("[N18] No reference checks for `skills:`, `mcp-servers:`, skill `agent:`");
|
|
28
|
-
it.todo("[N19] Hook stubs carry the date, so output is not byte-stable");
|
|
29
|
-
it.todo("[C1] `scaffold --dry-run` says settings.json and .mcp.json would be \"config merged\" but does not show the diff (content session, 2026-10-29)");
|
|
30
|
-
it.todo("[C2] Scaffold adds `.claude/CLAUDE.md`, which competes with a project's root CLAUDE.md (content session, 2026-10-29)");
|
|
31
|
-
it.todo("[C3] Run-line parsing takes placeholders and file arguments as scripts (`SLUG`, `frames-critic.json`) and plans stubs for them (content session, 2026-10-29)");
|
|
32
|
-
it.todo("[C4] A gate whose `after:` is an action or a human compiles to no enforceable hook (10 gates in content-harness)");
|
|
33
|
-
it.todo("[B5] An agent's permissions read as per-agent grants; Claude Code allow rules are session-wide");
|
|
34
|
-
it.todo("[F1] Missing first-class fields: agent effort, initialPrompt, omitClaudeMd, cache TTL, color; skill when_to_use, arguments, paths, shell");
|
|
35
|
-
it.todo("[F2] Hooks as a typed union (http, mcp_tool, agent; once, async, if)");
|
|
11
|
+
it.todo("[B3] Agent teams (peers that message each other) have no node or edge type; experimental in Claude Code, interactive sessions only");
|
|
12
|
+
it.todo("[B7] The `observability { }` block is ignored by the claude-code binding");
|
|
13
|
+
it.todo("[N22] Subagent nesting depth (Claude Code: 3) and fan-out (20 at once) are not checked");
|
|
14
|
+
it.todo("[F4] Agent `memory` scope (user/project/local) and `autoCompactWindow` are not first-class; `memory:` already names stores, so the scope needs another word");
|
|
36
15
|
});
|
|
37
16
|
//# sourceMappingURL=open-findings.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open-findings.test.js","sourceRoot":"","sources":["../../src/__tests__/open-findings.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEtC,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"open-findings.test.js","sourceRoot":"","sources":["../../src/__tests__/open-findings.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEtC,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,EAAE,CAAC,IAAI,CAAC,oIAAoI,CAAC,CAAC;IAC9I,EAAE,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAC;IACpF,EAAE,CAAC,IAAI,CAAC,wFAAwF,CAAC,CAAC;IAClG,EAAE,CAAC,IAAI,CAAC,6JAA6J,CAAC,CAAC;AACzK,CAAC,CAAC,CAAC"}
|
|
@@ -208,8 +208,8 @@ describe("claude-code binding", () => {
|
|
|
208
208
|
const mcp = JSON.parse(mcpFile.content);
|
|
209
209
|
expect(mcp.mcpServers.filesystem).toBeDefined();
|
|
210
210
|
});
|
|
211
|
-
it("produces a context file (.claude/
|
|
212
|
-
const contextFile = files.find((f) => f.path
|
|
211
|
+
it("produces a context file (.claude/rules/<topology>.md, never a CLAUDE.md)", () => {
|
|
212
|
+
const contextFile = files.find((f) => /^\.claude\/rules\/[^/]+\.md$/.test(f.path));
|
|
213
213
|
expect(contextFile).toBeDefined();
|
|
214
214
|
// Must never generate root-level CLAUDE.md
|
|
215
215
|
const rootClaudeMd = files.find((f) => f.path === "CLAUDE.md");
|
|
@@ -358,10 +358,11 @@ topology gate-target-test : [pipeline] {
|
|
|
358
358
|
const humanHook = (settings.hooks?.SubagentStop ?? []).find((h) => h.matcher === "approver");
|
|
359
359
|
expect(humanHook).toBeUndefined();
|
|
360
360
|
});
|
|
361
|
-
it("
|
|
362
|
-
|
|
363
|
-
expect(
|
|
364
|
-
|
|
361
|
+
it("wires a gate after a human node before its next agent launches (PreToolUse), without a warning", () => {
|
|
362
|
+
expect(warnings.find((w) => w.includes("gate-on-human"))).toBeUndefined();
|
|
363
|
+
expect(JSON.stringify(settings.hooks.PreToolUse)).toContain("before-agent.sh");
|
|
364
|
+
const script = files.find((f) => f.path.endsWith("/scripts/before-agent.sh"));
|
|
365
|
+
expect(script.content).toMatch(/publisher\)\n[\s\S]*gate-gate-on-human\.sh/);
|
|
365
366
|
});
|
|
366
367
|
it("still generates the gate wrapper script for non-agent-targeted gate", () => {
|
|
367
368
|
// The wrapper must exist so the orchestrator/playbook can invoke it
|
|
@@ -369,10 +370,9 @@ topology gate-target-test : [pipeline] {
|
|
|
369
370
|
const wrapper = files.find((f) => f.path.endsWith("/scripts/gate-gate-on-human.sh"));
|
|
370
371
|
expect(wrapper).toBeDefined();
|
|
371
372
|
});
|
|
372
|
-
it("wrapper script for
|
|
373
|
+
it("wrapper script for a gate after a human documents its PreToolUse enforcement", () => {
|
|
373
374
|
const wrapper = files.find((f) => f.path.endsWith("/scripts/gate-gate-on-human.sh"));
|
|
374
|
-
expect(wrapper.content).toContain(
|
|
375
|
-
expect(wrapper.content).toContain("orchestrator playbook");
|
|
375
|
+
expect(wrapper.content).toContain('PreToolUse hook (before-agent.sh) before Claude Code launches "publisher"');
|
|
376
376
|
});
|
|
377
377
|
it("wrapper script for agent-targeted gate documents SubagentStop enforcement", () => {
|
|
378
378
|
const wrapper = files.find((f) => f.path.endsWith("/scripts/gate-gate-on-agent.sh"));
|
|
@@ -490,9 +490,10 @@ topology youtube-flywheel : [pipeline, fan-out, human-gate] {
|
|
|
490
490
|
const matchers = (settings.hooks?.SubagentStop ?? []).map((h) => h.matcher);
|
|
491
491
|
expect(matchers).not.toContain("approve-brief");
|
|
492
492
|
});
|
|
493
|
-
it("
|
|
494
|
-
|
|
495
|
-
|
|
493
|
+
it("runs the platform-credentials gate (after the human approve-brief) before renderer launches", () => {
|
|
494
|
+
expect(warnings.find((m) => m.includes("platform-credentials"))).toBeUndefined();
|
|
495
|
+
const script = files.find((f) => f.path.endsWith("/scripts/before-agent.sh"));
|
|
496
|
+
expect(script.content).toMatch(/renderer\)\n[\s\S]*gate-platform-credentials\.sh/);
|
|
496
497
|
});
|
|
497
498
|
});
|
|
498
499
|
// ---------------------------------------------------------------------------
|
|
@@ -718,12 +719,11 @@ topology debate-test : [fan-out, debate, pipeline] {
|
|
|
718
719
|
expect(judge.content).not.toContain("Group Conversation Protocol");
|
|
719
720
|
});
|
|
720
721
|
});
|
|
721
|
-
describe("human node →
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
expect(
|
|
726
|
-
expect(humanAgent.content).toContain("skip");
|
|
722
|
+
describe("human node → approval step", () => {
|
|
723
|
+
it("is an approval step in the playbook, with timeout and on-timeout, and no AGENT.md", () => {
|
|
724
|
+
expect(exoticFiles.find((f) => f.path === ".claude/agents/moderator/AGENT.md")).toBeUndefined();
|
|
725
|
+
const playbook = exoticFiles.find((f) => /^\.claude\/skills\/[^/]+\/SKILL\.md$/.test(f.path) && f.content.includes("## Approval steps"));
|
|
726
|
+
expect(playbook.content).toMatch(/### Moderator[\s\S]*Timeout: 1h\nOn timeout: skip/);
|
|
727
727
|
});
|
|
728
728
|
});
|
|
729
729
|
describe("agent frontmatter — Claude Code native fields", () => {
|
|
@@ -804,7 +804,7 @@ topology debate-test : [fan-out, debate, pipeline] {
|
|
|
804
804
|
expect(schema.content).toContain("winner");
|
|
805
805
|
});
|
|
806
806
|
it("artifacts documented in CLAUDE.md", () => {
|
|
807
|
-
const ctx = exoticFiles.find((f) => f.path
|
|
807
|
+
const ctx = exoticFiles.find((f) => /^\.claude\/rules\/[^/]+\.md$/.test(f.path));
|
|
808
808
|
expect(ctx.content).toContain("transcript");
|
|
809
809
|
});
|
|
810
810
|
it("skills generate SKILL.md files", () => {
|