20 KiB
20 KiB
财务后台定位与主导航减法:执行计划
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-reductionnode scripts/qa/check-trellis-governance.mjsnode scripts/qa/check-process-contract.mjs --baseline --jsonnode scripts/qa/audit-docs.mjs --check-registry(退出 0;保留基线 warning:22 个未登记 docs 文件,本轮未新增 docs 文件)- 敏感扫描与
git diff --checkPASS。 - 形成生产批准包: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,migrationpending=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 responsecount=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,responsecount=3;单项 PUT=0、workspace PATCH=0、其他业务 mutation=0。 - 执行器随后因只监听页面网络、没有监听同一 browser context 的
APIRequestContext,把已成功的 batch 误计为 0;该本地 witness 缺陷触发了用户预授权的最多一次恢复 batch。恢复 responsecount=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、各目标 changelog0,回滚窗口OPEN/0。 - 前向写入:batch HTTP 成功且
count=3,三项实际进入force_off@48。执行器的页面级 request listener 没有观察到context.request.fetch,本地计数断言错误报forward_batch_count_0;这不是服务器拒绝或通道不确定。 - 预授权恢复:失败分支只读确认三项确已统一进入
force_off@48后,严格一次 batch 恢复force_on,responsecount=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.mjsPASS;focused Vitest5/5PASS。npm run prisma:validatePASS。完整 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,migrationpending=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 脱敏过滤器按
moduleKeyfail-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 responsecount=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,migrationpending=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;只有多名真人持续使用且出现导航摩擦时才重新评估导航减法。届时验证只覆盖实际依赖和最小
/portalwitness,失败默认保留已知低风险现场做只读诊断,确认产品回归后才恢复。