Skip to content

[PR] feat: invariant judge GA — default-on L1 advisory, egress chokepoint, loop continuity, bounded exemptions (#3938 PR-A) - #3944

Merged
ranxianglei merged 4 commits into
masterfrom
2026-10-20_invariant-judge-ga
Oct 20, 2026
Merged

ranxianglei merged 4 commits into
masterfrom
2026-10-20_invariant-judge-ga

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

(ai: zhipuai-lb/glm-5.3)

Part of #3938 (PR-A step of the ladder; judge promotion) — the umbrella stays open for PR-B/C/D. Rebased from #3866 (its two content commits are the first two of this branch).

这是什么

把 #3866 的 I1/I2 出站不变量判官从「测试专用、默认关闭」升级为「默认开启的 L1 advisory」,并补齐 #3938 拍板的三件事:判官挂到真正的出口字节上、补上 loop 车道、给豁免清单上计数封顶。纯观测层:只记日志(warn/debug),绝不阻塞流量。

改动

  1. 默认开启(Unified Prefix Cache Fix: Transactional Folding Boundaries + Single Exit Arbiter (Global Tracking) | 前缀缓存统一修复:折叠边界事务化 + 出口单一判官(总跟踪) #3938 决策②「全量不采样」):违规 warn、干净判定 debug。新增开关 diagnostics.invariantJudge(默认 true)/ BILI_INVARIANT_JUDGE=0 静默(CONFIGURATION en+zh 已同步)。
  2. 判官移到通用出口汇合点(src/server/relay.ts noteForwardedBody 块):判的是 compat-role / steering / chain-stamp / shed 改写之后的真实出站字节,替换 handle.ts 里判改写前快照的旧挂点。
  3. loop 车道连续性判定(src/loop/core.ts fetchUpstream):loop 第 2+ 轮没有客户端入站,I1 的入口基准 = 上一轮出站;取证截断/超限的 body 自动跳过(不误报)。抓的是「循环内重建改写历史」这类 seam。
  4. [design] Pin cache stability with two outbound invariants: no-fold ⇒ exit only appends a tail; fold ⇒ bytes before the f | [design] 用两条出站不变量定死缓存稳定:无折叠=出口只多尾部,有折叠=折叠点前字节不动(证明式断言 + 属性/SMT 搜索分层) #3842 具名计数封顶豁免清单:carrier/reasoning/crush 豁免量随每个判定输出(exempt 台账),超过默认 128 即 exemption-overflow 违规 —— 防止缺陷伪装成豁免。
  5. 三线 e2e:openai + anthropic + google 三条 wire 真实走代理:合法增长零误报 + 注入缺陷必响。

Config surface

测试

边界(有意不做,留给后续)

awork and others added 3 commits October 20, 2026 17:07
…und cores (#3842)

Reconciles inbound vs outbound message cores on the live request path to enforce two cache-stability invariants machine-checkably: I1 (no fold) requires every inbound message to reappear at egress in order, core-identical, modulo tail growth plus a closed exemption list (chain carriers, acp_summary carriers, reasoning drops, crush envelopes); I2 (fold) confines all divergence to [earliest fold coverage .. end) with the frozen prefix identical and the carrier position pinned.

Exit cores are re-parsed from the exact outbound body through its own wire codec, so the comparison reflects what crossed the wire and is wire-neutral (same-wire and cross-wire unified via the kernel canonical core). Render-tag scaffolding (renderTags=text-only) is normalized away on both sides, so the exemption list closes without documenting a carve-out.

The judge is advisory and disarmed by default (zero hot-path cost); it is armed in tests today, and production arming on real traffic is deliberately left as an owner decision (perf/event-noise tradeoff and the point at which a config knob would enter). CI enforcement is active: a seeded host-behavior generator (append/edit/retry/model-switch/restart) drives the real proxy through the judge with zero false positives, and injected rewrite/reorder/drop/mid-insertion faults are all caught.

Tests: unit oracle (positive controls + five-shape negatives + fold boundary) and a real-proxy e2e generator + defect fixtures. Fixes nothing upstream; the referenced defects (#3805/#2483/#3691/#3769/#3676) stay scheduled separately per the issue.
…entity (#3842)

Review findings on the I1/I2 judge (PR #3866):

- The call site sat right after runPrepare(), BEFORE preflight compression.
  A fold-CREATING request was judged on its pre-fold bytes, so I2 never
  reconciled the one traffic class it exists for. Move the call to the
  resolved prepared value (after preflight / reforge), where prepared.body
  is the exact byte stream relayed upstream.

- The scan skipped every exit carrier while the entry side only skipped
  reasoning: a stateful host that re-sends previously-injected acp_summary /
  chain-checkpoint carriers false-positived on every steady-state post-fold
  turn (even entry==exit). Carrier entries now match their own twin by
  identity, and the gap budget counts non-carrier elements only.

- The sink delivered violations only, so folded-but-clean verdicts were
  invisible and the live I2 path could not be asserted. Every judged
  request now reports its verdict (test-only surface; prod stays disarmed).

Tests: unit fixtures for carrier echo (summary + chain), five-consecutive
carrier gap, and the carrier-text-drift design boundary; e2e gains a real
preflight fold through the live path (tiny window) - zero false positives
across the folded stream, and post-fold prefix corruption fires.
…ontinuity; bound the exemption list (#3938 PR-A)

- Arm by default (#3938 decision 2): violations log at warn, clean verdicts at
  debug, never blocks. Knob diagnostics.invariantJudge / BILI_INVARIANT_JUDGE=0
  to disarm (CONFIGURATION en+zh).
- Move the main-lane hook from the pre-send site (handle.ts) to the universal
  egress chokepoint (relay.ts noteForwardedBody block): judges the EXACT bytes
  after compat-role / steering / chain-stamp / shed rewrites.
- New loop-lane continuity check (loop/core.ts fetchUpstream): rounds 2+ have
  no client inbound, so I1's entry ground truth is the previous outbound;
  clipped/oversized forensics silently skip.
- #3842 count-bounded exemption list: carrier/reasoning/crush volume rides
  every verdict (exempt ledger) and beyond the cap (128 default) is itself an
  exemption-overflow violation.
- e2e now proves all three wires live (openai + anthropic + google): zero
  false positives on legitimate growth, teeth on injected mid-history defects.

Rebased from #3866 (its 2 content commits ride as the first two commits of
this branch).
@ranxianglei ranxianglei changed the title feat: invariant judge GA — default-on L1 advisory, egress chokepoint, loop continuity, bounded exemptions (#3938 PR-A) [PR] feat: invariant judge GA — default-on L1 advisory, egress chokepoint, loop continuity, bounded exemptions (#3938 PR-A) Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-20_invariant-judge-ga (2dc06a4)

Option A — Install this exact build (recommended)

npm install -g billion-context@0.0.4701-pr.3944.df0c88a

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-pr3944.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)

查重: 不重复。 #3866 是本 PR 的前身(同一判官的「测试专用、默认关闭」版;本分支前两个 commit 即其 rebase),两者是演进关系而非平行工作——本 PR 合入后 #3866 应以 superseded 关闭(留待 owner/作者处置)。#3938 是总跟踪 issue,按设计保持 open 给 PR-B/C/D,不构成重复。无其他在途 PR 触碰同一出口判官面。

标签: pr / scope/wiring / p3(纯观测层特性——只加日志不改流量,挂点在出口协议接线层;非缺陷类)。

正在做完整 review:分段通读 diff(9 文件 +936/-4)、核查 CI、本地跑定向测试。结论按八问体例随后补上。

…ION en/zh (#3944)

Review fix for #3944: the config-surface-guard / docs-coverage / docs-sync gates
failed because the CONFIGURATION tables were hand-edited while the single
source of truth (website/config-reference/*.yaml, #2107) got no entry.
Add the diagnostics.invariantJudge seed entry and regenerate both doc
tables from it. Net effect vs the previous commit: wording drops backticks
(generator constraint), and the BILI_INVARIANT_JUDGE env row moves to its
alphabetical slot. No behavior change.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

审核结论

方向正确、实现扎实、测试有牙。审核中发现 1 个阻塞问题(CI 红)——已直接修掉并推送到本分支(独立 commit 2dc06a445)。待 test lanes 全绿后可合并(合并由你操作)。

我做了什么

  1. 全 diff 分段通读(9 文件 +936/-4),对照 origin/master@1cec7add9a98(= merge-base,分支新鲜)做既有行为清点。
  2. CI 红根因——本地复现三个红 gate(config-surface-guard / docs-coverage / docs-sync):CONFIGURATION 表是从 website/config-reference/*.yaml([docs][website] 配置文档单一事实源:从声明式 schema 生成 CONFIGURATION.md 与网站 /docs/(一步到位) #2107 单一事实源)生成的,PR 手改了生成物却没加 seed 条目。更关键的是 ci.yml:206/251 的 test job needs: doc gates——所以原 head 的全部 test lanes 是被 skip 的,测试套件根本没跑过。
  3. 修复(commit 2dc06a445,docs only):补 seed 条目 diagnostics.invariantJudge(复用你的文案;生成器禁 backtick,措辞微调)+ 重新生成 en/zh 两表(BILI_INVARIANT_JUDGE env 行移到字母序位)。本地验证:三 gate 全绿、generate 幂等、build 绿、定向测试 28/28(unit 23 + e2e 5)全绿。
  4. 代码级核实要点:

回归清点(diff 触碰路径的既有行为)

既有行为 结论
请求热路径字节 保持——判官 observe-only、try/catch 隔离、不改字节、不抛入管线
日志量 有意变更:每笔请求新增 debug 行(干净判定)+ warn(违规)——功能本身,PR 已披露
配置面 纯新增 key/env,无既有键语义变化;config surface 节合规
kernel/ · version · update.ts · 持久化/wire shape 未触碰(kernel-guard/version-guard 亦过)
默认开启 = 行为变更 旧:test-only 默认关 → 新:默认开、全量观测。#3938 决策②明确批准,PR 已披露

八问

  1. 是什么问题:不是修缺陷,是补能力——Unified Prefix Cache Fix: Transactional Folding Boundaries + Single Exit Arbiter (Global Tracking) | 前缀缓存统一修复:折叠边界事务化 + 出口单一判官(总跟踪) #3938 统一前缀缓存修复需要一个运行时观察者,证明「出站字节 = 客户端历史 + 合法差集」。
  2. 什么原因导致的:[PR] feat: add I1/I2 outbound-invariant judge for cache-stability attribution #3866 的判官存在但默认关、挂在改写前快照上(判错对象)、缺 loop 车道、豁免清单无界。
  3. 影响范围与严重程度:所有代理请求新增一个同步观测步骤;严重度=内部实现级——绝不阻塞流量,最坏情况是多一条误报 warn 或多一点 CPU。
  4. 怎么修复的:判官移到通用出口汇合点判真实出站字节;入口基准=客户端入站历史(loop 车道=上一轮出站);合法差集=尾部追加 + 具名计数封顶豁免(>128 即违规,防缺陷伪装成豁免)。
  5. 是否有回归问题:未发现(见清点表)。重试/重发路径未被判官覆盖 = 覆盖缺口而非回归,已记入 Unified Prefix Cache Fix: Transactional Folding Boundaries + Single Exit Arbiter (Global Tracking) | 前缀缓存统一修复:折叠边界事务化 + 出口单一判官(总跟踪) #3938 清单。
  6. 是否破坏缓存:否——不触碰任何缓存/去重/游标机制;cache-proof 7 剧本×4 线在默认开状态下全绿为作者侧实证,CI test lanes 将再验。
  7. 是否改了设计方向:否——纯观测层,现有数据流加一个消费者;side 车道不判(合成请求无入站基准,I1 必误报)是有意的,已在 Unified Prefix Cache Fix: Transactional Folding Boundaries + Single Exit Arbiter (Global Tracking) | 前缀缓存统一修复:折叠边界事务化 + 出口单一判官(总跟踪) #3938 记录。
  8. 是否引入新配置:是——diagnostics.invariantJudge(boolean,默认 true)+ BILI_INVARIANT_JUDGE(0/false/off 关停);纯新增,无迁移。

后续项(不阻塞,已记入 #3938 清单)

主车道体积守卫(每请求全 body 重解析,#3128 后多 GB 请求合法)· 重试/重发路径判官覆盖 · 判官内部异常可见性(现空 catch 静默失武)· snapshot-render D 车道交互确认(rollout >0% 时)· 马拉松会话 reasoning 溢出边缘。

CI 状态与判定

新 head 2dc06a445:doc gates 已绿(config-surface-guard ✓ docs-sync ✓,docs-coverage 跑的就是我本地验证过的同一条命令),test matrix(ubuntu 22/24 × 3 shards + windows 22 + static-gates)排队运行中。全绿即可合并;合并后建议把 #3866 按 superseded 关闭(它的两个内容 commit 就是本分支前两个 commit)。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

CI 全绿,可以合并

新 head 2dc06a445(含 docs 修复 commit)的完整 CI 结果:

  • test matrix 全部通过:ubuntu 22 × 3 shards、ubuntu 24 × 1、windows 22 × 2 —— 6/6 success(上一轮被 doc gates 卡住而整批 skip 的测试套件这次真实跑过并全绿);
  • static-gates(ubuntu 24 + windows 22)、config-surface-guard、docs-sync、docs-coverage(经 gate job)、kernel-guard、version-guard、lane-guard、lock-sync、test-import-graph、unused-exports 等全部 success;
  • skipped 的均为 env 门控的真实客户端 e2e 车道(ACP_TEST_E2E 等),与 master 行为一致。

PR 状态:open / mergeable / 仅等你合并(agent 不能合 PR)。

合并后建议:把 #3866 按 superseded 关闭——它的两个内容 commit 就是本分支的前两个 commit,留着只会造成「两个 PR 修同一件事」的误读。关闭说明写一句「已并入 #3944 并 GA」即可。

@ranxianglei
ranxianglei merged commit 71d0721 into master Oct 20, 2026
46 checks passed
@ranxianglei
ranxianglei deleted the 2026-10-20_invariant-judge-ga branch October 20, 2026 14:21
@github-actions github-actions Bot mentioned this pull request Oct 20, 2026
@github-actions github-actions Bot mentioned this pull request Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant