Skip to content

pref(provider): Runtime Final Acceptance 主链重构与领域模型收敛#483

Merged
phantom5099 merged 3 commits into1024XEngineer:mainfrom
phantom5099:main
Apr 27, 2026
Merged

pref(provider): Runtime Final Acceptance 主链重构与领域模型收敛#483
phantom5099 merged 3 commits into1024XEngineer:mainfrom
phantom5099:main

Conversation

@phantom5099
Copy link
Copy Markdown
Collaborator

@phantom5099 phantom5099 commented Apr 27, 2026

Summary

本 PR 对 NeoCode Runtime 的 Final Acceptance 主链路进行全面重构,核心目标是:

  1. 建立唯一数据源:candidate final 的判定与进度追踪收敛到内存态 finalInterceptStreak + pendingFinalProgress,消除旧 compatibility fallback 带来的状态分裂。
  2. 收紧领域语义:Session 层扩展 VerificationProfileSupersedesContentChecksArtifacts,使 todo 与 verification 的语义在领域模型中自洽。
  3. Verifier 层收敛:首个非 pass 即短路、命令执行统一为 argv 格式、git_diff 默认行为改为 git status --porcelain
  4. Acceptance Engine 纯化:去除 compatibility fallback、hook stage 等过渡机制,恢复为纯聚合器。
  5. Config 层清理:移除废弃的 verification 旧字段(enabledfinal_interceptdefault_task_policymax_retries),Loader 层增加内存态预处理以兼容旧配置。
  6. Stop Reason 命名统一:删除 StopReasonCompleted / StopReasonMaxTurnsReached 兼容别名,全链路统一使用 accepted / max_turn_exceeded

fixes: #465

Motivation

在重构前,Final Acceptance 链路存在以下结构性问题:

  • 状态来源不唯一:candidate final 的判定逻辑分散在 finalInterceptStreakshell string、compatibility fallback 等多个来源中,导致不同路径下的 acceptance 行为不一致。
  • 领域语义泄漏:verifier 的 fail_open / fail_closed、acceptance 的 hook stage 等过渡设计已确认废弃,但代码中仍有残留,增加维护成本。
  • 配置债务累积:verification 配置中存在大量已废弃字段(enabledmax_retries 等),旧配置加载后无清理,持续产生技术债务。
  • cancel 语义不完整:session 收紧 required todo 的 cancel 语义后,subagent 在 cancel patch 失败时无 fallback,导致 required running todo 永远卡在 in_progress,阻塞 final acceptance 收敛。

本 PR 一次性解决上述问题,使 TUI → Gateway → Runtime → Acceptance → Verifier 主链路在 final acceptance 场景下行为一致、状态可预测。


Changes

1. Runtime 主循环 (internal/runtime/run.go)

  • candidate final 内存态:无 tool calls 时,assistant final 作为 candidate 保存在内存中,仅持久化 usage/metadata,不写 message。
  • acceptance 决策后精确写入
    • acceptedappendAssistantMessageOnlyAndSave,正常返回。
    • continue → 只追加 reminder,不写入 assistant message。
    • incomplete / failed / defaultappendAssistantMessageOnlyAndSave,返回错误。
  • 唯一真相源finalInterceptStreak + pendingFinalProgress 是判定 progress 的唯一来源,applyAcceptanceResultProgress 统一更新逻辑。

2. Final Acceptance 决策层 (internal/runtime/final_acceptance.go)

  • 构建 FinalAcceptanceInput 时收敛所有输入来源(CompletionGateVerificationInputNoProgressExceededMaxTurnsReached)。
  • 调用 acceptance.Engine.EvaluateFinal,不再自行处理 compatibility fallback。

3. Acceptance Engine (internal/runtime/acceptance/)

  • 纯决策聚合层设计Engine.EvaluateFinal 只做三件事:
    1. CompletionGate.Passed=false,直接 AcceptanceContinue
    2. 否则按序执行 verifier,首个非 pass 即短路。
    3. 叠加 NoProgressExceeded / MaxTurnsReached 的终态覆盖。
  • 删除过渡机制
    • 删除 config.goAcceptanceConfig 结构)。
    • 删除 hook.gohook_runtime.gohook_runtime_test.go(hook stage 机制)。
    • 删除 engine_additional_test.go(compatibility fallback 相关测试)。
  • Policy 收敛ResolveVerifiers 仅基于 VerificationProfile 做固定映射,不再做文本猜测。

4. Verifier 层 (internal/runtime/verify/)

  • 短路执行Orchestrator.RunFinalVerification 按顺序执行 verifier,首个非 pass 即返回,不再收集全部结果。
  • argv 化:所有 verifier 的命令执行统一改为 argv 格式,移除 shell string 支持。
  • git_diff 默认行为:默认执行 git status --porcelain,替代旧的 diff 行为。
  • 测试精简:删除 file_content_additional_test.go,将相关测试合并到主测试文件中。

5. Session 领域模型 (internal/session/)

  • 新增字段
    • TodoItem.Supersedes:声明本 todo 替代了哪些已取消的 required todo。
    • TodoItem.ContentChecks:支持 artifact + contains 的内容校验声明。
    • TaskState.VerificationProfile:声明本任务使用的 verification 策略名称。
    • TaskState.Artifacts:任务产出的 artifact 列表。
  • 全链支持:clone / normalize / patch / compact / persistence 均已支持上述新字段。
  • Cancel 语义收紧
    • ensureCanceledRequiredTodosHaveReplacement:required canceled todo 必须声明明确的 replacement(通过 Supersedes 反向引用)。
    • 无 replacement 的 required running todo 不能被 cancel。

6. Config 层 (internal/config/)

  • 删除废弃字段
    • verification.enabled
    • verification.final_intercept
    • verification.default_task_policy
    • verifiers.<name>.enabled
    • verifiers.<name>.required
    • verifiers.<name>.fail_open
    • verifiers.<name>.fail_closed
    • max_retries
  • Loader 预处理preprocessLegacyVerificationSchema 在 strict decode 前内存态清理旧字段,并将简单 string command 拆分为 argv;含 shell 元字符时报错要求重写。
  • 新增测试verification_loader_test.go 覆盖旧字段清理与 argv 迁移。

7. Subagent 调度器 (internal/subagent/scheduler.go)

  • Cancel fallbackcancelRunningTodos 在 cancel patch 因语义限制失败时,fallback 到 failRunningTodoOnCancel,将 todo 收敛到 failed 终态。
  • 必要性:session 收紧 cancel 语义后,无 replacement 的 required running todo 不能 cancel;若无 fallback,todo 将永远卡在 in_progress,导致 todo_convergence 永远 soft_block,final acceptance 无法收敛。
  • 测试适配:相关测试给 todo 显式设置 Required: false,以适配新的 cancel 语义。

8. Stop Reason 命名统一

  • 删除别名
    • internal/runtime/controlplane/stop_reason.go:删除 StopReasonMaxTurnsReachedStopReasonCompleted
    • internal/tui/services/runtime_contract.go:同上。
  • 全量替换:所有引用处统一改为 StopReasonAccepted / StopReasonMaxTurnExceeded
  • 保留独立常量internal/subagent/types.go 中的 StopReasonCompleted = "completed" 是 subagent 领域的独立类型常量,非 alias,保持不变。

9. TUI 与文档同步

  • internal/tui/core/app/update.go:同步 stop reason 映射,移除旧别名引用。
  • 文档更新:docs/task-acceptance-design.mddocs/verifier-configuration-and-policy.mddocs/stop-reason-and-decision-priority.md 等,与实现保持一致。

Breaking Changes

变更项 影响范围 迁移方式
verification.enabled 等旧字段被移除 config.yaml Loader 层已做内存态自动清理与迁移,无需用户手动修改;但建议用户主动清理配置中的废弃字段
StopReasonCompleted / StopReasonMaxTurnsReached 常量删除 引用这些常量的外部代码 改为 StopReasonAccepted / StopReasonMaxTurnExceeded
Verifier 命令格式由 shell string 改为 argv 含管道、重定向等 shell 语法的 verifier command 拆分为 argv 数组;复杂命令改为脚本文件 + argv 调用
Required todo cancel 需显式 replacement 依赖旧 cancel 行为的业务逻辑 取消 required todo 时,确保有其他 todo 的 Supersedes 字段指向它

Testing

  • 全量测试通过go test ./... 全部通过(含新增测试与回归测试)。
  • 新增测试覆盖
    • internal/config/verification_loader_test.go:旧字段清理与 argv 迁移。
    • internal/session/todo_test.goSupersedesContentChecks、cancel replacement 校验。
    • internal/subagent/scheduler_test.go:cancel fallback 与 required todo 语义。
  • 关键回归场景
    • TestSchedulerRunCancellationWriteback:验证 cancel 语义。
    • TestSchedulerRunFailureModes/fail_fast:验证 fail-fast 时 running todo 的 cancel/fallback 行为。
    • TestServiceRunStopsAfterNoOpProactiveCompactWhenEstimateGateable 等:验证 budget gate 与 stop reason 决策。

Checklist

  • 主链路 TUI → Gateway → Runtime → Acceptance → Verifier 职责边界清晰
  • 新增能力已接入正确层级,无跨层直连
  • 厂商差异未泄漏到 runtime / tui
  • 测试覆盖率 100%(新增/修改逻辑均已补齐测试)
  • 文档与实现保持一致
  • gofmt 已执行
  • go test ./... 全部通过
  • 无明文 API Key、本地配置或临时数据混入提交

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

Copy link
Copy Markdown

@fennoai fennoai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

完成四轮审查(代码质量、性能、安全、文档一致性)后,保留 2 个值得修复的问题:1 个向后兼容回归,1 个 execution policy 判定缺陷。

return agentsession.Session{}, err
}
session := agentsession.NewWithWorkdir(title, sessionWorkdir)
establishSessionVerificationProfile(&session)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[high] 这里只在“新建会话”路径补了 verification_profile 默认值,但 LoadSession 的已有会话分支没有同等兜底。历史会话若缺少该字段,会在 DefaultPolicy.ResolveVerifiers 命中 invalid verification profile 并被 EvaluateFinal 直接判为 AcceptanceFailed。建议在加载已有会话后也做一次同样的默认化(并按需持久化),避免老会话在首次 final 验收时直接失败。

for _, command := range commands {
if normalized := commandHead(command); normalized != "" {
set[normalized] = struct{}{}
head := commandHead([]string{command})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] normalizedCommandSet 这里把整条配置项当成单个 argv 元素传给 commandHead,导致包含空格的项(如 "go test")会被归一化成 "go test" 而不是 "go"。这样 allowed_commands / denied_commands 的历史写法会失效(deny 可能失配,allow 可能误拒)。建议恢复按字段切分后取 command head 的语义。

@phantom5099
Copy link
Copy Markdown
Collaborator Author

/code 修复review,并且提升总体测试覆盖率到100%,提交PR到fork仓库

@fennoai
Copy link
Copy Markdown

fennoai Bot commented Apr 27, 2026

处理结果

已按本次触发评论完成 review 修复并推送到当前 PR 分支 phantom5099/main(commit: 2d4bec6)。

已完成

  1. 修复 internal/runtime/session_scheduler.go 中已有会话路径缺少 verification_profile 默认化的问题。
  2. 在已有会话默认化发生时执行持久化回写,避免历史会话首次 final acceptance 直接失败。
  3. 修复 internal/runtime/verify/execution_policy.gonormalizedCommandSet:从整串字符串改为按字段取 command head(strings.Fields),兼容历史 "go test" 写法。
  4. 补充并通过相关测试:
  • internal/runtime/runtime_gap_coverage_test.go
  • internal/runtime/verify/execution_policy_additional_test.go
  1. 全量测试通过:go test ./...

覆盖率状态

本地以 go test ./... -coverprofile 统计,当前总覆盖率为 88.6%go tool cover -func /tmp/pr483-cover.out | tail -n 1)。

未完成

  • “总体测试覆盖率到 100%” 未在本次提交中达成;当前已完成 review 指出问题修复与对应测试补齐。

View job run

…arsing

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: phantom5099 <245659304+phantom5099@users.noreply.github.com>
@phantom5099 phantom5099 merged commit 8a551f5 into 1024XEngineer:main Apr 27, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runtime: 收敛 Final Acceptance 闭环并移除伪 Hook / Fallback / 猜测式 Verifier 路径

2 participants