fabro/lib/components/fabro-workflow/README.md
Bryan Helmkamp 467087998d
Read workflow graphs through Petri's DOT parser
Fabro's own DOT parser was left with one job after create-time compile
moved to Petri: walking a workflow's file references for the bundler and
the workflow-version store, and reading a name, a goal and two counts.
Petri's frontend parses the same language, so the parser goes and a small
crate reads the graph through Petri's.

`fabro-dot` is that crate: `WorkflowGraph::parse` over
`petri_frontend_attractor::dot` and its semantic model (defaults applied,
subgraphs flattened, chains expanded), `references(position)` as the one
walker over the static-reference vocabulary (each reference with its node
and position, file references checked to be template-free), and
`normalize_for_graphviz`, the re-emit of Fabro DOT with dotted attribute
keys quoted, which the SVG render needs. It sits beside `fabro-petri`
rather than inside it because `fabro-petri` depends on `fabro-workflow`,
which depends on `fabro-workflow-version`: the version store cannot reach
`fabro-petri` without a cycle, and the bundler should not pull the engine
in to read a graph.

Deleted: `fabro-graphviz`'s lexer, grammar, AST, semantic pass and
`parse_ast` (1,829 lines, plus the `nom` dependency); the DOT model in
`fabro-types::graph` (`Graph`, `Node`, `Edge`, `AttrValue`,
`shape_to_handler_type`), with only `ReferenceKind` kept, moved to
`fabro_types::reference`; `fabro-template`'s `visit_graph_references` and
the `GraphReference`/`GraphPosition` types, with the template-syntax rule
(`validate_static_reference`) kept there; the pull-request body's DOT
fallback summary, which was unreachable because the DOT source only
travels with the run spec whose display graph the summary already reads.
`fabro-graphviz` is now the render alone, over `fabro-dot`.

Parity: the old and new walkers were run over every `.fabro` and `.dot`
file in the repository (118) before the deletion. Every reference set is
identical. Five files differ in what Petri reads more correctly: a
backslash before a newline inside a quoted string is a line continuation
(four files, inline prompt text only), and a node named only by an edge
counts as a node (`test/edge_only_node.fabro`, 3 nodes rather than 2, so
the `fabro validate` snapshot moves). The checked-in bundles' shapes and
references are pinned by a snapshot in `fabro-dot`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-19 12:23:57 -04:00

29 lines
1.5 KiB
Markdown

# fabro-workflow
Fabro's platform half of a workflow run: what Fabro does around the engine.
Petri compiles and executes every run. `fabro-petri` is the crate that talks
to the engine (`fabro-dot` reads a graph's shape and file references through
Petri's parser), and this crate keeps what Fabro itself owns:
- **`operations`** — creating a run around Petri's admission
(`materialize_admitted_run`, `persist_create_run`), and the other run
operations: fork, rewind, retry, and the timeline they resolve targets on.
The run's display graph (`fabro_types::RunGraph`) is read off the graph
Petri admitted; the DOT the workflow was written in is persisted beside it
as `graph_source`.
- **`workflow_bundle`** — the bundle a run is created from: every workflow
of the version closure with its settings file and its files, and the
`RunDefinition` the run records.
- **`git`**, **`sandbox_git`** — the Git helpers a run's platform effects use,
on the host and inside a sandbox.
- **`pull_request`** — pull request creation for a finished run.
- **`run_tools`**, **`services`** — the run tools an agent session calls.
- **`web_search`** — the built-in web search backend.
- **`run_lookup`** — resolving a run selector to a run.
The run records and status vocabulary are `fabro_types`'. Workflow
diagnostics are Petri's: `fabro validate`, `fabro preflight` and the create
handler report Petri's codes (`attractor.*`, `unsupported.*`, `deprecated.*`,
`info.*`), plus Fabro's `fabro.model.no_ready_provider` when a model node has
no provider ready to run it.