Event

March 29, 2026 · View on GitHub

What an event is

An event is an immutable, schema-validated JSON record appended to the event log at <runtime-root>/events/coordinator.jsonl (one JSON object per line). Events are the audit trail. The full history of any goal or run is reconstructable from events alone.

Schema

See schema/event.schema.json.

Required fields (all events)

FieldTypeDescription
tsISO 8601 UTCSystem-assigned at emit time.
typestringNamed event type. See table below.
actorstringWho caused this: "system", "operator", or agent name.

Conditional fields (by event type)

Event typeAdditional required fields
GoalTransitionedgoal, from, to
GoalClosedgoal, goal_reason
RunFinishedgoal, run, run_reason
DispatchPacketMaterializedgoal, run
TendStartedgoal, run, trigger_kinds
TendFinishedgoal, run, follow_up_goal_count, memory_updated, operator_note_written
ActiveThreadsRefreshStartedplant, active_threads_path
ActiveThreadsRefreshFinishedplant, active_threads_path, active_threads_outcome
DashboardInvocationStarteddashboard_invocation_id, dashboard_mode, dashboard_refresh_seconds, dashboard_tty
DashboardInvocationFinisheddashboard_invocation_id, dashboard_mode, dashboard_refresh_seconds, dashboard_tty, dashboard_outcome, dashboard_render_count, dashboard_wall_ms, dashboard_record_path
ConversationHopQueuedgoal, run, conversation_id, hop_goal, hop_requested_by, hop_reason, hop_automatic
ConversationHopQueueFailedgoal, run, conversation_id, hop_requested_by, hop_reason, hop_automatic, detail
ConversationCheckpointWrittenconversation_id, checkpoint_id, checkpoint_requested_by, checkpoint_reason, checkpoint_summary_path, source_message_id, source_session_ordinal, source_session_turns, checkpoint_count
SystemErrorerror_reason

Optional fields

goal, run, and typed metadata fields are included as relevant to the event type.

Common optional metadata now includes:

  • goal_type — the submitted goal's type
  • goal_subtype — a more specific goal surface when used; current values are post_reply_hop and plant_commission
  • goal_priority — the submitted goal's numeric priority
  • goal_origin — e.g. conversation
  • conversation_id — when the goal is linked to a conversation
  • source_message_id — conversation message source, when present
  • source_goal_id / source_run_id — the run that submitted the goal, when known
  • hop_goal, hop_requested_by, hop_reason, hop_automatic — queued post-reply hop outcome metadata
  • checkpoint_*, source_session_* — durable checkpoint-write metadata
  • trigger_kinds — tend trigger family on tend lifecycle and related goal/run events
  • trigger_goal / trigger_run — the goal or run that triggered a tend
  • follow_up_goals — goal ids submitted by a tend run
  • operator_note_path — the tend survey delivery path recorded for a tend run; this may be a transcript-backed top-level reply copy or an out-of-band notes/ path
  • active_threads_* — Active Threads refresh target path, typed outcome, and rejection reason
  • dashboard_* — dashboard invocation mode, measured wall time, and record path metadata
  • packet_path, supplement_* — dispatch-packet and supplement observability fields

Path-valued event fields stay relative instead of absolute:

  • runtime-churn paths such as dashboard_record_path, packet_path, and operator_note_path are relative to <runtime-root>/
  • plant-local paths such as active_threads_path stay relative to the garden root because those artifacts live under plants/...

Event types

TypeWhen emitted
GoalSubmittedA goal is accepted by the submission protocol
GoalTransitionedA goal moves to a new state
GoalDispatchedDispatcher hands goal to a worker
GoalClosedA goal reaches closed state
GoalSupplementedA queued durable goal receives an immutable pre-dispatch supplement
DispatchPacketMaterializedThe exact pre-dispatch packet for a run is frozen to disk
RunStartedA run subprocess launches
RunFinishedA run reaches a terminal status
EvalSpawnedAn evaluate goal is created for a completed goal
EvalClosedAn evaluate goal closes, parent transitions
TendStartedA tend run begins its survey after RunStarted
TendFinishedA tend run emits its semantic summary before RunFinished
ActiveThreadsRefreshStartedwrite_active_threads() begins one bounded Active Threads refresh
ActiveThreadsRefreshFinishedThat refresh ends with a typed success or rejection outcome
DashboardInvocationStartedpak2 dashboard starts one CLI session
DashboardInvocationFinishedpak2 dashboard finishes and records its measured wall-time cost
ConversationHopQueuedA converse turn successfully queues a post-reply hop goal after replying
ConversationHopQueueFailedA converse turn needed a post-reply hop but could not queue it
ConversationCheckpointWrittenA checkpoint record and archive summary are durably written
MemoryUpdatedA participant writes new memory
SkillAddedA new skill is codified
SkillArchivedA skill is archived for disuse
SystemErrorThe system encountered a named error condition

Reason fields (typed per event type)

Reason codes are split into three typed fields to allow the schema to enforce valid values per event type. Do not use a generic reason field.

goal_reason — GoalClosed, EvalClosed

CodeMeaning
successGoal completed successfully
failureRun failed
cancelledGoal stopped before running
dependency_impossibleA dependency can never close

run_reason — RunFinished

CodeMeaning
successRun completed
failureRun failed
killedWatchdog or operator stopped the run
timeoutRun exceeded time limit
zero_outputRun produced no output

error_reason — SystemError

CodeMeaning
schema_violationA record failed schema validation
invalid_transitionAn illegal state transition was attempted
submission_rejectedA goal submission was rejected
validator_unavailableValidator could not run

Conditional required fields by type

Event typeRequired fields beyond ts/type/actor
GoalSubmittedgoal
GoalTransitionedgoal, from, to (must be valid statuses)
GoalDispatchedgoal
GoalClosedgoal, goal_reason
GoalSupplementedgoal
DispatchPacketMaterializedgoal, run
RunStartedgoal, run
RunFinishedgoal, run, run_reason
EvalSpawnedgoal, eval_goal
EvalClosedgoal, eval_goal, goal_reason
TendStartedgoal, run, trigger_kinds
TendFinishedgoal, run, follow_up_goal_count, memory_updated, operator_note_written
ActiveThreadsRefreshStartedplant, active_threads_path
ActiveThreadsRefreshFinishedplant, active_threads_path, active_threads_outcome
DashboardInvocationStarteddashboard_invocation_id, dashboard_mode, dashboard_refresh_seconds, dashboard_tty
DashboardInvocationFinisheddashboard_invocation_id, dashboard_mode, dashboard_refresh_seconds, dashboard_tty, dashboard_outcome, dashboard_render_count, dashboard_wall_ms, dashboard_record_path
ConversationHopQueuedgoal, run, conversation_id, hop_goal, hop_requested_by, hop_reason, hop_automatic
ConversationHopQueueFailedgoal, run, conversation_id, hop_requested_by, hop_reason, hop_automatic, detail
ConversationCheckpointWrittenconversation_id, checkpoint_id, checkpoint_requested_by, checkpoint_reason, checkpoint_summary_path, source_message_id, source_session_ordinal, source_session_turns, checkpoint_count
SystemErrorerror_reason

Failure modes

Reason codeWhen it occurs
MISSING_REQUIRED_FIELDA required field is absent for this event type
INVALID_TYPEtype is not a known event type
INVALID_TIMESTAMPts is not ISO 8601 UTC
INVALID_ACTORactor is empty, uppercase, or otherwise malformed
INVALID_STATUSfrom or to on GoalTransitioned is not a valid goal status
INVALID_REASONReason code is not valid for this event type
INVALID_TEND_TRIGGER_KINDA tend event used an unknown trigger kind
INVALID_GOAL_FORMATA goal-shaped event field is malformed
INVALID_ID_FORMATA run, conversation, message, checkpoint, or dashboard invocation id is malformed
INVALID_PLANT_NAMEA plant field is empty or does not match the plant-name pattern
INVALID_SHAPEDocument is not a JSON object

Active Threads refresh fields

  • ActiveThreadsRefreshStarted means system.active_threads.write_active_threads() began one bounded refresh of the artifact named by active_threads_path.
  • ActiveThreadsRefreshFinished means that refresh ended.
  • active_threads_outcome is currently success, validation_rejected, or io_error.
  • When active_threads_outcome is not success, active_threads_reason carries the helper's named ValidationResult.reason, and detail may carry the explanatory text.

Validation

system/validate.py:validate_event(data: dict) -> ValidationResult

Called before every append. Returns .ok=True or .ok=False with .reason and .detail. Never raises.

Tests

Focused regression coverage currently lives in:

  • tests/test_active_threads.py
  • tests/test_coordinator.py
  • tests/test_tend.py
  • tests/test_conversation_session_maintenance.py
  • tests/test_dashboard.py
  • tests/test_dashboard_invocations.py

For the current automatic run_failure / queued_attention_needed trigger pair that produces these tend events, see Automatic Tend Submission.