R7E 非人工剩余项处理收口

这个提交包含在:
2026-05-14 16:58:06 +08:00
父节点 b437743ef1
当前提交 45900e0673
共修改 5 个文件,包含 293 行新增和 14 行删除
@@ -11,7 +11,16 @@ import { approveWorkflowTaskViaApi, waitForWorkflowTask } from "../helpers/workf
type StepStatus = "PASS" | "FAIL" | "SKIP"; type StepStatus = "PASS" | "FAIL" | "SKIP";
type FlowName = "公共前置" | "报销" | "审批" | "请假" | "采购" | "财务" | "移动" | "企业微信UA"; type FlowName = "公共前置" | "报销" | "审批" | "请假" | "采购" | "财务" | "移动" | "企业微信UA";
type FlowKey = "preflight" | "reimbursement-finance" | "leave" | "purchase-attachment" | "mobile" | "wecom-ua" | "all"; type FlowKey =
| "preflight"
| "reimbursement-finance"
| "leave"
| "purchase-attachment"
| "mobile"
| "wecom-ua"
| "finance-closeout"
| "approval-boundary"
| "all";
type TrialStep = { type TrialStep = {
flow: FlowName; flow: FlowName;
@@ -44,6 +53,11 @@ type PaymentBatch = {
id: string; id: string;
name: string; name: string;
status: string; status: string;
items?: Array<{
entityId: string;
entityCode: string;
status: string;
}>;
reviewRequirement: { reviewRequirement: {
completedReviewCount: number; completedReviewCount: number;
requiredReviewCount: number; requiredReviewCount: number;
@@ -51,6 +65,22 @@ type PaymentBatch = {
}; };
}; };
type FinanceLedgerItem = {
id: string;
formNumber: string | null;
status: string;
payment: {
status: string;
paymentVoucherNo: string | null;
paidAt: string | null;
};
};
type FinanceLedgerResponse = {
total: number;
items: FinanceLedgerItem[];
};
type TrialState = { type TrialState = {
reimbursementId?: string; reimbursementId?: string;
reimbursementCode?: string; reimbursementCode?: string;
@@ -72,8 +102,20 @@ const reportDir = path.join(rootDir, "artifacts/r7e/browser-business-trialrun");
const reportPath = path.join(reportDir, "report.md"); const reportPath = path.join(reportDir, "report.md");
const issueCandidatesPath = path.join(reportDir, "issues.csv"); const issueCandidatesPath = path.join(reportDir, "issues.csv");
const screenshotDir = path.join(rootDir, "output/playwright/r7e-browser-business-trialrun"); const screenshotDir = path.join(rootDir, "output/playwright/r7e-browser-business-trialrun");
const validFlows = new Set<FlowKey>(["preflight", "reimbursement-finance", "leave", "purchase-attachment", "mobile", "wecom-ua", "all"]); const validFlows = new Set<FlowKey>([
"preflight",
"reimbursement-finance",
"leave",
"purchase-attachment",
"mobile",
"wecom-ua",
"finance-closeout",
"approval-boundary",
"all",
]);
const loginRateLimitRetryMs = Number.parseInt(process.env.R7E_LOGIN_RETRY_WAIT_MS ?? "65000", 10); const loginRateLimitRetryMs = Number.parseInt(process.env.R7E_LOGIN_RETRY_WAIT_MS ?? "65000", 10);
const defaultCloseoutReimbursementId = "40876ef3-0652-4972-aa14-1aad1a855ae0";
const defaultCloseoutReimbursementCode = "BX-20260514-0016";
const wecomUa = const wecomUa =
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 wxwork/4.1.20 MicroMessenger/8.0.1 Language/zh_CN"; "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 wxwork/4.1.20 MicroMessenger/8.0.1 Language/zh_CN";
@@ -140,6 +182,27 @@ function looksLikeLoginRateLimit(error: unknown) {
return /请求过于频繁|rate.?limit|too many requests|HTTP_429|429/i.test(message); return /请求过于频繁|rate.?limit|too many requests|HTTP_429|429/i.test(message);
} }
async function responseTextSummary(response: { status(): number; text(): Promise<string> }) {
const raw = await response.text().catch(() => "");
if (!raw) return `HTTP ${response.status()}`;
try {
const parsed = JSON.parse(raw) as { error?: { code?: string; message?: string; details?: unknown } };
const code = parsed.error?.code ?? `HTTP_${response.status()}`;
const message = parsed.error?.message ?? "";
const details = parsed.error?.details ? ` details=${JSON.stringify(parsed.error.details)}` : "";
return `${code}: ${message}${details}`.slice(0, 500);
} catch {
return `HTTP ${response.status()} ${raw.slice(0, 300)}`;
}
}
async function expectApiRejected(response: { ok(): boolean; status(): number; text(): Promise<string> }, label: string) {
if (response.ok()) {
throw new Error(`${label} 未被拒绝:HTTP ${response.status()}`);
}
return responseTextSummary(response);
}
async function waitForLoginRateLimitWindow() { async function waitForLoginRateLimitWindow() {
if (Number.isFinite(loginRateLimitRetryMs) && loginRateLimitRetryMs > 0) { if (Number.isFinite(loginRateLimitRetryMs) && loginRateLimitRetryMs > 0) {
await new Promise((resolve) => setTimeout(resolve, loginRateLimitRetryMs)); await new Promise((resolve) => setTimeout(resolve, loginRateLimitRetryMs));
@@ -191,6 +254,48 @@ async function firstEnabledExpenseTypeId(api: APIRequestContext) {
return item.id; return item.id;
} }
async function fetchFinanceLedger(api: APIRequestContext, query: { q?: string; page?: number; pageSize?: number } = {}) {
const params = new URLSearchParams();
params.set("page", String(query.page ?? 1));
params.set("pageSize", String(query.pageSize ?? 20));
if (query.q) params.set("q", query.q);
return apiGetData<FinanceLedgerResponse>(api, `/api/ap-operations/reimbursement-ledger?${params.toString()}`);
}
async function fetchPaymentBatches(api: APIRequestContext) {
return apiGetData<{ items: PaymentBatch[] }>(api, "/api/payment-batches");
}
async function findPaymentBatchByEntity(api: APIRequestContext, entityId: string) {
const batches = await fetchPaymentBatches(api);
return batches.items.find((batch) => batch.items?.some((item) => item.entityId === entityId)) ?? null;
}
async function createPaymentBatchViaApi(api: APIRequestContext, input: {
reimbursementId: string;
name: string;
marker: string;
}) {
return apiPostData<{ item: PaymentBatch }>(api, "/api/payment-batches", {
entityType: "reimbursement",
name: input.name,
entityIds: [input.reimbursementId],
defaultPaymentDate: new Date().toISOString().slice(0, 10),
defaultPaymentChannel: "bank",
voucherPrefix: `R7E-PAY-${input.marker.slice(-8)}`,
});
}
async function reviewPaymentBatchViaApi(api: APIRequestContext, batchId: string, marker: string) {
return apiPostData<{ item: PaymentBatch }>(api, `/api/payment-batches/${batchId}/review`, {
comment: `R7E 非人工付款复核 ${marker}`,
});
}
async function executePaymentBatchViaApi(api: APIRequestContext, batchId: string) {
return apiPostData<{ item: PaymentBatch }>(api, `/api/payment-batches/${batchId}/execute`, {});
}
async function createReimbursementItem(api: APIRequestContext, reimbursementId: string, marker: string) { async function createReimbursementItem(api: APIRequestContext, reimbursementId: string, marker: string) {
const expenseTypeId = await firstEnabledExpenseTypeId(api); const expenseTypeId = await firstEnabledExpenseTypeId(api);
const response = await api.post(`/api/reimbursements/${reimbursementId}/items`, { const response = await api.post(`/api/reimbursements/${reimbursementId}/items`, {
@@ -527,6 +632,172 @@ test("R7E 浏览器业务先行试运行:报销、审批、请假、采购、
return; return;
} }
if (shouldRunFlow(selectedFlow, "finance-closeout")) {
await runStep("财务", "finance/financeMgr/admin", "AP API 诊断、付款闭环和管理员边界", async () => {
const reimbursementId = process.env.R7E_EXISTING_REIMBURSEMENT_ID?.trim() || defaultCloseoutReimbursementId;
const reimbursementCode = process.env.R7E_EXISTING_REIMBURSEMENT_CODE?.trim() || defaultCloseoutReimbursementCode;
const financeApi = await createLiveApiClientWithRetry("finance");
let financeMgrApi: Awaited<ReturnType<typeof createLiveApiClientWithRetry>> | null = null;
let adminApi: Awaited<ReturnType<typeof createLiveApiClientWithRetry>> | null = null;
try {
const reimbursementBefore = await apiGetData<ReimbursementDetail>(financeApi.api, `/api/reimbursements/${reimbursementId}`);
const ledgerResponse = await financeApi.api.get(`/api/ap-operations/reimbursement-ledger?q=${encodeURIComponent(reimbursementCode)}&page=1&pageSize=20`);
const paymentBatchesResponse = await financeApi.api.get("/api/payment-batches");
let paymentBatchesSummary = "";
if (paymentBatchesResponse.ok()) {
const paymentBatchesPayload = (await paymentBatchesResponse.json()) as { data?: { items?: PaymentBatch[] } };
const matchedBatch = paymentBatchesPayload.data?.items?.find((batch) => batch.items?.some((item) => item.entityId === reimbursementId));
paymentBatchesSummary = matchedBatch ? `matchedBatch=${matchedBatch.id}; status=${matchedBatch.status}` : "matchedBatch=none";
} else {
paymentBatchesSummary = `paymentBatches=${await responseTextSummary(paymentBatchesResponse)}`;
}
if (!ledgerResponse.ok()) {
return {
status: "SKIP",
businessId: `${reimbursementCode}; reimbursement=${reimbursementId}`,
pcResult: "SKIP: AP 台账 API 不可用",
conclusion: "暂停",
detail: `reimbursementStatus=${reimbursementBefore.status}; apLedger=${await responseTextSummary(ledgerResponse)}; ${paymentBatchesSummary}`,
};
}
const ledgerPayload = (await ledgerResponse.json()) as { data?: FinanceLedgerResponse };
const ledger = ledgerPayload.data;
const ledgerItem = ledger?.items?.find((item) => item.id === reimbursementId || item.formNumber === reimbursementCode) ?? null;
if (!ledgerItem) {
return {
status: "SKIP",
businessId: `${reimbursementCode}; reimbursement=${reimbursementId}`,
pcResult: "SKIP: 已审批报销未进入 AP 台账 API 结果",
conclusion: "暂停",
detail: `reimbursementStatus=${reimbursementBefore.status}; apLedgerTotal=${ledger?.total ?? "unknown"}; apLedgerMatched=false`,
};
}
state.reimbursementId = reimbursementId;
state.reimbursementCode = reimbursementCode;
let batch: PaymentBatch | null = null;
if (reimbursementBefore.status === "paid" || ledgerItem.payment.status === "paid") {
batch = await findPaymentBatchByEntity(financeApi.api, reimbursementId).catch(() => null);
} else {
if (!/approved/.test(reimbursementBefore.status)) {
return {
status: "SKIP",
businessId: `${reimbursementCode}; status=${reimbursementBefore.status}`,
pcResult: "SKIP: 报销未处于可付款状态",
conclusion: "暂停",
detail: `reimbursementStatus=${reimbursementBefore.status}; ledgerStatus=${ledgerItem.status}; paymentStatus=${ledgerItem.payment.status}`,
};
}
const existingBatch = await findPaymentBatchByEntity(financeApi.api, reimbursementId).catch(() => null);
if (existingBatch && ["draft", "reviewed", "failed"].includes(existingBatch.status)) {
batch = existingBatch;
} else {
const batchName = `R7E 非人工付款批次 ${marker}`;
const created = await createPaymentBatchViaApi(financeApi.api, { reimbursementId, name: batchName, marker });
batch = created.item;
}
if (batch.status === "draft") {
financeMgrApi = await createLiveApiClientWithRetry("financeMgr");
const reviewed = await reviewPaymentBatchViaApi(financeMgrApi.api, batch.id, marker);
batch = reviewed.item;
}
if (["reviewed", "failed"].includes(batch.status)) {
const executed = await executePaymentBatchViaApi(financeApi.api, batch.id);
batch = executed.item;
}
}
const reimbursementAfter = await apiGetData<ReimbursementDetail>(financeApi.api, `/api/reimbursements/${reimbursementId}`);
const finalLedger = await fetchFinanceLedger(financeApi.api, { q: reimbursementCode });
const finalLedgerItem = finalLedger.items.find((item) => item.id === reimbursementId || item.formNumber === reimbursementCode) ?? null;
if (reimbursementAfter.status !== "paid" || finalLedgerItem?.payment.status !== "paid") {
throw new Error(
`付款闭环后状态不一致:reimbursement=${reimbursementAfter.status}; ledgerPayment=${finalLedgerItem?.payment.status ?? "missing"}`,
);
}
adminApi = await createLiveApiClientWithRetry("admin");
const adminExecuteProbe = await adminApi.api.post("/api/payment-batches/not-a-valid-uuid/execute", { data: {} });
const adminBoundary = await expectApiRejected(adminExecuteProbe, "admin-only 执行付款探测");
if (adminExecuteProbe.status() !== 403) {
throw new Error(`admin-only 付款权限边界不是 403:${adminBoundary}`);
}
const finance = await loginRole(page, "finance");
try {
await page.goto("/ap-operations");
await expect(page.getByTestId("finance-ledger-table")).toBeVisible({ timeout: 30_000 });
await page.getByPlaceholder("单号、姓名、部门、项目").fill(reimbursementCode);
await expect(page.getByTestId("finance-ledger-table")).toContainText(reimbursementCode, { timeout: 30_000 });
await expect(page.getByTestId("finance-ledger-table")).toContainText(/已付款|paid/, { timeout: 30_000 });
} finally {
await logoutLiveUser(page, { name: finance.name }).catch(() => undefined);
}
return {
businessId: `${reimbursementCode}; reimbursement=${reimbursementId}; batch=${batch?.id ?? "already-paid"}`,
pcResult: "PASS: AP API 可见、付款批次复核执行、报销和台账已付款、管理员付款权限被拒绝",
detail: `reimbursementStatus=${reimbursementAfter.status}; ledgerPayment=${finalLedgerItem.payment.status}; batchStatus=${batch?.status ?? "already-paid"}; adminBoundary=${adminBoundary}`,
};
} finally {
await adminApi?.dispose();
await financeMgrApi?.dispose();
await financeApi.dispose();
}
});
}
if (shouldRunFlow(selectedFlow, "approval-boundary")) {
await runStep("审批", "employee/admin/manager", "真实待办申请人和 admin-only 越权拒绝", async () => {
const employeeApi = await createLiveApiClientWithRetry("employee");
let managerApi: Awaited<ReturnType<typeof createLiveApiClientWithRetry>> | null = null;
let adminApi: Awaited<ReturnType<typeof createLiveApiClientWithRetry>> | null = null;
const startDate = futureWeekday(uniqueFutureOffset(5200));
const employee = await loginRole(page, "employee");
try {
await (await openNavLink(page, "请假")).click();
await expect(page.getByRole("heading", { name: "请假申请" })).toBeVisible();
const leaveId = await createLeaveDraft(page, startDate, `R7E 审批边界 ${marker}`);
const submitResult = await apiPostData<{ leaveRequestId: string; currentTaskId: string }>(employeeApi.api, `/api/leave-requests/${leaveId}/submit`, {});
const taskId = submitResult.currentTaskId;
if (!taskId) {
throw new Error(`请假提交后未返回 currentTaskId: ${JSON.stringify(submitResult)}`);
}
const selfApproveResponse = await employeeApi.api.post(`/api/workflow/tasks/${taskId}/approve`, { data: {} });
const selfBoundary = await expectApiRejected(selfApproveResponse, "申请人本人审批探测");
adminApi = await createLiveApiClientWithRetry("admin");
const adminApproveResponse = await adminApi.api.post(`/api/workflow/tasks/${taskId}/approve`, { data: {} });
const adminBoundary = await expectApiRejected(adminApproveResponse, "admin-only 审批探测");
managerApi = await createLiveApiClientWithRetry("manager");
await approveWorkflowTaskViaApi(managerApi.api, taskId);
await page.goto("/leave-requests");
await expect(page.getByRole("row").filter({ hasText: startDate }).first()).toContainText("已通过", { timeout: 30_000 });
await expect(page.getByRole("row").filter({ hasText: startDate }).first()).toContainText(/通过|已通过/, { timeout: 30_000 });
return {
businessId: `leave=${leaveId}; task=${taskId}`,
pcResult: "PASS: 申请人本人和 admin-only 审批接口均被拒绝,经理正常通过并申请人回看已通过",
detail: `selfBoundary=${selfBoundary}; adminBoundary=${adminBoundary}`,
};
} finally {
await adminApi?.dispose();
await managerApi?.dispose();
await employeeApi.dispose();
await logoutLiveUser(page, { name: employee.name }).catch(() => undefined);
}
});
}
if (shouldRunFlow(selectedFlow, "reimbursement-finance")) { if (shouldRunFlow(selectedFlow, "reimbursement-finance")) {
const existingReimbursementId = process.env.R7E_EXISTING_REIMBURSEMENT_ID?.trim() || ""; const existingReimbursementId = process.env.R7E_EXISTING_REIMBURSEMENT_ID?.trim() || "";
if (existingReimbursementId) { if (existingReimbursementId) {
+8 -8
查看文件
@@ -211,17 +211,17 @@ R7E 结论:公网、live smoke/OCR、移动矩阵、核心业务流、账号
| --- | --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- | --- |
| 公共前置 | 员工、审批人、财务、财务主管、管理员 | N/A | 5 类账号登录 `/portal` 通过;`/ready` 通过;public bundle `findings=0`;live smoke env ready;授权 PDF 文件存在且为 PDF | N/A | - | 通过 | | 公共前置 | 员工、审批人、财务、财务主管、管理员 | N/A | 5 类账号登录 `/portal` 通过;`/ready` 通过;public bundle `findings=0`;live smoke env ready;授权 PDF 文件存在且为 PDF | N/A | - | 通过 |
| 报销 | 员工、审批人 | `BX-20260514-0016` | 员工创建报销、添加明细、上传授权 PDF、提交;审批人处理通过;申请人回看状态和审批历史 | N/A | - | 报销业务链路通过;财务付款另记 `R7E-14` | | 报销 | 员工、审批人 | `BX-20260514-0016` | 员工创建报销、添加明细、上传授权 PDF、提交;审批人处理通过;申请人回看状态和审批历史 | N/A | - | 报销业务链路通过;财务付款另记 `R7E-14` |
| 审批 | 审批人 | `BX-20260514-0016`、`CG-20260514-0005`、请假单 `a22e45f8-b3d6-4862-97f2-30cbe4815e09` | 报销、采购、请假均完成待办处理并可回看历史 | N/A | R7E-ISSUE-BROWSER-004 | 主链路通过;live 自审/越权边界未补齐,不关闭 `R7E-11` | | 审批 | 员工、管理员、审批人 | `BX-20260514-0016`、`CG-20260514-0005`、请假单 `a22e45f8-b3d6-4862-97f2-30cbe4815e09`、审批边界请假单 `b0cd3e00-2e67-4f51-9aaf-63aa2c53b47e` | 报销、采购、请假均完成待办处理并可回看历史;申请人本人和 admin-only 对真实待办调用审批接口均被拒绝,经理正常通过收尾 | N/A | - | 通过;`R7E-11` 可关闭 |
| 请假 | 员工、审批人 | `a22e45f8-b3d6-4862-97f2-30cbe4815e09` | 员工提交未来工作日请假;审批人通过;员工 PC 回看已通过 | `/mobile/leave` 记录页可见且无横向滚动 | - | 通过 | | 请假 | 员工、审批人 | `a22e45f8-b3d6-4862-97f2-30cbe4815e09` | 员工提交未来工作日请假;审批人通过;员工 PC 回看已通过 | `/mobile/leave` 记录页可见且无横向滚动 | - | 通过 |
| 采购 | 员工、审批人 | `CG-20260514-0005` | PC 创建、明细、无敏感测试附件上传、提交、审批、状态和审批历史回看通过 | 移动采购列表、详情和附件可见且无横向滚动 | - | 通过 | | 采购 | 员工、审批人 | `CG-20260514-0005` | PC 创建、明细、无敏感测试附件上传、提交、审批、状态和审批历史回看通过 | 移动采购列表、详情和附件可见且无横向滚动 | - | 通过 |
| 财务 | 财务 | `BX-20260514-0016` | 财务账号可进入 `/ap-operations`;已审批报销按单号筛选未进入 AP 台账,未创建付款批次、未执行付款、未验证导出 | N/A | R7E-ISSUE-BROWSER-005 | 暂停,分流 `R7E-14`/`R7E-16` | | 财务 | 财务 | `BX-20260514-0016` | 报销状态为 `approved`;`/api/ap-operations/reimbursement-ledger` 和 `/api/payment-batches` 均返回 `payment_batch_v1_disabled / flag_force_off`,未创建付款批次、未复核、未执行付款、未验证导出 | N/A | R7E-ISSUE-BROWSER-005 | 暂停,分流 `R7E-14`/`R7E-16` |
| 移动通用 | 员工、审批人、财务 | N/A | N/A | `/mobile`、移动报销、请假、审批、通知、采购入口通过;无 PC 壳和横向滚动 | - | 通过 | | 移动通用 | 员工、审批人、财务 | N/A | N/A | `/mobile`、移动报销、请假、审批、通知、采购入口通过;无 PC 壳和横向滚动 | - | 通过 |
| 企业微信 UA 模拟 | 匿名 | N/A | N/A | 登录入口、企业微信配置和 OAuth 边界可达 | - | 通过;不代表真机验收 | | 企业微信 UA 模拟 | 匿名 | N/A | N/A | 登录入口、企业微信配置和 OAuth 边界可达 | - | 通过;不代表真机验收 |
| 补充移动矩阵 | 本地 mock 前置 | N/A | N/A | `dg7-mobile-information-dedupe` 未启动本地前端服务时访问 `127.0.0.1:3000` 失败 | QAOPS8-TEST-002 | 前置条件问题,不作为公网业务失败 | | 补充移动矩阵 | 本地 mock 前置 | N/A | N/A | 启动 Vite `http://127.0.0.1:5173` 后重跑 `dg7-mobile-information-dedupe`,5 passed;临时服务已关闭 | - | 通过;前次 `127.0.0.1:3000` 失败确认为前置服务未启动 |
本轮新增测试辅助:`r7e-browser-business-trialrun.spec.ts` 支持 `R7E_BROWSER_FLOW=preflight|reimbursement-finance|leave|purchase-attachment|mobile|wecom-ua|all` 分段执行;移动 flow 使用浏览器 storage state 注入登录态并写入匹配的 device fingerprint,避免反复 UI 登录触发限流。 本轮新增测试辅助:`r7e-browser-business-trialrun.spec.ts` 支持 `R7E_BROWSER_FLOW=preflight|reimbursement-finance|leave|purchase-attachment|mobile|wecom-ua|finance-closeout|approval-boundary|all` 分段执行;移动 flow 使用浏览器 storage state 注入登录态并写入匹配的 device fingerprint,避免反复 UI 登录触发限流。
阶段结论:无人工自动化已完成公网健康、报销提交审批、请假、采购附件、移动浏览器和企业微信 UA 模拟。`R7E-10`、`R7E-12`、`R7E-13` 可按浏览器业务线证据关闭;`R7E-11` 因 live 自审/越权边界未补齐保持 `DOING`;`R7E-14` 因 AP 台账未出现已审批报销保持 `DOING`;`R7E-9`、`R7E-15`、`R7E-18` 仍需真实企业微信和人工验收,不由本轮自动化替代。 阶段结论:无人工自动化已完成公网健康、报销提交审批、请假、采购附件、审批边界、移动浏览器、企业微信 UA 模拟和本地移动矩阵前置修正。`R7E-10`、`R7E-11`、`R7E-12`、`R7E-13` 可按浏览器业务线证据关闭;`R7E-14` 因公网 AP/payment-batches 功能门禁 `flag_force_off` 保持 `DOING`;`R7E-9`、`R7E-15`、`R7E-18` 仍需真实企业微信和人工验收,不由本轮自动化替代。
## QAOPS8 Go/No-Go 当前结论 ## QAOPS8 Go/No-Go 当前结论
@@ -234,7 +234,7 @@ R7E 结论:公网、live smoke/OCR、移动矩阵、核心业务流、账号
| QAOPS8 发布、备份、回滚和 SLO 基线 | 已形成 | 可作为 R7E 启动前准备证据 | | QAOPS8 发布、备份、回滚和 SLO 基线 | 已形成 | 可作为 R7E 启动前准备证据 |
| R7E-1..7 人工启动确认 | 已确认 | 可以进入启动当天公网健康复核 | | R7E-1..7 人工启动确认 | 已确认 | 可以进入启动当天公网健康复核 |
| R7E-8 公网健康复核 | 已完成 | 最新代码 `4b14c92` 已部署;`/ready`、public bundle、远端 migration 状态和公网移动矩阵通过 | | R7E-8 公网健康复核 | 已完成 | 最新代码 `4b14c92` 已部署;`/ready`、public bundle、远端 migration 状态和公网移动矩阵通过 |
| R7E-9..15 真实业务和真机流程 | 部分完成 | 浏览器业务线已关闭报销、请假、采购;企业微信专属线、live 自审/越权边界和财务付款闭环仍需后补 | | R7E-9..15 真实业务和真机流程 | 部分完成 | 浏览器业务线已关闭报销、审批边界、请假、采购;企业微信专属线和财务付款闭环仍需后补 |
| R7E-16..18 每日问题和验收结论 | 未完成 | 需试运行窗口内记录 | | R7E-16..18 每日问题和验收结论 | 未完成 | 需试运行窗口内记录 |
| WF8-11 通知 deeplink 回 OA | 未完成 | 需企业微信或代表性真机验证 | | WF8-11 通知 deeplink 回 OA | 未完成 | 需企业微信或代表性真机验证 |
| BIZ8-12 移动业务入口评估 | 暂停收口 | 自动化截图已有,仍需代表性真机和角色反馈 | | BIZ8-12 移动业务入口评估 | 暂停收口 | 自动化截图已有,仍需代表性真机和角色反馈 |
@@ -244,10 +244,10 @@ R7E 结论:公网、live smoke/OCR、移动矩阵、核心业务流、账号
- `SMOKE002` 企业微信工作台进入 `/mobile` 后确认无 PC 外壳,底部导航和业务入口正常。 - `SMOKE002` 企业微信工作台进入 `/mobile` 后确认无 PC 外壳,底部导航和业务入口正常。
- `SMOKE002` 补充企业微信 WebView 内的移动报销详情和 PDF 上传确认,不能被图片拍照入口误导。 - `SMOKE002` 补充企业微信 WebView 内的移动报销详情和 PDF 上传确认,不能被图片拍照入口误导。
- `SMOKE101` 完成移动审批和通知 deeplink 回 OA 的确认。 - `SMOKE101` 完成移动审批和通知 deeplink 回 OA 的确认。
- 财务角色完成 AP 台账、付款、导出或可解释财务路径确认;当前自动化发现 `BX-20260514-0016` 未进入 AP 台账筛选结果。 - 财务角色完成 AP 台账、付款、导出或可解释财务路径确认;当前自动化发现公网 AP/payment-batches 功能门禁为 `payment_batch_v1_disabled / flag_force_off`。
- `SMOKE301` / `SMOKE302` 尚未启用且没有企业微信,不能作为企业微信真机证据。 - `SMOKE301` / `SMOKE302` 尚未启用且没有企业微信,不能作为企业微信真机证据。
结论:当前可以按最新代码继续 R7E 浏览器业务和后续人工真机试运行,但不能给正式上线 `Go`,也不能关闭 `R7E-9`、`R7E-11`、`R7E-14`、`R7E-15`、`R7E-18`、`WF8-11`、`BIZ8-12` 或 QAOPS8 后续收口项。 结论:当前可以按最新代码继续 R7E 浏览器业务和后续人工真机试运行,但不能给正式上线 `Go`,也不能关闭 `R7E-9`、`R7E-14`、`R7E-15`、`R7E-18`、`WF8-11`、`BIZ8-12` 或 QAOPS8 后续收口项。
## 历史恢复 ## 历史恢复
@@ -10,12 +10,12 @@ R7E-7,暂停和回滚决策人确认,"确认 R7E 试运行中触发暂停、回
R7E-8,公网健康复核,"在真实 R7E 启动当天复核公网匿名健康和 public bundle。","1) /ready 返回 ok=true;2) public bundle findings=0;3) 结果写入试运行报告;4) 失败则暂停试运行。","流程级验证: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,"[""R7E-7""]",2026-05-14 按最新代码 4b14c92 完成受控部署;部署前 client typecheck/build 通过;部署中发现既有 BIZ8 加性 migration 未应用 先创建 DB 备份 hyb-oa-db-20260514_011940.dump 和附件备份 hyb-oa-storage-20260514_011940.tar.gz 后执行 prisma migrate deploy;复跑 deploy.sh 通过且远端 migration up to date;公网 /ready ok=true;public bundle scanned=57 focused=4 findings=0;公网移动矩阵 dg7-mobile-information-dedupe 5 passed。 R7E-8,公网健康复核,"在真实 R7E 启动当天复核公网匿名健康和 public bundle。","1) /ready 返回 ok=true;2) public bundle findings=0;3) 结果写入试运行报告;4) 失败则暂停试运行。","流程级验证: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,"[""R7E-7""]",2026-05-14 按最新代码 4b14c92 完成受控部署;部署前 client typecheck/build 通过;部署中发现既有 BIZ8 加性 migration 未应用 先创建 DB 备份 hyb-oa-db-20260514_011940.dump 和附件备份 hyb-oa-storage-20260514_011940.tar.gz 后执行 prisma migrate deploy;复跑 deploy.sh 通过且远端 migration up to date;公网 /ready ok=true;public bundle scanned=57 focused=4 findings=0;公网移动矩阵 dg7-mobile-information-dedupe 5 passed。
R7E-9,企业微信入口复核,"在真实 R7E 启动前复核企业微信入口、绑定状态、免登或账号密码兜底、deeplink 回 OA。","1) 企业微信入口可达;2) 绑定用户可进入移动端;3) 未绑定有明确兜底;4) deeplink 回 OA 正确。","流程级验证:代表性真机或企业微信 WebView 人工复核;必要时补 Playwright WeCom UA。",manual|playwright,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md|output/playwright,"[""R7E-8""]",2026-05-14 无人工自动化补测:WeCom UA 模拟通过登录入口 企业微信配置和 OAuth 边界可达;证据 artifacts/r7e/browser-business-trialrun/report-wecom-ua.md;真实企业微信免登录 消息送达 消息 deeplink WebView 文件选择器和代表设备反馈仍需人工确认,故本行不提前 DONE。 R7E-9,企业微信入口复核,"在真实 R7E 启动前复核企业微信入口、绑定状态、免登或账号密码兜底、deeplink 回 OA。","1) 企业微信入口可达;2) 绑定用户可进入移动端;3) 未绑定有明确兜底;4) deeplink 回 OA 正确。","流程级验证:代表性真机或企业微信 WebView 人工复核;必要时补 Playwright WeCom UA。",manual|playwright,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md|output/playwright,"[""R7E-8""]",2026-05-14 无人工自动化补测:WeCom UA 模拟通过登录入口 企业微信配置和 OAuth 边界可达;证据 artifacts/r7e/browser-business-trialrun/report-wecom-ua.md;真实企业微信免登录 消息送达 消息 deeplink WebView 文件选择器和代表设备反馈仍需人工确认,故本行不提前 DONE。
R7E-10,报销流程试运行,"员工按真实路径提交报销或复核已有样例,覆盖发票/OCR/附件/审批/财务查看。","1) 员工可提交或查看报销;2) OCR/PDF-only 口径清晰;3) 审批链可追溯;4) 财务可复核;5) 问题进入登记清单。","流程级验证:员工进入报销 -> 上传/选择材料 -> 提交 -> 审批 -> 财务复核;记录结果和问题。",manual|playwright,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:员工创建并提交报销 40876ef3-0652-4972-aa14-1aad1a855ae0 / BX-20260514-0016;授权 PDF 样票上传成功并绑定票据 188b076e-07cc-4058-aac9-02b5161a188a;审批人处理通过后申请人回看状态 approved 和审批历史;复用该单进入财务验证时 AP 台账筛选为空,财务付款闭环另记 R7E-14/R7E-16;证据 artifacts/r7e/browser-business-trialrun/report-reimbursement-finance.md 和 output/playwright/r7e-browser-business-trialrun。 R7E-10,报销流程试运行,"员工按真实路径提交报销或复核已有样例,覆盖发票/OCR/附件/审批/财务查看。","1) 员工可提交或查看报销;2) OCR/PDF-only 口径清晰;3) 审批链可追溯;4) 财务可复核;5) 问题进入登记清单。","流程级验证:员工进入报销 -> 上传/选择材料 -> 提交 -> 审批 -> 财务复核;记录结果和问题。",manual|playwright,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:员工创建并提交报销 40876ef3-0652-4972-aa14-1aad1a855ae0 / BX-20260514-0016;授权 PDF 样票上传成功并绑定票据 188b076e-07cc-4058-aac9-02b5161a188a;审批人处理通过后申请人回看状态 approved 和审批历史;复用该单进入财务验证时 AP 台账筛选为空,财务付款闭环另记 R7E-14/R7E-16;证据 artifacts/r7e/browser-business-trialrun/report-reimbursement-finance.md 和 output/playwright/r7e-browser-business-trialrun。
R7E-11,审批流程试运行,"审批人按真实路径处理待办,员工查看进度,验证通知和审批历史一致。","1) 审批人可处理待办;2) 申请人可看进度;3) 审批历史一致;4) 自审和越权被拒绝。","流程级验证:提交申请 -> 审批人处理 -> 申请人查看状态 -> 审计/历史可追溯。",manual|playwright,DOING,TODO,TODO,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:报销 BX-20260514-0016 请假 a22e45f8-b3d6-4862-97f2-30cbe4815e09 和采购 CG-20260514-0005 均完成真实浏览器或 API 待办审批并可申请人回看状态和历史;live 自审或越权边界未在本轮补齐,故保持 DOING 不关闭。 R7E-11,审批流程试运行,"审批人按真实路径处理待办,员工查看进度,验证通知和审批历史一致。","1) 审批人可处理待办;2) 申请人可看进度;3) 审批历史一致;4) 自审和越权被拒绝。","流程级验证:提交申请 -> 审批人处理 -> 申请人查看状态 -> 审计/历史可追溯。",manual|playwright,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:报销 BX-20260514-0016 请假 a22e45f8-b3d6-4862-97f2-30cbe4815e09 采购 CG-20260514-0005 均完成真实浏览器或 API 待办审批并可申请人回看状态和历史;补跑 approval-boundary 创建请假 b0cd3e00-2e67-4f51-9aaf-63aa2c53b47e / task 2cf30190-f569-4cce-ac9e-a0fe183bd460,申请人本人和 admin-only 审批接口均被 PERM_002 拒绝,经理正常通过;server workflow 单元测试 2 files 14 tests passed;证据 report-approval-boundary.md。
R7E-12,请假流程试运行,"员工提交请假,审批人审批,员工和团队视角查看状态。","1) 请假提交成功;2) 审批处理成功;3) 移动/PC 状态一致;4) 团队状态或日历口径可解释。","流程级验证:员工提交请假 -> 审批通过/驳回 -> 查看进度和团队状态。",manual|playwright,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:员工创建未来工作日请假并提交;审批人处理通过;申请人 PC 回看已通过且 /mobile/leave 记录页可见无横向滚动;测试单据 a22e45f8-b3d6-4862-97f2-30cbe4815e09;证据 artifacts/r7e/browser-business-trialrun/report-leave.md。 R7E-12,请假流程试运行,"员工提交请假,审批人审批,员工和团队视角查看状态。","1) 请假提交成功;2) 审批处理成功;3) 移动/PC 状态一致;4) 团队状态或日历口径可解释。","流程级验证:员工提交请假 -> 审批通过/驳回 -> 查看进度和团队状态。",manual|playwright,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:员工创建未来工作日请假并提交;审批人处理通过;申请人 PC 回看已通过且 /mobile/leave 记录页可见无横向滚动;测试单据 a22e45f8-b3d6-4862-97f2-30cbe4815e09;证据 artifacts/r7e/browser-business-trialrun/report-leave.md。
R7E-13,采购流程试运行,"员工提交或查看采购申请,审批人处理,状态和附件可追溯。","1) 采购申请路径可用;2) 审批处理可用;3) 附件和状态可追溯;4) 移动采购创建如缺失则记录为后续 UX/P2。","流程级验证:员工提交/查看采购 -> 审批处理 -> 查看状态和附件。",manual|playwright,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:采购 CG-20260514-0005 完成 PC 创建 明细 无敏感测试附件上传 提交 审批 状态和审批历史回看;移动采购列表 详情和附件可见且无横向滚动;证据 artifacts/r7e/browser-business-trialrun/report-purchase-attachment.md。 R7E-13,采购流程试运行,"员工提交或查看采购申请,审批人处理,状态和附件可追溯。","1) 采购申请路径可用;2) 审批处理可用;3) 附件和状态可追溯;4) 移动采购创建如缺失则记录为后续 UX/P2。","流程级验证:员工提交/查看采购 -> 审批处理 -> 查看状态和附件。",manual|playwright,DONE,DONE,DONE,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:采购 CG-20260514-0005 完成 PC 创建 明细 无敏感测试附件上传 提交 审批 状态和审批历史回看;移动采购列表 详情和附件可见且无横向滚动;证据 artifacts/r7e/browser-business-trialrun/report-purchase-attachment.md。
R7E-14,财务付款和导出试运行,"财务按真实路径复核报销、标记付款、查看台账或导出。","1) 财务角色入口正确;2) 付款标记或台账查看可用;3) 导出权限边界清楚;4) 管理员不自动获得财务能力。","流程级验证:财务进入台账 -> 复核/付款/导出 -> 检查权限和审计。",manual|playwright,DOING,TODO,TODO,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 无人工自动化补测:财务账号可进入 /ap-operations;但已审批报销 BX-20260514-0016 在 finance-ledger-table 按单号筛选为空,未创建付款批次 未执行付款 未验证导出;本行保持 DOING 并分流到 R7E-16。 R7E-14,财务付款和导出试运行,"财务按真实路径复核报销、标记付款、查看台账或导出。","1) 财务角色入口正确;2) 付款标记或台账查看可用;3) 导出权限边界清楚;4) 管理员不自动获得财务能力。","流程级验证:财务进入台账 -> 复核/付款/导出 -> 检查权限和审计。",manual|playwright,DOING,TODO,TODO,docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts,"[""R7E-8""]",2026-05-14 finance-closeout 诊断:报销 40876ef3-0652-4972-aa14-1aad1a855ae0 / BX-20260514-0016 状态 approved;/api/ap-operations/reimbursement-ledger 和 /api/payment-batches 均返回 payment_batch_v1_disabled / flag_force_off;未创建付款批次 未复核 未执行付款 未验证导出;本行保持 DOING 并分流 R7E-16,待公网功能门禁开启或财务路径确认后复测。
R7E-15,移动端和真机反馈,"收集 R7E 参与者在移动浏览器和企业微信中的真实体验反馈。","1) 至少覆盖代表性 iPhone/Android 或企业微信设备;2) 记录页面、视口、角色和问题级别;3) 阻断问题进入修复分流;4) 体验优化进入 UX8。","流程级验证:按真机公网测试清单人工复核;必要时补 Playwright 截图。",manual|playwright,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md|output/playwright,"[""R7E-9""]",2026-05-14 无人工自动化补测:移动浏览器员工 审批人 财务核心入口通过且无横向滚动;证据 artifacts/r7e/browser-business-trialrun/report-mobile.md;企业微信 UA 模拟通过但不能替代代表性 iPhone/Android 企业微信真机反馈,故本行不提前 DONE。 R7E-15,移动端和真机反馈,"收集 R7E 参与者在移动浏览器和企业微信中的真实体验反馈。","1) 至少覆盖代表性 iPhone/Android 或企业微信设备;2) 记录页面、视口、角色和问题级别;3) 阻断问题进入修复分流;4) 体验优化进入 UX8。","流程级验证:按真机公网测试清单人工复核;必要时补 Playwright 截图。",manual|playwright,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md|output/playwright,"[""R7E-9""]",2026-05-14 无人工自动化补测:移动浏览器员工 审批人 财务核心入口通过且无横向滚动;证据 artifacts/r7e/browser-business-trialrun/report-mobile.md;企业微信 UA 模拟通过但不能替代代表性 iPhone/Android 企业微信真机反馈,故本行不提前 DONE。
R7E-16,每日问题清单,"R7E 期间每天登记问题、级别、归属治理流、处理状态和证据路径。","1) 问题均有级别;2) 阻断问题当天决策;3) 新需求不混入即时修复;4) 每日 closeout 可追溯。","流程级验证:每日人工 closeout;问题分流到 R7E/UX8/ORG8/WF8/BIZ8/QAOPS8。",manual,DOING,TODO,TODO,docs/trialrun/人工试运行报告.md,"[""R7E-10"",""R7E-11"",""R7E-12"",""R7E-13"",""R7E-14"",""R7E-15""]",2026-05-14 无人工自动化待分流项:已审批报销 BX-20260514-0016 未进入 AP 台账筛选结果,财务付款闭环暂停;R7E-11 的 live 自审和越权边界仍需补齐;真实企业微信免登录 消息 deeplink WebView 文件选择器和代表设备反馈仍需人工;既有 dg7-mobile-information-dedupe 未启动本地前端服务时访问 127.0.0.1:3000 失败,属于补充矩阵前置条件不是公网业务失败;移动多角色 flow 已通过 browser storage state 修复登录态注入。问题记录不得包含密码 token 或隐私明文。 R7E-16,每日问题清单,"R7E 期间每天登记问题、级别、归属治理流、处理状态和证据路径。","1) 问题均有级别;2) 阻断问题当天决策;3) 新需求不混入即时修复;4) 每日 closeout 可追溯。","流程级验证:每日人工 closeout;问题分流到 R7E/UX8/ORG8/WF8/BIZ8/QAOPS8。",manual,DOING,TODO,TODO,docs/trialrun/人工试运行报告.md,"[""R7E-10"",""R7E-11"",""R7E-12"",""R7E-13"",""R7E-14"",""R7E-15""]",2026-05-14 无人工自动化待分流项:财务付款闭环暂停,原因已收敛为公网 AP/payment-batches 功能门禁 payment_batch_v1_disabled / flag_force_off;R7E-11 live 申请人/admin-only 越权边界已补齐并关闭;真实企业微信免登录 消息 deeplink WebView 文件选择器和代表设备反馈仍需人工;dg7-mobile-information-dedupe 启动本地 Vite 后 5 passed,之前 127.0.0.1:3000 失败确认为前置服务未启动;问题记录不得包含密码 token 或隐私明文。
R7E-17,阻断问题修复分流,"根据每日问题清单把阻断问题分流到当前 R7E 修复或后续连续治理流。","1) 阻断问题有 owner;2) 能在 R7E 内修的有方案和验证;3) 范围外问题进入 UX8/ORG8/WF8/BIZ8/QAOPS8;4) 不顺手扩大。","流程级验证:人工核对问题清单和分流结果;必要时创建后续连续 CSV。",manual,TODO,TODO,TODO,issues/*.csv|docs/trialrun/人工试运行报告.md,"[""R7E-16""]",涉及代码修复时必须先方案批准。 R7E-17,阻断问题修复分流,"根据每日问题清单把阻断问题分流到当前 R7E 修复或后续连续治理流。","1) 阻断问题有 owner;2) 能在 R7E 内修的有方案和验证;3) 范围外问题进入 UX8/ORG8/WF8/BIZ8/QAOPS8;4) 不顺手扩大。","流程级验证:人工核对问题清单和分流结果;必要时创建后续连续 CSV。",manual,TODO,TODO,TODO,issues/*.csv|docs/trialrun/人工试运行报告.md,"[""R7E-16""]",涉及代码修复时必须先方案批准。
R7E-18,验收结论,"汇总 R7E 真实试运行结果,给出通过、暂停、回滚或继续观察结论。","1) 主流程结论完整;2) 阻断问题为 0 或明确暂停/回滚;3) 用户验收结论记录;4) 未完成项进入后续治理流。","流程级验证:人工验收;报告中列出流程结论、问题清单和后续动作。",manual,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md,"[""R7E-17""]",不能仅凭自动化通过宣布 R7E 完成。 R7E-18,验收结论,"汇总 R7E 真实试运行结果,给出通过、暂停、回滚或继续观察结论。","1) 主流程结论完整;2) 阻断问题为 0 或明确暂停/回滚;3) 用户验收结论记录;4) 未完成项进入后续治理流。","流程级验证:人工验收;报告中列出流程结论、问题清单和后续动作。",manual,TODO,TODO,TODO,docs/trialrun/人工试运行报告.md,"[""R7E-17""]",不能仅凭自动化通过宣布 R7E 完成。
R7E-19,P2 排序调整,"根据 R7E 真实反馈调整 P2 候选优先级和后续连续治理流顺序。","1) P2 排序基于真实反馈;2) ORG8/WF8/BIZ8/QAOPS8 入口明确;3) 冻结项仍不进入;4) 如需变更 PRD 则另走事实源更新。","流程级验证:人工核对 PRD P2T 表、问题清单和后续 Issue 计划。",manual|rg,TODO,TODO,TODO,docs/海音达OA-MVP需求规格说明书.md|issues/*.csv,"[""R7E-18""]",P2 功能开发必须另建或延续对应连续合同。 R7E-19,P2 排序调整,"根据 R7E 真实反馈调整 P2 候选优先级和后续连续治理流顺序。","1) P2 排序基于真实反馈;2) ORG8/WF8/BIZ8/QAOPS8 入口明确;3) 冻结项仍不进入;4) 如需变更 PRD 则另走事实源更新。","流程级验证:人工核对 PRD P2T 表、问题清单和后续 Issue 计划。",manual|rg,TODO,TODO,TODO,docs/海音达OA-MVP需求规格说明书.md|issues/*.csv,"[""R7E-18""]",P2 功能开发必须另建或延续对应连续合同。
1 ID Title Description Acceptance Test_Method Tools Dev_Status Review1_Status Regression_Status Files Dependencies Notes
10 R7E-8 公网健康复核 在真实 R7E 启动当天复核公网匿名健康和 public bundle。 1) /ready 返回 ok=true;2) public bundle findings=0;3) 结果写入试运行报告;4) 失败则暂停试运行。 流程级验证: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 ["R7E-7"] 2026-05-14 按最新代码 4b14c92 完成受控部署;部署前 client typecheck/build 通过;部署中发现既有 BIZ8 加性 migration 未应用 先创建 DB 备份 hyb-oa-db-20260514_011940.dump 和附件备份 hyb-oa-storage-20260514_011940.tar.gz 后执行 prisma migrate deploy;复跑 deploy.sh 通过且远端 migration up to date;公网 /ready ok=true;public bundle scanned=57 focused=4 findings=0;公网移动矩阵 dg7-mobile-information-dedupe 5 passed。
11 R7E-9 企业微信入口复核 在真实 R7E 启动前复核企业微信入口、绑定状态、免登或账号密码兜底、deeplink 回 OA。 1) 企业微信入口可达;2) 绑定用户可进入移动端;3) 未绑定有明确兜底;4) deeplink 回 OA 正确。 流程级验证:代表性真机或企业微信 WebView 人工复核;必要时补 Playwright WeCom UA。 manual|playwright TODO TODO TODO docs/trialrun/人工试运行报告.md|output/playwright ["R7E-8"] 2026-05-14 无人工自动化补测:WeCom UA 模拟通过登录入口 企业微信配置和 OAuth 边界可达;证据 artifacts/r7e/browser-business-trialrun/report-wecom-ua.md;真实企业微信免登录 消息送达 消息 deeplink WebView 文件选择器和代表设备反馈仍需人工确认,故本行不提前 DONE。
12 R7E-10 报销流程试运行 员工按真实路径提交报销或复核已有样例,覆盖发票/OCR/附件/审批/财务查看。 1) 员工可提交或查看报销;2) OCR/PDF-only 口径清晰;3) 审批链可追溯;4) 财务可复核;5) 问题进入登记清单。 流程级验证:员工进入报销 -> 上传/选择材料 -> 提交 -> 审批 -> 财务复核;记录结果和问题。 manual|playwright DONE DONE DONE docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts ["R7E-8"] 2026-05-14 无人工自动化补测:员工创建并提交报销 40876ef3-0652-4972-aa14-1aad1a855ae0 / BX-20260514-0016;授权 PDF 样票上传成功并绑定票据 188b076e-07cc-4058-aac9-02b5161a188a;审批人处理通过后申请人回看状态 approved 和审批历史;复用该单进入财务验证时 AP 台账筛选为空,财务付款闭环另记 R7E-14/R7E-16;证据 artifacts/r7e/browser-business-trialrun/report-reimbursement-finance.md 和 output/playwright/r7e-browser-business-trialrun。
13 R7E-11 审批流程试运行 审批人按真实路径处理待办,员工查看进度,验证通知和审批历史一致。 1) 审批人可处理待办;2) 申请人可看进度;3) 审批历史一致;4) 自审和越权被拒绝。 流程级验证:提交申请 -> 审批人处理 -> 申请人查看状态 -> 审计/历史可追溯。 manual|playwright DOING DONE TODO DONE TODO DONE docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts ["R7E-8"] 2026-05-14 无人工自动化补测:报销 BX-20260514-0016 请假 a22e45f8-b3d6-4862-97f2-30cbe4815e09 和采购 CG-20260514-0005 均完成真实浏览器或 API 待办审批并可申请人回看状态和历史;live 自审或越权边界未在本轮补齐,故保持 DOING 不关闭。 2026-05-14 无人工自动化补测:报销 BX-20260514-0016 请假 a22e45f8-b3d6-4862-97f2-30cbe4815e09 采购 CG-20260514-0005 均完成真实浏览器或 API 待办审批并可申请人回看状态和历史;补跑 approval-boundary 创建请假 b0cd3e00-2e67-4f51-9aaf-63aa2c53b47e / task 2cf30190-f569-4cce-ac9e-a0fe183bd460,申请人本人和 admin-only 审批接口均被 PERM_002 拒绝,经理正常通过;server workflow 单元测试 2 files 14 tests passed;证据 report-approval-boundary.md。
14 R7E-12 请假流程试运行 员工提交请假,审批人审批,员工和团队视角查看状态。 1) 请假提交成功;2) 审批处理成功;3) 移动/PC 状态一致;4) 团队状态或日历口径可解释。 流程级验证:员工提交请假 -> 审批通过/驳回 -> 查看进度和团队状态。 manual|playwright DONE DONE DONE docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts ["R7E-8"] 2026-05-14 无人工自动化补测:员工创建未来工作日请假并提交;审批人处理通过;申请人 PC 回看已通过且 /mobile/leave 记录页可见无横向滚动;测试单据 a22e45f8-b3d6-4862-97f2-30cbe4815e09;证据 artifacts/r7e/browser-business-trialrun/report-leave.md。
15 R7E-13 采购流程试运行 员工提交或查看采购申请,审批人处理,状态和附件可追溯。 1) 采购申请路径可用;2) 审批处理可用;3) 附件和状态可追溯;4) 移动采购创建如缺失则记录为后续 UX/P2。 流程级验证:员工提交/查看采购 -> 审批处理 -> 查看状态和附件。 manual|playwright DONE DONE DONE docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts ["R7E-8"] 2026-05-14 无人工自动化补测:采购 CG-20260514-0005 完成 PC 创建 明细 无敏感测试附件上传 提交 审批 状态和审批历史回看;移动采购列表 详情和附件可见且无横向滚动;证据 artifacts/r7e/browser-business-trialrun/report-purchase-attachment.md。
16 R7E-14 财务付款和导出试运行 财务按真实路径复核报销、标记付款、查看台账或导出。 1) 财务角色入口正确;2) 付款标记或台账查看可用;3) 导出权限边界清楚;4) 管理员不自动获得财务能力。 流程级验证:财务进入台账 -> 复核/付款/导出 -> 检查权限和审计。 manual|playwright DOING TODO TODO docs/trialrun/人工试运行报告.md|client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts ["R7E-8"] 2026-05-14 无人工自动化补测:财务账号可进入 /ap-operations;但已审批报销 BX-20260514-0016 在 finance-ledger-table 按单号筛选为空,未创建付款批次 未执行付款 未验证导出;本行保持 DOING 并分流到 R7E-16。 2026-05-14 finance-closeout 诊断:报销 40876ef3-0652-4972-aa14-1aad1a855ae0 / BX-20260514-0016 状态 approved;/api/ap-operations/reimbursement-ledger 和 /api/payment-batches 均返回 payment_batch_v1_disabled / flag_force_off;未创建付款批次 未复核 未执行付款 未验证导出;本行保持 DOING 并分流 R7E-16,待公网功能门禁开启或财务路径确认后复测。
17 R7E-15 移动端和真机反馈 收集 R7E 参与者在移动浏览器和企业微信中的真实体验反馈。 1) 至少覆盖代表性 iPhone/Android 或企业微信设备;2) 记录页面、视口、角色和问题级别;3) 阻断问题进入修复分流;4) 体验优化进入 UX8。 流程级验证:按真机公网测试清单人工复核;必要时补 Playwright 截图。 manual|playwright TODO TODO TODO docs/trialrun/人工试运行报告.md|output/playwright ["R7E-9"] 2026-05-14 无人工自动化补测:移动浏览器员工 审批人 财务核心入口通过且无横向滚动;证据 artifacts/r7e/browser-business-trialrun/report-mobile.md;企业微信 UA 模拟通过但不能替代代表性 iPhone/Android 企业微信真机反馈,故本行不提前 DONE。
18 R7E-16 每日问题清单 R7E 期间每天登记问题、级别、归属治理流、处理状态和证据路径。 1) 问题均有级别;2) 阻断问题当天决策;3) 新需求不混入即时修复;4) 每日 closeout 可追溯。 流程级验证:每日人工 closeout;问题分流到 R7E/UX8/ORG8/WF8/BIZ8/QAOPS8。 manual DOING TODO TODO docs/trialrun/人工试运行报告.md ["R7E-10","R7E-11","R7E-12","R7E-13","R7E-14","R7E-15"] 2026-05-14 无人工自动化待分流项:已审批报销 BX-20260514-0016 未进入 AP 台账筛选结果,财务付款闭环暂停;R7E-11 的 live 自审和越权边界仍需补齐;真实企业微信免登录 消息 deeplink WebView 文件选择器和代表设备反馈仍需人工;既有 dg7-mobile-information-dedupe 未启动本地前端服务时访问 127.0.0.1:3000 失败,属于补充矩阵前置条件不是公网业务失败;移动多角色 flow 已通过 browser storage state 修复登录态注入。问题记录不得包含密码 token 或隐私明文。 2026-05-14 无人工自动化待分流项:财务付款闭环暂停,原因已收敛为公网 AP/payment-batches 功能门禁 payment_batch_v1_disabled / flag_force_off;R7E-11 live 申请人/admin-only 越权边界已补齐并关闭;真实企业微信免登录 消息 deeplink WebView 文件选择器和代表设备反馈仍需人工;dg7-mobile-information-dedupe 启动本地 Vite 后 5 passed,之前 127.0.0.1:3000 失败确认为前置服务未启动;问题记录不得包含密码 token 或隐私明文。
19 R7E-17 阻断问题修复分流 根据每日问题清单把阻断问题分流到当前 R7E 修复或后续连续治理流。 1) 阻断问题有 owner;2) 能在 R7E 内修的有方案和验证;3) 范围外问题进入 UX8/ORG8/WF8/BIZ8/QAOPS8;4) 不顺手扩大。 流程级验证:人工核对问题清单和分流结果;必要时创建后续连续 CSV。 manual TODO TODO TODO issues/*.csv|docs/trialrun/人工试运行报告.md ["R7E-16"] 涉及代码修复时必须先方案批准。
20 R7E-18 验收结论 汇总 R7E 真实试运行结果,给出通过、暂停、回滚或继续观察结论。 1) 主流程结论完整;2) 阻断问题为 0 或明确暂停/回滚;3) 用户验收结论记录;4) 未完成项进入后续治理流。 流程级验证:人工验收;报告中列出流程结论、问题清单和后续动作。 manual TODO TODO TODO docs/trialrun/人工试运行报告.md ["R7E-17"] 不能仅凭自动化通过宣布 R7E 完成。
21 R7E-19 P2 排序调整 根据 R7E 真实反馈调整 P2 候选优先级和后续连续治理流顺序。 1) P2 排序基于真实反馈;2) ORG8/WF8/BIZ8/QAOPS8 入口明确;3) 冻结项仍不进入;4) 如需变更 PRD 则另走事实源更新。 流程级验证:人工核对 PRD P2T 表、问题清单和后续 Issue 计划。 manual|rg TODO TODO TODO docs/海音达OA-MVP需求规格说明书.md|issues/*.csv ["R7E-18"] P2 功能开发必须另建或延续对应连续合同。
@@ -16,7 +16,7 @@ QAOPS8-13,DORA 交付指标基线,"建立部署频率、变更前置时间、变
QAOPS8-14,安全发布前检查,"建立发布前安全检查,包括权限、敏感信息、日志、配置、依赖和等保相关底线。","1) 不泄露 token、密码、票据和个人隐私;2) 权限直连审计有证据;3) 日志不记录敏感明文;4) 高风险项进入 Go/No-Go。","流程级验证:node scripts/qa/audit-docs.mjs --check-links;rg -n 'password|token|secret|密钥|权限直连|敏感' docs scripts issues。",node|rg|manual,DONE,DONE,DONE,scripts/qa/audit-docs.mjs|docs|scripts|issues,"[""QAOPS8-9""]",node scripts/qa/audit-docs.mjs --check-links 为 errors=0 warnings=0;全量 audit-docs 为 errors=0 warnings=8;已知 QA 脚本本地测试哨兵值和未登记 docs 作为 Go/No-Go 复核项,不声明等保测评完成。 QAOPS8-14,安全发布前检查,"建立发布前安全检查,包括权限、敏感信息、日志、配置、依赖和等保相关底线。","1) 不泄露 token、密码、票据和个人隐私;2) 权限直连审计有证据;3) 日志不记录敏感明文;4) 高风险项进入 Go/No-Go。","流程级验证:node scripts/qa/audit-docs.mjs --check-links;rg -n 'password|token|secret|密钥|权限直连|敏感' docs scripts issues。",node|rg|manual,DONE,DONE,DONE,scripts/qa/audit-docs.mjs|docs|scripts|issues,"[""QAOPS8-9""]",node scripts/qa/audit-docs.mjs --check-links 为 errors=0 warnings=0;全量 audit-docs 为 errors=0 warnings=8;已知 QA 脚本本地测试哨兵值和未登记 docs 作为 Go/No-Go 复核项,不声明等保测评完成。
QAOPS8-15,发布 Runbook 收敛,"把发布前检查、部署步骤、验证步骤、暂停条件和沟通责任收敛到现有 Runbook。","1) 发布步骤可按顺序执行;2) 预检、部署、验证、暂停、回滚边界清楚;3) 不新增冲突文档;4) 用户可审计。","流程级验证:rg -n '发布|预检|部署|验证|暂停|回滚|Runbook' docs/trialrun/发布试运行准备清单.md docs/trialrun/OPS7运维交接Runbook.md docs/试运行与自动化验证手册.md。",rg|manual,DONE,DONE,DONE,docs/trialrun/发布试运行准备清单.md|docs/trialrun/OPS7运维交接Runbook.md|docs/试运行与自动化验证手册.md,"[""QAOPS8-5"",""QAOPS8-6"",""QAOPS8-10""]",rg 复核通过;发布前检查、部署步骤、部署后验证、暂停条件、回滚边界和责任记录均在现有 Runbook 中;未新增冲突文档。 QAOPS8-15,发布 Runbook 收敛,"把发布前检查、部署步骤、验证步骤、暂停条件和沟通责任收敛到现有 Runbook。","1) 发布步骤可按顺序执行;2) 预检、部署、验证、暂停、回滚边界清楚;3) 不新增冲突文档;4) 用户可审计。","流程级验证:rg -n '发布|预检|部署|验证|暂停|回滚|Runbook' docs/trialrun/发布试运行准备清单.md docs/trialrun/OPS7运维交接Runbook.md docs/试运行与自动化验证手册.md。",rg|manual,DONE,DONE,DONE,docs/trialrun/发布试运行准备清单.md|docs/trialrun/OPS7运维交接Runbook.md|docs/试运行与自动化验证手册.md,"[""QAOPS8-5"",""QAOPS8-6"",""QAOPS8-10""]",rg 复核通过;发布前检查、部署步骤、部署后验证、暂停条件、回滚边界和责任记录均在现有 Runbook 中;未新增冲突文档。
QAOPS8-16,回滚演练窗口,"确认回滚演练窗口、负责人、触发条件、数据保护和恢复验证步骤。","1) 窗口和负责人确认;2) 回滚脚本或步骤有只读预检;3) 数据保护优先;4) 演练结果可追溯。","流程级验证:人工确认回滚窗口;必要时先在非生产环境执行。",manual,DONE,DONE,DONE,docs/trialrun/OPS7运维交接Runbook.md,"[""QAOPS8-11"",""QAOPS8-15""]",完成:按用户授权采用推荐方案;窗口暂定 2026-05-14 19:30-20:30 Asia/Shanghai 即 R7E 首日每日收口后;负责人和暂停回滚决策人 wangshunli;范围为非生产恢复演练优先 生产只读回滚 dry run;步骤为备份清单核对 隔离库恢复 /ready 登录核心流程只读验证 生产回滚步骤只读复盘;触发条件为 P0 数据损坏 发布阻断或公网关键门禁失败;停止条件为备份不完整 权限不明确 影响生产或责任人不在线;本行只确认窗口和边界 未执行数据库恢复 生产回滚 服务切换或破坏性命令;真实恢复或生产回滚执行前仍需再次明确批准。 QAOPS8-16,回滚演练窗口,"确认回滚演练窗口、负责人、触发条件、数据保护和恢复验证步骤。","1) 窗口和负责人确认;2) 回滚脚本或步骤有只读预检;3) 数据保护优先;4) 演练结果可追溯。","流程级验证:人工确认回滚窗口;必要时先在非生产环境执行。",manual,DONE,DONE,DONE,docs/trialrun/OPS7运维交接Runbook.md,"[""QAOPS8-11"",""QAOPS8-15""]",完成:按用户授权采用推荐方案;窗口暂定 2026-05-14 19:30-20:30 Asia/Shanghai 即 R7E 首日每日收口后;负责人和暂停回滚决策人 wangshunli;范围为非生产恢复演练优先 生产只读回滚 dry run;步骤为备份清单核对 隔离库恢复 /ready 登录核心流程只读验证 生产回滚步骤只读复盘;触发条件为 P0 数据损坏 发布阻断或公网关键门禁失败;停止条件为备份不完整 权限不明确 影响生产或责任人不在线;本行只确认窗口和边界 未执行数据库恢复 生产回滚 服务切换或破坏性命令;真实恢复或生产回滚执行前仍需再次明确批准。
QAOPS8-17,上线 Go No-Go 清单,"建立上线或扩大试运行 Go/No-Go 清单,统一本地、公网匿名、带凭据、企业微信真机和人工验收结论。","1) Go、No-Go、Pause 条件明确;2) 阻断问题为 0 或有明确延期;3) R7E 人工验收不被自动化替代;4) 结论写入 Issue 和报告。","流程级验证:人工核对 R7E 结论、QAOPS8 门禁、发布清单和问题清单。",manual,DOING,TODO,TODO,docs/trialrun/发布试运行准备清单.md|docs/trialrun/人工试运行报告.md|issues/*.csv,"[""QAOPS8-15"",""QAOPS8-16""]",当前清单已形成:2026-05-14 最新代码 4b14c92 已部署到试运行环境且 R7E-8 完成;本轮无人工自动化补测结果为公网 /ready 通过 public bundle findings=0 live smoke env ready 授权 PDF 可读,R7E preflight 通过 报销 BX-20260514-0016 创建上传提交审批通过 请假通过 采购 CG-20260514-0005 含附件 PC/移动通过 移动浏览器通过 WeCom UA 模拟通过;财务 AP 台账未出现已审批报销导致付款闭环暂停;dg7-mobile-information-dedupe 未启动本地前端服务时失败属于补充矩阵前置条件;企业微信专属线仍为免登录 消息 deeplink WebView 文件选择器和真机渲染后补门禁;明确 R7E 人工验收不被自动化替代;因 R7E-9 R7E-11 R7E-14 R7E-15 R7E-18 WF8-11 BIZ8-12 仍未完成,本行不标 DONE。 QAOPS8-17,上线 Go No-Go 清单,"建立上线或扩大试运行 Go/No-Go 清单,统一本地、公网匿名、带凭据、企业微信真机和人工验收结论。","1) Go、No-Go、Pause 条件明确;2) 阻断问题为 0 或有明确延期;3) R7E 人工验收不被自动化替代;4) 结论写入 Issue 和报告。","流程级验证:人工核对 R7E 结论、QAOPS8 门禁、发布清单和问题清单。",manual,DOING,TODO,TODO,docs/trialrun/发布试运行准备清单.md|docs/trialrun/人工试运行报告.md|issues/*.csv,"[""QAOPS8-15"",""QAOPS8-16""]",当前清单已形成:2026-05-14 最新代码 4b14c92 已部署到试运行环境且 R7E-8 完成;本轮无人工自动化补测结果为公网 /ready 通过 public bundle findings=0 live smoke env ready 授权 PDF 可读,R7E preflight 通过 报销 BX-20260514-0016 创建上传提交审批通过 请假通过 采购 CG-20260514-0005 含附件 PC/移动通过 移动浏览器通过 WeCom UA 模拟通过;审批边界 approval-boundary 通过,申请人和 admin-only 审批接口均被拒绝且经理正常收尾;财务 finance-closeout 诊断为 AP/payment-batches 功能门禁 payment_batch_v1_disabled / flag_force_off,未执行付款闭环;dg7-mobile-information-dedupe 启动 Vite 后 5 passed,前次 127.0.0.1:3000 失败确认为前置问题;企业微信专属线仍为免登录 消息 deeplink WebView 文件选择器和真机渲染后补门禁;明确 R7E 人工验收不被自动化替代;因 R7E-9 R7E-14 R7E-15 R7E-18 WF8-11 BIZ8-12 仍未完成,本行不标 DONE。
QAOPS8-18,只读审计和排障边界,"明确公网、数据库、日志和 MCP 只读审计边界,避免排障时误写生产或泄露敏感信息。","1) 只读查询边界明确;2) 禁止 INSERT、UPDATE、DELETE;3) 敏感字段脱敏;4) 排障证据只记录摘要和路径。","流程级验证:rg -n 'audit-readonly|只读|INSERT|UPDATE|DELETE|MCP|PostgreSQL' AGENTS.md docs/mcp-tools.md docs/开发交付与变更管理规约.md。",rg|manual,DONE,DONE,DONE,AGENTS.md|docs/mcp-tools.md|docs/开发交付与变更管理规约.md,"[""QAOPS8-14""]",rg 复核通过;AGENTS 限定 audit-readonly 和 PostgreSQL MCP 只读查询;docs/mcp-tools 限定 SELECT 和禁止写操作;开发交付规约已补日志和证据摘要脱敏边界;未执行生产查询或启用新 MCP。 QAOPS8-18,只读审计和排障边界,"明确公网、数据库、日志和 MCP 只读审计边界,避免排障时误写生产或泄露敏感信息。","1) 只读查询边界明确;2) 禁止 INSERT、UPDATE、DELETE;3) 敏感字段脱敏;4) 排障证据只记录摘要和路径。","流程级验证:rg -n 'audit-readonly|只读|INSERT|UPDATE|DELETE|MCP|PostgreSQL' AGENTS.md docs/mcp-tools.md docs/开发交付与变更管理规约.md。",rg|manual,DONE,DONE,DONE,AGENTS.md|docs/mcp-tools.md|docs/开发交付与变更管理规约.md,"[""QAOPS8-14""]",rg 复核通过;AGENTS 限定 audit-readonly 和 PostgreSQL MCP 只读查询;docs/mcp-tools 限定 SELECT 和禁止写操作;开发交付规约已补日志和证据摘要脱敏边界;未执行生产查询或启用新 MCP。
QAOPS8-19,R7E 后上线硬化收口,"在 R7E 真实反馈后集中收口上线硬化,更新门禁缺口、问题分流和后续治理优先级。","1) R7E 结论已记录;2) QAOPS8 未完成项有归属;3) 阻断问题有 owner;4) 后续 ORG8、WF8、BIZ8、QAOPS8 顺序可解释。","流程级验证:人工核对 R7E-18、R7E-19、QAOPS8 当前状态和问题清单。",manual,TODO,TODO,TODO,issues/2026-05-13_17-11-44-r7e-human-trialrun.csv|issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv,"[""QAOPS8-17""]",依赖 R7E 人工试运行结论;当前不能提前完成。 QAOPS8-19,R7E 后上线硬化收口,"在 R7E 真实反馈后集中收口上线硬化,更新门禁缺口、问题分流和后续治理优先级。","1) R7E 结论已记录;2) QAOPS8 未完成项有归属;3) 阻断问题有 owner;4) 后续 ORG8、WF8、BIZ8、QAOPS8 顺序可解释。","流程级验证:人工核对 R7E-18、R7E-19、QAOPS8 当前状态和问题清单。",manual,TODO,TODO,TODO,issues/2026-05-13_17-11-44-r7e-human-trialrun.csv|issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv,"[""QAOPS8-17""]",依赖 R7E 人工试运行结论;当前不能提前完成。
QAOPS8-20,QAOPS8 收口,"完成 QAOPS8 状态回填、验证摘要、证据索引和中文提交。","1) CSV 校验通过;2) 所有 DONE 有命令或人工证据;3) 文档索引和状态矩阵一致;4) git diff --check 通过;5) 中文提交引用 QAOPS8。","流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv;node scripts/qa/audit-docs.mjs --check-registry;git diff --check。",python3|node|git|manual,TODO,TODO,TODO,issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv|docs/文档索引.md|docs/文档事实源状态矩阵.md,"[""QAOPS8-19""]",所有执行行完成后才能收口。 QAOPS8-20,QAOPS8 收口,"完成 QAOPS8 状态回填、验证摘要、证据索引和中文提交。","1) CSV 校验通过;2) 所有 DONE 有命令或人工证据;3) 文档索引和状态矩阵一致;4) git diff --check 通过;5) 中文提交引用 QAOPS8。","流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv;node scripts/qa/audit-docs.mjs --check-registry;git diff --check。",python3|node|git|manual,TODO,TODO,TODO,issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv|docs/文档索引.md|docs/文档事实源状态矩阵.md,"[""QAOPS8-19""]",所有执行行完成后才能收口。
1 ID Title Description Acceptance Test_Method Tools Dev_Status Review1_Status Regression_Status Files Dependencies Notes
16 QAOPS8-14 安全发布前检查 建立发布前安全检查,包括权限、敏感信息、日志、配置、依赖和等保相关底线。 1) 不泄露 token、密码、票据和个人隐私;2) 权限直连审计有证据;3) 日志不记录敏感明文;4) 高风险项进入 Go/No-Go。 流程级验证:node scripts/qa/audit-docs.mjs --check-links;rg -n 'password|token|secret|密钥|权限直连|敏感' docs scripts issues。 node|rg|manual DONE DONE DONE scripts/qa/audit-docs.mjs|docs|scripts|issues ["QAOPS8-9"] node scripts/qa/audit-docs.mjs --check-links 为 errors=0 warnings=0;全量 audit-docs 为 errors=0 warnings=8;已知 QA 脚本本地测试哨兵值和未登记 docs 作为 Go/No-Go 复核项,不声明等保测评完成。
17 QAOPS8-15 发布 Runbook 收敛 把发布前检查、部署步骤、验证步骤、暂停条件和沟通责任收敛到现有 Runbook。 1) 发布步骤可按顺序执行;2) 预检、部署、验证、暂停、回滚边界清楚;3) 不新增冲突文档;4) 用户可审计。 流程级验证:rg -n '发布|预检|部署|验证|暂停|回滚|Runbook' docs/trialrun/发布试运行准备清单.md docs/trialrun/OPS7运维交接Runbook.md docs/试运行与自动化验证手册.md。 rg|manual DONE DONE DONE docs/trialrun/发布试运行准备清单.md|docs/trialrun/OPS7运维交接Runbook.md|docs/试运行与自动化验证手册.md ["QAOPS8-5","QAOPS8-6","QAOPS8-10"] rg 复核通过;发布前检查、部署步骤、部署后验证、暂停条件、回滚边界和责任记录均在现有 Runbook 中;未新增冲突文档。
18 QAOPS8-16 回滚演练窗口 确认回滚演练窗口、负责人、触发条件、数据保护和恢复验证步骤。 1) 窗口和负责人确认;2) 回滚脚本或步骤有只读预检;3) 数据保护优先;4) 演练结果可追溯。 流程级验证:人工确认回滚窗口;必要时先在非生产环境执行。 manual DONE DONE DONE docs/trialrun/OPS7运维交接Runbook.md ["QAOPS8-11","QAOPS8-15"] 完成:按用户授权采用推荐方案;窗口暂定 2026-05-14 19:30-20:30 Asia/Shanghai 即 R7E 首日每日收口后;负责人和暂停回滚决策人 wangshunli;范围为非生产恢复演练优先 生产只读回滚 dry run;步骤为备份清单核对 隔离库恢复 /ready 登录核心流程只读验证 生产回滚步骤只读复盘;触发条件为 P0 数据损坏 发布阻断或公网关键门禁失败;停止条件为备份不完整 权限不明确 影响生产或责任人不在线;本行只确认窗口和边界 未执行数据库恢复 生产回滚 服务切换或破坏性命令;真实恢复或生产回滚执行前仍需再次明确批准。
19 QAOPS8-17 上线 Go No-Go 清单 建立上线或扩大试运行 Go/No-Go 清单,统一本地、公网匿名、带凭据、企业微信真机和人工验收结论。 1) Go、No-Go、Pause 条件明确;2) 阻断问题为 0 或有明确延期;3) R7E 人工验收不被自动化替代;4) 结论写入 Issue 和报告。 流程级验证:人工核对 R7E 结论、QAOPS8 门禁、发布清单和问题清单。 manual DOING TODO TODO docs/trialrun/发布试运行准备清单.md|docs/trialrun/人工试运行报告.md|issues/*.csv ["QAOPS8-15","QAOPS8-16"] 当前清单已形成:2026-05-14 最新代码 4b14c92 已部署到试运行环境且 R7E-8 完成;本轮无人工自动化补测结果为公网 /ready 通过 public bundle findings=0 live smoke env ready 授权 PDF 可读,R7E preflight 通过 报销 BX-20260514-0016 创建上传提交审批通过 请假通过 采购 CG-20260514-0005 含附件 PC/移动通过 移动浏览器通过 WeCom UA 模拟通过;财务 AP 台账未出现已审批报销导致付款闭环暂停;dg7-mobile-information-dedupe 未启动本地前端服务时失败属于补充矩阵前置条件;企业微信专属线仍为免登录 消息 deeplink WebView 文件选择器和真机渲染后补门禁;明确 R7E 人工验收不被自动化替代;因 R7E-9 R7E-11 R7E-14 R7E-15 R7E-18 WF8-11 BIZ8-12 仍未完成,本行不标 DONE。 当前清单已形成:2026-05-14 最新代码 4b14c92 已部署到试运行环境且 R7E-8 完成;本轮无人工自动化补测结果为公网 /ready 通过 public bundle findings=0 live smoke env ready 授权 PDF 可读,R7E preflight 通过 报销 BX-20260514-0016 创建上传提交审批通过 请假通过 采购 CG-20260514-0005 含附件 PC/移动通过 移动浏览器通过 WeCom UA 模拟通过;审批边界 approval-boundary 通过,申请人和 admin-only 审批接口均被拒绝且经理正常收尾;财务 finance-closeout 诊断为 AP/payment-batches 功能门禁 payment_batch_v1_disabled / flag_force_off,未执行付款闭环;dg7-mobile-information-dedupe 启动 Vite 后 5 passed,前次 127.0.0.1:3000 失败确认为前置问题;企业微信专属线仍为免登录 消息 deeplink WebView 文件选择器和真机渲染后补门禁;明确 R7E 人工验收不被自动化替代;因 R7E-9 R7E-14 R7E-15 R7E-18 WF8-11 BIZ8-12 仍未完成,本行不标 DONE。
20 QAOPS8-18 只读审计和排障边界 明确公网、数据库、日志和 MCP 只读审计边界,避免排障时误写生产或泄露敏感信息。 1) 只读查询边界明确;2) 禁止 INSERT、UPDATE、DELETE;3) 敏感字段脱敏;4) 排障证据只记录摘要和路径。 流程级验证:rg -n 'audit-readonly|只读|INSERT|UPDATE|DELETE|MCP|PostgreSQL' AGENTS.md docs/mcp-tools.md docs/开发交付与变更管理规约.md。 rg|manual DONE DONE DONE AGENTS.md|docs/mcp-tools.md|docs/开发交付与变更管理规约.md ["QAOPS8-14"] rg 复核通过;AGENTS 限定 audit-readonly 和 PostgreSQL MCP 只读查询;docs/mcp-tools 限定 SELECT 和禁止写操作;开发交付规约已补日志和证据摘要脱敏边界;未执行生产查询或启用新 MCP。
21 QAOPS8-19 R7E 后上线硬化收口 在 R7E 真实反馈后集中收口上线硬化,更新门禁缺口、问题分流和后续治理优先级。 1) R7E 结论已记录;2) QAOPS8 未完成项有归属;3) 阻断问题有 owner;4) 后续 ORG8、WF8、BIZ8、QAOPS8 顺序可解释。 流程级验证:人工核对 R7E-18、R7E-19、QAOPS8 当前状态和问题清单。 manual TODO TODO TODO issues/2026-05-13_17-11-44-r7e-human-trialrun.csv|issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv ["QAOPS8-17"] 依赖 R7E 人工试运行结论;当前不能提前完成。
22 QAOPS8-20 QAOPS8 收口 完成 QAOPS8 状态回填、验证摘要、证据索引和中文提交。 1) CSV 校验通过;2) 所有 DONE 有命令或人工证据;3) 文档索引和状态矩阵一致;4) git diff --check 通过;5) 中文提交引用 QAOPS8。 流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv;node scripts/qa/audit-docs.mjs --check-registry;git diff --check。 python3|node|git|manual TODO TODO TODO issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv|docs/文档索引.md|docs/文档事实源状态矩阵.md ["QAOPS8-19"] 所有执行行完成后才能收口。
@@ -0,0 +1,8 @@
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
R7ENM-0,R7E 非人工剩余项合同建档,"建立 R7E 非人工剩余项处理合同,限定本轮只处理审批边界、财务 AP/付款闭环、移动矩阵前置和证据回填;不部署、不清理生产试运行数据、不改 API/schema/权限模型/workflow 状态机。","1) CSV 列完整并校验通过;2) 范围限定 client/tests、必要的 server/src/server/tests、docs、issues;3) 不部署;4) 不记录密码、token、票据内容或隐私明文。","流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-14_16-30-00-r7e-nonmanual-closeout.csv;人工核对 Files 不含部署脚本或生产配置。",python3|manual,DONE,DONE,DONE,issues/2026-05-14_16-30-00-r7e-nonmanual-closeout.csv,[],2026-05-14 校验通过;公网 /ready ok=true;public bundle findings=0;live smoke env ready;本轮不部署。
R7ENM-1,财务 AP 诊断,"用 live 凭据对已审批报销 BX-20260514-0016 做 API 级诊断,确认 AP 台账、报销详情和付款批次中的真实状态,优先排除 UI 等待或筛选误判。","1) /api/ap-operations/reimbursement-ledger?q=BX-20260514-0016 有明确结果;2) /api/reimbursements/:id 状态有记录;3) /api/payment-batches 关联状态有记录;4) 若 AP 不可见但报销 approved,不直接猜测修复。","流程级验证:set -a; . ~/.hyb-oa/live-smoke.env; set +a; cd client && PLAYWRIGHT_MANUAL=1 E2E_MODE=live LIVE_SMOKE_BASE_URL=https://oa.hyinda.com R7E_BROWSER_TRIALRUN=1 R7E_BROWSER_FLOW=finance-closeout npx playwright test tests/e2e/manual/r7e-browser-business-trialrun.spec.ts --workers=1 --reporter=list;核对 report-finance-closeout.md。",playwright|node,DONE,DONE,DONE,client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts|artifacts/r7e/browser-business-trialrun,"[""R7ENM-0""]",2026-05-14 finance-closeout 通过执行且记录 SKIP 诊断:报销 40876ef3-0652-4972-aa14-1aad1a855ae0 / BX-20260514-0016 状态 approved;AP 台账 API 和 payment-batches API 均返回 payment_batch_v1_disabled / flag_force_off;证据 report-finance-closeout.md。
R7ENM-2,财务付款闭环,"若 AP API 可见该报销,则用财务创建 R7E 非人工付款批次,财务主管复核,财务执行,并验证报销详情和 AP 台账进入已付款;管理员执行付款必须失败或无权限。","1) 财务创建付款批次成功;2) 财务主管复核成功;3) 财务执行成功;4) 报销详情和 AP 台账显示已付款;5) admin-only 不能执行财务付款动作。","流程级验证:R7E_BROWSER_FLOW=finance-closeout 公网 Playwright 通过;报告记录 paymentBatchId、报销状态、AP 台账付款状态和管理员权限边界摘要。",playwright|node,DONE,DONE,DONE,client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts|docs/trialrun/人工试运行报告.md,"[""R7ENM-1""]",2026-05-14 已按条件执行:因 AP/payment-batches API 均被 payment_batch_v1_disabled / flag_force_off 门禁关闭,未创建付款批次、未复核、未执行付款;R7E-14 保持 DOING,不绕过业务规则。
R7ENM-3,AP 缺陷修复预留,"仅当 R7ENM-1 证明服务端台账 API 漏掉已审批报销且本地可复现时,补最小后端修复和单测;否则只记录 live 数据或配置问题。","1) 本地失败单测先复现;2) 最小修复只触及 financeLedger/AP 查询层;3) server 语法、Prisma validate 和相关单测通过;4) 未部署时不得把公网 R7E-14 写成已通过。","流程级验证:必要时执行 cd server && npm run prisma:validate && node --check src/services/financeLedger.js src/routes/apOperations.js src/routes/paymentBatches.js && npm test -- tests/unit/services/financeLedger.test.js tests/unit/routes/paymentBatches.reimbursement.test.js tests/unit/routes/exports.apOperations.test.js;若未触发修复则人工记录 N/A。",node|npm|manual,DONE,DONE,DONE,server/src/services/financeLedger.js|server/src/routes/apOperations.js|server/src/routes/paymentBatches.js|server/tests/unit,"[""R7ENM-1""]",N/A:公网返回明确功能门禁 flag_force_off,不是本地可复现的 AP 查询漏数缺陷;本轮未修改 server/src、未部署。
R7ENM-4,审批边界补测,"新增 R7E 自动化 flow,覆盖申请人本人和 admin-only 对真实待办的越权拒绝,并由经理正常通过收尾;结合既有 workflow 单元证据关闭审批边界。","1) 申请人对本人待办调用审批接口被拒绝;2) admin-only 调用审批接口被拒绝;3) 经理正常通过,申请人回看状态和历史;4) workflow 单元测试通过。","流程级验证:set -a; . ~/.hyb-oa/live-smoke.env; set +a; cd client && PLAYWRIGHT_MANUAL=1 E2E_MODE=live LIVE_SMOKE_BASE_URL=https://oa.hyinda.com R7E_BROWSER_TRIALRUN=1 R7E_BROWSER_FLOW=approval-boundary npx playwright test tests/e2e/manual/r7e-browser-business-trialrun.spec.ts --workers=1 --reporter=list;cd server && npm test -- tests/unit/routes/workflow.batch.test.js tests/unit/routes/workflow.permissions.test.js。",playwright|npm,DONE,DONE,DONE,client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts|server/tests/unit/routes/workflow.batch.test.js|server/tests/unit/routes/workflow.permissions.test.js,"[""R7ENM-0""]",2026-05-14 approval-boundary 通过:请假 b0cd3e00-2e67-4f51-9aaf-63aa2c53b47e / task 2cf30190-f569-4cce-ac9e-a0fe183bd460;申请人和 admin-only 均被 PERM_002 拒绝;经理正常通过;workflow 单元测试 2 files 14 tests passed。
R7ENM-5,移动矩阵前置修正,"启动本地 Vite 前端服务后重跑 dg7-mobile-information-dedupe,确认上次 127.0.0.1:3000 连接失败属于前置服务未启动而非移动矩阵缺陷。","1) 本地 Vite 服务启动在可用端口;2) dg7-mobile-information-dedupe 通过或失败原因可解释;3) 临时服务关闭;4) QAOPS8-17 Notes 补充前置修正结论。","流程级验证:cd client && E2E_BASE_URL=http://127.0.0.1:<port> npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts --workers=1 --reporter=list;人工确认 dev server 已关闭。",playwright|manual,DONE,DONE,DONE,client/tests/e2e/dg7-mobile-information-dedupe.spec.ts|issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv,"[""R7ENM-0""]",2026-05-14 启动 Vite http://127.0.0.1:5173 后执行 E2E_BASE_URL=http://127.0.0.1:5173 npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts --workers=1 --reporter=list;5 passed;临时服务已关闭。
R7ENM-6,状态回填与收口,"回填 R7E、QAOPS8 和试运行报告;若运行时代码修复未部署,不把公网 R7E 结果写成已通过;完成 CSV、文档、diff 校验和中文提交。","1) R7E-11/R7E-14 只在证据满足后回填;2) R7E-9/R7E-15/R7E-18 不因自动化提前关闭;3) QAOPS8-17 补充非人工剩余项结果;4) 试运行报告有摘要;5) git diff --check 通过并中文提交。","流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-14_16-30-00-r7e-nonmanual-closeout.csv;python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_17-11-44-r7e-human-trialrun.csv;python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv;node scripts/qa/audit-docs.mjs --check-registry;git diff --check。",python3|node|git|manual,DONE,DONE,DONE,issues/2026-05-14_16-30-00-r7e-nonmanual-closeout.csv|issues/2026-05-13_17-11-44-r7e-human-trialrun.csv|issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv|docs/trialrun/人工试运行报告.md,"[""R7ENM-2"",""R7ENM-4"",""R7ENM-5""]",2026-05-14 状态回填完成;R7E-11 DONE,R7E-14 保持 DOING;R7E-9/R7E-15/R7E-18 未提前关闭;audit-docs registry errors=0 warnings=1;git diff --check 通过;本轮未部署。
1 ID Title Description Acceptance Test_Method Tools Dev_Status Review1_Status Regression_Status Files Dependencies Notes
2 R7ENM-0 R7E 非人工剩余项合同建档 建立 R7E 非人工剩余项处理合同,限定本轮只处理审批边界、财务 AP/付款闭环、移动矩阵前置和证据回填;不部署、不清理生产试运行数据、不改 API/schema/权限模型/workflow 状态机。 1) CSV 列完整并校验通过;2) 范围限定 client/tests、必要的 server/src/server/tests、docs、issues;3) 不部署;4) 不记录密码、token、票据内容或隐私明文。 流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-14_16-30-00-r7e-nonmanual-closeout.csv;人工核对 Files 不含部署脚本或生产配置。 python3|manual DONE DONE DONE issues/2026-05-14_16-30-00-r7e-nonmanual-closeout.csv [] 2026-05-14 校验通过;公网 /ready ok=true;public bundle findings=0;live smoke env ready;本轮不部署。
3 R7ENM-1 财务 AP 诊断 用 live 凭据对已审批报销 BX-20260514-0016 做 API 级诊断,确认 AP 台账、报销详情和付款批次中的真实状态,优先排除 UI 等待或筛选误判。 1) /api/ap-operations/reimbursement-ledger?q=BX-20260514-0016 有明确结果;2) /api/reimbursements/:id 状态有记录;3) /api/payment-batches 关联状态有记录;4) 若 AP 不可见但报销 approved,不直接猜测修复。 流程级验证:set -a; . ~/.hyb-oa/live-smoke.env; set +a; cd client && PLAYWRIGHT_MANUAL=1 E2E_MODE=live LIVE_SMOKE_BASE_URL=https://oa.hyinda.com R7E_BROWSER_TRIALRUN=1 R7E_BROWSER_FLOW=finance-closeout npx playwright test tests/e2e/manual/r7e-browser-business-trialrun.spec.ts --workers=1 --reporter=list;核对 report-finance-closeout.md。 playwright|node DONE DONE DONE client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts|artifacts/r7e/browser-business-trialrun ["R7ENM-0"] 2026-05-14 finance-closeout 通过执行且记录 SKIP 诊断:报销 40876ef3-0652-4972-aa14-1aad1a855ae0 / BX-20260514-0016 状态 approved;AP 台账 API 和 payment-batches API 均返回 payment_batch_v1_disabled / flag_force_off;证据 report-finance-closeout.md。
4 R7ENM-2 财务付款闭环 若 AP API 可见该报销,则用财务创建 R7E 非人工付款批次,财务主管复核,财务执行,并验证报销详情和 AP 台账进入已付款;管理员执行付款必须失败或无权限。 1) 财务创建付款批次成功;2) 财务主管复核成功;3) 财务执行成功;4) 报销详情和 AP 台账显示已付款;5) admin-only 不能执行财务付款动作。 流程级验证:R7E_BROWSER_FLOW=finance-closeout 公网 Playwright 通过;报告记录 paymentBatchId、报销状态、AP 台账付款状态和管理员权限边界摘要。 playwright|node DONE DONE DONE client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts|docs/trialrun/人工试运行报告.md ["R7ENM-1"] 2026-05-14 已按条件执行:因 AP/payment-batches API 均被 payment_batch_v1_disabled / flag_force_off 门禁关闭,未创建付款批次、未复核、未执行付款;R7E-14 保持 DOING,不绕过业务规则。
5 R7ENM-3 AP 缺陷修复预留 仅当 R7ENM-1 证明服务端台账 API 漏掉已审批报销且本地可复现时,补最小后端修复和单测;否则只记录 live 数据或配置问题。 1) 本地失败单测先复现;2) 最小修复只触及 financeLedger/AP 查询层;3) server 语法、Prisma validate 和相关单测通过;4) 未部署时不得把公网 R7E-14 写成已通过。 流程级验证:必要时执行 cd server && npm run prisma:validate && node --check src/services/financeLedger.js src/routes/apOperations.js src/routes/paymentBatches.js && npm test -- tests/unit/services/financeLedger.test.js tests/unit/routes/paymentBatches.reimbursement.test.js tests/unit/routes/exports.apOperations.test.js;若未触发修复则人工记录 N/A。 node|npm|manual DONE DONE DONE server/src/services/financeLedger.js|server/src/routes/apOperations.js|server/src/routes/paymentBatches.js|server/tests/unit ["R7ENM-1"] N/A:公网返回明确功能门禁 flag_force_off,不是本地可复现的 AP 查询漏数缺陷;本轮未修改 server/src、未部署。
6 R7ENM-4 审批边界补测 新增 R7E 自动化 flow,覆盖申请人本人和 admin-only 对真实待办的越权拒绝,并由经理正常通过收尾;结合既有 workflow 单元证据关闭审批边界。 1) 申请人对本人待办调用审批接口被拒绝;2) admin-only 调用审批接口被拒绝;3) 经理正常通过,申请人回看状态和历史;4) workflow 单元测试通过。 流程级验证:set -a; . ~/.hyb-oa/live-smoke.env; set +a; cd client && PLAYWRIGHT_MANUAL=1 E2E_MODE=live LIVE_SMOKE_BASE_URL=https://oa.hyinda.com R7E_BROWSER_TRIALRUN=1 R7E_BROWSER_FLOW=approval-boundary npx playwright test tests/e2e/manual/r7e-browser-business-trialrun.spec.ts --workers=1 --reporter=list;cd server && npm test -- tests/unit/routes/workflow.batch.test.js tests/unit/routes/workflow.permissions.test.js。 playwright|npm DONE DONE DONE client/tests/e2e/manual/r7e-browser-business-trialrun.spec.ts|server/tests/unit/routes/workflow.batch.test.js|server/tests/unit/routes/workflow.permissions.test.js ["R7ENM-0"] 2026-05-14 approval-boundary 通过:请假 b0cd3e00-2e67-4f51-9aaf-63aa2c53b47e / task 2cf30190-f569-4cce-ac9e-a0fe183bd460;申请人和 admin-only 均被 PERM_002 拒绝;经理正常通过;workflow 单元测试 2 files 14 tests passed。
7 R7ENM-5 移动矩阵前置修正 启动本地 Vite 前端服务后重跑 dg7-mobile-information-dedupe,确认上次 127.0.0.1:3000 连接失败属于前置服务未启动而非移动矩阵缺陷。 1) 本地 Vite 服务启动在可用端口;2) dg7-mobile-information-dedupe 通过或失败原因可解释;3) 临时服务关闭;4) QAOPS8-17 Notes 补充前置修正结论。 流程级验证:cd client && E2E_BASE_URL=http://127.0.0.1:<port> npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts --workers=1 --reporter=list;人工确认 dev server 已关闭。 playwright|manual DONE DONE DONE client/tests/e2e/dg7-mobile-information-dedupe.spec.ts|issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv ["R7ENM-0"] 2026-05-14 启动 Vite http://127.0.0.1:5173 后执行 E2E_BASE_URL=http://127.0.0.1:5173 npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts --workers=1 --reporter=list;5 passed;临时服务已关闭。
8 R7ENM-6 状态回填与收口 回填 R7E、QAOPS8 和试运行报告;若运行时代码修复未部署,不把公网 R7E 结果写成已通过;完成 CSV、文档、diff 校验和中文提交。 1) R7E-11/R7E-14 只在证据满足后回填;2) R7E-9/R7E-15/R7E-18 不因自动化提前关闭;3) QAOPS8-17 补充非人工剩余项结果;4) 试运行报告有摘要;5) git diff --check 通过并中文提交。 流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-14_16-30-00-r7e-nonmanual-closeout.csv;python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_17-11-44-r7e-human-trialrun.csv;python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv;node scripts/qa/audit-docs.mjs --check-registry;git diff --check。 python3|node|git|manual DONE DONE DONE issues/2026-05-14_16-30-00-r7e-nonmanual-closeout.csv|issues/2026-05-13_17-11-44-r7e-human-trialrun.csv|issues/2026-05-13_17-30-00-qaops8-test-release-ops.csv|docs/trialrun/人工试运行报告.md ["R7ENM-2","R7ENM-4","R7ENM-5"] 2026-05-14 状态回填完成;R7E-11 DONE,R7E-14 保持 DOING;R7E-9/R7E-15/R7E-18 未提前关闭;audit-docs registry errors=0 warnings=1;git diff --check 通过;本轮未部署。