Skip to main content

State Model

Panopticon keeps almost no irreplaceable state of its own. The durable record of your work lives in systems that already exist for their own reasons — GitHub and git — and the local database is a derived cache: a fast view over those sources that holds nothing which can’t be rebuilt from them. If you remember one thing from this page: the database is a cache, not a source of truth.

The sources of truth

Everything Panopticon needs — to show you a board, run the pipeline, or recover after a crash — is a function of four things that live outside its database:
Source of truthWhat it holdsWhere it lives
GitHub IssuesWhat work exists and its lifecycle (todo / in progress / done)github.com
Git repo & workspacesThe plan, the code, the feature branch, the PR, the per-issue record, task stateYour repo + origin
Agent transcriptsThe conversation history to resume an agent mid-taskOn disk, per harness (kept while work is active)
tmuxWhich agents are alive right nowLocal tmux server

The local database is a cache

Panopticon uses a local SQLite database (~/.panopticon/panopticon.db) for two jobs:
  1. A uniform read/write API for the dashboard, the deacon, and the CLI — so every component talks to state the same way instead of each parsing files.
  2. A materialized view of the pipeline — so the board renders instantly instead of re-scanning every workspace on each page load.
Both are performance conveniences. The database stores nothing that cannot be recomputed from the sources of truth above.
The design principle: the database holds no state that isn’t derivable from GitHub + your workspaces. It is a cache in front of those sources, not a system of record — which is what keeps recovery and cross-machine work straightforward. The durable record of your work lives in git, not in a local file you have to back up.

The pipeline is derived, not stored

An issue’s pipeline phase is a function of GitHub + its workspace, not a value the database owns:
Workspace / GitHub statePhase
Feature branch + open tasks, no PRWork
PR open, not approvedReview
PR approvedMerge
Issue closed on GitHubDone
Panopticon computes this view by walking the workspaces and reading GitHub, then caches the result. The cache is for speed; the derivation is the truth.

What lives where

StateDurable homeIn the cache?
Issue status / lifecycleGitHub✅ cached
Plan (vBRIEF spec)git — .pan/specs/✅ cached
Code & branchgit / origin
Task completion (beads)git (dolt-backed)✅ cached
Per-issue record — decisions, progress, harness/model, verdictsgit — the feature branch✅ cached
Conversation transcriptson disk, per harness (while active)indexed
Costderived from transcripts✅ cached
Live activity (who’s thinking)ephemeralcache only
Retry counters, merge-queue positionephemeral bookkeepingcache only — safe to lose
The only things that vanish on a database loss are ephemeral counters — retry counts, queue positions. They gate loop-prevention, not your work; on a rebuild they reset, and the worst case is an agent gets a fresh set of attempts.

Search indexes are the exception

Panopticon also keeps search indexes in SQLite — full-text and semantic search over conversations and docs. Unlike pipeline state, a search index is legitimately a database’s job and persists as one. These indexes are rebuildable from the transcripts on disk, but they are a search feature, not part of the “pipeline is a cache” model.

The rules that keep this true

  • All state mutations go through the database API — never ad-hoc writes to scattered files. The database is the single write surface; the per-issue git record is its durable mirror. This is enforced mechanically by scripts/lint-state-writes.sh, which runs in npm run lint and CI.
  • Legacy continue/feedback/session writers are being routed to the record writer. A small set of pre-PAN-1919 writers (continue files, feedback files, session JSONL) remain while they are migrated; the guard allowlists them explicitly and fails on any new ad-hoc state write.
  • The database is reconstructable. A rebuild path walks every workspace + GitHub and repopulates the cache from scratch.
  • The few facts a workspace can’t derive — an agent’s chosen harness/model, pipeline verdicts, retry counters — live in the per-issue record committed to the feature branch, so they travel across machines and survive a database loss.

Why it matters

  • Recovery is trivial. Lost database, corrupted file, fresh machine — git clone, start Panopticon, and the board rebuilds. No backups to restore, no event logs to replay.
  • Work is portable. Because the durable record travels in git, another machine — or another engineer — can pull a branch and continue exactly where the last agent left off.
  • The system is simple to reason about. Every piece of state has a clear home: if it isn’t derivable from GitHub + the workspaces, it lives in the per-issue git record — never only in the local cache.