diff --git a/apps/web/app/projects/[id]/page.tsx b/apps/web/app/projects/[id]/page.tsx
index 58517ea..d03010a 100644
--- a/apps/web/app/projects/[id]/page.tsx
+++ b/apps/web/app/projects/[id]/page.tsx
@@ -77,6 +77,15 @@ function VersionCard({ version, progress, plans, devTasks, testCases, bugs, requ
vTCs.forEach((c) => { if (c.startedAt) startDates.push(c.startedAt); });
const earliestStart = startDates.length > 0 ? startDates.sort()[0] : version.startDate;
+ const actualStartDisplay = startDates.length > 0 ? startDates.sort()[0].slice(0, 10) : (version.startDate ?? null);
+
+ // 实际截止:取所有阶段最晚完成
+ const endDates: string[] = [];
+ vPlans.forEach((p) => { if (p.completedAt) endDates.push(p.completedAt); });
+ vDevTasks.forEach((t) => { if (t.completedAt) endDates.push(t.completedAt); });
+ vTCs.forEach((c) => { if (c.completedAt) endDates.push(c.completedAt); });
+ vBugs.forEach((b) => { if (b.closedAt) endDates.push(b.closedAt); });
+ const actualEndDisplay = endDates.length > 0 ? endDates.sort().reverse()[0].slice(0, 10) : null;
let totalDays = 0;
if (earliestStart) {
@@ -87,7 +96,7 @@ function VersionCard({ version, progress, plans, devTasks, testCases, bugs, requ
totalDays = Math.max(0, Math.floor((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24)));
}
- return { vPlans, vDevTasks, vTCs, vBugs, totalDays };
+ return { vPlans, vDevTasks, vTCs, vBugs, totalDays, actualStart: actualStartDisplay, actualEnd: actualEndDisplay };
}, [version, plans, devTasks, testCases, bugs, requirements]);
// 状态胶囊数据 — 与版本详情一致
@@ -185,7 +194,9 @@ function VersionCard({ version, progress, plans, devTasks, testCases, bugs, requ
{displayStatus}
- {version.startDate ?? '-'} → {version.releaseDate ?? '-'}
+ {versionData.actualStart ?? version.startDate ?? '-'}
+ →
+ {versionData.actualEnd ?? version.releaseDate ?? '-'}
共 {totalDays} 天
@@ -212,11 +223,19 @@ function VersionCard({ version, progress, plans, devTasks, testCases, bugs, requ
{progress}%
-
+
- {version.startDate ?? '-'} → 预计 {version.expectedReleaseDate ?? '-'}
+ {versionData.actualStart ?? version.startDate ?? '-'}
+ →
+ 预计 {version.expectedReleaseDate ?? '-'}
+ {versionData.actualEnd && (
+ <>
+ |
+ 实际 {versionData.actualEnd}
+ >
+ )}
已耗时 {totalDays} 天
diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 0000000..8b3edfa
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,136 @@
+# FTB 智能项目管理系统 — 架构文档
+
+## 项目定位
+
+FTB 是一个面向中小型研发团队的项目管理平台,集成 AI 能力辅助决策。核心层级:
+
+```
+产品(Product) → 项目(Project) → 版本(Version) → 需求/任务/用例/Bug
+```
+
+不是给测试团队的工具,也不是 Jira 替代品。**核心目标是让产品/项目经理在一个页面看到:"开发完了吗 → 验收过了吗 → 还有多少 BUG → 能不能发布"**。
+
+## 心智模型(重要)
+
+系统设计遵循**三条维度线**的分离:
+
+```
+语义线(Why) 执行线(How) 质量线(Quality)
+───────────────── ───────────────── ────────────────
+Requirement Version TestCase
+解释为什么做 驱动状态流转 └─ Bug
+不参与流程 所有状态看版本 质量闭环
+```
+
+**Requirement(需求)= 语义层**,解释功能范围和业务原因,不驱动流程。
+**Version(版本)= 执行主线**,所有任务归属版本,状态由版本派生。
+**TestCase + Bug = 质量闭环**,挂在版本上验收。
+
+## 技术栈
+
+| 层 | 技术 | 说明 |
+|---|------|------|
+| 前端 | Next.js 14 (App Router) | TypeScript + 客户端组件为主 |
+| UI | Tailwind CSS + Shadcn/ui | 紧凑信息密度、现代风格 |
+| 状态 | Zustand | 每个领域一个 store |
+| 持久化 | localStorage(V1) | 后端 NestJS + Prisma 已搭好但未启用 |
+| 后端 | NestJS + Prisma + PostgreSQL(V2) | 暂未启用 |
+| AI | Anthropic SDK(V3 远景) | 健康度/风险预警/排期建议 |
+
+## 模块结构
+
+```
+apps/web/
+├── app/
+│ ├── products/ # 产品列表 + 详情(点击项目可跳转)
+│ ├── projects/[id]/ # 项目详情:版本卡片/状态胶囊
+│ ├── versions/ # 版本列表 + 详情
+│ ├── requirements/ # 需求池
+│ ├── workspace/ # 与我相关(聚合工作台)
+│ └── admin/ # 系统管理(任务类型字典等)
+├── components/
+│ ├── product/ # 产品组件
+│ ├── version/ # 版本组件(PlanTab, CapsuleStages, MemberChips...)
+│ ├── dev-task/ # 开发任务组件
+│ ├── test-case/ # 测试用例组件
+│ ├── bug/ # Bug 组件
+│ └── requirement/ # 需求组件
+├── lib/
+│ ├── derive.ts # 派生数据(flattenVersions/flattenProjects)
+│ ├── linkage-engine.ts # 跨模块联动引擎(需求↔DevTask 派生状态)
+│ ├── workspace-engine.ts # 工作台聚合引擎(统一WorkItem)
+│ ├── version-status.ts # 版本执行态推导
+│ ├── version-plan.ts # 计划任务(调研/产品/UI)
+│ ├── dev-task.ts # 开发任务
+│ ├── test-case.ts # 测试用例
+│ ├── bug.ts # Bug
+│ └── requirement.ts # 需求
+└── stores/ # Zustand stores(每个领域独立)
+```
+
+## 关键架构原则
+
+### 1. 引擎模式(关键)
+
+跨模块的数据派生通过**引擎层**处理,不是各 store 互相调用:
+
+- **linkage-engine.ts**:从 DevTask 状态派生需求"实际进度",新建模块只需在此聚合
+- **workspace-engine.ts**:聚合 WorkItem 给"与我相关"页面用
+
+引擎是**纯函数**,输入多个 store 数据,输出统一视图。引擎使应用各模块松耦合,新增模块时不需要改其他模块的代码。
+
+### 2. 派生胜过存储
+
+时间字段、状态、进度都尽量从底层数据派生,而不是手填:
+
+- 实际工时 = `startDate → completedAt` 时间差(精确到 0.5h)
+- 阶段耗时 = 所有阶段任务的最早开始 → 最晚完成
+- 需求开发状态 = 从 DevTask 状态聚合
+- 版本执行态 = 从所有 DevTask + TestCase + Bug 聚合
+- 阶段进度 = 已完成子任务/总子任务
+
+### 3. 时间戳精确到分钟
+
+所有"实际开始/完成"时间都是 ISO 时间戳(含时分秒),不是日期。展示时统一 `slice(0, 16).replace('T', ' ')`。
+
+### 4. 数据联动
+
+修改 A 影响 B 时,**B 通过 filter A 派生**,不要双向写。例:
+- 需求关联到版本:需求设 `versionId`,版本详情 `requirements.filter(r => r.versionId === id)`
+- 删除版本:清理孤儿数据(PlanTask/DevTask/TestCase/Bug + 释放 Requirement.versionId)
+
+## 状态机概览
+
+| 实体 | 状态流转 |
+|------|---------|
+| Requirement | pending_review → adopted → planned → developing → testing → released → closed(rejected 可回 pending_review)|
+| VersionPlan | pending → in_progress → completed |
+| DevTask | todo → in_progress → testing → submitted(终态,提测=已完成)|
+| TestCase | pending → running → passed/failed/blocked |
+| Bug | open → fixing → fixed → verifying → closed/rejected |
+
+DevTask 没有"已完成"状态,"已提测"就是终态——开发交付完成,后续 Bug 单独流转。
+
+## 数据持久化
+
+**V1(当前):** 全部 localStorage,每个 store 独立 key
+- `ftb_overview_v1` - 产品/项目/版本树
+- `ftb_requirements_v3`
+- `ftb_version_plans_v1`
+- `ftb_dev_tasks_v1`
+- `ftb_test_cases_v1`
+- `ftb_bugs_v1`
+- `ftb_overtime_v1`
+- `ftb_task_categories_v1`
+
+**V2(计划):** NestJS + Prisma + PostgreSQL,Schema 已设计但尚未运行 migration。
+
+## 权限模型(轻量)
+
+V1 仅做前端校验,无后端鉴权:
+- 版本 `members` 字段限定参与者
+- 版本列表/详情按 `members.contains(currentUser)` 过滤
+- 创建版本时自动加入创建者
+- 版本 `members` 为空时所有人可见(兼容旧数据)
+
+V2 接入后端后改为基于 `ProjectMember` 表的 RBAC(Owner/Admin/Member/Viewer)。
diff --git a/docs/decisions.md b/docs/decisions.md
new file mode 100644
index 0000000..9262fe3
--- /dev/null
+++ b/docs/decisions.md
@@ -0,0 +1,157 @@
+# 关键设计决策记录
+
+每条决策都包含**为什么这么做**,避免后续模型重新讨论或推翻。
+
+## 1. 进度计算 — 由状态推导,不要手填百分比
+
+**问题**:Jira/TAPD 等系统让开发手填进度(20%/35%/50%),数据完全主观,不可靠。
+
+**决策**:DevTask 进度由 `status` 推导:
+- `todo` → 0%
+- `in_progress` → 50%
+- `testing` → 80%
+- `submitted` → 100%
+
+**理由**:客观、不允许造假。需求级/版本级进度 = `Σ(estimateHours × 状态推导%) / Σ(estimateHours)`。
+
+## 2. 实际工时 — 由开始/完成时间戳计算
+
+**问题**:让人手填工时太粗糙(一天 8h 真的全部花在这个任务吗?)。
+
+**决策**:精确到 0.5h 的时间差计算
+```
+实际工时 = (completedAt - startDate) / 3600000,精确到 0.5h
+```
+
+**理由**:状态流转时自动记录精确时间戳,工时直接派生。
+
+## 3. DevTask "已提测" = 终态
+
+**问题**:原本有 `submitted → done`,但开发提测之后就交付完成了,后续测试结果不应该回过来改 DevTask 状态。
+
+**决策**:去掉 `done`,`submitted` 是终态。测试通过/失败产生 Bug,不影响 DevTask。
+
+**理由**:DevTask 的责任是"开发到提测",验收是 TestCase 的职责。
+
+## 4. 调研/产品/UI — 自动开始 + 手动提前开始
+
+**问题**:到了计划开始日期,状态还是 pending 不合理。
+
+**决策**:
+- 当前时间 ≥ `startTime` 时自动视为 in_progress
+- 用户可在计划日期前手动点"开始"
+- 自动开始时记录 `actualStartAt`(精确到分钟)
+
+**理由**:减少冗余操作但保留灵活性。
+
+## 5. TestCase 主归属版本,需求是可选标签
+
+**问题**:早期把测试用例挂在需求上,但同一需求跨版本迭代时用例难以管理。
+
+**决策**:
+- TestCase.versionId 必填(执行归属)
+- TestCase.requirementId 可选(语义标签)
+- 测试人员从"我的测试用例"看到的就是当前版本的用例
+
+**理由**:测试是按版本执行的,不是按需求;但需求作为思考维度仍然有用。
+
+## 6. Bug 直接挂版本
+
+**问题**:早期通过 `Bug → TestCase → Requirement → Version` 四级反查,太绕。
+
+**决策**:Bug 增加 `versionId` 字段,直接挂版本。`testCaseId` 保留作为来源追溯。
+
+**理由**:判断"能不能发布"的唯一维度是版本,必须 O(1) 查询。
+
+## 7. 跨模块通信 — 引擎层,不是事件总线
+
+**问题**:模块多了,A store 改动影响 B 的派生数据,散落各处难维护。
+
+**决策**:建立**纯函数引擎**:
+- `linkage-engine.ts`:从 DevTask 状态派生需求"实际进度"
+- `workspace-engine.ts`:聚合所有 store 数据为统一 WorkItem
+
+**理由**:事件总线过度设计,纯函数派生更可预测。新增模块只需在引擎中添加聚合逻辑。
+
+## 8. 时间字段统一 ISO 时间戳到分钟
+
+**问题**:日期(`YYYY-MM-DD`) vs 时间戳混用,UI 展示不一致。
+
+**决策**:所有"实际开始/完成"用 `new Date().toISOString()`,展示统一 `slice(0, 16).replace('T', ' ')`。
+
+**理由**:时间戳到分钟够精确,不像秒/毫秒那么噪。
+
+## 9. 任务类型字典化 + 分组
+
+**问题**:早期 enum 写死类型(前端/后端/大数据/其他),新增类型需改代码。
+
+**决策**:建 TaskCategory 字典表 + group(development/implementation/other),管理员可增删。
+
+**理由**:业务变化快,配置 > 写死。group 方便统计(开发工时 vs 实施工时)。
+
+## 10. 阻塞正交标记,不是状态值
+
+**问题**:`status: blocked` 会丢信息——`开发中+阻塞` ≠ `自测+阻塞`。
+
+**决策**:
+- `status: todo|in_progress|testing|submitted`
+- `isBlocked: boolean` + `blockReason: string` + `blockedById: string`
+
+**理由**:阻塞和状态正交。工作台筛选 `isBlocked=true` 一键拉出所有阻塞项,跨状态。
+
+## 11. 加班原因可选,且去掉"其他"
+
+**问题**:可选"其他"会让人逃避思考具体原因。
+
+**决策**:变更原因/加班原因严格定义有限选项,**没有"其他"**。
+
+**理由**:强制具体化,统计才有意义。
+
+## 12. 项目维度 vs 个人维度耗时分开计算
+
+**问题**:多个开发并行做任务,简单加总会重复计算时间。
+
+**决策**:
+- **个人耗时**:每个任务独立累加(`Σ(end - start)`)
+- **项目维度阶段耗时**:`min(start)` → `max(end)` 日历跨度(不重复)
+
+**理由**:两个维度回答不同问题——"谁花了多少时间" vs "这个阶段拖了多久"。
+
+## 13. 删除版本时清理孤儿数据
+
+**问题**:删版本只删 version 实体,留下 PlanTask/DevTask/TestCase/Bug 变成孤儿数据。
+
+**决策**:删除版本时级联清理:
+1. 释放需求 versionId(回需求池)
+2. 删除 PlanTask
+3. 删除 DevTask(通过需求 ID)
+4. 删除 TestCase
+5. 删除 Bug
+
+**理由**:localStorage 没外键约束,必须手动级联。
+
+## 14. 工作台数据点击 → 侧边详情 + 可操作
+
+**问题**:早期工作台只显示信息,操作要跳转到版本详情。
+
+**决策**:点击卡片打开 Drawer(复用版本详情用的同一组件),可在 Drawer 内完成状态流转、转交、提 Bug 等。
+
+**理由**:减少跳转,工作台一站式处理。Drawer 顶部显示"产品/项目/版本"上下文,不会迷失。
+
+## 15. UI 阴影统一 shadow-2xl
+
+**问题**:各 Drawer 阴影不一致(有些 `shadow-lg` 有些 `shadow-2xl`)。
+
+**决策**:全局 Drawer 用 `shadow-2xl`。
+
+**理由**:视觉权重明显,且一致。
+
+## 16. 不进入 Brainstorm 模式的判定
+
+**约定**:以下情况直接修复,**不强制走 brainstorming 流程**:
+1. Bug fix(明确 bug,方案直接)
+2. 已批准方案的 in-progress 延续
+3. 用户已通过 AskUserQuestion 选择了方案
+4. 简单文案/样式调整
+
+**理由**:brainstorming 适合新功能设计,bug fix 强行套流程浪费时间。
diff --git a/docs/roadmap.md b/docs/roadmap.md
new file mode 100644
index 0000000..77f8ad8
--- /dev/null
+++ b/docs/roadmap.md
@@ -0,0 +1,100 @@
+# 开发路线图
+
+## 当前阶段:V1 — 前端 Mock + 业务流程打磨
+
+所有数据用 localStorage 持久化,重点验证业务模型和交互。
+
+### 已完成(按时间倒序)
+
+**2026-06-16**
+- 项目模块顶部卡片(总版本数/已开发/需求数/Bug 总数)
+- 项目模块版本记录与版本详情数据联动(耗时 + 状态胶囊)
+- 4 份核心文档:architecture / decisions / workflow / roadmap
+
+**2026-06-15**
+- 与我相关:产品/项目/版本树筛选 + 红色待办徽标
+- 与我相关:点击卡片打开 Drawer(PlanDetailDrawer 新建,DevTask/TestCase/Bug 复用)
+- 全局 Drawer 阴影统一 shadow-2xl + 顶部上下文条
+- 测试用例提 Bug 流程:drawer 内点击 → BugCreateModal
+- DevTask + TestCase 转交功能(人员离职场景)
+- 需求池:录入人员自动取当前用户 + 状态列改名(业务状态 / 实际进度)
+- 产品页面:去掉规划中、项目名/版本胶囊可点击跳转
+
+**2026-06-14**
+- 需求变更模块:变更人员/原因/概述/详细 + 概览统计(变更人员排名 + 原因占比饼图)
+- 计划任务转交(未开始/进行中可转交,从参与人员选)
+- 关联需求增强:描述列 hover 完整内容、需求类型/变更原因/添加日期列
+- 计划时间精确到分钟(datetime-local)+ 到期自动开始
+- 阶段耗时 + 个人耗时排名(涵盖调研/产品/UI/开发/测试 5 类工作)
+
+**2026-06-13**
+- DevTask 状态简化:去掉 done,submitted 是终态
+- 实际工时改为精确时间戳计算(精确到 0.5h)
+- TestCase 主归属版本,requirement 改为可选标签
+- Bug 直接挂版本(versionId 字段)
+- linkage-engine(需求 ↔ DevTask 派生)
+- workspace-engine(统一 WorkItem 聚合)
+
+**2026-06-12 及更早**
+- 完整模块:需求池/版本管理/计划任务(调研/产品/UI)/开发任务/测试用例/Bug
+- 加班记录 + 排名 + 原因占比饼图
+- 健康度计算 + 风险标签
+- 版本执行态自动推导
+
+### 进行中
+
+- 项目详情页 VersionCard 状态胶囊数据联动(部分已完成)
+
+## V2 — 后端接入
+
+NestJS + Prisma + PostgreSQL Schema 已设计,等业务流程稳定后开始迁移。
+
+### 关键任务
+
+1. **运行 Prisma migration**:把现有的 lib/*.ts 类型转为 Prisma schema
+2. **API 层**:每个 store 对应一组 CRUD endpoint
+3. **localStorage → API 切换**:保留 localStorage 作为离线缓存
+4. **认证**:NextAuth.js + JWT
+5. **权限**:RBAC(Owner/Admin/Member/Viewer),按项目/版本级别
+
+### 数据迁移策略
+
+提供管理员脚本把当前用户的 localStorage 数据导出为 SQL,导入到 PostgreSQL。
+
+## V3 — AI 集成
+
+### 已规划场景
+
+1. **需求智能分解**:输入需求描述,AI 拆解为子任务(技术分析+UI 调整+联调+测试)
+2. **风险预警**:自动识别延期/阻塞集中/工时偏差大的任务,提前预警
+3. **排期建议**:基于成员负载和历史耗时,建议下一阶段任务分配
+4. **需求转任务**:需求采纳后一键生成 DevTask 草稿
+5. **健康度智能解读**:把数据指标转化为自然语言报告
+
+### 落地方式
+
+`apps/server/src/modules/ai/`:
+- `AiGateway` — 统一 prompt 管理、token 计量、降级
+- `AiTaskService.decompose(description)`
+- `AiRiskService.analyze(projectId)`
+- `AiScheduleService.suggest(projectId)`
+- `AiLog` 表存调用记录,便于审计
+
+## 不在路线图(明确不做)
+
+- **Jira/TAPD 替代品**:定位是产品/项目经理视角,不是开发任务管理
+- **测试套件/测试计划**:测试用例是版本验收手段,不做完整测试管理
+- **Gantt 甘特图**:现有的胶囊状态条 + 阶段耗时已经够用
+- **看板视图**:DevTask 列表 + 筛选 + 状态流转已够用
+- **回归测试**:测试用例不做版本间复用
+- **客户/合同管理**:超出研发管理边界
+
+## 关键里程碑
+
+| 节点 | 状态 |
+|------|------|
+| V1 业务流程打磨 | 进行中 |
+| V1 朋友试用反馈 | 持续中 |
+| V2 后端接入 | 等 V1 稳定 |
+| V3 AI 集成 | 等 V2 数据沉淀 |
+| 公开发布 | TBD |
diff --git a/docs/workflow.md b/docs/workflow.md
new file mode 100644
index 0000000..6e992f8
--- /dev/null
+++ b/docs/workflow.md
@@ -0,0 +1,118 @@
+# 工作流程
+
+记录用户的协作偏好和系统化流程,方便后续模型理解项目运作方式。
+
+## 用户协作风格
+
+- **直接修复明确 bug**,不强制走 brainstorming 流程
+- **方案确认后立即执行**,不重复讨论
+- **不喜欢自动 push**:commit 由模型完成,**push 需要用户明说"推/push"**
+- **要求高级开发思维**:考虑数据联动、引擎层抽象,而不是分散写 ad-hoc 逻辑
+- **重视一致性**:所有 Drawer 阴影、所有时间格式、所有状态计算都要统一
+- **省略多余对话**:能直接做的不要问,只在真有歧义时用 AskUserQuestion 给选项
+- **Brainstorming 适用于新功能**,bug fix 和已批准方案的延续不走 brainstorming
+
+## 实际工时计算流程
+
+所有"实际开始时间"和"实际完成时间"都是 ISO 时间戳:
+
+```
+状态变更时机:
+- DevTask: todo → in_progress 时记 startDate
+ testing → submitted 时记 completedAt
+- TestCase: pending → running 时记 startedAt
+ running → passed/failed/blocked 时记 completedAt
+- VersionPlan: pending → in_progress 时记 actualStartAt
+ in_progress → completed 时记 completedAt
+
+计算:
+- 实际工时 = (completedAt - startDate) / 3600000,精确到 0.5h
+- 阶段日历耗时 = min(start) → max(end) 跨度(项目维度,不重复)
+- 个人耗时 = 每个任务独立累加(个人维度)
+```
+
+## 数据联动检查清单
+
+新加模块或字段时,检查以下点:
+
+- [ ] 是否需要在 `linkage-engine.ts` 加派生函数?
+- [ ] 是否需要在 `workspace-engine.ts` 加聚合?
+- [ ] 删除版本时是否需要清理这类数据?
+- [ ] 工作台 / 版本详情 / 项目详情三处的统计是否同步?
+- [ ] localStorage 旧数据是否需要兼容处理?
+
+## Drawer(侧边详情)规范
+
+所有侧边详情遵循:
+
+- `fixed inset-0 z-50 flex justify-end`
+- 背景 `bg-black/40`
+- Drawer 容器 `w-full max-w-md h-full bg-[var(--bg)] border-l shadow-2xl flex flex-col`
+- 顶部上下文条(可选):`px-5 py-2 bg-[var(--bg-subtle)] text-[11px]`
+- 顶栏:`h-14 border-b bg-[var(--bg-card)]`
+- 操作按钮按颜色编码:blue=进行/转交、emerald=完成、red=删除/失败、orange=关闭/提BUG
+
+## Modal(弹窗)规范
+
+- 居中 `flex items-center justify-center bg-black/40`
+- `rounded-2xl bg-[var(--bg-card)] border shadow-md`
+- 提交 BUG 等图片密集型用 `max-w-2xl`,普通表单 `max-w-md` 或 `max-w-lg`
+
+## 字段命名规范
+
+- 实际开始:`startDate` (DevTask) / `startedAt` (TestCase) / `actualStartAt` (VersionPlan)
+- 实际完成:`completedAt`(统一)
+- 派生进度:在 lib 层提供函数,不存储
+
+历史原因导致命名不完全一致(DevTask 用 startDate 是因为最早是日期字段),但行为一致。
+
+## 提交信息规范
+
+- 中文 commit message
+- 格式:`类型(模块): 描述`
+ - feat / fix / refactor / docs / test
+- 描述列出关键改动点,特别是跨模块影响
+- Co-Authored-By 行带版本号
+
+## 文档维护流程
+
+- **新增/改动核心架构** → 更新 `architecture.md`
+- **关键设计决策** → 追加到 `decisions.md`,包含"为什么"
+- **新功能/路线图变更** → 更新 `roadmap.md`
+- **不影响架构的功能性改动** → 不需要更新文档
+
+## Bug 排查流程
+
+朋友拉新代码出现"显示问题"时,按顺序排查:
+
+1. 旧 localStorage 数据格式不兼容 → 让朋友清缓存
+2. 类型定义和实际数据不一致(缺字段)
+3. 列宽溢出导致裁切
+4. 派生计算错误(filter 条件错)
+5. 跨模块联动断了(store 的 store.getState() 调用时机)
+
+## 测试 / 验证流程
+
+- 改动后必须 `npx tsc --noEmit` 通过
+- 涉及 UI 改动:`curl http://localhost:3000/` 检查 200
+- 不会自动跑 dev server,假定它已经运行
+
+## 与我相关(Workspace)数据流
+
+```
+useProductStore → versions
+useRequirementStore → requirements (with versionId)
+useDevTaskStore → tasks (with requirementId)
+useTestCaseStore → testCases (with versionId)
+useBugStore → bugs (with versionId)
+useVersionPlanStore → plans (with versionId, owner)
+useAuthStore → user (filter by current user)
+ ↓
+workspace-engine.aggregateWorkItems(...)
+ ↓
+WorkItem[] (统一格式)
+ ↓
+Workspace 页面(树筛选 + tab 筛选 + 已完成开关)
+```
+
+新增模块时,只需在 `aggregateWorkItems` 中添加聚合逻辑,工作台自动展示。