auto-sync: 2026-05-17 00:42:06

This commit is contained in:
cfdaily
2026-05-17 00:42:06 +08:00
parent ed191c11eb
commit 867b096b4f
+160 -189
View File
@@ -12,7 +12,8 @@ def init_db(db_path: Path) -> None:
db_path.parent.mkdir(parents=True, exist_ok=True)
conn = _connect(db_path)
try:
conn.executescript(SCHEMA_SQL)
for stmt in _SCHEMA_STATEMENTS:
conn.execute(stmt)
conn.commit()
finally:
conn.close()
@@ -90,203 +91,173 @@ ATTEMPT_OUTCOMES = frozenset({
# ---------------------------------------------------------------------------
# Schema SQL
# Schema - split into individual statements to avoid SQLite 3.51 CHECK bug
# (table-level CHECK as non-last column definition causes parse error)
# ---------------------------------------------------------------------------
SCHEMA_SQL = """
-- ===== 任务表 =====
CREATE TABLE IF NOT EXISTS tasks (
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')),
_SCHEMA_STATEMENTS = [
# tasks
"""CREATE TABLE IF NOT EXISTS tasks (
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')),
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
)""",
"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)",
assignee TEXT,
assigned_by TEXT,
# comments
"""CREATE TABLE IF NOT EXISTS comments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL REFERENCES tasks(id),
author TEXT NOT NULL,
comment_type TEXT NOT NULL DEFAULT 'general' CHECK (comment_type IN ('general','handoff','observation','rebuttal','rebuttal_response','debate_argument','debate_rebuttal','debate_judgment')),
body TEXT NOT NULL,
mentions TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)""",
"CREATE INDEX IF NOT EXISTS idx_comments_task ON comments(task_id)",
"CREATE INDEX IF NOT EXISTS idx_comments_type ON comments(task_id, comment_type)",
"CREATE INDEX IF NOT EXISTS idx_comments_author ON comments(author)",
depends_on TEXT,
parent_task TEXT,
# outputs
"""CREATE TABLE IF NOT EXISTS outputs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL REFERENCES tasks(id),
agent TEXT NOT NULL,
output_type TEXT NOT NULL CHECK (output_type IN ('code','document','data','config','other')),
title TEXT NOT NULL,
content_path TEXT,
summary TEXT,
metadata TEXT,
attempt_number INTEGER DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)""",
"CREATE INDEX IF NOT EXISTS idx_outputs_task ON outputs(task_id)",
priority INTEGER NOT NULL DEFAULT 5,
task_type TEXT,
# decisions
"""CREATE TABLE IF NOT EXISTS decisions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL REFERENCES tasks(id),
decider TEXT NOT NULL,
decision TEXT NOT NULL,
rationale TEXT NOT NULL,
alternatives TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)""",
"CREATE INDEX IF NOT EXISTS idx_decisions_task ON decisions(task_id)",
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,
# observations
"""CREATE TABLE IF NOT EXISTS observations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL REFERENCES tasks(id),
observer TEXT NOT NULL,
severity TEXT NOT NULL DEFAULT 'info' CHECK (severity IN ('blocking','warning','info','audit')),
body TEXT NOT NULL,
resolved_by TEXT,
resolved_at TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)""",
retry_count INTEGER NOT NULL DEFAULT 0,
max_retries INTEGER NOT NULL DEFAULT 2,
# events
"""CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT,
agent TEXT,
event_type TEXT NOT NULL,
detail TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)""",
"CREATE INDEX IF NOT EXISTS idx_events_task ON events(task_id)",
"CREATE INDEX IF NOT EXISTS idx_events_time ON events(created_at)",
must_haves TEXT,
risk_level TEXT DEFAULT 'standard',
estimated_duration_minutes INTEGER,
# agents
"""CREATE TABLE IF NOT EXISTS agents (
agent_id TEXT PRIMARY KEY,
role TEXT,
current_status TEXT DEFAULT 'idle',
current_task TEXT,
last_active TEXT,
capabilities TEXT
)""",
escalated INTEGER DEFAULT 0
);
# task_attempts
"""CREATE TABLE IF NOT EXISTS task_attempts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL REFERENCES tasks(id),
attempt_number INTEGER NOT NULL,
agent TEXT NOT NULL,
outcome TEXT NOT NULL CHECK (outcome IN ('completed','blocked','crashed','timed_out','spawn_failed','reclaimed')),
exit_code INTEGER,
log_path TEXT,
summary TEXT,
metadata TEXT,
started_at TEXT NOT NULL DEFAULT (datetime('now')),
completed_at TEXT
)""",
"CREATE INDEX IF NOT EXISTS idx_attempts_task ON task_attempts(task_id)",
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);
# reviews
"""CREATE TABLE IF NOT EXISTS reviews (
id TEXT PRIMARY KEY,
task_id TEXT NOT NULL REFERENCES tasks(id),
output_id TEXT,
reviewer TEXT NOT NULL,
review_type TEXT NOT NULL CHECK (review_type IN ('plan_review','output_review','guardrail','final_review')),
verdict TEXT NOT NULL CHECK (verdict IN ('approved','rejected','needs_revision')),
confidence REAL,
round INTEGER NOT NULL DEFAULT 1,
max_rounds INTEGER NOT NULL DEFAULT 3,
consensus_reached INTEGER DEFAULT 0,
summary TEXT NOT NULL,
detail_path TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)""",
"CREATE INDEX IF NOT EXISTS idx_reviews_task ON reviews(task_id)",
"CREATE INDEX IF NOT EXISTS idx_reviews_output ON reviews(output_id)",
-- ===== 评论线程表 =====
CREATE TABLE IF NOT EXISTS comments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL,
author TEXT NOT NULL,
comment_type TEXT NOT NULL DEFAULT 'general',
body TEXT NOT NULL,
mentions TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (task_id) REFERENCES tasks(id),
CHECK (comment_type IN ('general','handoff','observation','rebuttal','rebuttal_response','debate_argument','debate_rebuttal','debate_judgment'))
);
# experiences
"""CREATE TABLE IF NOT EXISTS experiences (
experience_id TEXT PRIMARY KEY,
source TEXT NOT NULL CHECK (source IN ('task_completion','error_correction','review_finding','manual')),
task_id TEXT,
summary TEXT NOT NULL,
category TEXT NOT NULL CHECK (category IN ('pitfall','best_practice','pattern','anti_pattern')),
confidence REAL DEFAULT 0.8,
status TEXT DEFAULT 'active' CHECK (status IN ('draft','active','deprecated')),
skill_id TEXT,
usage_count INTEGER DEFAULT 0,
last_used_at TEXT,
created_at TEXT NOT NULL,
created_by TEXT NOT NULL,
updated_at TEXT,
deprecated_reason TEXT
)""",
CREATE INDEX IF NOT EXISTS idx_comments_task ON comments(task_id);
CREATE INDEX IF NOT EXISTS idx_comments_type ON comments(task_id, comment_type);
CREATE INDEX IF NOT EXISTS idx_comments_author ON comments(author);
-- ===== 产出表 =====
CREATE TABLE IF NOT EXISTS outputs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL,
agent TEXT NOT NULL,
output_type TEXT NOT NULL,
title TEXT NOT NULL,
content_path TEXT,
summary TEXT,
metadata TEXT,
attempt_number INTEGER DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (task_id) REFERENCES tasks(id),
CHECK (output_type IN ('code','document','data','config','other'))
);
CREATE INDEX IF NOT EXISTS idx_outputs_task ON outputs(task_id);
-- ===== 决策记录表 =====
CREATE TABLE IF NOT EXISTS decisions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL,
decider TEXT NOT NULL,
decision TEXT NOT NULL,
rationale TEXT NOT NULL,
alternatives TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (task_id) REFERENCES tasks(id)
);
CREATE INDEX IF NOT EXISTS idx_decisions_task ON decisions(task_id);
-- ===== 观察表 =====
CREATE TABLE IF NOT EXISTS observations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL,
observer TEXT NOT NULL,
severity TEXT NOT NULL DEFAULT 'info',
CHECK (severity IN ('blocking','warning','info','audit')),
body TEXT NOT NULL,
resolved_by TEXT,
resolved_at TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (task_id) REFERENCES tasks(id)
);
-- ===== 事件日志 =====
CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT,
agent TEXT,
event_type TEXT NOT NULL,
detail TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_events_task ON events(task_id);
CREATE INDEX IF NOT EXISTS idx_events_time ON events(created_at);
-- ===== Agent 注册表 =====
CREATE TABLE IF NOT EXISTS agents (
agent_id TEXT PRIMARY KEY,
role TEXT,
current_status TEXT DEFAULT 'idle',
current_task TEXT,
last_active TEXT,
capabilities TEXT
);
-- ===== 任务尝试记录 =====
CREATE TABLE IF NOT EXISTS task_attempts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id TEXT NOT NULL,
attempt_number INTEGER NOT NULL,
agent TEXT NOT NULL,
outcome TEXT NOT NULL,
CHECK (outcome IN ('completed','blocked','crashed','timed_out','spawn_failed','reclaimed')),
exit_code INTEGER,
log_path TEXT,
summary TEXT,
metadata TEXT,
started_at TEXT NOT NULL DEFAULT (datetime('now')),
completed_at TEXT,
FOREIGN KEY (task_id) REFERENCES tasks(id)
);
CREATE INDEX IF NOT EXISTS idx_attempts_task ON task_attempts(task_id);
-- ===== 评审表 =====
CREATE TABLE IF NOT EXISTS reviews (
id TEXT PRIMARY KEY,
task_id TEXT NOT NULL,
output_id TEXT,
reviewer TEXT NOT NULL,
review_type TEXT NOT NULL,
CHECK (review_type IN ('plan_review','output_review','guardrail','final_review')),
verdict TEXT NOT NULL,
CHECK (verdict IN ('approved','rejected','needs_revision')),
confidence REAL,
round INTEGER NOT NULL DEFAULT 1,
max_rounds INTEGER NOT NULL DEFAULT 3,
consensus_reached INTEGER DEFAULT 0,
summary TEXT NOT NULL,
detail_path TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (task_id) REFERENCES tasks(id)
);
CREATE INDEX IF NOT EXISTS idx_reviews_task ON reviews(task_id);
CREATE INDEX IF NOT EXISTS idx_reviews_output ON reviews(output_id);
-- ===== 经验表 =====
CREATE TABLE IF NOT EXISTS experiences (
experience_id TEXT PRIMARY KEY,
source TEXT NOT NULL,
CHECK (source IN ('task_completion','error_correction','review_finding','manual')),
task_id TEXT,
summary TEXT NOT NULL,
category TEXT NOT NULL,
CHECK (category IN ('pitfall','best_practice','pattern','anti_pattern')),
confidence REAL DEFAULT 0.8,
status TEXT DEFAULT 'active',
CHECK (status IN ('draft','active','deprecated')),
skill_id TEXT,
usage_count INTEGER DEFAULT 0,
last_used_at TEXT,
created_at TEXT NOT NULL,
created_by TEXT NOT NULL,
updated_at TEXT,
deprecated_reason TEXT
);
-- ===== 经验标签关联表 =====
CREATE TABLE IF NOT EXISTS experience_tags (
experience_id TEXT NOT NULL REFERENCES experiences(experience_id),
tag TEXT NOT NULL,
PRIMARY KEY (experience_id, tag)
);
CREATE INDEX IF NOT EXISTS idx_exptags_tag ON experience_tags(tag);
"""
# experience_tags
"""CREATE TABLE IF NOT EXISTS experience_tags (
experience_id TEXT NOT NULL REFERENCES experiences(experience_id),
tag TEXT NOT NULL,
PRIMARY KEY (experience_id, tag)
)""",
"CREATE INDEX IF NOT EXISTS idx_exptags_tag ON experience_tags(tag)",
]