文件

20 KiB
原始文件 Blame 文件历史

财务后台定位与主导航减法:执行计划

0. 规划与启动门禁

  • 用户批准创建 task 并进入规划。
  • 核验最初四个候选导航项、flag key、batch transaction、后端副作用和生产普查证据。
  • 明确本轮只有“定位固化 + 三个固定 flag 关闭”;原条件目标 project_domain_v1 已因本地准入失败排除,二级入口不实施。
  • 用户只读复核 prd.md、design.md、implement.md 并明确批准启动;已运行 task.py start。

1. 本地定位固化(启动批准后)

  • 更新 docs/产品口径.md:将 A/B 未决门替换为“范围收缩为财务/台账后台,核心 OA 主办流程要求真实使用”。
  • 对齐 P0-1/P0-3/P0-10 中 OA 主办域,明确项目主域当前冻结候选,合同/采购/资产仍为低频台账。
  • 更新 project-governance.md 的 Adoption Mode decision,禁止按失效 R63–R66 排期继续扩建。
  • 只纠正当前活跃任务中会把执行带回 R63–R66 的前向说明;未批量改归档历史。
  • git diff --name-only 断言没有 client/src、server/src、scripts、migration、依赖或部署配置;不新增执行脚本。

2. 本地验证与生产审批停点

  • 启动本地服务并复用两张本地草稿;一张保持未关联,另一张仅在验证窗口内临时关联现有合成项目;记录 flag on 基线。
  • 本地临时 force_off project_domain_v1,用真实浏览器验证页面、控件、错误提示、已关联项目名称/编号和 /api/projects 网络响应。
  • 恢复本地 flag 完整 snapshot 并复核;准入失败,生产 target 固定为 3,project_domain_v1 不进入本轮生产写入。
  • python3 ./.trellis/scripts/task.py validate 08-11-internal-oa-finance-backoffice-positioning-and-navigation-reduction
  • node scripts/qa/check-trellis-governance.mjs
  • node scripts/qa/check-process-contract.mjs --baseline --json
  • node scripts/qa/audit-docs.mjs --check-registry(退出 0;保留基线 warning:22 个未登记 docs 文件,本轮未新增 docs 文件)
  • 敏感扫描与 git diff --check PASS。
  • 形成生产批准包:PRE、三个固定 target、完整副作用、一次 batch、APPLY_UNCERTAIN、可选一次回滚;已在用户批准前停止。

2.1 本地真实浏览器证据(2026-08-11)

  • 环境:本地 PostgreSQL、真实 Fastify/Vite、仓库已安装的 Playwright Chromium;无 page.route、无组件 mock、无产品代码或测试代码改动。Playwright CLI 因系统 Chrome 通道缺失且 CLI Firefox 构建不支持当前环境而未能启动,故只在浏览器驱动层回退到仓库 Playwright,验证对象和网络路径不变。
  • 合成样本:本地原有 1 个项目;从原有草稿中取 2 张,一张保持 project_id=null,另一张临时关联该项目。窗口前后全库已关联报销数均为 0。
  • 开启基线:两张详情的 /api/projects 均为 200;未关联控件有“不关联项目 + 现有项目”两项,已关联控件选中现有项目,项目名称和编号显示一致。
  • 关闭观察:两张详情的 /api/projects 均为 409;页面无红色可见错误,但未关联控件仍启用且只剩“不关联项目”,没有“项目能力已关闭/不可用”的解释;已关联详情的事实卡仍显示原项目名称和编号,控件却丢失该项目选项并回落到“不关联项目”。这会把“关联事实仍存在”呈现成“当前未关联”,不满足明确且不误导的准入合同。
  • 请求边界:关闭阶段自动出现 2 次 POST /api/reimbursements/:id/precheck,代码和现场均确认它是只读预检;其他业务 mutation 为 0。
  • 恢复:flag 的 override/rollout/departments/note/version/创建与更新时间/更新人 snapshot 精确一致;已关联报销数恢复为 0;专用本地浏览器 session 已删除。本地第一次恢复尝试曾把 JSON [] 通过 raw 参数写成 {},门禁立即识别并恢复为原数组;最终有效 witness 的恢复路径只改 override_mode,完整 snapshot PASS。
  • 判定:project_domain_v1 不通过本地准入,不得进入生产 batch。最终生产目标恰好为 announcements_v1、todo_board_v1、weekly_report_v1。

3. 生产 PRE(需单独批准)

  • 只读确认 trialrun identity、运行 SHA、migration 和当前产品差异;不因本地文档提交领先误报运行漂移。
  • 复用既有只读普查能力严格一次确认三个最终 target 模块仍为零数据/零真人活动;任一非零即 PAUSED。
  • 管理员登录一次,只读保存三个最终 target 的 override/rollout/departments/note/version/effective snapshot 和审计基线;不输出账号或凭据。
  • GET 三项 impact,确认副作用与批准合同一致。
  • 断言 project_linking_v1 与合同、采购、资产相关配置不在目标集合。

3.1 生产 PRE 证据(2026-08-12)

  • 身份与运行:唯一 trialrun 身份 PASS;既有部署聚合体检 PASS=13 FAIL=0;运行候选与 origin/main 已部署提交一致,当前本地领先的 8 个提交在 client/src、server/src 和部署 compose 上零差异。数据库三方身份 PASS,migration pending=none,回滚窗口 OPEN / terminatedRows=0 / basis=terminated_status_count。
  • preflight 执行边界:第一次 detached 临时 worktree 在 provenance 阶段因无 upstream 被拒,尚未进入迁移查询;随后使用跟踪 origin/main 的 clean 临时分支完成唯一有效 preflight。临时 worktree/branch 已删除。
  • 使用度:复用已审查的只读事务查询器,通过 stdin 送入运行容器且不落盘;公告、普通待办、周报 totalRows=0,30/90 天真人 actor/event 与真人审计 actor/event 均为 0,queryStatus=PASS,effectiveQueryExecutions=1、zeroRetry=true。第一次本地路径拦截发生在 stdin 重定向前,远端查询执行数为 0。
  • 管理员只读 API:一次登录、零 retry;三项均为 overrideMode=force_on、rolloutType=global、departmentIds=[]、version=47、envEnabled=true、effectiveEnabled=true、effectiveReason=flag_force_on_global。三项现有 note 均非空且 SHA-256 相同;未保存或输出 note 原文。正常 logout 已用于撤销本次 session。
  • 导航与影响:公告 /announcements、普通待办 /todos、周报 /weekly-reports 当前均存在。公告 impact 为公告 API 与 Portal;普通待办 impact 为 todos API、Portal、搜索;周报 impact 为 weekly-reports API、Portal、搜索。公告是“关闭”而非仅隐藏:flag off 后公告 API(含写接口)硬拒,临时发公告前必须先重新开启;Portal/搜索消费者按条件省略,不构成项目 flag 的跨域矛盾。
  • 审计基线:全局 FEATURE_FLAG_UPDATED total=1;三项目标 changelog total 均为 0。源码确认 batch 事务对每个 target 各写 1 条 FEATURE_FLAG_UPDATED,没有独立 batch 审计;因此预期写后为全局 auditDelta=3、三项 changelog 各 +1、batch response count=3,不得按 4 条判断。
  • 最终写入输入:目标恰好为 announcements_v1@47、todo_board_v1@47、weekly_report_v1@47;project_domain_v1、project_linking_v1 及其他 flag 不在集合。生产 batch 尚未批准、尚未执行。

4. 生产 APPLY(需单独批准)

  • 使用既有 batch API 选择恰好三个固定目标;写前重新确认三项均为 force_on/global/version=47/effective=true,审计与回滚窗口基线未漂移。
  • 一次前向 batch 将三项设为 force_off,response count=3;单项 PUT=0、workspace PATCH=0、其他业务 mutation=0。
  • 执行器随后因只监听页面网络、没有监听同一 browser context 的 APIRequestContext,把已成功的 batch 误计为 0;该本地 witness 缺陷触发了用户预授权的最多一次恢复 batch。恢复 response count=3,没有重试前向 batch。
  • 请求通道和 JSON 响应始终明确,没有进入 APPLY_UNCERTAIN;实际配置 mutation 精确为一次前向 batch + 一次预授权恢复 batch。

4.1 生产写入与恢复证据(2026-08-12)

  • 写前现场锁:三个目标仍为 force_on/global/departmentIds=[]/version=47/effective=true;全局 FEATURE_FLAG_UPDATED total=1、各目标 changelog 0,回滚窗口 OPEN/0。
  • 前向写入:batch HTTP 成功且 count=3,三项实际进入 force_off@48。执行器的页面级 request listener 没有观察到 context.request.fetch,本地计数断言错误报 forward_batch_count_0;这不是服务器拒绝或通道不确定。
  • 预授权恢复:失败分支只读确认三项确已统一进入 force_off@48 后,严格一次 batch 恢复 force_on,response count=3;终态三项均为 force_on/global/departmentIds=[]/version=49/effective=true/reason=flag_force_on_global。
  • 独立交叉验证:全局 feature-flag 审计从 1 到 7,增量 6;三个目标 changelog 均从 0 到 2,各增量 2,精确对应一次前向和一次恢复。公告、普通待办、周报及项目导航均已恢复,Portal 只读为 200,回滚窗口仍为 OPEN / terminatedRows=0 / basis=terminated_status_count。
  • 边界与清理:没有单项 PUT、workspace PATCH、其他 flag 或业务数据写入;没有第二次前向 batch。CLI wrapper 权限位、系统 Chrome 缺失、一次缺设备指纹的 400 和一次导航响应形状误判均发生在配置写入之外;最终有效只读核验正常 logout,浏览器/API context 和 token 均销毁。导航响应形状误判的只读核验在 logout 前退出,留下 1 个无人持有的服务端 session;本任务不追加未批准的认证状态写入,记录为自然过期残留。
  • 结论:生产安全回到 PRE 功能状态,但“关闭三项并保持关闭”的业务目标未达成。原 expectedVersion=47 已消耗,任何后续前向写入必须以现场 version=49 重新规划并再次获得明确批准,不能沿用本次批准。

5. POST 与回滚判断

  • 最终 target 均 force_off/effective=false/reason=flag_force_off,version 各 +1;本次因预授权恢复而未达到该终态。
  • 单次前向落地的审计增量恰好为 3、各 target +1;本次最终审计包含前向与恢复,实际为全局 +6、各 target +2。
  • 导航所有 section 不含公告、普通待办、周报入口;本次恢复后这些入口按 PRE 状态重新出现。
  • 三个最终 target 直达 GET 返回可解释 disabled;本次在进入完整 disabled/Portal witness 前被执行器计数断言中止并恢复,未形成可接受的保持关闭 POST 证据。
  • 恢复终态下其他 flag、project_linking_v1、导航、Portal 和回滚窗口保持 PRE 可用状态;业务 mutation 为 0。
  • 只执行用户预授权的最多一次恢复 batch;恢复后停止,没有重试前向写入。

6. 收口

  • 更新 task 证据,明确产品代码零改动、部署 0、最终 target=3、两轮 batch/恢复、审计增量、项目本地准入失败和二级入口延后。
  • 重跑 task/governance/process/docs/sensitive/diff 门禁。
  • 中文 commit 引用 task 名;不自动推送。
  • 按用户批准归档,不创建二级入口、退役或第三次生产尝试 task。

7. 恢复后再次准入(任何新生产批准之前)

  • 新增纯本地 feature-flag-apply-uncertainty.mjs:真实发送次数在 sendMutation 包装层计数,page.on("request") 只作为可选辅助观察;响应和服务端 readback 分开记录,高层入口固定“发送至多一次 → 只读定性”,没有 rollback 回调入口。
  • 本地覆盖“batch 成功但页面观察为 0”:readback 为 POST 时返回 CONTINUE_POST,发送次数=1、前向重试=0、rollback=0。
  • 本地覆盖响应缺失但 GET 为 POST、响应缺失但 GET 为 PRE、GET 失败、部分状态;分别得到 CONTINUE_POST、STOP_NOT_APPLIED、STOP_UNKNOWN、STOP_FOR_MANUAL_DECISION。部分状态不自动继续或恢复,必须停止并申请人工决策。
  • node --check scripts/qa/feature-flag-apply-uncertainty.mjs PASS;focused Vitest 5/5 PASS。
  • npm run prisma:validate PASS。完整 server Vitest 发现既有付款单导出用例 1 条稳定失败(期望 200、实际 409);在干净 HEAD 临时 worktree 中单独运行同一标题仍失败,证明不是本次 QA 状态机/测试引入。本任务不修改付款业务代码,focused 状态机用例保持 5/5 PASS。
  • 重新执行生产 PRE,以现场 version=49 冻结三项目标和审计基线;不得沿用 version=47。身份、运行 SHA、migration、窗口、flag snapshot、审计基线和三模块零使用证据均已重新取得。
  • 形成新的生产批准包并等待明确批准;本次一次前向与一次恢复的批准均已消耗,新的 batch 尚未批准、尚未执行。

7.1 新一轮生产 PRE 的已确认部分(2026-08-13)

  • 管理员只读现场:一次登录、正常 logout,配置 mutation=0、业务 mutation=0。三项仍恰好为 force_on/global/departmentIds=[]/version=49/effective=true/reason=flag_force_on_global;note 均非空且脱敏 hash 一致,未保存或输出原文。全局 FEATURE_FLAG_UPDATED total=7,三项目标 changelog 均为 2;公告、普通待办、周报和项目导航均存在,Portal 返回 200。
  • 运行门禁:唯一生产身份 PASS;运行 build 精确等于 origin/main 已部署候选,本地提交相对该候选在 client/src、server/src 和部署 compose 上产品差异为 0;数据库身份 PASS,migration pending=none,回滚窗口仍为 OPEN / terminatedRows=0 / basis=terminated_status_count。
  • 使用度首次查询:复用归档查询器严格执行一次,执行器报告该次 queryExecuted=1 / zeroRetry=1,内置合同确认只读事务、20 个模块齐全且全部 queryStatus=PASS。本地脱敏过滤器误用 module 而非真实字段 moduleKey,因此没有保留三个目标模块的当前聚合值;没有把该次成功查询伪写成“三模块仍为零”。
  • 使用度 supplemental:用户另行批准后又执行一次、明确标注为 supplemental 的只读查询;它不是首次查询的 retry。三个目标 announcements、todos、weekly_reports 均为 totalRows=0,30/90 天活动、真人 actor/event 和真人审计 actor/event 全部为 0,effectiveFlagState=on、queryStatus=PASS。该次自身 queryExecuted=1 / zeroRetry=1;本轮合计发生两次只读 census 执行,不合并成一次。
  • supplemental 脱敏过滤器按 moduleKey fail-closed:必须恰好命中三个唯一目标,完整数值字段必须为非负整数,query/flag 状态必须符合预期;少项、重复、字段异常或任一使用度非零均直接失败并停止。本次 targetCount=3 且全部通过。
  • 新锁输入:三个目标恰好为 announcements_v1@49、todo_board_v1@49、weekly_report_v1@49;全局审计基线 7、各目标 changelog 2。正式写入前仍须读取现场值做 version lock;若任一项不再为 49、状态/审计漂移或使用度前提改变,停止而不是沿用本批准包。

7.2 第二次生产 APPLY 与恢复(2026-08-13)

  • 批准边界:严格一次三目标前向 batch;只有“前向已通过现场 readback 确认落地”且“真实 POST 验收失败”同时成立,才允许最多一次恢复。观察器信号本身不能触发恢复。本轮没有单项 PUT、workspace PATCH、其他 flag 或业务数据写入。
  • 写前门禁:身份、运行 build、数据库身份与 migration 再次 PASS,回滚窗口 OPEN / terminatedRows=0 / basis=terminated_status_count。同一执行现场确认三项目标仍为 force_on@49,全局审计 7、各目标 changelog 2,导航目标均存在。
  • 前向结果:executeFeatureFlagApplyAttempt 发送计数严格为 1;batch response count=3,无重试。无条件 readback 确认三项统一进入 force_off@50/effective=false/reason=flag_force_off,因此前向确实已落地。页面 observer 没有观察 APIRequestContext 请求只形成 observerMismatch,没有直接触发恢复。
  • 恢复触发:POST witness 报告两个门禁失败——合同台账列表 HTTP 400、Portal UI 失败。由于前向已确认落地且当时执行器把这两项判为真实 POST 失败,按获批分支严格一次恢复;恢复 batch response count=3,readback 为 CONTINUE_POST,三项统一回到 force_on@51/effective=true/reason=flag_force_on_global。配置 mutation 恰好为一次前向 + 一次恢复,业务 mutation=0。
  • 失败定性:恢复后用全新浏览器/API context 只读复核,证明两项均是 witness 假失败,而非产品故障。合同列表端点不接受 page/pageSize,执行器错误附加分页参数才得到 400;正确 GET /api/contracts-registry 为 200。Portal 门禁错误地复用了整段会话累计的 pageErrors;全新分段观察 /portal 正常、正文存在、无新 page error、无 API 5xx。报销、合同、采购、资产、项目五个保留域均为 200。
  • 审计与终态:全局 FEATURE_FLAG_UPDATED 从 7 到 13,增量 6;各目标 changelog 从 2 到 4,各增量 2,精确对应一次前向和一次恢复。导航已恢复,写后回滚窗口仍为 OPEN / terminatedRows=0 / basis=terminated_status_count,migration pending=none。
  • 结论:生产安全,但“关闭三项并保持关闭”的业务目标再次未达成。本次前向与恢复批准均已消费;expectedVersion=49 已失效,任何后续写入必须以现场 version=51 重新锁定并另获明确批准,禁止在本轮第三次尝试。

风险与停止条件

  • 三个最终 flag 不是纯导航开关;若影响合同/采购/资产/报销页面整体可用性,停止并按已批准边界决定回滚。
  • 现场出现任何业务数据或真人活动:停止,不关闭对应模块。
  • 目标、version、运行身份或结果不确定:停止,禁止盲重试。
  • 发现需要产品代码才能完成:返回规划并重新批准;不得把阶段二偷渡进本轮。

Residual Register

  • OPEN / OUT_OF_SCOPE:付款批次 BIFF8 导出单测“exports a reviewed CCB batch as BIFF8 and records the first export”稳定得到 409、预期 200;完整 server suite 与干净 HEAD 临时 worktree 的单标题复现结果一致,证明不是本任务 QA 状态机改动引入。后续应独立定性运行依赖、模板门禁或产品行为,不得长期把该红灯当作可忽略背景噪音;本任务不修改付款业务代码或测试断言。
  • OPEN / TOOLING:归档后的 run-production-usage-census.sh 仍按活动 task 相对层级计算仓库根,并引用归档前 query 路径;直接运行会在本地 source deployment contract library 前失败,远端查询为 0。本轮通过进程内只读路径替换复用既有 runner,未修改归档证据;后续若正式复用该入口,应让 runner 对归档移动稳定或提供受测的显式仓库根,不把本地路径漂移误判为生产故障。
  • OPEN / TOOLING:第二次生产 APPLY 的恢复由两个 witness 假失败触发:合同列表探针使用了端点不支持的分页参数;Portal 门禁跨阶段累计 pageErrors。两者在全新只读 context 中均证明产品正常,但恢复已经执行。后续若再次尝试导航减法,必须先用本地用例固定“每个保留域使用真实查询合同”和“页面错误按单个导航阶段切片”,不得直接复用本次一次性 runner。

Lifecycle Closeout

  • 完成:财务与低频台账后台定位已进入事实源和治理 spec;项目 flag 因报销跨域降级被排除;三目标零使用与生产安全终态已有证据;QA 状态机 5/5;两轮前向和恢复的版本/审计链完整。
  • 未完成:公告、普通待办、周报仍为 force_on@51,导航减法未保持生效;POST 终态相关 AC 保持未勾选。
  • 停止原因:当前真人采用度过低,入口复杂度尚未形成真实摩擦;继续修建一次性生产 witness 的成本超过业务收益。两次成功写入被验证工具假失败撤销,说明下一步不应继续增加验证复杂度。
  • 替代条件:不创建即时工程任务。下一轮真实报销由管理要求走 OA;只有多名真人持续使用且出现导航摩擦时才重新评估导航减法。届时验证只覆盖实际依赖和最小 /portal witness,失败默认保留已知低风险现场做只读诊断,确认产品回归后才恢复。