新增: 知识图谱Phase2事件流(父⑥) — project_events统一事件流+埋点+timeline

父⑥ Phase 2(对标设计 §2.4):
- V30 迁移:project_events 追加型审计表(id/project_id/event_type/entity_type/entity_id/from_state/to_state/context_json/source/conversation_id/created_at)+ 双索引(project,time / entity)
- ProjectEventRecord + ProjectEventRepo(insert 追加型/get_by_project/get_by_entity/list_recent)
- 事件埋点(best-effort,hook/after,失败 warn 不阻断主操作):
  - task.rs emit_event 辅助 + create_task/advance_task/move_task_queue 埋点
  - idea.rs promote_idea 埋点(idea_promoted,project_id=新项目)
  - project.rs create/delete 埋点
  - 注:idea_created 暂不埋点(idea 无 project_id,待 Inbox 项目落地,NOT NULL+FK 约束)
- get_project_timeline IPC(events 模块)+ lib.rs 注册 + AI 工具(基线 +N)
- source 语义:IPC 标 human,AI 工具路径标 ai

注:workflow 脚本中文变量名 const 致验证 agent 未跑,主控独立 cargo check EXIT 0 + grep 落地齐全核验。
This commit is contained in:
2026-06-27 00:23:17 +08:00
parent 744b68da5b
commit 5a893680b7
12 changed files with 853 additions and 20 deletions

View File

@@ -37,7 +37,10 @@ pub fn run(conn: &Connection) -> Result<()> {
// 项目知识图谱与任务队列系统-2026-06-26.md §2.1/§2.2):tasks 加 queue(管理池)/
// parent_id(父任务纵向关联)/content_json(结构化需求规格)三列 + task_links 表
// (横向关联 depends_on/blocks/relates_to),为 AI 编排地基打底。
let steps: [(i32, fn(&Connection) -> Result<()>); 29] = [
// V30 = 知识图谱 Phase 2 统一事件流(对标设计 §2.4):project_events 追加型审计表,
// 跨实体(idea/task/workflow/knowledge/module/service/project)事件流,AI 精准检索
// 的基础(回答"上周做了什么/这个任务为何 blocked/决策何时做出")。
let steps: [(i32, fn(&Connection) -> Result<()>); 30] = [
(1, migrate_v1),
(2, migrate_v2),
(3, migrate_v3),
@@ -67,6 +70,7 @@ pub fn run(conn: &Connection) -> Result<()> {
(27, migrate_v27),
(28, migrate_v28),
(29, migrate_v29),
(30, migrate_v30),
];
for (version, migrate_fn) in steps {
@@ -773,6 +777,74 @@ fn migrate_v29(conn: &Connection) -> Result<()> {
Ok(())
}
/// V30:知识图谱 Phase 2 统一事件流 — project_events 追加型审计表
///
/// 对标 docs/02-架构设计/专项设计/项目知识图谱与任务队列系统-2026-06-26.md §2.4,
/// 为「AI 精准检索项目事件流」打数据层地基。一张表承载跨实体(idea/task/workflow/
/// knowledge/module/service/project)的全部事件,回答"上周做了什么 / 这个任务为何 blocked /
/// 这个决策何时做出"——此前需跨 6 张表 JOIN。
///
/// **追加型审计表**(对标 knowledge_events V10 / idea_evaluations V22):只 INSERT 不 UPDATE/
/// DELETE,历史不改可追溯。故表无 updated_at,无通用 update/delete 路径,无列白名单登记
/// (ProjectEventRepo 走专用方法,与 TaskLinkRepo 同款全专用路径)。
///
/// **与 knowledge_events 的关系**(对标设计 D9 / §2.4):knowledge_events 保持不变(知识库专属,
/// 向后兼容),project_events 是全局事件流;knowledge 相关事件**同时写入两者**——本表只管写入,
/// 双写策略在埋点层(commands/IPC hook)实现,非本表职责。
///
/// 列语义(对标设计 §2.4):
/// - `event_type`:事件类型白名单(idea_created/idea_promoted/...task_created/task_advanced/
/// .../decision_made 等,见设计 §2.4 注释枚举)。白名单**应用层校验**(类比 task_links
/// link_type),不进 DB 约束(保留扩展性,新增事件类型无需迁移)。
/// - `entity_type` / `entity_id`:事件指向的实体(可空——部分事件无明确实体,如纯决策日志)。
/// entity_type 白名单同样应用层校验(idea/project/task/workflow/knowledge/module/service)。
/// - `from_state` / `to_state`:状态变化前后(仅状态变化类事件有值,如 task_advanced;
/// created/referenced 类为 NULL)。
/// - `context_json`:事件附加上下文(JSON 字符串,因 event_type 而异)。
/// - `source`:ai / human / system(AI Working 溯源——区分是 AI 自主操作还是人操作)。
/// - `conversation_id`:触发事件的对应对话(AI Working 溯源链:事件→对话→决策,可空)。
///
/// **埋点策略**(设计 §2.4 hook/after):在现有 IPC 命令(create_task/advance_task/create_project
/// /idea_promote 等)执行后追加事件写入,不侵入业务逻辑。事件写入失败 best-effort 不阻断主操作
/// (设计 §10.1 风险已识别),由埋点层实现,非本表职责。
///
/// **CREATE TABLE IF NOT EXISTS 幂等**:新库建表、老库(V30 之前的库)已有则跳过,均安全。
/// 索引覆盖最高频查询:
/// - `idx_project_events_project(project_id, created_at)`:按项目查事件流(时间倒序,Dashboard 时间线)
/// - `idx_project_events_entity(entity_type, entity_id)`:按实体反查(AI「这个任务发生过什么」)
fn migrate_v30(conn: &Connection) -> Result<()> {
conn.execute(
"CREATE TABLE IF NOT EXISTS project_events (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL REFERENCES projects(id),
event_type TEXT NOT NULL,
entity_type TEXT,
entity_id TEXT,
from_state TEXT,
to_state TEXT,
context_json TEXT,
source TEXT,
conversation_id TEXT,
created_at TEXT NOT NULL
)",
[],
)?;
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_project_events_project \
ON project_events(project_id, created_at)",
[],
)?;
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_project_events_entity \
ON project_events(entity_type, entity_id)",
[],
)?;
tracing::info!("v30: 建 project_events 表 + 索引(统一事件流,知识图谱 Phase 2)");
conn.execute("INSERT INTO schema_version (version) VALUES (?)", [30])?;
tracing::info!("迁移 v30 完成");
Ok(())
}
/// V21 建表 SQL — 消息拆分存储 ai_messages 表
///
/// 与 V9_SQL 中的 ai_messages 镜像(V9 给新库,此 const 给老库 V21 迁移用 IF NOT EXISTS)。