39 KiB
Implementation Plan:错误可解释性与付款就绪治理
R1内容复核处置(R2修订,未提交/部署)
R2结果:npm test -- tests/unit/scripts/error-reason-client.test.js tests/unit/routes/auth.login.test.js tests/unit/routes/workflow.transfer.test.js tests/unit/routes/invoicePool.patch.test.js四文件311/311(244条客户端契约);typecheck与vite build退出0。修订后visual-portal.spec.ts实际22/22零重试,含新增财务两段href和BX/PB均消失。日志/tmp/followup-r2-unit.log、typecheck/build/browser同前缀;不是R1的471项整批重跑。
RUN_ISOLATED_DB_TEST=1 RUN_BROWSER_TEST=1 RUN_JOB_QUEUE=1 RUN_ERROR_GUIDANCE_TEST=1 node scripts/qa/test-invoice-first-http.cjs通过PASS_ERROR_GUIDANCE_REAL_AUTH_DB_BROWSER:真实密码登录/JWT、实际发票PATCH携原因码与missingFields、页面显示发票代码/销售方缺失、失败保留ocr_failed,补齐后数据库和页面均变available。fixture是隔离库预置ocr_failed,不声称本次由OCR产生;mock provider无真实云调用。原invoice-ocr-flow全套seed用例本轮未原样运行,其对应修正子流程由此专项覆盖。隔离数据库/合成存储已清理,浏览器及临时preview均关闭,生产未接触。
外部新会话结论有条件通过,未执行测试;包完整性另已核,不能合并成独立运行验收。F1/F2按阻断修复:客户端仅对三个已注册原因投影其允许的动态字段,再复用原文案分支;无动态数据保留注册fallback,不将其他域details带入递归。OCR字段/密码策略使用已知清单,时间只接受有效UTC时间戳,不直接回显未知payload。补同时带reasonCode与真实legacy键的精确内容测试,以及未知/跨域details不泄露反例;invoice-ocr-flow原断言改为实际缺失两字段的完整文案。
F3登记未修债务:共享utils/date日期解析及报销/差旅/资产/付款消费者仍需逐模块审查严格日历校验;本次只修发票的局部函数,不能据此声称共享解析安全。归本任务后续日期输入批次,负责人shunli,09-25复审时给出消费者矩阵、拒绝溢出/闰日/月末/null/时区边界、无写入回归及历史异常只读盘点方案;不改历史记录、不混进本次R2的阻断修复,不延长错误豁免日期。
F4已修:转审输入原因文案同步注册/客户端/固定夹具为10至500字;转审实际守卫未变。F5补财务两段href断言和刷新后BX/PB均消失断言,旧R1表格超出当时实际断言的部分以复核结论为准,新增断言重跑后另记。F6批量逐条错误不携reasonCode登记后续投影债务,不破坏已有跳过键;F7密码登录的401/403/423为既有可区分设计,本次防枚举声明仅适用于邮箱验证码/重置链,不扩称全部登录路径。
R1包及其manifest不变;本轮代码已偏离R1,必须重冻R2后交增量复核。471/27/22是R1记录,不能冒称本次输入通过。
2026-09-15 第三阶段连续收口(本地实施与单元/构建验证通过,未提交/部署)
最终本地结果:19文件471/471通过(/tmp/followup-stage3-tests.log),其中包含发票上传/编辑/选票/文件/查验/差旅关联、七份workflow路由回归、门户、回单独立复核、auth/me/付款账户及237条客户端原因契约。命令为cd server && npm test --后逐个传入上述日志首行登记的19个测试文件;不是全仓测试,也未发送真实OCR。通知管理/IM路由/dispatcher另轮27/27,不能声称实际通知已发送。cd client && npm run typecheck && ./node_modules/.bin/vite build退出0;本轮修改后构建,不复用旧dist。AST229注册/612遗留/零finding、Trellis、process baseline及diff检查通过;docs registry零错误,仍有既有22项未登记告警。浏览器交接测试另记结果。
到期清单收口:paymentAccounts、auth/me、invoicePool主路由及read/verification/shared-schemas、workflow路由的本批VALID_001均已迁移,不为这些路径保留豁免。剩余591条entries/count612仍由原baseline逐条保留owner及2026-10-05到期;utils/workflow15条涉及路由推导,需独立按流程负例评审,workflowDefinitions11条属配置域,不与本次输入修复混交。其他模块保持原逐项责任与期限;09-25复审、09-30有理由的延期提案、10-02查漏均是计划而非已安排自动任务,不允许统一延期,也不把全部技术债宣称完成。
按“尽量一次完成、不重复询问”继续原范围:invoicePool主路由与查验查询schema、workflow路由剩余操作级原因迁移。不是全库612条遗留统一改名,不动workflowDefinitions配置域及utils/workflow审批路由算法。当前AST PASS registered229/migrated316/legacy612;本轮开始695,累计减少83次遗留命中。上述目标路由已无遗留命中,领域workflow仍有utils/workflow等15条,不能把路由清零写成全审批域清零。
发票覆盖上传文件/大小/类型/所属人、修改输入/金额/日期/必填OCR信息、归档、OCR重试和重复例外前置。原PDF专用顶层文案与兼容details保留,原因码走注册builder;不修改OCR默认值、不开启查验、不发送真实发票。审批剩余提示区分已处理、本人不能自审、目标人不可用/不合格、节点异常、业务类型不支持、催办冷却等,守卫条件/顺序/锁/状态不改。
新增日期负例发现真实缺陷:JS Date会把2月30日滚动为3月,且无效月份可能生成Invalid Date。沿本task发票字段输入校验补有限时间值与UTC日期回读一致性;增加非闰年2月29日、2月30日、4月31日、13月拒绝且无写入,以及真实闰日/月末正例。此项是实际输入验证修复,不冒充纯文案更改;不回填历史日期。
中途测试发现builder固定通用顶层message,直接替换PDF两处分支会改变旧API文案;已恢复专用文案且保留原因码。静态门禁不接受动态原因码或直接AppError伪迁移,因此分别使用固定注册builder,不修改门禁或增加豁免。最终联合测试、浏览器交接与构建结果完成后补记,不复用中途失败作为通过。
2026-09-15 后续三域实施(当前权威增量,未提交/未部署)
最终客户端npm run typecheck && ./node_modules/.bin/vite build退出0(/tmp/followup-final-typecheck.log、followup-final-build.log),构建包含本节所有34个新增原因映射。保留既有Browserslist/chunk提示,不新加依赖、不把构建成功称为已发布。
最终同输入回归:cd server && npm test -- tests/unit/routes/auth.login.test.js tests/unit/routes/me.test.js tests/unit/routes/paymentAccounts.test.js tests/unit/routes/invoicePool.bindable.test.js tests/unit/routes/invoicePool.file.test.js tests/unit/routes/invoicePool.verification.test.js tests/unit/routes/workflow.batch.test.js tests/unit/routes/workflow.transfer.test.js tests/unit/routes/workflow.permissions.test.js tests/unit/routes/workflow.return-notifications.test.js tests/unit/routes/workflow.task-detail.test.js tests/unit/routes/portal.test.js tests/unit/services/paymentReceiptManualReview.test.js tests/unit/scripts/error-reason-client.test.js,14文件367/367通过,日志/tmp/followup-final-tests.log。覆盖实际客户端错误解析、认证负例与原业务守卫的合成回归,不是公网/browser/真实JWT新验收。AST、node语法、Trellis治理、process baseline、diff检查通过;docs registry零错误,既有22项未登记告警未扩修。
在已批准D阶段继续完成auth/me、发票查验及审批输入,不另建task。auth/me新增10个原因:输入格式、设备上下文、密码策略、无效内部入口、统一无效验证码及通知设置。缺失/停用/锁定账户与验证码不正确仍返回相同原因,不新增账号枚举;登录、刷新、密码修改与会话事务顺序不变。三条旧测试精确details断言漏加原因码导致初跑失败,修正断言后auth/me连同首批六文件259/259通过,不改业务逻辑绕过测试。
发票查验新增disabled/already_pending/record_missing三个原因并复用invoice_pool.id_invalid;不是OCR开关变更,不启用查验、不新增云端调用。补不存在查验记录、重复排队与无效标识的无写入/无队列反例;两文件201/201通过(含当时191条客户端契约)。审批迁移七个输入parser:意见、转审输入、任务ID、批量同意/退回、催办与统计范围;权限门、状态机、事务与转审资格不变。七个HTTP输入反例均在事务前拒绝;六文件243/243通过(含当时198条客户端契约),包含既有转审、权限、退回通知及详情回归。
最终AST检查PASS:registered190、migrated271、legacy656、findings0;基线634条entries/count656,较本轮开始695减少39次AST遗留命中,日期仍全部2026-10-05。不是已经清完656条;保留invoicePool.js30、shared/schemas1、workflow.js13,workflowDefinitions11仍为未启用配置域,不扩改审批状态/资格。这些余项继续按操作与负例迁移,禁止整文件批量替换或统一延期。
验证日志:/tmp/followup-errors-combined.log、followup-verification-tests.log、followup-workflow-tests.log、followup-final-scan.json。最终同输入合并回归、typecheck/build另记录结果;以上不同轮测试含重叠,不累加宣称独立用例数。没有提交、推送、部署或生产写入;不是独立复核结论。
2026-09-15 第一批实施与验证(未提交/未部署)
按统一计划实际运行既有AST检查器,修复前PASS:registered156、migrated225、legacy695。第一批仅迁移paymentAccounts与invoicePool/read,不改auth/审批状态机或生产数据。
付款账户9个原因涵盖账号/银行输入、完整账号查看理由、无效标识、主体/银行不可用、重复银行编码、银行仍被使用、已有账户不能改公司。发票读取5个原因涵盖筛选分页、选票查询、状态批量查询、不可编辑报销、无效票据标识。保留HTTP status、VALID_001和legacy details;客户端真实resolveErrorMessage与固定中文夹具一起验。未修改解密/查看权限、文件授权、状态或付款逻辑。
移除实际已消除的8条AST豁免,当前665个entries/count687,日期仍全部2026-10-05;新增注册14项,检查PASS registered170/legacy687/findings0。不是只删豁免隐藏旧调用,不把公共helper的一条AST记录当作只有一条业务分支。
最终同轮四文件207/207通过:paymentAccounts13、invoicePool.bindable新增输入负例及既有行为、invoicePool.file文件授权/审计、error-reason-client178;付款账户反例确保未创建/更新/成功审计/通知且不泄漏合成账号。中途发票测试漏解构prisma导致一项测试代码失败,修正后完整四文件重跑207通过,未改业务逻辑绕过失败。客户端typecheck通过,构建另记结果。原auth/me、发票上传/识别核验主路由和workflow仍待后续批次,未声明本task完成。
证据安全日志本机/tmp/followup-error-scan.json、followup-error-after.json、followup-error-wave1-tests.log。未新增真实OCR、生产写入或部署,其他任务旧差异继续隔离;下一批仍沿本task操作级范围,不新建任务。
前端typecheck与vite生产构建最终均退出0,原有chunk体积/Browserslist提示不扩修。node语法、git diff、Trellis治理及process baseline通过;docs registry零错误,保留既有22项未登记文档告警。此轮提示映射由真实客户端resolveErrorMessage测试覆盖,不宣称重跑全部浏览器;权限/状态机未修改。测试/构建日志分别为/tmp/followup-typecheck.log、followup-build.log,产品补丁保持未提交状态。
2026-09-15 统一收口接续
用户采纳一次规划连续实施,协调入口为09-08-reimbursement-payment-closeout/implement.md“六项统一执行计划”。本task承接D,不新建豁免管理系统。已只读重统计:基线673个entries、count合计695、均2026-10-05到期,距09-15为20天;不是695个当前AST命中或产品缺陷。
先用既有检查器区分当前命中/已消除/变动指纹,再逐操作处理paymentAccounts、invoicePool已启用上传/读取/识别核验、auth/me、workflow审批动作;workflowDefinitions配置域不自动纳入。每次同时注册安全原因码、客户端映射、具体提示及禁止副作用断言。09-18首批验证、09-25复审、09-30逐模块延期建议、10-02查漏沿用原节点。延期需具体理由、负责人与验收,不在本轮规划中修改expiresOn。范围内本地实现/重验不逐项询问,最终提交/发布范围集中审批。
2026-09-11 到期治理接续(不统一续期)
本次只读复核现有 AST 基线为 673 条记录,到期仍为 2026-10-05,距 09-11 为 24 天;不是 673 个已证实产品故障。本轮主线修复不改到期日,不重复建立豁免台账。
先按员工首批业务路径排序既有延期域:付款账户维护(paymentAccounts)、发票池读取/识别/核验(invoicePool 系列)、登录/个人资料(auth/me)、审批动作错误(workflow)。这些是下一阶段候选模块名单,不批准整文件替换泛化错误或解冻配置/合同功能;实现时沿注册原因码、客户端映射、具体文本断言三件套按操作迁移。
09-18 验证首批操作迁移;09-25 按模块复审剩余记录;09-30 前逐模块写明未改原因、负责人与新验收点;10-02 查漏。只有有理由的单项/模块延期可交审,禁止到期前统一延长。当前仍全部保留原日期,本轮没有声称已完成余下错误迁移。
0. 开工门
- 用户复核并批准 PRD、design、implement。
- 批准后运行
task.py start;inline 模式实施前加载trellis-before-dev,不派 implement/check sub-agent。 - 记录开工基线、工作区状态和当前 20 处旧字符串测试命中清单。
1. 原因码合同与 parity
- 新增原因码注册表和 reason-aware validation helper;保留顶层
VALID_001与 legacy details。 - 新增客户端 reasonCode 映射与未知错误安全兜底,接入
ApiError.requestId。 - 建立 AST/结构化 parity 检查和版本化遗留指纹:基于规范化 AST 节点形状而非源码文本,纯格式化不得改变指纹;注册唯一性、服务端使用、客户端覆盖、孤儿映射、新增遗留、过期例外全部 fail closed。
- self-test 覆盖同 key 跨域、未注册、拼写、缺映射、一增一删、结构性指纹变化、纯格式化不变、到期和主链路试图加例外。
- 接入既有治理入口;报告只输出相对文件、原因码/域、计数和稳定 finding。
2. 首批主链路迁移
- 迁移报销提交/编辑/票据关联的用户可达校验。
- 迁移付款创建/复核/回单/登记的用户可达校验。
- 迁移请假提交、考勤修正提交的用户可达校验。
- 主链路达到零例外;其他存量按域记录 owner/reason/expiresOn,不使用永久目录豁免。
- 逐项处置 20 处旧字符串:
- 客户端 4 个 mock 改为 reasonCode,并断言具体提示/安全兜底;
- 主链路服务测试断言 exact reasonCode、status 和兼容 details;
- workflow utility、ERP procurement、budget 等逐项迁移或登记有效遗留;
failure_message、批处理 reason 等持久化/内部摘要单独验证兼容,不与 UI 文案混同。
3. 付款 readiness
- 抽取共享 resolver,复用快照、部门 gate、账户、占用和 reviewer 事实;搬移 create 条件而非复制。
- 候选批量计算单条 readiness,避免 N+1;异常候选仍返回但不可选择。
- 增加多选组合只读 readiness API;严格输入,响应仅含安全 blocker。
- create 在锁和事务内复用 resolver;失败零 batch/item/成功 audit/notification 副作用。
- 覆盖资料或账户变化后的即时重算,不新增持久字段或长期缓存。
4. 付款页面
- 扩展 API types;候选行显示就近 blocker,正常行无解释噪音。
- 异常候选不可选择并具备可访问原因;有维护权限才显示维护入口。
- 多选变化查询组合 readiness;提示紧贴主按钮,按钮禁用、handler 和 create 二次拦截消费同一原因映射。
- 并发失败留在动作附近;toast 为补充;未知原因使用 request ID 安全兜底。
- PC 覆盖主路径;移动端保持现有能力边界且不显示技术错误。
5. 验证
node scripts/qa/check-error-reason-contract.mjs --self-test与 strict 正常扫描。- Server:registry/helper、付款 readiness/route、报销/B2、请假、考勤 focused Vitest;涉及 workflow/状态机时做只读 review。
- Client:error mapping 测试;付款 Playwright 覆盖正常、三类 0014 缺项、非建行、跨公司、占用、无 reviewer、并发、未知 request ID fallback、键盘/ARIA。
cd server && npm run prisma:validate;触达 JS 运行node --check。cd client && npm run typecheck && npm run build。- UI strict/self-test、Trellis governance、敏感信息扫描、
git diff --check。 - 核对 schema/migration/seed/flag/routing 和生产数据修改为零。
6. Spec、提交与部署
- 实现验证稳定后,把“原因码 + 遗留指纹 + 主链路零例外”和“共享 readiness 多消费者”沉淀到现有 spec,不新建泛化设计文档。
- spec 明确迁移一条遗留原因码的完整合同:服务端注册、客户端映射、具体内容断言三件缺一不可。
- 提交建议:A 原因码/parity;B 首批迁移;C 付款 readiness/UI;task 元数据另行回填。
- commit message 使用中文并引用
[09-05-error-explainability-payment-readiness]。 - commit、push、provenance、部署分别批准;切换前再次运行 UI strict。
- 部署保持
SYNC_ENV=0、existing 数据合同,无 migration/schema/seed/flag/routing/资料补录。 - 部署后核版本、公网文案、合成 readiness/错误投影、B2、maker-checker 和真人单据状态。
- 不自动创建 0014 批次、不复核、不登记付款;真实业务由授权人员完成。
- 回滚无需数据库补偿;新客户端遇旧服务端未知码仍须显示可行动兜底。
7. 开工基线与 20 处旧断言处置
2026-09-05 恢复实施;开工 HEAD 为 ab82fe3,仅当前 task 目录未跟踪并已保留。
依据交接中的明确批准幂等执行 task.py start;本会话主会话实施/检查,没有派 implement/check agent。
原生 update_plan 未在工具集中提供,未创建替代 plan;继续以原已批准清单执行。
下表行号是开工前定位,不以当前字符串总数作为完成证据。兼容响应的原始 message
仍可以出现在测试 fixture;用户展示断言必须具体,不能用宽泛正则掩盖。
延期域均由 shunli 负责,遗留 AST 基线到期日为 2026-10-05(UTC);未增添主链路例外。
| 编号 | 开工前测试定位 | 逐项处置 |
|---|---|---|
| T01 | client/tests/e2e/r103-cross-page-ui-consistency.spec.ts:544 |
采购附件 mock 增加 purchase_attachment.unsupported_type;对应服务端分支、固定中文断言和安全上传浏览器断言一并保留。 |
| T02 | client/tests/e2e/r111-invoice-reimbursement-guard.spec.ts:448 |
提交 mock 改为 reimbursement.items_invoice_item_guard_failed;保留四类精确数量解释、异常字段安全兜底与双端就近提示断言。 |
| T03 | client/tests/e2e/r111-invoice-reimbursement-guard.spec.ts:481 |
明细关联 mock 改为 reimbursement.invoice_invalid_unlinked_item_state;保留准确中文和原子关联断言。 |
| T04 | client/tests/e2e/pc-finance-admin-visual-wave4.spec.ts:83 |
核验 mock 分别登记频控/次数上限原因码;服务端注册、客户端映射、固定内容和 route details 精确断言齐全;旧 VALID_001: UI 前缀断言改为无技术前缀的准确中文,不用正则。 |
| T05 | server/tests/unit/utils/workflow.test.js:64 |
workflow 配置工具延期;保留原准确消息断言,对应 utils/workflow.js 到期指纹。 |
| T06 | server/tests/unit/utils/workflow.test.js:65 |
workflow 空步骤配置延期;保留原断言,对应同文件独立调用指纹。 |
| T07 | server/tests/unit/utils/workflow.test.js:87 |
approval-rule 配置工具延期;保留原断言及到期指纹。 |
| T08 | server/tests/unit/utils/workflow.test.js:94 |
approval-rule 无效配置分支延期;保留原断言及到期指纹。 |
| T09 | server/tests/unit/utils/workflow.test.js:112 |
approval-rule 结构配置分支延期;保留原断言及到期指纹。 |
| T10 | server/tests/unit/utils/workflow.test.js:331 |
缺少 assignee rule 配置延期;保留原断言及到期指纹。 |
| T11 | server/tests/unit/utils/workflow.test.js:332 |
未知 assignee rule 类型延期;保留原断言及到期指纹。 |
| T12 | server/tests/unit/services/leave.test.js:50 |
改为精确 VALID_001、422、leave.leave_invalid_range 与兼容 leave: invalid_range。 |
| T13 | server/tests/unit/services/leave.test.js:98 |
改为精确 VALID_001、422、leave.leave_non_working_range 与兼容 leave: non_working_range。 |
| T14 | server/tests/unit/routes/integrations.erp.procurement.test.js:49 |
ERP procurement 非首批域延期;保留原消息断言与 integrations 模块到期指纹。 |
| T15 | server/tests/unit/routes/integrations.erp.procurement.test.js:57 |
ERP procurement 另一资格分支延期;保留原断言,不扩展集成能力。 |
| T16 | server/tests/unit/routes/paymentBatches.reimbursement.test.js:2341 |
内部持久化 failure_code/failure_message 及 API 字段兼容断言保留;执行风险既有 JSON 仅附加注册原因码、刷新安全说明,不改风险状态;明细/风险卡经专用 helper 展示,历史与未知原因安全兜底,不直接展示原摘要。 |
| T17 | server/tests/unit/routes/workflow.batch.test.js:377 |
内部批处理 reason 兼容断言原样保留;不把批处理摘要冒充用户恢复文案。 |
| T18 | server/tests/unit/routes/workflow.permissions.test.js:172 |
workflow 管理查询域延期;保留准确消息与 routes/workflow.js 到期指纹。 |
| T19 | server/tests/unit/budgetPool.service.test.js:28 |
budget scope 配置域延期;保留原断言与 services/budgetPool.js 到期指纹。 |
| T20 | server/tests/unit/budgetPool.service.test.js:75 |
budget pool 候选配置域延期;保留原断言及到期指纹,不变更预算规则。 |
8. 实施与只读复核记录
- 原因码合同接入既有
run-release-gate.shstatic 阶段;主链路包含 invoice bind/unbind 与共享 item resolver,不借整目录永久豁免绕过。 - 候选、组合预检和创建事务复用
loadPaymentCreationFacts与resolvePaymentBatchCreationReadiness;候选关系、占用、公司账户、复核人批量读取。 部门 gate 仅在单次事实加载内复用底层 flag 查询,仍调用原判定实现;没有修改 flag。 - 只读 reviewer 首轮发现两项 P2:未选中时无法切换付款渠道、失效已选项无法取消。 已分别移出渠道选择器的选中条件、允许失效已选项取消,并补浏览器回归。 第二轮只读 review 确认这两项闭环及请求内 gate 查询复用;无新增高置信问题。
- 系统 Python 缺
xlwt导致既有银行模板导出测试失败;使用现有隔离测试环境提供的 Python、通过PAYMENT_ORDER_PYTHON_BIN运行后恢复通过。未改依赖清单或生产配置。 - 首轮扩大浏览器运行另包含一个合同只读用例超时,未完成该项归因,未改合同产品逻辑或该断言; 付款、B2、采购与本轮核验反馈改为明确 focused 集重跑,不把无关失败标成通过。
- 已更新现有 backend/frontend spec;根因归类为跨层合同和传播缺失,而非真实资料补录。
- 本轮不提交、不 push、不部署、不归档;真实资料和 0014 的任何业务写入均未执行。 部署后 AC12 仍须独立批准与公网证据,不能用本地合成结果替代。
- 最终检查进一步发现两处付款明细直出旧失败摘要,已按 T16 补齐安全展示转换; 新原因只保存在既有执行风险 JSON 元数据中,未新增 schema、readiness 持久字段或日志机制。 追加只读 review 确认历史兼容、事务和风险状态边界,无新增高置信问题。
9. 本地验证结果(2026-09-05)
| 验证 | 结果与边界 |
|---|---|
| AST strict | PASS;142 注册原因、199 已迁移使用点、695 遗留调用、主链路例外 0、finding 0。遗留身份同时包含相对文件、operation 和规范化 AST 形状,不能靠移动操作或一增一删抵消。 |
| AST self-test | 20 项 PASS;正常跨域与纯格式化退出 0,其余拒绝场景退出 1,包括六类必查失败、主链路加例外、同数替换、别名、具体内容断言缺失、operation 移动、条件式通用码和不安全文案。 |
| 扩展服务端 focused | 23 文件 / 407 用例 PASS:报销、票据、请假、考勤、付款、readiness、registry/helper 和客户端投影。 |
| 后续兼容/新增边界 focused | 8 文件 / 309 用例 PASS:包含当轮 75 个付款 route 用例、149 个具体内容/安全投影用例、采购附件和延期域/内部摘要兼容测试;与上一行有交集,不合并虚报数量。 |
| 最终摘要投影 focused | 4 文件 / 244 用例 PASS:76 付款 route、150 内容/投影、16 readiness、2 helper;新增既有风险元数据更新与历史摘要保护,和前述测试有交集。 |
| Playwright focused | 18 个不同用例 PASS(原 17 项 + 最后追加的失败摘要保护 1 项):银行正常提交、现金渠道、三类缺项、非建行、跨公司、占用、无 reviewer、创建并发、移动未知原因排障编号、键盘/ARIA、渠道可达与失效项取消、B2 双端、采购附件、核验错误、PC/移动视口历史失败明细及风险保护。仅本地全合成 API mock。 |
| 客户端工程 | npm run typecheck、npm run build PASS;未部署构建产物。 |
| 服务端工程 | Prisma validate、触达 JS/MJS node --check PASS;没有执行 migration 或数据库重置。 |
| 治理 | UI strict/self-test、process baseline、docs registry、Trellis validate/governance、敏感扫描、git diff --check PASS。 |
| 只读 review | 首轮两项 P2 已修复;第二轮确认闭环;追加摘要投影与风险元数据复核无新增高置信问题。Reviewer 未写文件、未操作真实数据。 |
| 边界核对 | schema/migration/seed/flag 实现、前端 routing、真实资料与真实付款写入均为 0;0014 未操作。 |
复跑入口:node scripts/qa/check-error-reason-contract.mjs --strict 与 --self-test;
服务端测试中的银行模板导出需把 PAYMENT_ORDER_PYTHON_BIN 指向满足现有锁定依赖的隔离测试 Python。
浏览器 focused 文件为 payment-reviewer-permissions.spec.ts、r111-invoice-reimbursement-guard.spec.ts、
r103-cross-page-ui-consistency.spec.ts 和 pc-finance-admin-visual-wave4.spec.ts,筛选本表相关用例;
不得对公网或真实账户套用这些 mock 场景。
10. 独立复核、遗留验证事项与发布授权(2026-09-05)
- 用户独立复核 PASS:真实调用点注入未注册原因码时 strict 退出 1;向主链路新增例外时 strict 退出 1;确认 readiness 三处共用、20 项 self-test 及格式化指纹稳定。用户确认探针全部还原,基线校验与备份一致。
- 两个 task 已按完整文件物理分离;本目录仅保留错误可解释性与付款 readiness,Trellis 升级在独立 worktree 待单独审查。原治理文件均与开工 HEAD 一致,分离后原因码及治理门禁通过。
- 未解决验证事项:首轮扩大浏览器运行的合同只读用例超时,未归因、不计入通过结果,不是已确认的产品缺陷或可永久忽略的 flaky。后续合同域验证前必须单独复现,补充精确用例、失败步骤及环境证据后归类;本任务不得通过放宽断言、重试至绿或混入 focused PASS 关闭它。
- 用户明确批准本任务提交、push、部署;部署后核验
/ready与 bundle marker、文案扫描零 findings、0014 候选禁用及缺项原因、创建接口 fail-closed、B2 保持 force_on + global。 - 生产核验只使用最小脱敏结果,不读取或修改真实银行卡资料;不补录 0014,不执行真实付款。若前置条件变化可能导致创建成功,停止强行创建探针。
- Task 保持
in_progress;独立复核通过不等于公网 AC12 完成。发布和公网证据待实际执行后回填,不提前标记 PASS,不归档 Trellis 升级任务。
11. 发布与公网验收结果(2026-09-05)
- 产品提交:
a83791263833547fdab7ba6910f190fcccd5e34b,已 push;本任务 42 个文件,未包含 Trellis 升级改动。当前节及验收状态属于后续证据提交,不改变线上产品版本。 - 按既有入口
production-identity-bootstrap.mjs先执行只读预检再部署,两次退出均为 0。生产身份验证通过,迁移 reconciliation 前后均pending=none,回滚窗口 OPEN;应用发布、运行时 smoke 及备份合同刷新通过。未修改部署脚本、schema、migration、seed 或 flag 实现;使用既有部署 init,不将其描述为完全无运维写入。 /ready:HTTP 200,buildSha=a83791263833,与产品提交前缀一致。公网 bundle 扫描:scanned=106 focused=2 buildMarker=PASS findings=0。- 0014 候选 API:
ready=false,原因码精确包含payment_batch.legal_entity_required、payment_batch.payee_bank_required、payment_batch.payee_account_required。 - 公网真实浏览器:候选行可见,复选框 disabled;所属公司及银行资料缺项说明就近可见,
aria-describedby正确关联。不是本地 mock 或仅根据 bundle 推断 UI。 - 创建接口探针:先重新请求组合 readiness,确认三类缺项仍存在且
ready=false后,才发出用户批准的创建请求;HTTP 409、VALID_001、details.reasonCode=payment_batch.legal_entity_required。未补录资料、未创建成功批次、未执行付款。 - B2:受控认证只读查询确认
reimbursement_invoice_guard_v1仍为force_on + global;未调用 flag 修改接口。 - 验证账号边界:受控财务测试账号登录 HTTP 403,未重置、恢复或更改权限;上述页面与 API 验收改用可正常登录且有既有权限的受控管理员账号完成。不将本次结果表述为该财务账号登录恢复;该账号可用性待管理员单独核对。
- 所有公网探针仅输出状态码、原因码和布尔断言;未保存 token、真实银行资料、原始业务响应或包含真实业务内容的截图。临时浏览器均已关闭。
- AC12 已凭上述真实负向证据勾选。0014 仍需业务人员补所属公司、确认真实开户行并录入真实资料;非建行停止,不得伪填。合同只读超时仍为未归因事项,由
shunli在下次合同域验证前安排独立复现并归类,不计入本轮通过,不以本次发布关闭。 - 本 task 发布验收完成,未获归档授权,保留
in_progress和现有目录;Trellis 升级继续留在独立 worktree,未审、未提交、未部署。
12. 用户复核后的交接与待规划事项(2026-09-05)
- 用户确认部署后复核 PASS:线上
/ready=a83791263833,复核时工作区干净且 HEAD 与 origin/main 一致。 - 公司使用事实:用户明确本系统仅供本公司内部使用。付款主体字段用于确定对公付款账户归属,不等同于为外部公司提供多租户服务;是否存在多个付款主体不能仅由“内部使用”推导,后续方案以用户确认的单主体业务事实及有效配置为准。
- 待规划建议(未批准实施):单公司模式下,在主体归属唯一且有效时自动采用默认主体,保留现有账户归属结构;没有有效主体、多主体或员工已有显式归属冲突时不得猜测、覆盖或按首条记录取值。员工创建时赋值与付款时解析默认值是不同的数据合同,须先选定方案;付款事实加载、账户查询、候选/组合/事务须保持一致,不能只在页面隐藏缺项或只消除 blocker。当前付款路径仍读取员工的主体归属,尚未实现此建议;未全面审计所有员工写入入口,不宣称“全系统没有自动赋值”。
- 该建议可与单主体体验盘点一起收集,但不作为统一待办实现的前置条件或顺带改动;成本中心、单据分类仅列为待核查项,未确认其冗余,也不删除或擅自隐藏。
- 0014 当前仍由授权业务人员按顺序补所属公司、向本人确认真实开户行及卡号并直接录入系统;资料不发聊天,非建行停止,不伪填。完成后由业务人员走创建并提交复核、经理/CEO 复核、财务登记付款。本会话不执行这些真实业务动作。
- 下一项统一待办需求仅以该真实流程的三个交接观察为输入:交给财务组批、交给经理/CEO 复核、交回财务登记付款;每处记录谁交给谁、接收人通过什么现有入口或提醒知道轮到自己、是否需要口头催办。尚未发生的交接不预填结论,不记录真实银行资料。
- 独立待办仍保留:财务测试账号 403 需要单独解决并补财务身份真实验收(管理员代验不等于该角色验收);合同只读超时需单独复现归因,不计入通过;“三张单的答复”仅作为用户提醒保留,未明确具体单据和答复内容,不自行推断或代答。
- Trellis 升级另行审查:逐条核对 workflow.md 与 project-governance.md 删除或弱化的规则及理由,独立检查 hooks 行为变化;不以模型升级为整批删除保障的理由。本次仅记录后续事项,不启动新产品任务、不修改配置或真实资料、不自动提交、部署或归档。
2026-09-16 上线后契约补强
后续日期批次方案:共享date工具新增纯isValidDateOnlyString谓词(严格YYYY-MM-DD、有限UTC日期、回读同日),保持旧parseDateOnlyString行为以免无关服务突然抛500;先接报销/付款/差旅申请/资产四路由的既有Zod日期schema,optional/nullable外层语义不变,失败沿原输入错误合同且写入前拒绝。催办复用前端displayFormat的Asia/Shanghai格式并明确“北京时间”,旧details分支也校验UTC形状/有限性,不回显任意字符串。验证单测正反边界、各域实际入口/解析器、无副作用及前端typecheck/build;采购、合同、考勤等剩余消费者继续单列,不冒称所有日期解析债务清零。不迁移或改生产历史日期,不提交/部署本轮未审代码。
日期批次已本地实施:9文件450/450定向回归通过(日期工具/客户端映射/四域验证/报销统计/金额/草稿分类)。付款导出两项首跑因系统Python缺BIFF8依赖返回409,改用已有隔离Python(xlrd2.0.2/xlwt1.3.0)后整轮通过,没有修改生产依赖或产品导出门禁。命令:cd server && PAYMENT_ORDER_PYTHON_BIN=<已有隔离Python> npm test -- tests/unit/utils/date.test.js tests/unit/scripts/error-reason-client.test.js tests/unit/routes/assets.validation.test.js tests/unit/routes/travelRequests.test.js tests/unit/routes/reimbursements.create.test.js tests/unit/routes/paymentBatches.reimbursement.test.js tests/unit/routes/reimbursements.stats.test.js tests/unit/routes/reimbursements.amount-guard.test.js tests/unit/routes/reimbursements.draft-classification.test.js。资产覆盖实际create解析器的4字段无效/闰日/null,不冒充真实DB写入;差旅覆盖PATCH两日期输入前拒绝;报销/付款另有正常日期/清空/无写入反例。催办保留秒且显示北京时间,默认格式消费者仍分钟精度。
消费者盘点:已收口4路由输入schema;invoicePool局部日期函数已有独立严格校验,未重写。contractsRegistry/purchaseRequests/travelOrders/travelReconciliation/weeklyReports/presence/portal、contractRegistryFilters/attendance/employeeStats/feeControl/presenceHistory及export-small-team-observation仍调用旧解析器,需按外部输入与内部派生分类后逐项迁移,不因共享谓词新增就算已修。无生产历史日期扫描/修订;原到期日未改。当前主会话自检不计独立复核,整批新变更待只读内容复核与单独提交/发布批准。
最终增量合并验证:上述9文件再加auth.login、invoicePool.patch、workflow.batch共12文件526/526通过。cd client && npm run typecheck && npm run build退出0;Node语法检查、原因码注册229/遗留612/零finding、process baseline、Trellis治理及git diff --check通过。构建有既有Browserslist数据过期与大chunk提示,未升级依赖或修改拆包。当前未执行浏览器/生产登录业务链,不把旧22项记录当新输入重跑。准备calendar-contract-review-20260916-r1独立只读交审,旧R1/R2交付包保持原字节;本轮不提交或部署,生产仍842c61e6。
842c61e6已部署,公网只读验收通过,发布回执见error-explainability-r2-release。用户批准继续后续工作;本轮先处理独立复核F-1/F-2/F-3的本地测试缺口,不改已上线业务逻辑、不重冻旧包、不自动提交或部署。验收:服务端当前VAT必填集合逐字段投影、密码校验实际输出逐规则投影;路由断言missingFields/password兼容键与具体值;严格UTC形状但非有限日期安全回落。票种扩展、时区展示仍需分别核验,测试覆盖不扩称全集已完成。
最终同输入验证:cd server && npm test -- tests/unit/scripts/error-reason-client.test.js tests/unit/routes/auth.login.test.js tests/unit/routes/invoicePool.patch.test.js tests/unit/routes/workflow.batch.test.js,4文件323/323通过。新增4项(VAT集合、密码策略、非有限日期、催办精确24小时冷却负载);两项已有路由用例加强动态键断言。催办409同时核nextAllowedAt、查询时间窗、无历史/通知/任务写入;只用合成actor/存储替身,不是生产登录链。首轮1项失败是新测试把已有“总金额”误写为“价税合计”,已校正测试预期而未修改产品文案;最终整轮通过。存在Node既有punycode弃用警告,无测试失败。
流程baseline、Trellis治理及git diff --check通过。本轮仅测试/文档,无运行时代码或schema变化,未重跑前端build/浏览器,未独立复核、提交、推送或发布。扩展票种buyerName、密码新规则的输入覆盖、时区与共享日历校验仍不是这组测试能全量保证的事项。