Update roadmap and standardize on Graphviz terminology

Roadmap: replace placeholder items with current shipped/building/planned
features. Use real dates for sorting instead of manual sortOrder. Fix
UTC timezone rendering for date display.

Terminology: replace all standalone "DOT" references with "Graphviz" or
"Graphviz DOT" across docs, marketing, README, AGENTS.md, and OpenAPI
spec. Changelogs left unchanged as historical records.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-16 20:01:33 -04:00
parent b116c07ea7
commit f416643a48
No known key found for this signature in database
44 changed files with 115 additions and 128 deletions

View file

@ -45,11 +45,11 @@ The OpenAPI spec at `docs/api-reference/fabro-api.yaml` is the source of truth f
## Architecture
Fabro is an AI-powered workflow orchestration platform. Workflows are defined as DOT graphs, where each node is a stage (agent, prompt, command, conditional, human, parallel, etc.) executed by the workflow engine.
Fabro is an AI-powered workflow orchestration platform. Workflows are defined as Graphviz graphs, where each node is a stage (agent, prompt, command, conditional, human, parallel, etc.) executed by the workflow engine.
### Rust crates (`lib/crates/`)
- **fabro-cli** — CLI entry point. Commands: `run`, `exec`, `serve`, `validate`, `parse`, `cp`, `model`, `doctor`, `init`, `install`, `ps`, `system prune`, `llm`
- **fabro-workflows** — Core workflow engine. Parses DOT graphs, runs stages, manages checkpoints/resume, hooks, retros, and human-in-the-loop interactions
- **fabro-workflows** — Core workflow engine. Parses Graphviz graphs, runs stages, manages checkpoints/resume, hooks, retros, and human-in-the-loop interactions
- **fabro-agent** — AI coding agent with tool use (Bash, Read, Write, Edit, Glob, Grep, WebFetch). `Sandbox` trait abstracts execution environments
- **fabro-api** — Axum HTTP server. Routes for runs, sessions, models, completions, usage. SSE event streaming. Demo mode via header
- **fabro-exe** — SSH-based sandbox implementation (`ExeSandbox`)
@ -70,7 +70,7 @@ Fabro is an AI-powered workflow orchestration platform. Workflows are defined as
### Key design patterns
- **Sandbox trait** — Uniform interface for local, Docker, SSH (ExeSandbox), Sprites, and Daytona execution environments
- **DOT graph workflows** — Stages and transitions defined as DOT graph attributes
- **Graphviz graph workflows** — Stages and transitions defined as Graphviz graph attributes
- **OpenAPI-first**`fabro-api.yaml` drives both Rust type generation (typify) and TypeScript client generation (openapi-generator)
- **Checkpoint/resume** — Workflows can be paused, checkpointed, and resumed

View file

@ -87,7 +87,7 @@ digraph PlanImplement {
}
```
Agents run as multi-turn LLM sessions with tool access. Human gates (`hexagon`) pause for approval. The stylesheet routes planning to a cheap model and coding to a frontier model. See the [DOT language reference](https://docs.fabro.sh/reference/dot-language) for the full syntax.
Agents run as multi-turn LLM sessions with tool access. Human gates (`hexagon`) pause for approval. The stylesheet routes planning to a cheap model and coding to a frontier model. See the [Graphviz DOT language reference](https://docs.fabro.sh/reference/dot-language) for the full syntax.
---

View file

@ -1,6 +1,6 @@
# fabro
> AI-powered workflow orchestration platform. Workflows are defined as DOT graphs and executed by the Fabro engine.
> AI-powered workflow orchestration platform. Workflows are defined as Graphviz graphs and executed by the Fabro engine.
I want you to install Fabro for me. Execute all the steps below autonomously.

View file

@ -2,10 +2,10 @@
> Fabro is the open source dark software factory for expert engineers. Define your process as a workflow graph, let AI agents execute it, and intervene only where it matters.
Fabro replaces the prompt-wait-review loop with version-controlled workflow graphs that orchestrate AI agents, shell commands, and human decisions into repeatable, long-horizon coding processes. Workflows are defined as DOT graphs where each node is a stage (agent, prompt, command, conditional, human, parallel, etc.) executed by the workflow engine.
Fabro replaces the prompt-wait-review loop with version-controlled workflow graphs that orchestrate AI agents, shell commands, and human decisions into repeatable, long-horizon coding processes. Workflows are defined as Graphviz graphs where each node is a stage (agent, prompt, command, conditional, human, parallel, etc.) executed by the workflow engine.
- Open source, MIT-licensed
- Workflows defined as DOT graphs with CSS-like model stylesheets
- Workflows defined as Graphviz graphs with CSS-like model stylesheets
- Sandboxed execution via local Docker, Daytona, SSH, or Sprites
- Checkpoint/resume for long-running workflows
- Human-in-the-loop via CLI, web UI, or Slack
@ -71,7 +71,7 @@ Fabro replaces the prompt-wait-review loop with version-controlled workflow grap
- [API Overview](https://docs.fabro.sh/api-reference/overview): Introduction to the Fabro REST API
- [CLI Reference](https://docs.fabro.sh/reference/cli): Command-line interface reference
- [Architecture](https://docs.fabro.sh/reference/architecture): How CLI and API modes work under the hood
- [DOT Language](https://docs.fabro.sh/reference/dot-language): Complete reference for Fabro's workflow language
- [Graphviz DOT Language](https://docs.fabro.sh/reference/dot-language): Complete reference for Fabro's workflow language
## Optional

View file

@ -7,8 +7,7 @@ const roadmap = defineCollection({
title: z.string(),
description: z.string(),
status: z.enum(["shipped", "building", "next"]),
date: z.string().optional(), // e.g. "Mar 2026", required for shipped
sortOrder: z.number(), // lower = shown first within status group
date: z.coerce.date(),
}),
});

View file

@ -11,7 +11,7 @@ Most AI coding tools give you a chat window and hope for the best. Fabro takes a
A chat-based agent is a single loop: prompt, act, repeat. That works for small tasks, but it falls apart when you need structure — when the plan should be approved before implementation begins, when tests must pass before the PR is opened, when a second model should cross-review the first.
Fabro workflows are DOT graphs. Each node is a stage with a specific role: planning, coding, reviewing, testing. Edges define the flow. Human-in-the-loop gates let you intervene where it matters and step back where it doesn't.
Fabro workflows are Graphviz graphs. Each node is a stage with a specific role: planning, coding, reviewing, testing. Edges define the flow. Human-in-the-loop gates let you intervene where it matters and step back where it doesn't.
## Multi-model by design

View file

@ -0,0 +1,4 @@
title: Analytics
description: Cost tracking, success rates, and performance trends across runs. Budgets, alerts, and optimization insights.
status: next
date: 2026-06-01

View file

@ -1,5 +1,4 @@
title: API server & web UI
description: REST API with SSE event streaming and a React dashboard for managing workflows at scale.
status: shipped
date: Feb 2026
sortOrder: 2
title: REST API server mode
description: REST API with SSE event streaming for queuing runs, tracking progress, and managing workflows programmatically.
status: building
date: 2026-04-02

View file

@ -1,5 +1,4 @@
title: Automatic retrospectives
description: Each run generates a retro with cost, duration, files touched, and an LLM-written narrative.
status: shipped
date: Mar 2026
sortOrder: 1
description: Structured post-run analysis with cost, duration, smoothness ratings, friction points, and LLM-generated narratives.
status: building
date: 2026-04-03

View file

@ -1,5 +1,4 @@
title: Cloud sandboxes
description: Isolated VM execution environments with snapshot-based setup, network controls, and SSH access.
description: Isolated cloud VMs with snapshot-based setup, network controls, SSH access, and preview URLs.
status: shipped
date: Jan 2026
sortOrder: 3
date: 2026-03-15

View file

@ -1,5 +1,4 @@
title: Core workflow engine
description: DOT graph parsing with branching, loops, parallel execution, and conditional routing.
title: Workflow engine
description: Graphviz graph parsing with agent, command, and human nodes. Dynamic edge selection with conditions and loops.
status: shipped
date: May 2025
sortOrder: 7
date: 2026-02-15

View file

@ -1,4 +0,0 @@
title: Custom tool plugins
description: Extend agent capabilities with your own tool definitions. Package, share, and version tools independently of workflows.
status: next
sortOrder: 2

View file

@ -1,5 +1,4 @@
title: Git checkpointing & resume
description: Every stage commits to a Git branch with full metadata. Revert or resume from any checkpoint.
title: Git checkpoints
description: Every stage commits code and execution metadata to Git branches. Resume or fork from any checkpoint.
status: shipped
date: Nov 2025
sortOrder: 4
date: 2026-03-01

View file

@ -1,5 +1,4 @@
title: Human-in-the-loop
description: Approval gates pause for human decisions. Steer running agents mid-turn. Interview steps collect input.
title: Interview-based steering
description: Approval gates, multiple choice, and freeform questions. Steer running agents via CLI, web, or Slack.
status: shipped
date: Sep 2025
sortOrder: 5
date: 2026-02-15

View file

@ -1,4 +0,0 @@
title: Metrics & cost dashboards
description: Real-time cost tracking, success rates, and performance trends across all runs. Set budgets, alerts, and optimization targets.
status: next
sortOrder: 3

View file

@ -1,5 +1,4 @@
title: Multi-model routing
description: CSS-like model stylesheets assign providers per stage. Automatic fallback chains across providers.
title: Multi-model agent
description: Multi-turn LLM sessions with bash, file editing, sub-agents, skills, and lifecycle hooks.
status: shipped
date: Jul 2025
sortOrder: 6
date: 2026-02-15

View file

@ -1,4 +0,0 @@
title: Parallel execution scaling
description: Dynamic fan-out with resource-aware scheduling. Run dozens of sandboxes concurrently with automatic load balancing and cost caps.
status: building
sortOrder: 2

View file

@ -1,4 +0,0 @@
title: Self-hosted cloud
description: Deploy Fabro as a managed service in your own infrastructure. Kubernetes-native with horizontal scaling and multi-tenant isolation.
status: next
sortOrder: 4

View file

@ -0,0 +1,4 @@
title: Slack integration
description: Receive notifications, approve human gates, and monitor runs directly from Slack channels.
status: next
date: 2026-06-02

View file

@ -1,4 +0,0 @@
title: Team collaboration
description: Shared workflow runs with role-based access. Assign reviewers, track ownership, and coordinate across teams.
status: next
sortOrder: 1

View file

@ -0,0 +1,4 @@
title: Verifications
description: Deterministic quality gates — test suites, linters, type checkers, and LLM-as-judge — wired into the workflow graph.
status: building
date: 2026-04-01

View file

@ -0,0 +1,4 @@
title: Web app
description: React dashboard for managing workflows, viewing runs, approving human gates, and browsing retrospectives.
status: next
date: 2026-06-03

View file

@ -1,4 +0,0 @@
title: Workflow marketplace
description: Browse, fork, and publish community workflows. One-command install with dependency resolution and version pinning.
status: building
sortOrder: 1

View file

@ -430,7 +430,7 @@ const cssExample = `<span class="text-ice-300">/* All nodes default to fast + ch
</svg>
</div>
<!-- DOT source code -->
<!-- Graphviz source code -->
<div class="rounded-xl border border-navy-800 bg-navy-900/60 p-6 shadow-[0_0_60px_-15px_rgba(103,178,215,0.08)]">
<div class="mb-3 flex items-center gap-2">
<span class="h-3 w-3 rounded-full bg-coral/70"></span>

View file

@ -6,18 +6,21 @@ import PageScripts from "../components/PageScripts.astro";
import { getCollection } from "astro:content";
const allItems = await getCollection("roadmap");
const byStatus = (status: string) =>
const byDate = (status: string) =>
allItems
.filter((item) => item.data.status === status)
.sort((a, b) => a.data.sortOrder - b.data.sortOrder);
.sort((a, b) => b.data.date.getTime() - a.data.date.getTime());
const shipped = byStatus("shipped");
const formatDate = (date: Date) =>
date.toLocaleDateString("en-US", { month: "short", year: "numeric", timeZone: "UTC" });
const shipped = byDate("shipped");
const SHIPPED_VISIBLE = 3;
const shippedVisible = shipped.slice(0, SHIPPED_VISIBLE);
const shippedHidden = shipped.slice(SHIPPED_VISIBLE);
const building = byStatus("building");
const next = byStatus("next");
const building = byDate("building");
const next = byDate("next");
const statusConfig = {
building: {
@ -74,7 +77,7 @@ const statusConfig = {
<div class="mt-6 space-y-0">
{shippedVisible.map((item, i) => (
<div class={`reveal reveal-d${i + 1} flex items-center gap-4 py-3 border-b border-navy-800/40`}>
<span class="shrink-0 w-20 text-xs font-mono text-mint/60">{item.data.date}</span>
<span class="shrink-0 w-20 text-xs font-mono text-mint/60">{item.data.date && formatDate(item.data.date)}</span>
<span class="font-display text-sm font-semibold text-ice-50">{item.data.title}</span>
<span class="shipped-info relative ml-auto shrink-0">
<svg class="h-4 w-4 text-ice-300/30 hover:text-ice-300/60 transition-colors cursor-help" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24">
@ -118,7 +121,7 @@ const statusConfig = {
<div class="space-y-0">
{shippedHidden.map((item) => (
<div class="flex items-center gap-4 py-3 border-b border-navy-800/40">
<span class="shrink-0 w-20 text-xs font-mono text-mint/60">{item.data.date}</span>
<span class="shrink-0 w-20 text-xs font-mono text-mint/60">{item.data.date && formatDate(item.data.date)}</span>
<span class="font-display text-sm font-semibold text-ice-50">{item.data.title}</span>
<span class="shipped-info relative ml-auto shrink-0">
<svg class="h-4 w-4 text-ice-300/30 hover:text-ice-300/60 transition-colors cursor-help" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24">

View file

@ -200,7 +200,7 @@ const langIcons: Record<string, { label: string; path: string }> = {
</Layout>
<style>
/* DOT syntax coloring for workflow code block */
/* Graphviz syntax coloring for workflow code block */
.showcase-dot {
color: var(--color-ice-300);
}

View file

@ -9,7 +9,7 @@ description: "Run Fabro as an API server with a web UI, concurrent runs, and tea
Fabro has two modes: **standalone** and **server**. Standalone mode (`fabro run`) executes a single workflow synchronously in your terminal. Server mode (`fabro serve`) starts an HTTP API that queues runs, streams events, and serves a web UI — so you can close your laptop and let workflows run.
Both modes use the same workflow engine, the same DOT files, and the same sandbox providers. The difference is how you interact with them.
Both modes use the same workflow engine, the same Graphviz files, and the same sandbox providers. The difference is how you interact with them.
## Standalone vs. server mode

View file

@ -11,7 +11,7 @@ The `prompt` attribute on a node defines the task instructions for that stage. I
### Inline prompts
Short prompts can be written directly in the DOT file:
Short prompts can be written directly in the Graphviz file:
```dot
plan [label="Plan", prompt="Analyze the codebase and write a step-by-step plan."]
@ -33,7 +33,7 @@ review [
### External file references
For longer prompts, use the `@` prefix to load from a Markdown file relative to the DOT file:
For longer prompts, use the `@` prefix to load from a Markdown file relative to the Graphviz file:
```dot
plan [label="Plan Implementation", prompt="@prompts/implement/plan.md"]
@ -41,9 +41,9 @@ implement [label="Implement", prompt="@prompts/implement/implement.md"
review [label="Review", prompt="@prompts/implement/review.md"]
```
The `@` prefix tells the engine to read the file contents and use them as the prompt text. This keeps DOT files concise and lets you version prompts as standalone Markdown.
The `@` prefix tells the engine to read the file contents and use them as the prompt text. This keeps Graphviz files concise and lets you version prompts as standalone Markdown.
File references are resolved relative to the DOT file's directory first, then fall back to `~/.fabro/`. This lets you keep shared prompts in your user-level config and reference them from any project.
File references are resolved relative to the Graphviz file's directory first, then fall back to `~/.fabro/`. This lets you keep shared prompts in your user-level config and reference them from any project.
### Variable expansion

View file

@ -128,7 +128,7 @@ paths:
operationId: startRun
tags: [Runs]
summary: Start Run
description: Queues a new workflow run from a DOT graph source. The run is created in `queued` status and will be picked up by the scheduler.
description: Queues a new workflow run from a Graphviz graph source. The run is created in `queued` status and will be picked up by the scheduler.
requestBody:
required: true
content:
@ -143,7 +143,7 @@ paths:
schema:
$ref: "#/components/schemas/RunStatusResponse"
"400":
description: Invalid DOT source
description: Invalid Graphviz source
content:
application/json:
schema:
@ -673,7 +673,7 @@ paths:
operationId: retrieveWorkflow
tags: [Workflows]
summary: Retrieve Workflow
description: Returns the full detail of a workflow including its DOT graph, TOML config, and description.
description: Returns the full detail of a workflow including its Graphviz graph, TOML config, and description.
parameters:
- $ref: "#/components/parameters/WorkflowName"
responses:
@ -1924,14 +1924,14 @@ components:
- paused
StartRunRequest:
description: Request body for starting a new run from a DOT graph source.
description: Request body for starting a new run from a Graphviz graph source.
type: object
required:
- dot_source
properties:
dot_source:
type: string
description: DOT language source defining the workflow graph.
description: Graphviz DOT language source defining the workflow graph.
example: 'digraph { start [shape=Mdiamond]; exit [shape=Msquare]; start -> exit }'
RunStatusResponse:
@ -2509,7 +2509,7 @@ components:
example: 154.0
dot_id:
type: string
description: Node identifier in the DOT graph source.
description: Node identifier in the Graphviz graph source.
example: propose
ToolUse:
@ -2923,7 +2923,7 @@ components:
example: fix_build
filename:
type: string
description: DOT graph filename.
description: Graphviz graph filename.
example: fix_build.fabro
last_run:
$ref: "#/components/schemas/WorkflowLastRun"
@ -2951,7 +2951,7 @@ components:
example: fix_build
filename:
type: string
description: DOT graph filename.
description: Graphviz graph filename.
example: fix_build.fabro
description:
type: string
@ -2961,7 +2961,7 @@ components:
$ref: "#/components/schemas/RunConfiguration"
graph:
type: string
description: DOT language source defining the workflow graph.
description: Graphviz DOT language source defining the workflow graph.
example: "digraph fix_build { rankdir=LR; start -> diagnose -> fix -> validate }"
# ── Verification Detail Schemas ──────────────────────────────────────
@ -4006,7 +4006,7 @@ components:
example: Diagnose and fix CI build failures
graph:
type: string
description: DOT graph filename.
description: Graphviz graph filename.
example: fix_build.fabro
work_dir:
type: string

View file

@ -16,13 +16,13 @@ Fabro has two interfaces, both backed by the same workflow engine:
- **Standalone mode** (`fabro run`) — Run a single workflow synchronously in your terminal. Best for local development, one-off runs, and CI/CD.
- **Server mode** (`fabro serve`) — Start an HTTP API server with a web UI, concurrent run scheduling, and team access. Best for production use and running at scale.
Both modes parse the same DOT files, use the same execution engine, and support the same sandbox providers. See [Server Mode](/administration/deploy-server) for a detailed comparison and setup guide, or [Architecture](/reference/architecture) for internals.
Both modes parse the same Graphviz files, use the same execution engine, and support the same sandbox providers. See [Server Mode](/administration/deploy-server) for a detailed comparison and setup guide, or [Architecture](/reference/architecture) for internals.
## Author time
You provide three inputs:
1. **Workflow graph** (`.fabro`) — A Graphviz DOT file defining nodes, edges, and their attributes. This is the core of what Fabro executes. See [Workflows](/core-concepts/workflows).
1. **Workflow graph** (`.fabro`) — A Graphviz file defining nodes, edges, and their attributes. This is the core of what Fabro executes. See [Workflows](/core-concepts/workflows).
2. **Run config** (`.toml`, optional) — Overrides for the default model, sandbox provider, setup commands, and variables. See [Run Configuration](/execution/run-configuration).
3. **API keys** (`.env`) — Provider credentials for LLM APIs. See [Quick Start](/getting-started/quick-start).
@ -30,7 +30,7 @@ You provide three inputs:
When you run `fabro run`, Fabro:
1. Parses the DOT file into an in-memory graph of nodes and edges
1. Parses the Graphviz file into an in-memory graph of nodes and edges
2. Validates the graph structure (exactly one start node, one exit node, all edges point to valid nodes)
3. Applies the [model stylesheet](/workflows/stylesheets) to resolve which LLM model each node uses
4. Merges run config defaults with CLI flags (CLI flags override the config, config overrides graph defaults)

View file

@ -72,7 +72,7 @@ This routes the spec node to Haiku (the default), implementation to Sonnet, and
## Overriding the default model
Model stylesheets set per-node models inside the workflow graph, but you can also override the default model for an entire run. This is useful for quick experimentation or when you want to swap models without editing the DOT file.
Model stylesheets set per-node models inside the workflow graph, but you can also override the default model for an entire run. This is useful for quick experimentation or when you want to swap models without editing the Graphviz file.
### CLI flags

View file

@ -121,14 +121,14 @@ Or from a [run config TOML](/execution/run-configuration) for repeatable, parame
fabro run run.toml
```
In the web UI, the Workflows page lists all available workflows. Click into a workflow to view its DOT definition, rendered graph diagram, and run history.
In the web UI, the Workflows page lists all available workflows. Click into a workflow to view its Graphviz definition, rendered graph diagram, and run history.
<Frame caption="The Workflows page lists all available workflows with their trigger type and last run time.">
<img src="/images/web/workflows-list.png" alt="Fabro web UI Workflows list showing Fix Build, Implement Feature, Sync Drift, and Expand Product workflows" />
</Frame>
<Frame caption="The workflow detail view shows the DOT definition with syntax highlighting.">
<img src="/images/web/workflow-detail.png" alt="Fabro web UI workflow detail showing the DOT source for Fix Build" />
<Frame caption="The workflow detail view shows the Graphviz definition with syntax highlighting.">
<img src="/images/web/workflow-detail.png" alt="Fabro web UI workflow detail showing the Graphviz source for Fix Build" />
</Frame>
<Frame caption="The Diagram tab renders the workflow graph visually, showing nodes, edges, and conditions.">

View file

@ -44,7 +44,7 @@ The `Fabro-Checkpoint` trailer links each run branch commit to its metadata bran
The metadata branch (`fabro/meta/{run_id}`) is an orphan branch that stores structured run data using Git's object storage directly (via `git2`). It is initialized at run start with:
- **`manifest.json`** — Run metadata: run ID, graph name, node/edge counts, base SHA, and branch name
- **`graph.fabro`** — The workflow DOT source as it was parsed
- **`graph.fabro`** — The workflow Graphviz source as it was parsed
After each node, the metadata branch is updated with:
@ -111,7 +111,7 @@ Resume from the Git branches created during a previous run:
fabro run --run-branch fabro/run/01JKXYZ...
```
This reads the checkpoint, manifest, and graph DOT from the metadata branch (`fabro/meta/01JKXYZ...`), re-attaches a worktree to the existing run branch, and resumes execution. No workflow file argument is needed — everything is recovered from Git.
This reads the checkpoint, manifest, and Graphviz graph from the metadata branch (`fabro/meta/01JKXYZ...`), re-attaches a worktree to the existing run branch, and resumes execution. No workflow file argument is needed — everything is recovered from Git.
<Accordion title="What happens during resume">
1. Fabro reads `checkpoint.json` from the metadata branch

View file

@ -22,10 +22,10 @@ goal = "Implement the login feature"
| Field | Required | Description |
|---|---|---|
| `version` | Yes | Config format version. Must be `1`. |
| `graph` | Yes | Path to the DOT workflow file, resolved relative to the TOML file's directory. |
| `goal` | No | What the workflow should accomplish. Passed to agents and used in retrospectives. Can also be provided via `--goal` CLI flag or DOT graph `goal` attribute. |
| `graph` | Yes | Path to the Graphviz workflow file, resolved relative to the TOML file's directory. |
| `goal` | No | What the workflow should accomplish. Passed to agents and used in retrospectives. Can also be provided via `--goal` CLI flag or Graphviz graph `goal` attribute. |
Goal precedence: CLI `--goal` > TOML `goal` > DOT graph attribute.
Goal precedence: CLI `--goal` > TOML `goal` > Graphviz graph attribute.
## Full example
@ -275,7 +275,7 @@ Exclude globs from `server.toml` defaults and the run config are merged (union,
### `[vars]`
Define variables that are expanded into the DOT source before the graph is parsed. See [Variables](/workflows/variables) for the full reference.
Define variables that are expanded into the Graphviz source before the graph is parsed. See [Variables](/workflows/variables) for the full reference.
```toml title="run.toml"
[vars]
@ -284,7 +284,7 @@ repo_url = "https://github.com/fabro-sh/fabro"
language = "rust"
```
Variables can be used anywhere in the DOT file with `$name` syntax:
Variables can be used anywhere in the Graphviz file with `$name` syntax:
```dot title="c-i.fabro"
digraph CI {
@ -294,7 +294,7 @@ digraph CI {
}
```
If a `$variable` in the DOT file has no matching entry in `[vars]`, Fabro raises an error immediately. A bare `$` not followed by an identifier (e.g. `costs $5`) is left as-is.
If a `$variable` in the Graphviz file has no matching entry in `[vars]`, Fabro raises an error immediately. A bare `$` not followed by an identifier (e.g. `costs $5`) is left as-is.
### `[assets]`
@ -430,11 +430,11 @@ Settings can come from multiple sources. Fabro resolves them in this order (firs
| CLI flags (`--model`, `--provider`, `--sandbox`) | |
| Project defaults (`fabro.toml`) | |
| Server defaults (`~/.fabro/server.toml`) | |
| DOT graph attributes (`default_model`, `default_provider`) | |
| Graphviz graph attributes (`default_model`, `default_provider`) | |
| Built-in defaults | Lowest |
<Note>
For model and provider specifically, the precedence is: CLI flags > TOML config > project defaults > server defaults > DOT graph attributes > built-in defaults. Stylesheet rules on individual nodes always take priority over all of these.
For model and provider specifically, the precedence is: CLI flags > TOML config > project defaults > server defaults > Graphviz graph attributes > built-in defaults. Stylesheet rules on individual nodes always take priority over all of these.
</Note>
### Project defaults (`fabro.toml`)
@ -484,9 +484,9 @@ The same merge behavior applies to Daytona labels. All other fields use simple "
Fabro validates the run config when it loads:
- **Version check** — Only `version = 1` is accepted. Other versions are rejected immediately.
- **Required fields** — `version` and `graph` are required. `goal` is optional (can be provided via `--goal` or DOT graph attribute).
- **Required fields** — `version` and `graph` are required. `goal` is optional (can be provided via `--goal` or Graphviz graph attribute).
- **Unknown fields** — Extra fields not listed above are rejected (`deny_unknown_fields`).
- **Variable check** — Any `$variable` in the DOT file without a matching `[vars]` entry produces an error.
- **Variable check** — Any `$variable` in the Graphviz file without a matching `[vars]` entry produces an error.
Use `--preflight` to validate a run config without executing it:

View file

@ -66,6 +66,6 @@ fabro run hello
Understand the problems Fabro solves.
</Card>
<Card title="Workflows" icon="diagram-project" href="/core-concepts/workflows">
Learn how to define workflow graphs in DOT.
Learn how to define workflow graphs in Graphviz.
</Card>
</Columns>

View file

@ -19,11 +19,11 @@ AI coding agents have transformed software engineering productivity, but the sur
## How Fabro solves this
Fabro gives you a deterministic harness around non-deterministic AI. You define **workflow graphs** in DOT files that specify exactly what happens, in what order, with which models, and where humans weigh in. Fabro handles orchestration, parallelism, model routing, verification, and observability.
Fabro gives you a deterministic harness around non-deterministic AI. You define **workflow graphs** in Graphviz files that specify exactly what happens, in what order, with which models, and where humans weigh in. Fabro handles orchestration, parallelism, model routing, verification, and observability.
<Columns cols={2}>
<Card title="Version-controlled workflows" icon="diagram-project">
Define workflows as code in Graphviz DOT. Nodes are agents, shell commands, or human input gates. Fan out, loop, branch, and resume — all traceable and repeatable.
Define workflows as code in Graphviz. Nodes are agents, shell commands, or human input gates. Fan out, loop, branch, and resume — all traceable and repeatable.
</Card>
<Card title="Multi-model orchestration" icon="microchip">
Route tasks to the right model using CSS-like stylesheets. Cross-critique with fresh eyes, delegate simple tasks to fast models, and fail over automatically when providers go down.
@ -46,7 +46,7 @@ Fabro gives you a deterministic harness around non-deterministic AI. You define
## What a workflow looks like
Workflows are defined in Graphviz DOT, a simple graph description language. Here's a plan-approve-implement workflow and its DOT source:
Workflows are defined in Graphviz, a simple graph description language. Here's a plan-approve-implement workflow and its Graphviz source:
<Frame>
<img src="/images/plan-implement-workflow.svg" alt="Plan-Implement workflow graph" />

View file

@ -7,7 +7,7 @@ Fabro provides two interfaces — a CLI for local development and an HTTP API fo
## Shared engine
At the core of both modes is the `WorkflowRunEngine`. It parses the DOT graph, walks nodes, dispatches to handlers (agent, command, human, etc.), selects edges, and checkpoints after each stage. The engine is parameterized by an `Interviewer` trait that controls how human-in-the-loop questions are presented — terminal prompts in CLI mode, HTTP request/response in API mode.
At the core of both modes is the `WorkflowRunEngine`. It parses the Graphviz graph, walks nodes, dispatches to handlers (agent, command, human, etc.), selects edges, and checkpoints after each stage. The engine is parameterized by an `Interviewer` trait that controls how human-in-the-loop questions are presented — terminal prompts in CLI mode, HTTP request/response in API mode.
## CLI mode
@ -46,7 +46,7 @@ Key server config options:
### Run lifecycle
1. **Submit** — `POST /runs` with a DOT workflow source. The run is created with status `Queued` and the response returns immediately with the run ID.
1. **Submit** — `POST /runs` with a Graphviz workflow source. The run is created with status `Queued` and the response returns immediately with the run ID.
2. **Schedule** — A background scheduler promotes queued runs to `Running` in FIFO order, up to the concurrency limit.
3. **Execute** — The engine walks the graph, streaming events to all subscribers.
4. **Complete** — The run transitions to `Completed`, `Failed`, or `Cancelled`.
@ -82,7 +82,7 @@ cd apps/fabro-web && bun run dev # Web UI on port 5173
The UI provides:
- **Run board** — List and monitor all runs
- **Run detail** — Real-time stage progress, event stream, diffs, usage stats
- **Start new run** — Submit a DOT workflow from the browser
- **Start new run** — Submit a Graphviz workflow from the browser
- **Human-in-the-loop** — Answer agent questions through the web interface
- **Sessions** — Interactive chat interface (coming soon)
- **Insights** — SQL-based analysis across runs via DuckDB

View file

@ -361,7 +361,7 @@ fabro system df -v
## `fabro graph`
Render a workflow DOT graph as SVG or PNG. Requires [Graphviz](https://graphviz.org) (`dot`) to be installed.
Render a workflow graph as SVG or PNG. Requires [Graphviz](https://graphviz.org) (`dot`) to be installed.
```bash
fabro graph workflow.fabro
@ -374,11 +374,11 @@ fabro graph run.toml --format svg
| `<WORKFLOW>` | Path to a `.fabro` workflow file or `.toml` run config (required) |
| `--format <FORMAT>` | Output format: `svg` (default) or `png` |
| `-o, --output <FILE>` | Output file path. Defaults to stdout. |
| `-d, --direction <DIR>` | Graph direction: `lr` or `tb`. If omitted, uses the DOT file's own `rankdir`. |
| `-d, --direction <DIR>` | Graph direction: `lr` or `tb`. If omitted, uses the Graphviz file's own `rankdir`. |
## `fabro skill install`
Install the built-in `fabro-create-workflow` skill for AI assistants (Claude Code, Codex). The skill teaches AI assistants Fabro's DOT syntax, node types, and run configuration format.
Install the built-in `fabro-create-workflow` skill for AI assistants (Claude Code, Codex). The skill teaches AI assistants Fabro's Graphviz syntax, node types, and run configuration format.
```bash
# Install into the current project (.claude/skills/ or .agents/skills/)
@ -522,7 +522,7 @@ fabro validate run.toml
## `fabro parse`
Parse a DOT file and print its AST as JSON. Useful for debugging workflow definitions.
Parse a Graphviz file and print its AST as JSON. Useful for debugging workflow definitions.
```bash
fabro parse workflow.fabro

View file

@ -1,6 +1,6 @@
---
title: "Fabro Language"
description: "Complete reference for Fabro's DOT workflow language"
description: "Complete reference for Fabro's Graphviz workflow language"
---
Fabro workflows are written in a subset of the [Graphviz DOT language](https://graphviz.org/doc/info/lang.html) with extensions for agent orchestration. This page is the complete syntax reference. For conceptual introductions, see [Workflows](/core-concepts/workflows) and [Nodes & Stages](/workflows/stages-and-nodes).
@ -323,7 +323,7 @@ shared [prompt="@~/shared-prompts/review.md"]
parent [prompt="@../common/plan.md"]
```
Untracked `@file` references (files not committed to git) are inlined into the DOT source at prepare time, so they work even inside sandboxes that only see the git tree.
Untracked `@file` references (files not committed to git) are inlined into the Graphviz source at prepare time, so they work even inside sandboxes that only see the git tree.
Fabro validates `@file` references at parse time — if the referenced file does not exist, validation fails with a clear error pointing to the bad reference.

View file

@ -20,7 +20,7 @@ The naming format is `YYYYMMDD-{run_id}`, where `run_id` is the ULID assigned to
| File | Format | When written | Description |
|---|---|---|---|
| `manifest.json` | JSON | Run start | Run metadata — `run_id`, `workflow_name`, `goal`, `start_time`, `node_count`, `edge_count`, `run_branch`, `base_sha`, `labels` |
| `graph.fabro` | DOT | Run start | Copy of the workflow graph |
| `graph.fabro` | Graphviz | Run start | Copy of the workflow graph |
| `run.pid` | Text | Run start | Process ID of the running CLI process. Presence indicates the run is active; an orphaned file indicates a crash. |
| `run.toml` | TOML | Run start | Copy of the original workflow file (only when the workflow is defined in TOML) |
| `progress.jsonl` | JSONL | Continuous | Event stream — one JSON object per line for every significant event (stage starts, completions, tool calls, retries, etc.). See [Observability](/execution/observability) for the full event catalog. |

View file

@ -83,7 +83,7 @@ The `simplify` node uses `@files-internal/prompts/simplify.md` instead of an inl
simplify [label="Simplify", prompt="@files-internal/prompts/simplify.md"]
```
The `@` prefix tells Fabro to load the prompt from a Markdown file, resolved relative to the DOT file's location. This keeps DOT files concise and lets you version prompts as standalone files. See [Prompts](/agents/prompts) for details.
The `@` prefix tells Fabro to load the prompt from a Markdown file, resolved relative to the Graphviz file's location. This keeps Graphviz files concise and lets you version prompts as standalone files. See [Prompts](/agents/prompts) for details.
## Context flow between nodes
@ -100,7 +100,7 @@ The agent reads `plan.md` (as instructed by its prompt), but the preamble gives
- **Human gates** (`shape=hexagon`) pause for human input with edge labels as options
- **Revision loops** are just edges that point back to earlier nodes
- **Prompt file references** (`@path/to/file.md`) keep DOT files clean
- **Prompt file references** (`@path/to/file.md`) keep Graphviz files clean
- **`reasoning_effort`** controls how hard the model thinks
- Nodes receive preambles summarizing prior stages

View file

@ -81,7 +81,7 @@ The child workflow runs through its own start → implement → validate → gat
|---|---|
| `stack.child_workflow` | Path to the child workflow file (resolved relative to the parent). Preferred. |
| `stack.child_dotfile` | Backward-compatible alias for `stack.child_workflow`. |
| `stack.child_dot_source` | Inline child DOT source (alternative to `child_workflow`) |
| `stack.child_dot_source` | Inline child Graphviz source (alternative to `child_workflow`) |
| `manager.max_cycles` | Safety limit on poll cycles before the child is cancelled (default: 1000) |
| `manager.poll_interval` | How often to check for completion or stop conditions (default: `45s`) |
| `manager.stop_condition` | Condition expression that, when true, cancels the child early |
@ -134,7 +134,7 @@ For simpler cases, just add more nodes to a single workflow. Sub-workflows add a
<Card title="Nodes & Stages" icon="shapes" href="/workflows/stages-and-nodes">
Complete reference for all node types.
</Card>
<Card title="DOT Language" icon="code" href="/reference/dot-language">
<Card title="Graphviz Language" icon="code" href="/reference/dot-language">
Full syntax reference including sub-workflow attributes.
</Card>
<Card title="Context" icon="database" href="/execution/context">

View file

@ -5,7 +5,7 @@ description: "All node types and how they become stages at runtime"
## Nodes vs. stages
A **node** is a step defined in the DOT file at author time. A **stage** is the runtime execution of a node. In a simple linear workflow, each node runs once and produces one stage. But when a workflow loops — for example, an implement-test-fix cycle — the same node can produce multiple stages within a single run.
A **node** is a step defined in the Graphviz file at author time. A **stage** is the runtime execution of a node. In a simple linear workflow, each node runs once and produces one stage. But when a workflow loops — for example, an implement-test-fix cycle — the same node can produce multiple stages within a single run.
This distinction matters for observability and debugging: the workflow graph shows nodes, but the run timeline shows stages. Each stage records its own inputs, outputs, duration, and token usage.

View file

@ -3,7 +3,7 @@ title: "Variables"
description: "Using variables in workflows"
---
Fabro supports `$variable` placeholders that let you parameterize workflows without editing the DOT file.
Fabro supports `$variable` placeholders that let you parameterize workflows without editing the Graphviz file.
## Run config variables
@ -20,7 +20,7 @@ repo_url = "https://github.com/fabro-sh/fabro"
language = "rust"
```
These variables are expanded into the DOT source **before** the graph is parsed. You can use `$variable` anywhere in the DOT file — goals, prompts, labels, scripts, or any other attribute:
These variables are expanded into the Graphviz source **before** the graph is parsed. You can use `$variable` anywhere in the Graphviz file — goals, prompts, labels, scripts, or any other attribute:
```dot title="check.fabro"
digraph Check {
@ -40,7 +40,7 @@ When launched with `fabro run run.toml`, Fabro replaces `$repo_name`, `$repo_url
### Undefined variables
If a `$variable` in the DOT file has no matching entry in `[vars]`, Fabro raises an error. This catches typos early — a misspelled `$langauge` fails immediately rather than passing a literal `$langauge` to the LLM.
If a `$variable` in the Graphviz file has no matching entry in `[vars]`, Fabro raises an error. This catches typos early — a misspelled `$langauge` fails immediately rather than passing a literal `$langauge` to the LLM.
### Escaping `$`