skip to content

Journal events

Every event a run raises, and the name each record carries on the wire where the run journal or the headless stream writes one.

The event vocabulary

Journal event vocabulary — 3 sets exported from src/engine/reference_vocabulary.rs

Run events

29 values from src/domain/mod.rs

The engine's event stream, as Gantry's two JSONL surfaces write it: the durable run journal at `.gantry/<plan>/history.jsonl`, which cold readers and `gantry replay` read, and the headless `--json` stream a watcher reads live. A record's token is its `t` field. The two surfaces carry different subsets, so a token says only that some surface writes the event and each value says which. Journals written before the task rename carry record names nothing writes any more — `chunk_started`, `chunk_finished`, `milestone_chunks_planned`, `roster_updated` — because a journal is git-tracked and travels with a merge: the decoder still reads them, into the same shape a record written today carries. A value with no token at all is an event that reaches a front-end in process and is written to neither surface — a reader of a file will never meet it. The rows carry names and meanings, not payload fields: a record's fields are written by hand at the encoder's call site, one shape per event, and a list of them transcribed here would be a second copy nothing keeps true.

value wire name what it means
run_started run_started The run began: the plan's name and the generated project title and description. It carries no task list — what the run means to build arrives on its own record, once per repetition, at whatever depth that repetition sits. The journal does not keep it; a cold reader rebuilds it from the run's own record on disk, so it is a record only the headless stream carries, and the attach endpoint and resolved configuration the event holds in process are encoded on neither surface.
task_list_announced task_list_announced A task list was announced: the id and title of each task, under the task path of the repetition the list belongs to. `preview = true` marks a display-only preview written when the directory becomes known; it is not the run's live roster, task-list directory state, inserted-task journal, ledger skip, or completion state. A repetition's real enumeration writes `preview = false`, which older records also decode as, and announces what it found before every iteration. Every later real binding in that frame announces it again, because a title a step writes after the directory binds would otherwise never reach the reader. A task the ledger already records as done is left out of a real enumeration, so a resumed run announces the shorter list it has left to build. A reader reconciles the children it holds under that path to this list, keeping what it already knows about an id that survives, so the same list announced twice changes nothing.
task_started task_started A task became the active focus, named by its whole path from the run's root. It attributes nothing by itself: every stage record carries the task path it belongs to, and a run-level stage carries none.
stage_started stage_started One stage of the pipeline began — an agent stage, or a mechanical one such as the gate or the merge. It opens a card: which stage, on which task, under which harness and model where an agent is about to run, and where its log is being written.
stage_progress A heartbeat for the stage running right now: how long it has been going and what it is doing. It is never written to either JSONL surface, so a reader of a file sees a stage start and then finish with nothing in between.
stage_finished stage_finished The stage closed, carrying the stage outcome it closed with and a one-line summary of what it did. For an agent stage it also carries what the work cost: tokens, turns and duration. For a gate stage it may carry parsed test coverage from the gate log.
agent_retrying agent_retrying An agent stage hit a transient failure — an overloaded API, a rate limit, a usage window that has not reopened yet — and is waiting before its next attempt. The run is waiting rather than hung and the task's status has not changed; the stage still finishes normally if a later attempt succeeds.
gate_lock_waiting gate_lock_waiting A gate is waiting for the per-repository gate lock another run of the same repository holds, or has just taken it. Nothing has failed: the gate has not started yet. The journal does not keep it; a resumed run contends for the lock again.
checkout_lock_waiting checkout_lock_waiting A merge back is waiting for the per-checkout merge lock, or has just taken it — the same waiting-not-hung signal as the gate lock, for the section that folds a run into the home branch. Not journaled either, for the same reason.
task_finished task_finished A task reached a terminal state, carrying the status it is being recorded under and, where it was built, the commit it produced. The ledger on disk holds the same verdict durably.
sandbox_visibility sandbox_visibility The run observed a wrapper state that needs explanation: unavailable managed process fence, custom wrapper, or intentionally disabled wrapper. It carries the host availability term, the effective wrapper state, and the reason. Journaled, so a run read back cold still says how it was fenced; the headless stream does not carry it.
pattern_journal One pattern journal record, delivered live beside the run stream so an in-process consumer can follow the executing structure as it happens. It is never written to either JSONL surface: the pattern engine writes those records itself, durably, and they are the pattern journal records set below.
prompt_needed prompt_needed The run needs a human answer before it can go on, and is waiting for one. It carries the question and the prompt kind that says what sort of answer will do. The journal does not keep it; a resumed run asks again live.
prompt_resolved prompt_resolved A waiting prompt was answered or resolved without an answer. The source says whether the answer came from a person, an abort-and-backstop default, or a disconnected command channel. Like the ask, only the headless stream carries it.
assistant_console_up The run's Gantry Assistant console is up and can take chat turns, under the harness and model named. It is never written to either JSONL surface — it tells a front-end its assistant affordances are live, and a file has none.
assistant_console_skipped The run deliberately has no assistant console, and this is the reason to show wherever one would have been offered. Like the console coming up, it is never written to either JSONL surface.
assistant_selection_pending assistant_selection_pending Someone asked the assistant to answer as a different harness or model, and the console stored that for the next turn. A reply already in flight keeps the identity it started under.
assistant_selection_activated assistant_selection_activated The pending assistant identity was taken up for a turn just submitted, and is now the one answering.
assistant_selection_failed assistant_selection_failed An assistant identity was asked for that the console cannot use, and the reason says why. Nothing changed: the assistant is still whatever it was.
agent_reply_identity agent_reply_identity The harness and model that are about to produce the assistant reply for a chat turn. It is journaled, so a transcript read back later attributes each answer to what actually wrote it rather than to whatever is selected now.
agent_reply_started agent_reply_started The assistant began answering a chat turn. It opens the message; the text itself arrives when the turn closes.
agent_reply_chunk One fragment of an assistant reply still streaming in. It is never written to either JSONL surface — the whole text arrives when the turn finishes — so a reader of a file sees complete replies only.
agent_reply_finished agent_reply_finished The assistant's answer to a chat turn is complete, and this carries the whole of it rather than the last fragment. The assistant transcript keeps the conversation after an engine restart.
agent_reply_failed agent_reply_failed An assistant turn failed before it produced a complete answer, and the reason says why. Only that turn is lost: the run, and any prompt awaiting an answer, are untouched.
settings_write_completed A settings change asked for from a front-end finished, and the refreshed catalog to redraw from comes with it. It is never written to either JSONL surface: it answers a front-end's own request, and belongs to no run's history.
reconciled reconciled The home branch advanced while the run was building, and the run folded that work into its own branch: which files had to be reconciled, and which of its commits were folded in. Written on every integrate, clean or not, so what the merge absorbed stays auditable after the fact.
stopped stopped The run stopped and is handing back to the operator, with the diagnosis to act on and, where one was written, the path of a fuller report. A terminal record, and one both surfaces carry: the journal keeps it because its structured reason is recorded nowhere else; resume restores the checkpoint and executes live.
pause_pending pause_pending The operator asked the run to pause at the next safe boundary. The current task keeps running, and the terminal stop carrying the operator pause arrives later, before the run admits more work. The journal does not keep it, and the headless front-end filters it out of the `--json` stream, so it has a wire name no file carries.
run_complete run_complete Every task is built and merged back: the run is over and there is nothing left to resume. The other terminal record, and unlike the stop it goes to a headless watcher rather than into the journal.

Pattern journal records

4 values from src/domain/mod.rs

The pattern engine's own durable journal, one record per line in `.gantry/<plan>/pattern-events.jsonl`. It sits beside the run journal rather than inside it: the run events carry the cards a front-end draws, and these records carry the shape the interpreter actually executed — the declared hierarchy, and the task-id path of everything that happened under it. Every positioned record carries that path, so a reader takes the structure from the path rather than inferring it from the order records arrive in. The token is the record's own discriminant, from the `record` tag its serde derive writes.

value wire name what it means
structure structure The shape the run is about to execute: which pattern is running, how many task levels it can open, and what those levels are called, outermost first. The first is declared from the pattern text before anything is enumerated and names no level at all, because a level is named only when its list is read; the record is journaled again each time a deeper level becomes known. A reader takes its vocabulary from this rather than assuming every run is milestones and tasks.
step step One step of the pattern reached a point in its life — the step phases below — at one position in the task tree. This is the bulk of the journal: what kind of step ran, where, and whether it was starting or ending. The kind is the step's routing discriminant rather than what the pattern calls it, and the engine writes no authored name beside it, so a reader naming a step has the kind to go on.
script_result script-result A command the pattern ran finished, recorded whole: what it exited with, what it printed, and the verdict the run drew from it. A replay of the run reads the result from here rather than running the command a second time.
work_list_inserted work-list-inserted An already-announced directory work list was enumerated again and had grown: the ids that appeared, under the path of the list's container. A list enumerated for the first time produces no such record.

Step phases

3 values from src/domain/mod.rs

Which point of a step's life a journaled step record is at. `started` and `finished` bracket a step that ran; `note` is for a record made without ending the step, and nothing in the engine writes one today. The token is the serde derive's own kebab-case spelling.

value wire name what it means
started started The step began; a `finished` record at the same position closes it.
finished finished The step is over, including one that stopped the run: a stop records the halt and its reason as the step finishes.
note note The step recorded something without ending — nothing failed and the run kept going. Nothing in the engine writes this phase today; it is read back for journals that carry it.