Add DOT docs test suite and fix invalid DOT in docs examples

Extract all 29 full digraph workflows from docs into test/docs/ with
an extraction script, assemble 7 snippet DOTs from reference pages,
and add a runner script for validate/dry-run/haiku/full phases.

Docs fixes:
- definition-of-done: replace multi-word condition values with
  underscored equivalents (parser doesn't support spaces), make
  safe-default edges unconditional for fallback coverage
- semantic-port: make fallback edges unconditional on fetch/analyze
  nodes so validator doesn't reject all-conditional-edge nodes

All 36 DOTs pass `arc validate`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-06 14:55:56 -05:00
parent ae3a9e7505
commit 2cce052f9f
47 changed files with 2792 additions and 15 deletions

View file

@ -149,7 +149,7 @@ Respond with JSON (not by writing out a file):
\"remaining_implementable\": M
}
If remaining_implementable > 0, set preferred_next_label to \"More fixes needed\".
If remaining_implementable > 0, set preferred_next_label to \"more_fixes_needed\".
Otherwise set preferred_next_label to \"Re-audit\"."
]
@ -206,7 +206,7 @@ Respond with JSON (not by writing out a file):
}
If remaining_total == 0 (ignoring DEFERRED items), set preferred_next_label to \"Complete\".
Otherwise set preferred_next_label to \"More work needed\"."
Otherwise set preferred_next_label to \"more_work_needed\"."
]
/*------------------------------------------------------------------------
@ -238,17 +238,17 @@ Otherwise set preferred_next_label to \"More work needed\"."
/* Build check outcomes */
build_check -> final_audit [label="Build OK", condition="outcome=success"]
build_check -> build_fix [label="Build failed", condition="outcome=fail"]
build_check -> build_fix [label="Build failed"]
/* Build fix loops back to build check */
build_fix -> build_check
/* Fix batch can loop for more fixes */
fix_batch -> fix_batch [label="More fixes needed", condition="preferred_label=More fixes needed", loop_restart=true]
fix_batch -> fix_batch [label="More fixes needed", condition="preferred_label=more_fixes_needed", loop_restart=true]
/* Final audit outcomes */
final_audit -> review_gate [label="Complete", condition="preferred_label=Complete"]
final_audit -> triage [label="More work needed", condition="preferred_label=More work needed"]
final_audit -> triage [label="More work needed"]
/* Human review gate */
review_gate -> exit [label="A) Accept"]
@ -701,9 +701,9 @@ Respond with JSON (not by writing out a file):
\"remaining_implementable\": M
}
If issues_found contains any critical items, set preferred_next_label to \"More fixes needed\".
If remaining_implementable > 0 and no critical issues, set preferred_next_label to \"More fixes needed\".
Otherwise set preferred_next_label to \"Ready for build\"."
If issues_found contains any critical items, set preferred_next_label to \"more_fixes_needed\".
If remaining_implementable > 0 and no critical issues, set preferred_next_label to \"more_fixes_needed\".
Otherwise set preferred_next_label to \"ready_for_build\"."
]
/*========================================================================
@ -810,7 +810,7 @@ Respond with JSON (not by writing out a file):
}
If remaining_total == 0 (ignoring DEFERRED items), set preferred_next_label to \"Complete\".
Otherwise set preferred_next_label to \"More work needed\"."
Otherwise set preferred_next_label to \"more_work_needed\"."
]
/*========================================================================
@ -857,12 +857,13 @@ Otherwise set preferred_next_label to \"More work needed\"."
review_fix_opus -> review_codex
/* Implementation loop */
review_codex -> fix_codex [label="More fixes needed", condition="preferred_label=More fixes needed", loop_restart=true]
review_codex -> build_check [label="Ready for build", condition="preferred_label=Ready for build"]
review_codex -> fix_codex [label="More fixes needed", condition="preferred_label=more_fixes_needed", loop_restart=true]
review_codex -> build_check [label="Ready for build", condition="preferred_label=ready_for_build"]
review_codex -> fix_codex [label="Fallback"]
/* Phase 6: Build */
build_check -> final_audit_opus [label="Build OK", condition="outcome=success"]
build_check -> build_fix [label="Build failed", condition="outcome=fail"]
build_check -> build_fix [label="Build failed"]
build_fix -> build_check
/* Phase 7: Dual final audit (sequential — Opus then GPT then consensus) */
@ -871,7 +872,7 @@ Otherwise set preferred_next_label to \"More work needed\"."
/* Final decision */
final_consensus -> review_gate [label="Complete", condition="preferred_label=Complete"]
final_consensus -> triage_merge [label="More work needed", condition="preferred_label=More work needed"]
final_consensus -> triage_merge [label="More work needed"]
/* Phase 8: Human gate */
review_gate -> exit [label="A) Accept"]

View file

@ -122,10 +122,10 @@ digraph SemanticPort {
start -> fetch
fetch -> analyze [label="Process", condition="preferred_label=process"]
fetch -> exit [label="Done", condition="preferred_label=done"]
fetch -> exit [label="Done"]
analyze -> plan [label="Port", condition="preferred_label=port"]
analyze -> fetch [label="Skip", condition="preferred_label=skip"]
analyze -> fetch [label="Skip"]
plan -> implement -> validate -> gate

83
test/docs/CHECKLIST.md Normal file
View file

@ -0,0 +1,83 @@
# DOT Documentation Examples Test Checklist
## Summary
- 36 .dot files (29 extracted from full workflows + 7 assembled from snippets)
- Covers 29 doc pages, 118 DOT code blocks (29 full, 89 snippets)
- Skipped: changelog/2026-02-27 (deprecated `handler=codergen` syntax)
## Phase 1: Validate (`arc validate`)
| # | File | Status | Notes |
|---|------|--------|-------|
| 1 | agents/outputs/output-patterns.dot | PASS | assembled |
| 2 | agents/prompts/pipeline.dot | PASS | added start/exit |
| 3 | changelog/2026-03-05/new-features.dot | PASS | assembled, added fallback |
| 4 | core-concepts/agents/backend-demo.dot | PASS | assembled |
| 5 | core-concepts/models/example.dot | PASS | added start/exit + wiring |
| 6 | core-concepts/workflows/my-workflow.dot | PASS | |
| 7 | examples/clone-substack/clone-substack.dot | PASS | 578 lines |
| 8 | examples/definition-of-done/spec-dod-multimodel.dot | PASS | fixed condition quoting + fallbacks |
| 9 | examples/definition-of-done/spec-dod.dot | PASS | fixed condition quoting + fallbacks |
| 10 | examples/nlspec-conformance/n-l-spec-conformance.dot | PASS | warning: goal_gate without retry_target |
| 11 | examples/semantic-port/semantic-port.dot | PASS | added fallback edges |
| 12 | examples/solitaire/build-solitaire.dot | PASS | warning: missing retry_target |
| 13 | execution/context/example.dot | PASS | added start/exit |
| 14 | execution/failures/example.dot | PASS | added start/exit |
| 15 | execution/failures/example-02.dot | PASS | added start/exit |
| 16 | execution/failures/example-03.dot | PASS | added start/exit |
| 17 | execution/failures/example-04.dot | PASS | added start/exit |
| 18 | execution/interviews/default-choice.dot | PASS | assembled |
| 19 | execution/run-configuration/c-i.dot | PASS | added start/exit, has run.toml |
| 20 | getting-started/why-arc/plan-implement.dot | PASS | |
| 21 | reference/dot-language/implement-feature.dot | PASS | |
| 22 | reference/dot-language/my-workflow.dot | PASS | |
| 23 | tutorials/branch-loop/branch-loop.dot | PASS | |
| 24 | tutorials/ensemble/ensemble.dot | PASS | |
| 25 | tutorials/hello-world/hello.dot | PASS | |
| 26 | tutorials/hello-world/sub-agent.dot | PASS | |
| 27 | tutorials/hello-world/tool-use.dot | PASS | |
| 28 | tutorials/multi-model/multi-model.dot | PASS | |
| 29 | tutorials/parallel-review/parallel.dot | PASS | |
| 30 | tutorials/plan-implement/plan-implement.dot | PASS | has @prompt stub |
| 31 | workflows/human-in-the-loop/hitl-patterns.dot | PASS | assembled |
| 32 | workflows/stages-and-nodes/all-node-types.dot | PASS | assembled, 15 nodes |
| 33 | workflows/stylesheets/example.dot | PASS | |
| 34 | workflows/transitions/transition-patterns.dot | PASS | assembled, added fallbacks |
| 35 | workflows/variables/check.dot | PASS | has run.toml |
| 36 | workflows/variables/example.dot | PASS | added start/exit |
## Phase 2: Dry Run (`arc run start --dry-run --auto-approve`)
| # | File | Status | Notes |
|---|------|--------|-------|
| 1-36 | (all) | | |
## Phase 3: Haiku (`arc run start --model claude-haiku-4-5 --auto-approve`)
| # | File | Status | Notes |
|---|------|--------|-------|
| 1-36 | (all) | | |
## Phase 4: Full (`arc run start --auto-approve`)
| # | File | Status | Notes |
|---|------|--------|-------|
| 1-36 | (all) | | |
## Issues Found During Validation (fixed in test DOTs)
1. **Condition parser doesn't support multi-word values**`preferred_label=More fixes needed` fails parse. Fixed by using underscored values (`more_fixes_needed`). Affects: definition-of-done examples. **This is a docs bug** — the source DOTs in docs/examples/ use multi-word condition values that won't parse.
2. **Several "full" digraphs in docs lack start/exit nodes** — 9 extracted DOTs were minimal digraph wrappers showing graph-level attributes without start/exit nodes or wiring. Fixed by adding them in test DOTs.
3. **All-conditional edges need unconditional fallback** — Validator requires at least one fallback edge when a node has only conditional outgoing edges. Fixed by adding fallback edges. Affects: semantic-port, definition-of-done examples, and assembled snippet DOTs.
## Commands
```bash
# Run each phase:
./test/docs/run_tests.sh validate
./test/docs/run_tests.sh dry-run
./test/docs/run_tests.sh haiku
./test/docs/run_tests.sh full
```

View file

@ -0,0 +1,33 @@
// Assembled from docs/agents/outputs.mdx snippets
// Tests output context keys and routing directives
digraph OutputPatterns {
graph [goal="Exercise output and routing patterns from the outputs docs page"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
// Line 25-29: Context keys from prior stages
plan [label="Plan", prompt="Create an implementation plan."]
implement [label="Implement", prompt="Implement the plan."]
// Line 68-78: Review node with routing directives
review [
label="Review",
shape=tab,
prompt="Review the implementation. If changes are needed, \
respond with: {\"preferred_next_label\": \"fix\"}. \
If everything looks good, respond with: \
{\"preferred_next_label\": \"approve\"}."
]
fix [label="Fix", prompt="Fix the issues found."]
// Wiring
start -> plan -> implement -> review
review -> fix [label="Fix"]
review -> exit [label="Approve"]
fix -> review
}

View file

@ -0,0 +1,10 @@
digraph Pipeline {
graph [goal="Add a /health endpoint to the API server"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
implement [prompt="Implement the following: $goal"]
start -> implement -> exit
}

View file

@ -0,0 +1,28 @@
// Assembled from docs/changelog/2026-03-05.mdx snippets
// Tests: condition expressions, model assignment, per-node max_visits,
// $$ escape, and simplified handler type names
digraph NewFeatures {
graph [goal="Exercise new features from the 2026-03-05 changelog"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
// Line 85: Model assignment (gpt54-pro)
stage_a [model="gpt54-pro", type="agent", prompt="The cost is $$50 and the goal is $goal"]
// Line 95: Per-node loop limit
verify [type="agent", max_visits=20, prompt="Verify the implementation."]
// Line 128-129: Simplified handler type names
stage_b [type="prompt", prompt="Summarize the results."]
// Wiring with condition expressions (line 31)
start -> stage_a -> verify
verify -> stage_b [label="Pass", condition="outcome=success"]
verify -> stage_a [label="Retry", condition="outcome=fail"]
verify -> exit [label="Fallback"]
stage_b -> exit
}

View file

@ -0,0 +1,18 @@
// Assembled from docs/core-concepts/agents.mdx snippets
// Tests backend attribute and inline vs external prompts
digraph BackendDemo {
graph [goal="Exercise agent backend and prompt patterns from the agents docs page"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
// Line 47: CLI backend with explicit provider
implement [label="Implement", backend="cli", llm_provider="anthropic"]
// Line 95-96: Inline prompt
plan [label="Plan", prompt="Analyze the codebase and write a step-by-step plan."]
// Wiring
start -> plan -> implement -> exit
}

View file

@ -0,0 +1,19 @@
digraph Example {
graph [
goal="Demonstrate model stylesheet",
model_stylesheet="
* { llm_model: claude-haiku-4-5; }
.coding { llm_model: claude-sonnet-4-5; reasoning_effort: high; }
#review { llm_model: gemini-3.1-pro-preview; }
"
]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
spec [label="Write Spec"]
implement [label="Implement", class="coding"]
review [label="Review"]
start -> spec -> implement -> review -> exit
}

View file

@ -0,0 +1,12 @@
digraph MyWorkflow {
graph [goal="Describe the project"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
scan [label="Scan Files", shape=parallelogram, script="find . -maxdepth 2 -type f | head -30"]
analyze [label="Analyze", prompt="Review the file listing. Summarize the project structure.", shape=tab]
start -> scan -> analyze -> exit
}

View file

@ -0,0 +1,578 @@
digraph CloneSubstack {
graph [
goal="Build the Substack Creator Newsletter Engine — a pure React frontend \
(no backend) for brand-driven Substack content creation. Client-side Gemini LLM \
integration (gemini-3-flash-preview for fast tasks, gemini-3.1-pro-preview with \
extended thinking for important tasks, gemini-2.5-flash-lite for tests). IndexedDB \
persistence via idb library. Setup flow with API key, company identity, voice \
definition, and guardrails — each confirmed by gemini-3.1-pro-preview. Dashboard \
with post history, draft management, New Post and Trending Topics access. Trending \
Topics uses gemini-3-flash-preview with search grounding for research, \
gemini-3.1-pro-preview synthesizes 3 writing prompts. New Post pipeline: Topic \
(rich input) then Research (gemini-3-flash-preview search grounding, source \
metadata) then Outline (gemini-3.1-pro-preview one-shot) then Write/Edit/Guardrails \
(3 automatic gemini-3.1-pro-preview cycles) then Complete (serif footnoted citations \
with attribution lineage). Demo mode replays recorded sessions through production \
code path with fade-in prefills; ships with one bundled P&G session; cache miss \
shows error, no API fallback. Visual design matches Substack (serif fonts, horizontal \
dot step indicators, card primitives, accent progress bars, numbered footnotes). Test \
infrastructure: integration tests with canned data, smoke tests with live \
gemini-2.5-flash-lite, manual test option with real models. Deployment readiness for \
GitHub to Railway validated by code review only — no live deployment execution.",
rankdir=LR,
default_max_retry=3,
retry_target="plan_fanout",
fallback_retry_target="plan_fanout",
model_stylesheet="
* { llm_model: claude-opus-4-6; llm_provider: anthropic; }
.hard { llm_model: gpt-5.3-codex; llm_provider: openai; }
.verify { llm_model: claude-opus-4-6; llm_provider: anthropic; }
.branch-a { llm_model: claude-opus-4-6; llm_provider: anthropic; }
.branch-b { llm_model: gemini-3-flash-preview; llm_provider: gemini; }
"
]
exit [shape=Msquare, label="Exit"]
// =========================================================================
// Bootstrap
// =========================================================================
subgraph cluster_bootstrap {
label="Bootstrap"
start [shape=Mdiamond, label="Start"]
check_toolchain [
shape=parallelogram,
label="Check Toolchain",
max_retries=0,
script="command -v node >/dev/null 2>&1 && command -v npm >/dev/null 2>&1 \
&& node --version && npm --version"
]
expand_spec [
label="Expand Spec",
prompt="Goal: $goal\n\n\
The project specification is at substack-spec-v01.md and the Definition of Done \
is at substack-dod-v01.md. The UI flow diagram is at substack-spec-v01-ui.gv.\n\n\
Read all three files. Scratch artifacts go under .workflow/.\n\n\
If .workflow/spec.md does not exist or is a placeholder, copy the spec verbatim \
to .workflow/spec.md, appending a reference to the UI flow diagram. If \
.workflow/definition_of_done.md does not exist or is a placeholder, copy the DoD \
verbatim to .workflow/definition_of_done.md. If both already exist and are \
adequate, skip."
]
}
// =========================================================================
// Planning Fanout
// =========================================================================
subgraph cluster_planning {
label="Planning Fanout"
node [shape=box]
plan_fanout [shape=component, label="Plan Fan-Out"]
plan_a [
label="Plan A",
class="branch-a",
prompt="Goal: $goal\n\n\
Read .workflow/spec.md and .workflow/definition_of_done.md. If those files do not \
exist, fall back to reading substack-spec-v01.md and substack-dod-v01.md directly. \
If .workflow/postmortem_latest.md exists, incorporate its lessons.\n\n\
Create an implementation plan for the Substack Creator Newsletter Engine covering \
all deliverables and acceptance criteria from the DoD. Be specific about:\n\
- React project setup (Vite + TypeScript + idb + @google/generative-ai SDK)\n\
- Module decomposition with file paths and estimated sizes (~200-500 lines each)\n\
- Core infrastructure: LLM client with structured JSON output and retry/backoff, \
IndexedDB persistence layer, shared UI components (rich input, card, progress bar, \
step indicators)\n\
- Feature modules: Setup flow, Dashboard, Trending Topics, New Post pipeline, \
Demo mode\n\
- Test infrastructure: integration (canned data), smoke (gemini-2.5-flash-lite), \
manual (real models)\n\
- Deployment config: Railway config, validation scripts\n\
- Build/validate scripts: validate-build.sh, validate-fmt.sh, validate-test.sh, \
validate-browser.sh, fix-fmt.sh, validate-artifacts.sh\n\
- Visual design: Substack-like serif styling, no spinners\n\n\
Specify dependency ordering between modules.\n\n\
Write to .workflow/plan_a.md."
]
plan_b [
label="Plan B",
class="branch-b",
prompt="Goal: $goal\n\n\
Read .workflow/spec.md and .workflow/definition_of_done.md. If those files do not \
exist, fall back to reading substack-spec-v01.md and substack-dod-v01.md directly. \
If .workflow/postmortem_latest.md exists, incorporate its lessons.\n\n\
Create an implementation plan for the Substack Creator Newsletter Engine covering \
all deliverables and acceptance criteria from the DoD. Be specific about:\n\
- React project setup (Vite + TypeScript + idb + @google/generative-ai SDK)\n\
- Module decomposition with file paths and estimated sizes (~200-500 lines each)\n\
- Core infrastructure: LLM client with structured JSON output and retry/backoff, \
IndexedDB persistence layer, shared UI components (rich input, card, progress bar, \
step indicators)\n\
- Feature modules: Setup flow, Dashboard, Trending Topics, New Post pipeline, \
Demo mode\n\
- Test infrastructure: integration (canned data), smoke (gemini-2.5-flash-lite), \
manual (real models)\n\
- Deployment config: Railway config, validation scripts\n\
- Build/validate scripts: validate-build.sh, validate-fmt.sh, validate-test.sh, \
validate-browser.sh, fix-fmt.sh, validate-artifacts.sh\n\
- Visual design: Substack-like serif styling, no spinners\n\n\
Specify dependency ordering between modules.\n\n\
Write to .workflow/plan_b.md."
]
debate [
label="Debate & Consolidate",
prompt="Synthesize the two implementation plans into a single best-of-breed \
final plan.\n\n\
Read branch outputs via parallel_results.json. If parallel_results.json is missing, \
fall back to reading .workflow/plan_a.md and .workflow/plan_b.md.\n\n\
If .workflow/postmortem_latest.md exists, read it FIRST. The postmortem contains \
root-cause analysis and concrete fixes from the previous iteration. The final plan \
MUST be adjusted to address every issue identified in the postmortem — add new \
steps, change approaches, or reorder work as needed. Do not simply re-emit the \
same plan that failed.\n\n\
Also read .workflow/implementation_log.md and .workflow/verify_fidelity.md if they \
exist, to understand what worked and what failed in the previous iteration.\n\n\
Read .workflow/spec.md and .workflow/definition_of_done.md for context. If those \
files do not exist, fall back to reading substack-spec-v01.md and \
substack-dod-v01.md directly. Resolve conflicts between plans. Ensure dependency \
order is correct. Pick the most detailed and actionable approach for each module. \
The final plan must produce a work queue of bounded modules (~200-500 lines each), \
ordered so core infrastructure items come first (lower IDs), features next, and \
tests/deployment last.\n\n\
Write the final plan to .workflow/plan_final.md."
]
}
// =========================================================================
// Implement
// =========================================================================
subgraph cluster_implement {
label="Implement"
implement [
class="hard",
max_tokens=32768,
label="Implement",
prompt="Goal: $goal\n\n\
Read .workflow/plan_final.md, .workflow/spec.md, and \
.workflow/definition_of_done.md. If the spec or DoD files do not exist at those \
paths, fall back to reading substack-spec-v01.md and substack-dod-v01.md directly.\n\n\
BEFORE ANYTHING ELSE: check if .workflow/verify_errors.log exists. If it does, \
read it — it contains the exact commands that failed and their error output from \
the verify chain. Fix every error listed in that file, then delete \
.workflow/verify_errors.log when all fixes are applied. Do NOT regenerate working \
code — only fix the specific errors.\n\n\
Also check if .workflow/verify_fidelity.md exists. If it does, read it — it \
contains per-AC pass/fail verdicts from the fidelity check. Fix every failing AC \
listed in that file.\n\n\
If .workflow/postmortem_latest.md exists, read it and fix ONLY identified gaps — \
do NOT regenerate working code. On repair passes, read and fix existing files \
rather than skipping them.\n\n\
Implement the complete Substack Creator Newsletter Engine as a single pass. On a \
fresh pass (no postmortem), check if target files already exist on disk and are \
non-empty — if so, skip those files. Implement each module with complete, \
functional code — no stubs, no placeholders, no TODO comments. Follow the plan \
and spec precisely.\n\n\
Implementation order (core infrastructure first, then features, then tests/deploy):\n\n\
1. Project scaffold — package.json, vite.config.ts, tsconfig.json, index.html, \
src/main.tsx, src/App.tsx. Install dependencies: react, react-dom, \
react-router-dom, idb, @google/generative-ai. Write ALL validation scripts:\n\
- scripts/validate-build.sh: runs npm run build, checks dist/ exists\n\
- scripts/validate-fmt.sh: runs npx prettier --check src/\n\
- scripts/validate-test.sh: runs integration scenarios first, then smoke, \
writes evidence + .workflow/test-evidence/latest/manifest.json even on failure\n\
- scripts/validate-browser.sh: runs browser verification and captures artifacts\n\
- scripts/fix-fmt.sh: runs npx prettier --write src/\n\
- scripts/validate-artifacts.sh: verifies manifest scenario IDs match DoD \
integration scenarios\n\
All scripts: #!/bin/sh, set -e, POSIX sh failure trap.\n\n\
2. LLM client — src/lib/llm.ts, src/lib/llm-schemas.ts: structured JSON output \
with schema enforcement, retry with error feedback and intelligent backoff, model \
switching (gemini-3-flash-preview/gemini-3.1-pro-preview/gemini-2.5-flash-lite), \
client-side API key.\n\n\
3. Persistence — src/lib/db.ts, src/lib/types.ts: IndexedDB via idb with stores \
for configuration (API key, company, voice, guardrails), drafts, sessions (all \
inputs/LLM responses/intermediate state), post history (Markdown + attribution). \
All data persists unless user resets.\n\n\
4. Shared UI — src/components/RichInput.tsx, Card.tsx, ProgressBar.tsx, \
StepIndicator.tsx, src/styles/global.css.\n\n\
5. Setup flow — src/pages/Settings.tsx and step components: API key, company \
(rich input + gemini-3.1-pro-preview confirm + back), voice, guardrails. Parallel \
completion, status icons. Reset everything with confirmation.\n\n\
6. Dashboard — src/pages/Dashboard.tsx: New Post button, Trending Topics button, \
Settings link, post history, draft resume.\n\n\
7. Trending Topics — src/pages/TrendingTopics.tsx: parallel gemini-3-flash-preview \
search grounding queries, trend visualization, 3 gemini-3.1-pro-preview writing \
prompts, navigate to New Post prefilled.\n\n\
8. New Post — src/pages/NewPost.tsx with step components: Topic (rich input), \
Research (gemini-3-flash-preview search grounding, source cards with \
URL/title/author/date, highlight/delete), Outline (gemini-3.1-pro-preview one-shot, \
accept/back), Write (3 automatic gemini-3.1-pro-preview cycles: Write with \
citations, Edit for style, Guardrails-only), Complete (serif post with numbered \
footnotes, linked sources, attribution lineage).\n\n\
9. Demo mode — src/lib/demo.ts, src/pages/DemoMode.tsx, \
src/demo/bundled-session.json: session recording, replay through production path \
(fade-in prefills, highlight next button), bundled P&G session, cache-miss error \
with no API fallback.\n\n\
10. Test infrastructure — src/__tests__/: integration with canned data, smoke with \
gemini-2.5-flash-lite, manual mode option.\n\n\
11. Deploy config — railway.json or equivalent, deployment docs.\n\n\
Ensure App.tsx routing includes all pages. Verify imports/exports are consistent. \
Run npm install. Fix TypeScript errors.\n\n\
Log progress to .workflow/implementation_log.md.\n\n\
PRE-EXIT VERIFICATION: if .workflow/postmortem_latest.md exists, run \
sh scripts/validate-build.sh and re-read targeted files to confirm fixes."
]
}
// =========================================================================
// Verify Chain
// =========================================================================
subgraph cluster_verify {
label="Verify"
fix_fmt [
shape=parallelogram,
label="Fix Format",
max_retries=0,
script="sh scripts/fix-fmt.sh 2>&1 || { printf '\\n=== VERIFY FAILURE: \
fix-fmt ===\\n%s\\n' \"$(cat /tmp/fix-fmt.log 2>/dev/null || echo 'script missing \
or produced no output')\" >> .workflow/verify_errors.log; exit 1; }"
]
verify_fmt [
shape=parallelogram,
label="Check Format",
max_retries=0,
script="sh scripts/validate-fmt.sh 2>&1 | tee /tmp/validate-fmt.log; \
test ${PIPESTATUS[0]} -eq 0 || { printf '\\n=== VERIFY FAILURE: validate-fmt \
===\\n%s\\n' \"$(tail -30 /tmp/validate-fmt.log)\" >> .workflow/verify_errors.log; \
exit 1; }"
]
gate_fmt [shape=diamond, label="Fmt OK?"]
verify_build [
shape=parallelogram,
label="Check Build",
script="sh scripts/validate-build.sh 2>&1 | tee /tmp/validate-build.log; \
test ${PIPESTATUS[0]} -eq 0 || { printf '\\n=== VERIFY FAILURE: validate-build \
===\\n%s\\n' \"$(tail -50 /tmp/validate-build.log)\" >> .workflow/verify_errors.log; \
exit 1; }"
]
gate_build [shape=diamond, label="Build OK?"]
verify_test [
shape=parallelogram,
label="Run Tests",
script="sh scripts/validate-test.sh 2>&1 | tee /tmp/validate-test.log; \
test ${PIPESTATUS[0]} -eq 0 || { printf '\\n=== VERIFY FAILURE: validate-test \
===\\n%s\\n' \"$(tail -50 /tmp/validate-test.log)\" >> .workflow/verify_errors.log; \
exit 1; }"
]
gate_test [shape=diamond, label="Tests OK?"]
verify_browser [
shape=parallelogram,
label="Check Browser",
script="sh scripts/validate-browser.sh 2>&1 | tee \
/tmp/validate-browser.log; test ${PIPESTATUS[0]} -eq 0 || { printf '\\n=== VERIFY \
FAILURE: validate-browser ===\\n%s\\n' \"$(tail -50 /tmp/validate-browser.log)\" \
>> .workflow/verify_errors.log; exit 1; }"
]
gate_browser [shape=diamond, label="Browser OK?"]
verify_artifacts [
shape=parallelogram,
label="Check Artifacts",
max_retries=0,
script="sh scripts/validate-artifacts.sh 2>&1 | tee \
/tmp/validate-artifacts.log; test ${PIPESTATUS[0]} -eq 0 || { printf '\\n=== \
VERIFY FAILURE: validate-artifacts ===\\n%s\\n' \"$(tail -30 \
/tmp/validate-artifacts.log)\" >> .workflow/verify_errors.log; exit 1; }"
]
gate_artifacts [shape=diamond, label="Artifacts OK?"]
verify_fidelity [
label="Verify Fidelity",
class="verify",
prompt="Read .workflow/spec.md, .workflow/definition_of_done.md, \
.workflow/verify_fidelity.md (if present), \
.workflow/test-evidence/latest/manifest.json, and relevant implementation files.\n\n\
Evaluate these grouped acceptance checks and map each to concrete file paths:\n\
AC1: src/**/settings* and src/**/router* and src/**/indexeddb* - first-run routing, \
setup flow, persistence.\n\
AC2: src/**/dashboard* and src/**/history* and src/**/draft* - dashboard actions \
and resume/view flows.\n\
AC3: src/**/trending* and src/**/research* - grounded research, deterministic \
trends, prompt handoff.\n\
AC4: src/**/new-post* and src/**/outline* and src/**/write* and src/**/complete* - \
full Topic->Complete pipeline with automatic write cycles.\n\
AC5: src/**/citation* and src/**/markdown* - citation lineage, footnote rendering, \
attribution persistence.\n\
AC6: src/**/demo* and src/demo/** - session picker/replay, bundled P&G demo, \
cache-miss no-fallback behavior.\n\
AC7: src/**/llm* and src/**/schema* - structured outputs, retry/backoff, \
production/test model intent.\n\
AC8: scripts/validate-build.sh and railway.json/Procfile/README* - \
build/deploy-readiness by static review only, no live deployment execution.\n\
AC9: scripts/validate-test.sh and scripts/validate-browser.sh and test sources - \
integration before smoke, manual mode option, browser evidence capture.\n\
AC10: .workflow/test-evidence/latest/manifest.json and \
.workflow/test-evidence/latest/** - IT-1..IT-12 manifest coverage and required \
artifact types.\n\
AC11: src/**/style* and src/**/card* and src/**/progress* - Substack-like visual \
contract including bars, cards, and serif post preview.\n\n\
Write .workflow/verify_fidelity.md with pass/fail verdict and evidence per \
AC1..AC11.\n\n\
On ANY failure: also append to .workflow/verify_errors.log with the header \
'=== VERIFY FAILURE: verify_fidelity ===' followed by the list of failing ACs \
and their specific issues, so the implement node can read the consolidated \
error log.\n\n\
If all ACs pass, include in your response:\n\
{\"context_updates\": {\"all_acs_pass\": \"true\"}}\n\n\
If any AC fails, include in your response:\n\
{\"context_updates\": {\"all_acs_pass\": \"false\"}}"
]
gate_fidelity [shape=diamond, label="Fidelity OK?"]
}
// =========================================================================
// Review Fanout
// =========================================================================
subgraph cluster_review {
label="Review Fanout"
node [shape=box]
review_fanout [shape=component, label="Review Fan-Out"]
review_a [
label="Review A",
class="branch-a",
prompt="Review the Substack Creator Newsletter Engine implementation \
against .workflow/definition_of_done.md.\n\n\
Read the DoD for acceptance criteria. Read all implementation source files and \
.workflow/test-evidence/latest/manifest.json.\n\n\
## MANDATORY: Browser verification\n\
You MUST verify the app works in a real browser. Do not trust code reading alone.\n\
1. Run: npm run build (must exit 0)\n\
2. Start the preview server: npx vite preview --port 4567 &\n\
3. Wait 2 seconds, then use curl to fetch http://localhost:4567/ and verify it \
returns HTML with a root div\n\
4. Check that the HTML references JS and CSS bundles\n\
5. Kill the preview server when done\n\
6. Check browser artifacts in .workflow/test-evidence/latest/ — screenshots must \
be real rendered pages (not 1x1 placeholders). If screenshot files are under 5KB, \
they are fake. REJECT.\n\
7. Check that playwright-report or equivalent browser test output exists and shows \
real test execution\n\n\
If browser verification fails or artifacts are fake, REJECT immediately.\n\n\
## Code and AC verification\n\
Check every AC group (AC1 through AC11):\n\n\
AC1: Build exits 0, static assets produced, deployment config present and coherent \
(review only, no live deploy)\n\
AC2: IndexedDB persistence for API key, config, posts, drafts, sessions, \
attribution mappings across reloads\n\
AC3: Structured JSON output with retry/backoff, correct model routing \
(gemini-3-flash-preview/gemini-3.1-pro-preview/gemini-2.5-flash-lite), \
client-side key\n\
AC4: Parallel setup (any order), status icons, rich input (text/upload/link), \
gemini-3.1-pro-preview confirmation, back button\n\
AC5: Dashboard with New Post and Trending Topics buttons, Settings link, post \
history, draft resume\n\
AC6: Trending Topics: parallel gemini-3-flash-preview search research, trend \
visualization, 3 gemini-3.1-pro-preview writing prompts, navigate to New Post\n\
AC7: Full post pipeline with source metadata, highlight/delete, one-shot outline, \
3 automatic write cycles, citations with attribution lineage\n\
AC8: Demo replay through production path, fade-in/highlight, bundled P&G session, \
cache-miss error\n\
AC9: Validation scripts and runtime evidence contract for build/test/browser checks\n\
AC10: IT-1..IT-12 evidence manifest coverage and artifact completeness\n\
AC11: Substack visual design: serif fonts, step dots, card primitive, accent \
progress bars, no spinners, footnoted post\n\n\
Verdict: APPROVED (all criteria met with evidence) or REJECTED (specific gaps \
by AC ID).\n\
Write to .workflow/review_a.md."
]
review_b [
label="Review B",
class="branch-b",
prompt="Review the Substack Creator Newsletter Engine implementation \
against .workflow/definition_of_done.md.\n\n\
Read the DoD for acceptance criteria. Read all implementation source files and \
.workflow/test-evidence/latest/manifest.json.\n\n\
## MANDATORY: Browser verification\n\
You MUST verify the app works in a real browser. Do not trust code reading alone.\n\
1. Run: npm run build (must exit 0)\n\
2. Start the preview server: npx vite preview --port 4568 &\n\
3. Wait 2 seconds, then use curl to fetch http://localhost:4568/ and verify it \
returns HTML with a root div\n\
4. Check that the HTML references JS and CSS bundles\n\
5. Kill the preview server when done\n\
6. Check browser artifacts in .workflow/test-evidence/latest/ — screenshots must \
be real rendered pages (not 1x1 placeholders). If screenshot files are under 5KB, \
they are fake. REJECT.\n\
7. Check that playwright-report or equivalent browser test output exists and shows \
real test execution\n\n\
If browser verification fails or artifacts are fake, REJECT immediately.\n\n\
## Code and AC verification\n\
Check every AC group (AC1 through AC11):\n\n\
AC1: Build exits 0, static assets produced, deployment config present and coherent \
(review only, no live deploy)\n\
AC2: IndexedDB persistence for API key, config, posts, drafts, sessions, \
attribution mappings across reloads\n\
AC3: Structured JSON output with retry/backoff, correct model routing \
(gemini-3-flash-preview/gemini-3.1-pro-preview/gemini-2.5-flash-lite), \
client-side key\n\
AC4: Parallel setup (any order), status icons, rich input (text/upload/link), \
gemini-3.1-pro-preview confirmation, back button\n\
AC5: Dashboard with New Post and Trending Topics buttons, Settings link, post \
history, draft resume\n\
AC6: Trending Topics: parallel gemini-3-flash-preview search research, trend \
visualization, 3 gemini-3.1-pro-preview writing prompts, navigate to New Post\n\
AC7: Full post pipeline with source metadata, highlight/delete, one-shot outline, \
3 automatic write cycles, citations with attribution lineage\n\
AC8: Demo replay through production path, fade-in/highlight, bundled P&G session, \
cache-miss error\n\
AC9: Validation scripts and runtime evidence contract for build/test/browser checks\n\
AC10: IT-1..IT-12 evidence manifest coverage and artifact completeness\n\
AC11: Substack visual design: serif fonts, step dots, card primitive, accent \
progress bars, no spinners, footnoted post\n\n\
Verdict: APPROVED (all criteria met with evidence) or REJECTED (specific gaps \
by AC ID).\n\
Write to .workflow/review_b.md."
]
review_consensus [
label="Review Consensus",
goal_gate=true,
retry_target="postmortem",
prompt="Synthesize the two reviews into a consensus verdict.\n\n\
Read branch outputs via parallel_results.json. If parallel_results.json is \
missing, fall back to reading .workflow/review_a.md and .workflow/review_b.md.\n\n\
Read .workflow/definition_of_done.md for acceptance criteria reference.\n\n\
Consensus rules:\n\
- Both APPROVED with no critical gaps: the implementation passes\n\
- Any critical gap identified by either reviewer: rejected with specific AC IDs\n\
- Mixed verdicts: rejected with gaps enumerated\n\n\
Write to .workflow/review_consensus.md.\n\n\
If approved, respond with:\n\
{\"preferred_next_label\": \"approved\"}\n\n\
If rejected, respond with:\n\
{\"preferred_next_label\": \"rejected\"}"
]
}
// =========================================================================
// Postmortem
// =========================================================================
subgraph cluster_postmortem {
label="Postmortem"
postmortem [
label="Postmortem",
prompt="Analyze the failure and guide the next repair iteration.\n\n\
Read (if they exist):\n\
- .workflow/review_consensus.md\n\
- .workflow/verify_fidelity.md\n\
- .workflow/implementation_log.md\n\
- .workflow/test-evidence/latest/manifest.json\n\
- Evidence files referenced by manifest entries for failed or suspicious IT \
scenarios\n\
- Branch review outputs via parallel_results.json (if available)\n\n\
Output to .workflow/postmortem_latest.md (overwrite previous):\n\
- Root causes of failure\n\
- What works and must be preserved\n\
- What failed and must be fixed\n\
- Concrete next changes (specific files, specific fixes)\n\
- Evidence file paths read (or explicit reason each was skipped)\n\
- Do NOT direct from-scratch restart — preserve working code\n\n\
PROGRESS DETECTION (required):\n\
Extract current failing AC IDs from verify_fidelity.md or review outputs. \
Compare with previous iteration and note whether progress was made \
(fewer/different failing ACs) or zero progress (identical set).\n\n\
OUTCOME CLASSIFICATION:\n\
- replan: default — always routes back through planning so the plan can be \
adjusted based on this postmortem\n\
- needs_toolchain: environment/bootstrap/toolchain issue detected (routes to \
check_toolchain)\n\n\
Respond with exactly one of:\n\
{\"preferred_next_label\": \"replan\", \"context_updates\": \
{\"last_failing_acs\": \"AC1,AC7\"}}\n\
{\"preferred_next_label\": \"needs_toolchain\", \"context_updates\": \
{\"last_failing_acs\": \"AC1,AC7\"}}"
]
}
// =========================================================================
// Edges
// =========================================================================
// Bootstrap
start -> check_toolchain
check_toolchain -> expand_spec [condition="outcome=success"]
check_toolchain -> check_toolchain [condition="outcome=fail && context.failure_class=transient_infra", loop_restart=true]
check_toolchain -> postmortem [condition="outcome=fail && context.failure_class!=transient_infra"]
check_toolchain -> postmortem
expand_spec -> plan_fanout
// Planning
plan_fanout -> plan_a
plan_fanout -> plan_b
plan_a -> debate
plan_b -> debate
debate -> implement
// Implement -> Verify chain
implement -> fix_fmt
// Verify chain — failures go directly back to implement (errors logged to .workflow/verify_errors.log)
fix_fmt -> verify_fmt
verify_fmt -> gate_fmt
gate_fmt -> verify_build [condition="outcome=success"]
gate_fmt -> implement
verify_build -> gate_build
gate_build -> verify_test [condition="outcome=success"]
gate_build -> implement
verify_test -> gate_test
gate_test -> verify_browser [condition="outcome=success"]
gate_test -> implement
verify_browser -> gate_browser
gate_browser -> verify_artifacts [condition="outcome=success"]
gate_browser -> implement
verify_artifacts -> gate_artifacts
gate_artifacts -> verify_fidelity [condition="outcome=success"]
gate_artifacts -> implement
verify_fidelity -> gate_fidelity
gate_fidelity -> review_fanout [condition="context.all_acs_pass=true"]
gate_fidelity -> implement
// Review
review_fanout -> review_a
review_fanout -> review_b
review_a -> review_consensus
review_b -> review_consensus
review_consensus -> exit [label="Approved", condition="preferred_label=approved"]
review_consensus -> postmortem [label="Rejected"]
// Postmortem recovery routing
postmortem -> check_toolchain [label="Toolchain", condition="preferred_label=needs_toolchain"]
postmortem -> plan_fanout [label="Replan"]
}

View file

@ -0,0 +1,599 @@
digraph SpecDoDMultiModel {
graph [
goal="Satisfy every Definition of Done checkbox across both specs (unified-llm-spec.md, coding-agent-loop-spec.md). The implementation is in Rust under crates/. Do NOT modify the spec files. Only modify implementation code. Uses multi-model consensus: Opus 4.6 and GPT-5.2 compete on audits and planning, GPT-5.2-codex and Opus 4.6 alternate on implementation.",
default_max_retry="3",
retry_target="triage_merge",
default_fidelity="full",
model_stylesheet="
* { llm_model: claude-opus-4-6; llm_provider: anthropic; }
.opus { llm_model: claude-opus-4-6; llm_provider: anthropic; reasoning_effort: high; }
.gpt { llm_model: gpt-5.2; llm_provider: openai; reasoning_effort: high; }
.codex { llm_model: gpt-5.2-codex; llm_provider: openai; reasoning_effort: high; }
.merge { llm_model: claude-opus-4-6; llm_provider: anthropic; reasoning_effort: high; }
"
]
start [shape=Mdiamond]
exit [shape=Msquare]
/*========================================================================
* PHASE 1 — Dual Independent Audits (interleaved, fidelity-isolated)
*
* Each spec is audited by both models before moving to the next.
* Audit nodes use fidelity="truncate" so they only see the graph goal
* and NOT each other's responses — prevents anchoring bias.
* Full responses are still stored as response.<node_id> for later use.
*======================================================================*/
/* ---- LLM spec: both models ---- */
audit_llm_opus [
label="Opus: Audit LLM DoD",
shape=box,
class="opus",
fidelity="truncate",
prompt="Read docs/specs/unified-llm-spec.md Section 8 (Definition of Done) in full. Then read every source file under crates/llm/src/.
For EACH checkbox in sections 8.1 through 8.10, evaluate whether the current Rust implementation satisfies it. Be strict — a checkbox is only checked if the feature is fully implemented and would work correctly at runtime.
Respond with ONLY a JSON object (no prose) -- don't write it out as a file:
{
\"spec\": \"unified-llm\",
\"model\": \"opus\",
\"sections\": {
\"8.1\": { \"title\": \"Core Infrastructure\", \"items\": [ {\"text\": \"...\", \"pass\": true/false, \"reason\": \"...\"} ] },
...
},
\"total\": N,
\"passed\": M,
\"failed\": K,
\"failed_items\": [ {\"section\": \"8.2\", \"text\": \"...\", \"reason\": \"...\"} ]
}
Be thorough. Check every single checkbox."
]
audit_llm_gpt [
label="GPT-5.2: Audit LLM DoD",
shape=box,
class="gpt",
fidelity="truncate",
prompt="Read docs/specs/unified-llm-spec.md Section 8 (Definition of Done) in full. Then read every source file under crates/llm/src/.
For EACH checkbox in sections 8.1 through 8.10, evaluate whether the current Rust implementation satisfies it. Be strict — a checkbox is only checked if the feature is fully implemented and would work correctly at runtime.
Respond with ONLY a JSON object (no prose) -- don't write it out as a file:
{
\"spec\": \"unified-llm\",
\"model\": \"gpt-5.2\",
\"sections\": {
\"8.1\": { \"title\": \"Core Infrastructure\", \"items\": [ {\"text\": \"...\", \"pass\": true/false, \"reason\": \"...\"} ] },
...
},
\"total\": N,
\"passed\": M,
\"failed\": K,
\"failed_items\": [ {\"section\": \"8.2\", \"text\": \"...\", \"reason\": \"...\"} ]
}
Be thorough. Check every single checkbox."
]
/* ---- Agent spec: both models ---- */
audit_agent_opus [
label="Opus: Audit Agent DoD",
shape=box,
class="opus",
fidelity="truncate",
prompt="Read docs/specs/coding-agent-loop-spec.md Section 9 (Definition of Done) in full. Then read every source file under crates/agent/.
For EACH checkbox in sections 9.1 through 9.13, evaluate whether the current Rust implementation satisfies it. Be strict.
Respond with ONLY a JSON object (no prose) -- don't write it out as a file:
{
\"spec\": \"coding-agent-loop\",
\"model\": \"opus\",
\"sections\": { ... },
\"total\": N,
\"passed\": M,
\"failed\": K,
\"failed_items\": [ {\"section\": \"9.1\", \"text\": \"...\", \"reason\": \"...\"} ]
}
Be thorough. Check every single checkbox."
]
audit_agent_gpt [
label="GPT-5.2: Audit Agent DoD",
shape=box,
class="gpt",
fidelity="truncate",
prompt="Read docs/specs/coding-agent-loop-spec.md Section 9 (Definition of Done) in full. Then read every source file under crates/agent/.
For EACH checkbox in sections 9.1 through 9.13, evaluate whether the current Rust implementation satisfies it. Be strict.
Respond with ONLY a JSON object (no prose) -- don't write it out as a file:
{
\"spec\": \"coding-agent-loop\",
\"model\": \"gpt-5.2\",
\"sections\": { ... },
\"total\": N,
\"passed\": M,
\"failed\": K,
\"failed_items\": [ {\"section\": \"9.1\", \"text\": \"...\", \"reason\": \"...\"} ]
}
Be thorough. Check every single checkbox."
]
/*========================================================================
* PHASE 2 — Cross-Critique (fidelity=full to see all response.* keys)
*
* Each model reviews the other's audit. Like megaplan's Compete phase:
* independent work first, then adversarial review.
*======================================================================*/
critique_by_gpt [
label="GPT-5.2: Critique Opus Audits",
shape=box,
class="gpt",
fidelity="full",
prompt="You have all four audit reports available in context. The full outputs are in these context keys:
OPUS AUDITS:
- response.audit_llm_opus — Opus's audit of unified-llm-spec.md Section 8
- response.audit_agent_opus — Opus's audit of coding-agent-loop-spec.md Section 9
GPT AUDITS (your own):
- response.audit_llm_gpt — your audit of unified-llm-spec.md Section 8
- response.audit_agent_gpt — your audit of coding-agent-loop-spec.md Section 9
Compare them item by item. For every DoD checkbox where the two models DISAGREE (one says pass, the other says fail), re-read the relevant spec section and source file to determine who is correct.
Also identify items that one model flagged but the other missed entirely.
Respond with JSON (not by writing out a file):
{
\"agreements\": { \"both_pass\": N, \"both_fail\": N },
\"disagreements\": [
{
\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\",
\"opus_says\": \"pass|fail\", \"gpt_says\": \"pass|fail\",
\"verdict\": \"pass|fail\",
\"reasoning\": \"...\"
}
],
\"missed_by_opus\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"reason\": \"...\"} ],
\"missed_by_gpt\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"reason\": \"...\"} ]
}
Be rigorous. When in doubt, fail the checkbox — strictness prevents false confidence."
]
critique_by_opus [
label="Opus: Critique GPT-5.2 Audits",
shape=box,
class="opus",
fidelity="full",
prompt="You have all four audit reports available in context. The full outputs are in these context keys:
GPT AUDITS:
- response.audit_llm_gpt — GPT-5.2's audit of unified-llm-spec.md Section 8
- response.audit_agent_gpt — GPT-5.2's audit of coding-agent-loop-spec.md Section 9
OPUS AUDITS (your own):
- response.audit_llm_opus — your audit of unified-llm-spec.md Section 8
- response.audit_agent_opus — your audit of coding-agent-loop-spec.md Section 9
Compare them item by item. For every DoD checkbox where the two models DISAGREE (one says pass, the other says fail), re-read the relevant spec section and source file to determine who is correct.
Also identify items that one model flagged but the other missed entirely.
Respond with JSON (not by writing out a file):
{
\"agreements\": { \"both_pass\": N, \"both_fail\": N },
\"disagreements\": [
{
\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\",
\"opus_says\": \"pass|fail\", \"gpt_says\": \"pass|fail\",
\"verdict\": \"pass|fail\",
\"reasoning\": \"...\"
}
],
\"missed_by_opus\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"reason\": \"...\"} ],
\"missed_by_gpt\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"reason\": \"...\"} ]
}
Be rigorous. When in doubt, fail the checkbox — strictness prevents false confidence."
]
/*========================================================================
* PHASE 3 — Audit Consensus
*
* Merge all findings into a single agreed-upon truth.
* Like megaplan's Merge phase: best ideas from both, disagreements resolved.
*======================================================================*/
audit_consensus [
label="Merge: Audit Consensus",
shape=box,
class="merge",
fidelity="full",
prompt="You have all prior audit and critique outputs in context. The key inputs are:
FOUR AUDIT REPORTS (context keys response.audit_llm_opus, response.audit_agent_opus, response.audit_llm_gpt, response.audit_agent_gpt)
TWO CROSS-CRITIQUES (context keys response.critique_by_gpt, response.critique_by_opus)
Produce a single definitive audit result. Resolution rules:
1. If BOTH models agree a checkbox passes → pass
2. If BOTH models agree a checkbox fails → fail
3. If they DISAGREE, use the cross-critique verdicts. If the critiques also disagree, re-read the spec and code yourself and make the call. When in doubt, fail it.
4. Include any items that were missed by one model but caught by the other.
Respond with JSON (not by writing out a file):
{
\"spec_results\": {
\"unified-llm\": { \"total\": N, \"passed\": M, \"failed\": K, \"failed_items\": [...] },
\"coding-agent-loop\": { ... }
},
\"consensus_total\": N,
\"consensus_passed\": M,
\"consensus_failed\": K,
\"disagreements_resolved\": N,
\"all_failed_items\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"reason\": \"...\", \"agreed_by\": \"both|opus_only|gpt_only|resolved\"} ]
}"
]
/*========================================================================
* PHASE 4 — Dual Triage
*
* Both models independently prioritize the failures, then merge.
* Different models weight different risks differently — consensus is stronger.
*======================================================================*/
triage_opus [
label="Opus: Triage & Prioritize",
shape=box,
class="opus",
fidelity="full",
prompt="The consensus audit results are in context key response.audit_consensus. Parse the all_failed_items list from that JSON and triage every failing DoD checkbox.
Group failures into:
1. IMPLEMENTABLE — can be fixed by writing/modifying Rust code (functions, handlers, logic)
2. STRUCTURAL — requires new files, new modules, or significant architecture changes
3. DEFERRED — requires external resources (real API keys, network access, interactive testing) that cannot be done in a code-only pass
For each IMPLEMENTABLE item, identify the exact file(s) to modify and briefly describe the fix. Rank them by impact (most important first).
Respond with JSON (not by writing out a file):
{
\"model\": \"opus\",
\"total_failing\": N,
\"implementable\": [ {\"rank\": 1, \"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"files\": [\"...\"], \"fix\": \"...\", \"impact\": \"high|medium|low\"} ],
\"structural\": [ ... ],
\"deferred\": [ ... ]
}"
]
triage_gpt [
label="GPT-5.2: Triage & Prioritize",
shape=box,
class="gpt",
fidelity="full",
prompt="The consensus audit results are in context key response.audit_consensus. Parse the all_failed_items list from that JSON and triage every failing DoD checkbox.
Group failures into:
1. IMPLEMENTABLE — can be fixed by writing/modifying Rust code (functions, handlers, logic)
2. STRUCTURAL — requires new files, new modules, or significant architecture changes
3. DEFERRED — requires external resources (real API keys, network access, interactive testing) that cannot be done in a code-only pass
For each IMPLEMENTABLE item, identify the exact file(s) to modify and briefly describe the fix. Rank them by impact (most important first).
Respond with JSON (not by writing out a file):
{
\"model\": \"gpt-5.2\",
\"total_failing\": N,
\"implementable\": [ {\"rank\": 1, \"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"files\": [\"...\"], \"fix\": \"...\", \"impact\": \"high|medium|low\"} ],
\"structural\": [ ... ],
\"deferred\": [ ... ]
}"
]
triage_merge [
label="Merge: Triage Consensus",
shape=box,
class="merge",
fidelity="full",
prompt="You have two triage reports in context: response.triage_opus and response.triage_gpt. Merge them into a single prioritized work plan.
Resolution rules:
1. If both models classify an item the same way (IMPLEMENTABLE/STRUCTURAL/DEFERRED) → keep that classification
2. If they disagree on classification → take the MORE ACTIONABLE classification (prefer IMPLEMENTABLE over STRUCTURAL over DEFERRED)
3. For ranking, average the ranks and re-sort. If one model identified files/fixes the other didn't, include all suggestions.
4. Deduplicate items that both models identified.
Respond with JSON (not by writing out a file):
{
\"total_failing\": N,
\"implementable\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"files\": [\"...\"], \"fix\": \"...\", \"opus_rank\": N, \"gpt_rank\": N} ],
\"structural\": [ ... ],
\"deferred\": [ ... ],
\"classification_disagreements\": N,
\"verdict\": \"all_clear\" | \"has_fixes\" | \"only_deferred\"
}
If total_failing == 0 or verdict == \"only_deferred\", set preferred_next_label to \"Done\".
Otherwise set preferred_next_label to \"Fix\"."
]
/*========================================================================
* PHASE 5 — Multi-Model Implementation
*
* Codex implements, Opus reviews and corrects, Codex validates.
* Like megaplan's draft→critique→merge but for code.
*======================================================================*/
fix_codex [
label="Codex: Implement Fixes",
shape=box,
class="codex",
goal_gate=true,
fidelity="full",
prompt="The merged triage report is in context key response.triage_merge. It contains a prioritized list of IMPLEMENTABLE DoD failures.
Pick the top 5 most impactful items (or all if fewer than 5) and implement the fixes in Rust.
Begin by making sure the build is green with `cargo test`
For each fix:
1. Read the relevant source file(s)
2. Make the minimal change needed to satisfy the DoD checkbox
3. Write the modified file(s) -- update tests as needed
4. Verify the fix and the tests pass (`cargo test`)
Constraints:
- Do NOT modify any files under docs/specs/ (those are the specs)
- Do NOT add external dependencies beyond what's already used
- Keep changes minimal and focused — one checkbox per fix
- Maintain the existing code style
Respond with JSON (not by writing out a file):
{
\"model\": \"codex\",
\"fixes_applied\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"files_changed\": [\"...\"], \"description\": \"...\"} ],
\"count\": N,
\"remaining_implementable\": M
}"
]
review_fix_opus [
label="Opus: Review & Fix",
shape=box,
class="opus",
goal_gate=true,
fidelity="full",
prompt="Codex just implemented a batch of fixes. Its report is in context key response.fix_codex.
PART A — Review Codex's work:
1. Read every file that Codex modified (check the files_changed lists in response.fix_codex)
2. For each fix, verify it actually satisfies the DoD checkbox it claims to address
3. Check for: correctness, edge cases, style consistency, missing error handling
4. If a fix is wrong or incomplete, rewrite it correctly
PART B — Implement additional fixes:
5. From the remaining IMPLEMENTABLE items (see response.triage_merge for the full list), pick up to 5 more and implement them
6. Follow the same constraints as Codex (Rust, no new deps, minimal changes)
Respond with JSON (not by writing out a file):
{
\"model\": \"opus\",
\"codex_fixes_reviewed\": N,
\"codex_fixes_correct\": N,
\"codex_fixes_corrected\": [ {\"spec\": \"...\", \"section\": \"...\", \"issue\": \"...\", \"correction\": \"...\"} ],
\"additional_fixes\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"files_changed\": [\"...\"], \"description\": \"...\"} ],
\"total_fixes_this_round\": N,
\"remaining_implementable\": M
}"
]
review_codex [
label="Codex: Validate All Changes",
shape=box,
class="codex",
fidelity="full",
prompt="Opus reviewed your fixes and implemented additional ones. Its report is in context key response.review_fix_opus. Your original report is in response.fix_codex.
Validate the full set of changes from this round:
1. Read every file modified in this round (check files_changed in both response.fix_codex and response.review_fix_opus)
2. Check each change for correctness: does it satisfy its DoD checkbox?
3. Check for regressions: did any fix break something else?
4. Check for consistency: do all the changes work together?
Respond with JSON (not by writing out a file):
{
\"model\": \"codex\",
\"total_changes_reviewed\": N,
\"all_correct\": true/false,
\"issues_found\": [ {\"file\": \"...\", \"issue\": \"...\", \"severity\": \"critical|minor\"} ],
\"remaining_implementable\": M
}
If issues_found contains any critical items, set preferred_next_label to \"more_fixes_needed\".
If remaining_implementable > 0 and no critical issues, set preferred_next_label to \"more_fixes_needed\".
Otherwise set preferred_next_label to \"ready_for_build\"."
]
/*========================================================================
* PHASE 6 — Build Verification
*======================================================================*/
build_check [
label="Build & Smoke Test",
shape=parallelogram,
script="cargo build 2>&1 && echo '---BUILD OK---' && cargo test 2>&1 && echo '---ALL TESTS PASSED---'",
timeout="120s"
]
build_fix [
label="Opus: Fix Build Errors",
shape=box,
class="opus",
fidelity="full",
prompt="The build or smoke tests failed. The build output is in context key command.output. Diagnose the compilation errors or test failures and fix them.
Read the relevant source files, identify the issue, and write corrected versions. Common issues:
- Missing includes
- Type mismatches
- Undeclared functions
Output the fixes applied and ensure the code will compile cleanly with: cargo build"
]
/*========================================================================
* PHASE 7 — Dual Final Audit (interleaved, fidelity-isolated)
*
* Both models independently verify the fixes worked.
* If either model finds a remaining failure, it counts.
*======================================================================*/
final_audit_opus [
label="Opus: Final Verification",
shape=box,
class="opus",
fidelity="full",
prompt="This is a verification pass. The items that were previously failing are listed in context key response.triage_merge (the implementable list). The fixes applied are in response.fix_codex and response.review_fix_opus.
Re-read both spec DoD sections:
- docs/specs/unified-llm-spec.md Section 8
- docs/specs/coding-agent-loop-spec.md Section 9
And re-read the implementation files that were changed in this iteration.
Check ONLY the items that were previously failing. Have they been fixed?
Respond with JSON (not by writing out a file):
{
\"model\": \"opus\",
\"verified_fixed\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\"} ],
\"still_failing\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"reason\": \"...\"} ],
\"newly_broken\": [ ... ],
\"remaining_total\": N
}"
]
final_audit_gpt [
label="GPT-5.2: Final Verification",
shape=box,
class="gpt",
fidelity="full",
prompt="This is a verification pass. The items that were previously failing are listed in context key response.triage_merge (the implementable list). The fixes applied are in response.fix_codex and response.review_fix_opus.
Re-read both spec DoD sections:
- docs/specs/unified-llm-spec.md Section 8
- docs/specs/coding-agent-loop-spec.md Section 9
And re-read the implementation files that were changed in this iteration.
Check ONLY the items that were previously failing. Have they been fixed?
Respond with JSON (not by writing out a file):
{
\"model\": \"gpt-5.2\",
\"verified_fixed\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\"} ],
\"still_failing\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"reason\": \"...\"} ],
\"newly_broken\": [ ... ],
\"remaining_total\": N
}"
]
final_consensus [
label="Merge: Final Consensus",
shape=box,
class="merge",
fidelity="full",
prompt="You have final audit results from both models in context: response.final_audit_opus and response.final_audit_gpt. Merge them into a definitive status.
Rules:
1. An item is only \"verified_fixed\" if BOTH models agree it's fixed
2. If EITHER model says an item is still failing, it counts as still failing
3. Union all newly_broken items from both models
Respond with JSON (not by writing out a file):
{
\"verified_fixed\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"agreed_by\": \"both|opus_only|gpt_only\"} ],
\"still_failing\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"flagged_by\": \"both|opus_only|gpt_only\", \"reason\": \"...\"} ],
\"newly_broken\": [ ... ],
\"remaining_total\": N
}
If remaining_total == 0 (ignoring DEFERRED items), set preferred_next_label to \"Complete\".
Otherwise set preferred_next_label to \"more_work_needed\"."
]
/*========================================================================
* PHASE 8 — Human Gate
*======================================================================*/
review_gate [
label="A) Accept & finish\nB) Push for another round",
shape=hexagon
]
/*========================================================================
* EDGES — Serial interleaved chain
*
* The engine is single-path, so we interleave model audits per-spec.
* fidelity="truncate" on audit nodes prevents cross-model anchoring.
*======================================================================*/
/* Phase 1: Interleaved audits (Opus then GPT for each spec) */
start -> audit_llm_opus
audit_llm_opus -> audit_llm_gpt
audit_llm_gpt -> audit_agent_opus
audit_agent_opus -> audit_agent_gpt
/* Phase 2: Cross-critique (now sequential — GPT critiques Opus, then Opus critiques GPT) */
audit_agent_gpt -> critique_by_gpt
critique_by_gpt -> critique_by_opus
/* Phase 3: Consensus */
critique_by_opus -> audit_consensus
/* Phase 4: Dual triage (sequential — Opus then GPT then merge) */
audit_consensus -> triage_opus
triage_opus -> triage_gpt
triage_gpt -> triage_merge
/* Triage decision */
triage_merge -> exit [label="Done", condition="preferred_label=Done"]
triage_merge -> fix_codex [label="Fix", condition="preferred_label=Fix", weight=10]
triage_merge -> exit [label="Only deferred remain"]
/* Phase 5: Multi-model implementation (sequential alternation) */
fix_codex -> review_fix_opus
review_fix_opus -> review_codex
/* Implementation loop */
review_codex -> fix_codex [label="More fixes needed", condition="preferred_label=more_fixes_needed", loop_restart=true]
review_codex -> build_check [label="Ready for build", condition="preferred_label=ready_for_build"]
review_codex -> fix_codex [label="Fallback"]
/* Phase 6: Build */
build_check -> final_audit_opus [label="Build OK", condition="outcome=success"]
build_check -> build_fix [label="Build failed"]
build_fix -> build_check
/* Phase 7: Dual final audit (sequential — Opus then GPT then consensus) */
final_audit_opus -> final_audit_gpt
final_audit_gpt -> final_consensus
/* Final decision */
final_consensus -> review_gate [label="Complete", condition="preferred_label=Complete"]
final_consensus -> triage_merge [label="More work needed"]
/* Phase 8: Human gate */
review_gate -> exit [label="A) Accept"]
review_gate -> triage_merge [label="B) Another round"]
}

View file

@ -0,0 +1,231 @@
digraph SpecDoD {
graph [
goal="Satisfy every Definition of Done checkbox across both specs (unified-llm-spec.md, coding-agent-loop-spec.md). The implementation is in Rust under crates/. Do NOT modify the spec files. Only modify implementation code.",
default_max_retry="3",
retry_target="triage",
model_stylesheet="
* { llm_model: claude-opus-4-6; llm_provider: anthropic; }
.audit { reasoning_effort: high; }
.fix { llm_model: claude-opus-4-6; reasoning_effort: high; }
#final_audit { reasoning_effort: high; }
"
]
start [shape=Mdiamond]
exit [shape=Msquare]
/*------------------------------------------------------------------------
* Phase 1: Baseline audit — read every DoD checkbox, check the code
*----------------------------------------------------------------------*/
audit_llm [
label="Audit: Unified LLM Client DoD",
shape=box,
class="audit",
prompt="Read docs/specs/unified-llm-spec.md Section 8 (Definition of Done) in full. Then read every source file under crates/llm/src/.
For EACH checkbox in sections 8.1 through 8.10, evaluate whether the current Rust implementation satisfies it. Be strict — a checkbox is only checked if the feature is fully implemented and would work correctly at runtime.
Respond with ONLY a JSON object (no prose) -- don't write it out as a file:
{
\"spec\": \"unified-llm\",
\"sections\": {
\"8.1\": { \"title\": \"Core Infrastructure\", \"items\": [ {\"text\": \"...\", \"pass\": true/false, \"reason\": \"...\"} ] },
...
},
\"total\": N,
\"passed\": M,
\"failed\": K,
\"failed_items\": [ {\"section\": \"8.2\", \"text\": \"...\", \"reason\": \"...\"} ]
}
Be thorough. Check every single checkbox."
]
audit_agent [
label="Audit: Coding Agent Loop DoD",
shape=box,
class="audit",
prompt="Read docs/specs/coding-agent-loop-spec.md Section 9 (Definition of Done) in full. Then read every source file under crates/agent/.
For EACH checkbox in sections 9.1 through 9.13, evaluate whether the current Rust implementation satisfies it. Be strict.
Respond with ONLY a JSON object (no prose) -- don't write it out as a file:
{
\"spec\": \"coding-agent-loop\",
\"sections\": { ... },
\"total\": N,
\"passed\": M,
\"failed\": K,
\"failed_items\": [ {\"section\": \"9.1\", \"text\": \"...\", \"reason\": \"...\"} ]
}
Be thorough. Check every single checkbox."
]
/*------------------------------------------------------------------------
* Phase 2: Triage — merge results, prioritize failures, decide next step
*----------------------------------------------------------------------*/
triage [
label="Triage & Prioritize",
shape=box,
prompt="You have two audit reports in context (from audit_llm, audit_agent). Merge them into a single prioritized list of ALL failing DoD checkboxes.
Group failures into:
1. IMPLEMENTABLE — can be fixed by writing/modifying Rust code (functions, handlers, logic)
2. STRUCTURAL — requires new files, new modules, or significant architecture changes
3. DEFERRED — requires external resources (real API keys, network access, interactive testing) that cannot be done in a code-only pass
For each IMPLEMENTABLE item, identify the exact file(s) to modify and briefly describe the fix.
Respond with JSON (not by writing out a file):
{
\"total_failing\": N,
\"implementable\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"files\": [\"...\"], \"fix\": \"...\"} ],
\"structural\": [ ... ],
\"deferred\": [ ... ],
\"verdict\": \"all_clear\" | \"has_fixes\" | \"only_deferred\"
}
If total_failing == 0 or verdict == \"only_deferred\", set preferred_next_label to \"Done\".
Otherwise set preferred_next_label to \"Fix\"."
]
/*------------------------------------------------------------------------
* Phase 3: Fix — implement the highest-priority fixes
*----------------------------------------------------------------------*/
fix_batch [
label="Implement Fixes",
shape=box,
class="fix",
goal_gate=true,
prompt="The triage report identified IMPLEMENTABLE DoD failures. Pick the top 5 most impactful items (or all if fewer than 5) and implement the fixes in Rust.
Begin by making sure the build is green with `cargo test`
For each fix:
1. Read the relevant source file(s)
2. Make the minimal change needed to satisfy the DoD checkbox
3. Write the modified file(s) -- update tests as needed
4. Verify the fix and the tests pass (`cargo test`)
Constraints:
- Do NOT modify any files under docs/specs/ (those are the specs)
- Do NOT add external dependencies beyond what's already used
- Keep changes minimal and focused — one checkbox per fix
- Maintain the existing code style
Respond with JSON (not by writing out a file):
{
\"fixes_applied\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"files_changed\": [\"...\"], \"description\": \"...\"} ],
\"count\": N,
\"remaining_implementable\": M
}
If remaining_implementable > 0, set preferred_next_label to \"more_fixes_needed\".
Otherwise set preferred_next_label to \"Re-audit\"."
]
/*------------------------------------------------------------------------
* Phase 4: Build verification
*----------------------------------------------------------------------*/
build_check [
label="Build & Smoke Test",
shape=parallelogram,
script="cargo build 2>&1 && echo '---BUILD OK---' && cargo test 2>&1 && echo '---ALL TESTS PASSED---'",
timeout="120s"
]
/*------------------------------------------------------------------------
* Phase 5: Build failure recovery
*----------------------------------------------------------------------*/
build_fix [
label="Fix Build Errors",
shape=box,
class="fix",
prompt="The build or smoke tests failed. Read the build output from context (command.output key). Diagnose the compilation errors or test failures and fix them.
Read the relevant source files, identify the issue, and write corrected versions. Common issues:
- Missing includes
- Type mismatches
- Undeclared functions
Output the fixes applied and ensure the code will compile cleanly with: cargo build"
]
/*------------------------------------------------------------------------
* Phase 6: Final audit to confirm fixes worked
*----------------------------------------------------------------------*/
final_audit [
label="Final Verification Audit",
shape=box,
prompt="This is a verification pass. Re-read both spec DoD sections:
- docs/specs/unified-llm-spec.md Section 8
- docs/specs/coding-agent-loop-spec.md Section 9
And re-read the implementation files that were changed in this iteration.
Check ONLY the items that were previously failing. Have they been fixed?
Respond with JSON (not by writing out a file):
{
\"verified_fixed\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\"} ],
\"still_failing\": [ {\"spec\": \"...\", \"section\": \"...\", \"text\": \"...\", \"reason\": \"...\"} ],
\"newly_broken\": [ ... ],
\"remaining_total\": N
}
If remaining_total == 0 (ignoring DEFERRED items), set preferred_next_label to \"Complete\".
Otherwise set preferred_next_label to \"more_work_needed\"."
]
/*------------------------------------------------------------------------
* Phase 7: Human gate — confirm completion or push for another round
*----------------------------------------------------------------------*/
review_gate [
label="A) Accept & finish\nB) Push for another round",
shape=hexagon
]
/*------------------------------------------------------------------------
* Edges
*----------------------------------------------------------------------*/
start -> audit_llm
/* Sequential audit chain */
audit_llm -> audit_agent
audit_agent -> triage
/* Triage decision */
triage -> exit [label="Done", condition="preferred_label=Done"]
triage -> fix_batch [label="Fix", condition="preferred_label=Fix", weight=10]
triage -> exit [label="Only deferred remain"]
/* Fix -> build check */
fix_batch -> build_check
/* Build check outcomes */
build_check -> final_audit [label="Build OK", condition="outcome=success"]
build_check -> build_fix [label="Build failed"]
/* Build fix loops back to build check */
build_fix -> build_check
/* Fix batch can loop for more fixes */
fix_batch -> fix_batch [label="More fixes needed", condition="preferred_label=more_fixes_needed", loop_restart=true]
/* Final audit outcomes */
final_audit -> review_gate [label="Complete", condition="preferred_label=Complete"]
final_audit -> triage [label="More work needed"]
/* Human review gate */
review_gate -> exit [label="A) Accept"]
review_gate -> triage [label="B) Another round"]
}

View file

@ -0,0 +1,46 @@
digraph NLSpecConformance {
graph [
goal="Implement a conformant system from a natural language specification",
model_stylesheet="
* { llm_model: claude-haiku-4-5; llm_provider: anthropic; }
.impl { llm_model: claude-sonnet-4-5; reasoning_effort: high; }
"
]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
// Phase 1: Read spec and plan
plan [label="Plan", class="impl", prompt="@prompts/plan.md"]
// Phase 2: Build the initial implementation
subgraph cluster_impl {
label = "Implement & Conform"
node [thread_id="impl", fidelity="full"]
implement [label="Implement", class="impl", prompt="@prompts/implement.md"]
fix [label="Fix Failures", class="impl", prompt="@prompts/fix.md", max_visits=5]
}
// Phase 3: Quick conformance loop
test_quick [label="Quick Conformance", shape=parallelogram, script="make conformance-quick 2>&1 || true"]
gate_quick [shape=diamond, label="Quick suite passing?"]
// Phase 4: Full conformance
test_full [label="Full Conformance", shape=parallelogram, script="make conformance-full 2>&1 || true", goal_gate=true]
gate_full [shape=diamond, label="All tests passing?"]
// Wiring
start -> plan -> implement -> test_quick -> gate_quick
gate_quick -> test_full [label="Pass", condition="outcome=success"]
gate_quick -> fix [label="Fix"]
fix -> test_quick
test_full -> gate_full
gate_full -> exit [label="Pass", condition="outcome=success"]
gate_full -> fix [label="Fix"]
}

View file

@ -0,0 +1 @@
Stub prompt for testing.

View file

@ -0,0 +1 @@
Stub prompt for testing.

View file

@ -0,0 +1 @@
Stub prompt for testing.

View file

@ -0,0 +1,122 @@
digraph SemanticPort {
graph [
goal="Port semantic changes from upstream Python repository to our Go implementation",
rankdir=LR,
default_max_retry=3,
model_stylesheet="
* { llm_model: claude-sonnet-4-5; llm_provider: anthropic; }
.hard { llm_model: claude-opus-4-6; llm_provider: anthropic; }
.analyze { llm_model: gemini-3.1-pro-preview; llm_provider: gemini; }
"
]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
// Phase 1: Find the next unprocessed commit
fetch [
label="Fetch & Identify",
prompt="Find the next unprocessed upstream commit.\n\n\
1. Run `python3 ledger/manage.py earliest` to get the oldest commit with status=new\n\
2. If found, write the commit details to .arc/current_commit.md and respond with:\n\
{\"preferred_next_label\": \"process\"}\n\
3. If no new commits exist:\n\
a. Fetch latest from upstream: cd upstream/ && git fetch && git pull\n\
b. Find commits newer than the latest in ledger.tsv\n\
c. Add them with `python3 ledger/manage.py add <sha> <timestamp>`\n\
d. Try `earliest` again\n\
e. If still none, respond with: {\"preferred_next_label\": \"done\"}\n\n\
Respond with exactly one of: process or done."
]
// Phase 2: Analyze the commit and decide port vs. skip
analyze [
label="Analyze & Decide",
class="analyze",
prompt="Read .arc/current_commit.md for the commit to process.\n\
Examine it with `git show <sha>` in the upstream/ directory.\n\n\
Analyze the semantic changes — what functionality changed, not just syntax.\n\
Decide if this change is relevant to our Go implementation or if it is\n\
Python-specific, docs-only, or not applicable.\n\n\
Write .arc/analysis.md with sections:\n\
- Commit summary\n\
- Semantic analysis\n\
- Decision: PORT or ACKNOWLEDGE (with reasoning)\n\
- Port plan (if porting): concrete tasks with file:line references\n\n\
If decision is ACKNOWLEDGE:\n\
1. Update ledger: `python3 ledger/manage.py update <sha> acknowledged`\n\
2. Commit: `git add ledger/ && git commit -m \"semport: acknowledge <sha> - <reason>\"`\n\
3. Respond with: {\"preferred_next_label\": \"skip\"}\n\n\
If decision is PORT:\n\
Respond with: {\"preferred_next_label\": \"port\"}"
]
// Phase 3: Refine the plan
plan [
label="Finalize Plan",
prompt="Read .arc/analysis.md. Perform a final editorial pass.\n\
Write .arc/plan.md ensuring each task has:\n\
- Concrete file:line references in our Go code\n\
- Clear acceptance criteria\n\
- Directly executable instructions\n\n\
Remove vague language. The plan must be actionable."
]
// Phase 4: Implement the port
implement [
label="Implement Port",
class="hard",
prompt="Follow the plan in .arc/plan.md.\n\
Port the semantic changes to the Go codebase.\n\
Focus on semantic equivalence, not literal translation.\n\
Use Go idioms and respect existing architecture.\n\
Log all changes to .arc/implementation_log.md."
]
// Phase 5: Validate
validate [
label="Validate",
shape=parallelogram,
script="cd go-sdk && go build ./... && go test ./... -v 2>&1 || true"
]
gate [shape=diamond, label="Tests pass?"]
// Phase 6: Fix failures
fix [
label="Analyze & Fix",
class="hard",
max_visits=3,
prompt="Tests or build failed. Read the test output from the prior stage.\n\
Read .arc/plan.md and .arc/implementation_log.md.\n\
Diagnose the root cause, fix the issue, and log the fix."
]
// Phase 7: Update ledger and commit
finalize [
label="Finalize",
prompt="All tests pass. Finalize this port:\n\
1. Update ledger: `python3 ledger/manage.py update <sha> implemented`\n\
2. Commit all changes:\n\
`git add -A && git commit -m \"semport: implement <sha> - <description>\"`\n\
3. Write a brief summary to .arc/implementation_summary.md"
]
// Wiring
start -> fetch
fetch -> analyze [label="Process", condition="preferred_label=process"]
fetch -> exit [label="Done"]
analyze -> plan [label="Port", condition="preferred_label=port"]
analyze -> fetch [label="Skip"]
plan -> implement -> validate -> gate
gate -> finalize [label="Pass", condition="outcome=success"]
gate -> fix [label="Fail"]
fix -> validate
finalize -> fetch
}

View file

@ -0,0 +1,170 @@
digraph BuildSolitaire {
graph [
goal="Build a terminal-based solitaire (Klondike) game in Python",
rankdir=LR,
default_max_retry=3,
retry_target="impl_setup",
fallback_retry_target="impl_game_logic",
model_stylesheet="
* { llm_model: claude-sonnet-4-5; llm_provider: anthropic; }
.hard { llm_model: claude-opus-4-6; llm_provider: anthropic; }
.verify { llm_model: claude-haiku-4-5; llm_provider: anthropic; }
"
]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
// Phase 0: Expand the goal into a detailed spec
expand_spec [
label="Expand Spec",
prompt="Expand the goal into a detailed spec covering:\n\
- Game rules and data structures (Card, Deck, Pile types)\n\
- Terminal rendering approach (curses library)\n\
- Input handling and move validation\n\
- Win/loss detection\n\
- UI layout\n\
- Test strategy\n\n\
Write the spec to spec.md."
]
// Phase 1: Project setup
impl_setup [
label="Setup Project",
prompt="Read spec.md. Create the Python project structure:\n\
pyproject.toml, src/ directory, tests/ directory, main.py stub.\n\
Run: python3 -m py_compile src/*.py"
]
verify_setup [label="Verify Setup", class="verify",
prompt="Verify project setup: check pyproject.toml exists,\n\
source directories exist, and files compile without errors.\n\
Run: python3 -m py_compile src/*.py"
]
check_setup [shape=diamond, label="Setup OK?"]
// Phase 2: Core data structures
impl_data [
label="Data Structures",
prompt="Read spec.md. Implement Card, Deck, and Pile types\n\
with unit tests. Run: python3 -m pytest tests/ -v"
]
verify_data [label="Verify Data", class="verify",
prompt="Verify data structures: build, run tests, check that\n\
Card, Deck, and Pile types are defined and basic operations work.\n\
Run: python3 -m pytest tests/ -v"
]
check_data [shape=diamond, label="Data OK?"]
// Phase 3: Game logic (hardest phase)
impl_logic [
label="Game Logic",
class="hard",
max_retries=2,
prompt="Read spec.md and the data structure files.\n\
Implement Klondike rules: initial deal, move validation,\n\
auto-complete detection, win condition, undo.\n\
Write tests for legal/illegal moves, win detection, edge cases.\n\
Run: python3 -m pytest tests/ -v"
]
verify_logic [label="Verify Logic", class="verify",
prompt="Verify game logic: run all tests, check move validation,\n\
win detection, and undo.\n\
Run: python3 -m pytest tests/ -v"
]
check_logic [shape=diamond, label="Logic OK?"]
// Phase 4: Terminal UI
impl_ui [
label="Terminal UI",
class="hard",
max_retries=2,
prompt="Read spec.md and game logic files.\n\
Implement terminal UI with curses: card rendering (ASCII art),\n\
board layout, keyboard input, move selection, help text.\n\
Run: python3 -m pytest tests/ && python3 -m py_compile src/*.py"
]
verify_ui [label="Verify UI", class="verify",
prompt="Verify terminal UI: build, run tests, check that\n\
renderer and input handler exist, game can be instantiated.\n\
Run: python3 -m pytest tests/"
]
check_ui [shape=diamond, label="UI OK?"]
// Phase 5: Integration
impl_integration [
label="Integrate",
prompt="Wire up main.py to start the game loop.\n\
Connect UI input to game logic. Add game over screen,\n\
help menu, and README with build/run instructions.\n\
Run: python3 -m pytest tests/"
]
verify_integration [label="Verify Integration", class="verify",
prompt="Verify integration: build, run all tests, check README\n\
exists, verify the game starts without errors.\n\
Run: python3 -m pytest tests/"
]
check_integration [shape=diamond, label="Integration OK?"]
// Phase 6: Final review (goal gate)
review [
label="Final Review",
class="hard",
goal_gate=true,
prompt="Read spec.md in full. Review the complete implementation:\n\
- All Klondike rules correctly implemented\n\
- Terminal UI works and is intuitive\n\
- Tests comprehensive and passing\n\
- README clear and accurate\n\n\
Run the full test suite. Write a review to review.md.\n\
Run: python3 -m pytest tests/ -v"
]
check_review [shape=diamond, label="Review OK?"]
// Wiring: linear phases with verify-gate loops
start -> expand_spec -> impl_setup -> verify_setup -> check_setup
check_setup -> impl_data [condition="outcome=success"]
check_setup -> impl_setup [condition="outcome=fail", label="Retry"]
check_setup -> impl_setup
impl_data -> verify_data -> check_data
check_data -> impl_logic [condition="outcome=success"]
check_data -> impl_data [condition="outcome=fail", label="Retry"]
check_data -> impl_data
impl_logic -> verify_logic -> check_logic
check_logic -> impl_ui [condition="outcome=success"]
check_logic -> impl_logic [condition="outcome=fail", label="Retry"]
check_logic -> impl_logic
impl_ui -> verify_ui -> check_ui
check_ui -> impl_integration [condition="outcome=success"]
check_ui -> impl_ui [condition="outcome=fail", label="Retry"]
check_ui -> impl_ui
impl_integration -> verify_integration -> check_integration
check_integration -> review [condition="outcome=success"]
check_integration -> impl_integration [condition="outcome=fail", label="Retry"]
check_integration -> impl_integration
review -> check_review
check_review -> exit [condition="outcome=success"]
check_review -> impl_ui [condition="outcome=fail", label="Fix"]
check_review -> impl_ui
}

View file

@ -0,0 +1,10 @@
digraph Example {
graph [goal="Test default fidelity setting", default_fidelity="summary:medium"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
plan [label="Plan", prompt="Create a plan."]
start -> plan -> exit
}

View file

@ -0,0 +1,11 @@
digraph Example {
graph [goal="Test max_node_visits with per-node max_visits", max_node_visits="20"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
implement [label="Implement", prompt="Implement the feature."]
fix [label="Fix", max_visits=3, prompt="Fix the issues."]
start -> implement -> fix -> exit
}

View file

@ -0,0 +1,12 @@
digraph Example {
graph [goal="Test retry_target attributes", retry_target="plan"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
plan [label="Plan", prompt="Create a plan."]
implement [label="Implement", prompt="Implement the plan."]
verify [label="Verify", goal_gate="true", retry_target="implement", prompt="Verify the implementation."]
start -> plan -> implement -> verify -> exit
}

View file

@ -0,0 +1,10 @@
digraph Example {
graph [goal="Test stall_timeout setting", stall_timeout="300"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
plan [label="Plan", prompt="Create a plan."]
start -> plan -> exit
}

View file

@ -0,0 +1,10 @@
digraph Example {
graph [goal="Test max_node_visits graph setting", max_node_visits="20"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
implement [label="Implement", prompt="Implement the feature."]
start -> implement -> exit
}

View file

@ -0,0 +1,23 @@
// Assembled from docs/execution/interviews.mdx snippet
// Tests human gate with default_choice attribute
digraph DefaultChoice {
graph [goal="Exercise human gate with default choice from the interviews docs page"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
deploy [label="Deploy", prompt="Deploy the changes."]
abort [label="Abort", prompt="Abort the deployment."]
// Line 114: Human gate with human.default_choice
approve [shape=hexagon, label="Approve?", human.default_choice="deploy"]
start -> approve
approve -> deploy [label="[A] Deploy"]
approve -> abort [label="[R] Abort"]
deploy -> exit
abort -> exit
}

View file

@ -0,0 +1,11 @@
digraph CI {
graph [goal="Run tests for $repo_name"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
clone [shape=parallelogram, script="git clone $repo_url repo"]
test [label="Test", prompt="Run the $language test suite."]
start -> clone -> test -> exit
}

View file

@ -0,0 +1,8 @@
version = 1
goal = "Run tests for $repo_name"
graph = "c-i.dot"
[vars]
language = "test-language"
repo_name = "test-repo_name"
repo_url = "test-repo_url"

182
test/docs/extract_dots.py Normal file
View file

@ -0,0 +1,182 @@
#!/usr/bin/env python3
"""Extract full digraph DOT examples from Arc documentation files."""
import os
import re
import sys
from pathlib import Path
DOCS_DIR = Path(__file__).resolve().parent.parent.parent / "docs"
OUTPUT_DIR = Path(__file__).resolve().parent
def extract_dot_blocks(filepath: Path) -> list[dict]:
"""Extract all ```dot code blocks from a file."""
blocks = []
with open(filepath) as f:
lines = f.readlines()
in_dot = False
block_start = 0
block_lines: list[str] = []
title = ""
for i, line in enumerate(lines, 1):
m = re.match(r'\s*```dot(?:\s+title="([^"]*)")?\s*$', line)
if m and not in_dot:
in_dot = True
block_start = i
block_lines = []
title = m.group(1) or ""
elif in_dot and re.match(r"\s*```\s*$", line):
in_dot = False
code = "".join(block_lines)
is_full = "digraph" in code
blocks.append(
{
"line": block_start,
"code": code,
"is_full": is_full,
"title": title,
"num_lines": len(block_lines),
}
)
elif in_dot:
block_lines.append(line)
return blocks
def page_dir(filepath: Path) -> Path:
"""Convert docs/tutorials/hello-world.mdx -> tutorials/hello-world/"""
rel = filepath.relative_to(DOCS_DIR)
return Path(rel.parent) / rel.stem
def derive_filename(block: dict, index: int) -> str:
"""Derive .dot filename from title or digraph name."""
if block["title"]:
name = block["title"]
if not name.endswith(".dot"):
name += ".dot"
return name
# Extract digraph name
m = re.search(r"digraph\s+(\w+)", block["code"])
if m:
# Convert CamelCase to kebab-case
name = re.sub(r"(?<!^)(?=[A-Z])", "-", m.group(1)).lower()
return f"{name}.dot"
return f"workflow-{index:02d}.dot"
def find_prompt_refs(code: str) -> list[str]:
"""Find @path/to/file.md references in DOT code."""
return re.findall(r'@([\w./-]+\.md)', code)
def find_custom_vars(code: str) -> list[str]:
"""Find $variable references that aren't $goal or $$-escaped."""
# Remove $$ escapes first
cleaned = code.replace("$$", "")
vars_found = set(re.findall(r'\$([a-zA-Z_]\w*)', cleaned))
vars_found.discard("goal")
return sorted(vars_found)
def main():
skip_pages = {"changelog/2026-02-27"} # deprecated syntax
extracted = 0
skipped_snippets = 0
prompt_stubs_needed: list[tuple[Path, str]] = []
var_dots_needed: list[tuple[Path, list[str]]] = []
for mdx_path in sorted(DOCS_DIR.rglob("*.mdx")):
blocks = extract_dot_blocks(mdx_path)
if not blocks:
continue
pdir = page_dir(mdx_path)
if str(pdir) in skip_pages:
print(f" SKIP {pdir} (excluded)")
continue
full_blocks = [b for b in blocks if b["is_full"]]
snippet_blocks = [b for b in blocks if not b["is_full"]]
if not full_blocks:
skipped_snippets += len(snippet_blocks)
continue
out_dir = OUTPUT_DIR / pdir
out_dir.mkdir(parents=True, exist_ok=True)
seen: set[str] = set()
for i, block in enumerate(full_blocks):
filename = derive_filename(block, i)
if filename in seen:
base, ext = os.path.splitext(filename)
n = 2
while f"{base}-{n:02d}{ext}" in seen:
n += 1
filename = f"{base}-{n:02d}{ext}"
seen.add(filename)
out_path = out_dir / filename
out_path.write_text(block["code"])
extracted += 1
print(f" WRITE {out_path.relative_to(OUTPUT_DIR)} ({block['num_lines']} lines)")
# Check for prompt refs
for ref in find_prompt_refs(block["code"]):
prompt_stubs_needed.append((out_dir, ref))
# Check for custom vars
custom_vars = find_custom_vars(block["code"])
if custom_vars:
var_dots_needed.append((out_path, custom_vars))
skipped_snippets += len(snippet_blocks)
# Create prompt stubs
created_stubs = set()
for dot_dir, ref in prompt_stubs_needed:
stub_path = dot_dir / ref
if str(stub_path) in created_stubs:
continue
stub_path.parent.mkdir(parents=True, exist_ok=True)
stub_path.write_text("Stub prompt for testing.\n")
created_stubs.add(str(stub_path))
print(f" STUB {stub_path.relative_to(OUTPUT_DIR)}")
# Create run.toml files for variable-using DOTs
for dot_path, vars_list in var_dots_needed:
toml_name = f"run-{dot_path.stem}.toml"
toml_path = dot_path.parent / toml_name
# Extract goal from the DOT if possible
dot_content = dot_path.read_text()
goal_match = re.search(r'goal\s*=\s*"([^"]*)"', dot_content)
goal = goal_match.group(1) if goal_match else "Test workflow"
lines = [
'version = 1',
f'goal = "{goal}"',
f'graph = "{dot_path.name}"',
'',
'[vars]',
]
for v in vars_list:
lines.append(f'{v} = "test-{v}"')
lines.append('')
toml_path.write_text("\n".join(lines))
print(f" TOML {toml_path.relative_to(OUTPUT_DIR)} (vars: {', '.join(vars_list)})")
print(f"\nDone: {extracted} full workflows extracted, {skipped_snippets} snippets skipped")
print(f" {len(created_stubs)} prompt stubs created")
print(f" {len(var_dots_needed)} run.toml configs created")
if __name__ == "__main__":
main()

View file

@ -0,0 +1,16 @@
digraph PlanImplement {
graph [goal="Plan, approve, implement, and simplify a change"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
plan [label="Plan", prompt="Analyze the goal and codebase. Write a step-by-step plan.", reasoning_effort="high"]
approve [shape=hexagon, label="Approve Plan"]
implement [label="Implement", prompt="Read plan.md and implement every step."]
simplify [label="Simplify", prompt="Review the changes for clarity and correctness."]
start -> plan -> approve
approve -> implement [label="[A] Approve"]
approve -> plan [label="[R] Revise"]
implement -> simplify -> exit
}

View file

@ -0,0 +1,48 @@
digraph ImplementFeature {
graph [
goal="Implement a feature with tests and code review",
model_stylesheet="
* { llm_model: claude-haiku-4-5; llm_provider: anthropic; reasoning_effort: low; }
.coding { llm_model: claude-sonnet-4-5; llm_provider: anthropic; reasoning_effort: high; }
#review { llm_model: claude-sonnet-4-5; llm_provider: anthropic; reasoning_effort: high; }
"
]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
// Planning phase
plan [label="Plan", shape=tab, prompt="Create a detailed implementation plan for: $goal"]
// Human approval
approve [shape=hexagon, label="Approve Plan"]
// Implementation (threaded for context continuity)
subgraph cluster_impl {
label = "Implementation"
node [thread_id="impl", fidelity="full"]
implement [label="Implement", class="coding", prompt="Implement the approved plan."]
test [label="Write Tests", class="coding", prompt="Write comprehensive tests."]
}
// Validation
validate [label="Run Tests", shape=parallelogram, script="cargo test 2>&1 || true"]
gate [shape=diamond, label="Tests passing?"]
// Review
review [label="Code Review", shape=tab, prompt="Review the implementation for correctness."]
// Wiring
start -> plan -> approve
approve -> implement [label="[A] Approve"]
approve -> plan [label="[R] Revise"]
implement -> test -> validate -> gate
gate -> review [label="Pass", condition="outcome=success"]
gate -> implement [label="Fix"]
review -> exit
}

View file

@ -0,0 +1,12 @@
digraph MyWorkflow {
graph [goal="Describe the project"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
scan [label="Scan Files", shape=parallelogram, script="find . -type f | head -30"]
analyze [label="Analyze", shape=tab, prompt="Summarize the project structure."]
start -> scan -> analyze -> exit
}

87
test/docs/run_tests.sh Executable file
View file

@ -0,0 +1,87 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
ARC="${ARC:-$REPO_ROOT/target/release/arc}"
PHASE="${1:-validate}"
pass=0
fail=0
total=0
run_one() {
local dot="$1"
local rel
rel="$(realpath --relative-to="$SCRIPT_DIR" "$dot" 2>/dev/null || echo "$dot")"
# Check for companion run.toml (run-<stem>.toml in same dir)
local stem
stem="$(basename "${dot%.dot}")"
local toml
toml="$(dirname "$dot")/run-${stem}.toml"
total=$((total + 1))
case "$PHASE" in
validate)
if "$ARC" validate "$dot" 2>&1; then
echo " PASS $rel"
pass=$((pass + 1))
else
echo " FAIL $rel"
fail=$((fail + 1))
fi
;;
dry-run)
local target="$dot"
[[ -f "$toml" ]] && target="$toml"
if "$ARC" run start "$target" --dry-run --auto-approve 2>&1; then
echo " PASS $rel"
pass=$((pass + 1))
else
echo " FAIL $rel"
fail=$((fail + 1))
fi
;;
haiku)
local target="$dot"
[[ -f "$toml" ]] && target="$toml"
if "$ARC" run start "$target" --model claude-haiku-4-5 --auto-approve 2>&1; then
echo " PASS $rel"
pass=$((pass + 1))
else
echo " FAIL $rel"
fail=$((fail + 1))
fi
;;
full)
local target="$dot"
[[ -f "$toml" ]] && target="$toml"
if "$ARC" run start "$target" --auto-approve 2>&1; then
echo " PASS $rel"
pass=$((pass + 1))
else
echo " FAIL $rel"
fail=$((fail + 1))
fi
;;
*)
echo "Usage: $0 <validate|dry-run|haiku|full>"
exit 1
;;
esac
}
echo "=== Phase: $PHASE ==="
echo ""
while IFS= read -r dot; do
run_one "$dot"
done < <(find "$SCRIPT_DIR" -name '*.dot' | sort)
echo ""
echo "=== Results: $pass passed, $fail failed, $total total ==="
[[ $fail -eq 0 ]]

View file

@ -0,0 +1,16 @@
digraph BranchLoop {
graph [goal="Create a Python script that passes its test suite"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
plan [label="Plan", prompt="Plan a small Python script (fizzbuzz.py) and a test file (test_fizzbuzz.py) using pytest. Describe what you will create.", shape=tab, reasoning_effort="low"]
implement [label="Implement", prompt="Create fizzbuzz.py and test_fizzbuzz.py as planned. Write the files to disk."]
validate [label="Validate", shape=parallelogram, script="python -m pytest test_fizzbuzz.py -v 2>&1 || true"]
gate [shape=diamond, label="Tests passing?"]
start -> plan -> implement -> validate -> gate
gate -> exit [label="Pass", condition="outcome=success"]
gate -> implement [label="Fix"]
}

View file

@ -0,0 +1,37 @@
digraph Ensemble {
graph [
goal="Get independent opinions from multiple providers, then synthesize",
model_stylesheet="
#opus { llm_model: claude-opus-4-6; llm_provider: anthropic; }
#gemini { llm_model: gemini-3.1-pro-preview; llm_provider: gemini; }
#codex { llm_model: gpt-5.3-codex; llm_provider: openai; }
#mercury { llm_model: mercury-2; llm_provider: inception; }
#synth { llm_model: claude-opus-4-6; llm_provider: anthropic; reasoning_effort: high; }
"
]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
fork [label="Fan Out", shape=component, join_policy="wait_all", error_policy="continue"]
opus [label="Opus", prompt="Analyze the goal. Provide your independent assessment, recommendations, and any code or prose needed. Be thorough.", shape=tab]
gemini [label="Gemini", prompt="Analyze the goal. Provide your independent assessment, recommendations, and any code or prose needed. Be thorough.", shape=tab]
codex [label="Codex", prompt="Analyze the goal. Provide your independent assessment, recommendations, and any code or prose needed. Be thorough.", shape=tab]
mercury [label="Mercury", prompt="Analyze the goal. Provide your independent assessment, recommendations, and any code or prose needed. Be thorough.", shape=tab]
merge [label="Merge", shape=tripleoctagon]
synth [label="Synthesize", prompt="You have received independent analyses from four different models (Opus, Gemini, Codex, Mercury). Compare their perspectives: identify consensus, highlight disagreements, and synthesize the strongest ideas into a single coherent recommendation. Note where models agreed and where they diverged.", shape=tab]
start -> fork
fork -> opus
fork -> gemini
fork -> codex
fork -> mercury
opus -> merge
gemini -> merge
codex -> merge
mercury -> merge
merge -> synth -> exit
}

View file

@ -0,0 +1,11 @@
digraph Hello {
graph [goal="Write a haiku about software workflows"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
compose [label="Compose", prompt="Write a haiku (5-7-5 syllable) about software workflows. Output only the haiku, nothing else.", shape=tab, reasoning_effort="low"]
start -> compose -> exit
}

View file

@ -0,0 +1,11 @@
digraph SubAgent {
graph [goal="Research and summarize using a sub-agent"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
research [label="Research", prompt="You have a sub-agent available via the spawn_agent tool. Spawn a sub-agent to list the files in the current directory and read the first 10 lines of any README or CLAUDE.md. Then, using the sub-agent's findings, write a 2-sentence summary of the project."]
start -> research -> exit
}

View file

@ -0,0 +1,11 @@
digraph ToolUse {
graph [goal="Explore the current directory using shell tools"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
explore [label="Explore", prompt="Use bash to list the files in the current directory, then read the first 5 lines of any README or CLAUDE.md file you find. Summarize what this project is about in 2-3 sentences."]
start -> explore -> exit
}

View file

@ -0,0 +1,21 @@
digraph MultiModel {
graph [
goal="Build and review a utility function using multiple models",
model_stylesheet="
* { llm_model: claude-haiku-4-5; llm_provider: anthropic; reasoning_effort: low; }
.coding { llm_model: claude-sonnet-4-5; llm_provider: anthropic; reasoning_effort: high; }
#review { llm_model: claude-sonnet-4-5; llm_provider: anthropic; reasoning_effort: high; }
"
]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
spec [label="Write Spec", prompt="Write a brief spec for a TypeScript string utility module with 3 functions: slugify, truncate, and capitalize. Output the spec only.", shape=tab]
implement [label="Implement", prompt="Implement the TypeScript string utility module from the spec. Write it to string-utils.ts.", class="coding"]
test [label="Write Tests", prompt="Write tests for the string utility module using Bun's test runner. Write to string-utils.test.ts.", class="coding"]
review [label="Code Review", prompt="Review the implementation and tests. Check for edge cases, type safety, and correctness. Provide a brief verdict.", shape=tab]
start -> spec -> implement -> test -> review -> exit
}

View file

@ -0,0 +1,25 @@
digraph Parallel {
graph [goal="Perform a multi-perspective code review"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
fork [label="Fork Analysis", shape=component, join_policy="wait_all", error_policy="continue"]
security [label="Security Audit", prompt="Examine the codebase for security concerns: hardcoded secrets, injection risks, unsafe dependencies. List findings as bullet points.", shape=tab, reasoning_effort="low"]
architecture [label="Architecture Review", prompt="Assess the codebase architecture: separation of concerns, dependency structure, modularity. List findings as bullet points.", shape=tab, reasoning_effort="low"]
quality [label="Code Quality", prompt="Check code quality: naming conventions, dead code, test coverage gaps, error handling. List findings as bullet points.", shape=tab, reasoning_effort="low"]
merge [label="Merge Findings", shape=tripleoctagon]
report [label="Final Report", prompt="Synthesize the security, architecture, and code quality findings into a prioritized summary report with top 5 action items.", shape=tab]
start -> fork
fork -> security
fork -> architecture
fork -> quality
security -> merge
architecture -> merge
quality -> merge
merge -> report -> exit
}

View file

@ -0,0 +1 @@
Stub prompt for testing.

View file

@ -0,0 +1,17 @@
digraph PlanImplement {
graph [goal="Plan, approve, implement, and simplify a change"]
rankdir=LR
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
plan [label="Plan", prompt="Analyze the goal and codebase. Write a clear, step-by-step implementation plan to a Markdown file called plan.md. Include what files will change and why.", reasoning_effort="high"]
approve [shape=hexagon, label="Approve Plan"]
implement [label="Implement", prompt="Read plan.md and implement every step. Make all the code changes described in the plan."]
simplify [label="Simplify", prompt="@docs-internal/prompts/simplify.md"]
start -> plan -> approve
approve -> implement [label="[A] Approve"]
approve -> plan [label="[R] Revise"]
implement -> simplify -> exit
}

View file

@ -0,0 +1,40 @@
// Assembled from docs/workflows/human-in-the-loop.mdx snippets
// Tests human gates: basic, freeform, and default_choice
digraph HitlPatterns {
graph [goal="Exercise human-in-the-loop patterns from the HITL docs page"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
plan [label="Plan", prompt="Create an implementation plan."]
implement [label="Implement", prompt="Implement the plan."]
custom [label="Custom", prompt="Handle custom input."]
// Line 13-17: Basic human gate with accelerators
approve [shape=hexagon, label="Approve Plan"]
// Line 39-43: Freeform input on human gate
review [shape=hexagon, label="Review Changes"]
// Line 53: Default choice on timeout
deploy_gate [shape=hexagon, label="Deploy?", human.default_choice="approve"]
// Wiring
start -> plan -> approve
approve -> implement [label="[A] Approve"]
approve -> plan [label="[R] Revise"]
approve -> exit [label="[S] Skip"]
implement -> review
review -> deploy_gate [label="[A] Approve"]
review -> plan [label="[R] Revise"]
review -> custom [freeform=true]
custom -> deploy_gate
deploy_gate -> exit [label="[A] Approve"]
deploy_gate -> plan [label="[R] Revise"]
}

View file

@ -0,0 +1,69 @@
// Assembled from docs/workflows/stages-and-nodes.mdx snippets
// Tests every node type documented on that page
digraph AllNodeTypes {
graph [goal="Exercise every node type from the stages-and-nodes docs page"]
// Line 23: Start node
start [shape=Mdiamond, label="Start"]
// Line 33: Exit node
exit [shape=Msquare, label="Exit"]
// Line 43: Agent node
implement [label="Implement", prompt="Read plan.md and implement every step."]
// Line 74-81: Subgraph cluster with thread_id
subgraph cluster_impl {
node [fidelity="full", thread_id="impl"]
plan_thread [label="Plan Thread"]
implement_thread [label="Implement Thread"]
review_thread [label="Review Thread"]
}
// Line 90: Prompt (tab) node
spec [label="Write Spec", shape=tab, prompt="Write a brief spec for a string utility module."]
// Line 102: Command (parallelogram) node
test [label="Run Tests", shape=parallelogram, script="echo 'tests passed' 2>&1 || true"]
// Line 117-120: Human (hexagon) node
approve [shape=hexagon, label="Approve Plan"]
// Line 132: Wait (insulator) node
cooldown [label="Wait 1s", shape=insulator, duration="1s"]
// Line 146-149: Conditional (diamond) node
gate [shape=diamond, label="Tests passing?"]
// Line 161-165: Parallel (component) fan-out node
fork [label="Fan Out", shape=component, join_policy="wait_all", error_policy="continue"]
// Line 198-203: Merge (tripleoctagon) fan-in node
merge [label="Merge Results", shape=tripleoctagon]
// Branches for fan-out
security [label="Security", prompt="Check for security issues."]
architecture [label="Architecture", prompt="Check architecture."]
// Wiring
start -> spec -> implement -> test -> gate
gate -> approve [label="Pass", condition="outcome=success"]
gate -> implement [label="Fix"]
approve -> plan_thread [label="[A] Approve"]
approve -> implement [label="[R] Revise"]
plan_thread -> implement_thread -> review_thread -> cooldown
cooldown -> fork
fork -> security
fork -> architecture
security -> merge
architecture -> merge
merge -> exit
}

View file

@ -0,0 +1,20 @@
digraph Example {
graph [
goal="Build and review a utility function",
model_stylesheet="
* { llm_model: claude-haiku-4-5; llm_provider: anthropic; }
.coding { llm_model: claude-sonnet-4-5; reasoning_effort: high; }
#review { llm_model: gemini-3.1-pro-preview; llm_provider: gemini; }
"
]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
spec [label="Write Spec"]
implement [label="Implement", class="coding"]
test [label="Write Tests", class="coding"]
review [label="Code Review"]
start -> spec -> implement -> test -> review -> exit
}

View file

@ -0,0 +1,76 @@
// Assembled from docs/workflows/transitions.mdx snippets
// Tests conditions, human gates, unconditional edges, weights, and agent routing
digraph TransitionPatterns {
graph [goal="Exercise every transition pattern from the transitions docs page"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
// Line 103-114: Agent transition with routing JSON
review [
label="Review",
shape=tab,
prompt="Review the implementation for correctness and \
code quality. If changes are needed, respond with: \
{\"preferred_next_label\": \"fix\"}. If everything \
looks good, respond with: \
{\"preferred_next_label\": \"approve\"}."
]
fix [label="Fix", prompt="Fix the issues found in the review."]
// Line 32-33: Condition on edges
gate [shape=diamond, label="Tests passing?"]
// Line 60: Boolean flag condition (truthiness check)
flag_gate [shape=diamond, label="Flag check"]
// Line 68-79: Compound conditions
deploy_gate [shape=diamond, label="Deploy gate"]
deploy [label="Deploy", prompt="Deploy the changes."]
proceed [label="Proceed", prompt="Proceed with next step."]
retry [label="Retry", prompt="Retry the operation."]
// Line 123-128: Human gate transitions
approve [shape=hexagon, label="Approve Plan"]
plan [label="Plan", prompt="Create a plan."]
skip [label="Skip", prompt="Skip this step."]
// Line 137: Chain syntax (unconditional)
start -> plan -> review
review -> fix [label="Fix"]
review -> gate [label="Approve"]
fix -> review
// Line 32-33: Conditional edges
gate -> exit [label="Pass", condition="outcome=success"]
gate -> flag_gate [label="Fix", condition="outcome=fail"]
gate -> exit [label="Fallback"]
// Line 60: Truthiness check
flag_gate -> deploy_gate [condition="outcome=success"]
flag_gate -> retry
// Line 68-70: Compound condition
deploy_gate -> deploy [condition="outcome=success && context.tests_passed=true"]
// Line 72: OR condition
deploy_gate -> proceed [condition="outcome=success || outcome=partial_success"]
deploy_gate -> exit [label="Fallback"]
deploy -> approve
// Line 123-128: Human gate edges
approve -> exit [label="[A] Approve"]
approve -> plan [label="[R] Revise"]
approve -> skip [label="[S] Skip"]
skip -> exit
proceed -> exit
retry -> review
// Line 152-153: Weight tiebreaking (tested on deploy_gate fallback)
}

View file

@ -0,0 +1,11 @@
digraph Check {
graph [goal="Run tests for $repo_name"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
clone [label="Clone", shape=parallelogram, script="git clone $repo_url repo"]
test [label="Test", prompt="Run the $language test suite in the repo/ directory."]
start -> clone -> test -> exit
}

View file

@ -0,0 +1,10 @@
digraph Example {
graph [goal="Implement the login feature"]
start [shape=Mdiamond, label="Start"]
exit [shape=Msquare, label="Exit"]
plan [label="Plan", prompt="Create a plan for: $goal"]
start -> plan -> exit
}

View file

@ -0,0 +1,8 @@
version = 1
goal = "Run tests for $repo_name"
graph = "check.dot"
[vars]
language = "test-language"
repo_name = "test-repo_name"
repo_url = "test-repo_url"