-- Structured mission activity: what an agent actually DID, as data. -- -- Until now the World could show a mission's shape (phases, status, who is on -- which station) but nothing about the work itself. The detail existed only as -- prose in `checkpoint.log` and agent output, where a tool name is -- indistinguishable from an agent *talking about* a tool — so it was never -- parsed, deliberately. This table is the structured channel that replaces it. -- -- `run_events` could not be reused: 0003 declares `run_id REFERENCES -- agent_runs(id)`, and mission phases insert into `topology_runs`. Those are -- independent id spaces, so every write would have been an FK violation. CREATE TABLE IF NOT EXISTS mission_events ( id BIGSERIAL PRIMARY KEY, mission_id UUID NOT NULL REFERENCES missions(id) ON DELETE CASCADE, -- No FK. `mission_phases` rows survive, but a phase that loops is re-run -- and this column is only ever read as a grouping key. phase_id UUID, -- Deliberately NO FK, and this is the load-bearing decision in the file: -- `phase_runner` DELETEs the `topology_runs` row on every retry. With a -- cascading FK, a phase's whole history would vanish the moment it retried -- — silently, since a cascade is not an error. The id is kept as a plain -- correlation value. run_id UUID, -- The platform agent, when there is one. NULL for a microVM phase, which -- has no platform agent at all — that is the truth, not missing data. agent_id UUID, -- phase.started | phase.completed | tool.call | file.touch -- | finding.raised | benchmark.delta kind TEXT NOT NULL, -- The tool name, or the file path — whatever the event is *about*. target TEXT, detail JSONB NOT NULL DEFAULT '{}'::jsonb, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); -- The World reads by mission, newest last, and by phase for the per-phase cap. CREATE INDEX IF NOT EXISTS mission_events_mission_idx ON mission_events (mission_id, id); CREATE INDEX IF NOT EXISTS mission_events_phase_idx ON mission_events (phase_id, id); -- The retention sweep in `mission_gc` scans by age. CREATE INDEX IF NOT EXISTS mission_events_created_idx ON mission_events (created_at);