aps-agent/poc/pi-fallback/GOAL-P1.md

74 lines
12 KiB
Markdown
Raw Normal View History

# GOAL:Pi Agent 兜底能力 · P1 只读兜底进产品路径(多 agent 协同 · 第二轮)
> 本文件是本轮协同的唯一权威协调板。每位 agent 开工前必读;完成后在文末留言板交接。
> P0 已 GO(见本目录 NOTES-pi-runtime / NOTES-architecture / NOTES-validation)。
## 本轮目标(P1 出口标准)
按根目录《Pi-Agent兜底能力详细方案》§6 P1:S1(意图未识别的只读类兜底)/S5(自由分析)进产品路径——
用户在对话里说了一句产品功能覆盖不了的话,不再只得到话术,而是得到**一份 Pi 真实产出的分析成果**(草稿语义,只读,不写世界)。
具体交付(全部产品代码,可测试、可开关、可审计):
1. `server/agent_core/fallback_lane.py`(moduleId: core-fallback-lane,可重生 ✅):兜底编排器——触发判定、任务简报、拉起 Pi headless、三重熔断、环境清洗、run 目录管理(`~/.aps/fallback/<runId>/` 或 server/data/fallback/)、成败按 stopReason;
2. `server/integrations/pi_bridge.py`(moduleId: integ-pi-bridge):围墙内工具桥——P1 阶段只暴露**只读工具**(fs_read 限 run 目录、aps 只读查询),callId 凭证 + calls.jsonl 落盘 + 报告凭证校验;
3. Harness 登记:`_POWER_MAP` 新增 `"agent.fallback.propose": "P1"`;harness.md 权力矩阵同轮更新;
4. FF-01 开关:`FEATURE_CATALOG` 新增 `"fallback": "智能兜底(Pi Agent)"`,**默认语义=配置缺失即全开,但本功能要求默认关**——需要在 feature_flags 语义内特殊处理(设计员给出方案:如 fallback 键缺失时默认 false,与其余键 fail-open 相反,并在端点响应中显式标注);
5. 接线:`workflow.py` unknown/assistant.reply 分支 → 开关开 且 意图未识别 → 走 fallback propose(**同步超时保护,不得拖死聊天**;失败显式回退原话术);
6. 黄金测试:`tests/golden/test_fallback_lane.py`——开关关=原行为不变;开关开=propose 路径触发(注入 fake runner,确定性);未登记意图仍拒绝;审计落链;熔断触发显式失败;凭证校验拦截伪造;
7. 文档同轮:docs/architecture/harness.md、docs/CHANGELOG.md、新增 docs/architecture/fallback.md。
## 硬约束(全员遵守)
- 工作区根:当前仓库根目录;Python 一律 `.venv\Scripts\python.exe`;
- **不 git commit / push**(等用户授权);改动最小化,不顺手重构;
- 修改 harness.py / workflow.py / feature_flags.py 前必须先查调用方(rg 或 GitNexus),把爆炸半径写进交接记录;
- 遵守 PROJECT_OPERATING_RULES:失败显式、无隐式副作用、P1 草稿语义不得写主干、不引入 mock 进产品路径(fake runner 只允许在测试注入);
- Pi runtime 定位:P1 复用 poc/pi-fallback/runtime/ 的安装,产品化打包(桌面 sidecar)留到后续阶段,但代码里路径解析要可配置;
- 黄金测试必须确定性:不依赖真实 LLM/网络(用注入 fake runner;rogue_llm_server 模式可选用)。
- 模型端点配置:复用 .env 现有 key(不得打印/落盘),模型名要协商(P0 踩过 404 坑:先 GET /models 或配置化)。
## 角色分工
| 角色 | 任务 | 输出 |
|------|------|------|
| Agent-D 设计员 | 读现状代码,产出 P1 文件级详细设计(接口签名、接线点、开关语义方案、风险点) | `P1-DESIGN.md` |
| Agent-E 实施员 | 按 P1-DESIGN 实现全部产品代码改动 | 代码 + `P1-IMPL-NOTES.md` |
| Agent-F 测试文档员 | 黄金测试 + 文档同轮 + focused/全量验证 | 测试 + 文档 + `P1-VALIDATION.md` |
## 协同留言板
(格式:`[角色] 时间 — 结论/交接物/给下一位的话`)
[Agent-D 设计员] 2026-09-02 — 设计完成,交接物 `poc/pi-fallback/P1-DESIGN.md`(8 节:变更清单表 / fallback_lane 与 pi_bridge 全量接口签名 / workflow 接线片段(现状+改法对照)/ 默认关方案 / run 目录与 APS_FALLBACK_* 配置 / 13 例确定性测试矩阵 / 爆炸半径 / P1 边界外清单)。
- **「默认关」一句话**:feature_flags 内新增 `_DEFAULT_OFF_KEYS={"fallback"}`——文件缺失/损坏/未配置/非 bool 时 fallback 默认 False(其余键保持 fail-open),返回体加 `defaultOff` 字段显式标注;`fallback_feature_enabled()` 直接消费 load_feature_flags 单一事实源,不另起解析。
- **风险最高点**:feature_flags 默认关会打破两条既有黄金测试(test_feature_flags.py 的 all-enabled 断言 ×2),必须同轮修(改法已写进设计 §6.0);其次是 workflow 聊天热路径接线(MED,缓解:开关默认关 + propose_reply 绝不抛异常 + 90s 硬熔断)。
- **关键现状核实**(施工前必读设计 §0):真实聊天到兜底分支时 name 几乎总是 `assistant.reply`(intent.py:948 把 unknown/低置信改写掉了);`IntentResult.intent` 是封闭 Literal——**不要**构造 `IntentResult("agent.fallback.propose")`,它只是 _POWER_MAP 动作名;聊天路径 handle_intent 已在线程池跑,同步+90s 上限方案成立,无需异步机制。
- 爆炸半径已 rg 盘点(设计 §7):harness.py=LOW(纯追加)、workflow.py=MED、feature_flags.py=MED。gateway/app.py / tool_runtime.py / contracts.py **零改动**。
- 给 Agent-E:照 §2 签名施工,fake runner 注入点是 `propose_reply(..., runner=..., config=...)`;P0 代码只作参照不重用(不 import poc)。给 Agent-F:测试矩阵 §6 逐例可断言行已写明,test_feature_flags.py 两条旧断言的同轮修法也在 §6。
[Agent-E 实施员] 2026-09-02 — P1 产品代码施工完成,交接物 `P1-IMPL-NOTES.md`(改动清单 / 8 条与设计的偏差及理由 / 自验命令与数字 / 6 条遗留)。
- **改动 7 文件**:新建 fallback_lane.py(809 行)/ pi_bridge.py(259 行)/ test_fallback_lane.py(13 例全确定性);修改 harness.py(+2 纯追加)/ feature_flags.py(_DEFAULT_OFF_KEYS 默认关 + defaultOff 标注)/ workflow.py(+8 接线,开关关时原路径逐字节不变)/ test_feature_flags.py。
- **自验**:fallback+feature_flags 19 passed;受影响回归(contract_sync/assistant/guidance/folder_pack/tool_runtime/gov_api + 聊天网关门禁切片)102 passed;ruff 新增文件全绿、修改文件零新增告警。未 commit。
- **偏差要点**:test_feature_flags 实际修了三条(设计漏列 corrupt_json 那条);result.json 改在 propose_reply 收尾落盘(含 citation_check);unavailable 不建 run 目录;新增空报告防御与 pi→桥工具名映射(不加映射则每次工具调用都误抛 ToolBridgeViolation)。全部理由见 NOTES §2。
- **给 Agent-F**:① 文档同轮未做(harness.md 权力矩阵追加 agent.fallback.propose 行——harness.py 里有同步铁律注释;新建 docs/architecture/fallback.md;CHANGELOG);② 全量 tests/golden 我 300s 没跑完,请用长窗口补跑;③ 真实 pi 端到端冒烟未做(本轮全 fake runner),有 key 环境时按 P0 方法补;④ 既有 test_preference_features.py 日期炸弹失败与本轮无关(已核实零 diff),别误归为回归;⑤ 已知张力:真实 pi 无法获知桥侧 callId,引用即 forged_citation——测试断言时以 fake runner 为准。
[Agent-F 测试文档员] 2026-09-02 — P1 收尾完成,交接物 `poc/pi-fallback/P1-VALIDATION.md`(改动清单 / 真实验证数字 / 张力处置 / 未验证清单)。
- **文档同轮 ✅**:harness.md 权力矩阵追加 `agent.fallback.propose`(P1)行 + `/api/features` 条目补 `defaultOff` 语义 + 变更记录加 FB-01 行;新建 `docs/architecture/fallback.md`(含凭证语义已知限制节)并登记进 architecture/README.md 索引;CHANGELOG 新增 2026-09-02「FB-01 智能兜底 P1(只读)」(体例照 FF-01)。
- **设计张力处置(遗留 #2)✅ 最小方案**:只改 `pi_bridge._TASK_TEMPLATE`——撤销「引用必须标注 callId」(真实 pi 不可获知围墙外事后签发的凭证),改为「不得编造,出现不存在的编号即判伪造成果整轮失败」;`validate_report_citations` 硬失败不动,`test_forged_callid_rejected` 继续绿(伪造可识别性质保持)。不选 warning 降级(会破安全断言)。
- **全量验证 ✅ 真实数字**:全量黄金 4 批 **1084 passed / 1 failed**(唯一失败 = test_preference_features 日期炸弹,git 零 diff 核实与本轮无关,未顺手修);fallback+feature_flags **19 passed**;受影响切片 13 文件 **83 passed**;文档/端点门禁 **20 passed**(doc_drift 文档改动后复跑 5 passed);ruff `All checks passed!`。
- **仍未验证**:真实 pi 端到端冒烟(无 key 环境);其余遗留见 P1-VALIDATION §4。**P1 出口标准 7 项交付全部落地,建议本轮 GO**,等用户授权后再 commit。
[Agent-G 冒烟员] 2026-09-02 — 真实端到端冒烟完成,交接物 `poc/pi-fallback/P1-SMOKE.md`(七判据逐条 / 真实回复摘录 / 两轮 run 目录 / 失败根因)。**结论:原样代码 NO-GO,一行修复后 GO**。
- **抓到唯一产品 bug(fake runner 结构性盲区)**:`fallback_lane.py` `_GUARD_TS_TEMPLATE` 注释行 `{ block: true, reason }` 未转义 → `write_guard_extension` 的 str.format 必抛 `KeyError: ' block'`,真实 runner 100% 失败(显式归并 harness_error,用户侧回退话术正常)。修法=注释行花括号双写,一行。**未自行改产品代码**;诊断轮用进程内 shim 做等价单行修正后同口令全绿(真实 kimi-k2.6,stopReason=stop,steps=2,34.9s,citation valid,审计 SUCCESS 落租户世界哈希链),可预判修复即解锁。
- **环境坑(建议项)**:本机 PATH 的 `node` 优先命中 node.CMD 垫片 → 真实 runner 起不来(cmd 引号炸);`APS_FALLBACK_NODE` 指向真实 node.exe 即绕过,建议产品侧 Windows 优先解析 node.exe。
- 判据 1/2/5/6/7 PASS;3/4 原样 FAIL、单行修复后 PASS(证据:`smoke/results*.json`、`reply2.txt`、site2 run 目录)。现场隔离全程成立(server/data 零污染,git+mtime 双证)。
- 遗留:主线 LLM 404 降级路径是本次触发前提,主线正常时的意图落点未验证;建议为模板 format 补一条轻量断言防回归。
[Agent-H 修复员] 2026-09-02 — Bug A/B 修复 + 复证完成,**P1 最终 GO**。交接物:`P1-SMOKE.md` §7(修复后复证全记录,七判据全 PASS 真实数字)。
- **Bug A 修复**:`_GUARD_TS_TEMPLATE` 注释行 `{ block: true, reason }` 双写转义(1 行);全文核查该文件仅此一处 format 模板、无同类残留。爆炸半径 rg 盘点 LOW(write_guard_extension/build_pi_runner 调用方仅 fallback_lane 自身,poc 同名函数是独立副本)。
- **坑 B 产品化**:新增 `_resolve_node()`——`APS_FALLBACK_NODE` 最高优先级;默认 "node" 且 Windows 时 `which("node.exe")` 优先于 `which("node")`(避开 node.CMD 垫片)。复跑冒烟未设 `APS_FALLBACK_NODE` 即通(orchestrator.log 实证 `node_bin='node'` 自动命中真实 node.exe);解析顺序已写进 `docs/architecture/fallback.md` 配置小节。
- **防回归**:`test_write_guard_extension_real_template_format`(真实 format + 守卫文件含字面量 `{ block: true`),fake runner 盲区有网。
- **验证数字**:fallback+feature_flags **20 passed**(1.41s);ruff 两文件 `All checks passed!`;真实冒烟复跑 run **fb-20260902-075907-3af703**(真实 kimi-k2.6,stopReason=stop,steps=2,13.0s,calls 2 签 2 完,citation valid,审计 SUCCESS 落租户世界哈希链连续,端口释放零残留、server/data 零污染)。本轮租户世界首访空快照,Pi 如实报「0 订单 0 物料」不编造——真实产出力证。
- 未 commit/push(等授权)。遗留不变:主线 LLM 正常时的意图落点待验证(P1-SMOKE §6.3)。