Skip to content

feat: DSG041 子代理事件源全链 + Host.DisposeAsync 死锁根治 + TASK062 守卫体系 - #444

Merged
liuqihonggit merged 30 commits into
mainfrom
w1
Oct 21, 2026
Merged

liuqihonggit merged 30 commits into
mainfrom
w1

Conversation

@liuqihonggit

Copy link
Copy Markdown
Owner

Summary

  • DSG041 引擎侧子代理事件源四批次(协议三回调/通道直投/BridgeEvent DTO/消费者映射)+ 集成验收双收口(三 E2E 绿 + Host selftest 扩断言)
  • Host.DisposeAsync 永挂死锁根治(三处邮箱 ReceiveAsync 漏传 ct——dumpasync 取证完整链)
  • TASK062 问题登记+守卫体系(AgentMessageRouteLoop 单一职责路由循环/E2E 工具名常量化/TeammatePane 角色守卫/CI 白名单增补)
  • McpPluginBootstrapHandle.Completion 插件就绪通知信号(邮箱语义替代时间性等待)

Test plan

  • 子代理 E2E 3/3 绿(MockServer 真实 LLM 全链)
  • Host selftest 全链通过(真实 spawn 三回调断言)
  • agents.tests 632 + host.tests 1381 + NativeTui.Tests 817 + NativeTui.Host.Tests 64 全绿

…决策: 根因是 CLI 单命令退出释放容器(LocalToolRegistry.DisposeAsync 释放内部匿名锁 AsyncLock#2)与后台插件链就绪钩子 RefreshKernelPluginsAsync 竞态,原 catch 一律 LogError 进 stderr 触发 E2E 断言红;ObjectDisposedException 属退出竞态良性噪音(进程将亡刷新无意义)降级 LogDebug 对齐 McpPluginBootstrap 取消静默先例,其余异常保持 Error 真实故障不静默;提取 HandleRefreshError internal 有名函数供测试面
…—Esc改双击状态机(忙时500ms内两击Interrupt,单击等窗口;闲时清输入;永不置_running=false),双击窗口用internal Func<long> EscClock注入测试;Ctrl+C改复制最后assistant消息(剪贴板写入走构造委托Action<string>宿主注入引擎IClipboardService,Core零依赖ADR 0140,复制后PostInfo反馈);退出路径收敛为Ctrl+D空输入+/exit命令
…—忙时改基准queued语义(用户输入上屏+⎿已排队dim行复用ToolResultItem、入历史环不调引擎,回合结束DrainEngine队列泵逐条自动发送维持一问一答),未登录走SessionInfo.LoggedIn字段链(引擎ApiKey判定→driver门禁态+footer真实化替换硬编码种子)提交本地⎿反馈行不调引擎;LoggedIn默认true旧引擎兼容不误拦
…时掐流重试后拿到空流,SessionTurnResult.Success(空) 静默返回致 TUI 无消息无错误 spinner 永转;防御判定三条件(无文本+无思考+无实质产出)判 Error 带重试诱导,_hasSubstantiveOutput 字段覆盖 onToolStart 与子代理路由置位防工具/子代理回合误判,思考回合经 thinkingContent 长度豁免;三个特殊事件测试补 Text 产出回归本意
…代理路径而非 AgentBase/QueryEngine——回合级 EnterScope 覆盖 QueryEngine 工具执行段(AsyncLocal 沿 await 链传播到 Agent 工具中间件 Emit 点),chunk 循环逐拍 TryDrain 直投 ProcessEvent 复用批1 RouteSubagentEvent 分流,完全绕过 chunk 转换层(AgentBase/adapter 零改动,L2 批次被本方案吸收);循环后末批冲刷+Complete 防迟到事件泄漏(对齐 QueryLoopMiddleware 先例);2 新测试(通道事件全序列直投三回调+子代理工具事件不走普通回调)+ host.tests 1373 全绿 + Host 编译绿
…) | 决策: 引擎侧 Cli.Bridge.BridgeEvent 增 SubagentStarted/SubagentToolUse/SubagentFinished 三 record(字段与 native_tui 侧逐字段镜像——SubagentId/AgentType/Description + ToolName/Summary/TokenGain + IsError,camelCase JSON 命名策略自动对齐),[JsonDerivedType] 注册 subagent_started/subagent_tool_use/subagent_finished 三 type;BridgeEventConsumer 显式实现三方法(DIM 默认实现经类类型调用不可见的既有坑——直接调用方必须显式实现);JSON 形状经 BridgeJsonContractTests 序列化快照锁定防双端漂移;2 新测试 + host.tests 1375 全绿 + engine/cli/Host 三链编译绿
…法直转 BridgeEvent.SubagentStarted/SubagentToolUse/SubagentFinished 内存 record 入队(对齐 bridge 形态唯一差异——序列化 stdout → 队列写内存对象),显式实现规避 DIM 经类类型调用不可见坑;下游 ReplBridgeDriver 路由与 SubagentGroupCoordinator 分组渲染均既有零改动——整条「引擎通道直投→SessionController 分流→消费者映射→TUI 分组渲染」链路闭合;1 新测试 + NativeTui.Host.Tests 61 全绿 + Host 编译绿
…主代理路径骨架 | 决策: Completion 暴露后台链 Task(Run 前已完成占位、Run 后即八插件+就绪钩子完成信号),消费方等通知而非 Task.Delay 固定延时——CI 快慢机均可靠且零浪费(用户指正时间耦合手法错误后的正确形态);E2E 主代理路径脚本含 Completion 等待示范用法+30s 挂死保护;E2E 工具名修正 Agent→agent(AgentToolName 枚举 [EnumValue("agent")] 真值);主代理路径 E2E Skip 登记引擎侧子代理执行链崩溃缺陷(对照 ChatService 路径同域红——子代理 LLM 输出无 AgentId 串入主流,疑 TASK043 流式透传域,非 DSG041 接线问题单测全绿);InternalsVisibleTo 补 E2E 测试工程;1 新测试+host.tests 1376 全绿
…ystem+生成器 fallback "system" 双处旁路两阶段机制,506 工具全量 schema 466KB 被 10s 超时撞断致空回复;默认改 Mcp(BuildToolsFromKernel 已支持 McpTools 组只发名称+tool_description_request 二阶段补齐),核心四类 File/Search/CodeExecution/Agent 显式 System 对齐基准 Claude Code 核心工具集;实测请求体 466919→95509 字节(-80%)、工具 506→32、耗时 9.9s→1.9s、sensenova 真实回复恢复
…类(ModelId/Provider/DisplayName/ContextWindow+ValidateOrThrow,两源投影 ModelEntry/ModelItemConfig);②ContextWindowResolver 严格化(FindModel 命中 contextWindow<=0 抛 ConfigurationException 带修复指引,不再静默透传 0 致下游 ArgumentOutOfRange——agnes 9 模型 0 值脏数据形态将即时报错;未知模型仍兜底 200K 不阻断);③请求前预算守卫孤儿接线(DecidePreflight 此前无消费方——QueryLoopMiddleware 每轮迭代取历史快照后 GuardContextBudget,估算比率>=1.0 抛 ContextOverflowException 直接拦截不发 API 带清上下文诱导,null 容错不破 mock/旧实现);IChatContextManager 增 DecidePreflightWithCurrentSpecs 自取版(唯一实现 ChatContextManager);实测 sensenova 正常回复恢复
…E 转绿 | 决策: dumpasync 取证锁定完整死锁链——E2E→AsyncHostWrapper→Host→容器→AgentServiceImpl.DisposeAsync→BackgroundTaskActor.WhenAll→RouteWorkerPermissionResponsesAsync 挂在 Channel 读(ct 只在收到消息后检查、ReceiveAsync 调用漏传 ct——MailboxBase 底层 ReadAllAsync(ct) 本就支持,纯调用遗漏);修复三处同类:AgentServiceImpl:679+SwarmPermissionMessageRouter worker 路由(补 _cts 传递)+PlanApprovalMessageRouter teammate 路由(补独立 Cts 列表入 StopRoutingAsync 统一收尾);E2E 主代理路径脚本补子代理工具调用轮(turn2 read 工具)后全链贯通转绿——MockServer 真实 LLM→agent 工具→子代理 spawn(含工具轮)→Emit→通道→Drain 直投→三回调全达消费者,16 秒干净收尾;验证:主代理路径 E2E 1/1 绿+agents.tests 628+host.tests 1381 全绿;遗留登记:ChatService 路径 E2E 仍红(子代理 LLM 流无 AgentId 透传主流——疑 TASK043 StreamingFallbackDecorator 域,独立缺陷非 DSG041 接线问题)
…nc 漏传 ct 再犯) | 决策: 邮箱消息路由循环提取独立小类(构造注入 broker+agentId+handler,'ct 传入 ReceiveAsync'收敛为类内一处构造契约——漏传在结构上不可能),Swarm/PlanApproval 两路由器重构消费(worker/teammate 路由改经 RouteLoop+StopRoutingAsync 统一收尾+删旧 1 参死代码重载);所有权转移经工厂方法返回值形态(analyzer JCC9108 IAsyncDisposable 守卫触发的显式化——守卫本身证明'问题更容易暴露'方法论);守卫测试 4 个(无消息 Dispose 时限收尾=挂死回归形态/消息路由派发/停止语义/未注册空流)+ 注册经 WaitForCommandsDrainedAsync 排空屏障(邮箱模型通知语义替代固定延时);agents.tests 632 全绿+主代理路径 E2E 复验 1/1 绿
…产物默认mcp用Sandbox真实样本+核心File白名单System)防巨型请求复活,生成器此前零测试覆盖;②API超时默认10s→120s(根因链最后一环——慢推理模型首包常超10s,超时兜底已有空回合防御+Timeout诱导不怕长等);③排队上限10条(狂敲防膨胀,满后丢弃带反馈);基线804+1381全绿
…ineTurnClient→SessionController(mainAgent)→QueryEngine,逐事件相对时间戳 turn_started/首思考/首 token/turn_completed,60s 超时兜底);实测 sensenova 首包 3.6~8s 波动回合 4~8s 完成链路健康,用户 40s+ 复现系旧二进制(巨型请求修复前构建);后续回归延迟问题可用此探针一键定位
… 决策: P4 两 E2E 脚本 magic string 改 AgentToolNameEnumConstants.Agent/FileToolNameEnumConstants.FileRead(单一数据源——枚举改名即编译错而非 E2E 静默 not found,排障两轮的根因消除);P5 TeammatePaneMiddleware 判定加 ExecutorVariant.Teammate 守卫(executor 前台子代理不再尝试 tmux pane——Windows 警告噪音归零、E2E 16s→7s);P6 ci-e2e 增 subagent-events 条目(MainAgentPath 进 CI 白名单——曾因不在白名单缺陷长期潜伏的教训;ChatService 路径待 P1 修复后增补);E2E 复验 1/1 绿+agents.tests 632 全绿
…SK043 串话假设——ChatService 路径 agent-handler/fork/中间件全部零执行=工具在 handler 前被 not found 短路(kernel.Plugins 挂载晚于启动);修复三件=①先例 E2E 补 McpPluginBootstrapHandle.Completion 确定性等待(通知语义对齐主代理路径先例)②两类加 [Collection(SubAgentEventSerial)] 强制串行(同 testhost 并行时引擎 session 进程级干扰致 turn 跨测试消耗——xunit parallelizeTestCollections 参数实测未生效改用 Collection)③fork 用例断言对齐 teammate 路径演进(AgentName=teammate/前缀 teammate-);CI 白名单补全 ChatService 两用例(subagent-events 条目三测试全覆盖);3/3 全绿 14s
…ngine 的 Complete 后尾部又补发一个(CLI 流式直写无感掩盖,TUI/bridge 累积式消费者双上屏)——sawComplete 标记单次语义(未发时兜底补发保异常路径),探针实证 assistant_message 2→1;②spinner 回合结束不清 Mode 致 Thinking shimmer 续转——EndTurn 复位 Responding;③中文光标错位=CursorCol char 偏移直接当屏幕列(CJK 每字 2 列)——PromptInputBox.MeasureDisplayWidth 渲染层换算(光标列+ghost 起点+ReplView 帧尾光标三处,编辑语义不动单一职责);基线 809+62+agents 632 全绿
…Message 末尾可选参数同 SessionInfo.Vendor 先例),渲染形态对齐基准(思考dim前缀行+ctrl+o展开CoT),InProcessEventConsumer累积思考文本OnDone组装;MessageId为回合序号非时间戳(终端不显示ID本身避免视觉噪音);三个决策点待用户确认:思考行位置/ctrl+o作用域/无思考模型形态
…后兼容(MessageId会话级递增+ThinkingDurationMs多段累计+ThinkingContent全量),InProcessEventConsumer OnThinking每段重启计时(多段1500+1500测试锁定),渲染对齐基准(⎿思考Ns·ctrl+o展开dim行+展开态CoT缩进+200行守卫),Ctrl+O绑定ToggleLastThinking(两类消息引用相等索引取更靠后者,无CoT静默);三决策点用户确认全按推荐
…(用户消息发送时刻才进消息区),ReplView 增 QueuedInputs 面板渲染在输入框上方(❯ 文本 dim 逐行,次条起带 (queued) 标记,首条即将发送高亮语义),高度计入 TailHeight/MeasureContentHeight 布局链,Submit/Pump 即时同步视图不等渲染帧
…gentSelftest 可测类提取(Program 入口薄接线)——真实 MockServer 假 LLM+真实引擎组装+主代理路径完整回合,断言 OnSubagentStarted/ToolUse/Finished 三回调到达(通道 Emit→Drain 直投→分流→映射全链);插件就绪经 Completion 通知等待(E2E 同款根因防护);MockServer 未构建返回 Skipped 非失败(CI 由 ci-e2e subagent-events 三用例兜底,本地全链验证用);exe 递归查找对齐 E2E 先例(配置/TFM 子目录);InternalsVisibleTo 补 NativeTui.Host;实测 selftest 全链通过(无 SKIP 退出 0 三回调断言全过)+ NativeTui.Host.Tests 64 + NativeTui.Tests 817 全绿
@liuqihonggit
liuqihonggit enabled auto-merge (squash) October 21, 2026 15:55
….InterruptAndSend(默认false向后兼容,邮箱消息模型单一数据源);②AgentBase.RequestSteer 轮级打断信号(volatile 置位,ExecuteStreamAsync chunk 循环开头检查点跳出,Complete 兜底补发收尾,轮结束复位——转发消息下轮 TryDrain 消费);③双链路由(SendMessageToAgentAsync 邮箱路径置 InterruptAndSend=true+运行中实例 RequestSteer,ForwardUserInputToAgentAsync 转发队列路径同语义一致;未运行实例 null 静默——消息仍在邮箱等下轮);IAgent 接口面 +RequestSteer(唯一实现 AgentBase 零破坏其他实现方)
… 三层修复——①产品守卫:SendAsync 连接失败原静默 return 丢消息(无异常无日志无返回值),补 TransportDiagnostics+logger 双通道告警使丢帧点在 CI 输出直接可定位;②连接失败有限重试(3 次线性退避 100/200/300ms):接收方 accept 循环是单实例串行模型(accept 后才建下一实例),重连撞该窗口即 ECONNREFUSED→null→丢消息——退避重试穿透窗口,正常首连零额外开销(重试仅失败分支触发);③测试消除 Task.Delay(100) 时间耦合反模式(Windows 碰巧够/Linux 慢机无正确性保证)改为立即发送(对齐同文件双向测试 CI 绿实证形态——同数据路径无 Delay 亦通)+测试窗口内开 TransportDiagnostics.Enabled(finally 复位)使 CI 再失败时 PIPE-ACCEPT/MESH/MESH-WRITE 全链日志直达断点;本地实证:TransportE2ETest 6/6+单向测试 5 轮连跑稳定(42-56ms)+async_primitives 全量 600/600 绿
@liuqihonggit
liuqihonggit merged commit ff9a5e8 into main Oct 21, 2026
@liuqihonggit
liuqihonggit deleted the w1 branch October 21, 2026 17:00
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.

1 participant