Skip to content

feat: events table — add interactive_session_start event class with served model + provider #109

Description

@jakecelentano

Summary

Today, tms's events table (tms_review.events) captures dispatched-reviewer events with model, provider, session columns, but does NOT capture the interactive session that drove a workstream. So if we want to A/B compare interactive session models (e.g. Claude Code kimi-k3 vs pi/MiniMax-M3 vs future Claude-Code / Max-sub sessions), we have no fleet-side data — only ad-hoc wrap memos and pi footer text.

This is the missing link: a small event class on the events table fires whenever a tmq/aoe session starts, carrying the interactive session's provider + model. Once landed, all the analytics (plan-gate latency, code-review P0-detection, cost-per-task) become sliceable by interactive session model, not just by dispatched reviewers.

Scope

  • Add a new event class: interactive_session_start (and interactive_session_end for symmetry).
  • Schema change: NONE. Existing columns session, model, provider, event_type, event_timestamp, repo, worktree, payload already cover everything; idempotency UNIQUE on (event_type, aoe_id_prefix, event_timestamp) covers backfill too.
  • Hook: at aoe/tmq spawn time (after the worktree is attached, before the agent process boots), emit one interactive_session_start event with the served model+provider from pi's models.json (or equivalent) and the aoe session id as aoe_id_prefix.
  • Migration path: introduce the event class in the producer (tms poll, tmq spawn, or pi CLI --record-session-start). Backfill: aoe list can reconstruct historical sessions; models.json on each worktree provides the model. For backfill beyond what the producer captures, scrape existing ~/.local/state/tmq/events.jsonl archives (if any were retained) and the agent-config repo for served-model hints.
  • Query surface: add a tms CLI subcommand tms events sessions (or extend tms events transitions) that returns events filtered by event_type='interactive_session_start' and joins on reviewer_runs.model / llm_call_log for the workstream attribution.

Why now

This week's dogfood waves (Jul 19, two wraps) dispatched 14 PRs and recorded 29 reviewer_runs rows, all with panel= attribution. The missing attribution is the interactive session that authored the day. Without it, every "how is model X performing?" question reduces to inference from memos.

Out of scope

  • A new "sessions" table — the events table already covers this surface.
  • A cost column on the event itself — cost flows through llm_call_log (worktree attribution) and joins from there.
  • Per-user attribution (which human kicked off which session) — would need an aoe event for start_session that doesn't exist yet.

Acceptance criteria

  • A tmq/aoe spawn emits one interactive_session_start event with session, model, provider, worktree populated
  • Event is emitted BEFORE the agent process boots (i.e., the consumer can observe start even if the agent crashes immediately)
  • Backfill script (tms backfill session-events or similar) reconstructs the past N days of interactive session starts from aoe list JSON + the worktree's models.json
  • New query: tms events sessions --model <id> --since <date> returns the sessions for that model; cross-joins reviewer_runs to attribute panel verdicts to their driving interactive session
  • Tests: idempotent insert (ON CONFLICT DO NOTHING on the UNIQUE), backfill idempotency on a re-run, missing-models.json graceful skip

References

  • Precedent: distillery's media_digest_runs.model = actually-served (PR distillery#442, memory distillery-provenance-served-model.md) — the same pattern: capture the model that actually served, not the model that should have served.
  • Existing migration 006-specialist-composition.sql establishes the precedent for additive column-add migrations on tms_review.
  • bogocat/openagent#51 (weekly fleet-digest) is the downstream consumer; this column lands the sliceable dimension.
  • Memory: "Fleet runtimes: pi is primary" + "MiniMax-M3 eval — Opus-class; caveat = runtime reliability" make the case for the data without the metric being available.
  • Related: tms#101 (verdict capture → reviewer_runs, landed 2026-07-19) did this for dispatched reviewers; this issue extends the same pattern to the interactive session.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions