From 9af02831ea681542e793aeb3fa973a3aa5bfcbd8 Mon Sep 17 00:00:00 2001 From: codex Date: Wed, 1 Jul 2026 16:53:23 +0000 Subject: [PATCH] docs(prd): add sqlite local storage plan --- docs/prds/prd-new-sqlite-local-storage.md | 140 ++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 docs/prds/prd-new-sqlite-local-storage.md diff --git a/docs/prds/prd-new-sqlite-local-storage.md b/docs/prds/prd-new-sqlite-local-storage.md new file mode 100644 index 0000000..1a24c69 --- /dev/null +++ b/docs/prds/prd-new-sqlite-local-storage.md @@ -0,0 +1,140 @@ +# PRD prd-new: SQLite local storage + +- **Status:** Draft +- **Author:** codex +- **Created:** 2026-07-01 +- **Issue:** #319 + +## Summary + +Add a small stdlib SQLite storage layer for bot-bottle host runtime state, +starting with the supervise queue and audit log. This replaces scattered JSON +queue files and JSONL audit logs with structured tables while preserving the +existing public supervise helper functions and sidecar queue mount contract. + +## Problem + +Bot-bottle currently stores supervise proposals and responses as individual JSON +files under `~/.bot-bottle/queue//`, and audit entries as JSONL files +under `~/.bot-bottle/audit/`. That worked for the original interactive TUI, but +new forge-native orchestration needs durable, queryable local state for queues, +audit trails, watchdogs, and lifecycle records. PR #318 started introducing +SQLite-shaped boilerplate for forge state; the storage foundation should live in +its own PR so forge work can build on the shared runtime store instead of adding +one-off persistence. + +## Goals / Success Criteria + +1. Supervise proposals and responses are persisted through SQLite. +2. Audit entries are persisted through SQLite. +3. Existing public supervise helpers keep their current call shape where + practical: `write_proposal`, `read_proposal`, `list_pending_proposals`, + `write_response`, `read_response`, `wait_for_response`, + `archive_proposal`, `write_audit_entry`, and `read_audit_entries`. +4. The sidecar queue mount still works across docker, smolmachines, and + macOS-container backends. +5. The implementation stays stdlib-only. +6. Unit tests cover queue round-trips, pending discovery, response waits, + archive semantics, audit round-trips, and path creation. + +## Non-goals + +- Migrating old JSON queue files or JSONL audit logs. +- Adding forge orchestration state tables. +- Adding egress metering or budget tables. +- Changing the supervise TUI workflow or remediation behavior. +- Introducing a third-party ORM or migration framework. + +## Design + +### Database locations + +Queue state remains tied to the mounted per-bottle queue directory: + +```text +~/.bot-bottle/queue//supervise.db +``` + +The supervise sidecar already receives that directory at +`/run/supervise/queue`, so both the sidecar and host TUI can read and write the +same SQLite file without changing backend mounts. + +Audit state uses the host-level local database: + +```text +~/.bot-bottle/bot-bottle.db +``` + +This creates the shared host database that later forge/native lifecycle work can +extend in separate PRDs. + +### Tables + +`supervise_proposals` lives in the per-queue database: + +```sql +CREATE TABLE supervise_proposals ( + id TEXT PRIMARY KEY, + bottle_slug TEXT NOT NULL, + tool TEXT NOT NULL, + proposed_file TEXT NOT NULL, + justification TEXT NOT NULL, + arrival_timestamp TEXT NOT NULL, + current_file_hash TEXT NOT NULL, + archived INTEGER NOT NULL DEFAULT 0 +); +``` + +`supervise_responses` lives in the same per-queue database: + +```sql +CREATE TABLE supervise_responses ( + proposal_id TEXT PRIMARY KEY, + status TEXT NOT NULL, + notes TEXT NOT NULL, + final_file TEXT, + archived INTEGER NOT NULL DEFAULT 0 +); +``` + +`supervise_audit_entries` lives in the host database: + +```sql +CREATE TABLE supervise_audit_entries ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL, + bottle_slug TEXT NOT NULL, + component TEXT NOT NULL, + operator_action TEXT NOT NULL, + operator_notes TEXT NOT NULL, + justification TEXT NOT NULL, + diff TEXT NOT NULL +); +``` + +### Compatibility + +The existing helper functions keep accepting `Path` arguments for queue +directories. Internally, they map the queue directory to `supervise.db` and +perform equivalent operations: + +- `list_pending_proposals` returns non-archived proposals without a non-archived + response, sorted by arrival time. +- `archive_proposal` marks matching proposal/response rows archived instead of + moving files into `processed/`. +- `wait_for_response` keeps the current polling behavior but polls SQLite. + +The old path helpers (`queue_dir_for_slug`, `audit_dir`, `audit_log_path`) stay +available for compatibility. `audit_log_path` no longer describes the active +storage location; callers should use `read_audit_entries`. + +## Implementation chunks + +1. Add SQLite store helpers for supervise queue and audit state. +2. Rewire `bot_bottle.supervise` queue/audit functions to the store. +3. Update supervise CLI discovery tests and queue/audit unit tests. +4. Run unit tests, pyright, and pylint for touched modules. + +## Open questions + +None.