Skip to content

[PR] fix: v0.1.200 review follow-ups — self-heal guard, cold-load counter, JSONC audit + web editor - #3689

Merged
ranxianglei merged 4 commits into
masterfrom
2026-10-18_pr3668-review-fixes
Oct 18, 2026
Merged

ranxianglei merged 4 commits into
masterfrom
2026-10-18_pr3668-review-fixes

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Review follow-ups for the v0.1.200 diff (78 commits, #3668). Four independent fixes, each with a regression test; none changes hot-path behavior for a healthy setup.

1. Native self-heal could bind a dead origin after a re-attach (dsh-native)

When a native agent's proxy died, maybeRetry started a fetch for a fresh origin. If the agent was re-activated while that fetch was still in flight (e.g. the user re-attached), the stale origin resolved later and was written into the live register unconditionally — every subsequent tool call went to the dead origin. Same class as #3616; the bootstrap guard already snapshots its generation, but its return value flowed into maybeRetry unguarded. Fix: snapshot originGen before the fetch and drop the write if the world moved on. Post-giveUp revival (#983) is still allowed — only the generation check is added.

2. Cold-load diagnostics printed a dead counter (persist)

logColdLoad logged session.stats.tokensSaved, but #2734 removed the last writer of that field — the line always showed a stale zero (the test hand-set 42000 to fake it). Now reads the kernel's live counter state.stats.compressionCount, which starts at 0, increments on every fold, and round-trips with the persisted state.

3. Startup credential audit broke on JSONC configs (#3572)

The runtime accepts JSONC config files since #3572, but the boot-time external-summary audit still read the file with strict JSON — a JSONC config logged a bogus parse error and the global summary-credential chain was silently skipped at boot. Now routed through loadConfigFile (tolerant parser, never throws). The per-route chain was already correct.

4. Web editor rejected JSONC configs (#3572, #3488)

The server accepts JSONC since #3572, but the web client strict-parsed the draft text in five places (quick-config hydrate, freshDraft, summary hydrate read(), save-quick, save-file) — so a config that works at runtime made the quick panel vanish (#3488) and blocked saves. One tolerant parser is defined once in the TS module (strict JSON first, then comment/trailing-comma stripping; string-aware, length-preserving) and inlined into the browser IIFE via toString() — a single implementation, importable by tests. A genuinely broken draft still fails locally, and the server's parseBiliConfig stays authoritative on save.

Test plan

  • tests/dsh-native.test.ts — new case pins the superseded-respawn flight; full file 60/60
  • tests/issue3573-cold-load-diagnostics.test.ts — 3/3 on the new counter
  • tests/issue3488-credential-status.test.ts — new case: boot audit walks the global chain on a JSONC file; 8/8
  • tests/issue3572-client-draft-parse.test.ts — new: strict-JSON fast path, comments/trailing commas, string literals containing ///*//,] survive, malformed text throws, WEB_CLIENT embeds + executes the same parser
  • tests/web-routing.test.ts, tests/issue3572-jsonc-config.test.ts, tests/issue3572-web-jsonc-config.test.ts — all green; tsc --noEmit and npm run build clean

ework-agent added 4 commits October 18, 2026 17:47
A self-heal origin fetch started under activation N could resolve after
the agent was re-activated (originGen bumped), and its stale origin was
written unconditionally into the live register — the same class of bug
as #3616, reachable through the bootstrap guard's return value. Snapshot
originGen before the fetch and drop the write when the world moved on.
A post-giveUp revival is still allowed by design (#983): only the gen
check is added, giveUpSeq is deliberately not consulted.
logColdLoad printed session.stats.tokensSaved, but since #2734 nothing
in the tree increments that counter, so the line always showed a stale
zero (tests hand-set 42000 to fake it). Read the kernel's live counter
state.stats.compressionCount instead — it starts at 0, is bumped on
every fold, and round-trips with the persisted state.
auditStartupSummaryCredentials read the config file with strict
safeReadJson, so a JSONC config (accepted by the runtime loader since
#3572) logged a bogus parse error and silently skipped the global
external-summary chain at boot. Route the boot audit through
loadConfigFile, which uses the tolerant parser and never throws. The
per-route chain already went through loadRoutes and was correct.
The server accepts JSONC since #3572, but the web client still strict-
parsed the draft in five places: quick-config hydrate, freshDraft,
summary hydrate read(), save-quick and save-file. A user with a JSONC
config saw the quick panel vanish (#3488) and could not save. Add one
tolerant parser (strict JSON first, then comment/trailing-comma
stripping) defined once in the TS module, inlined into the browser IIFE
via toString(), and used by all five call sites. A genuinely broken
draft still throws locally and the server's parseBiliConfig remains the
authoritative check on save.
@ranxianglei ranxianglei changed the title fix: v0.1.200 review follow-ups — self-heal guard, cold-load counter, JSONC audit + web editor [PR] fix: v0.1.200 review follow-ups — self-heal guard, cold-load counter, JSONC audit + web editor Oct 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-18_pr3668-review-fixes (ed14be9)

Option A — Install this exact build (recommended)

npm install -g [email protected]

This exact version is immutable and reproducible. The rolling pr tag tracks the newest test build across all PRs.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr3689.tgz
npm install -g package

Install instructions are refreshed on each push.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

查重: 不重复。检索了 open+closed 的 issue/PR(关键词:self-heal origin re-attach / maybeRetry generation、JSONC web editor quick panel、cold-load counter、credential audit JSONC)——无同签名条目。本 PR 引用的 #3616/#3572/#3488/#2734/#983 是它修复所依据的历史条目,不是并行工作;#3668 是被 review 的 v0.1.200 release PR,本 PR 是其 review follow-up,方向不同。

标签: bug + dsh + scope/wiring + p2(四项均为 v0.1.200 review 发现的缺陷;最重的一条是 dsh-native 自愈在 re-attach 后可能把死 origin 写进 live register,属客户端接线层;均可用但有明确问题 → p2)。

开始独立审核:已拉取分支 2026-10-18_pr3668-review-fixes(4 commits, 8 files, +296/−24),正在逐段通读 diff、核对回归测试与 CI 状态,结论稍后按八问体例给出。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

PR #3689 review 结论(v0.1.200 四项 review follow-up)

四个修复逐一独立核验(读 diff + 核对上下游机制 + 本地定向测试),全部成立。

结构化八问

  1. 是什么问题:v0.1.200 review 留下的四个独立缺陷——dsh native self-heal 可能把死掉的旧 origin 绑进活注册表(dsh attach mode test intermittently fails on Windows CI: the async recovery flow reverts the registered origin back to i | dsh attach 模式测试在 Windows CI 偶发红:异步恢复流程把注册 origin 改回旧值(测试隔离竞态) #3616 同类);冷加载诊断打印一个早已没有写入方的死计数器;启动期 external-summary 凭据审计用严格 JSON 读配置,JSONC 配置被静默跳过全局链审计(JSONC doc examples vs bare JSON.parse loader — copying the docs silently drops the config | 文档示例是 JSONC(含 // 注释),loader 却用裸 JSON.parse——照文档抄配置会静默失效 #3572);Web 编辑器五处严格解析草稿,JSONC 配置导致快捷面板消失且无法保存(External summary credential feature entirely unusable + fully opaque failures + no retry | 外部摘要(externalSummary)凭据功能整体不可用 + 失败全程黑箱 + 无重试 #3488)。
  2. 什么原因导致的:①bootstrap 的 generation 守卫只保护自己的写,返回值流进 maybeRetry 的 .then 后无守卫落库;②fix(web): derive tokensSaved from active blocks; label frozen context/ledger windows #2734 删掉了 tokensSaved 最后一个写入方,日志行没跟上;③④都是 JSONC doc examples vs bare JSON.parse loader — copying the docs silently drops the config | 文档示例是 JSONC(含 // 注释),loader 却用裸 JSON.parse——照文档抄配置会静默失效 #3572 只改了服务端解析、漏了审计路径与浏览器端。
  3. 影响范围与严重程度:①仅 dsh native 插件模式「代理死亡→用户重新激活」的竞态窗口内触发,触发后该会话所有工具调用打到死 origin(p2,需绕行重启);②纯诊断日志失真,无功能影响(p3);③④仅影响使用 JSONC 配置的用户——启动审计静默缺失 / Web 面板不可用(p2,特定条件下不可用但可绕行:去注释或重启前手改)。
  4. 怎么修复的:①fetch 前快照 originGen,落地时世界已变则丢弃写入(只加 generation 检查,不碰 giveUpSeq,[dsh] native proxyEnvOrigin() 把临时 origin 冻结进 BILLION_CONTEXT_PROXY,绕过 ensureProxyRunning() 的 instance 验活;工具调用全部 fetch failed,需重启宿主 #983 的 giveUp 后复活语义完整保留);②改读 kernel 活计数器 state.stats.compressionCount(每次压缩 += blocksCreated,随持久化状态往返);③审计改走 loadConfigFile()(容错解析器,永不抛,严格 JSON 文件走原快速路径零变化);④一个容错解析器(strict JSON 优先→注释/尾逗号剥离,字符串感知、长度保持)定义在 TS 模块里,toString() 内联进浏览器 IIFE,五处调用点统一换用,单一实现可被测试直接导入。
  5. 是否有回归问题:逐项审过触碰路径的既有行为——
    • dsh-native:baseless self-heal 仍照常 arm;apply() 世界切换/off-mode/giveUp 复活均不受影响(guard 只查 originGen);被丢弃的过期落地不会造成永久卡死——重试计时器/下次工具调用会在当前世界重新 arm 飞行,孤儿 spawn 的代理可被 ensureProxyRunning 实例发现接管;热路径无变化(只是 in-flight fetch 的回调多一个判断)。
    • persist:纯诊断日志,无行为面。行为变更披露:冷加载日志字段 savedTok <n>(恒为 0 的死值)→ compressions <n>(真实计数),warn 行同改;旧值恒 0 无信息量,新值才是真计数,属修复本身而非漂移。
    • 启动审计:严格 JSON 配置文件走 loadConfigFile 的 strict-first 快速路径,解析结果与旧 safeReadJson 完全一致;ENOENT→{}、坏文件→loud error+缓存 {} 的表面不变;唯一副作用是 unknown-key/inert-key 警告可能在审计时点提前出现(签名去重、幂等,运行时 loader 本来也会打同样的警告)。route 级链本来就正确,未动。
    • Web 客户端:strict JSON 草稿走快速路径结果不变;真正坏掉的草稿仍在本地抛错(同样的 toast/return 路径);保存时服务端 parseBiliConfig 仍是权威校验,未动;其余 JSON.parse 点(localStorage/美化打印/归一化)刻意保持严格;WEB_CLIENT 通过 new Function 编译 + vm 沙箱执行(web-i18n 等既有用例不注入任何全局对象,新增函数不引用任何全局)。一个已声明的小偏差:客户端比 jsonc-parser 多容忍「closer 前的孤立逗号」({,}→{}),测试注释里写明无害——保存时服务端按原文拒绝。
    • 高危模式逐项:无语义漂移、无 fail-fast 变吞错、无阈值/时序变化、无缓存/重试策略变化。
  6. 是否破坏缓存:不涉及。持久化格式未动;compressionCount 是既有持久化字段(测试钉死了 seed 42 → 冷加载读出 42 的往返)。
  7. 是否改了设计方向:不涉及。四处都是把已有契约(generation 守卫、kernel 统计、容错解析、服务端权威)补到漏掉的路径上。
  8. 是否引入了新的配置:不涉及(config-surface-guard CI 绿)。

测试有效性:四个新用例都有牙——①reset 到新 world 后释放 in-flight 的 stale 落地,断言 register.base 仍是新 origin(修前必挂);②seed kernel 计数器 42 后断言日志 compressions 42(修前恒 0);③JSONC 配置文件断言审计仍报 AUDIT_A is not set(修前 0 problems);④直测解析器(含字符串内含 //、*/、,]、转义引号存活)+ 从 WEB_CLIENT 字符串里抽出内联副本实际执行比对行为,负向行齐全(malformed 抛错)。

验证记录:本地定向跑 PR 列出的全部 7 个测试文件 95/95 绿;另单独跑了本次 CI 红掉的 tests/lane-decisions-matrix.test.ts 本地 58/58 绿。CI 在 head ed14be9 上 43/44 绿(typecheck/build/static-gates/kernel-guard/lane-guard/config-surface-guard/e2e 全套均绿),唯一红的 test (windows-latest, 22, 2):fail 0 / cancelled 34,挂点是 lane-decisions-matrix 第 1740 行「Promise resolution is still pending but the event loop has already resolved」——与本 PR 改动文件无机制关联(dsh-native 的 in-flight 回调 / persist 诊断 / 启动审计 / Web HTML),且与已知 flake 家族完全同号:#3602(Windows CI lane-decisions-matrix 偶发 teardown 挂起,随机把 PR 打红,已 close 归档)、#3530 同族,修复 PR #3563 在途(win22 drain-cancel recovery)。我已对该失败 job 触发 rerun-failed-jobs,结果出来补一条。

判定:四项修复方向、实现、测试均成立,无回归、无缓存破坏、无配置面变更;唯一红 lane 为在途修复中的已知 Windows flake。rerun 转绿即可合;若 rerun 仍红且挂点相同,按 #3563 合入前的既定处置对待(重跑或等 #3563),不阻塞本 PR 的合入判断。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

(ai: vllm-qwen/qwen3.8-27b)

补一条:已触发的 test (windows-latest, 22, 2) rerun 转绿(run 39116744977 completed/success),坐实上一轮的判断——该失败是 #3602/#3530 家族的已知 Windows teardown 挂起 flake,与本 PR 无关。至此 head ed14be9 上全部 CI lane 绿。

最终判定不变:可合(合并动作按规矩留给你)。

@ranxianglei
ranxianglei merged commit 65d60cb into master Oct 18, 2026
63 of 64 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

📦 Merged Build Published

This merge to master was published as 0.0.573-master.65d60cb (rolling master tag).

npm install -g [email protected]  # this exact build
npm install -g billion-context@master  # always the newest merged build

npm view billion-context@master prints the current version at any time.

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