Skip to content

feat(todo): Todo Schema v7重构与运行时洞察UI全链路接入#558

Merged
pionxe merged 30 commits into1024XEngineer:mainfrom
Yumiue:html_gui_build
May 6, 2026
Merged

feat(todo): Todo Schema v7重构与运行时洞察UI全链路接入#558
pionxe merged 30 commits into1024XEngineer:mainfrom
Yumiue:html_gui_build

Conversation

@Yumiue
Copy link
Copy Markdown
Collaborator

@Yumiue Yumiue commented May 5, 2026

概述

本PR完成了Todo Schema v7重构,并实现了运行时洞察UI的全链路接入,同时增强了Gateway协议与前端预算面板的上下文传递能力。

主要变更

1. Todo Schema v7重构

  • blocked_reason 不变量:强化blocked状态的不变性约束
  • 空plan三层守卫:为空plan场景添加三层防御机制
  • Todo链路增强:修复隐患问题,优化状态管理
  • 文档更新:新增 docs/todo-schema-migration.md 迁移指南

2. 运行时洞察UI全链路接入

  • Insight面板:运行时洞察UI组件完整实现
  • Checkpoint接入:支持会话快照恢复,保留验证能力
  • 事件桥接eventBridge.ts 完整实现运行时事件到UI的映射
  • TodoStrip组件:实时任务状态展示(334行新增)
  • Acceptance/Verification消息:新增接受与验证消息组件

3. 文件变更面板增强

  • Patch解析器patchParser.ts 支持Git patch格式解析
  • 文件变更展示FileChangePanel.tsx 实时查看代码修改
  • Checkpoint标记:消息内联显示checkpoint快照点

4. Gateway协议扩展

  • JSON-RPC增强jsonrpc.go 新增135行协议支持
  • 安全增强:更新安全验证逻辑
  • Bootstrap增强:Gateway启动流程优化

5. 预算面板上下文传递

  • context_window全链路:模型上下文窗口值从runtime传递到前端
  • BudgetIndicator组件:新增预算指示器(183行)
  • Facts收集器:增强运行时事实收集能力

6. 测试覆盖

  • Runtime todo边界测试(93行)
  • Todo快照测试(71行)
  • Web Store测试(useChatStore、useRuntimeInsightStore等)
  • 事件桥接测试(244行)
  • Patch解析器测试(121行)

变更统计

  • 63 files changed
  • 4,106 insertions(+)
  • 152 deletions(-)

测试验证

# 运行后端测试
go test ./internal/runtime/... ./internal/gateway/...

# 运行前端测试
cd web && npm test

Yumiue and others added 23 commits May 4, 2026 20:39
- Budget 常驻 StatusBar + 点击 popover 展示 ledger 对账详情
- 聊天流内联:Checkpoint 微标识(一键撤回)、Verification 折叠卡、Acceptance 决策卡
- 右侧 InsightPanel + Todo/Verification/Checkpoint 三 tab
- switchSession 并发预拉取 session.todos.list + checkpoint.list
- eventBridge 改造:verify/acceptance/checkpoint 事件直接生成聊天内联消息
- 新增 11 个单测,Web 42/42 全绿

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- session/todo.go:CurrentTodoVersion 6→7,新不变量 blocked_reason!="" ⇔ status=="blocked";去掉 BlockedReasonValue 兼容方法,wire 出口直读 raw 字段(omitempty 自动隐藏空值)
- ReplaceTodos / todo_write action="plan" 拒绝空 items,工具层与 session 层双层守卫;清空意图请走 set_status / remove
- TodoStrip 仅在 status=blocked 时渲染 blocked_reason;useRuntimeInsightStore.setTodoSnapshot 对空 items 视为 no-op,前端兜底防回归
- 新增 normalize/wire/lifecycle 不变量测试,docs/todo-schema-migration.md 同步重写

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
BudgetResolver 接口从 (int, string, error) 改为返回 BudgetResolution 结构体,
ContextWindow 从模型目录经 TurnBudgetSnapshot -> TurnBudgetDecision -> BudgetCheckedPayload
一路传递到前端 BudgetIndicator popover 中展示。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Budget 常驻 StatusBar + 点击 popover 展示 ledger 对账详情
- 聊天流内联:Checkpoint 微标识(一键撤回)、Verification 折叠卡、Acceptance 决策卡
- 右侧 InsightPanel + Todo/Verification/Checkpoint 三 tab
- switchSession 并发预拉取 session.todos.list + checkpoint.list
- eventBridge 改造:verify/acceptance/checkpoint 事件直接生成聊天内联消息
- 新增 11 个单测,Web 42/42 全绿

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- session/todo.go:CurrentTodoVersion 6→7,新不变量 blocked_reason!="" ⇔ status=="blocked";去掉 BlockedReasonValue 兼容方法,wire 出口直读 raw 字段(omitempty 自动隐藏空值)
- ReplaceTodos / todo_write action="plan" 拒绝空 items,工具层与 session 层双层守卫;清空意图请走 set_status / remove
- TodoStrip 仅在 status=blocked 时渲染 blocked_reason;useRuntimeInsightStore.setTodoSnapshot 对空 items 视为 no-op,前端兜底防回归
- 新增 normalize/wire/lifecycle 不变量测试,docs/todo-schema-migration.md 同步重写

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
BudgetResolver 接口从 (int, string, error) 改为返回 BudgetResolution 结构体,
ContextWindow 从模型目录经 TurnBudgetSnapshot -> TurnBudgetDecision -> BudgetCheckedPayload
一路传递到前端 BudgetIndicator popover 中展示。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@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.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 5, 2026

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.

发现 3 个值得处理的问题:

  1. web/src/utils/eventBridge.ts
    新增了 _latestVerificationMsgId / _latestDoneToolCallId / _latestCheckpointId 这组模块级游标,并提供了 resetEventBridgeCursors(),但没有把它接到会话切换、新建会话或清空聊天的主路径上。这样上一会话残留的 _latestCheckpointId 会被下一会话第一次 ToolStart 直接复用到 fileChanges,用户在新会话里点“拒绝更改”时会尝试恢复旧会话的 checkpoint。其余两个游标也会继续跨会话串线。

  2. internal/runtime/todo_run_boundary.go
    shouldResetTodosForUserRun() 现在只对白名单里的 5 个精确字符串返回“续做当前任务”。真实对话里更常见的是 继续修这个继续刚才的改动continue with the failing test 这类带补充语义的输入,它们都会落到 default 分支并清空现有 todo。这样会把用户明确想续做时的 in-progress / blocked todo 误删掉。

  3. internal/runtime/run.go
    多文件 tool_diff 这里只靠 WasNew 折算成 added/modified,没有保留“删除”或“未变化”的信息。结果是 move/copy 的源文件会被前端当成 modified,而 delete/remove_dir 这类路径也无法在多文件场景下标成 deleted。另外 toolResultMultiDiffs() 上游会把所有 pre-snapshot 都塞进 payload,像 copy 的 source 即使 diff 为空也会进入列表,文件变更面板会出现一个 0/0 的“modified”条目。

其余代码质量 / 性能 / 安全 / 文档检查未见需要单独指出的问题。

Comment thread internal/runtime/todo_run_boundary.go Outdated
return false
}
switch goal {
case "continue", "继续", "继续执行", "继续任务", "继续上一个任务":
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

这里把“续做当前任务”的识别做成了精确匹配;像 继续修这个继续刚才的改动continue with the failing test 这类更常见的 follow-up 输入都会误判成新任务并清空 todo。

Yumiue and others added 4 commits May 5, 2026 19:21
修复 PR 1024XEngineer#558 review 指出的白名单过窄问题。原实现仅识别 5 个精确字符串,
"继续修这个"/"continue with X"/"接着做"/"继续。"等带补充语义或标点的输入
都会落到 default 分支并清空 in_progress/blocked todo。

调整为前缀+标点容忍策略:
- TrimRight 去除尾部中英文标点
- 中文前缀:继续 / 接着 / 续做 / 再继续 / 再来
- 英文前缀:continue / keep going / keep doing / go on / resume / carry on
  英文要求精确或后跟空格,避免 "keep it simple" 单词误命中

新增 TestShouldResetTodosForUserRunContinueVariants 覆盖 25 个用例。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
修复 PR 1024XEngineer#558 review 指出的多文件 tool_diff change kind 不全问题。
原实现仅基于 WasNew 做 added/modified 二分,导致:
- move 的 source 文件被标为 modified(实际应为 deleted)
- delete_file/remove_dir 多文件场景无法标记 deleted
- copy 的 source(diff 为空)进入面板,显示 0/0 modified 占位

调整方案(向后兼容):
- file_snapshot.go 新增 Kind() 与 FileChangeKind* 常量,根据
  pre.existed 与 post 存在性输出 added/modified/deleted/unchanged
- toolexec.go 收集层调用 Kind(),unchanged 直接跳过(过滤 copy 源)
- events.go FileDiffEntry 加 Kind 字段(omitempty 保兼容)
- run.go buildToolDiffPayload 优先取 entry.Kind,缺失时回退 WasNew 二分
- toolResultMultiDiffs 兜底再过滤一次 unchanged

测试:
- file_snapshot_test.go 新增 TestFileSnapshotKind 覆盖 4 态
- tool_diff_helpers_test.go 新增 metadata kind 优先 / unchanged 过滤 /
  deleted 保留 / 兼容 fallback 共 4 个 case

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
修复 PR 1024XEngineer#558 review 指出的跨会话游标泄漏问题。eventBridge.ts 中的
_latestVerificationMsgId / _latestDoneToolCallId / _latestCheckpointId
仅在 MessageItem.tsx restoreCheckpoint 后调用 resetEventBridgeCursors(),
未覆盖会话切换/新建/清空入口。

后果:用户切换到新会话后,首次 ToolStart 写入的 fileChange 会继承上一会话
的 _latestCheckpointId,点击拒绝更改时会回退旧会话的 checkpoint。

修复:在 useChatStore.clearMessages 内部统一调用 resetEventBridgeCursors()。
switchSession/createSession/prepareNewChat 已统一走 clearMessages,
单点收敛保证一致;MessageItem.tsx 显式调用保留(restoreCheckpoint 不清 messages)。

测试:
- eventBridge.test.ts beforeEach 新增 resetEventBridgeCursors + fileChanges 重置
  保证测试隔离
- 新增 "clearMessages resets eventBridge cursors so new session does not
  inherit prior checkpoint" 验证完整跨会话场景

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
}

// continuationChinesePrefixes 中文续做关键词,落到 strings.HasPrefix 直接匹配。
var continuationChinesePrefixes = []string{"继续", "接着", "续做", "再继续", "再来"}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@xgopilot 所以现在是靠特殊文本匹配来确定是否保留todo状态吗

Copy link
Copy Markdown

@fennoai fennoai Bot May 5, 2026

Choose a reason for hiding this comment

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

结论

是,但范围要缩小一点说。

当前这版里,只有“新一轮用户 Run 开始时,要不要保留上一轮的 todo”这个边界判断,是靠用户输入文本做启发式匹配,不是语义级判定。

代码链路是:

所以严格讲,现在保留/清空旧 todo 的入口条件,确实是特殊文本模式匹配

补充说明

todo 状态本身 不是靠文本保存的,而是结构化会话状态:

也就是说:

  • todo 是否存在、内容是什么、状态怎么演进:是结构化数据
  • 新一轮用户输入进来后,沿用旧 todo 还是清空旧 todo:目前是文本启发式

如果你问的是 fennoai 前面指出的风险,那它说的是对的:这个判定现在仍然是 heuristic,不是显式的任务边界协议。

View job run

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

这是你那个没完成得妥协政策,判断继不继续来清不清空todo,否则verify不过

"enum": blockedReasonEnum,
"type": "string",
"enum": blockedReasonEnum,
"description": "仅当 status == \"blocked\" 时填写;其他状态请省略本字段。unknown 仅用于\"已经阻塞但无法给出具体原因\"的场景。",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这里是不是应该改成英语的

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

那很多提示得改了

@pionxe pionxe merged commit f17374e into 1024XEngineer:main May 6, 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.

3 participants