Skip to content

Preserve continuation baseline and draft lineage when restarting cancelled delivery attempts #2377

Open

Description

@zy95-12

Written-by: Codex

目标分支与负责人

用户报告

OpenToday 清理 unreachable 时,取消旧 Attempt、重启服务,再调用 task.run。后续执行在工作树复用/分配阶段被拒,原因是“保留了未封存草稿,但期望基线已变化”。

用户本想继续原工作,后来需通过 input.publish 说明沿用 seedSha=05e4736 / PR #3,并向 Chief 补充草稿路径、基线 SHA、purpose=integrate 才纠偏。

05e4736 / PR #3 是现场线索,不是本次已核验的授权来源或完整候选证明;该次 Task/Attempt/草稿/仓库/退出时间线仍待现场快照确认。故障可能在 task.run 返回后异步角色准入时显现,不应未经核实统称 task.run 请求本身同步拒绝。

已核对的代码事实与根因

只读核对交付代码 8e47767(PR #2362 已合入交付分支):

  1. attempt.stop 设置 cancelRequested,语义为取消,不是暂停后继续原 Attempt;未清理的旧工作树/草稿可能按设计保留。
  2. 新 task.run 创建 Attempt 时,仅在取得 publicationBinding 的分支中继承 previous 的 seed/base。没有正式 PR 绑定时,原 seed/base 不在该路径中自动延续,新 Attempt 会按固定仓当前 HEAD 选择基线;原输入来源也不能据此假定已继承。
  3. allocate 按 Task-role 身份寻找可复用工作树,验证旧执行退出、旧 checkpoint 与实际 HEAD/dirty 状态。
  4. 若保留未封存草稿,而新 Attempt 的 expectedCheckout 与旧工作树 HEAD 不同,抛出 bot/workspace-baseline,要求保留草稿并显式准入新基线。该保护避免 reset/clean 覆盖工作,是正确门禁。
  5. 现有 reworkPool 已有部分 seed/输入来源继承与未封候选恢复能力,但取消后重新 task.run 并不等于走了相同恢复契约。
  6. 基线冲突抛出时已有 recovery、workspaceId、expectedCheckout、actualCheckout 等结构化 details;pool 准入失败主要保存字符串,对 bot/context-resume 才另存专门分类。基线门禁发生在新 workspace 记录建立之前,新 Attempt 的 recoveryFacts snapshot/materialization 可能为空,Chief 不一定得到关联旧草稿的完整事实。

缺口是:取消/重启/重新准入之间没有完整保留并表达续作意图与草稿血缘。本想续作,却按新基线启动,同时仍尝试复用旧草稿。 不能以删除基线检查、硬 reset/clean 或盲目指定 seed 来修复。

现有测试已覆盖“脏草稿+新基线应拒绝”和“显式准入新基线后保留草稿”,但本次未运行这些文件型测试、未重放现场完整链路;实施需补“取消旧 Attempt→固定仓前进→task.run→复用旧草稿”的红/绿复现,而不能把已有门禁测试当作新缺口已修复。

实现范围

1. 明确续作与重新开发的契约

  • 区分继续已有工作、基于新基线重新开发、保留草稿并集成新来源;通过现有恢复/准入机制或明确的接口参数表达,不能要求模型从错误字符串猜测。
  • attempt.stop 保持取消语义,已取消 Attempt 不被静默复活。继续交付可创建符合当前契约的 successor Attempt,保留 Task、旧 Attempt、草稿和逻辑 Task-role Session 血缘。
  • 对存在草稿/历史候选的 task.run,在选择基线前判断并返回可用续作事实;不得无提示地把继续原工作的意图变成固定仓最新 HEAD。
  • 不能把所有新 task.run 都强制钉在旧 seed:真正要求新基线时仍允许显式选择,保留当前权限、来源与工作区保护。

2. 持久化并重新核验恢复血缘

  • successor Attempt 记录原 Attempt/Task-role/工作区、原 base/seed/候选、当前实际 HEAD、保留草稿状态、已准入输入及其来源、既有 PR 关联(如有)和恢复决策来源。
  • 恢复时重新核验 Project/Task/仓库/资源绑定、当前权限、requirements revision、角色定义、claim/generation 与旧执行可信退出;旧授权、旧 ref/SHA 或旧配置不能自动当作仍有效。
  • 继承此前合法输入时保留可追溯准入证据,并重新验证其当前适用性;不能只复制数组或把 input.publish 文本当作来源授权。
  • 复用旧草稿时,核验旧 checkout/checkpoint 及 workspace 的 HEAD/index/status 指纹;原样保留未提交文件、未跟踪文件和未完成合并信息,不用 reset/clean 掩盖冲突。
  • 沿用已验证 seed 继续时,expectedCheckout 与保留工作树保持一致;选择新基线时,通过显式的 integrate 来源准入保留草稿后集成。purpose=inspect 不得充当必需集成或候选父提交。
  • 正式 PR/候选认领由 Use role-bound GitHub App identities for SDK development, reviews and delivery reconciliation #2365 的核验回写契约承接;不得凭 PR 号、短 SHA、MERGEABLE 或模型声明填入 publicationBinding/candidateSha。
  • 不迁移旧测试/Review 为新基线的有效证据。候选产生/变化后重新按精确 SHA 验证。

3. 让 Chief 获得后端已知的恢复事实

  • 将 bot/workspace-baseline 作为持久、结构化的恢复问题暴露,保留错误 kind、关联旧/新 Attempt、旧工作区引用、实际/期望 checkout、草稿存在性及可采取的恢复条件。
  • 即使新工作区还未分配,也能通过已注册的旧工作区和准确血缘提供恢复上下文;不能仅因当前 Attempt.workspaces 为空就丢失后端已知草稿事实。
  • 在授权范围内提供当前可用的批准来源/ref/完整 SHA 与 inspect/integrate 语义,避免反复询问后端已经掌握的草稿路径和基线。
  • Chief 基于事实自主选择合法恢复方案,不能框架固定改派 Developer/转人工或自动决定集成哪个来源。
  • 确实缺少权限、来源含义或业务取舍时,由 Chief 发起聚焦咨询;不能凭“自主推进”猜测用户期望的基线。
  • input.publish 只增加待处理输入;实际来源准入、续作选择与 PR 回写必须分别留下正式回执。
  • 错误区分基线冲突、草稿被改动、来源过期、退出未知、claim 未退场和权限变化;与 Reconcile proven execution exit with durable claim retirement before integration admission #2375/明确重启恢复窗口与 Chief inspect 失败分类,打通中断 Attempt 的安全恢复路由 #2347 复用状态/恢复机制,不新增第二个控制器。

4. 幂等与并发保护

  • 在当前 generation/workspace snapshot 下提交恢复意图,再进行分配/复用;保存失败、重启、重复 task.run/恢复请求、同时更新固定仓或输入时,不重复创建 Attempt/分支、覆盖草稿或改变既定来源。
  • 未知外部写入先对账;旧 SDK/旧 claim 的迟到结果不能修改后继候选或恢复已失效授权。
  • 无法安全续作时保留明确可恢复状态、旧草稿与完整原因,不以重启或手改 state JSON 作为正常修复流程。

验收与测试

  • 最小红/绿用例覆盖:取消旧 Attempt,保留未封草稿,固定仓推进,重启后 task.run;准确识别续作/新基线选择,不误把草稿冲突当普通开发失败。
  • 没有 publicationBinding 但存在合法旧 seed/草稿血缘时,受权续作仍能创建/恢复后继执行;不要求先伪造 PR 绑定才能保留 seed。
  • 沿旧 seed 续作保留原文件与上下文;显式新基线 integrate 保留草稿并进行实际集成;inspect-only 不被误用。
  • 已取消 Attempt 不被复活;原生/SDK 逻辑 Task-role Session 按 修复 Task-role 执行绑定含易变 cwd 导致跨 Attempt 无法 resume 的死锁 #2346 约定续接,旧 Attempt/claim/日志与最终记录保留。
  • 无效退出证明、active claim 未退场、草稿 HEAD/index/status 变化、移动 ref、过期 generation、权限撤销及跨仓库输入继续被门禁拒绝。
  • 基线冲突在尚未创建新 workspace 时仍保留旧工作区与实际/期望基线信息;Chief 可通过受权上下文完成决策,不重复询问已知事实。
  • input.publish 中的 PR/短 SHA/建议不自动成为正式 candidate、integration admission 或 publicationBinding;与 Use role-bound GitHub App identities for SDK development, reviews and delivery reconciliation #2365/Reconcile proven execution exit with durable claim retirement before integration admission #2375 的接口语义一致。
  • 重复请求、保存失败、宿主重启、固定仓并发推进、SDK 迟到结果和来源变化不丢草稿、不重复派工、不继承过期测试/Review。
  • 本地与 Docker 隔离链路验证“取消/中断→后继准入→保留草稿→选择/集成基线→继续执行”;分别记录 fixture、真实 SDK 与现场证据,不能借用历史测试结论。
  • 更新长期记忆、Attempt/Task-role/工作区基线与恢复架构、运维及 API/OpenAPI,明确 stop、续作、输入建议、集成来源与 PR 绑定的区别。

范围边界

本次只授权落 Issue,不修改主会话代码、现场任务或服务。保留草稿/基线/退出/权限门禁;不清空 bindings、不丢弃草稿、不复活已取消 Attempt、不自动关闭或合入现场 PR、不扩大权限或改动 control-plane。现场 05e4736 / PR #3 的具体合法恢复路径须结合完整状态再确认。

Activity

  1. self-assigned this
    on Nov 4, 2026
  2. Birfy commented on Nov 4, 2026

    @Birfy
    Collaborator

    Written-by: Triage

    挂起(H 类),不转 agent-ready。卡在判据 ③(另一条交付线),另带一条 ①。

    卡在哪条

    缺什么

    1. owner 的 go-ahead:这条交付线的问题要不要本仓 main 接手、先切哪一片;
    2. 现场证据(Task/Attempt/workspace 快照)把「取消 → 重启 → task.run 拒绝」确认为可复现,才能谈红先。

    谁能给

    owner(经 Chief);现场快照由报告方 @zy95-12 提供。

  3. added
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:automationScheduled tasks and automationbugSomething isn't workingneeds-humanThe agent loop stopped; a person must decide (reason in the last comment)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions