Files
ftb-project-management/docs/workflow.md
Script Generator 61f4ca51f1 chore(部署): 增加 Docker 部署配置
关键改动:

- 新增本地和生产 Docker Compose、Web/Server Dockerfile 与 Nginx 模板

- 增加生产部署校验脚本、环境变量示例和 Prisma 初始迁移

- 更新部署文档、README 和架构/决策/流程/路线图说明

Co-Authored-By: Codex GPT-5 <codex@openai.com>
2026-07-01 16:04:18 +08:00

310 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 工作流程
记录用户的协作偏好和系统化流程,方便后续模型理解项目运作方式。
## 用户协作风格
- **直接修复明确 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) 跨度(项目维度,不重复)
- 个人耗时 = 每个任务独立累加(个人维度)
```
## 开发任务延后原因判断
开发任务从“待开发”切换到“开发中”时,只有当前时间已经超过 `expectedEndAt`(预计截止)才要求填写延后原因。超过预计开始时间但仍未超过预计截止时间,不视为延后。
## AI 草案领取与计划流程
开发任务和测试用例由 AI 生成后,版本详情里不再显示独立的“待排期”状态:
1. DevTask / TestCase 没有负责人时显示“待领取”。
2. 点击“领取并填写计划”时同时写入当前用户为负责人,并填写计划起止时间。
3. 已采纳推荐负责人的 AI 草案已经有负责人,不需要领取,但开始开发/测试前仍必须点击“填写计划”补齐计划起止时间。
4. DevTask 开始开发前必须同时具备 `assigneeId``expectedStartAt``expectedEndAt`TestCase 开始测试前必须同时具备 `assigneeId``plannedTestAt``plannedEndAt`
5. 计划起止时间自动按工作日历计算 `estimateHours`。AI 预估仍保留在 `aiEstimateHours`,不代表负责人已确认排期。
## 开发任务提测流程
1. DevTask 从“自测”转为“已提测”前,任务不能处于阻塞中。
2. 如果 `isBlocked=true`,必须先解除阻塞并清空阻塞原因,再允许提测。
3. “已提测”仍然是 DevTask 终态;后续测试通过或失败不回写 DevTask 状态。
## 测试轮次流程
测试用例支持按版本开启多轮测试:
1. 旧测试用例或未写入 `roundNo` 的测试用例默认属于第 1 轮。
2. 点击“开启新一轮测试”时,系统从第 1 轮复制全部测试用例到下一轮,包含 AI 创建和人工创建的用例。
3. 只有最新一轮全部测完(状态为通过、不通过或阻塞)后,才能开启下一轮;第 1 轮未测完不能开启第 2 轮。
4. 新轮次保留用例范围与估时信息关联需求、任务类型、优先级、负责人、引用来源、AI 预估、执行预估。
5. 新轮次清空执行记录:状态回到待测试,不带开始/完成时间、执行人、失败原因、阻塞原因。
6. 测试用例列表、当前轮次进度、无 Bug 通过率按选中的轮次展示。
7. 顶部耗时汇总按当前版本全部轮次累计,实际耗时和人力投入会包含新一轮执行产生的耗时。
8. 测试用例按所属需求分组展示开发提测标签:该需求下所有开发任务都已提测时显示“已提测”,否则显示“待提测”。
## 数据联动检查清单
新加模块或字段时,检查以下点:
- [ ] 是否需要在 `linkage-engine.ts` 加派生函数?
- [ ] 是否需要在 `workspace-engine.ts` 加聚合?
- [ ] 删除版本时是否需要清理这类数据?
- [ ] 工作台 / 版本详情 / 项目详情三处的统计是否同步?
- [ ] 是否需要新增 `app_data` key后端 `data-keys.ts` + 前端 `server-data.ts`
- [ ] 是否需要从旧浏览器数据做一次性迁移?(当前不做本地导入导出)
## 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. 后端是否启动:`GET http://localhost:3001/api/v1/config/ai` 应返回 200
2. 数据库是否启动并完成 Prisma 同步:`app_data` 表必须存在
3. 对应 `app_data.key` 是否有值,例如 `products-overview` / `requirements` / `dev-tasks`
4. 前端 store 是否已经调用对应 `fetch*` 方法
5. 类型定义和实际 JSON 数据不一致(缺字段)
6. 列宽溢出导致裁切
7. 派生计算错误filter 条件错)
8. 跨模块联动断了store 的 store.getState() 调用时机)
## 测试 / 验证流程
- 改动后必须 `npx tsc --noEmit` 通过
- 涉及服务端数据持久化:`pnpm --filter server exec prisma validate --schema prisma/schema.prisma`
- 涉及 UI 改动:`curl http://localhost:3000/<path>` 检查 200
- 不会自动跑 dev server假定它已经运行
## 与我相关Workspace数据流
```
useProductStore → versions
useRequirementStore → requirements (with versionId)
useDevTaskStore → tasks (with versionId; legacy 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` 中添加聚合逻辑,工作台自动展示。
## AI 拆解工作流V3.1
详细 Agent 规范见 `agent-spec.md`。这里是用户视角的工作流:
```
1. 创建版本(不需要单独填原型链接)
2. 在版本详情 → 产品方案 Tab 创建一条 product 计划
3. 完成产品方案计划,提交「成果」(成果链接即原型链接,附成果标题)
4. 从当前项目已采纳需求中关联需求到本版本
5. 点击「AI 拆解开发任务」或「AI 拆解测试用例」按钮(位于产品方案 Tab
6. Agent 从 product 类型的 completed 计划取 resultUrl 作为原型,
抓取原型 + 关联需求 + 版本成员,输出对账报告 + 任务/用例草案
(关联需求优先;原型中明确可拆但没有 REQID 的内容进入“无需求ID”分组
- 生成中状态和完成结果保存在前端 AI 拆解会话中;用户离开版本详情再返回时,未结束的生成继续保持“拆解中”,已完成的生成显示“查看结果”。
- 生成结果只有在用户点击「采纳选中」或「不采纳」后才清空;单纯关闭弹窗或切到其他页面不会丢失结果。
7. 用户审核对账报告
├─ 系统先自动过滤已采纳过的重复 DevTask/TestCase 草案
├─ 报告全 ✅:直接确认写入
├─ 报告有无需求ID分组确认后写入任务/用例,但不创建需求池记录
├─ 报告有 ⚠️/❓:选择性放弃部分草案 / 补充信息后重跑
└─ 报告全 ❓:放弃 AI 拆解,人工创建
8. 确认后DevTask / TestCase 草案写入对应 Tab标记 aiDraft: true并写入 aiEstimateHours
无需求ID草案按 `无需求ID · 需求名称` 分组展示,不额外显示“原型发现”标记
9. 团队成员在 DevTask Tab 看到紫色边的 AI 草案任务
10. 任意成员编辑任务(改标题/描述/负责人/优先级/时间/分类/执行预估),保存后 aiDraft 自动清除
changeStatus / setBlocked 等用户主动操作也会清除)
```
**触发条件**AI 拆解按钮可点):
- 至少有 1 条 type=product 的产品方案计划处于 completed 且 resultUrl 非空
- 至少 1 条需求关联到本版本
**人工创建任务/用例的引用要求**
- 创建 DevTask 时已选「关联需求」自动作为 reference 写入
- 创建表单加「原型批注」字段(手填,逗号或空格分隔,如 `QY0007, QY0023`
- 至少一类引用非空才能保存V3.1 暂未做强校验,靠 UI 引导)
## 高级开发约束:规则先归位
涉及以下任意类型的改动时,先判断规则应该放在哪一层,不允许直接在页面组件里散写临时判断:
- 跨模块联动:例如 Requirement、VersionPlan、DevTask、TestCase、Bug 互相派生状态。
- 状态流转:例如 `pending -> in_progress -> completed``todo -> testing -> submitted`
- 完成条件:例如子任务是否完成、是否提交成果、是否允许点击完成。
- 候选数据来源:例如关联需求只能来自当前项目已采纳需求,不能从全量需求池随手取。
- AI 写入契约:例如 AI 输出任务类型、引用来源、草案标记。
- AI 无需求ID分组原型中明确可拆但没有匹配关联需求的内容只写入 DevTask/TestCase 的 `requirementName`,不进入需求池或版本关联需求列表。
默认落点:
- 可派生数据进 `*-engine.ts` 或纯函数 helper。
- 有状态流转的实体要有状态机或 workflow helper。
- 多个组件共用的候选筛选规则进 selector/helper。
- AI 输入输出字段先更新 `agent-spec.md` 和 shared type再改 prompt/schema。
AI 估时约束:
- `aiEstimateHours` 是 AI 建议工时,只能由 AI 拆解写入。
- `estimateHours` 是执行人预估,只能由人工创建/编辑或负责人确认排期时写入。
- 统计进度优先取 `estimateHours`,没有时取 `aiEstimateHours`,避免 AI 草案在未确认前失去统计权重。
版本模块新增规则:
- `version-plan-workflow.ts` 是调研/产品方案/UI 设计完成条件的唯一入口。
- `requirement-selector.ts` 是版本内关联需求候选的唯一入口。
- `TaskCategory.code` 是 AI 和系统任务类型的稳定映射锚点,`id` 只作为存储主键。
- DevTask 新数据必须有 `versionId``requirementId` 作为正式需求语义标签可选。版本级聚合走 `versionId`,需求级进度只统计带 `requirementId` 的任务。
- 产品方案和 UI 设计的引用需求不再用 checkbox 直接标记完成,必须通过 `requirementCoverage[]` 记录 `not_started / partial / completed`、本次已完成内容和剩余内容;只有 `completed` 计入成果提交门禁。
- 产品/UI 计划右侧展示计划日志,需求进度更新和 AI 拆解触发/完成/失败都写入 `VersionPlan.logs[]`,页面只消费日志数据,不临时拼历史。
- 调研/产品方案/UI 设计的计划级 `actualStartAt` 只表示计划容器已开始,不直接作为具体任务日报耗时。具体调研方向或引用需求需要先点击「开始任务」,写入当前行的 `currentWorkStartedAt`;提交「记录」时日志和 `work-activities` 保留 `workStartedAt`,日报耗时按 `workStartedAt -> 记录提交时间` 计算,提交后清空当前行的开始时间。完全完成可直接提交结束本次耗时,部分完成才需要填写本次已完成内容和剩余未完成内容。
## Work Activity Daily Report Flow (2026-06-26)
The daily report flow uses mixed evidence:
1. Automatic evidence is written when a user performs a successful domain action:
- VersionPlan created, started, or completed.
- DevTask created, started, moved to self-test, submitted to test, blocked, or unblocked.
- TestCase created, started, passed, failed, or blocked.
- Bug created, moved to fixing, fixed, closed, or transferred.
2. Manual progress notes are used for multi-day work that does not change status today.
- DevTask「今日进展」必须填写 `nextStartAt`,默认值为第二天 09:30。
-`nextStartAt` 的进展记录按「上一条记录的 `nextStartAt` → 本次记录时间」计算当日耗时;如果任务是当天开始,才回退到当天实际开始时间。
3. `/workspace` shows only the current logged-in user's report.
4. Project-owner and management views will reuse the same `work-activities` data later, but are not part of the personal workspace panel.
Implementation convention:
- Activity wording and category mapping belong in `apps/web/lib/work-activity-factory.ts`.
- Daily report grouping belongs in `apps/web/lib/workspace-daily-report.ts`.
- Page components should consume report output, not rebuild report rules.
## 小宝预警工作流
小宝预警位于主导航“工作区 / 小宝预警”,展示在“与我相关”上方。可见范围由角色权限控制:
- `xiaobao.warning:manage`:查看所有未结束版本的预警。
- `xiaobao.warning:view`:仅查看当前用户在 `version.members` 中的未结束版本。
页面打开时会聚合版本下的计划、开发任务、测试用例、Bug、日报和工作活动计算当前风险并保存当天快照。页面使用 `buildXiaobaoWorkItems` 做版本级聚合,不使用个人工作台的 `aggregateWorkItems(userName, ...)` 过滤。快照按同版本同日节流保存:重大变化立即保存,普通变化 10 分钟内不重复写入。
AI 解读不由人工按钮触发。`at_risk``likely_delayed``blocked` 自动触发;`attention` 在风险分明显上升、趋势连续上升、关键 Bug 增加、测试失败、阻塞增加、静默风险增加、置信度下降或预测发版日延后时触发。缓存命中时复用解读;同版本最近 6 小时内已有解读时进入 cooldown不重复请求风险等级升级时可绕过缓存保存时间使用客户端时间不信任模型返回的 `generatedAt` 作为缓存新鲜度。
静默风险包括长期无更新、无日报、无活动、进行中事项无人处理等信号。日报和工作活动是风险解释的重要证据,必须进入 AI 解读输入。
## 日期选择与计划时间
- 调研、产品方案、UI 设计、开发任务、测试用例、Bug 创建时使用统一工作日日期时间选择器。
- 日期选择器接入中国节假日日历。当前内置 2026 年国务院办公厅放假调休安排;其他年份先按周末/工作日兜底。
- 非工作日只提示,不阻止保存;调休工作日按工作日提示。
- 测试用例计划测试时间字段为 `plannedTestAt` / `plannedEndAt`Bug 计划修复时间字段为 `plannedFixAt`
- 测试轮次复制用例时保留计划测试起止时间、AI 预估和执行预估,清空实际执行记录。
## 工时统计口径
- 正常任务耗时使用 `calcWorkHours` / `calcActualElapsedHours`,按中国工作日历和 9:00-12:00、13:00-18:00 工作时段计算。
- 法定节假日和周末不计入正常任务耗时;调休上班日计入正常任务耗时。
- AI 预估工时和手填执行预估工时本身是小时数,不再按日期过滤;只有从计划起止时间自动推导的执行预估会按工作日历计算。
- 加班记录使用 `overtime.calcDuration`,不受节假日过滤,但按项目管理口径计算:每个自然日默认最多 8h跨天中间日期按 8h结束晚于 18:00 的当天额外计入超出时长,避免把夜间空档当作打卡工时。
- 新建加班记录也使用工作日历日期选择器;节假日和周末可选,只提示不阻止。
## 生产部署流程
生产部署以 `docs/deployment.md` 为准,标准顺序如下:
本地服务器/局域网部署:
1. 复制 `.env.local-server.example``.env.local-server`,按需把 `LOCAL_ACCESS_HOST``NEXTAUTH_URL` 改为本机局域网 IP。
2. 运行 `pnpm deploy:verify`
3. 运行 `pnpm deploy:local:build` 构建镜像。
4. 运行 `pnpm deploy:local:up` 启动服务,默认访问 `http://localhost:8080`
5. 首次部署或升级后运行 `docker compose --env-file .env.local-server -f docker-compose.local.yml exec server pnpm --filter server db:deploy`
6.`curl http://localhost:8080/api/v1/config/ai` 验证 Nginx 到后端链路。
云服务器部署:
1. 复制 `.env.production.example``.env.production`,替换密码、域名、`NEXTAUTH_SECRET`、AI key 等真实值。
2. 运行 `pnpm deploy:verify`,确认生产 Docker、Compose、Nginx、env 示例和文档齐全。
3. 运行 `docker compose --env-file .env.production -f docker-compose.prod.yml build` 构建镜像。
4. 运行 `docker compose --env-file .env.production -f docker-compose.prod.yml up -d` 启动服务。
5. 首次部署或升级后运行 `docker compose --env-file .env.production -f docker-compose.prod.yml exec server pnpm --filter server db:deploy`
6.`curl http://localhost/api/v1/config/ai` 验证 Nginx 到后端链路。
7.`docker compose --env-file .env.production -f docker-compose.prod.yml ps``logs -f server/web/nginx` 排查健康状态。
生产环境不提交 `.env.production`。HTTPS 默认由外层负载均衡、CDN、宿主机证书工具或外层 Nginx 终止Compose 内置 Nginx 只承担同域 HTTP 反代。