# 工作流程 记录用户的协作偏好和系统化流程,方便后续模型理解项目运作方式。 ## 用户协作风格 - **直接修复明确 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` 加聚合? - [ ] 删除版本时是否需要清理这类数据? - [ ] 工作台 / 版本详情 / 项目详情三处的统计是否同步? - [ ] 是否需要新增关系表、Prisma model、领域 API、权限和审计? - [ ] 是否需要从旧浏览器数据做一次性迁移?(当前不做本地导入导出) ## 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 行带版本号 ## Git 推送流程 - **push 必须由用户明确要求**:默认只 commit,不自动 push。 - **GitHub 是主推送目标**:需要推送时,必须优先确保 GitHub 上的目标分支更新成功,再同步到 Gitea。 - `origin` 配有两个 push URL,顺序应保持为 GitHub 在前、Gitea 在后。推送前可用 `git remote get-url --push --all origin` 核对。 - 标准推送命令优先使用显式 refspec:`git push origin :`。这样会按 `origin` 的 push URL 顺序先推 GitHub,再推 Gitea,并避免当前分支与目标分支不一致时误推。 - 如果 GitHub fetch/push 失败,不要静默改为只推 Gitea,也不要把“已推送”视为完成。必须明确告知用户 GitHub 未成功,并等待用户决定是否临时只推 Gitea。 - 推送完成后必须分别核对两边目标分支指向同一个提交: - `git ls-remote --heads origin ` - `git ls-remote --heads gitea ` ## 文档维护流程 - **新增/改动核心架构** → 更新 `architecture.md` - **关键设计决策** → 追加到 `decisions.md`,包含"为什么" - **新功能/路线图变更** → 更新 `roadmap.md` - **不影响架构的功能性改动** → 不需要更新文档 ## Bug 排查流程 朋友拉新代码出现"显示问题"时,按顺序排查: 1. 后端是否启动:`GET http://localhost:3001/api/v1/config/ai` 应返回 200 2. 数据库是否启动并完成 Prisma migration:领域关系表必须存在 3. 对应领域 API 是否有数据,例如 `/api/v1/products`、`/api/v1/v2.2/workspace`、`/api/v1/versions/:versionId/plans` 4. 前端 store 是否已经调用对应 `fetch*` 方法,且是否传了正确的 `productId` / `versionId` 5. 类型定义和实际 JSON 数据不一致(缺字段) 6. 列宽溢出导致裁切 7. 派生计算错误(filter 条件错) 8. 跨模块联动断了(store 的 store.getState() 调用时机) ## 测试 / 验证流程 - 改动后必须 `pnpm type-check` 通过 - 涉及服务端数据持久化:`DATABASE_URL=postgresql://postgres:postgres@localhost:5432/ftb_pm pnpm --filter server exec prisma validate --schema prisma/schema.prisma` - 涉及 V2.5 后端权限/审计/AppData/一致性:至少运行 `pnpm --filter server test` - 涉及 UI 改动:`curl http://localhost:3000/` 检查 200 - 不会自动跑 dev server,假定它已经运行 ## AppData 归档/配置写入流程 - 正常业务 store 不再通过 `loadServerData(key)` / `saveServerData(key, value)` 读取或保存已迁移业务文档。 - 仅允许低频配置例外使用 AppData:成员配置中的部门/角色/密码规则、加班原因。小宝历史缓存/已读状态只保留迁移与归档读取价值,正常页面运行时不得读写这些 AppData key。 - 前端通过 `loadServerData(key)` 读取配置文档时,必须缓存响应里的 `version`。 - 前端通过 `saveServerData(key, value)` 保存已读取过的配置 key 时,必须把最近一次成功读取/保存得到的 `version` 一起提交。 - 后端只在 `key + updatedAt(version)` 匹配时更新;如果其他用户已经先保存,返回 `409 APP_DATA_CONFLICT`,响应包含当前服务端 `currentVersion` 和 `currentValue`。 - 收到 `ServerDataConflictError` 时,不要自动重试覆盖。当前处理策略是阻止静默覆盖,后续 UI 冲突合并能力再单独补。 ## V2.4 领域写入流程 已迁移领域的 store 默认写入顺序: 1. 本地状态先做乐观更新,保持 UI 响应速度。 2. 调用 `apps/web/lib/domain-api.ts` 中的领域 API。 3. 领域 API 成功后,用服务端返回行替换本地临时行;若返回 `activities`,直接合并工作活动证据。 4. 领域 API 不可用时回滚乐观更新并提示 API/网络错误,不再写 AppData 兼容兜底。 5. 不新增双写逻辑;迁移、归档、回滚工具可以读历史 AppData,但正常业务 UI 不把它当事实源。 当前领域主写范围: - Product / Project / Version:根数据主写,正常运行时不读 `products-overview`。 - Requirement:按 `productId` 写入,需求池列表走服务端分页、搜索、筛选、排序。 - VersionPlan / DevTask / TestCase / Bug:按 `versionId` 写入,并维护工作活动和小宝 dirty 标记。 - Member / TaskCategory:成员身份字段和任务类型字典主写关系表。 - TaskWorklog / OvertimeRecord / WorkActivity:证据型数据主写关系表,保持追加语义。 仍在 AppData 兼容配置中的内容: - 部门、角色、密码规则。 - 加班原因。 新增领域 store 时,先写 source contract 测试证明运行时不调用 `loadServerData('')` / `saveServerData('')`,再实现领域 API。 ## V2.5 权限、审计与 AppData 退场流程 新增或修改领域 mutation endpoint 时,必须使用统一合同: 1. Controller mutation 使用 `@ProtectedMutation(permission, scope, audit)`,不要只在前端做权限判断。 2. `scope` 必须能从 param/body 中解析 `productId`、`projectId` 或 `versionId`,版本资源优先传 `versionId`。 3. Service 写入需要保留 `actorId`、`resourceScope` 或可推导的产品/项目/版本上下文,便于审计与一致性校验。 4. 成功 mutation 必须写 `audit_events`;审计详情中不得暴露密码、token、secret、API key 等敏感字段。 5. 查询审计走 `/admin/audit` 或 `GET /api/v1/audit`,需要 `audit:view`。 AppData key 退场遵循: 1. 所有业务 key 先在 `AppDataRetirementService` 标注状态和替代路径。 2. `write_frozen` / `read_only_archive` key 的写入返回 `409 APP_DATA_WRITE_FROZEN`;前端捕获 `ServerDataWriteFrozenError` 后提示改用领域 API。 3. 读取仍可用,只用于历史数据核对、兼容导入、归档导出和故障排查;正常业务 UI 不应把读取结果当 fallback 数据源。 4. 导出归档使用 `pnpm appdata:archive:export`,归档校验使用 `pnpm appdata:archive:verify -- --archive `。 5. 不新增 AppData key 作为主写;新业务先设计关系表、Prisma model、领域 API、权限和审计。 一致性检查流程: 1. 本地或部署环境先确保 server 可访问并完成 migration。 2. 运行 `pnpm consistency:v25`,默认检查 `http://localhost:3001/api/v1/consistency`。 3. `error` 必须修复后才能继续发布;`warn` 需要记录原因。历史数据缺少审计事件属于 warning,不阻断 V2.5。 4. 后台页面 `/admin/consistency` 由 `consistency:view` 控制,展示 counts、分区键、孤儿引用和审计覆盖。 跨阶段协调点: - `xiaobao-risk-snapshots` / `xiaobao-risk-insights` 已进入只读归档;正常前端运行时不再读取或写入这些 AppData key,V2.6 关系表和后台任务负责 summary/insight。 - `xiaobao-warning-views` 已进入只读归档;正常前端运行时不再写该 AppData key,当前页面已读状态仅作为浏览器本地 UI 状态,后续由 per-user read-state API 承接。 - 成员身份写 `users`,但部门、角色、密码规则和加班原因的正式配置 schema 仍属 V2.7 管理治理。 ## 与我相关(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.name` 是 AI 草案的可复用任务类型锚点;可复用开发类型可自动入库,测试用例未知类型回退到已有测试分类。`TaskCategory.code` 仅作为可选兼容映射,`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 -> 记录提交时间` 计算,提交后清空当前行的开始时间。完全完成可直接提交结束本次耗时,部分完成才需要填写本次已完成内容和剩余未完成内容。 ## Production Release Workflow (2026-07-06) Production releases use GitHub Actions as the default path. The deployment side should not manually rebuild frontend assets after every change; it keeps `.env.production` and Docker volumes, while Actions builds immutable images and updates the running containers. Standard flow: 1. Merge or push to `master`. 2. GitHub Actions builds `web` and `server` images with `APP_VERSION=`. 3. Actions pushes the images to GHCR. 4. Actions SSHes into the server, updates `.env.production` image tags, pulls the images, runs `pnpm --filter server db:deploy`, and restarts Compose. 5. Actions verifies `/api/v1/health/version` equals the commit SHA. If a user reports "latest code pulled but UI is still old", first compare the running version endpoint with the expected commit. A mismatch means deployment did not update the running container. A match means the code is deployed and the remaining issue is likely browser cache, data, or business logic. ## 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` 中的未结束版本。 V2.6/V3.2 后小宝当前 summary 由服务端后台刷新:领域写入标记 `xiaobao_risk_summaries.dirty=true` 并排入 `xiaobao.summary.refresh`,worker 从版本下的计划、开发任务、测试用例、Bug、日报和工作活动重新计算风险。页面仍可用前端 `buildXiaobaoWorkItems` 做兼容聚合,但不再把快照或解读保存到 AppData,默认优先读取 V2.2 summary。 AI 解读不由人工按钮触发。服务端 summary 刷新后按 policy 排入 `xiaobao.ai.interpret`:`at_risk`、`likely_delayed`、`blocked` 自动触发;`attention` 当前服务端只在临近发版且仍有未完成工作时触发。缓存命中时复用解读;同版本最近 6 小时内已有解读时进入 cooldown,不重复请求,风险等级升级时可绕过;缓存保存时间使用服务端写入时间,不信任模型返回的 `generatedAt` 作为缓存新鲜度。V2.2 小宝快读会带出当前版本最新 generated 关系表解读,前端优先展示这份解读,不再回读旧 `xiaobao-risk-insights` AppData 缓存。 静默风险包括长期无更新、无日报、无活动、进行中事项无人处理等信号。日报和工作活动是风险解释的重要证据,必须进入 AI 解读输入。 ## V2.7 协作治理工作流 通知统一进入 `notifications` 关系表,事件类型固定为: - `assignment`:负责人或处理人被分配工作。 - `mention`:评论中 `@成员名` 或显式选择成员。 - `risk_alert`:小宝风险摘要/高风险事件触发后提醒管理者。 - `overdue_item`:逾期事项提醒。 评论统一使用 `CommentPanel`,支持 DevTask、TestCase、Bug、Requirement 和 VersionPlan。创建/删除评论必须写 audit;提及成员必须生成 mention 通知。 项目成员治理走 `/projects/:projectId/members` 服务端接口。角色为 Owner/Admin/Member/Viewer,Owner/Admin 可管理成员;服务端禁止移除或降级最后一个 Owner。版本成员可见性继续兼容旧 `version.members` 展示,但治理来源应逐步收敛到 ProjectMember。 管理驾驶舱 `/admin/management` 只查关系表和小宝 summary,不读取 AppData,并通过 RBAC adapter 校验 `management:view`。治理设置 `/admin/governance` 统一维护任务类型、需求类型、支持端与需求来源,并由 `governance:manage` 控制。需求池只消费治理字典,不再提供本地类型/来源/支持端管理抽屉;AI 分析读取这些字段作为维度,不负责修改字典。 ## Business Analysis Agent 工作流(第一版已接入) Business Analysis Agent 用于 AI 助手业务数据对话,以及产品/项目/版本详情页的上下文分析入口。它只读关系表和 summary,不写业务数据。 业务分析请求走 `POST /api/v1/ai/analysis`。前端必须传入 `surface` 和可用上下文 ID;后端基于当前用户、服务端权限和页面上下文再次收窄范围,不能只信任前端传入的权限或自然语言意图。 标准流程: 1. 用户在 `/wenfan-xiaobao` 或详情页输入问题。 2. 前端提交问题和上下文:`surface`、`productId`、`projectId`、`versionId`。 3. 后端 Analysis Planner 识别用户意图。 4. Semantic Layer 将自然语言映射成系统语义、指标、维度、分析类型和时间意图。 5. Permission Scope Resolver 根据当前用户权限和页面上下文收窄数据范围。 6. Analysis Strategy 生成分析计划: - Template Strategy 优先命中固定高频模板。 - Rule Composition Strategy 用确定性规则组合已知指标、维度和时间口径。 - AI Planning Strategy 只生成计划建议,不直接执行。 7. Analysis Plan Processor 校验权限、指标、维度、聚合、时间范围、Top N 和筛选条件,并规范化为统一 `AnalysisPlan`。 8. Metric Engine 执行关系表查询和聚合,返回 `MetricResult`。 9. ChartSpec Builder、Insight Engine、Report Builder、Follow-up Builder 并行消费 `MetricResult`。 10. 前端展示 Insight Card、ECharts 图表、固定结构报告、可点击 Evidence 和只读 Follow-up。 时间口径: - 用户明确说本月、季度、年份、最近 N 天时,按用户指定。 - 当前状态或风险问题不默认套近 30 天,使用实时状态、未完成事项、小宝 summary、阻塞、Bug、测试完成率和发版日期。 - 趋势、吞吐、效率、投入和变化类问题,用户未指定时间时默认近 30 天。 - 对比类问题未指定基准时,用近 30 天对比前 30 天。 - 生命周期类问题按对象生命周期统计。 - 每次回答必须显示统计范围、数据截止时间、权限范围和时间口径类型。 无数据时返回 No Data 结果,不生成虚假解释。低语义置信时先说明系统默认解释,必要时给用户可选追问。 视觉工作流: - 结果先显示一句 Insight Card,再显示图表和报告。 - 图表使用平台 Unified ChartSpec,通过前端 ECharts Renderer 渲染。 - 图表遵循 AI Analysis Design System:Apple Vision 风格、大留白、大圆角、轻阴影、半透明材质、数字优先、折线面积渐变、横向圆角柱状、少坐标、少颜色、无大屏炫光。 ## 日期选择与计划时间 - 调研、产品方案、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 反代。