From 8e17e8dfa1beaac8800a6a383c432db0e5aae723 Mon Sep 17 00:00:00 2001 From: shunli Date: Fri, 9 Oct 2026 09:22:10 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E9=BD=90=E4=BC=81=E5=BE=AE=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E9=AA=8C=E6=94=B6=E6=A8=A1=E6=8B=9F=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E9=9A=94=E7=A6=BB=EF=BC=8809-06-release-gate-integrity=20/=200?= =?UTF-8?q?9-17-company-loan-principal-repayment=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit N3 第三轮候选 98bab397:浏览器 371 通过、1 失败;报销付款与 PWA 升级通过。 桌面企微历史测试整页导航后等待标题超时,快照退回登录页。 确认默认桌面 context 漏掉已有的 Service Worker 隔离;原运行没有请求来源证据,历史唯一根因未证实。 补文件级隔离,验证原导航实际获得该 fixture 的 refresh/profile 响应:200、非 Worker、requestId 对应。 原三项用例、登录/会话、桌面只读、手机布局及截图保持。受管定向 3 项通过,无失败/跳过/重试,环境和清理通过。 应用、资金规则、迁移、门禁范围、预算和全局并发未改。前三轮失败回执保留。 第四轮完整候选结果以新回执为准;独立代码复核及真实还款待验。 仅本地提交,不推送、不部署,不访问生产或真实 OCR。 --- .trellis/spec/hyb-oa/frontend-react-vite-design.md | 1 + .../tasks/09-06-release-gate-integrity/implement.md | 11 +++++++++++ .trellis/tasks/09-06-release-gate-integrity/prd.md | 8 ++++++++ .../implement.md | 12 ++++++++++++ .../09-17-company-loan-principal-repayment/prd.md | 8 ++++++++ client/tests/e2e/internal-readiness-ui.spec.ts | 13 ++++++++++++- 6 files changed, 52 insertions(+), 1 deletion(-) diff --git a/.trellis/spec/hyb-oa/frontend-react-vite-design.md b/.trellis/spec/hyb-oa/frontend-react-vite-design.md index 4364b9fe..f1a5fdc9 100644 --- a/.trellis/spec/hyb-oa/frontend-react-vite-design.md +++ b/.trellis/spec/hyb-oa/frontend-react-vite-design.md @@ -265,6 +265,7 @@ and verification contracts. Do not copy broad aesthetic guidance from - A spec that depends on Playwright route mocks must block Service Workers when it can run a PWA build. Do not rely on Service Worker installation or takeover timing to keep requests visible to `page.route`. +- Cover both default `{ page }` fixtures and manually created contexts. A mobile `browser.newContext({ serviceWorkers: "block" })` does not protect the default desktop fixture; register full-navigation refresh/profile response witnesses before navigating and verify their synthetic source when diagnosing session loss. - Vite dev success is not equivalent evidence: the generated PWA worker is a production-build behavior and may be absent in dev. - Blocking the worker is a fixture boundary, not an authentication bypass. The diff --git a/.trellis/tasks/09-06-release-gate-integrity/implement.md b/.trellis/tasks/09-06-release-gate-integrity/implement.md index 831d6f7c..41bf5d94 100644 --- a/.trellis/tasks/09-06-release-gate-integrity/implement.md +++ b/.trellis/tasks/09-06-release-gate-integrity/implement.md @@ -1,3 +1,14 @@ +## 2026-10-09 桌面模拟接口隔离补齐(N3 第三轮后) + +原回执 `artifacts/release-gate/loan-receipt-n3-20261009-r3/`:候选 `98bab397`,82 迁移、服务端 4558 通过/1 项既有可选跳过,浏览器 371 通过/1 失败。PWA 升级和报销付款主链路通过;唯一失败位于桌面企微历史标题等待,失败快照为登录页。环境、源码一致性及自有资源清理通过。 + +- [x] 读取最终错误栈和快照,确认 `page.route` 文件缺默认 context 的 Worker 隔离;手机 helper 已有 `serviceWorkers: block`,不代表默认桌面 fixture 也生效。原请求来源未采集,历史唯一成因仍未证实。 +- [x] 文件级补既有隔离设置;在桌面原导航前同时等待 refresh 与 `/api/me`,断言 200、非 Worker、匹配该 fixture 的 requestId。保持原登录、三项用例、页面/只读/布局断言、截图和预算。 +- [x] 受管 `retained-local` 全文件三项通过、零失败/跳过/重试,浏览器用例总耗时 9.1 秒;生产构建、两种 context 的全导航及桌面响应来源检查通过,环境、源码一致性及清理通过。原第三轮 `login-portal-ux` 16 项及 R101 3 项按未变输入保留,不计入此次三项结果;不据单次通过追认历史唯一根因或真实银行/生产验收。 +- [ ] 主会话检查和任务/治理通过后形成新的本地提交;N3 对干净新候选执行原完整门禁。此次是已有模拟隔离合同补漏,不修改产品认证或 PWA,也不提高预算/重试到绿。 + +准备目录中的 `internal-readiness-focused/`、`internal-readiness-focused.log` 记录定向结果,下一轮完整回执为 `artifacts/release-gate/loan-receipt-n3-20261009-r4/`。测试时冻结受测输入,结果写 ignored 回执。独立代码复核待完成;未推送、部署、查询生产或使用真实材料。 + ## 2026-10-09 PWA 跨导航版本等待修正(N3 候选验证接续) 来源为借款任务 N3 的 `18315d11` 完整回执:服务端 4558 通过/1 项既有可选跳过,浏览器 371 通过/1 失败、零跳过/重试。栈明确位于 `expect.poll` 回调中的 `documentBuildSha`:页面自动更新销毁旧执行环境后,直接 `page.evaluate` 抛错,未等完原定 45 秒。冻结诊断已观察到文档 B、B 控制器摘要匹配、旧资源缓存归零、B 资源加载、会话保留及零静态 404;这些事后观察不改写原失败。 diff --git a/.trellis/tasks/09-06-release-gate-integrity/prd.md b/.trellis/tasks/09-06-release-gate-integrity/prd.md index bf75fb05..acabc2b5 100644 --- a/.trellis/tasks/09-06-release-gate-integrity/prd.md +++ b/.trellis/tasks/09-06-release-gate-integrity/prd.md @@ -1,3 +1,11 @@ +## 2026-10-09 桌面模拟接口隔离补齐(N3 第三轮接续) + +候选 `98bab397` 第三轮完整门禁为 FAIL:浏览器 371 通过/1 失败、零跳过/重试;报销付款与 PWA 升级已通过。唯一失败是 `internal-readiness-ui.spec.ts` 的桌面企微历史页在整页导航后未出现标题,失败快照为登录页。该文件的手机手动 context 已屏蔽 Service Worker,使用 `page.route` 的桌面默认 context 却遗漏了既有隔离合同。原运行没有请求来源证据,不能宣称历史唯一根因已证明。 + +本次只补测试边界:默认 context 在首次导航前屏蔽 Service Worker;桌面整页导航必须观察到 refresh 与 `/api/me` 的 200 响应、来自预设模拟接口而非 Worker。保留真实页面登录操作、会话提示、全部三项用例、桌面只读和手机空态/详情/布局断言及截图,不改产品认证、PWA、权限、资金、预算或全局并发。先受管定向全文件,再固定本地候选并由 N3 完整复验;保留第三轮 FAIL,不用定向结果拼接资格。 + +修正后受管定向 3 项通过、无失败/跳过/重试,原页面断言、截图及新增响应来源检查通过,环境/源码一致性/自有资源清理通过。新候选完整门禁仍待第四轮回执;独立代码复核未完成。 + ## 2026-10-09 借款候选验证中的 PWA 导航观测修正 `09-17-company-loan-principal-repayment` 的 N3 接续已获本地提交、验证及必要测试修正授权。其候选 `18315d11` 第二轮完整门禁为 FAIL:浏览器 371 通过/1 失败、零跳过/重试;唯一失败为 PWA 跨版本测试的版本读取在应用自动导航时抛出 `Execution context was destroyed`。报销付款主链路已通过,受管环境、源码一致性及清理通过。原回执保留在 `artifacts/release-gate/loan-receipt-n3-20261009-r2/`。 diff --git a/.trellis/tasks/09-17-company-loan-principal-repayment/implement.md b/.trellis/tasks/09-17-company-loan-principal-repayment/implement.md index 02e93ee0..92c3b96c 100644 --- a/.trellis/tasks/09-17-company-loan-principal-repayment/implement.md +++ b/.trellis/tasks/09-17-company-loan-principal-repayment/implement.md @@ -1,3 +1,15 @@ +## 2026-10-09 N3 第三轮结果及第四轮候选验证 + +第三轮候选 `98bab397` 的完整门禁为 **FAIL**:82 个迁移、服务端 4558 通过/1 项既有可选跳过、静态/构建及业务回归通过;浏览器 371 通过/1 失败、零跳过/重试。报销付款主链路和 PWA 跨版本升级通过。原回执及准确失败边界见 `artifacts/release-gate/loan-receipt-n3-20261009-r3/`;环境、源码一致性及自有资源清理通过。 + +- 唯一失败是 `internal-readiness-ui.spec.ts` 桌面企微历史页整页导航后等待标题超时,截图为登录页。确认该文件的模拟接口只在手机手动 context 屏蔽 Worker,默认桌面 fixture 遗漏既有合同;原运行没有请求来源证据,历史唯一成因仍未证实。 +- 已由 `09-06-release-gate-integrity` 补文件级 Worker 隔离,并在原桌面导航中验证 refresh 与 `/api/me` 的 200、非 Worker 和预设 requestId。保留全部原三项用例、登录/会话、桌面只读、手机布局和截图,不改认证/PWA/借款资金代码、迁移、预算或全局并发。 +- 修正后的完整文件受管定向 3 项通过、无失败/跳过/重试;新增响应来源检查、生产构建、环境/源码一致性/清理通过。证据为准备目录的 `internal-readiness-focused/`、`internal-readiness-focused.log`、`internal-focused-process.json`。原第三轮登录体验 16 项和 R101 3 项按未变输入保留,不累加成此次定向总数。 +- 经主会话差异及任务/治理检查后按 N3 既有授权本地提交,再对干净新候选执行原 `bash scripts/qa/run-release-gate.sh verify-candidate`。第四轮回执为 `artifacts/release-gate/loan-receipt-n3-20261009-r4/`;前三轮失败不覆盖、不与定向拼接,不预填 PASS。 +- 验证期间冻结源码、测试和任务文档,实际提交、完整结果、复核交接及专用浏览器清理写入 ignored 回执。独立代码复核、真实还款及公网仍待;未推送、部署、查询生产或调用真实 OCR。 + +最终候选及实际结果以第四轮回执和 `local-followup.json` 为准。以下保留前三轮历史记录,整体任务尚未完成。 + ## 2026-10-09 N3 第二轮结果及第三轮候选验证 第二轮候选为 `18315d11`,完整 `verify-candidate` 为 **FAIL**。82 个迁移、服务端 4558 通过/1 项既有可选跳过、静态/构建和业务回归通过;浏览器 371 通过/1 失败、无跳过或重试。修正后的报销付款主链路实际走到执行及下游收口并通过。原始回执、失败定位及环境清理见 `artifacts/release-gate/loan-receipt-n3-20261009-r2/`,不可由定向结果抵扣。 diff --git a/.trellis/tasks/09-17-company-loan-principal-repayment/prd.md b/.trellis/tasks/09-17-company-loan-principal-repayment/prd.md index 37e4f804..d043cbf1 100644 --- a/.trellis/tasks/09-17-company-loan-principal-repayment/prd.md +++ b/.trellis/tasks/09-17-company-loan-principal-repayment/prd.md @@ -1,5 +1,13 @@ # 公司借款台账与本金归还 +## 2026-10-09 N3 第三轮结果及桌面测试隔离修正 + +候选 `98bab397` 第三轮为 FAIL:82 迁移、服务端 4558 通过/1 项既有可选跳过、静态/构建和业务回归通过;浏览器 371 通过/1 失败、无跳过或重试。报销付款主链路和 PWA 升级本轮均通过。唯一失败为桌面企微历史测试在整页导航后等待标题超时,快照已回登录页;现有测试使用模拟接口,却只在手机 context 屏蔽 Service Worker。原请求来源未记录,不将该漏项写成已证实的历史唯一根因。 + +`09-06-release-gate-integrity` 已补默认桌面 context 的隔离,并要求原导航实际获得该 fixture 的 refresh/profile 响应。原三项用例、登录、会话、桌面只读、手机布局和截图全部保留;受管定向 3 项通过,环境和清理通过。资金及产品代码、迁移、正式门禁范围和预算未变。按 N3 既有授权形成新的本地提交,第四轮完整回执固定为 `artifacts/release-gate/loan-receipt-n3-20261009-r4/`,以其 `release-result.json` 和 `local-followup.json` 记录实际候选及结论。 + +前三轮 FAIL 完整保留,定向通过不能拼接完整资格。独立代码复核和真实还款验收仍开放;没有推送、部署、生产查询或真实材料外发。以下为各历史时点,整体任务继续 `in_progress`。 + ## 2026-10-09 N3 第二轮结果及 PWA 测试等待修正 修复候选 `18315d11` 的完整第二轮仍为 FAIL:82 个迁移、服务端 4558 通过/1 项既有可选跳过、静态/构建及业务回归通过;浏览器 371 通过/1 失败、无跳过或重试。本轮报销付款主链路完整通过;唯一失败为 PWA 自动升级时,测试读取版本号的 `page.evaluate` 遇到正常导航而失去执行环境。错误栈和原回执保留,不把定向通过或事后 B 版本见证替换为整轮 PASS。 diff --git a/client/tests/e2e/internal-readiness-ui.spec.ts b/client/tests/e2e/internal-readiness-ui.spec.ts index 7e77d165..45881a0a 100644 --- a/client/tests/e2e/internal-readiness-ui.spec.ts +++ b/client/tests/e2e/internal-readiness-ui.spec.ts @@ -2,6 +2,8 @@ import { mkdirSync, mkdtempSync } from "node:fs"; import path from "node:path"; import { expect, test, type Browser, type Page, type Route } from "@playwright/test"; +test.use({ serviceWorkers: "block" }); + const visualRoot = path.resolve(process.env.QA_VISUAL_OUTPUT_DIR?.trim() || path.join(process.cwd(), "../output/playwright")); mkdirSync(visualRoot, { recursive: true }); const SCREENSHOT_DIR = mkdtempSync(path.join(visualRoot, "internal-readiness-ui-")); @@ -397,7 +399,16 @@ test.describe("五人团队本地候选移动证据", () => { await mockApis(page, state); await login(page); await page.setViewportSize({ width: 1024, height: 768 }); - await page.goto("/wecom-approval-archive"); + const [refreshResponse, meResponse] = await Promise.all([ + page.waitForResponse((response) => new URL(response.url()).pathname === "/api/auth/refresh"), + page.waitForResponse((response) => new URL(response.url()).pathname === "/api/me"), + page.goto("/wecom-approval-archive"), + ]); + for (const response of [refreshResponse, meResponse]) { + expect(response.status()).toBe(200); + expect(response.fromServiceWorker()).toBe(false); + expect((await response.json()).requestId).toBe("mock-internal-readiness-ui"); + } await expect(page).toHaveURL(/\/wecom-approval-archive$/); await expect(page.getByRole("heading", { level: 1, name: "企微审批历史" })).toBeVisible(); await expect(page.getByRole("button", { name: "查看历史" })).toBeVisible();