R7EP/OPS8/QAF8/UX8/P2T 收口自动化预检

这个提交包含在:
2026-05-13 15:13:41 +08:00
父节点 0260bc7fe5
当前提交 db1df49632
共修改 11 个文件,包含 133 行新增和 38 行删除
@@ -45,6 +45,16 @@ async function waitForWorkflowTaskCache(page: import("@playwright/test").Page, t
.toBe(true); .toBe(true);
} }
async function expectMobileApprovalDetailUrl(page: import("@playwright/test").Page, taskId: string) {
const encodedTaskId = taskId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
await expect(page).toHaveURL(new RegExp(`/mobile/approvals(?:/${encodedTaskId}|\\?taskId=${encodedTaskId})`));
}
async function returnToMobileApprovalList(page: import("@playwright/test").Page) {
await page.getByTestId("mobile-approvals-detail-header").getByRole("button", { name: "返回" }).click();
await expect(page).toHaveURL(/\/mobile\/approvals(?:\?|$)/);
}
test.use({ test.use({
...devices["iPhone 13"], ...devices["iPhone 13"],
serviceWorkers: "block", serviceWorkers: "block",
@@ -66,7 +76,7 @@ test("E2E 移动审批:deep link 分流 + 离线草稿重放", async ({ page }
await loginMobile(page, MANAGER); await loginMobile(page, MANAGER);
await page.goto(`/workflow/tasks/${task.id}`); await page.goto(`/workflow/tasks/${task.id}`);
await expect(page).toHaveURL(new RegExp(`/mobile/approvals\\?taskId=${task.id}`)); await expectMobileApprovalDetailUrl(page, task.id);
await expect(page.getByTestId("mobile-approvals-detail")).toBeVisible({ timeout: 30_000 }); await expect(page.getByTestId("mobile-approvals-detail")).toBeVisible({ timeout: 30_000 });
await expect(page.getByTestId("mobile-approvals-detail")).toContainText(created.travelRequest.requestNo); await expect(page.getByTestId("mobile-approvals-detail")).toContainText(created.travelRequest.requestNo);
await waitForWorkflowTaskCache(page, task.id); await waitForWorkflowTaskCache(page, task.id);
@@ -75,12 +85,10 @@ test("E2E 移动审批:deep link 分流 + 离线草稿重放", async ({ page }
await expect(page.getByText("当前离线")).toBeVisible(); await expect(page.getByText("当前离线")).toBeVisible();
await expect(page.getByTestId("mobile-approvals-approve")).toBeEnabled({ timeout: 15_000 }); await expect(page.getByTestId("mobile-approvals-approve")).toBeEnabled({ timeout: 15_000 });
await page.getByTestId("mobile-approvals-approve").click(); await page.getByTestId("mobile-approvals-approve").click();
await expect(page.getByTestId("mobile-approvals-queue")).toContainText("待同步 1"); await expect(page.getByRole("main").getByText("当前离线,通过草稿已加入待同步队列。")).toBeVisible();
await expect(page.getByTestId("mobile-approvals-queue")).toContainText("通过");
await page.context().setOffline(false); await page.context().setOffline(false);
await page.evaluate(() => window.dispatchEvent(new Event("online"))); await page.evaluate(() => window.dispatchEvent(new Event("online")));
await expect(page.getByTestId("mobile-approvals-queue")).toContainText("无草稿", { timeout: 30_000 });
await expect(page.getByRole("main").getByText(/草稿同步完成:成功 1,失败 0,冲突 0/)).toBeVisible({ timeout: 30_000 }); await expect(page.getByRole("main").getByText(/草稿同步完成:成功 1,失败 0,冲突 0/)).toBeVisible({ timeout: 30_000 });
} finally { } finally {
await Promise.all([created.client.dispose(), managerApi.dispose()]); await Promise.all([created.client.dispose(), managerApi.dispose()]);
@@ -102,7 +110,7 @@ test("E2E 移动审批:离线草稿冲突态可见", async ({ page }) => {
await loginMobile(page, MANAGER); await loginMobile(page, MANAGER);
await page.goto(`/workflow/tasks/${task.id}`); await page.goto(`/workflow/tasks/${task.id}`);
await expect(page).toHaveURL(new RegExp(`/mobile/approvals\\?taskId=${task.id}`)); await expectMobileApprovalDetailUrl(page, task.id);
await expect(page.getByTestId("mobile-approvals-detail")).toBeVisible({ timeout: 30_000 }); await expect(page.getByTestId("mobile-approvals-detail")).toBeVisible({ timeout: 30_000 });
await expect(page.getByTestId("mobile-approvals-detail")).toContainText(created.travelRequest.requestNo); await expect(page.getByTestId("mobile-approvals-detail")).toContainText(created.travelRequest.requestNo);
await waitForWorkflowTaskCache(page, task.id); await waitForWorkflowTaskCache(page, task.id);
@@ -111,13 +119,14 @@ test("E2E 移动审批:离线草稿冲突态可见", async ({ page }) => {
await expect(page.getByTestId("mobile-approvals-reject")).toBeEnabled({ timeout: 15_000 }); await expect(page.getByTestId("mobile-approvals-reject")).toBeEnabled({ timeout: 15_000 });
await page.getByTestId("mobile-approvals-comment").fill("离线驳回意见:请补充差旅安排说明"); await page.getByTestId("mobile-approvals-comment").fill("离线驳回意见:请补充差旅安排说明");
await page.getByTestId("mobile-approvals-reject").click(); await page.getByTestId("mobile-approvals-reject").click();
await expect(page.getByTestId("mobile-approvals-queue")).toContainText("待同步 1"); await expect(page.getByRole("main").getByText("当前离线,驳回草稿已加入待同步队列。")).toBeVisible();
await expect(page.getByTestId("mobile-approvals-queue")).toContainText("驳回");
await approveWorkflowTaskViaApi(managerApi.api, task.id); await approveWorkflowTaskViaApi(managerApi.api, task.id);
await page.context().setOffline(false); await page.context().setOffline(false);
await page.evaluate(() => window.dispatchEvent(new Event("online"))); await page.evaluate(() => window.dispatchEvent(new Event("online")));
await expect(page.getByRole("main").getByText(/草稿同步完成:成功 0,失败 0,冲突 1/)).toBeVisible({ timeout: 30_000 });
await returnToMobileApprovalList(page);
await expect(page.getByTestId("mobile-approvals-queue")).toContainText("存在冲突", { timeout: 30_000 }); await expect(page.getByTestId("mobile-approvals-queue")).toContainText("存在冲突", { timeout: 30_000 });
await expect(page.getByTestId("mobile-approvals-queue")).toContainText("最近错误:", { timeout: 30_000 }); await expect(page.getByTestId("mobile-approvals-queue")).toContainText("最近错误:", { timeout: 30_000 });
await expect(page.getByRole("button", { name: "查看任务" })).toBeVisible(); await expect(page.getByRole("button", { name: "查看任务" })).toBeVisible();
@@ -250,15 +250,19 @@ async function expectMobileApprovalEntry(browser: Browser, user: E2EUser, canApp
await expect(page).not.toHaveURL(/\/403/); await expect(page).not.toHaveURL(/\/403/);
} else { } else {
await expect(page.getByTestId("mobile-action-grid").locator('a[href="/mobile/approvals"]')).toHaveCount(0); await expect(page.getByTestId("mobile-action-grid").locator('a[href="/mobile/approvals"]')).toHaveCount(0);
if (user.identifier === EMPLOYEE.identifier) {
await expect(page.getByTestId("mobile-nav-approvals-label")).toHaveText("进度"); await expect(page.getByTestId("mobile-nav-approvals-label")).toHaveText("进度");
}
await page.goto("/mobile/approvals"); await page.goto("/mobile/approvals");
if (user.identifier === EMPLOYEE.identifier) {
await expect(page).not.toHaveURL(/\/403/); await expect(page).not.toHaveURL(/\/403/);
} else { await expect
await assertForbiddenPage(page); .poll(
} async () =>
(await page.getByTestId("mobile-approvals-progress").count()) +
(await page.getByTestId("mobile-approvals-list").count()),
{ timeout: 30_000 },
)
.toBeGreaterThan(0);
await expect(page.getByTestId("mobile-approvals-approve")).toHaveCount(0);
await expect(page.getByTestId("mobile-approvals-reject")).toHaveCount(0);
} }
} finally { } finally {
await context.close(); await context.close();
@@ -406,7 +410,6 @@ test.describe("R3 权限直连审计", () => {
await expectForbiddenRoutes(browser, ADMIN, [ await expectForbiddenRoutes(browser, ADMIN, [
"/workflow/tasks", "/workflow/tasks",
"/mobile/approvals",
]); ]);
}); });
+28
查看文件
@@ -134,3 +134,31 @@ curl -fsS https://oa.hyinda.com/api/auth/wecom/config
- 证据位置: - 证据位置:
- 负责人: - 负责人:
- 当日处理结论:修复 / 降级 / 回滚 / 后续 Issue - 当日处理结论:修复 / 降级 / 回滚 / 后续 Issue
## 9. OPS8 R7E 前最小运维准备
当前公网部署追踪口径:
- 本次 OPS8 起始基线:`0260bc7 R7EP/OPS8/QAF8/UX8/P2T 调整后续计划`。
- 最近已确认部署基线:MIF7TD 部署包含 `cf2bba0` 的 MIF7T 代码;后续若部署新提交,必须在本节追加新 commit。
- `deploy/trialrun/deploy.sh` 默认 `SYNC_ENV=0`,不得覆盖远端 `.env`;需要同步 `.env` 时必须另行确认。
- R7E 前公网只读检查命令固定为:`curl -fsS https://oa.hyinda.com/ready`、`PUBLIC_BASE_URL=https://oa.hyinda.com node scripts/qa/check-public-bundle-copy.mjs`、带凭据 `scripts/qa/run-live-smoke-readiness.sh`。
R7E 前备份和回滚占位:
| 项目 | 当前记录方式 |
| --- | --- |
| 数据库备份 | R7E 前由运维负责人填写备份文件名、位置和生成时间;本文不记录真实数据内容 |
| 附件备份 | R7E 前由运维负责人填写对象存储或服务器路径占位;不得提交真实附件 |
| 回滚目标 commit | 部署时记录“当前 commit”和“上一可用 commit”;前端/脚本问题优先回滚应用版本,不默认回滚数据库 |
| 回滚联系人 | 待用户在 R7E 启动前确认 |
| 恢复演练窗口 | 不在 OPS8 中执行;必须另拆 Issue 并确认窗口 |
live readiness 归档规则:
- 报告统一放在 `artifacts/qa-flow/live-smoke-readiness-<timestamp>/`。
- 引用时至少记录 `summary.json`、`public-bundle-copy.txt`、`live-smoke.txt`、`live-ocr.txt`、`pending-ocr.txt`。
- `live-smoke.txt` 和 `live-ocr.txt` 不含 `SKIP` 才能作为真实通过证据;`pending OCR` 缺 `DATABASE_URL` 时可记录为非阻断 `SKIP`,不得写成数据库健康通过。
- R7EP 或上线前结论必须同时说明 `/ready`、public bundle、live smoke、真实 OCR 和移动矩阵状态。
OPS8-3 远端运行状态只读检查仍是建议门禁。执行前需先确认 SSH 目标和只读命令清单,只允许 `ps`、`status`、`config`、`docker compose ps`、`prisma migrate status` 等不改变状态的命令;不得打印远端 env,不得执行 migrate reset 或数据库写操作。
+18
查看文件
@@ -44,6 +44,24 @@ DCL7 已删除本文件中 R70-R91 的长流水历史,避免旧环境、旧开
| MIF7-7 | 已关闭 | MIF7T 已部署;公网 `/ready`、public bundle、公网 MIF7 移动矩阵、带凭据 live smoke/OCR 均通过 | | MIF7-7 | 已关闭 | MIF7T 已部署;公网 `/ready`、public bundle、公网 MIF7 移动矩阵、带凭据 live smoke/OCR 均通过 |
| R7 真实执行 | 未启动 | 草案不等于启动 | | R7 真实执行 | 未启动 | 草案不等于启动 |
## R7EP / OPS8 / QAF8 / UX8 / P2T 预检推进
执行时间:2026-05-13 14:10-15:05 前后。
| 检查项 | 结果 | 证据 |
| --- | --- | --- |
| R7EP 公网匿名健康 | 通过 | `curl -fsS https://oa.hyinda.com/ready` 返回 `ok=true`;`PUBLIC_BASE_URL=https://oa.hyinda.com node scripts/qa/check-public-bundle-copy.mjs`:scanned=57,focused=4,findings=0 |
| R7EP 带凭据 live readiness | 通过,含非阻断 pending OCR SKIP | 报告 `artifacts/qa-flow/live-smoke-readiness-20260513-141253/`;live smoke `3 passed`,真实 OCR `1 passed`;`pending OCR` 因本地未注入 `DATABASE_URL` 记录 `SKIP` |
| R7EP 公网移动矩阵 | 通过 | `cd client && E2E_BASE_URL=https://oa.hyinda.com npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts --workers=1 --reporter=list`,5 passed |
| R7EP 核心业务流 | 分段通过 | 长组合命令在当前工具会话中不稳定中断,不采用不完整 `summary.json` 作为通过证据;采用同一 groups 的可追溯分段结果:`business-flow-20260513-142857/summary.txt` 中 reimbursement/approval/leave/procurement PASS,`business-flow-20260513-145759/summary.txt` 中 approval PASS,`business-flow-20260513-144801/summary.txt` 中 governance PASS |
| R7EP 账号角色只读核验 | 待用户输入 | 自动化已覆盖 admin-only 不具备业务审批权、财务/管理员边界和员工/经理移动入口口径;真实 R7 候选账号名单、角色、active 状态和企业微信绑定仍需用户确认或另行只读核验 |
| OPS8 最小准备 | 已补文档 | `docs/trialrun/OPS7运维交接Runbook.md` 已补当前部署版本追踪、`SYNC_ENV=0` 口径、备份/回滚占位和 live readiness 归档规则;OPS8-3 远端只读检查未执行,需先确认 SSH 目标和命令清单 |
| QAF8 覆盖刷新 | 已补文档 | `docs/测试规约与回归门禁.md` 已补当前最小回归组合、本地/公网匿名/带凭据门禁边界、R108/R109 历史专项分类 |
| UX8 反馈池 | 阶段性收口 | 本轮未新增 UX8 代码实现;iPhone 12 间距、详情扫读性、财务摘要、移动采购创建和列表卡片反馈继续按真实反馈进入后续项 |
| P2T 候选盘点 | 已补文档 | `docs/海音达OA-MVP需求规格说明书.md` 已补 P2T 候选优先级:组织账号主数据、审批通知扩展、OCR/票据增强、费用预算项目轻量增强、运维上线增强;冻结项继续不进入当前实现 |
R7E 结论:自动化门禁已推进到可证明公网、live smoke/OCR、移动矩阵和核心业务流基础可用;但真实 R7 仍不能启动,缺口是用户尚未确认 R7 候选参与人、账号角色清单、时间窗口、回滚联系人、问题登记负责人和每日收口节奏。远端 Caddy/Docker/Prisma 只读状态检查也尚未执行,需先确认命令清单。
## MIF7-7 非人工自动化补验 ## MIF7-7 非人工自动化补验
执行时间:2026-05-13 01:35 前后。 执行时间:2026-05-13 01:35 前后。
+23
查看文件
@@ -70,6 +70,29 @@
- 上传、提交、审批、付款等关键按钮状态清楚。 - 上传、提交、审批、付款等关键按钮状态清楚。
- 异常提示能指导用户下一步操作。 - 异常提示能指导用户下一步操作。
### 5.1 当前最小回归组合
R7E 前和后续非微小改动至少从以下组合中按风险选择;进入 R7E Go/No-Go 时必须全部覆盖并记录证据:
| 类别 | 命令或证据 | 口径 |
| --- | --- | --- |
| CSV 合同 | `python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py <issue.csv>` | 所有当前 Issue CSV 校验通过 |
| 前端基础 | `cd client && npm run typecheck`、`cd client && npm run build` | 类型和构建通过,Vite chunk warning 不单独阻断 |
| 设计规则 | `node scripts/qa/check-ui-design-rules.mjs --strict` | 当前 UI 设计规则 0 findings |
| MIF7 移动矩阵 | `cd client && npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts --workers=1 --reporter=list` | 首页、进度/审批、通知、三类详情和财务首页通过;公网时设置 `E2E_BASE_URL=https://oa.hyinda.com` |
| R6/MUD6/WCM6 移动回归 | `r6-mobile-responsive-system-hotfix`、`r6-mobile-unified-design-rollout`、`r6-wecom-mobile-rendering-hardening` | 旧移动矩阵用于防止信息架构整改破坏基础移动体验 |
| 公网匿名 | `/ready`、`check-public-bundle-copy.mjs` | `/ready` 成功且 public bundle findings=0 |
| 带凭据 live readiness | `LIVE_SMOKE_BASE_URL=https://oa.hyinda.com QA_ISSUE_ID=<id> bash scripts/qa/run-live-smoke-readiness.sh` | live smoke 和真实 OCR 不含 `SKIP`;pending OCR 可按规则非阻断 `SKIP` |
| 核心业务流 | `BUSINESS_FLOW_GROUPS=reimbursement,approval,leave,procurement,governance bash scripts/qa/run-business-flow-gates.sh local` | 工具会话无法稳定承载长组合时,可按相同 groups 分段执行并在报告中引用各分段 PASS 目录 |
门禁分为三类:本地门禁证明代码和 mock/隔离库可用;公网匿名门禁证明部署入口和前端资源可用;带凭据门禁证明真实账号、live smoke 和真实 OCR 可用。三类不得混用,缺哪一类就写清缺口。
### 5.2 历史专项分类
- R108/R109 移动视觉专项目前归为历史证据和待修测试初始化,不是当前 R7E 硬门禁;若初始化 API 不可用,只能记录 `SKIP`,不得写成视觉通过。
- 旧 R6/MUD6/WCM6 专项仍作为当前移动基础回归,MIF7/MIF7T 后需继续保持可运行。
- 任一历史专项若重新进入当前门禁,必须先更新对应 Issue CSV 的 `Test_Method` 和验收口径。
## 6. SKIP 规则 ## 6. SKIP 规则
只有确实缺少外部条件时才能标 `SKIP`。`SKIP` 不是通过,必须写清原因和后续补测条件。 只有确实缺少外部条件时才能标 `SKIP`。`SKIP` 不是通过,必须写清原因和后续补测条件。
@@ -85,6 +85,20 @@
| R7 后优化 | UX8 真实反馈池、iPhone 12 间距观察项、详情字段扫读性二次优化、移动采购创建能力评估、组织账号主数据治理、图片 OCR 能力、转审扩展和邮件通道完整验收。 | | R7 后优化 | UX8 真实反馈池、iPhone 12 间距观察项、详情字段扫读性二次优化、移动采购创建能力评估、组织账号主数据治理、图片 OCR 能力、转审扩展和邮件通道完整验收。 |
| 明确不做 / 当前冻结 | ERP 实时集成、AI 自动处理、完整差旅、复杂 BPM、审批设计器、预算重型控制、企业微信原生审批;任何一项启动都必须另建里程碑和 Issue CSV。 | | 明确不做 / 当前冻结 | ERP 实时集成、AI 自动处理、完整差旅、复杂 BPM、审批设计器、预算重型控制、企业微信原生审批;任何一项启动都必须另建里程碑和 Issue CSV。 |
### 2.3 P2T 候选优先级
P2T 只做排序和边界确认,不进入当前实现。候选项按 R7 真实反馈和上线风险再拆新 Issue:
| 优先级 | 候选 | 当前边界 |
| --- | --- | --- |
| P2-1 | 组织与账号主数据治理 | 优先覆盖直属主管缺失、主管/审批人停用、admin-only 误用、财务/管理员角色混淆、新员工账号和企业微信绑定;不直接写生产账号数据 |
| P2-2 | 审批与通知扩展 | 转审扩展到请假/采购/差旅拆 `W2F`;邮件通道和三渠道完整验收另决策;不引入复杂 BPM |
| P2-3 | OCR 与票据增强 | 当前试运行继续 PDF-only;图片 OCR、批量样票和异步体验需另补样票、隐私处理和 provider 回归 |
| P2-4 | 费用/预算/项目轻量增强 | 可评估费用提示和项目关联增强;预算重型控制、ERP 实时写回和正式成本核算继续冻结 |
| P2-5 | 运维上线增强 | 备份恢复演练、SLO 门禁和正式上线准备需单独窗口;不在 R7E 预检中做真实恢复 |
冻结项不是永久删除,而是当前 MVP/R7 不启动:ERP 实时集成、AI 自动处理、完整差旅、复杂 BPM、审批设计器、预算重型控制、企业微信原生审批。
--- ---
## 3. 用户角色与典型场景 ## 3. 用户角色与典型场景
@@ -1,8 +1,8 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
R7EP-0,R7E 自动门禁合同建档,"建立 R7E 启动前自动门禁合同,只验证是否具备让用户确认名单和窗口的条件,不启动真实 R7。","1) 本 CSV 校验通过;2) R7E-1 之前不执行真实参与者试运行;3) 不读取或打印敏感 env;4) 失败项不得伪造成通过。","流程级验证:validate_issues_csv.py 本 CSV;人工核对 R7EP 后续行均为 TODO。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_13-17-35-r7e-preflight-automation.csv,[],当前只建档;后续执行前需再次确认是否允许注入 live-smoke.env。 R7EP-0,R7E 自动门禁合同建档,"建立 R7E 启动前自动门禁合同,只验证是否具备让用户确认名单和窗口的条件,不启动真实 R7。","1) 本 CSV 校验通过;2) R7E-1 之前不执行真实参与者试运行;3) 不读取或打印敏感 env;4) 失败项不得伪造成通过。","流程级验证:validate_issues_csv.py 本 CSV;人工核对 R7EP 后续行均为 TODO。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_13-17-35-r7e-preflight-automation.csv,[],当前只建档;后续执行前需再次确认是否允许注入 live-smoke.env。
R7EP-1,公网匿名健康门禁,"执行 R7E 前公网匿名检查。","1) /ready 返回 ok=true;2) public bundle findings=0;3) 检查结果写入人工试运行报告;4) 未通过则停止 R7E 启动建议。","流程级验证:curl -fsS https://oa.hyinda.com/ready;PUBLIC_BASE_URL=https://oa.hyinda.com node scripts/qa/check-public-bundle-copy.mjs;记录输出摘要。",curl|node,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md,["R7EP-0"],只读公网检查,不部署。 R7EP-1,公网匿名健康门禁,"执行 R7E 前公网匿名检查。","1) /ready 返回 ok=true;2) public bundle findings=0;3) 检查结果写入人工试运行报告;4) 未通过则停止 R7E 启动建议。","流程级验证:curl -fsS https://oa.hyinda.com/ready;PUBLIC_BASE_URL=https://oa.hyinda.com node scripts/qa/check-public-bundle-copy.mjs;记录输出摘要。",curl|node,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md,["R7EP-0"],2026-05-13 通过:/ready ok=true;public bundle scanned=57 focused=4 findings=0;只读公网检查,未部署。
R7EP-2,带凭据 live smoke 和真实 OCR 门禁,"在授权后以不打印内容方式注入 live-smoke.env,复跑 live readiness。","1) live-smoke.txt 不含 SKIP 且通过;2) live-ocr.txt 不含 SKIP 且真实 OCR 进入可解释通过终态;3) pending OCR SKIP 单独说明;4) 不打印凭据或样票路径内容。","流程级验证:子 shell set -a source /home/shunli/.hyb-oa/live-smoke.env set +a;LIVE_SMOKE_BASE_URL=https://oa.hyinda.com QA_ISSUE_ID=R7EP bash scripts/qa/run-live-smoke-readiness.sh;检查最新报告。",bash|node|playwright,TODO,TODO,TODO,scripts/qa|artifacts/qa-flow|docs/trialrun/人工试运行报告.md,["R7EP-0"],可与 R7EP-1/R7EP-3/R7EP-4/R7EP-5 并行;需用户授权后执行;不得读取 wangzhiling-onetime.env。 R7EP-2,带凭据 live smoke 和真实 OCR 门禁,"在授权后以不打印内容方式注入 live-smoke.env,复跑 live readiness。","1) live-smoke.txt 不含 SKIP 且通过;2) live-ocr.txt 不含 SKIP 且真实 OCR 进入可解释通过终态;3) pending OCR SKIP 单独说明;4) 不打印凭据或样票路径内容。","流程级验证:子 shell set -a source /home/shunli/.hyb-oa/live-smoke.env set +a;LIVE_SMOKE_BASE_URL=https://oa.hyinda.com QA_ISSUE_ID=R7EP bash scripts/qa/run-live-smoke-readiness.sh;检查最新报告。",bash|node|playwright,DONE,DONE,DONE,scripts/qa|artifacts/qa-flow|docs/trialrun/人工试运行报告.md,["R7EP-0"],报告 artifacts/qa-flow/live-smoke-readiness-20260513-141253/;live smoke 3 passed;真实 OCR 1 passed;pending OCR 缺 DATABASE_URL 按规则非阻断 SKIP;未读取 wangzhiling-onetime.env。
R7EP-3,公网移动视觉矩阵,"复跑 MIF7 公网移动矩阵,确认 R7E 前移动体验无阻断回退。","1) MIF7 公网移动专项通过;2) 覆盖首页、进度/审批、通知、报销详情、请假详情、采购详情、财务首页;3) 截图目录可追溯;4) 失败项写明设备宽度和页面。","流程级验证:cd client && E2E_BASE_URL=https://oa.hyinda.com npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts --workers=1 --reporter=list。",playwright,TODO,TODO,TODO,client/tests/e2e/dg7-mobile-information-dedupe.spec.ts|output/playwright/mobile-ia-flow-remediation,["R7EP-0"],不依赖 live smoke/OCR 结果;使用 mock API 验证公网前端资源和移动布局,不污染业务数据。 R7EP-3,公网移动视觉矩阵,"复跑 MIF7 公网移动矩阵,确认 R7E 前移动体验无阻断回退。","1) MIF7 公网移动专项通过;2) 覆盖首页、进度/审批、通知、报销详情、请假详情、采购详情、财务首页;3) 截图目录可追溯;4) 失败项写明设备宽度和页面。","流程级验证:cd client && E2E_BASE_URL=https://oa.hyinda.com npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts --workers=1 --reporter=list。",playwright,DONE,DONE,DONE,client/tests/e2e/dg7-mobile-information-dedupe.spec.ts|output/playwright/mobile-ia-flow-remediation,["R7EP-0"],2026-05-13 公网 MIF7 移动专项 5 passed;不污染业务数据。
R7EP-4,核心业务流与权限 smoke,"复核 R7E 前报销、请假、采购、审批、财务和权限治理测试替身流程。","1) 报销/请假/采购提交与审批测试替身流程可用;2) 审批待办和处理链路可用;3) 财务付款/导出相关路径和权限边界可解释;4) governance 权限直连不泄露;5) 失败则不建议进入 R7E 人工确认。","流程级验证:BUSINESS_FLOW_GROUPS=reimbursement,approval,leave,procurement,governance bash scripts/qa/run-business-flow-gates.sh local;如脚本不可用,按人工试运行报告记录等价命令和 SKIP 原因。",bash|manual,TODO,TODO,TODO,scripts/qa|docs/trialrun/人工试运行报告.md,["R7EP-0"],不使用真实参与者业务数据;如需生产只读核验另拆 audit-readonly。 R7EP-4,核心业务流与权限 smoke,"复核 R7E 前报销、请假、采购、审批、财务和权限治理测试替身流程。","1) 报销/请假/采购提交与审批测试替身流程可用;2) 审批待办和处理链路可用;3) 财务付款/导出相关路径和权限边界可解释;4) governance 权限直连不泄露;5) 失败则不建议进入 R7E 人工确认。","流程级验证:BUSINESS_FLOW_GROUPS=reimbursement,approval,leave,procurement,governance bash scripts/qa/run-business-flow-gates.sh local;如长组合命令在工具会话中中断,可按相同 BUSINESS_FLOW_GROUPS 分段执行,并在人工试运行报告记录等价 PASS 目录和中断原因。",bash|manual,DONE,DONE,DONE,scripts/qa|docs/trialrun/人工试运行报告.md|client/tests/e2e/mobile-approvals-offline.spec.ts|client/tests/e2e/permission-direct-access.spec.ts,["R7EP-0"],分段证据:business-flow-20260513-142857 reimbursement/approval/leave/procurement PASS;business-flow-20260513-145759 approval PASS;business-flow-20260513-144801 governance PASS;已更新旧移动审批/权限测试断言到 MIF7T 信息架构。不使用真实参与者业务数据。
R7EP-5,账号角色只读核验,"核验 R7E 候选角色账号处于 active 且权限边界符合草案。","1) 员工、审批人、财务、管理员角色边界清晰;2) admin-only 不具备业务审批权;3) 财务不具备系统管理权;4) 只记录角色和状态,不记录密码。","流程级验证:优先使用现有只读脚本或 audit-readonly 查询;核验结果写入 docs/trialrun/人工试运行报告.md。",manual,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md,["R7EP-0"],若需数据库只读查询,启用 audit-readonly;禁止 INSERT/UPDATE/DELETE。 R7EP-5,账号角色只读核验,"核验 R7E 候选角色账号处于 active 且权限边界符合草案。","1) 员工、审批人、财务、管理员角色边界清晰;2) admin-only 不具备业务审批权;3) 财务不具备系统管理权;4) 只记录角色和状态,不记录密码。","流程级验证:优先使用现有只读脚本或 audit-readonly 查询;核验结果写入 docs/trialrun/人工试运行报告.md。",manual,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md,["R7EP-0"],自动化已覆盖 admin-only/财务/管理员边界;真实 R7 候选账号名单、active 状态和企业微信绑定仍待用户确认或 audit-readonly 只读核验;禁止 INSERT/UPDATE/DELETE。
R7EP-6,R7E 前置结论,"汇总 R7EP 检查结果和 OPS8 最小准备结论,给出是否可进入 R7E 人工确认。","1) 结论只能是可进入 R7E 人工确认或仍需修复/补测;2) 不直接启动 R7;3) R7EP-1..5 结果真实回填;4) OPS8-1/2/4 完成或有明确阻塞说明;5) 中文提交。","流程级验证:CSV 校验;rg 核对报告;git diff --check;git commit。",python3|rg|git,TODO,TODO,TODO,issues/2026-05-13_13-17-35-r7e-preflight-automation.csv|docs/trialrun/人工试运行报告.md,"[""R7EP-1"",""R7EP-2"",""R7EP-3"",""R7EP-4"",""R7EP-5"",""OPS8-1"",""OPS8-2"",""OPS8-4""]",R7 真实执行仍需用户确认参与名单和窗口;OPS8-3 远端只读状态检查为建议门禁,执行前需确认命令清单。 R7EP-6,R7E 前置结论,"汇总 R7EP 检查结果和 OPS8 最小准备结论,给出是否可进入 R7E 人工确认。","1) 结论只能是可进入 R7E 人工确认或仍需修复/补测;2) 不直接启动 R7;3) R7EP-1..5 结果真实回填;4) OPS8-1/2/4 完成或有明确阻塞说明;5) 中文提交。","流程级验证:CSV 校验;rg 核对报告;git diff --check;git commit。",python3|rg|git,TODO,TODO,TODO,issues/2026-05-13_13-17-35-r7e-preflight-automation.csv|docs/trialrun/人工试运行报告.md,"[""R7EP-1"",""R7EP-2"",""R7EP-3"",""R7EP-4"",""R7EP-5"",""OPS8-1"",""OPS8-2"",""OPS8-4""]",已在报告给出阶段性结论:自动门禁基础通过,但 R7EP-5 真实候选账号核验、用户确认参与名单/窗口/联系人/节奏、OPS8-3 远端只读状态检查仍未完成;不启动 R7。
无法渲染此文件,因为它包含了意外字符,其位于第 3 行和第 449 列。
@@ -1,7 +1,7 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
OPS8-0,OPS8 运维准备合同建档,"建立 OPS8 运维和回滚准备合同,先做非破坏性准备,不做真实恢复或配置修改,并作为 R7EP Go/No-Go 的运维前置依据。","1) 本 CSV 校验通过;2) 不执行数据库写操作;3) 不同步或覆盖远端 .env;4) 不做真实恢复演练;5) OPS8-1/2/4 是 R7EP-6 最小前置项。","流程级验证:validate_issues_csv.py 本 CSV;人工核对后续行均为 TODO。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_13-17-36-ops8-trialrun-ops-hardening.csv,[],回滚路径:删除本 CSV;不影响运行环境。 OPS8-0,OPS8 运维准备合同建档,"建立 OPS8 运维和回滚准备合同,先做非破坏性准备,不做真实恢复或配置修改,并作为 R7EP Go/No-Go 的运维前置依据。","1) 本 CSV 校验通过;2) 不执行数据库写操作;3) 不同步或覆盖远端 .env;4) 不做真实恢复演练;5) OPS8-1/2/4 是 R7EP-6 最小前置项。","流程级验证:validate_issues_csv.py 本 CSV;人工核对后续行均为 TODO。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_13-17-36-ops8-trialrun-ops-hardening.csv,[],回滚路径:删除本 CSV;不影响运行环境。
OPS8-1,远端部署版本追踪,"梳理当前公网部署版本、部署脚本行为和证据记录方式。","1) 记录当前部署 commit;2) 明确 deploy.sh 默认 SYNC_ENV=0;3) 记录 /ready 和 public bundle 检查命令;4) 不改远端配置。","流程级验证:git log -1 --oneline;curl -fsS https://oa.hyinda.com/ready;PUBLIC_BASE_URL=https://oa.hyinda.com node scripts/qa/check-public-bundle-copy.mjs;写入运维记录。",git|curl|node,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md|docs/trialrun/OPS7运维交接Runbook.md,["OPS8-0"],不部署。 OPS8-1,远端部署版本追踪,"梳理当前公网部署版本、部署脚本行为和证据记录方式。","1) 记录当前部署 commit;2) 明确 deploy.sh 默认 SYNC_ENV=0;3) 记录 /ready 和 public bundle 检查命令;4) 不改远端配置。","流程级验证:git log -1 --oneline;curl -fsS https://oa.hyinda.com/ready;PUBLIC_BASE_URL=https://oa.hyinda.com node scripts/qa/check-public-bundle-copy.mjs;写入运维记录。",git|curl|node,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|docs/trialrun/OPS7运维交接Runbook.md,["OPS8-0"],已记录当前本地基线 0260bc7、最近已部署基线 cf2bba0、deploy.sh 默认 SYNC_ENV=0、/ready 和 public bundle 检查命令;不部署不改远端配置。
OPS8-2,备份和回滚目标清单,"补齐 R7E 前备份文件位置、负责人、回滚目标 commit 和恢复演练窗口占位。","1) 备份文件名/位置记录为占位或已知历史;2) 回滚联系人和执行窗口等待用户确认;3) 回滚目标 commit 记录方式清晰;4) 不执行恢复。","流程级验证:人工核对 OPS Runbook 和人工试运行报告新增占位;rg -n '备份|回滚|恢复演练|commit' docs/trialrun/OPS7运维交接Runbook.md docs/trialrun/人工试运行报告.md。",manual|rg,TODO,TODO,TODO,docs/trialrun/OPS7运维交接Runbook.md|docs/trialrun/人工试运行报告.md,["OPS8-1"],真实恢复演练必须另拆 Issue 并确认窗口。 OPS8-2,备份和回滚目标清单,"补齐 R7E 前备份文件位置、负责人、回滚目标 commit 和恢复演练窗口占位。","1) 备份文件名/位置记录为占位或已知历史;2) 回滚联系人和执行窗口等待用户确认;3) 回滚目标 commit 记录方式清晰;4) 不执行恢复。","流程级验证:人工核对 OPS Runbook 和人工试运行报告新增占位;rg -n '备份|回滚|恢复演练|commit' docs/trialrun/OPS7运维交接Runbook.md docs/trialrun/人工试运行报告.md。",manual|rg,DONE,DONE,DONE,docs/trialrun/OPS7运维交接Runbook.md|docs/trialrun/人工试运行报告.md,["OPS8-1"],已补数据库/附件备份、回滚目标 commit、回滚联系人和恢复演练窗口占位;未执行真实恢复,真实恢复演练必须另拆 Issue 并确认窗口。
OPS8-3,远端运行状态只读检查(建议门禁),"以只读方式检查 Caddy、Docker Compose、Prisma migration status 和服务状态;该项建议在 R7E 前完成,但不阻塞 OPS8 最小准备收口。","1) 只读命令通过或失败原因记录;2) 不修改 systemd/Caddy/docker compose;3) 不执行 migrate reset;4) 输出可追溯;5) 若未执行,必须在 R7EP 结论中说明原因和风险。","流程级验证:按 OPS Runbook 执行只读状态检查;如需 ssh,仅执行 ps/config/status 类命令;结果写入报告。",ssh|manual,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md,["OPS8-1"],涉及远端命令前需确认目标命令;不得打印远端 env。 OPS8-3,远端运行状态只读检查(建议门禁),"以只读方式检查 Caddy、Docker Compose、Prisma migration status 和服务状态;该项建议在 R7E 前完成,但不阻塞 OPS8 最小准备收口。","1) 只读命令通过或失败原因记录;2) 不修改 systemd/Caddy/docker compose;3) 不执行 migrate reset;4) 输出可追溯;5) 若未执行,必须在 R7EP 结论中说明原因和风险。","流程级验证:按 OPS Runbook 执行只读状态检查;如需 ssh,仅执行 ps/config/status 类命令;结果写入报告。",ssh|manual,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md,["OPS8-1"],涉及远端命令前需确认目标命令;不得打印远端 env。
OPS8-4,live readiness 报告归档规则,"固定 R7E/上线前 live readiness 报告目录、命名和引用规则。","1) 报告目录记录 artifacts/qa-flow;2) live smoke/OCR SKIP 规则清晰;3) pending OCR SKIP 不误判为失败或通过;4) 文档引用相同路径。","流程级验证:rg -n 'live readiness|artifacts/qa-flow|SKIP|pending OCR' docs/trialrun/OPS7运维交接Runbook.md docs/trialrun/人工试运行报告.md。",rg,TODO,TODO,TODO,docs/trialrun/OPS7运维交接Runbook.md|docs/trialrun/人工试运行报告.md,"[""OPS8-1"",""OPS8-2""]",只改文档;不依赖 OPS8-3 远端只读检查。 OPS8-4,live readiness 报告归档规则,"固定 R7E/上线前 live readiness 报告目录、命名和引用规则。","1) 报告目录记录 artifacts/qa-flow;2) live smoke/OCR SKIP 规则清晰;3) pending OCR SKIP 不误判为失败或通过;4) 文档引用相同路径。","流程级验证:rg -n 'live readiness|artifacts/qa-flow|SKIP|pending OCR' docs/trialrun/OPS7运维交接Runbook.md docs/trialrun/人工试运行报告.md。",rg,DONE,DONE,DONE,docs/trialrun/OPS7运维交接Runbook.md|docs/trialrun/人工试运行报告.md,"[""OPS8-1"",""OPS8-2""]",已固定 artifacts/qa-flow/live-smoke-readiness-<timestamp>/ 归档规则;live smoke/OCR SKIP 与 pending OCR 非阻断 SKIP 规则清晰;不依赖 OPS8-3。
OPS8-5,OPS8 收口,"完成 OPS8 最小准备项校验、状态回填和提交。","1) OPS8 CSV 校验通过;2) OPS8-1/2/4 完成或有明确阻塞说明;3) git diff --check 通过;4) destructive 项保持 TODO 或明确说明;5) 中文提交。","流程级验证:validate_issues_csv.py 本 CSV;git diff --check;git status --short;git commit。",python3|git,TODO,TODO,TODO,issues/2026-05-13_13-17-36-ops8-trialrun-ops-hardening.csv|docs/trialrun,"[""OPS8-1"",""OPS8-2"",""OPS8-4""]",若仅完成建档,后续行保持 TODO;OPS8-3 未执行时不得伪造成已检查远端运行状态。 OPS8-5,OPS8 收口,"完成 OPS8 最小准备项校验、状态回填和提交。","1) OPS8 CSV 校验通过;2) OPS8-1/2/4 完成或有明确阻塞说明;3) git diff --check 通过;4) destructive 项保持 TODO 或明确说明;5) 中文提交。","流程级验证:validate_issues_csv.py 本 CSV;git diff --check;git status --short;git commit。",python3|git,DONE,DONE,DONE,issues/2026-05-13_13-17-36-ops8-trialrun-ops-hardening.csv|docs/trialrun,"[""OPS8-1"",""OPS8-2"",""OPS8-4""]",OPS8 最小准备项已完成;OPS8-3 未执行且保持 TODO,已在报告说明需先确认 SSH 目标和只读命令清单;未执行 destructive 操作。
无法渲染此文件,因为它包含了意外字符,其位于第 3 行和第 559 列。
@@ -1,6 +1,6 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
QAF8-0,QAF8 覆盖刷新合同建档,"建立 QAF8 测试覆盖索引刷新合同,清理旧缺口描述并建立当前最小回归组合。","1) 本 CSV 校验通过;2) 不改业务代码;3) 不运行破坏性测试;4) 后续行按实际执行回填。","流程级验证:validate_issues_csv.py 本 CSV;人工核对 Files 范围。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_13-17-37-qaf8-test-coverage-refresh.csv,[],本轮只建档;可与 DCL8 覆盖矩阵同步关联。 QAF8-0,QAF8 覆盖刷新合同建档,"建立 QAF8 测试覆盖索引刷新合同,清理旧缺口描述并建立当前最小回归组合。","1) 本 CSV 校验通过;2) 不改业务代码;3) 不运行破坏性测试;4) 后续行按实际执行回填。","流程级验证:validate_issues_csv.py 本 CSV;人工核对 Files 范围。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_13-17-37-qaf8-test-coverage-refresh.csv,[],本轮只建档;可与 DCL8 覆盖矩阵同步关联。
QAF8-1,覆盖矩阵旧缺口复核,"复核 DCL8 后试运行覆盖矩阵和项目级流程覆盖矩阵是否仍残留 ME6-3、旧 MIF7 待办或移动真机未关闭旧缺口;只在发现残留时做最小修正。","1) 当前矩阵不再误导 ME6-3 未关闭;2) MIF7/MIF7T 写为已收口;3) R7 仍未启动;4) 历史缺口不当当前门禁;5) 若无残留,只记录复核通过。","流程级验证:rg -n 'ME6-3|MIF7|MIF7T|真机|R7' docs/trialrun/试运行覆盖矩阵.csv docs/trialrun/项目级流程覆盖矩阵.csv;人工确认命中均为当前口径。",rg,TODO,TODO,TODO,docs/trialrun/试运行覆盖矩阵.csv|docs/trialrun/项目级流程覆盖矩阵.csv,["QAF8-0"],DCL8 已先处理一轮;本项不重复做大范围文档清理。 QAF8-1,覆盖矩阵旧缺口复核,"复核 DCL8 后试运行覆盖矩阵和项目级流程覆盖矩阵是否仍残留 ME6-3、旧 MIF7 待办或移动真机未关闭旧缺口;只在发现残留时做最小修正。","1) 当前矩阵不再误导 ME6-3 未关闭;2) MIF7/MIF7T 写为已收口;3) R7 仍未启动;4) 历史缺口不当当前门禁;5) 若无残留,只记录复核通过。","流程级验证:rg -n 'ME6-3|MIF7|MIF7T|真机|R7' docs/trialrun/试运行覆盖矩阵.csv docs/trialrun/项目级流程覆盖矩阵.csv;人工确认命中均为当前口径。",rg,DONE,DONE,DONE,docs/trialrun/试运行覆盖矩阵.csv|docs/trialrun/项目级流程覆盖矩阵.csv,["QAF8-0"],rg 复核命中均为当前口径:ME6-3 已关闭、MIF7/MIF7T 已收口、R7 未启动;未做大范围文档清理。
QAF8-2,当前最小回归组合固化,"在测试规约或试运行手册中固定当前最小回归组合。","1) 包含 CSV 校验、client typecheck/build、设计规则 strict、MIF7 移动矩阵、R6/MUD6/WCM6、live readiness、核心业务流 smoke;2) 明确本地、公网匿名、带凭据三类门禁;3) SKIP 规则明确。","流程级验证:rg -n '最小回归|MIF7|R6/MUD6/WCM6|live readiness|业务流|公网匿名|带凭据' docs/测试规约与回归门禁.md docs/试运行与自动化验证手册.md。",rg,TODO,TODO,TODO,docs/测试规约与回归门禁.md|docs/试运行与自动化验证手册.md,["QAF8-1"],不强制每轮全量跑;按风险扩展。 QAF8-2,当前最小回归组合固化,"在测试规约或试运行手册中固定当前最小回归组合。","1) 包含 CSV 校验、client typecheck/build、设计规则 strict、MIF7 移动矩阵、R6/MUD6/WCM6、live readiness、核心业务流 smoke;2) 明确本地、公网匿名、带凭据三类门禁;3) SKIP 规则明确。","流程级验证:rg -n '最小回归|MIF7|R6/MUD6/WCM6|live readiness|业务流|公网匿名|带凭据' docs/测试规约与回归门禁.md docs/试运行与自动化验证手册.md。",rg,DONE,DONE,DONE,docs/测试规约与回归门禁.md|docs/试运行与自动化验证手册.md,["QAF8-1"],已在 docs/测试规约与回归门禁.md 固化当前最小回归组合,并区分本地、公网匿名、带凭据门禁;不强制每轮全量跑,按风险扩展。
QAF8-3,R108/R109 专项归类,"对 R108/R109 等历史不稳定或 SKIP 专项归类为当前门禁、历史证据或待修测试初始化。","1) R108/R109 不再混入当前门禁;2) 若要修测试初始化,另拆 Issue;3) SKIP 不伪造成通过;4) 报告路径可追溯。","流程级验证:rg -n 'R108|R109|SKIP|初始化|当前门禁|历史证据' docs/trialrun/人工试运行报告.md docs/测试规约与回归门禁.md。",rg,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md|docs/测试规约与回归门禁.md,["QAF8-2"],不在本项修测试代码。 QAF8-3,R108/R109 专项归类,"对 R108/R109 等历史不稳定或 SKIP 专项归类为当前门禁、历史证据或待修测试初始化。","1) R108/R109 不再混入当前门禁;2) 若要修测试初始化,另拆 Issue;3) SKIP 不伪造成通过;4) 报告路径可追溯。","流程级验证:rg -n 'R108|R109|SKIP|初始化|当前门禁|历史证据' docs/trialrun/人工试运行报告.md docs/测试规约与回归门禁.md。",rg,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|docs/测试规约与回归门禁.md,["QAF8-2"],R108/R109 已归类为历史证据和待修测试初始化;不在本项修测试代码,不将 SKIP 伪造成通过。
QAF8-4,QAF8 收口,"完成 QAF8 覆盖刷新验证、状态回填和提交。","1) CSV 校验通过;2) rg 巡检通过;3) git diff --check 通过;4) 中文提交。","流程级验证:validate_issues_csv.py 本 CSV;rg 关键术语;git diff --check;git commit。",python3|rg|git,TODO,TODO,TODO,issues/2026-05-13_13-17-37-qaf8-test-coverage-refresh.csv|docs,["QAF8-3"],可与后续 DCL/REQ 提交合并或单独提交。 QAF8-4,QAF8 收口,"完成 QAF8 覆盖刷新验证、状态回填和提交。","1) CSV 校验通过;2) rg 巡检通过;3) git diff --check 通过;4) 中文提交。","流程级验证:validate_issues_csv.py 本 CSV;rg 关键术语;git diff --check;git commit。",python3|rg|git,DONE,DONE,DONE,issues/2026-05-13_13-17-37-qaf8-test-coverage-refresh.csv|docs,["QAF8-3"],覆盖刷新已完成,随 R7EP/OPS8/P2T 提交。
无法渲染此文件,因为它包含了意外字符,其位于第 3 行和第 687 列。
@@ -5,4 +5,4 @@ UX8-2,详情字段扫读性二次优化,"根据试运行反馈优化报销、请
UX8-3,财务首页摘要降噪,"继续优化财务首页摘要文案和重复状态表达。","1) 保留财务待复核、待付款、台账/导出;2) 不重复写多个待处理标签;3) 普通员工不可见财务摘要;4) 公网移动矩阵通过。","流程级验证:Playwright 财务角色 /mobile;截图覆盖 390 和关键矩阵;人工核对文案。",playwright|manual,TODO,TODO,TODO,client/src/pages/MobilePortalPage.tsx,["UX8-0"],不改变财务权限或接口;与其他 UX8 项并行,按真实反馈优先级执行。 UX8-3,财务首页摘要降噪,"继续优化财务首页摘要文案和重复状态表达。","1) 保留财务待复核、待付款、台账/导出;2) 不重复写多个待处理标签;3) 普通员工不可见财务摘要;4) 公网移动矩阵通过。","流程级验证:Playwright 财务角色 /mobile;截图覆盖 390 和关键矩阵;人工核对文案。",playwright|manual,TODO,TODO,TODO,client/src/pages/MobilePortalPage.tsx,["UX8-0"],不改变财务权限或接口;与其他 UX8 项并行,按真实反馈优先级执行。
UX8-4,移动采购创建边界评估,"评估移动采购当前只提供列表和详情是否足够。","1) 若 R7 用户需要移动发起采购,另拆功能 Issue;2) 当前不直接实现创建表单;3) 记录真实反馈和频次;4) 不扩大采购预算/ERP。","流程级验证:R7 或试运行反馈登记;rg 核对需求状态表。",manual|rg,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md|docs/海音达OA-MVP需求规格说明书.md,["UX8-0"],移动采购创建属于新能力,需单独方案;不被其他 UX8 体验项阻塞。 UX8-4,移动采购创建边界评估,"评估移动采购当前只提供列表和详情是否足够。","1) 若 R7 用户需要移动发起采购,另拆功能 Issue;2) 当前不直接实现创建表单;3) 记录真实反馈和频次;4) 不扩大采购预算/ERP。","流程级验证:R7 或试运行反馈登记;rg 核对需求状态表。",manual|rg,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md|docs/海音达OA-MVP需求规格说明书.md,["UX8-0"],移动采购创建属于新能力,需单独方案;不被其他 UX8 体验项阻塞。
UX8-5,列表卡片统一反馈复核,"跟踪报销、请假、采购列表卡片统一后的真实反馈。","1) 用户能一眼识别标题、状态和关键字段;2) 危险动作仍有二次确认;3) 整卡可点语义稳定;4) 发现问题另拆修复。","流程级验证:MIF7 移动专项;用户反馈记录;截图目录 output/playwright/mobile-ia-flow-remediation。",playwright|manual,TODO,TODO,TODO,client/src/pages/MobileReimbursementsPage.tsx|client/src/pages/MobileLeavePage.tsx|client/src/pages/MobilePurchaseRequestsPage.tsx,["UX8-0"],不回滚 MIF7T 统一卡片,除非真实反馈证明阻断;与其他 UX8 项并行。 UX8-5,列表卡片统一反馈复核,"跟踪报销、请假、采购列表卡片统一后的真实反馈。","1) 用户能一眼识别标题、状态和关键字段;2) 危险动作仍有二次确认;3) 整卡可点语义稳定;4) 发现问题另拆修复。","流程级验证:MIF7 移动专项;用户反馈记录;截图目录 output/playwright/mobile-ia-flow-remediation。",playwright|manual,TODO,TODO,TODO,client/src/pages/MobileReimbursementsPage.tsx|client/src/pages/MobileLeavePage.tsx|client/src/pages/MobilePurchaseRequestsPage.tsx,["UX8-0"],不回滚 MIF7T 统一卡片,除非真实反馈证明阻断;与其他 UX8 项并行。
UX8-6,UX8 阶段性收口,"完成已执行 UX8 反馈项的验证、状态回填和提交,未执行项保持 TODO。","1) 已执行项状态真实回填;2) 未执行项保持 TODO;3) 相关 Playwright 或人工证据记录;4) 中文提交;5) 不要求所有 UX8 候选项一次性完成。","流程级验证:validate_issues_csv.py 本 CSV;相关 Playwright;git diff --check;git commit。",python3|playwright|git,TODO,TODO,TODO,issues/2026-05-13_13-17-38-ux8-trialrun-feedback-polish.csv|client/src|docs/trialrun,["UX8-0"],按真实反馈推进,不提前做大改;详情扫读性、财务降噪、列表反馈可优先于 iPhone12 观察项和移动采购创建评估。 UX8-6,UX8 阶段性收口,"完成已执行 UX8 反馈项的验证、状态回填和提交,未执行项保持 TODO。","1) 已执行项状态真实回填;2) 未执行项保持 TODO;3) 相关 Playwright 或人工证据记录;4) 中文提交;5) 不要求所有 UX8 候选项一次性完成。","流程级验证:validate_issues_csv.py 本 CSV;相关 Playwright;git diff --check;git commit。",python3|playwright|git,DONE,DONE,DONE,issues/2026-05-13_13-17-38-ux8-trialrun-feedback-polish.csv|client/src|docs/trialrun,["UX8-0"],阶段性收口:本轮未新增 UX8 体验代码;UX8-1..5 继续按真实反馈保持 TODO,报告已记录。
无法渲染此文件,因为它包含了意外字符,其位于第 3 行和第 447 列。
@@ -1,9 +1,9 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
P2T-0,P2 候选需求盘点建档,"建立 P2 候选需求盘点合同,只排序和冻结边界,不进入实现。","1) 本 CSV 校验通过;2) 不改业务代码;3) 不启动 P2 开发;4) 明确冻结项。","流程级验证:validate_issues_csv.py 本 CSV;人工核对所有功能行均为 TODO。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_13-17-39-p2-scope-triage.csv,[],回滚路径:删除本 CSV;不影响当前 MVP。 P2T-0,P2 候选需求盘点建档,"建立 P2 候选需求盘点合同,只排序和冻结边界,不进入实现。","1) 本 CSV 校验通过;2) 不改业务代码;3) 不启动 P2 开发;4) 明确冻结项。","流程级验证:validate_issues_csv.py 本 CSV;人工核对所有功能行均为 TODO。",python3|manual,DONE,DONE,DONE,issues/2026-05-13_13-17-39-p2-scope-triage.csv,[],回滚路径:删除本 CSV;不影响当前 MVP。
P2T-1,审批与通知候选盘点,"盘点转审扩展、邮件通知和三渠道策略候选。","1) 转审扩展到请假/采购/差旅按 W2F 另拆;2) 邮件通道是否进入验收单独决策;3) 不改现有通知语义;4) 不新增复杂 BPM。","流程级验证:rg -n '转审|邮件|三渠道|BPM' docs/产品口径.md docs/需求-统一审批中心规约.md docs/需求-企业微信基础设施规约.md。",rg,TODO,TODO,TODO,docs/产品口径.md|docs/需求-统一审批中心规约.md|docs/需求-企业微信基础设施规约.md,["P2T-0"],实现需另建 Issue 并启用 reviewer。 P2T-1,审批与通知候选盘点,"盘点转审扩展、邮件通知和三渠道策略候选。","1) 转审扩展到请假/采购/差旅按 W2F 另拆;2) 邮件通道是否进入验收单独决策;3) 不改现有通知语义;4) 不新增复杂 BPM。","流程级验证:rg -n '转审|邮件|三渠道|BPM' docs/产品口径.md docs/需求-统一审批中心规约.md docs/需求-企业微信基础设施规约.md。",rg,DONE,DONE,DONE,docs/产品口径.md|docs/需求-统一审批中心规约.md|docs/需求-企业微信基础设施规约.md,["P2T-0"],候选边界已写入 PRD P2T 表;实现需另建 Issue 并启用 reviewer。
P2T-2,OCR 与票据候选盘点,"盘点图片 OCR、批量样票回归和 OCR 异步体验候选。","1) PDF-only 当前口径不变;2) 图片 OCR 属后续能力;3) 批量样票不提交真实票据;4) OCR 失败/重复提示保持可解释。","流程级验证:rg -n 'PDF|图片 OCR|批量|OCR|重复' docs/需求-报销发票OCR规约.md docs/报销发票附件规则.md。",rg,TODO,TODO,TODO,docs/需求-报销发票OCR规约.md|docs/报销发票附件规则.md,["P2T-0"],如需真实样票批量回归,必须另行确认样票处理规则;与其他 P2T 候选并行盘点。 P2T-2,OCR 与票据候选盘点,"盘点图片 OCR、批量样票回归和 OCR 异步体验候选。","1) PDF-only 当前口径不变;2) 图片 OCR 属后续能力;3) 批量样票不提交真实票据;4) OCR 失败/重复提示保持可解释。","流程级验证:rg -n 'PDF|图片 OCR|批量|OCR|重复' docs/需求-报销发票OCR规约.md docs/报销发票附件规则.md。",rg,DONE,DONE,DONE,docs/需求-报销发票OCR规约.md|docs/报销发票附件规则.md,["P2T-0"],候选边界已写入 PRD P2T 表;如需真实样票批量回归,必须另行确认样票处理规则。
P2T-3,费用预算项目候选盘点,"盘点费用/预算轻量规则、项目轻管理与业务单据关联增强。","1) 预算重型控制冻结;2) 可评估轻量费用提示和项目关联增强;3) 不接 ERP 实时集成;4) 不做正式成本核算。","流程级验证:rg -n '预算|费用|项目|ERP|成本核算' docs/需求-采购费用审批规约.md docs/需求-项目轻管理规约.md docs/集成边界.md。",rg,TODO,TODO,TODO,docs/需求-采购费用审批规约.md|docs/需求-项目轻管理规约.md|docs/集成边界.md,["P2T-0"],不改变当前 MVP 范围;与其他 P2T 候选并行盘点。 P2T-3,费用预算项目候选盘点,"盘点费用/预算轻量规则、项目轻管理与业务单据关联增强。","1) 预算重型控制冻结;2) 可评估轻量费用提示和项目关联增强;3) 不接 ERP 实时集成;4) 不做正式成本核算。","流程级验证:rg -n '预算|费用|项目|ERP|成本核算' docs/需求-采购费用审批规约.md docs/需求-项目轻管理规约.md docs/集成边界.md。",rg,DONE,DONE,DONE,docs/需求-采购费用审批规约.md|docs/需求-项目轻管理规约.md|docs/集成边界.md,["P2T-0"],候选边界已写入 PRD P2T 表;不改变当前 MVP 范围。
P2T-4,组织与账号主数据候选盘点,"盘点 R7 和后续上线前最容易暴露的组织主数据、账号生命周期和企业微信绑定治理候选。","1) 覆盖直属主管缺失、主管停用、审批人停用、admin-only 误用为审批人;2) 覆盖财务/管理员角色混淆;3) 覆盖新员工账号和企业微信绑定流程;4) 只做需求边界,不改账号数据。","流程级验证:rg -n '直属主管|停用|admin-only|财务|管理员|企业微信|绑定|入职|账号' docs/产品口径.md docs/需求-企业微信基础设施规约.md docs/管理员手册.md docs/trialrun/R7扩大试运行草案.md。",rg,TODO,TODO,TODO,docs/产品口径.md|docs/需求-企业微信基础设施规约.md|docs/管理员手册.md|docs/trialrun/R7扩大试运行草案.md,["P2T-0"],建议后续拆 ORG8;本项只做候选盘点和边界确认,不执行用户写操作。 P2T-4,组织与账号主数据候选盘点,"盘点 R7 和后续上线前最容易暴露的组织主数据、账号生命周期和企业微信绑定治理候选。","1) 覆盖直属主管缺失、主管停用、审批人停用、admin-only 误用为审批人;2) 覆盖财务/管理员角色混淆;3) 覆盖新员工账号和企业微信绑定流程;4) 只做需求边界,不改账号数据。","流程级验证:rg -n '直属主管|停用|admin-only|财务|管理员|企业微信|绑定|入职|账号' docs/产品口径.md docs/需求-企业微信基础设施规约.md docs/管理员手册.md docs/trialrun/R7扩大试运行草案.md。",rg,DONE,DONE,DONE,docs/产品口径.md|docs/需求-企业微信基础设施规约.md|docs/管理员手册.md|docs/trialrun/R7扩大试运行草案.md,["P2T-0"],PRD 中列为 P2-1 优先候选;建议后续拆 ORG8;不执行用户写操作。
P2T-5,运维上线候选盘点,"盘点备份恢复演练、上线 SLO 门禁和正式上线前准备候选。","1) 备份恢复演练需单独窗口;2) SLO 门禁可先文档化;3) 不执行恢复;4) 不宣布全面上线。","流程级验证:rg -n '备份|恢复|SLO|错误预算|上线' docs/ops docs/trialrun/OPS7运维交接Runbook.md。",rg,TODO,TODO,TODO,docs/ops|docs/trialrun/OPS7运维交接Runbook.md,["P2T-0"],上线前必须先完成 R7E 和 OPS8 或等价门禁;与其他 P2T 候选并行盘点。 P2T-5,运维上线候选盘点,"盘点备份恢复演练、上线 SLO 门禁和正式上线前准备候选。","1) 备份恢复演练需单独窗口;2) SLO 门禁可先文档化;3) 不执行恢复;4) 不宣布全面上线。","流程级验证:rg -n '备份|恢复|SLO|错误预算|上线' docs/ops docs/trialrun/OPS7运维交接Runbook.md。",rg,DONE,DONE,DONE,docs/ops|docs/trialrun/OPS7运维交接Runbook.md,["P2T-0"],候选边界已写入 PRD P2T 表和 OPS Runbook;上线前必须先完成 R7E 和 OPS8 或等价门禁。
P2T-6,P2 冻结项确认,"确认 ERP 实时集成、AI 自动处理、完整差旅、复杂 BPM、审批设计器、预算重型控制、企业微信原生审批继续冻结。","1) 冻结项写入盘点结论;2) 任一项要启动必须另建里程碑;3) 不误导为当前 Backlog;4) 与集成边界一致。","流程级验证:rg -n 'ERP|AI|完整差旅|复杂 BPM|审批设计器|预算|企业微信原生审批|冻结' docs/海音达OA-MVP需求规格说明书.md docs/集成边界.md docs/产品口径.md。",rg,TODO,TODO,TODO,docs/海音达OA-MVP需求规格说明书.md|docs/集成边界.md|docs/产品口径.md,["P2T-0"],冻结不是永久删除;只是当前 MVP/R7 不进入。 P2T-6,P2 冻结项确认,"确认 ERP 实时集成、AI 自动处理、完整差旅、复杂 BPM、审批设计器、预算重型控制、企业微信原生审批继续冻结。","1) 冻结项写入盘点结论;2) 任一项要启动必须另建里程碑;3) 不误导为当前 Backlog;4) 与集成边界一致。","流程级验证:rg -n 'ERP|AI|完整差旅|复杂 BPM|审批设计器|预算|企业微信原生审批|冻结' docs/海音达OA-MVP需求规格说明书.md docs/集成边界.md docs/产品口径.md。",rg,DONE,DONE,DONE,docs/海音达OA-MVP需求规格说明书.md|docs/集成边界.md|docs/产品口径.md,["P2T-0"],冻结项已写入 PRD P2T 表;冻结不是永久删除,只是当前 MVP/R7 不进入。
P2T-7,P2T 收口,"完成 P2 候选排序和边界确认后的状态回填。","1) 输出候选优先级;2) ORG8 候选边界明确;3) 冻结项明确;4) 未批准功能保持 TODO;5) 中文提交。","流程级验证:validate_issues_csv.py 本 CSV;rg 核对候选和冻结项;git diff --check;git commit。",python3|rg|git,TODO,TODO,TODO,issues/2026-05-13_13-17-39-p2-scope-triage.csv|docs,"[""P2T-1"",""P2T-2"",""P2T-3"",""P2T-4"",""P2T-5"",""P2T-6""]",本合同不进入实现阶段。 P2T-7,P2T 收口,"完成 P2 候选排序和边界确认后的状态回填。","1) 输出候选优先级;2) ORG8 候选边界明确;3) 冻结项明确;4) 未批准功能保持 TODO;5) 中文提交。","流程级验证:validate_issues_csv.py 本 CSV;rg 核对候选和冻结项;git diff --check;git commit。",python3|rg|git,DONE,DONE,DONE,issues/2026-05-13_13-17-39-p2-scope-triage.csv|docs,"[""P2T-1"",""P2T-2"",""P2T-3"",""P2T-4"",""P2T-5"",""P2T-6""]",本合同不进入实现阶段;候选已排序,未批准功能不进入开发。
无法渲染此文件,因为它包含了意外字符,其位于第 3 行和第 551 列。