fabro/docs/public/tutorials/parallel-review.mdx
Bryan Helmkamp 283eab181f
refactor(docs): split docs/ into public/ and internal/
Invert the docs convention so the Mintlify-published site lives under
docs/public/ and internal artifacts (strategy docs, brainstorms, plans,
etc.) sit at docs/ root or docs/internal/. Tools that default to writing
into docs/ now land in the catch-all instead of leaking into the
published tree.

- Move Mintlify content (administration/, agents/, api-reference/,
  changelog/, core-concepts/, examples/, execution/, getting-started/,
  human-tools/, integrations/, languages/, reference/, tutorials/,
  workflows/, images/, logo/, docs.json, favicon.svg, dot-highlight.js)
  into docs/public/.
- Collapse docs-internal/ into docs/internal/.
- Update Rust path references (fabro-api/build.rs, fabro-server,
  fabro-dev), TypeScript generator arg, CI path filters, clippy.toml
  reasons, AGENTS.md/CLAUDE.md, and README.md image refs.

Mintlify dashboard project root must be updated to docs/public/ in a
follow-up. .mintignore move/trim and .claude/skills/ updates land in a
separate commit.
2026-04-27 07:21:13 -07:00

104 lines
3.7 KiB
Text

---
title: "Parallel Review"
description: "Fan-out, fan-in, join policies, and merge nodes"
---
This tutorial runs three code review perspectives in parallel — security, architecture, and quality — then merges the results into a single report.
## The workflow
<Frame>
<img src="/images/tutorial-parallel-review.svg" alt="Parallel Review workflow: Start → Fan Out → Security Audit, Architecture Review, Code Quality → Merge → Final Report → Exit" />
</Frame>
```dot title="parallel.fabro"
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"]
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
}
```
```bash
fabro run files-internal/demo/06-parallel.fabro
```
## Fan-out with the fork node
The `fork` node has `shape=component`, making it a **parallel fan-out node**. Every outgoing edge becomes a concurrent branch:
```dot
fork [label="Fork Analysis", shape=component, join_policy="wait_all"]
fork -> security
fork -> architecture
fork -> quality
```
All three branches start at the same time. Each gets an isolated copy of the run context, so branches can't interfere with each other.
### Join policies
The `join_policy` controls when execution can proceed past the merge:
| Policy | Behavior |
|---|---|
| `wait_all` | Wait for every branch to finish (default) |
| `first_success` | Proceed as soon as one branch succeeds |
## Fan-in with the merge node
The `merge` node has `shape=tripleoctagon`, making it a **merge (fan-in) node**. It collects results from all branches into a single context:
```dot
merge [label="Merge Findings", shape=tripleoctagon]
security -> merge
architecture -> merge
quality -> merge
```
The merged branch results are available to downstream nodes. The `report` node receives all three perspectives in its preamble and synthesizes them.
## Concurrency control
By default, Fabro runs up to 4 parallel branches simultaneously. Control this with `max_parallel`:
```dot
fork [shape=component, max_parallel=2]
```
This is useful when branches are resource-intensive (e.g., each running a full agent session with tool calls) and you want to limit concurrency.
## What you've learned
- **Fan-out nodes** (`shape=component`) spawn concurrent branches
- **Merge nodes** (`shape=tripleoctagon`) collect branch results
- **Join policies** control when execution can proceed past the merge
- Each branch gets an isolated copy of the context
## Next
<Card title="Multi-Model Routing" icon="arrow-right" href="/tutorials/multi-model">
Assign different models to different workflow nodes using stylesheets.
</Card>