- 迁移 0025_memory_ingest_reviews(幂等,既有部署重跑不炸/不丢行) - GC:保留期 720h + 条数上限 10 万行,挂进审查服务生命周期(Start 起 / Stop 停 / 启动先扫) - 过期即硬删(RevertMerged 只读 memory_items,删留痕不损失回滚能力) - 偏离一处并给理由:表只留 created_at(先例 0017;append-only;加 updated_at 需三份 DDL 真源) - 3 个变异自检(边界 <=/元组比较方向/Retention=0)
69 lines
3.0 KiB
Go
69 lines
3.0 KiB
Go
package memory
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
)
|
|
|
|
// 本文件是 D3「入库前审查」(design/23 §15.1 D3)的 schema 侧。
|
|
//
|
|
// 为什么是一张新表而不是塞进 memory_tidy_candidates:设计稿要的是**每一次
|
|
// 入库前审查都留一条结构化记录**(决定 / 依据 / 命中的既有 id / 是否降级,
|
|
// §15 D3-8),而 tidy 候选表是「人工确认队列」(pending/applied/rejected),
|
|
// 语义不同、生命周期也不同 —— 审查是已经生效的事实留痕,不是待批准的提议。
|
|
// 两表共用同一套 id/时间戳口径(主键 id、created_at),词表口径见各列注释。
|
|
//
|
|
// 表结构的权威机制是 internal/db 的迁移(`0025_memory_ingest_reviews`,切片 W5 补登记);
|
|
// 本处仍保留幂等前滚,与 memory_items / tidy 两表同一手法(store_schema.go 的口径:
|
|
// 记忆存储必须自包含、可在任意 *sql.DB 上使用)。两份 DDL **必须逐字同形**:
|
|
// 少一列就是「新库有、老库无」的漂移(既有部署的表是这里建的,`CREATE TABLE
|
|
// IF NOT EXISTS` 不会给它们补列),由 preinsert_migration_test.go 逐列/逐索引比对钉住。
|
|
//
|
|
// 保留期清扫(按 created_at 删过期行 + 条数上限)见 preinsert_gc.go。
|
|
|
|
// createMemoryIngestReviewsTable 是入库前审查的结构化留痕(design/23 §15 D3-8)。
|
|
// 刻意**不存记忆正文**:命中的既有 id 足以让 owner-only 的读侧回表取正文,
|
|
// 而正文不进日志/不进这张表,是把「记忆正文不进日志」这条落成结构。
|
|
const createMemoryIngestReviewsTable = `
|
|
CREATE TABLE IF NOT EXISTS memory_ingest_reviews (
|
|
id TEXT PRIMARY KEY,
|
|
item_id TEXT NOT NULL,
|
|
persona_id TEXT NOT NULL,
|
|
scope TEXT NOT NULL,
|
|
project_id TEXT NOT NULL DEFAULT '',
|
|
decision TEXT NOT NULL,
|
|
reason TEXT NOT NULL DEFAULT '',
|
|
veto TEXT NOT NULL DEFAULT '',
|
|
target_id TEXT NOT NULL DEFAULT '',
|
|
merged_ids TEXT NOT NULL DEFAULT '[]',
|
|
score REAL NOT NULL DEFAULT 0,
|
|
recall_mode TEXT NOT NULL DEFAULT '',
|
|
degraded INTEGER NOT NULL DEFAULT 0,
|
|
rule_version TEXT NOT NULL DEFAULT '',
|
|
session_id TEXT NOT NULL DEFAULT '',
|
|
created_at TEXT NOT NULL
|
|
)`
|
|
|
|
const createMemoryIngestReviewsItemIndex = `
|
|
CREATE INDEX IF NOT EXISTS idx_memory_ingest_reviews_item_id
|
|
ON memory_ingest_reviews (item_id)`
|
|
|
|
const createMemoryIngestReviewsCreatedIndex = `
|
|
CREATE INDEX IF NOT EXISTS idx_memory_ingest_reviews_created_at
|
|
ON memory_ingest_reviews (created_at)`
|
|
|
|
// ensureIngestReviewSchema 幂等地创建入库前审查的留痕表与索引。
|
|
func ensureIngestReviewSchema(ctx context.Context, db *sql.DB) error {
|
|
for _, ddl := range []string{
|
|
createMemoryIngestReviewsTable,
|
|
createMemoryIngestReviewsItemIndex,
|
|
createMemoryIngestReviewsCreatedIndex,
|
|
} {
|
|
if _, err := db.ExecContext(ctx, ddl); err != nil {
|
|
return fmt.Errorf("memory: ingest review schema: %w", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|