# Workspace Curated Timeline Design

更新时间：2026-05-21

## 1. 背景

当前 workspace timeline 更接近 raw event feed：系统从 Jira issue status、Jira comments、task、DevOps operation/config change 中同步事件，然后按时间展示。

这个结果和人工整理的 incident timeline 有明显差距：

- 人工 timeline 聚焦关键 milestone，而不是逐条消息。
- 人工 timeline 会合并客户反馈、PingCAP 排查、根因判断、处理动作、恢复确认。
- 很多关键信息不一定来自系统数据源，例如首次告警时间、影响窗口、监控指标，需要人工录入。
- 紧急情况下，大家希望实时看到最新进展，不能等人工确认后才展示。

因此需要引入 curated timeline：

- 默认展示整理后的 timeline，而不是原始证据流。
- AI 自动生成实时 draft entry，默认可见。
- 人工可以确认、编辑、补充、隐藏、合并。
- 人工确认或编辑后的内容不能被 AI 自动覆盖。
- 原始证据流只在编辑模式中展示，用于追溯和辅助整理。

## 2. 设计原则

本设计按“先跑通闭环，再增强智能”的原则收敛：

- 第一版必须能端到端工作，而不是一次性引入完整 pipeline。
- 数据模型优先表达产品事实，不把复杂 AI 中间状态过早固化成表。
- AI 输出默认是 draft，可以展示，但不能覆盖人工内容。
- 人工编辑是最高优先级。
- 原始证据必须可追溯。
- 同步必须增量化，但允许保守重扫小窗口以换取正确性。
- 不靠关键词扩展解决事件识别，AI 负责结构化判断和信息增量判断。

## 3. 目标

- 默认页面展示一份实时可用的 curated timeline。
- AI 自动从新增 evidence 中生成 draft timeline entry。
- 人工可以新增、编辑、确认、隐藏、合并 timeline entry。
- 人工内容优先，AI 不能覆盖人工确认或人工编辑过的 entry。
- 支持每条 curated entry 关联原始 evidence。
- 支持人工录入系统无法自动获取的信息，例如告警时间、影响集群、影响窗口、监控表现。
- 同步与整理必须增量化，避免每次全量拉取 Jira comments 并全量重跑 AI。

## 4. 非目标

- 第一阶段不接入完整 monitoring 指标。
- 第一阶段接入 DevOps 已有 operation/config change 记录。
- 第一阶段不自动查询 TiKV live store 状态、AWS incident 细节。
- 如果 leader eviction 已记录在 DevOps operation/config change 中，第一阶段作为 DevOps evidence 同步；不从 live state 或 monitoring 自动推断。
- 第一阶段不建设完整 suggestions 系统。
- 第一阶段不持久化完整 atomic facts pipeline。
- 不保证 AI draft 完全准确；draft 是实时辅助，最终以人工确认和编辑内容为准。

## 5. 产品形态

### 5.1 默认视图

默认只展示 curated timeline：

```text
Workspace Detail
  Timeline
    7:54  客户侧 Slack 首次收到集群告警                         [AI draft]
    8:35  客户提单 ST-2663 反馈北美 saas01 问题                  [confirmed]
    8:57  PingCAP 内部检查 Wetech 主要集群状态                   [edited]
    20:31 PingCAP 同步 DDL 报错根因及三种临时解决方案             [AI draft]
```

默认展示：

- AI draft entry
- 人工确认 entry
- 人工编辑 entry

默认不展示：

- hidden entry
- superseded entry

draft entry 需要有轻量标记，例如 `AI draft` 或 `待确认`。

### 5.2 编辑视图

用户进入编辑模式后，展示双栏：

```text
左侧：Raw Evidence Stream
  - Jira comments
  - Slack mirrored comments
  - Jira status changes
  - Tasks
  - Manual notes

右侧：Curated Timeline
  - 可编辑 timeline entries
  - 可从左侧 evidence 绑定来源
  - 可确认或隐藏 AI draft
  - 可拖拽排序或编辑展示时间
```

编辑视图的核心动作：

- 新增人工 entry
- 编辑 entry
- 确认 AI draft
- 隐藏 AI draft
- 合并多个 entry
- 从 raw evidence 创建 entry
- 给 entry 绑定或解绑 evidence

拆分 entry 可以后置；第一版可通过人工新建 entry + 编辑原 entry 达成。

## 6. 核心概念

### 6.1 Evidence

原始证据。来自 Jira comment、Slack mirrored comment、Jira status、task、manual note 等。

特点：

- 用于追溯，不直接代表最终 timeline。
- 尽量保持原始内容。
- 通过 `content_hash` 做幂等和变更判断。

### 6.2 Timeline Entry

最终展示的 curated timeline entry。

来源可以是：

- AI draft
- 人工新增
- 人工编辑
- 系统迁移或导入

### 6.3 Sync State

每个 workspace/source/source_key 的同步水位，用于增量拉取。

例如：

- workspace 4 + Jira issue ST-2663
- workspace 4 + Lark chat oc_xxx

### 6.4 AI Draft Generation

第一版不强制持久化 atomic facts。AI 可以在一次调用中完成：

```text
new/changed evidence
  -> 判断是否有 timeline 价值
  -> 提取事实时间、主题、实体、摘要、细节
  -> 创建或更新 draft entry
```

为了调试和未来演进，AI 输出的结构化中间结果可以先放在 entry 的 `metadata_json` 中，而不是立即拆成独立表。

## 7. 数据模型

所有新增表统一使用 `workspace_timeline_` 前缀。

当前第一版建议只引入核心闭环需要的表：

- `workspace_timeline_evidence`
- `workspace_timeline_entries`
- `workspace_timeline_entry_evidence`
- `workspace_timeline_sync_states`
- `workspace_timeline_entry_revisions`

`workspace_timeline_entry_revisions` 可以和人工编辑能力同时引入。如果第一版需要更快落地，可以只记录最新状态，revision 在下一小步补上。

旧的 `workspace_timeline_events` legacy raw event 表在 curated timeline 迁移完成后应删除；curated timeline 不再依赖 `workspace_timeline_events` 的展示语义。

### 7.1 workspace_timeline_evidence

保存原始证据。

```sql
CREATE TABLE workspace_timeline_evidence (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  workspace_id BIGINT NOT NULL,
  source VARCHAR(64) NOT NULL,
  source_type VARCHAR(64) NOT NULL,
  source_key VARCHAR(512) NOT NULL,
  occurred_at DATETIME(3) NULL,
  observed_at DATETIME(3) NOT NULL,
  actor_id VARCHAR(255) NULL,
  actor_display_name VARCHAR(255) NULL,
  content LONGTEXT NULL,
  content_hash VARCHAR(128) NOT NULL,
  metadata_json JSON NOT NULL,
  created_at DATETIME(3) NOT NULL,
  updated_at DATETIME(3) NOT NULL,
  UNIQUE KEY uk_workspace_timeline_evidence_source (
    workspace_id,
    source,
    source_type,
    source_key
  ),
  KEY idx_workspace_timeline_evidence_workspace_time (
    workspace_id,
    occurred_at
  ),
  KEY idx_workspace_timeline_evidence_workspace_updated (
    workspace_id,
    updated_at
  )
);
```

字段说明：

- `source`: `jira`, `slack`, `lark`, `task`, `manual`, `system`
- `source_type`: `jira_comment`, `jira_status`, `slack_message`, `task_update`, `manual_note`
- `source_key`: 原始系统内唯一定位符，例如 `ST-2663/comment/22138624`
- `occurred_at`: 证据本身发生时间，例如 message created time
- `observed_at`: 系统观察到这条证据的时间
- `content_hash`: 用于判断内容是否变化
- `metadata_json`: 保存原始 source payload、issue key、comment id、message id 等扩展字段

### 7.2 workspace_timeline_entries

保存最终展示的 curated timeline entry。

```sql
CREATE TABLE workspace_timeline_entries (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  workspace_id BIGINT NOT NULL,
  occurred_at DATETIME(3) NOT NULL,
  sort_order INT NULL,
  title TEXT NOT NULL,
  details LONGTEXT NULL,
  event_kind VARCHAR(128) NULL,
  topic VARCHAR(255) NULL,
  entities_json JSON NOT NULL,
  status VARCHAR(64) NOT NULL,
  source VARCHAR(64) NOT NULL,
  confidence DECIMAL(5,4) NULL,
  superseded_by BIGINT NULL,
  metadata_json JSON NOT NULL,
  version BIGINT NOT NULL DEFAULT 1,
  created_by VARCHAR(255) NULL,
  updated_by VARCHAR(255) NULL,
  created_at DATETIME(3) NOT NULL,
  updated_at DATETIME(3) NOT NULL,
  KEY idx_workspace_timeline_entries_workspace_time (
    workspace_id,
    occurred_at
  ),
  KEY idx_workspace_timeline_entries_workspace_status (
    workspace_id,
    status
  )
);
```

`status` 取值：

- `draft`: AI 自动生成，默认可展示但标记为未确认。
- `confirmed`: 人工确认或人工创建。
- `hidden`: 人工隐藏，不默认展示。
- `superseded`: 被其他 entry 替代，不默认展示。

`source` 取值：

- `ai`
- `human`
- `system`

人工编辑不再单独作为 status，避免 `status` 和 `human_edited` boolean 互相矛盾。判断人工编辑用：

- `source = human`，表示人工创建。
- `updated_by` 非空且最近修改者是人，表示人工编辑过。
- `metadata_json.human_edited = true`，如果需要前端快速判断。

AI 覆盖保护以 `source/status/updated_by/metadata_json.human_edited` 综合判断：

- AI 可以直接更新 `source=ai AND status=draft` 的 entry。
- AI 不能直接更新 `source=human` 的 entry。
- AI 不能直接更新 `metadata_json.human_edited=true` 的 entry。
- 对人工内容只能创建新的 draft 或在 metadata 中记录建议，第一版不做独立 suggestion 表。

### 7.3 workspace_timeline_entry_evidence

保存 curated entry 与 evidence 的关联。

```sql
CREATE TABLE workspace_timeline_entry_evidence (
  entry_id BIGINT NOT NULL,
  evidence_id BIGINT NOT NULL,
  relation VARCHAR(64) NOT NULL,
  created_at DATETIME(3) NOT NULL,
  PRIMARY KEY (entry_id, evidence_id),
  KEY idx_workspace_timeline_entry_evidence_evidence (
    evidence_id
  )
);
```

`relation` 取值：

- `primary`: 主要证据
- `supporting`: 支撑证据
- `conflicting`: 冲突证据

### 7.4 workspace_timeline_sync_states

保存增量同步水位。

```sql
CREATE TABLE workspace_timeline_sync_states (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  workspace_id BIGINT NOT NULL,
  source VARCHAR(64) NOT NULL,
  source_key VARCHAR(512) NOT NULL,
  last_seen_updated_at DATETIME(3) NULL,
  last_seen_cursor VARCHAR(512) NULL,
  last_seen_content_hash VARCHAR(128) NULL,
  metadata_json JSON NOT NULL,
  created_at DATETIME(3) NOT NULL,
  updated_at DATETIME(3) NOT NULL,
  UNIQUE KEY uk_workspace_timeline_sync_state (
    workspace_id,
    source,
    source_key
  )
);
```

`metadata_json` 建议保存：

- last seen issue updated_at
- last seen comment updated_at
- last seen comment id
- last full reconciliation time
- last sync error

### 7.5 workspace_timeline_entry_revisions

保存 entry 修改历史，用于审计和回滚。

```sql
CREATE TABLE workspace_timeline_entry_revisions (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  entry_id BIGINT NOT NULL,
  workspace_id BIGINT NOT NULL,
  changed_by VARCHAR(255) NOT NULL,
  change_type VARCHAR(64) NOT NULL,
  before_json JSON NULL,
  after_json JSON NULL,
  created_at DATETIME(3) NOT NULL,
  KEY idx_workspace_timeline_entry_revisions_entry (
    entry_id
  ),
  KEY idx_workspace_timeline_entry_revisions_workspace (
    workspace_id
  )
);
```

第一版至少记录人工修改和 confirm/hide 动作。AI draft 自动更新可以只记录最新结果，等需要调试时再扩大 revision 范围。

## 8. 后置扩展表

以下表不进入 MVP，除非第一版验证后确实需要。

### 8.1 workspace_timeline_atomic_facts

当需要稳定评估 extraction 质量、复用 facts、或做复杂 merge/split 时，再引入 atomic facts 表。

如果引入，需要解决幂等问题：

```sql
CREATE TABLE workspace_timeline_atomic_facts (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  workspace_id BIGINT NOT NULL,
  evidence_id BIGINT NOT NULL,
  fact_index INT NOT NULL,
  occurred_at DATETIME(3) NULL,
  occurred_at_source VARCHAR(64) NOT NULL,
  event_kind VARCHAR(128) NOT NULL,
  topic VARCHAR(255) NULL,
  entities_json JSON NOT NULL,
  summary TEXT NOT NULL,
  details TEXT NULL,
  confidence DECIMAL(5,4) NOT NULL,
  is_timeline_worthy BOOLEAN NOT NULL,
  extraction_version VARCHAR(128) NOT NULL,
  source_content_hash VARCHAR(128) NOT NULL,
  created_at DATETIME(3) NOT NULL,
  updated_at DATETIME(3) NOT NULL,
  UNIQUE KEY uk_workspace_timeline_atomic_fact_version (
    evidence_id,
    source_content_hash,
    extraction_version,
    fact_index
  ),
  KEY idx_workspace_timeline_atomic_facts_workspace_time (
    workspace_id,
    occurred_at
  )
);
```

也可以采用更简单的策略：每次对同一个 `evidence_id + content_hash + extraction_version` delete-and-recreate。

### 8.2 workspace_timeline_suggestions

第一版不做通用 suggestions 表。AI 直接生成 draft entry，人工 Confirm/Edit/Hide。

当需要对 confirmed/human content 提供旁路建议时，再引入：

- create suggestion
- update suggestion
- merge suggestion
- split suggestion
- hide suggestion

这类表必须有明确 payload schema，不能只放一个无限泛化的 `payload_json`。否则 accept 逻辑会变得难维护。

### 8.3 workspace_timeline_dirty_scopes

第一版可以不建 dirty scope 表，用 job payload 或内存队列表达 dirty range。

只有在需要持久化重试、跨进程调度、或大量 workspace 并发时，再引入 dirty scope 表。

## 9. Entry 状态机

```text
AI creates entry
  -> draft

draft
  -> confirmed     人工确认
  -> hidden        人工隐藏
  -> superseded    被后续 draft 或 confirmed entry 替代

confirmed
  -> confirmed     人工继续编辑，仍保持 confirmed
  -> hidden        人工隐藏
  -> superseded    人工选择替代

hidden
  -> confirmed     人工恢复

superseded
  -> 通常不恢复；必要时人工复制为新 entry
```

默认展示条件：

```text
status in (draft, confirmed)
and superseded_by is null
```

排序规则：

```text
ORDER BY occurred_at ASC, sort_order ASC, id ASC
```

第一版建议弱化任意拖拽排序：

- 推荐通过编辑 `occurred_at` 修正事实时间。
- `sort_order` 只解决同一时间点或近似时间点的展示顺序。
- 如果未来要支持完全人工排序，需要新增 `sort_at` 或明确 `sort_order` 优先级高于 `occurred_at`。

## 10. 增量同步设计

当前全量同步的问题：

- 每次拉取所有 issue comments，浪费 Jira API quota。
- 每次全量重跑 timeline 生成，浪费模型 token。
- 全量重跑容易影响人工编辑过的内容。

目标链路：

```text
Sync workspace
  -> list bound issues/resources
  -> check workspace_timeline_sync_states
  -> fetch lightweight metadata
  -> fetch changed comments with overlap/reconciliation
  -> upsert workspace_timeline_evidence
  -> generate AI drafts for new/changed evidence
```

### 10.1 Jira issue 同步

对每个 bound Jira issue，先拉 lightweight metadata：

- issue key
- status
- updated_at
- resolved_at
- summary
- priority
- comment_count，如果 Jira API 支持

判断逻辑：

```text
if issue.updated_at <= sync_state.last_seen_updated_at:
  skip comments
else:
  fetch changed comments with overlap
```

### 10.2 Comment 增量拉取

不能简单采用“从最新 comment 往前拉，遇到第一个 hash 未变化就停止”的策略。这个策略会漏掉较早 comment 被编辑的情况。

推荐策略：

1. 如果 Jira API 支持按 comment `updated_at` 增量查询，优先使用。
2. 如果不支持，则从最新 comment page 往前扫描到 overlap window：
   - overlap 起点为 `last_seen_comment_updated_at - 24h`，具体窗口可配置。
   - 对窗口内 comments 全部计算 hash 并 upsert。
   - 不因遇到第一个 unchanged comment 就停止。
3. 对 active workspace，定期做小规模 reconciliation：
   - 例如每 1 小时重扫最近 24 小时 comments。
   - resolved workspace 降低频率。

这样会比“遇到 unchanged 即停”多消耗少量 API，但能显著降低漏数据风险。

### 10.3 Evidence upsert

dedup key：

```text
workspace_id + source + source_type + source_key
```

Jira comment 示例：

```text
source = jira
source_type = jira_comment
source_key = ST-2663/comment/22138624
```

只有新增 evidence 或 `content_hash` 变化时，才触发 AI draft generation。

## 11. AI Draft Generation

第一版不要求持久化 atomic facts。AI 输入一批新增或变化的 evidence，并输出 draft entry candidates。

输入：

```json
{
  "workspace_id": 4,
  "existing_entries": [
    {
      "id": 101,
      "occurred_at": "2026-05-08T08:35:00+08:00",
      "title": "客户提单 ST-2663 反馈北美 saas01 问题",
      "status": "confirmed",
      "source": "human"
    }
  ],
  "new_evidence": [
    {
      "id": 123,
      "source_type": "jira_comment",
      "posted_at": "2026-05-08T02:08:43Z",
      "actor": "kaixing.yang@pingcap.com",
      "content": "20260508 9:10 确认 wallet 没有受影响，SaaS 01、03、05 逐渐恢复。"
    }
  ]
}
```

输出：

```json
{
  "draft_entries": [
    {
      "action": "create",
      "occurred_at": "2026-05-08T09:10:00+08:00",
      "event_kind": "recovery_observed",
      "topic": "cluster recovery",
      "entities": ["wallet", "SaaS01", "SaaS03", "SaaS05"],
      "title": "Wallet 基本未受影响，SaaS01、SaaS03、SaaS05 逐渐恢复。",
      "details": "",
      "evidence_ids": [123],
      "confidence": 0.86
    }
  ]
}
```

AI 判断 timeline-worthy 的标准：

- 新增时间点
- 新增影响对象
- 新增状态变化
- 新增根因判断
- 新增处理动作
- 新增恢复确认
- 新增 workaround
- 新增客户影响或业务反馈
- 新增下一步决策

非 timeline-worthy 的消息仍保存在 evidence 中，但不创建 draft entry：

- 纯确认回复
- 纯 mention
- 纯会议链接
- 没有新增事实的重复表达
- 已被附近 entry 完全覆盖的消息

## 12. Draft 归并策略

第一版只允许 AI 自动更新 AI draft，不自动更新人工内容。

对每个新 draft candidate，寻找 candidate entries：

```text
same workspace
status = draft
source = ai
not superseded
occurred_at within configurable window
```

默认时间窗口：

- 普通讨论：前后 30 分钟
- 高频 incident：前后 10 分钟
- 长耗时阶段，例如 DDL workaround：前后 60 分钟

匹配维度：

- topic 是否相似
- entities 是否重叠
- event_kind 是否兼容
- 时间是否接近
- evidence 是否来自同一个 issue/thread

处理策略：

```text
high confidence match:
  update existing AI draft

uncertain match:
  create new AI draft

matches confirmed or human-created entry:
  do not update
  optionally attach evidence as unreviewed metadata, or skip in MVP
```

后续如果需要对 confirmed entry 给建议，再引入 suggestions 系统。

## 13. AI 覆盖保护

AI 更新规则：

```text
target status = draft AND source = ai:
  AI 可以直接更新、合并或 supersede

target status = confirmed:
  AI 不能直接改正文

target source = human:
  AI 不能直接改正文

target metadata_json.human_edited = true:
  AI 不能直接改正文

target status = hidden:
  AI 不再基于同一 evidence 重建 entry
```

需要记录：

- entry 使用的 evidence ids
- source content hash
- prompt/schema version
- AI raw output 或摘要，保存在 `metadata_json`

这样可以避免同一批 evidence 反复生成重复 draft，也方便排查 AI 输出问题。

## 14. API 设计

### 14.1 默认展示 curated timeline

```http
GET /api/v1/ticketmanager/workspace/workspaces/{id}/curated-timeline
```

Query：

- `include_drafts=true`
- `include_hidden=false`
- `include_evidence=false`

Response：

```json
{
  "entries": [
    {
      "id": 1,
      "workspace_id": 4,
      "occurred_at": "2026-05-08T00:35:00Z",
      "title": "客户提单 ST-2663 反馈北美 saas01 问题",
      "details": "",
      "status": "confirmed",
      "source": "human",
      "event_kind": "ticket_created",
      "evidence_count": 2,
      "version": 3
    }
  ]
}
```

### 14.2 人工新增 entry

```http
POST /api/v1/ticketmanager/workspace/workspaces/{id}/curated-timeline
```

创建结果：

- `status = confirmed`
- `source = human`
- `metadata_json.human_edited = true`

### 14.3 人工编辑 entry

```http
PATCH /api/v1/ticketmanager/workspace/curated-timeline/{entry_id}
```

需要 optimistic lock：

- request 带 `version`。
- 成功后 `version = version + 1`。
- 如果版本冲突，返回 conflict。

人工编辑后：

- 保持或转为 `status = confirmed`。
- 设置 `metadata_json.human_edited = true`。
- 写入 revision。

### 14.4 确认 draft

```http
POST /api/v1/ticketmanager/workspace/curated-timeline/{entry_id}/confirm
```

确认后：

- `status = confirmed`
- `source` 可以保留 `ai`，表示最初由 AI 创建。
- `updated_by` 记录确认人。
- `metadata_json.confirmed_by` 记录确认人。

### 14.5 隐藏 entry

```http
POST /api/v1/ticketmanager/workspace/curated-timeline/{entry_id}/hide
```

隐藏后：

- `status = hidden`
- 不默认展示。
- 同一 evidence 不应立即重新生成同样 draft。

### 14.6 Evidence stream

```http
GET /api/v1/ticketmanager/workspace/workspaces/{id}/timeline-evidence
```

Query：

- `source`
- `source_type`
- `issue_key`
- `actor`
- `start`
- `end`
- `bound=true|false`

### 14.7 手动刷新

```http
POST /api/v1/ticketmanager/workspace/workspaces/{id}/timeline-sync
```

### 14.8 重新生成草稿

```http
POST /api/v1/ticketmanager/workspace/workspaces/{id}/curated-timeline/regenerate
```

默认规则：

- 可以重新生成 draft。
- 可以 supersede 旧 draft。
- 不能覆盖 confirmed entry。
- 不能覆盖 human-created / human-edited entry。

## 15. UI 设计

### 15.1 默认 timeline 页

能力：

- 展示 curated entries。
- draft entry 显示 `AI draft`。
- 顶部提示：`包含未确认的自动整理内容`。
- 每条 draft 快捷操作：`Confirm` / `Edit` / `Hide`。
- 人工 entry 不显示 AI confidence，避免误导。

### 15.2 编辑模式

左侧 evidence stream：

- 按 source、issue、时间、actor 过滤。
- 支持查看原始内容。
- 支持查看是否已绑定到 entry。
- 支持选择多条 evidence 创建或补充 entry。

右侧 curated timeline：

- 新增 entry。
- 编辑 entry。
- 绑定或解绑 evidence。
- 确认或隐藏 AI draft。
- 合并 entry。
- 编辑事实时间。
- 同一时间点内调整顺序。

人工补充场景：

- 告警首次出现时间。
- 影响集群列表。
- 每个集群影响窗口。
- duration / QPS / 连接数表现。
- 根因结论。
- mitigation 操作。
- 客户恢复确认时间。

## 16. 后台任务

MVP 只需要两类任务：

```text
workspace-timeline-sync-job
  拉取 metadata/comments
  upsert evidence
  更新 sync state
  触发 draft generation

workspace-timeline-draft-job
  对新增或变化 evidence 生成 AI draft
  只更新 AI draft
  不覆盖人工内容
```

后续再拆：

```text
workspace-timeline-extract-job
workspace-timeline-synthesis-job
workspace-timeline-cleanup-job
```

触发频率：

- active workspace：1-5 分钟。
- resolved workspace：低频，例如 1 小时，或只手动刷新。
- closed workspace：停止自动同步。

## 17. 资源控制

同步侧：

- 先拉 lightweight metadata。
- `updated_at` 未变化则不拉 comments。
- comments 使用 overlap window 或 comment updated_at 增量，不用“遇到第一个 unchanged 即停”。
- evidence 通过唯一键幂等 upsert。

AI 侧：

- 只对新增或 `content_hash` 变化的 evidence 生成 draft。
- AI 结果按 `evidence_ids + content_hashes + prompt_version` 在 metadata 中记录。
- draft generation 只传附近 entries，不传整个 case。
- full regenerate 只在首次 backfill 或用户手动触发时运行。
- full regenerate 也不能覆盖人工内容。

并发和限流：

- 每个 workspace 同一时间只允许一个 sync job。
- 每个 workspace 同一时间只允许一个 draft job。
- 对长 case 分 chunk 处理。
- 设置每轮最大 evidence 数、最大 token 数、最大 draft entries 数。

## 18. 失败处理

- Jira 拉取失败：保留旧 curated timeline，记录 sync error。
- evidence upsert 失败：本轮 sync 失败，可重试。
- AI draft generation 失败：evidence 已入库，稍后重试。
- 人工编辑失败：事务回滚。
- 并发编辑冲突：返回 conflict，让前端提示刷新。

## 19. 权限与审计

需要记录：

- 谁创建了人工 entry。
- 谁编辑了 entry。
- 谁确认了 draft。
- 谁隐藏了 draft。
- entry 修改前后的快照。

所有人工可见内容的修改都写入 `workspace_timeline_entry_revisions`。

## 20. 评估方案

使用人工整理 timeline 作为 golden set。

评估指标：

- 关键 milestone 召回率。
- 噪声 entry 比例。
- 时间准确率。
- 合并合理性。
- 人工编辑量。
- draft 到 confirmed 的接受率。
- AI 覆盖人工内容次数，必须为 0。

第一批建议选 10-20 个真实 case，对比：

- 当前 raw timeline。
- AI draft curated timeline。
- 人工最终 timeline。

## 21. 分阶段落地

### Phase 1: 可用闭环

目标：默认页面能展示 curated timeline，人工能编辑，AI draft 能实时出现。

范围：

- 新增 `workspace_timeline_evidence`。
- 新增 `workspace_timeline_entries`。
- 新增 `workspace_timeline_entry_evidence`。
- 新增 `workspace_timeline_sync_states`。
- 可选新增 `workspace_timeline_entry_revisions`。
- Jira issue/comment 增量同步到 evidence。
- DevOps operation/config change 增量同步到 evidence。
- AI 从新增 evidence 生成 draft entries。
- 默认页展示 `draft + confirmed`。
- 支持人工新增、编辑、确认、隐藏。
- AI 不覆盖人工内容。

### Phase 2: 可靠性与审计

目标：提升同步正确性、并发安全和可追溯性。

范围：

- 完整引入 `workspace_timeline_entry_revisions`。
- 增量同步 reconciliation。
- optimistic lock。
- sync error 可观测。
- draft generation debug metadata。
- 初步 golden cases 评估。

### Phase 3: 更强的 AI 整理

目标：提升 AI 归并质量，但不破坏 Phase 1 的简单闭环。

可选范围：

- 引入 `workspace_timeline_atomic_facts`。
- 引入更明确的 draft merge/supersede 策略。
- 对 confirmed/human entry 提供旁路建议。
- 如确有需要，再设计 `workspace_timeline_suggestions`。

### Phase 4: 高级编辑体验

目标：提升人工整理效率。

可选范围：

- 批量 evidence 绑定。
- entry split UI。
- richer diff。
- 完整 suggestions accept/reject。
- 更多 source 接入。

## 22. 核心决策

- 默认展示 curated timeline，而不是 raw event feed。
- AI draft 默认可见，满足紧急情况下实时查看最新进展。
- 第一版不建设完整 suggestions 和 atomic facts pipeline。
- 第一版只做能跑通的核心闭环。
- 人工确认和人工编辑是最高优先级。
- AI 只能直接更新 AI draft，不能覆盖人工内容。
- 原始证据流只在编辑模式中展示。
- 不靠关键词扩展解决事件识别，而靠结构化判断和信息增量判断。
- monitoring 指标和 TiKV live state 第一阶段不接入，缺失事实允许人工录入。
- DevOps 已有 operation/config change 记录第一阶段接入，并作为 evidence 参与 AI draft generation。
- 同步与生成都必须增量化，避免全量拉取和全量重跑。
- 所有新增 timeline 相关表统一使用 `workspace_timeline_` 前缀。
