Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
918da52
fix: /mcp 退出竞态 ObjectDisposedException 降级 Debug(CI E2E NoErrors 红) | …
liuqihonggit Oct 20, 2026
99570c6
fix: 清理无用
liuqihonggit Oct 20, 2026
796d1c5
feat: 退出安全按键(双击Esc中断+Ctrl+C复制,永不误退出) | 决策: 用户痛点是Esc闲时/Ctrl+C误触直接关闭终端—…
liuqihonggit Oct 20, 2026
ff27492
feat: 一问一答节奏(忙时排队+未登录即时反馈) | 决策: 用户痛点是忙时提交被忽略致两条提问堆叠无回答、未登录时调引擎傻等40s—…
liuqihonggit Oct 21, 2026
a29f94c
fix: 空回合防御(空回复静默成功致 TUI 傻等) | 决策: 根因链是 506 工具 466KB 巨型请求+默认 10s API 超…
liuqihonggit Oct 21, 2026
27b013a
feat: DSG041 批2 子代理事件通道接通主代理路径(宿主层直投方案) | 决策: 挂点落 SessionController 主…
liuqihonggit Oct 20, 2026
7d92d61
docs: DSG041 批2 收口更新(宿主层直投方案变更 + L2 批次吸收撤销 + 批次重编号)
liuqihonggit Oct 20, 2026
264c5e8
feat: DSG041 批3 引擎侧子代理 BridgeEvent DTO + BridgeEventConsumer 映射(L4 投影…
liuqihonggit Oct 20, 2026
b355885
feat: DSG041 批4 InProcessEventConsumer 子代理三回调映射(TUI 进程内直连路径) | 决策: 三方…
liuqihonggit Oct 20, 2026
21c994b
docs: DSG041 批3/批4 收口(代码批次全部落地,链路闭合;剩余集成级验收三项列明)
liuqihonggit Oct 20, 2026
339639f
feat: McpPluginBootstrapHandle.Completion 插件就绪通知信号(邮箱语义替代时间性等待)+ E2E …
liuqihonggit Oct 21, 2026
44a7b17
fix: 巨型请求根因修复(两阶段工具加载生效) | 决策: 根因是 McpToolDispatchAttribute.Kind 默认 S…
liuqihonggit Oct 21, 2026
b7812de
feat: ModelInfo 信息类+上下文窗口硬校验+请求前预算守卫(1M 时代) | 决策: 三层修复——①ModelInfo 信息…
liuqihonggit Oct 21, 2026
49be153
docs: TASK061 落地记录(三层基线 1284+933+真机验证+孤儿接线发现)
liuqihonggit Oct 21, 2026
586b9c0
fix: 邮箱 ReceiveAsync 漏传 ct 三处根治(Host.DisposeAsync 永挂死锁)+ DSG041 批2 E2…
liuqihonggit Oct 21, 2026
2b73853
docs: DSG041 批2 E2E 集成验收收口(死锁根治+全链贯通)+ ChatService 路径缺陷遗留登记
liuqihonggit Oct 21, 2026
9a588ac
docs: TASK062 引擎侧问题登记(8 问题守卫总表——用户方法论'先记录再修复+守卫+单一职责'落地)
liuqihonggit Oct 21, 2026
cb50658
feat: TASK062 P2+P3 守卫落地——AgentMessageRouteLoop 单一职责路由循环(防 ReceiveAsy…
liuqihonggit Oct 21, 2026
4c05bee
test+fix: 三守卫补齐(Kind回归防护+超时120s+排队上限) | 决策: ①生成器Kind默认值三契约锁定(特性默认Mcp+…
liuqihonggit Oct 21, 2026
11d7abb
feat: Host 增 --selftest-turn 真实回合计时探针 | 决策: 诊断 TUI 回复延迟专用(走用户交互同链 Eng…
liuqihonggit Oct 21, 2026
3bc34c2
feat: TASK062 P4-P6 守卫落地——E2E 工具名常量化+TeammatePane 角色守卫+CI matrix 增补 |…
liuqihonggit Oct 21, 2026
1e2b8f2
fix: TASK062 P1 收口——子代理 E2E 三绿(误诊修正:非串话而是插件就绪+并行污染) | 决策: 分步插桩实证推翻 TA…
liuqihonggit Oct 21, 2026
7cab416
fix: TUI 三缺陷(回复双发/spinner续转/中文输入错位) | 决策: ①双发根因=AgentBase 循环透传 QueryE…
liuqihonggit Oct 21, 2026
ae5a166
docs: TASK062 结构化消息设计稿(消息ID/思考时长/CoT可展开/回复) | 决策: 四字段向后兼容扩展(Assistant…
liuqihonggit Oct 21, 2026
cf17c7b
feat: TASK062 结构化消息(消息ID/思考时长/CoT可展开) | 决策: AssistantMessage 末尾三可选参数向…
liuqihonggit Oct 21, 2026
9bdb2d4
fix: 排队提示改输入栏上方 queued 面板(对齐基准设计) | 决策: 用户验收反馈滚动区排队提示破坏消息流——忙时提交不上滚动区…
liuqihonggit Oct 21, 2026
2d267cd
feat: DSG041 集成验收第②项——Host selftest 扩子代理事件链断言(真实 spawn 全链) | 决策: Suba…
liuqihonggit Oct 21, 2026
550aa58
docs: DSG041 验收表终态——E2E 三绿+selftest 断言双收口(唯剩用户真实终端)
liuqihonggit Oct 21, 2026
ab33deb
feat: TASK063 子代理消息打断并发送(steer 协议) | 决策: 三层——①协议属性 CoordinatorMessage…
liuqihonggit Oct 21, 2026
dfc7d74
fix: MeshTransport 单向点对点 CI Linux 确定性失败根治(静默丢消息守卫+连接重试+测试反模式消除) | 决策:…
liuqihonggit Oct 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ jobs:
run: |
$tests = @(
@{Name="file-tools"; Filter="FullyQualifiedName~FileToolCoverageTests|FullyQualifiedName~SearchToolCoverageTests|FullyQualifiedName~ShellGitToolCoverageTests|FullyQualifiedName~ExtendedToolCoverageTests"},
@{Name="agent-tools"; Filter="FullyQualifiedName~AgentToolCoverageTests|FullyQualifiedName~BatchToolCoverageTests|FullyQualifiedName~TaskToolCoverageTests|FullyQualifiedName~AstIntegrationTests"}
@{Name="agent-tools"; Filter="FullyQualifiedName~AgentToolCoverageTests|FullyQualifiedName~BatchToolCoverageTests|FullyQualifiedName~TaskToolCoverageTests|FullyQualifiedName~AstIntegrationTests"},
@{Name="subagent-events"; Filter="FullyQualifiedName~SubAgentEventStreamE2ETests|FullyQualifiedName~SubAgentEventMainAgentPathE2ETests"}
)
foreach ($t in $tests) {
$name = $t.Name
Expand Down
31 changes: 22 additions & 9 deletions docs/proposed/design/DSG041-subagent-event-source-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,25 +69,38 @@ native_tui(TUI 宿主)子代理分组渲染全链已落地(SubagentGroupCo

| 基建实现 | 消费点 | 已实现 | 已验收 |
|---------|--------|--------|--------|
| L3 IEventConsumer 三方法(DIM 默认空)+ SessionController RouteSubagentEvent 前置分流 | BridgeEventConsumer / InProcessEventConsumer(批4/批5 接映射) | ✅ 批1(b64c5d16d) | ✅ SessionControllerSubagentEventTests 5/5(Started/Finished/工具分流/普通零回归/混合流)+ host.tests 1371 + abs.tests 694 + engine/cli/Host 三链编译绿 |
| L1 SubAgentEventChannel 接通 QueryEngine 主代理路径 | AgentStreamExecutionMiddleware/ForkSubAgentManagerActor 发射侧(零改动) | ⏳ 批2 | ⏳ E2E 复制先例 + agents 单测 |
| L2 AgentStreamChunkAdapter AgentId 传播 + 类型映射 | SessionController chunk→ChatStreamEvent 翻译 | ⏳ 批3 | ⏳ adapters 单测 |
| L4 引擎侧 BridgeEvent 三 record | bridge_serve JSON 协议消费方 | ⏳ 批4 | ⏳ BridgeJsonContractTests |
| InProcessEventConsumer 映射 | EngineTurnClient → ReplBridgeDriver(既有路由零改动) | ⏳ 批5 | ⏳ Host --selftest 扩断言(ADR 0080 真实运行) |
| TUI 真实链路分组显示 | SubagentGroupCoordinator → 分组渲染(既有零改动) | ⏳ 批5 | ⏳ 用户真实终端(agents 场景真实引擎 spawn) |
| L3 IEventConsumer 三方法(DIM 默认空)+ SessionController RouteSubagentEvent 前置分流 | BridgeEventConsumer / InProcessEventConsumer(批4/批5 接映射) | ✅ 批1(hash 已随 PR #439 squash,内容在库) | ✅ SessionControllerSubagentEventTests 5/5(Started/Finished/工具分流/普通零回归/混合流)+ host.tests 1371 + abs.tests 694 + engine/cli/Host 三链编译绿 |
| L1 SubAgentEventChannel 接通主代理路径(**宿主层直投方案**) | AgentStreamExecutionMiddleware/ForkSubAgentManagerActor 发射侧(零改动) | ✅ 批2(6b762c145) | ✅ 单元级:MainAgentPath 2/2(通道事件全序列直投三回调 + 子代理工具事件不走普通回调)+ host.tests 1373 全绿 + Host 编译绿;✅ 集成级:SubAgentEventMainAgentPathE2ETests 1/1 绿(00f2a77ae — MockServer 真实 LLM 全链:agent 工具→子代理 spawn(含工具轮)→Emit→通道→Drain 直投→三回调全达消费者,16s 干净收尾;过程中根治 Host.DisposeAsync 永挂死锁三处 ReceiveAsync 漏传 ct) |
| ~~L2 AgentStreamChunkAdapter AgentId 传播~~ | ~~SessionController chunk→ChatStreamEvent 翻译~~ | **✅ 被批2 宿主层直投方案吸收**(通道事件不经 chunk 转换层,AgentBase/adapter 零改动;批3 撤销) | —(无独立交付物) |
| L4 引擎侧 BridgeEvent 三 record + BridgeEventConsumer 显式映射 | bridge_serve JSON 协议消费方 | ✅ 批3(6d55a8215) | ✅ BridgeJsonContractTests JSON 形状快照锁定(subagent_started/subagent_tool_use/subagent_finished camelCase)+ BridgeEventConsumerTests 映射断言 + host.tests 1375 + engine/cli/Host 三链编译绿 |
| InProcessEventConsumer 映射 | EngineTurnClient → ReplBridgeDriver(既有路由零改动) | ✅ 批4(3f7f88919) | ✅ InProcessEventConsumerTests 映射断言(三 record 字段逐一对齐)+ NativeTui.Host.Tests 61 全绿 + Host 编译绿;✅ Host --selftest 扩子代理断言(2d267cd5b — SubagentSelftest 真实 MockServer+引擎+主代理路径完整回合,三回调断言实测通过退出 0) |
| TUI 真实链路分组显示 | SubagentGroupCoordinator → 分组渲染(既有零改动) | ✅ 链路闭合(批1-4) | ⏳ 用户真实终端(agents 场景真实引擎 spawn — 唯一剩余项) |

## 8. 后续

- ~~批1(L3 协议扩展)可立即开工(无前置依赖)~~ **✅ 已完成(b64c5d16d,2026-10-21)**
- 批2(L1 通道接通):挂点二选一决策见风险1(倾向 AgentBase 循环内排空先行)
- ~~批1(L3 协议扩展)~~ **✅ 已完成(内容随 PR #439 squash 入库)**
- ~~批2(L1 通道接通)~~ **✅ 已完成(6b762c145,宿主层直投方案 — 见批2 实施记录)**
- ~~批3(L2 chunk 传播)~~ **✅ 撤销 — 被批2 宿主层直投方案吸收**
- ~~批4(原批3 引擎侧 DTO + BridgeEventConsumer 映射)~~ **✅ 已完成(6d55a8215)**
- ~~批5(原批4 InProcessEventConsumer 映射)~~ **✅ 已完成(3f7f88919)— 代码批次全部落地,链路闭合**
- **剩余集成级验收**:~~① 批2 E2E~~ **✅(00f2a77ae,顺带根治 Host.DisposeAsync 永挂死锁——三处邮箱 ReceiveAsync 漏传 ct)** ~~② Host --selftest 扩子代理断言~~ **✅(2d267cd5b)** ③ 用户真实终端收口(唯一剩余项)
- ✅ ChatService 路径 E2E 亦三绿(b7e4ea782)——误诊修正:非串话缺陷,真实根因=插件就绪等待缺失+xunit 跨 class 并行污染(详见 TASK062 P1);CI 白名单 subagent-events 三用例全覆盖
- 本 DSG 落地后 TASK055 三缺口③关闭

### 批1 实施记录(b64c5d16d)
### 批1 实施记录(hash 已随 PR #439 squash,内容在库)

- IEventConsumer 三方法走 **DIM 默认空实现**(既有 8+ 实现方零改动;默认实现须经接口类型调用的既有坑已规避)
- SessionController.ProcessEvent 前置分流 **RouteSubagentEvent**:AgentId 非 null 即子代理事件——AgentStarted→OnSubagentStarted(身份三元组)、AgentFinished→OnSubagentFinished(**AgentSuccess 成功语义取反为 isError**)、带 AgentId 工具事件→OnSubagentToolUse(tokenGain 恒 0 兜底,批2 填真实值);返回 true 跳过主 Switch
- 实施坑:AgentSuccess→isError 语义取反(首轮直传 false 导致 finished.IsError 断言反);mixed 流中子代理 Content 事件暂不投影返回 false 走主路径(消费面仅三回调)

### 批2 实施记录(6b762c145 — 方案变更:宿主层直投)

- **挂点决策结果**:既非 AgentBase 循环排空也非 QueryCoreMiddleware 排空,而是 **SessionController 主代理路径**(第三方案,实施时发现的最优解)——通道作用域 + 排空全部落宿主层,AgentBase/QueryEngine/adapter 全零改动
- 结构:`StreamResponseAsync` 主代理分支内 `new SubAgentEventChannel() + EnterScope()`(AsyncLocal 沿 await 链传播覆盖 QueryEngine 工具执行段 → Agent 工具中间件 Emit 点可见)→ chunk 循环逐拍 `TryDrain` 直投 `ProcessEvent`(复用批1 分流)→ 循环后末批冲刷 + `Complete()`(迟到 Emit 静默丢弃防泄漏,对齐 QueryLoopMiddleware 先例)
- **L2 被吸收**:通道事件不经 chunk 转换层直接是 ChatStreamEvent,AgentStreamChunkAdapter 不需要传播 AgentId(主代理 chunk 的 AgentId 是主代理自身 id,传播反而会误分流——这也是直投方案的正确性优势)
- 实施坑:Moq 泛型回调返回类型必须精确匹配(QueryAsync 返回 IAsyncEnumerable<QueryStreamChunk> 非 AgentStreamChunk);QueryStreamChunk.AgentId 非必填(与 AgentStreamChunk 不同)
- tokenGain:批2 后仍恒 0(通道事件无 token 语义字段;真实 token 增量待 ChatStreamEvent.Usage 传播或 TUI 侧 TokenDelta 近似,列为低优先后续项)

## 9. 各批验收方式定义(2026-10-21 用户确认"先定义验收方式再逐个进行")

> 原则:TDD 红绿循环(每批先红测试后实现)+ 层级递进验收(单测 → E2E → 真实运行),全链最终以 ADR 0080 真实运行收口。
Expand Down
25 changes: 25 additions & 0 deletions docs/proposed/task/TASK059-退出安全按键.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# TASK059 — 退出安全按键(双击 Esc 中断 / Ctrl+C 复制 / 永不误退出)

> 状态:in_progress(2026-10-21 开工)
> 前置:TASK058 完结;用户指令:"双击ESC是中断对话, Ctrl+C是复制, 这两个都不要关闭终端, 因为很不舒服"

## 痛点(用户真机反馈)

| 键 | 现行为 | 问题 |
|----|--------|------|
| Esc 闲时空输入 | `_running = false` 退出 | 想打断按 Esc,回合恰好结束 → 终端直接关 |
| Ctrl+C | `_running = false` 退出 | 想复制的肌肉记忆 → 终端直接关 |

## 方案(Core 零依赖 + 宿主委托注入)

1. **Esc 双击中断**:忙时 500ms 内两击 → `Interrupt()`;单击无操作(等双击窗口,时钟 `internal Func<long> EscClock` 可注入测试);闲时有文本清输入(保留);**Esc 永不退出**
2. **Ctrl+C 复制**:复制滚动区最后一条 AssistantMessageItem 文本(基准语义:复制最后输出);剪贴板写入经构造参数 `Action<string>? copyToClipboard` 宿主注入(ADR 0140 — Core 不依赖引擎 IClipboardService);复制后 PostInfo 反馈;无 assistant 消息/未注入委托时无操作
3. **退出路径**:Ctrl+D 空输入退出(已有)+ `/exit` 引擎命令(ExitCommand 确认对话框)— 文档明示

## 验收表

| 基建实现 | 消费点 | 已实现 | 已验收 |
|---------|--------|--------|--------|
| Esc 双击状态机(ReplShell.EscClock + HandleEscape 改造) | 忙时中断链 | ✅ | 待真机 |
| Ctrl+C 复制(copyToClipboard 委托 + 最后 assistant 消息) | Program 接线引擎 IClipboardService | ✅ | 待真机 |
| 退出路径保留(Ctrl+D + /exit) | 文档说明 | ✅ | 待真机 |
34 changes: 34 additions & 0 deletions docs/proposed/task/TASK060-一问一答节奏.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# TASK060 — 一问一答节奏(忙时排队 + 未登录友好提示)

> 状态:in_progress(2026-10-21 开工)
> 前置:TASK059 完结;用户真机反馈(对照基准截图):"没有登录它提示多友好啊,而且消息区域是一问一答,我的提问倒是连续发送了两个"

## 痛点(用户真机截图分析)

| 现象 | 根因 |
|------|------|
| `❯ 112` 40s 无响应后 `❯ 3333` 又提交,两条提问堆叠无回答夹中间 | 忙时提交被忽略(EngineTurnClient 回 Error 诱导行),一问一答节奏破坏 |
| footer "未登录"是硬编码种子,未登录时输入仍调引擎傻等 | 登录态未从引擎真实获取(session_info 无此字段) |

## 方案(两步渐进)

### Step 1:忙时排队(Core 层,对齐基准 queued 语义)
- `ReplShell` 加排队队列:忙时 Submit → 用户输入上屏 + `⎿ 已排队` dim 行(不调引擎);
回合结束(DrainEngine 检测 !IsBusy)自动按序发送队首(不上屏重复)
- 新消息组件 `InlineNoteItem`(` ⎿ ` 前缀 dim 行)— queued 提示与未登录提示复用
- EngineTurnClient 忙拒逻辑保留兜底(不再被 Core 拦截路径触达)

### Step 2:未登录友好提示(引擎→TUI 全链)
- `BridgeEvent.SessionInfo` 加 `LoggedIn`(bool,末尾可选零破坏)
- 引擎侧 `BuildSessionInfoEvent` 判定:`config.Provider.ApiKey` 非空 = 已登录(key 可用即能对话)
- TUI:driver 应用 → FooterState.LoginError 真实化;未登录时 Submit 本地回
`⎿ 未登录 · 请配置 auth.json 或运行 /login`(不调引擎不傻等)

## 验收表

| 基建实现 | 消费点 | 已实现 | 已验收 |
|---------|--------|--------|--------|
| InlineNoteItem(⎿ dim 行) | queued/未登录提示复用 | 待做 | 待真机 |
| 忙时排队队列(ReplShell) | Submit/回合结束自动发送 | 待做 | 待真机 |
| SessionInfo.LoggedIn 字段链 | EngineSession 判定 + driver footer | 待做 | 待真机 |
| 未登录本地即时反馈 | Submit 拦截 | 待做 | 待真机 |
55 changes: 55 additions & 0 deletions docs/proposed/task/TASK061-ModelInfo与上下文窗口校验.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# TASK061 — ModelInfo 信息类 + 上下文窗口配置校验(1M 时代)

> 状态:implemented(2026-10-21 三层落地 + 全绿 + 真机验证;剩余用户验收 agnes 场景报错呈现)
> 前置:巨型请求修复(4c27592ab)完结;用户指令:"主流模型上下文已达 1M,模型配置里写模型名称+上下文大小,不对的直接报错;建一个 modelInfo 信息类"

## 调研结论

| 资产 | 现状 | 缺口 |
|------|------|------|
| ModelEntry(abs_core/configuration/llm) | Id/DisplayName/ContextWindow/Description 配置 DTO | 无自校验;无"当前模型"聚合信息类 |
| ContextWindowResolver(guard) | env > ModelConfigLoader.FindModel > ProviderDefinition > **兜底 200K** | **FindModel 命中但 ContextWindow=0 直接返回 0**(agnes 9 模型全 0 实锤)→ 下游 DecidePreflight 抛不友好 ArgumentOutOfRange;兜底 200K 掩盖配置错误(1M 模型被错误当 200K) |
| ContextFoldService(brain) | 折叠后仍超紧急阈值抛 ContextOverflowException(骨架已有) | 入口 ctxMax=0 时不友好 |
| providers_llm/{vendor}/models.json | contextWindow 字段已有 | agnes 9 模型全 0(脏数据);加载零校验 |

## 方案(三步)

### Step 1 — ModelInfo 信息类(abstractions)
`ModelInfo` sealed record:ModelId/Provider/DisplayName/ContextWindow + `ValidateOrThrow()`
(contextWindow<=0 → ConfigurationException 带修复指引:模型名+供应商+providers_llm 路径);
静态 `FromEntry(provider, ModelEntry)` 投影。

### Step 2 — ContextWindowResolver 严格化(guard)
`ResolveCurrentContextWindow`:FindModel 命中但 ContextWindow<=0 → 抛 ConfigurationException
(不再静默透传 0);找不到模型仍兜底 200K(未知模型不阻断,日志警告)。

### Step 3 — agnes 脏数据处置
agnes models.json 9 模型 contextWindow=0 — 校验报错即用户要求的"直接报错";
不猜数据(多模态模型窗口未知),错误信息带修复指引由用户补值。

## 验收表

| 基建实现 | 消费点 | 已实现 | 已验收 |
|---------|--------|--------|--------|
| ModelInfo + ValidateOrThrow(abstractions) | resolver/两源投影 | ✅ 4 测试 | ✅ 单元 13/13 |
| resolver 0 值严格化(guard) | 启动/请求前窗口解析 | ✅ 2 测试 | ✅ 1284/1284 + 真机 sensenova 正常 |
| 请求前预算守卫(QueryLoopMiddleware.GuardContextBudget 孤儿接线) | 每轮迭代 historySnapshot 后 | ✅ 2 测试 | ✅ 933/933 |
| IChatContextManager.DecidePreflightWithCurrentSpecs | 中间件守卫消费面 | ✅ | ✅ |

## 最终基线

- guard.config.tests:1281 → **1284**(+ModelInfo 4 + resolver 2 - 既有调整)
- brain.context.tests:931 → **933**(+守卫 2)
- 提交:5a5d7fa89
- 真机:sensenova 窗口临时置 0 → 报错链验证通过后恢复;正常路径回复 `ok` 恢复

## 额外发现(调研结论)

- **DecidePreflight 是孤儿**(接口+实现齐全但无任何消费方)——请求前预算守卫此前根本没挂主链,本任务接线修复
- agnes 9 模型 contextWindow 全 0(真实脏数据)——严格化后被使用到时立即报错(带修复指引),非当前 profile 不阻断启动

<!-- 🤖 Auto Decision: 2026-10-21 -->
<!-- 决策: 三层修复(信息类+配置校验+请求前守卫)而非单点校验 -->
<!-- 原因: 用户三诉求(ModelInfo 信息类/配置不对直接报错/超窗直接报错)分别对应元数据/加载校验/运行守卫三层,且调研发现 DecidePreflight 孤儿缺陷(守卫从未挂主链)一并接线 -->
<!-- 替代方案: 仅配置加载校验(治标——0 值被兜底 200K 掩盖、超窗请求仍发 API)-->
<!-- 验证: 1284+933 全绿 + 真机 sensenova 正常/0 值报错链验证 ✅ -->
Loading