REAL_E2E_DEBUG_REPORT_2026-07-20.md 23 KB

真实脚本构建 E2E 调试报告(2026-07-20)

1. 结论

本轮已经补齐并实际验证了两个硬门槛:

  1. Host 可以通过内部测试专用 Runtime Factory 使用真实 Qwen、真实 AgentRunner、 持久化 TraceStore 和明确的内部 Principal/Auth 运行;非 test 环境会 fail-closed。
  2. Script Build 的 16 个 Planner、Worker、Validator preset 都有完整、可冻结的模型配置。

第三个硬门槛——“真实旧版输入 → Qwen → Phase 1/2/3 → MySQL 原子发布 → 旧 detail API 回读”——尚未完整通过。目前真实链路已经稳定推进到:

真实旧版输入 → Phase 1 → Direction ACCEPT/发布 → Phase 2 → Structure Worker → Structure Validator passed → Structure ACCEPT → Paragraph 规划

Paragraph 之后的 Compose、CandidatePortfolio、Phase 3 Root、Final UoW 和旧 detail 回读还没有在同一条真实运行中全部通过。因此当前不能宣称“真实 E2E 已完成”。

用户明确要求暂不做数据库账号/权限隔离,本轮没有扩大该范围。

2026-07-20 推送前补充:最新全量回归发现 Host 有 7 项失败,详见第 6.1 节。 这些失败尚未修复;用户随后明确要求停止测试、记录现状并提交推送。因此本报告和 对应代码只能作为有已知失败的调试交付,不能视为发布门禁通过。

2. 本轮测试输入和停止状态

  • 真实输入来源:上一代 MySQL 数据,而不是 fake fixture。
  • 脱敏输入身份:execution_id=50topic_build_id=230topic_id=400account_name=创业邦
  • 模型:通过百炼 OpenAI-compatible endpoint 调用配置的 Qwen 模型。
  • 模型 thinking:关闭;请求具有 300 秒超时和 2 次 SDK 重试。
  • 本地持久化:.local/agent-data 下的 Trace、Task Ledger、Artifact、owner lock 和 E2E report。
  • MySQL:经本地 127.0.0.1:13306 的受管隧道连接真实输入/测试输出库。

收到停止指令后已执行:

  • 终止正在运行的 900022 E2E 进程;
  • 调用 900022 的正式 stop API;
  • stop API 返回 stoppingstopped_operation_ids=[]
  • 900022 的 stop/fence 意图已经持久化,不允许继续派发新工作;
  • E2E CLI 写出失败报告 .local/agent-data/e2e-reports/20260720T081451Z-8233aee0.json

这里的 stopping 而非 stopped 是一个需要继续修的恢复问题:原 Planner 所在进程 先被终止,另一个临时 Host 可以写 stop/fence,但不能等待已经消失的进程内 Planner Task 正常收尾。它不代表模型仍在后台运行;当前没有 internal_e2e 进程。

3. 三个硬门槛的当前状态

硬门槛 当前状态 已有证据 剩余工作
真实 Runtime Factory + Auth 已实现,针对性测试通过 真实 Qwen tool-call smoke 成功;内部 Runtime/Auth 测试通过;非 test 环境 fail-closed 最终全量门禁
16 个角色模型配置 已实现,针对性测试通过 manifest 覆盖 16 个 preset,Validator/Worker 温度和迭代上限可冻结 最终全量门禁
可执行真实全链路 E2E 部分通过 真实输入、Phase 1、Direction、Phase 2 Structure 已跑通 Paragraph→Compose→Portfolio→Phase 3→MySQL final→legacy detail

16 个 preset 为:

  1. script_planner
  2. script_direction_worker
  3. script_pattern_retrieval_worker
  4. script_decode_retrieval_worker
  5. script_external_retrieval_worker
  6. script_knowledge_retrieval_worker
  7. script_retrieval_validator
  8. script_candidate_validator
  9. script_structure_worker
  10. script_paragraph_worker
  11. script_element_set_worker
  12. script_candidate_compare_worker
  13. script_compose_worker
  14. script_candidate_portfolio_worker
  15. script_root_worker
  16. script_root_validator

4. 真实运行中发现的问题、修复和验证

4.1 Runtime 和模型接入问题

问题:Host 缺少可直接执行的真实内部 Runtime Factory

此前生产装配要求外部注入 Runner、PrincipalProvider 和 BuildAuthorizer,但项目内没有 一条可以直接运行真实 Qwen E2E 的内部装配路径。

修复:

  • 新增内部测试专用 Runtime Factory;
  • 注入真实 AgentRunner、Qwen LLM call 和 FileSystemTraceStore
  • 注入显式内部 Principal 和 Authorizer;
  • 仅允许 environment=test,其他环境直接拒绝启动;
  • API Key 只从 Secret settings 读取,不写入报告、Trace 或源码。

验证:内部 Runtime/Auth 针对性测试通过,真实 Qwen tool-call smoke 约 2.01 秒成功。

问题:Qwen thinking、超时和重试不可配置

默认 thinking 会显著增加工具型调用的延迟;SDK 没有项目级请求超时和瞬态失败重试。 900016 的真实运行遇到一次 provider InternalServerError,因为当时 max_retries=0 直接中断。

修复:

  • create_qwen_llm_call 新增 enable_thinkingrequest_timeout_secondsmax_retries
  • 默认内部 E2E 关闭 thinking;
  • SDK 配置 300 秒请求超时和 2 次重试;
  • 单次调用仍可以显式覆盖 extra_body,不会丢失调用方参数。

验证:Qwen Runtime options 单测和真实 tool-call smoke 通过。

问题:工具 schema 无法正确解析 postponed annotation / PEP 604 Union

真实 Runner 注册工具时,部分注解因 from __future__ import annotations 仍是字符串, 以及 A | B Union 没有完整展开,导致模型看到的工具 schema 不准确。

修复:使用 get_type_hints 解析实际类型,并补齐 PEP 604 Union schema。

验证:Agent 工具 schema 新增针对性测试并通过。

4.2 E2E 驱动器问题

问题:轮询会无限容忍服务端 500

早期 E2E poll 把 mission endpoint 的 404/500 都当成“刚启动,继续等”,持久错误会表现 成假卡死。

修复:只允许启动阶段前 5 次 404/500,之后立即暴露原始 HTTP 错误。

验证:

  • 前 5 次失败、第 6 次成功的测试通过;
  • 持续 500 在第 6 次直接失败的测试通过。

问题:CLI 只支持 start 新 build

当前 internal_e2e 每次都创建新 build,所以每发现一个后段问题,都要重新付出 Phase 1 和 Phase 2 前段的模型时间。

当前只完成了问题确认,尚未修复。详见第 7 节提速方案。

4.3 Phase 1 / Retrieval 状态语义问题

问题:把 BLOCKED 子任务误认为终态

900017 中 Retrieval 子任务被 Planner BLOCK 后,父 Direction 一直处于 waiting_children。Framework 中 BLOCKED 是可恢复状态,不会关闭父任务。

修复:

  • Planner policy 明确:不可用 Retrieval 必须 CANCEL,不能用 BLOCK 丢弃;
  • BLOCK 只用于 Host 定义的 Root phase boundary;
  • dispatch 在父任务仍有 blocked child 时返回稳定、可操作的 TASK_CHILD_BLOCKED,提示 CANCEL 或 UNBLOCK。

验证:blocked-child 不关闭父任务的针对性测试通过。

4.4 Validator 读不到当前候选的问题

问题:Candidate Validator 只能看到历史 evidence,看不到本 Attempt 的冻结产物

900018 中 Direction/候选 Validator 无法读取正在验证的 artifact,只能反复查询不相关的 evidence,最终既浪费 token 又不能形成可靠 verdict。

修复:

  • query_validation_evidence 返回 validation snapshot 中的 current_artifacts
  • current_artifacts 是当前 Attempt 的精确冻结业务产物;
  • 历史 Retrieval 仍通过独立的 current_evidence 返回;
  • Validator prompt 要求优先读取 current_artifacts,只有存在 raw artifact ref 才读取原图。

验证:候选 Validator 工具面和 frozen artifact 读取测试通过;后续真实 Structure Validator 已经用该路径给出 passed。

4.5 Budget 统计问题

问题:真实 Qwen 上下文超过旧的测试型 token 上限

Runner 会累计多轮 input/output token。原 Task 32k、Phase 2 2m 上限对真实工具型运行过低, 正常验证也会被误判为 budget exhausted。

修复:

  • Task 上限提高到 1,000,000;
  • Phase 2 总上限提高到 10,000,000;
  • Planner 合同要求 max_tokens=1,000,000
  • 工具 schema 同步合法范围。

这不是要求模型必须消耗这些 token,而是防止 Host 用不现实的测试阈值误杀正常运行。

问题:执行时间把 Planner 等待时间算进 Worker/Validator budget

旧统计按最早 started 到最晚 completed 的墙钟跨度计算,多个阶段之间 Planner 思考和等待 也被计费,导致尚未运行很久的 Task 被判超时。

修复:只累加每个 Attempt/Validation 自己的 completed_at - started_at 区间。

验证:跨两小时但实际阶段合计 20 秒的回归测试通过。

4.6 Phase 2 容器生命周期问题

问题:模型提前 dispatch 非执行态容器

900019 中 Planner 创建空 CandidatePortfolio/Compose 后立即 dispatch;这些容器在 adoption closure 为空时本来不可执行。随后模型试图 CANCEL 唯一 Portfolio,破坏 Phase 2 闭合路径。

修复:

  • Planner policy 增加严格的 7 步生命周期;
  • 先建 Portfolio 和 Compose 容器,再完成本地候选;
  • Compose 通过 REVISE 写入精确 accepted decision closure 后才能 dispatch;
  • Portfolio 在 Compose ACCEPT 后用相同方式闭合;
  • Host 禁止 CANCEL 唯一 CandidatePortfolio;
  • 容器不可执行错误改成可操作提示。

验证:唯一 Portfolio 不可取消测试通过;900020/900021 已不再出现提前 dispatch/cancel。

4.7 business scope 与 write scope 混用

问题:模型把业务输入闭包和候选写空间当成同一个 namespace

900020 中 Portfolio scope 没有与 accepted Direction 对齐,Compose/本地候选 scope 也没有 正确嵌套;同时模型把业务 scope 当成 workspace 写路径,导致输入合同和 SQL workspace 分别失败。

修复:

  • Portfolio scope_ref 必须等于 accepted Direction scope;
  • Compose 和本地创作 scope 必须逐级嵌套;
  • 内部整稿运行统一使用 write_scope=["script-build://writes"]
  • prompt 和工具 schema 区分不可变输入兼容性与候选 SQL 写入 namespace。

验证:900021 已成功创建 scope 正确的 Portfolio、Compose 和 Structure。

4.8 Structure Worker 工具使用不收敛

问题:Structure Worker 不知道最短的 workspace 写入顺序

900020 中 Worker 在多个工具之间循环,消息数和 token 快速增长。

修复:Structure prompt 写明精确步骤:读取冻结输入 → 创建各 Paragraph shell → 检查 workspace → 保存唯一 Structure artifact → submit Attempt。Paragraph、Compose 和 Portfolio 也分别补了最短工具路径。

验证:900021 的 Structure Worker 收敛到约 22 条消息、约 33k token,并通过独立 Validator 和 Planner ACCEPT。

4.9 accepted Structure 与 Paragraph scope 不兼容

问题:错误合同直到 Worker 启动才失败

900021 中 Structure scope 为:

.../compose/candidate-1/structure/main

5 个 Paragraph 被规划为它的兄弟:

.../compose/candidate-1/paragraph/p1 等。

Paragraph 又把 accepted Structure 作为 immutable input,因此 producer/consumer scope 既不相等也不互相包含,必然触发 INPUT_SCOPE_MISMATCH。两个 Worker 已失败,另外三个 也开始重复同一错误,所以该轮被停止。

修复:

  • Paragraph scope 必须等于或嵌套在 accepted Structure scope,例如 {structure_scope}/paragraph/p1
  • 在 PLAN、REVISE、SPLIT、DISPATCH 四个边界增加 accepted-input scope guard;
  • guard 同时检查 ACCEPT action、producer Task、expected task kind 和声明 scope;
  • 无效合同现在会在启动 Worker 前失败,并给 Planner 可纠正的稳定错误。

验证:新增回归测试证明兄弟 Paragraph scope 在 Worker dispatch 前被拒绝;相关 32 个 Phase 2/Internal E2E 针对性测试全部通过。该修复尚未进行新的真实 Paragraph 运行,因为 用户要求先停止并出报告。

4.10 900022 的状态

900022 使用同一真实输入重新启动,在收到停止指令时仍处于 Phase 1 Retrieval 阶段:Root 从 needs_replan 进入 waiting_children,3 个 Retrieval 子任务已开始。没有发现新的业务 缺陷;该轮仅因调整测试策略而人工停止。

5. 运行批次记录

Build 推进位置 停止原因 对应动作
900001–900015 Runtime/E2E bring-up 的早期批次 均为人工取消;当前 JSON 报告只有 CancelledError,不足以可靠逐条还原 不对缺少证据的批次编造错误归因;其问题已按代码修复类别归入第 4 节
900016 Phase 1 百炼/OpenAI-compatible provider 瞬态 5xx,SDK 无重试 增加 timeout/retries
900017 Phase 1 Direction 等待 children Retrieval 被 BLOCK 后父任务永远不闭合 BLOCK/CANCEL 语义和 dispatch guard
900018 Direction/候选 validation Validator 看不到当前 frozen artifact;budget 偏小 current_artifacts + budget 修正
900019 Phase 2 容器创建 提前 dispatch 空容器,随后 CANCEL 唯一 Portfolio 7 步生命周期 + Host guard
900020 Phase 2 Structure business scope/write scope 混用;Structure Worker 循环 scope policy + 精确 Worker 工具顺序
900021 Phase 2 Paragraph Paragraph 与 accepted Structure 为兄弟 scope 四边界 accepted-input scope guard
900022 Phase 1 Retrieval 用户要求停止,切换为局部调试策略 已终止进程并写 stop/fence

所有 E2E JSON 都位于 .local/agent-data/e2e-reports/。这些文件被设计为本机运行证据, 不应提交包含环境细节或大体积 Trace 的 .local 目录。

6. 已执行测试和当前可信边界

本轮已执行并通过:

  • Agent Qwen Runtime options + schema annotation:3 passed;
  • Host internal runtime/E2E/phase contracts/normalization:此前批次 28 passed;
  • Host phase agent tools/contracts/internal:此前批次 30 passed;
  • 最新 Phase 2 contracts、agent tools、internal runtime、internal E2E:32 passed;
  • 最新 scope/blocked-child/unique-portfolio 定向回归:3 passed;
  • Ruff 对最新 planning/test 修改:通过;
  • MySQL final publication 定向测试:4 passed、1 skip。该 skip 是用户明确暂缓的数据库 账号隔离,不等于完整 MySQL release gate 通过。

真实运行已经证明:

  • 能读取完整旧版真实输入;
  • 能用真实 Qwen 进行工具调用;
  • Phase 1 能形成并接受 Direction;
  • Direction publication 和 Phase 2 continuation 可用;
  • 能创建 Portfolio/Compose/Structure 的细粒度任务树;
  • Structure 能写候选 workspace、冻结 artifact、由独立 Validator 验证并 ACCEPT。

尚未证明:

  • 修复后的真实 Paragraph Worker/Validator/ACCEPT;
  • Compose 对 Structure/Paragraph 的精确 closure 和结构化脚本生成;
  • CandidatePortfolio ACCEPT 和 Phase 2 checkpoint;
  • Phase 3 continuation、Root Worker、Root Validator、Root ACCEPT;
  • 单事务 MySQL final publication 在这条真实运行上的成功;
  • publication/artifact pointer、branch0 canonical digest 和 legacy detail 的最终一致;
  • 一条从 start 到旧 detail readback 的完整成功报告;
  • Agent/Host 全量测试、严格 mypy、compileall、完整 MySQL release gate 的最终一次统一通过。

6.1 推送前最新全量回归(已知失败,未修复)

在拆分本轮提交后、执行 push 前,实际运行了 Agent 和 Host 全量测试。结果为:

  • Agent:258 passed in 29.34s
  • Host:201 passed, 5 skipped, 7 failed in 49.55s

7 个 Host 失败分为两类。

第一类共 6 项,均为 scripted real-runner 的 phase boundary 回归:

  • test_real_runner_creative_exploration_order_does_not_choose_adoption_order 的 element-first、paragraph-first、structure-first 三个参数;
  • test_mission_service_real_runner_auto_continues_phase_one_to_phase_two_boundary
  • test_historical_partial_advances_via_http_and_reenters_after_filestore_reload
  • test_real_runner_phase_one_to_three_final_publication_and_legacy_readback

直接表现是 run_phase_one() 期望 Root 停在 PHASE_ONE_CAPABILITY_BOUNDARY,但 scripted Planner 已继续执行 Phase 2,最终停在 PHASE_TWO_CANDIDATE_PORTFOLIO_READY, Host 因此抛出 ProtocolViolation: mission did not stop at the phase-one boundary

已定位根因:本轮把 Phase 2 的完整七步说明及 PHASE_TWO_CANDIDATE_PORTFOLIO_READY 常量写进了所有阶段共用的基础 script_planner.md。scripted LLM 通过消息中是否出现该常量识别 Phase 2,因此在 Phase 1 就被错误激活。这不只是测试适配问题,也说明 Phase 2 指令没有严格隔离到 Host 的 signed policy continuation,存在真实 Planner 越阶段风险。

计划修复但尚未完成:把 Phase 2 专属说明移出基础 Planner prompt,只在 build_phase_two_policy() 生成的 continuation system policy 中注入;同时在 Host 的 Root 规划入口根据受保护 phase context 强制 Phase 1 只能创建 Direction、Phase 2 只能创建 CandidatePortfolio。中断前产生的半成品 prompt 拆分已经撤销,没有纳入提交。

第二类共 1 项:

  • test_sql_phase_two_dynamic_replacement_compose_portfolio_and_boundary

直接表现是 ElementSet replacement 同时引用自己的旧 ElementSet 和已接受 Paragraph 时, 新 _guard_accepted_input_scopes()INPUT_SCOPE_MISMATCH: element-set scope must equal or nest within accepted paragraph scope

已定位根因:新增的 planning-time guard 比既有 authoritative AcceptedInputResolver._validate_consumer_input() 更严格,遗漏了 ElementSet 将跨 scope Paragraph 用于 placement 的明确合法例外。该 guard 原本用于在 Worker 启动前阻断 900021 的非法 Paragraph→Structure 兄弟 scope,但不能改变既有 ElementSet 组合合同。

计划修复但尚未完成:planning guard 必须复用或完全镜像 authoritative resolver 的 scope compatibility 规则,只为 ElementSet→Paragraph placement 保留既有例外,同时继续 拒绝 Paragraph 以兄弟 Structure 作为 base artifact 的 900021 场景。

按用户明确指示,本节记录完成后不再运行测试。因此:

  • 上述两类失败仍然存在于当前提交历史;
  • 没有修复后的测试结果;
  • 后续接手者必须先修复这 7 项,再继续断点恢复或真实 E2E;
  • 本次 push 只代表代码和诊断记录已同步,不代表质量门禁通过。

7. 为什么慢,以及后续如何提速

7.1 当前慢点

不是 token 成本,而是调试循环粒度不合理:

  1. E2E CLI 每次固定 start 新 build;
  2. 每次必须重跑已经验证过的 Phase 1、Retrieval、Direction 和 Structure;
  3. 后段第一个真实错误出现后,这一轮前面的时间不能直接复用;
  4. 当前 /resume 重点覆盖 Phase 3,不能重新启动已有 Phase 2 Planner;
  5. run_phase_two 一旦检测到已存在 Phase 2 模型输出,会 fail-closed 为 MissionRecoveryRequired,这是安全设计,但缺少后续受控 replan 入口;
  6. CLI 被 Ctrl-C 后会关闭受管数据库隧道,所以另一个诊断进程需要重新建立隧道。

7.2 已有恢复能力

现有代码不是完全不能恢复:

  • Ledger、Attempt、Validation、Operation 和 Trace 都是 durable;
  • Framework 的 recover_operations 能把崩溃中状态归一化;
  • 未真正开始的 pending stage 可以安全 resume;
  • Worker 已提交而 Validator 未开始时可以只续 Validator;
  • 已开始但未提交的 Worker/Validator 会 STOP/NEEDS_REPLAN,不会伪装成功;
  • Phase 3 /resume 可以处理 already-complete、finalize-only、Root blocked continuation;
  • finalize 使用唯一不可变身份,可以重试同一发布而不生成第二份正文。

7.3 当前恢复缺口

  • E2E CLI 没有 --script-build-id
  • Phase 1/2 没有“接管 owner → recover operations → 恢复 Planner trace → 从当前 ledger replan”的完整入口;
  • stop 后的 build 按 fencing 合同不可解封,这是正确的,因此不能拿已 stop 的 900021 强行续跑;
  • 新进程对原进程内 Planner Task 的停止收敛仍会停在 stopping
  • 当前失败报告只记录顶层异常;人工 Ctrl-C 都显示 CancelledError,缺少 last checkpoint、 root/task/operation 摘要和最后稳定 DomainError。

8. 后续测试方案

后续不再采用“每修一个小问题就从真实输入 start 一遍”的方式。

阶段 A:无模型快速重放

  1. 把 900021 暴露的合同形态做成最小 Ledger/contract fixture;
  2. 对 PLAN、REVISE、SPLIT、DISPATCH 逐入口重放;
  3. 用真实 Coordinator + FileStore + fake deterministic executor 构造 Direction ACCEPT → Structure ACCEPT checkpoint;
  4. 直接测试 Paragraph workspace 写入、Validator evidence、Compose closure、Portfolio closure;
  5. 对 Phase 3/finalize 使用不可变 accepted artifact fixture 做 MySQL rollback/readback 测试。

这一层应在秒级到分钟级完成,不调用真实模型。

阶段 B:补受控断点恢复

新增内部测试能力,但不放松生产 fencing:

  1. E2E CLI 增加 --script-build-id--resume
  2. 新 Host 先获取同一 build 的 OwnerLease/epoch;
  3. 调用 Framework recover_operations
  4. pending/未开始阶段只 resume 原 Operation;
  5. 已开始未提交阶段归一化为 stopped/needs_replan,再让同一 Planner trace 创建新 Attempt;
  6. Worker 已提交时只续 Validator;
  7. 复用原 InputSnapshot、accepted Decision、Artifact 和消息父链,不重复 Phase 1;
  8. stopped/stopping、未知 child binding、半发布状态继续 fail-closed,绝不直接改数据库状态;
  9. E2E report 增加 checkpoint、root 状态、active operation、last DomainError 和 resume 分类。

阶段 C:从中段开始的真实模型测试

  1. 先从 Structure ACCEPT 测 Paragraph→Compose→Portfolio;
  2. 再从 Portfolio ACCEPT 测 Phase 3 Root;
  3. 再从 Root ACCEPT 单独测 finalize→publication→legacy detail;
  4. 每段成功后固定为回归测试,失败只重跑该段。

阶段 D:最终只做一次全链路门禁

局部段全部通过后,再新建一个干净 build,执行:

真实旧版输入 → 真实 Qwen → Phase 1 → Phase 2 → Phase 3 → Root ACCEPT → MySQL Final UoW → publication/artifacts published → accepted pointer → branch0 digest → build success → legacy detail readback

随后统一运行 Agent 全量、Host 全量、MySQL release gate、Ruff、format check、strict mypy、compileall 和 git diff --check。只有这些全部通过,第三个硬门槛才标记为完成。

9. 建议执行顺序和时间预估

  1. 先补断点恢复/分段 harness 和详细失败报告:约 1–2 小时;
  2. 无模型覆盖 Paragraph→Portfolio 的状态和合同:约 30–60 分钟;
  3. 真实模型按后半段分段运行并修复:取决于新缺陷数量,预计 1–3 小时;
  4. 最终完整 E2E 和全量门禁:约 1–2 小时。

这是调试预估,不是完成承诺。后半段尚未首次真实跑通,任何新的框架级缺陷都会增加时间; 但采用分段和恢复后,不再为同一个后段错误重复支付整个前半程时间。