Write a graph
This page settles the shape a new graph needs, where it goes, and how a run picks it up.
The shape
A graph is the ordered set of nodes a run executes, with a DAG of real dependencies between the tasks it schedules — see Graphs for what a node and an edge mean. A new graph is a new course, not a new node: writing a new node type (a new kind of review, a new kind of validation) is a different, larger change than composing existing node types into a new order.
In code, a graph is a module with a function run(args, runner) -> dict.
It reads its cartridge and date from args, asks the runner for roles
and tiers, never skills or models, and returns proposals as data. It
writes nothing. src/graphs/docs/GRAPH-CONTRACT.md lists the rules,
and tests/test_portability.py in src/graphs enforces them.
Where it goes
A graph is a module under src/graphs/graphs/delivery/ (work that
produces work) or src/graphs/graphs/ops/ (keeping a running system
honest). The module opens with a docstring that names the node chain
right under its title line, such as decompose -> adversary -> emit; the
diagram on the
graph's docs page is generated from it by python -m harness.graphdoc.
The module declares GRAPH_NAME and a module-level SPEC, a
graphs._spec.GraphSpec naming the subcommand, the run function, a
one-line summary and the Needs that become command-line flags.
Graphs are platform code. They live in the coxswain repository, not in a team cartridge, and a new one lands as a pull request there.
How a run picks it up
Discovery is automatic. harness/registry.py imports every module under
graphs/ and collects each SPEC, so a new module is a new
shell.py <subcommand> with no dispatch table to edit. Two names
clashing is an error, not a silent shadow.
Reaching it from cox is not automatic:
cox route launchstarts a fixed set:epic,decompose,rescue,cosandsweep.- The coxswain dispatch graph can select only graphs its driver,
harness/cos.py, knows how to build arguments for (_KNOWN_GRAPHS). A new graph joins dispatch by extending that list and its argument builder.
What to check before writing a new one
A new graph is worth writing when an existing one's phases and edges don't fit the work — not when a single task in the middle needs different handling. A task that needs a different review tier or a different budget is a Policy change; a task that needs different nodes entirely, in a different order, is a new graph.