From 5098139d7d8a4f93e6cf192e8c50bcf8a3602c3c Mon Sep 17 00:00:00 2001 From: cfdaily Date: Mon, 18 May 2026 23:22:58 +0800 Subject: [PATCH] auto-sync: 2026-05-18 23:22:58 --- src/blackboard/db.py | 61 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/blackboard/db.py b/src/blackboard/db.py index 1534aa7..689911b 100644 --- a/src/blackboard/db.py +++ b/src/blackboard/db.py @@ -18,6 +18,8 @@ def init_db(db_path: Path) -> None: _migrate_v261(conn) # v2.7 迁移:stages_json _migrate_v27(conn) + # v2.8 迁移:新状态 + 归档字段 + _migrate_v28(conn) conn.commit() finally: conn.close() @@ -45,7 +47,62 @@ def _migrate_v27(conn: sqlite3.Connection) -> None: _safe_add_column(conn, "tasks", "stage", "TEXT") -def _safe_add_column(conn: sqlite3.Connection, table: str, +def _migrate_v28(conn: sqlite3.Connection) -> None: + """v2.8 数据迁移:3 新状态 + 归档字段 + CHECK 约束更新""" + # 1. 添加归档字段 + _safe_add_column(conn, "tasks", "archived", "INTEGER DEFAULT 0") + _safe_add_column(conn, "tasks", "archived_at", "TEXT") + + # 2. CHECK 约束需要重建表(SQLite 不支持 ALTER CHECK) + # 先检查当前 CHECK 是否已包含新状态 + row = conn.execute( + "SELECT sql FROM sqlite_master WHERE type='table' AND name='tasks'" + ).fetchone() + if row and "paused" not in row["sql"]: + # 重建 tasks 表以更新 CHECK 约束 + conn.executescript(""" + CREATE TABLE tasks_v28 ( + id TEXT PRIMARY KEY, + title TEXT NOT NULL, + description TEXT, + status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','claimed','working','review','paused','escalated','waiting_human','done','failed','blocked','cancelled')), + assignee TEXT, + assigned_by TEXT, + depends_on TEXT, + parent_task TEXT, + priority INTEGER NOT NULL DEFAULT 5, + task_type TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now')), + updated_at TEXT NOT NULL DEFAULT (datetime('now')), + claimed_at TEXT, + started_at TEXT, + completed_at TEXT, + deadline TEXT, + retry_count INTEGER NOT NULL DEFAULT 0, + max_retries INTEGER NOT NULL DEFAULT 2, + must_haves TEXT, + risk_level TEXT DEFAULT 'standard', + estimated_duration_minutes INTEGER, + escalated INTEGER DEFAULT 0, + current_agent TEXT, + previous_agent TEXT, + next_capability TEXT, + stage TEXT, + stages_json TEXT DEFAULT '[]', + archived INTEGER DEFAULT 0, + archived_at TEXT + ); + INSERT INTO tasks_v28 SELECT * FROM tasks; + DROP TABLE tasks; + ALTER TABLE tasks_v28 RENAME TO tasks; + """) + # 重建索引 + conn.executescript(""" + CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status); + CREATE INDEX IF NOT EXISTS idx_tasks_assignee ON tasks(assignee); + CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_task); + CREATE INDEX IF NOT EXISTS idx_tasks_current_agent ON tasks(current_agent); + """) column: str, col_type: str) -> None: """安全添加列(已存在则跳过)""" try: @@ -143,7 +200,7 @@ _SCHEMA_STATEMENTS = [ id TEXT PRIMARY KEY, title TEXT NOT NULL, description TEXT, - status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','claimed','working','review','done','failed','blocked','cancelled')), + status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','claimed','working','review','paused','escalated','waiting_human','done','failed','blocked','cancelled')), assignee TEXT, assigned_by TEXT, depends_on TEXT,