{"type":"meta","slug":"overdeck-observability","base_branch":"origin/main","gate0_mode":"strict","preset":"codex","land_mode":"merge-to-main"}
{"type":"goal","text":"Ship an Overdeck /logs page: one activity store fed by every overdeck-hosted source, a sortable+searchable DeckTable over it, and visx time-series charts over 1h/1d/3d/7d/30d/all — including per-account limit-usage lines. The system is currently blind; the owner has no way to see what the infra did."}
{"type":"intent","text":"The owner spent 2026-08-07 unable to tell whether anything was happening at all — 12h waiting on landings that were already complete, five agents killed at a token cap discovered only by hitting the wall, and 190 identical alerts that told him nothing. Notifications were rejected as harassment. The answer is a place he can LOOK when he chooses to, that reports honestly, not a channel that interrupts him."}
{"type":"methodology","text":"Contract-level spec, seams pinned in prose, implementer writes bodies. Compose existing @overdeck/deck-ui exports; three new primitives only (owner-approved). Tokens only, both themes. Wave 1 must RENDER from already-append-only sources before any new emitter is built — no ten-shipper prerequisite chain ahead of the first visible page."}
{"type":"direction","verbatim":"i think i deserve a Logs page, that will log ALL activity done by all this infra. currently, i have NO IDEA what happened, or if anything happened at all. notification spam is just harrassing me, but having a log file could be useful to analyze when i'm up for it."}
{"type":"direction","verbatim":"put it as a notice on the buildbox in the CI page in overdeck ui. not a push notification to systray"}
{"type":"direction","verbatim":"ultrathink about the logs UX , it can't be just a data dump, or it will be useless. it has to use the DataTable (sortable, searchable) primitive"}
{"type":"direction","verbatim":"i want to see , with option to see for 1h, 1d, 3d, 7d, 30d, ALL TIME, the activity of agents,(number of active agents) log lines generated, commits generated, bots activity, with per projet line selectable graphs , filters per project"}
{"type":"direction","verbatim":"i want to have charts of account usage, with the 7d limit percentage over time, as one of the charts. with each account has a line on the chart"}
{"type":"direction","verbatim":"which is the nicest ones? i am not restrained to space or package size here, its locally hosted"}
{"type":"direction","verbatim":"i really need you to fix things behind the scenes, and leave my visual everything alone."}
{"type":"direction","verbatim":"you are running dangerous tests on my laptop again. you have a memory against that. it's not good enough this memory, because every time after a disaster you are trying to test a disaster on my laptop. lately, you agents bricked 2 of my buildboxes and now my work is for many hours again not possible due to agentic BS. you are unable to even put out the fire before testing dangerous stuff on my laptop. you proved already that agents cant write safe code, so never test this shit here. EVER. FOR ANY REASON. I NEVER APPROVED THAT."}
{"type":"direction","verbatim":"I DONT WANT PID NOTIFICATIONS I DONT KNOW WHAT TO DO WITH IT - REMOVE IT!!!!!!!!!!!!! ONLY ACTIONABLE THINGS I CAN UNDERSTAND"}
{"type":"session_memory","note":"Charting foundation DECIDED: visx. Chosen over ECharts and Recharts because it is unstyled, so design tokens and both themes apply natively. Do NOT re-open this choice or substitute a styled library."}
{"type":"session_memory","note":"Store location DECIDED: OVERDECK_STATE_DIR (~/.local/state/overdeck), the collector's existing SQLite state dir. ~/.overdeck/ holds the older journal and factory db and is NOT extended. Every writer resolves the env var; none hardcodes a second path."}
{"type":"session_memory","note":"THREE record kinds, deliberately separate — a count table cannot answer a concurrency or a percentage question. activity_events (discrete), activity_sessions (intervals -> active-agent concurrency via overlap read), activity_gauge (samples -> limit-used percentage). Counting session-START events as 'active agents' is the wrong answer and is explicitly forbidden by the spec."}
{"type":"session_memory","note":"Dedupe is READ-TIME only. Raw stores every occurrence with dedupe_key; the table and digest group at render. Write-time collapsing is explicitly REJECTED — it would put all 190 fswatch occurrences in the first bucket and make every later bucket understate activity."}
{"type":"session_memory","note":"Samplers are EDGE-TRIGGERED for events (emit only on state change; liveness carried by a separate non-event last_sampled_at heartbeat) but SAMPLE-ON-POLL for gauges (a level is the signal). Monotonic counter sources (notif-gate/pending.json) ship the DELTA, never the running total."}
{"type":"session_memory","note":"Account-usage data ALREADY EXISTS and is already thrown away: modules/systray/ health clients (claude_health_client.py, codex_appserver.py, grok_health_client.py) return primary_used_pct (5h) / secondary_used_pct (7d) / resets_at per account, keyed by account.tray_key; quota_notification_store.py already keys (account_key, window). Nothing persists a series. The gauge shipper subscribes to that same snapshot — it does NOT build a new poller."}
{"type":"session_memory","note":"A quota window reset is a DISCONTINUITY, not a downward slope: resets_at moving forward starts a new segment and the chart CUTS the line. Drawing a fall from 96% to 3% would read as usage being refunded. A missing poll is a GAP — never carry the last value forward."}
{"type":"session_memory","note":"Honest-data law is load-bearing here: zero MUST NOT stand in for absence. Every read API response carries coverage/coverageFrom; a series renders 'no data before X' rather than a zero line. Several sources are current-state-only and can never produce history retroactively."}
{"type":"deferred","text":"Prometheus load overlay on the Logs page","reason":"Blocked on task #86 — the node_exporter textfile feed has been frozen since 2026-07-12 and Prometheus retention is unset. Overlay must degrade to 'no data', never to a flat line. Build the chart, accept it renders empty until #86 lands."}
{"type":"deferred","text":"botmaster-proxy activity events","reason":"It currently writes nothing to disk; its history is in-memory only. Needs a flush-to-store change in that service, tracked as its own emitter in spec 4.5 rather than blocking wave 1."}
{"type":"anchor","path":"docs/specs/2026-08-08-overdeck-observability-design.md","what":"spec"}
{"type":"anchor","path":"docs/specs/2026-08-08-overdeck-observability-source-inventory.md","what":"measured source inventory — per-source paths, formats, timestamp/id presence, append-vs-overwrite, retention, measured volumes; the evidence the spec rests on"}
{"type":"anchor","path":"docs/plans/2026-08-08-overdeck-observability.md","what":"plan"}
{"type":"anchor","path":".claude/skills/od-ui-dev/SKILL.md","what":"MANDATORY UI rules — compose deck-ui exports, tokens only, gallery registration, no hand-rolled tables/chips/menus/tooltips"}
