// Package shadowdb manages session-scoped shadow tables for Agent // multi-round reasoning. An Agent that reasons across several turns // (build a wave, observe effects, revise, re-observe) needs a // speculative write surface that does NOT touch production and is // cleaned up when the session ends. // // Design: column-tag isolation (scheme C). Callers provision a // physical shadow table that mirrors the production schema plus a // session_id VARCHAR(64) NOT NULL column. Opener.Open seeds the // shadow for a given sessionID (INSERT INTO shadow SELECT // session_id=?, * FROM seed). Every read and write inside the // session carries AND session_id=? so two concurrent sessions never // see each other's rows. Close deletes all rows tagged with the // session's ID; a crash leaves orphans that the platform-layer // Reap() cron cleans up. // // Why column-tag over PG TEMP TABLE: pooled *sql.DB routes each // query to any backend connection and PG TEMP tables are // connection-scoped -- the temp table vanishes on the next query. // PG TEMP would force *sql.Conn pinning, holding one backend // connection per Agent session, and breaking driver portability // (SQLite TEMP is connection-local, MySQL TEMP does not guarantee // pool cleanup). Column-tag uses pure INSERT/UPDATE/DELETE/SELECT // with ? params, one driver-agnostic code path, and matches the // zero-external-dependency constitution. // // Relationship to adjacent packages: // // - staging (pkg/staging): decision-level pre-commit approval // (one Record = one Agent decision). shadowdb is finer-grained // (SQL-level scratchpad during reasoning) and feeds into // staging: the final approved diff flows shadow -> staging -> // production. shadowdb never merges to production directly. // - evolve.ShadowRunner (pkg/evolve): parameter-tuning shadow // (compare fitness of baseline vs candidate parameter). Same // word, different concept -- package named shadowdb to // disambiguate. // - tools/builtin.SQLCASTool (pkg/tools/builtin): optimistic-lock // UPDATE on staging/shadow tables. Orthogonal; SQLCASTool // writes inside a shadow session just as it writes inside a // staging table. // - tools/builtin.StagingDB: sibling intent-marker newtype. This // package defines ShadowDB with the same shape; the two are // conceptually siblings but kept in separate packages to avoid // an import cycle through tools/builtin. // // Pull-only API (product decision #5, consistent with staging): // Opener.Reap is a function call the platform layer invokes from // its own scheduler. core does NOT spawn goroutines or run // watchdog loops. // // Package shadowdb 管理 session 级影子表, 服务于 Agent 多轮推理. // Agent 在多轮决策中 (建波次 -> 看效果 -> 改 -> 再看) 需要一个 // 试探性写入面: 不碰生产, session 结束时清理. // // 设计: 列标记隔离 (方案 C). 调用方预建一张物理影子表, schema // 与生产对齐并额外有 session_id VARCHAR(64) NOT NULL 列. Opener.Open // 按 sessionID 种子化 (INSERT INTO shadow SELECT session_id=?, * // FROM seed). session 内每次读写都带 AND session_id=?, 两个并发 // session 绝不会看到对方的行. Close 删掉带本 session ID 的所有 // 行; 崩溃留下的孤儿由平台层的 Reap() cron 清理. // // 为什么选列标记而非 PG TEMP TABLE: pool 化的 *sql.DB 会把每条 // query 路由到任一后端连接, PG TEMP 是 connection-scoped 的 -- // 下一条 query 上 temp 表就消失了. PG TEMP 会逼迫 *sql.Conn 绑定, // 每个 Agent session 占一条后端连接, 并且破坏 driver 可移植性 // (SQLite TEMP 是 connection-local, MySQL TEMP 不保证连接池回收). // 列标记路径仅用 INSERT/UPDATE/DELETE/SELECT + ? 参数, 单一 driver // 无关代码路径, 契合 "零外部依赖" 宪法. // // 与相邻包的关系: // // - staging (pkg/staging): 决策级 pre-commit 审批 (一条 Record // = 一次 Agent 决策). shadowdb 粒度更细 (推理期间的 SQL 级 // scratchpad), 并作为 staging 上游: 最终通过的 diff 流转为 // shadow -> staging -> 生产. shadowdb 绝不直接合并进生产. // - evolve.ShadowRunner (pkg/evolve): 参数级调优 shadow (比较 // baseline 与候选参数 fitness). 同词不同概念 -- 本包命名为 // shadowdb 消歧义. // - tools/builtin.SQLCASTool (pkg/tools/builtin): staging/shadow // 表乐观锁 UPDATE. 正交; SQLCASTool 在 shadow session 内写, // 与在 staging 表内写一样. // - tools/builtin.StagingDB: 同族意图标记 newtype. 本包定义 // ShadowDB 同构, 两者概念兄弟, 刻意分包避免经 tools/builtin // import cycle. // // Pull-only API (产品决策 #5, 与 staging 一致): Opener.Reap 是 // 函数调用, 由平台层从自己的调度器触发. core 不起 goroutine, // 不跑 watchdog 循环. package shadowdb