From 820c5067b7a67b569e03226326e5a268a3376249 Mon Sep 17 00:00:00 2001 From: gavrielc Date: Wed, 8 Apr 2026 23:16:17 +0300 Subject: [PATCH] docs: add DB file structure and migration strategy Split DB by entity (agent-groups.ts, messaging-groups.ts, sessions.ts) instead of one monolith. Numbered migration files replace inline ALTER TABLE blocks. Channels use barrel pattern for self-registration. Session DB split into messages-in.ts and messages-out.ts. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/v2-architecture-draft.md | 37 ++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/docs/v2-architecture-draft.md b/docs/v2-architecture-draft.md index 0be4149..e68d002 100644 --- a/docs/v2-architecture-draft.md +++ b/docs/v2-architecture-draft.md @@ -522,9 +522,44 @@ NanoClaw is customized via skills — branches that get merged into the user's i **Practical example:** Adding a new channel via skill should require: - One new file (the channel adapter or Chat SDK config) -- One line in index or a self-registering import +- One line in the barrel file (`channels/index.ts`) to import the self-registering module - Zero changes to routing, formatting, delivery, or container code +### DB File Structure + +v1's DB is one 750-line file with all tables, all CRUD functions, and all migrations inline. v2 splits by entity: + +``` +src/db/ + connection.ts ← singleton, init, WAL mode + schema.ts ← CREATE TABLE statements (current state, for reference) + migrations/ + index.ts ← runner: checks version, applies pending + 001-initial.ts ← v2 initial schema + 002-pending-questions.ts ← example: adds pending_questions table + ... ← skills append new numbered files + agent-groups.ts ← CRUD for agent_groups + messaging-groups.ts ← CRUD for messaging_groups + messaging_group_agents + sessions.ts ← CRUD for sessions + pending_questions + index.ts ← barrel: re-exports everything +``` + +**Principles:** +- **Split by entity, not by layer.** Each entity file has its own CRUD functions (~50-100 lines). A skill that adds a column to messaging_groups edits `messaging-groups.ts` — doesn't touch sessions or agent groups. +- **Schema as current state + migrations as history.** `schema.ts` documents what the DB looks like now (read this to understand the schema). Migrations are append-only numbered files that describe how we got here. +- **No inline ALTER TABLE.** v1 accumulates `try { ALTER TABLE } catch { /* exists */ }` blocks forever. v2 uses a migration runner with a `schema_version` table. On startup, it checks the current version and applies pending migrations in order. Each migration is a function: `(db: Database) => void`. +- **Skills add migrations.** A skill that needs a new column adds a new numbered migration file. No conflicts with other skills' migrations as long as numbers don't collide (use timestamps or high-enough numbers for skill branches). + +**Agent-runner session DB** uses the same pattern but lighter — no migrations needed since session DBs are created fresh by the host: + +``` +container/agent-runner/src/db/ + connection.ts ← open session.db at fixed path, WAL mode + messages-in.ts ← read pending, update status + messages-out.ts ← write results, outbox queries + index.ts ← barrel +``` + ### What the base architecture must support primitively These are the building blocks. None require special abstractions — they fall out of per-session DBs, host-managed routing, and messages_out with `kind: 'system'`: