Saphan StudioDocs
Getting started

Roles and the working rhythm

Master, executor, review, owner - and the channel files that are the wire between them.

Saphan instantiates a deliberate division of labour. The names are conventions, but the boundaries are enforced by the tooling:

RoleDoesNever does
MasterPlans, writes the dispatch material, creates worktrees, adjudicates what comes back from gates, keeps the board currentImplements, reviews its own dispatches, merges
ExecutorImplements the assigned scope inside its master-spawned worktree; commits locally; returns a structured resultCreates or removes worktrees; pushes; merges; writes outside its worktree
ReviewIndependently, adversarially evaluates an executor's returnWrites code; advances the stream itself
Owner (human)Every gate decision, every merge, every push, everything irreversible

The rhythm per stream:

ORDER → dispatch → STOP-1 (plan) → human gate → implementation
      → STOP-2 (proof) → review → human gate → merge (human) → observed → teardown

A fast path may skip the plan stage for small work; the pre-merge human gate is never skipped.

The review lane, specifically

Review in Saphan is not a thumbs-up emoji. It is a separate, adversarial role with a narrow, enforced footprint:

  • The reviewer reads the executor's return against the order — the scope, the test plan, the DoD — and produces a recommendation with concrete reasons: accept · accept-with-conditions · reject.
  • The reviewer writes exactly one file — its status artifact in the reviewed worktree — and nothing else. A reviewer that starts "fixing things" has left its role.
  • Branch diffs are read against the merge-base (three-dot), never two-dot — a moved base otherwise shows phantom reverts, and reviewers have rejected perfectly good work over phantoms.
  • Green is not correctness. A test suite that passes proves determinism, not truth — the proof at STOP-2 must show the actual artifact matching the claim (the diff, the golden, the output itself), never infer "fixed" from a green run. Correctness is an independent eye on the artifact.
  • The verdict is recorded as judgment, never the decision: the human's gate is a separate recorded act, and merge refuses unless the recorded review gate says accept or accept-with-conditions. Conditions are not a refusal — they are more work owed, honestly recorded.

The wire between roles: channel files

Master and executor do not talk through chat memory — and there is no lateral channel between agents at all: no master-to-master, no executor-to-executor, nothing off the record (Enterprise §6). They talk through channel files in the stream's worktree — gitignored, never committed, so the code history stays clean while the fleet stays observable; the engine ingests them into the record:

  • _MASTER_ORDER.md — written by the master, read by the executor: the worktree's current order (absolute worktree path, branch, base, one-line task, where the full order lives) and a mandatory REASON field — an executor receiving a new order mid-stream must be able to tell why (fix after review? scope change? continuation?).
  • _EXEC_STATUS.md — written by the executor, read by the master and ingested by the engine. Updated at every meaningful transition, and load-bearing at both ends of a run:
    • The started-ack is the executor's first act — before recon, before code. The fleet is never blind between kickoff and the first voluntary update; a stream whose tab never started must be distinguishable from one that is quietly working.
    • state: blocked is a first-class state — the executor stops to ask, and names the exact blocker or question. Waiting on the owner is honest fleet state, visible in fleet show, not dead air.
    • state: stop-2-ready is the close gate. Writing the file and verifying it on disk is a precondition of the executor's close signal; a "done" living only in a chat transcript is an incomplete return, by rule. The master verifies the file exists before accepting any STOP-2 — terminal actions are gated on durable records, not on messages.
  • _REVIEW_STATUS.md — the review role's one permitted file, in the reviewed stream's worktree: spawned when the review starts, then the verdict and where the full review return lives.

Returns are identified by their identity line — stream + head commit + close line — so a duplicated paste is acknowledged rather than re-gated, and a stale one is flagged rather than executed.

On this page