From a command to a record
cmd/agister, wires every one. Core knows no settings file, no git
and no runtime: it is given a workflow of items and a caller, and tells what
happens to an events port.A run starts from a request: a workflow with its params, or a process on
an agent, with --continue or --reuse naming an
earlier run. Resolve turns it into definitions or a refusal. The composition
plans every step, those in branch arms a run may not take included, and lists
what this Agister does not run yet. A refusal of either kind ends the command
before anything runs and before any record.
agister check shares that list, so it refuses
exactly what a run would.
What a workflow's items do
max at a time; one that fails does not stop the next; at least one must completea list, in declared order, of each one's status, class and outputif holds, else the arm with nonethe arm's output mappingnext over its state, then reads until; again until it holds or max passes have run; never reads until before the first pass{"state", "stopped", "passes"}: the last state, until or max, and how many passes ran<item>/<step>, with the pass where the item is in a repeatits outputs; one output named output is given wholeItems sit anywhere an item may: in the workflow's steps, an arm, a
repeat's body; a parallel holds steps and workflows. A condition is pure: it
reads params, inputs, a repeat's state and the outputs of items already ended,
with equals, present, all,
any, and, or and not. A
number never equals a string, and params and inputs are strings. A repeat's
body sees the state of the repeats around it, its own over theirs; a name
next does not bind keeps its value.
<step>/<pass>, outer passes first where repeats
nest. The call, its record entry, its progress line, its events and reuse
all use that name; its plan is found by the name it is declared by.<item>/<step> before anything runs.A call
A call is one step executed. core/admit holds its worktree
first, as a reader or a writer, checks a pinned revision and a clean worktree
where the process asks, and keeps the call to its limits and the day's budget.
core/call then makes turns on the runtime through its wrapper and
the supervisor, which starts the program, keeps the ends of its output and
ends its whole group.
- capacityA turn at capacity is made again, after 30 s, 1, 3
and 5 minutes, each telling the session to go on; then the call starts fresh
on its agent's
fallback, if it names one. - staleA turn that goes stale is followed by a recovery turn in its session, where the process allows a resume.
- sessionA call may continue an earlier step's session, by a binding; it goes on from where that session's latest call left the worktree.
- costEach turn counts its own cost, claude-code's as reported, codex's priced through ccusage, against the process's limit and the daily budget.
At its end a call keeps the HEAD and content it left, and, where it pinned a revision, its changes as a patch.
What a run leaves
Each run is a folder under ~/.agister/runs, named by its id:
its start's UTC time and six random hex characters.
<run id>/<step>, with its process, agent,
inputs, permission plan, environment, definition files by digest, HEAD and
content, cost and result. Under children, each child run, as
<run id>/<item>, with its workflow, params, inputs
and their identities, status and output. Written whole as each call ends;
lost until the run ends.Progress goes to stderr as it happens: a line per step started and ended,
· <branch>: took <arm>,
· <repeat>: ended pass <n> and
· <repeat>: stopped <why> after <n> passes. The
result, on stdout, is JSON. agister runs export copies a run
out.
Running again
What Agister does not do
Agister runs what settings define and records it. Committing, pushing,
deciding what a review's findings mean and asking the owner stay with whoever
calls it. It does not yet run a branch or repeat inside a parallel, or a turn
on pi; check and run refuse them alike.