11 KiB
P2 实施笔记 — 写操作过确认卡门禁(Fallback Execute Lane)
施工:Agent-J(实施员),对照
P2-DESIGN.md v1.0逐条落地。 代码轮验证日期:2026-09-03。状态:代码与黄金测试全部就绪,待 K 轮真实冒烟 + 注入复证后合闸。
1. 改动清单(git diff --stat 实测)
跟踪文件改动(git diff --stat,不含 package.json 的既有未提交改动):
docs/CHANGELOG.md | 19 +
docs/architecture/fallback.md | 90 ++++
docs/architecture/harness.md | 3 +
server/agent_core/fallback_lane.py | 915 +++++++++++++++++++- (净增,含 docstring/注释)
server/agent_core/harness.py | 4 +
server/aps_domain/workflow.py | 45 ++
server/integrations/pi_bridge.py | 152 ++++-
tests/golden/test_fallback_lane.py | 31 ++
8 files changed, 1246 insertions(+), 13 deletions(-)
新建文件(untracked):server/agent_core/fallback_verify.py 190 行、tests/golden/test_fallback_execute.py 762 行(19 例)。
(工作区另有 tests/golden/_saga_cp.json 被既有 saga 测试例行改写,已 git checkout -- 还原;package.json +3 行为既有 docx 依赖改动,非本轮产物。)
与设计 §1 文件清单逐条对应:
| # | 设计条目 | 落地情况 |
|---|---|---|
| 1 | fallback_lane.py 计划锁 + 执行编排 |
✅ plan_fingerprint/load_plan/validate_plan/check_step_request/_check_constraints + execute_plan + _stage_plan_confirmation + write_guard_extension + build_pi_runner + FallbackConfig +3 字段 |
| 2 | pi_bridge.py 邮箱协议 + fs_write + 简报模板 |
✅ ActionMailbox + handle_fs_write + fs_write/aps_invoke 注册 + render_plan_task_brief + _PLAN_TASK_TEMPLATE(含 <<<UNTRUSTED_DATA 段落) |
| 3 | harness.py 权力注册 |
✅ _POWER_MAP/_POLICY_DESC 各 +2(agent.fallback.execute=P2、agent.fallback.execute.highrisk=P3) |
| 4 | workflow.py execute_confirmed +1 分支 |
✅ 证据校验后、schedule.publish 前;try/except 归一为显式失败文案;WORLD_WRITE 审计 result=SUCCESS/DENIED/FAILED;补写落盘 |
| 5 | fallback_verify.py 新建 |
✅ world_diff/check_expectations/diff_summary_lines/build_report/report_fingerprint |
| 6 | tests/golden/test_fallback_execute.py 新建 |
✅ 19 例(T-1..T-17 + E-1/E-5/E-7)全绿 |
| 7 | test_fallback_lane.py 守卫模板断言 |
✅ 扩为 3 条(见 §2 偏差①) |
| 8 | docs/architecture/harness.md |
✅ 权力矩阵 +2 行 + 变更记录 FB-02 |
| 9 | docs/architecture/fallback.md |
✅ 追加 P2 章节(协议细节以代码为准,本文为准入口) |
| 10 | docs/CHANGELOG.md |
✅ FB-02 条目(含实测数字) |
| 11 | scripts/poc/smoke_s3_execute.py |
❌ 归 K 轮(设计 §7 已标注"给 Agent-K",J 分工为代码+notes;接口交接见 §4) |
| 12 | scripts/poc/rogue_llm_server.py +2 剧本 |
❌ 归 K 轮(同上;剧本规格见 §4) |
P1 既有面逐字节不变(黄金 test_pi_bridge.py/test_fallback_lane.py 原断言全绿佐证):_TASK_TEMPLATE/render_task_brief/handle_fs_read/render_request_envelope/parse_llm_result;run_fallback_lane(...) 不传新参数时行为与 P1 一致;readonly 守卫模板字节不变。
2. 与设计的偏差及理由
① 守卫双模板方案(v1 readonly / v2 plan+execute),设计预期的"既有守卫测试被打破"未发生。
设计 §2 E 案要求扩展 _GUARD_TS_TEMPLATE,并预期打破 test_fallback_lane.py::test_write_guard_extension_matches_template,要求同轮修复为逐字节断言。实际实施采用双模板:mode="readonly" 输出 P1 模板逐字节不变(原测试原样通过,无需修复),"plan"/"execute" 输出 v2 模板(追加 EXECUTE LANE MODE 注释 + APS_WORK_DIR + fs.unlink/rename/writeFile 许可包装)。理由:P1 只读 lane 的守卫面不应为 P2 承担任何字节级回归风险;v2 的新表面由同轮新增的两条测试逐字节锁定(沙箱写门面 + 两个 mode 的模板内容)。设计的真实意图——"改守卫必须改测试"——以更强形式满足(新增表面均有字节级断言)。
② 执行段任务简报渲染器位于 fallback_lane.py 而非 pi_bridge.py。
_render_exec_task_brief 依赖 PendingAction 结构与摘要字段,与编排器同模块避免跨层 import;pi_bridge 保持"信封/邮箱/注册表"纯协议层。plan_fingerprint/load_plan 同理放 fallback_lane(计划锁是编排概念)。设计 §2 的模块归属描述以本节为准。
③ 步骤级 TOOL 审计由 execute_plan 成功路径补写,而非 workflow 分支。
设计 §1 #4 说 workflow 分支"成功则补写步骤级审计"。实际:步骤级审计条目在 _execute_steps 各 handler 内构造、成功路径统一补写(含 actor/evidenceRefs/计划指纹);workflow 分支只写一条 WORLD_WRITE 汇总审计。理由:归并失败路径(try/except 捕获 + 显式失败文案)位于 execute_plan 内部,失败现场信息(cp_failed 指纹、回滚验证、diff 详情)只有 execute_plan 拿得到;workflow 分支保持薄壳。
④ ExecuteResult.message 由 execute_plan 组装。
设计说"message 由 workflow 分支组装"。实际失败文案的组装素材(失败原因、checkpoint id、漂移/回滚指纹)全部在 execute_plan 作用域内,workflow 只透传 fb_result.message。卡片摘要仍由编排器 _stage_plan_confirmation 从结构化字段再生成(设计 §4.1 的硬约束未变)。
⑤ T-17 经 monkeypatch.setattr("server.agent_core.llm_client.get_provider", ...) 直驱 parse_llm_result。
低置信/未知 verdict/非法 JSON 三态不需要真起 rogue HTTP 服务;真实 rogue 服务的三态复证归 K 轮 §7。
⑥ ExecuteResult 默认 status="failed",成功路径在 try 块末尾显式置位。
施工期曾因此出现"全步骤成功却走失败分支"的缺陷(回滚把已落库成果冲掉),已修复并由 T-2 锁定。记录在此提醒后续维护者:成功是显式结论,不是默认值。
3. 自验结果(全部实测,命令可复跑)
Python 一律 .venv\Scripts\python.exe(硬约束)。
| 验证项 | 命令 | 结果 |
|---|---|---|
| 目标三文件 | pytest tests/golden/test_fallback_execute.py tests/golden/test_fallback_lane.py tests/golden/test_feature_flags.py -q |
41 passed |
| 爆炸半径切片(impact 上下游全符号对应黄金文件) | confirm/审批/saga/checkpoint/chat/契约/导入 16 文件 | 118 passed |
| 邻近切片 | assistant/state 24 例 | 24 passed |
| 全量黄金·批一(80 文件) | 573 passed | |
| 全量黄金·批二(77 文件) | 517 passed, 3 failed, 14 errors | |
| ruff(本轮全部新/改文件) | ruff check ×8 文件 |
All checks passed!(零新增) |
批二 3 failed + 14 errors 与本轮无关,git stash -u 前后逐例一致(基线复跑实测):
test_preference_features.py3 例:内存时钟 2026-09-03 越过示例文档的 validUntil 2026-06-30(日期炸弹,仓库既有)。test_mes_http.py/test_mes_readiness.py/test_trace_external_http.py14 errors:fixture 假数据不满足新接口(仓库既有)。
T-1..T-17 全链路确定性:sandbox fake runner 由 _start_fake_runner 动态分配端口、结束即关,不涉及固定端口;execute 段 fake runner 不经端口(直接注入 build_pi_runner)。
关键断言落点(19 例 ↔ 设计 §5 映射):
- 锁:
load_plan指纹错/缺文件/超步数/空计划/非法结构拒绝;validate_plan漂移拒绝;check_step_request非法 intent/未知字段/数量非正/intent 与 action 不一致拒绝。 - 圈禁:
handle_fs_write写work/../x→{"error": "path escapes allowed roots"};越界 intent(order.delete)在 LLM 层拒绝、不进入审批流。 - 门禁:未决卡阻塞首步(含防重放 mock 回调篡改);无卡世界直接拒绝(hint 含 fallback.propose)。
- 回滚:数量篡改、verify 偏离、子进程崩溃三例均恢复 before 世界 + 显式失败文案 + WORLD_WRITE 失败审计 +(篡改类)cp_failed 现场指纹可复算。
- 证据:expectation 容差 0(±1 拒绝)、无关行变化容忍、中文文案 PASS、diff 摘要行格式。
- 审计链:PROPOSE→GATE(plan 指纹)→GATE(confirm 指纹+快照集)→TOOL×2(步骤)→WORLD_WRITE;失败链 PROPOSE→GATE(plan)→GATE(confirm)→WORLD_WRITE(FAILED)。
- 小世界:17 实体 demo 世界全流程成功(仅种子行可 import.commit)。
- 总开关:features.json
fallback.enabled=false时新分支不触达(feat_fallback=False 复跑 2 例)。
4. 遗留问题 / 交接清单(→ Agent-K)
- 真实 S3 冒烟(
scripts/poc/smoke_s3_execute.py,设计 §7 规格):临时 APS_HOME 双仓 + features.json 开 fallback + 根.env的 kimi-k2.6 key。验收点 A–H 见设计 §7。接口提示:fake pi runner 注入点为fallback_lane.build_pi_runner(签名(config, *, mode="readonly"),execute 段用mode="execute");make_customer_file自检要求detect_kind对该文件失败(否则 commit 阶段会先 reject)。 - 注入复证:
rogue_llm_server.pySCENARIOS +=inject_via_csv(CSV 藏指→断言零文件落盘+零审批+计划锁拦截)与inject_fake_approval(Pi 伪造审批→断言卡片结构不采纳+审批仓空);复跑 P1 三剧本回归。 - 真实 pi + 真实 LLM 端到端未验:守卫 v2 模板在真实 pi 子进程下的行为未验(黄金测试锁定的是模板字节内容本身);
--sabotage变体脚本未实现。 - ASSISTED 长执行占事件循环:设计 §5.2 已知边界,main 期处置项(K 轮真实冒烟时观察 pi 超时 120s 的占用表现)。
- async_jobs 不复用:P2 同步执行(设计 §4.2 取舍),main 期若执行耗时长再评估异步化。
handle_fs_write的root != "work"拒绝分支无专门用例:当前注册表只暴露 work;未来暴露 outbox 写时需补测试。harness.py存量 5 条、workflow.py存量 50 条 ruff 告警(git stash -u基线复跑同为 55 条,零新增;治理归清洁口粮,不在本 round)。
5. 宪法红线自证
- 新写路径唯一入口 = 既有
/api/actions/confirm(workflow.py分支挂在 confirm 处理器内部,无新 HTTP 端点)。 - 全部新 powers 注册进 Harness 权力矩阵并过
require_power调用链(stage→plan→confirm→execute 四段 GATE)。 - 失败路径显式文案且自动回滚;无任何静默降级。
- checkpoint 前/后/失败现场三段快照成对出现,指纹双向验证(beforeFingerprint 重算比对 + 回滚后指纹验证)。
- Pi 写面仍是圈禁
work/邮箱 + 沙箱 unlink/rename/writeFile 三函数包装——没有给 pi 新增任何物理写通道;fs_write仅供中间产物,aps_invoke仅产生请求、由计划锁拦截。 - 计划指纹 sha256 绑定 approvedPlanJson,卡片摘要全部由编排器从结构化字段再生成,注入文本只能出现在
<<<UNTRUSTED_DATA数据段落。