Repository navigation
[PR] feat(fastpath): v6 composite-identity incremental fastpath lane (full rework, #5576 line voided) - #5652
Conversation
schema v11 (three append-only sidecar tables: pf_rows data plane + pf_log/pf_ckpt metadata plane), UnifiedStore SQL methods (probe/meta/ commitTurn single-transaction double-plane/compact/hydrate/deleteAll), UnifiedShadow passthroughs (mysql backend = null soft-degrade), SessionStore facades in persist.ts. Raw host ids stored untruncated (P9); state = fold(ckpt, log-after-ckpt) (P7); zero trace on mid-turn crash via transaction rollback.
msgid-identity-driven fastpath rework per contract issue #5643 (old #5576 line voided): server-minted pf_sid worlds keyed by (sessionid,msgid) pairs, pure set-difference judgment over a FULL element id list, scattered NEW-span parse with _N/wireIndex absolute rekeying against the whole ledger, client compression ignored (NEW may sit anywhere), and a hard identity pre-gate that REJECTS with zero side effects on channel/malformed/width/consistency faults (no silent legacy fallback, no count guessing, no signature fallback). - fastpath-v6.ts: evaluateWatermarkV6/finalizeWatermarkV6, matching rules (echo O(1)+spot-check / composite probe / mint+arm), world mirrors (LRU-cached fold of ckpt+log, never ahead of disk), pending single-transaction commits (pf_rows + pf_log together), breaker 5-strike / 60min parking with memory-first guard state, opportunistic L1 compaction in finalize, hydration path with S4 checksum aborts. - rollout: new feature watermarkV6MsgId percent:0 (default OFF), nested under pluginFullResendWatermark bucketing. - headers: x-bili-pf-session added to the upstream hop filter. - prepare-openai: v6 evaluated before the v5 watermark lane (silently falls back when not engaged); V6Hit consumes the same field-rebuild path; finalize branches by evaluated source; snapshot pin skips the empty window of a no-progress hit. - handle: FastpathV6IdentityFault mapped to a 400 JSON refusal at the prepared-pipeline call site (supresses raw forward); overflow refold fails open. - storage facade completion: pfNeedsCompaction delegation through UnifiedShadow/SessionStore (soft degrade when sidecar unavailable).
…ho (#5643) The chokepoint now rides the FULL captured element id list (one percent-encoded segment per body element, body order, literal comma separators) instead of the k-1 tail slice — the v6 server judges NEW by set difference and the count claim keeps its last-stamped meaning for v5 lanes. A learned x-bili-pf-session (server-minted world id) is echoed back once received. Count-only mode (stamp known, nothing captured) still emits exactly x-bili-pf-count as before. MAX_IDS raised to 16k elements for long-hostory conversations.
…ectations New tests/fastpath-v6-msgid.test.ts covering the #5643 matrix rows: pure-append increment with frozen-core byte-parity vs full parse, '?'-free full lists, cold-start arming via baseline pass, compaction as pure ignore (forward-only view, summary judged only by ids), scattered NEW parsing, identity-boundary re-mint with old-world archive retention, three restart cycles across an L1 fold (hydration oracle), echo-header O(1) matching, carrier rotation, fault classes (incomplete/malformed/width/zero-resolve echo) with 5-strike parking and time-travel recovery, cap handling, and session-deletion cascade cleanup. Schema-head dependent suites updated for STORAGE_ SCHEMA_VERSION 10 -> 11 (v11 adds pf_rows/pf_log/pf_ckpt).
📦 Built Package ArtifactBranch: Latest build — install this exact versionnpm install -g billion-context@0.0.8426-pr.5652.5f10985This exact version is immutable and reproducible. The rolling Recent builds (commit → version)
Download artifact
tar xzf billion-context-pr5652.tgz
npm install -g packageInstall instructions are refreshed on each push. |
(ai: vllm-qwen/qwen3.8-27b) 查重:不重复。 本 PR 是契约 issue #5643(镜像 #5645)的唯一实现 PR;open+closed 检索(fastpath / msgid / identity lane 关键词,近 7 天为主)未发现其他在途的 v6 实现。相邻线谱确认:#5576/#5578/#5579(v5 身份门线)已按 owner 裁定作废关闭、代码未移植(与本 PR 声明一致);#5575(M1 观测层)与本 PR 明确正交(本 PR 不含 M1);#5573(设计文档 issue)作为背景参考保持打开。 标签: 开始深度审核:基线已核(PR base = 当前 master tip 23a826d,零落后,无 stale-base 风险),diff 总览 19 files / +2033/-59。下一步读 #5643 契约全文对照 P1–P9,再逐文件精读 + 回归清单。结论稍后按八问体例给出。 |
|
(ai: sglang-gpu0/qwen3.8-27b) 总体结论:GO(附一项合并前必须落地的 wire-form 修订,已按 owner 裁定定稿)——结构面扎实:前代 B1 hydration 陷阱已被 §8-16/19 测试钉住、config surface 章节齐全、base 新鲜。证据均为本机实测(Node v25.9.0,@edba38af9→5db091e23),目标测试本地亲跑 22/22 绿。 F1 wire form 修订(owner 裁定 2026-11-04,本 PR 内落地后可合)发现与机制链(保留作记录):
owner 裁定(定稿形态):
F2 MAJOR(契约 vs 实现张力,待 owner 一句话):"?" 占位槽位 = 潜在永久 reject loop
F3 已在评审期间被作者修复(commit 5db091e,已验证)CI unused-exports 红(clearWatermarkV6 零引用)由作者推 5db091e 修复(保留函数 + 测试 teardown 钉清理契约)。本地 @5db091e23 复验:unused-export gate clean / tsc clean / fastpath-v6 + pf-channel 22/22 通过。 MINOR(记录不动手)
Clean 区(读过确认):identity hard gate 对 echo fabrication / cross-world probe 的拒绝;recordFault guard 写先于 throw(§8-12 零副作用成立);cohort admission 与运行时故障分离;config surface 章节完整;base = live master tip;kernel 未动;restart-hydration(B1 钉)本地实跑绿。 流程注记:feat + wire 面,人合并区,不 auto-merge;CI 以 5db091e 之后的新波次为准。 |
… F1) x-bili-pf-tail-ids now carries ONLY the last PF_TAIL_WINDOW (64) element ids; server width gate becomes min(window,T); over-window lists are a format-class refusal in the strict decoder; the lane stops reading x-bili-pf-count (v5-only). The ledger keeps rows for out-of-window prefixes WITHOUT identity — an explicit honest coverage boundary, not a silent guarantee. New tail-window regression suite: long-history arm (honest-boundary probe miss + cross-edge _N parity), width discipline (over/under faults counted), and the demanded whole-rewrite matrix line (with-echo fault storm → park vs without-echo legal re-arm with archive preserved). Closes part of owner ruling 2026-11-04 on PR #5652 review (#5643).
|
F1 landed:
F2 待 owner 一句话:证据倾向 dsh/opencode/pi 的 msgId 信封不保证 post-compaction 全元素有 id(opencode 无 id 槽显式空串、dsh summary/persona 走保留前缀被滤出)。若属实推荐 §3.2 容错条款='?' 轮 soft-miss 落基线(不扣 breaker)、下一健康轮自愈;若能保证则降 minor(emitter 改有洞即清全表+负面测试行)。两条路都不动数据面,拍板后再动 emit 端那一处。 |
(ai: vllm-qwen/qwen3.8-27b) CI 自动修复车道 · 七问总结(本轮全部动作)
收工判定:当前 head |
…ole captured table ('?' never travels)
Owner ruling on the PR-review F2 question: proceed on the guarantee
branch (hosts keep EVERY element id-bearing post-compaction). Consequence
per the review: an id-less or invalid slot ANYWHERE in the span now clears
the stored table wholesale instead of riding as a '?' placeholder — the v6
hard gate treats '?' lists as malformed, so honest absence degrades safely
(v5 count-only) instead of poisoning the lane with a partial slice. The
PF_SLOT_UNKNOWN token is gone from the v6 capture path entirely (fastpath.ts
keeps its own for the v5 lane). Negative line: mixed spans emit no
tail-ids at all and the table re-arms once resolution goes fully healthy
again. If source analysis disproves the guarantee (issue filed for dsh /
opencode v1+v2 / pi), the sanctioned fallback is the contract §3.2
tolerance clause ('?' turns soft-miss without breaker strikes).
|
F2 closed on the guarantee branch (owner ruling): 按裁定"压缩后也有 id"落地:
至此评审 F1+F2+M1+M2 全部处理完毕,PR 可进回归。 |
A failed arm registration (geometry mismatch / element transform failure / pfCommitTurn null) left x-bili-pf-session in the response headers while the plane holds nothing for that sid. The client's next-turn echo then hits 'echo references unknown pf_sid' -> identity-fault 400 five times in a row -> 60min breaker park, from a single transient plane hiccup at arm time. Drop the echo on every arm failure exit; keep the honest seq stamp so the client keeps learning T. Regression pin added in tests/fastpath-v6-msgid.test.ts (#5643 review finding).
Two review pins for #5643 matrix coverage gaps: (1) a failed arm commit hands out no world id and the next turn re-arms cleanly with a fresh sid instead of fault-looping into a park; (2) store.removeSession cascades every registered world through the in-TX session_ext registry sweep (pf_rows/pf_log/pf_ckpt all emptied) -- the real deletion path the facade-only pfDeleteForSession test does not exercise.
(ai: vllm-qwen/qwen3.8-27b) PR #5652 审核完成:方向正确、实现扎实;审核中发现 1 个真实缺陷已修复推入分支,1 个可用性隐患经你并行提交的 tail-window 改造后已在源头消除(我准备的服务器端配套改动不再需要、未推);另有 1 项契约偏差待你拍板(单独一条 🏷 决策评论)。 审核过程:通读契约 #5643(P1–P9、§4/§4.1 存储设计、§8 测试矩阵 22 行)→ 全 diff 逐文件精读(19 文件 +2033/-59)→ §8 矩阵逐行对账 → 本地定向验证(tsc / fastpath 家族+pf-channel+rollout 共 73 用例 / unused-exports 门禁 / Node 头部上限实测)。你期间推了 4 个 commit(tail-window wire form、clearWatermarkV6 pin、rollout pin、F2 guarantee branch),我的修复已 rebase 到最新 head。 已推入 PR 分支(基于 8375702,两个独立标注 commit):
未推入(弃用说明): 我原本准备把主代理 createServer 的请求头上限从 Node 默认 16KB 提到 2MB。实测背景(node 22.23.2):默认上限下 >16KB 的头部直接 431、无任何日志;旧的 full-list wire form 下长会话必然撞线——且 pf-channel 发列表不受 v6 开关控制,v6 关着也受影响。但你的 da6885d 把列表改为固定 64 槽尾窗后,典型 msgid 长度下头部 ≤~3KB,源头已解决;再抬全服务器上顶属于不必要的行为变更,故不推。(理论极端 64×512 字符 ≈33KB 仍超默认上限,实际宿主 msgid 达不到这个长度;如要零风险可加 回归审查(触碰路径的既有行为逐项结论):
行为变更清单(旧→新 + 原因):
测试有效性: 断言有牙——核心判定用与 openaiToCore 全量解析结果的字节级 deepEqual 作 oracle(_N 编号一致);故障行断言零副作用(三表/ext/水位全部不动)+ 计数器递增;B1 trap 有重启 hydrate 字节一致钉;banned-kind(hide/replace/archive)缺席断言防词汇回归。缺口(均不阻塞,建议后续跟踪):§8-13 承诺的 drift warn 诊断未实现(骑旧核由构造自然成立,诊断缺失);§8-17 seen-cap 2048 截断未钉;block/unarm 条目未写(契约 best-effort 逃生条款允许——「宁可视图多给」,折叠区由 kernel fold 管道继续治理,idx_pf_rows_core 暂闲置);§8-19 单轮重启而非跨 L1 折叠三轮。 CI: head 8375702 运行中——static-gates(ubuntu24)/mysql-contract/gate/version-guard 已绿,9 个 test shard 在跑,完成后跟帖。原红(unused-exports: clearWatermarkV6 死导出)已由你的 5db091e pin 解决,本地门禁验证 clean。 结构化八问:
合并判定:建议 CI 全绿后由你验收合并。 feat + wire 形态 + 存储 schema v11 + rollout → 按 §7.4 属必须人工类别,我不能自动合并;审核视角方向、实现、测试均已过关,我的两处修复已推入,待拍板一项(见下条评论)不阻塞合并。另:PR 正文的 wire form 描述仍是 full-list 版本,与 da6885d 的 tail-window 不一致,建议合并前更新正文(作者描述我不代改)。 |
🔶 需要决策 背景一句话:PR #5652(v6 快路径)审核发现一处「实现 vs 契约」偏差——契约 §4.1.4 承诺命中轮常驻内存、不碰磁盘,实现是每轮从磁盘全量 hydrate 前缀。 待决问题:v6 命中轮每轮调用 loadWorldCores(src/server/fastpath-v6.ts:688/803),把该 world 的整个前缀从 pf_rows 读出并 JSON.parse 每个 core_json——正确性没问题(P7:缓存丢了只多付一次重载,视图字节一致有测试钉),但长会话下每轮付 MB 级 SQLite 读 + parse,与契约 §4.1.4「常驻 visible-core 数组,常路命中轮触碰数据面 0 次」及 #5403 的性能目标相悖。 选项(各带代价):
我的推荐:A。理由:功能默认 OFF(percent:0)、初始队列只有 shim 族车道、正确性不受影响;先小流量放量拿到真实命中轮规模数据,再决定常驻缓存的预算参数更稳。 不决定的默认行为:按 A 执行——该项不阻塞合并(CI 全绿 + 你验收即可合)。 附带(非阻塞,供参考):pf-channel 头注释声称头部体积 by-construction 有界、无需调 Node maxHeaderSize;理论极端(64 槽 × 512 字符 id ≈ 33KB)仍超 Node 默认 16KB 上限,实际宿主 msgid 达不到该长度。若想零风险,可在 src/server.ts createServer 加 |
(ai: vllm-qwen/qwen3.8-27b) CI 跟帖:head 8375702 全管线绿 —— 30/30 checks 通过(9 个 test shard:ubuntu/windows × node 22/24,加 static-gates×2、mysql-contract、gate、version-guard 等,0 failed)。原红项(unused-exports)已随你的 5db091e pin 解决。 PR 分支当前状态:你的 ef35c98(F2 guarantee branch)+ 我的两个审核修复(239f0a4 arm-failure echo 修复 / 8375702 测试钉)。等你验收合并;🔶 决策项(常驻核缓存 A/B)不阻塞合并,不回复则默认按 A 执行。 |
…r, not just ext creditReset touched only the advisory ext replica while readGuard is memory-first — a sound turn therefore did NOT actually clear this process's fault streak: 4 faults + 1 healthy turn + 1 more fault parked the session for 60m on a cumulative-but-not-consecutive fifth strike, violating the five-CONSECUTIVE contract (§8). Fix resets guardMem whenever a local copy exists (unconditionally — local state must not depend on replica availability); cross-boot/cross-replica semantics of the ext copy are unchanged. Regression test §8-12 pins both clear paths (hit @842 and no-progress ride @721) and is proven discriminating (fails pre-fix with early park).
ranxianglei
left a comment
There was a problem hiding this comment.
Deep review of #5652 (v6 msgid identity lane + #5664 render-snapshot lane)
Method: full read of every changed hunk (fastpath-v6.ts, fastpath-v6-render.ts, prepare-openai.ts, handle.ts, persist.ts, store.ts, shadow.ts, schema.ts, budget.ts, headers.ts, rollout.ts, dsh-native.ts, pf-channel.ts, plugin.ts, docs/site/website yaml) + eight independent hostile sub-reviews (identity lane ×2, render lane ×2, test-coverage audit, docs-vs-code truth audit, integration seams ×2 — all completed) + regression tests and one bugfix appended on this branch during review.
Verdict up front: no blocking correctness defect found in the shipped default state (both lanes gated percent: 0, OFF by default; every degrade path verified fail-safe in the direction away from wrong bytes). Five items need your adjudication below — none was patched unilaterally because each is either explicitly pinned as tracked design work in this branch or a boundary you should consciously accept.
Design items for owner adjudication (no code change made)
A1. The apply tier mixes two coordinate systems — the already-pinned F9 item is the real exposure
reconcileLegacyDiverged's fine-grained apply tier credits a changed row when covered.has(i) where i is the dense row ordinal (src/server/fastpath-v6-render.ts:813-818), but boundCoveredPositions returns ledger positions from pfLedgerIds(sid) (src/server/fastpath-v6-render.ts:881-899), consumed at src/server/prepare-openai.ts:901. The two coincide only while no leading element was absorbed into systemText — which the table comment itself pins (fastpath-v6-render.ts:150-165: "#5652 review F9 tracks the coordinate-mix correction, and this comment flips with it").
Exposure when they diverge (absorbed-leading-system bodies / any future core-element→multi-row mapping):
- shifted-down case: a genuinely fold-covered row is seen as unexplained → plane KILL (
structural divergence) — fail-safe, costs the plane availability for that session; - overlap case: an unrelated changed row lands inside the shifted covered set → credited without kernel evidence → weakens the witness guarantee (bytes still came from the wire that just succeeded; bounded by the full-pass audit).
Suggested resolution when you pick F9: build coverage in row coordinates at the capture site, or restrict the apply tier to sessions whose element↔row alignment is proven 1:1. Deliberately NOT touching this now — it is your pinned item and I did not want to race the ruling.
A2. Same root cause: rows-misaligned can go permanently red
After a witnessed rebase, dense row ordinals exceed identity maxPos under the same coordinate mix ⇒ the plane latches red forever and rides the legacy byte path (safe degradation, but the feature is dead for that sid and the reason string will confuse operators). Fixed by the same A1/F9 correction — listed separately because the operator-visible symptom differs.
A3. Please sign off the checksum scope (documented, direction-safe)
Row checksums cover the checkpoint meta, not payload bytes. A corrupted stored prefix therefore rides silently for at most N−1 green rounds (N = the audit cadence) until a full-pass round diverges and kills the plane. Bounded and terminates in kill, never in serving stale bytes to billing — but it IS "corrupt prefix served once-ish", so I'm asking for explicit acceptance rather than assuming it.
A4. Kill-permanence vs storage failure (soft-fail acknowledged, self-heal analyzed)
killRenderPlane's persistent write is try/catch-swallowed (src/server/fastpath-v6-render.ts:196-208): if storage is down at kill time, death binds only this process; the next process revives the plane until its own integrity checks re-fire. For structural-cause kills I traced that the on-disk condition survives, so the next process re-kills — acceptable. Residual: meta-only corruption invisible to captures keeps riding inside A3's window. Suggestion (either fine): add a restart re-kill test pinning the revive→re-kill path, or queue/retry the dead-row write. No change made.
A5. Rollout flag nesting — confirm intent (now pinned in code as "#5652 review F10" so nobody fixes it accidentally)
watermarkV6Render { percent: 0, base: "watermarkV6MsgId" } composes as nested-on-cohort, but the FORCE tier evaluates force(percent=0, base="pluginFullResendWatermark") against the parent plan — i.e., forcing v6 render also demands cohort membership of the other flag. This looks deliberate (force ≠ unconditional), and I pinned it with an explicit comment in src/rollout.ts (§3/§4 + RolloutPlan.base doc). If force should bypass nesting, say so and I'll flip the comment + tier.
Fixed on this branch during review (test/doc hardening + one availability-scoped bugfix)
| commit | what |
|---|---|
| 61eb805 | Pin v6 identity fault variants + client slot.v6 learn/echo/stale-retention (was untested fault surface) |
| 40a6211 | Markers render red reason: one-per-condition pins (red list was partly implicit) |
| 3ee0d46 | Docs corrected: pf_ckpt post-fold wording; exhaustive red-list stated; force-tier nesting qualified |
| 635dcb2 | Regression-pin inputEstBaseTokens base subtraction in budget math (legacy absent = byte-identical; non-usage sources ignore lastInputTokens; usage-grade baseline wins max() uncharged) |
| 27c21ed | Pin §7-A② soft-degrade node: sidecar down ⇒ lane disengages silently (never a 400), armed world untouched, reopen resumes with a hit |
| c5ecd34 | Fixed a real MEDIUM bug found in review: creditReset cleared only the advisory ext replica while readGuard is memory-first, so a healthy turn did not actually clear this process's fault streak — 4 faults + 1 sound turn + 1 more fault parked the session 60m on a cumulative-but-not-consecutive 5th strike (violates the five-CONSECUTIVE contract, fastpath-v6.ts §8). Now resets the memory mirror whenever one exists; regression test §8-12 pins both clear paths (hit + no-progress ride) and is proven discriminating (fails pre-fix). Availability-scoped defect — baseline lanes kept serving throughout; no data-plane impact. |
Remaining known-untested / hygiene (deliberately deferred, low value/risk): dead-sid exported registry listing shape; hydrate-failed permanent-red loop escalation (rides A2/A3 windows); docs could name in-body id duplication explicitly next to reorder/rewrite in the coverage-boundary note; refold cycles append 2 harmless pf_log rows each (bounded by pfCompact).
Verified OK (selection)
- Non-cohort requests stay byte-identical: the v6 gate runs first and short-circuits; the old v5 gate only executes when v6 says "not mine" (prepare-openai.ts v6/v5 ordering + rollout percent 0).
- Hard-gate 400s are produced outside the pipeline tail, which would otherwise forward the raw refused body (handle.ts refusal mapping).
- Overflow-refold double evaluation is safe end-to-end: pass #1's commit is durable BEFORE forward (finalize inside prepare), so pass #2 re-evaluates against already-committed truth → empty set-diff → no-progress ride; an accidental duplicate insert would be a rolled-back tx (ledger PK + plain INSERT), never a clobber; the refolded body is fully materialized, so a still-overflowing retry bails on byte-equal comparison and passes the original 400 through.
- Duplicate msgids cannot double-register or renumber (header-list dups rejected at parse; body-internal dups ride frozen under the documented P3 ignore boundary;
pos = maxPos+1+kstrictly increasing). _Ncontinuation numbering matches full-parse oracle byte-for-byte (content-hash base ids are neighbor-independent; occurrences counted in strict pos order);windowCorescontains ONLY new-slot cores, empty array on rides, stale-leak sweep found none (mirror+pending evicted together; missing-pending serves baseline, never a stale window).- Stamp honesty holds on every path: T always comes from a fresh server-side scan stamped identically on arm/hit/degrade/finalize; refusals carry no v6 stamp; a stale-retained client stamp is inert (width gate recomputes server-side) — worst observable case is absence, never falsehood.
- Every render-plane fault string funnels to kill-or-red; no fault path blesses bytes lacking kernel evidence, modulo A1's overlap corner and A3's window.
CI: gate jobs green on prior heads; full suite re-running on this head (local full-suite pass also in flight). Branch MERGEABLE (BEHIND master — routine rebase at merge time).
(ai: qwen/qwen3.8-27b) CI 自动修复(第 1/3 次):docs-sync 已修好并推上分支。查重:不重复——此 PR 首个 docs-sync 红,修复直接落在 PR 分支,未开新 issue。 七问:
判定:docs-sync 阻塞已解除,等新一轮 CI 确认后本 PR 侧无需再动手。 |
CI static-gates failed: 'msgs' implicitly any[] (TS7034/TS7005) — tests are typechecked under noImplicitAny. Annotate CoreMessage[] explicitly; npx tsc --noEmit clean afterwards.
Deep review of #5652 (v6 msgid identity lane + #5664 render-snapshot lane)Method: full read of every changed hunk (fastpath-v6.ts, fastpath-v6-render.ts, prepare-openai.ts, handle.ts, persist.ts, store.ts, shadow.ts, schema.ts, budget.ts, headers.ts, rollout.ts, dsh-native.ts, pf-channel.ts, plugin.ts, docs/site/website yaml) + eight independent hostile sub-reviews (identity lane ×2, render lane ×2, test-coverage audit, docs-vs-code truth audit, integration seams ×2 — all completed) + regression tests and one bugfix appended on this branch during review. Verdict up front: no blocking correctness defect found in the shipped default state (both lanes gated Design items for owner adjudication (no code change made)A1. The apply tier mixes two coordinate systems — the already-pinned F9 item is the real exposure
A2. Same root cause:
|
| commit | what |
|---|---|
| 61eb805 | Pin v6 identity fault variants + client slot.v6 learn/echo/stale-retention (was untested fault surface) |
| 40a6211 | Markers render red reason: one-per-condition pins (red list was partly implicit) |
| 3ee0d46 | Docs corrected: pf_ckpt post-fold wording; exhaustive red-list stated; force-tier nesting qualified |
| 635dcb2 | Regression-pin inputEstBaseTokens base subtraction in budget math (legacy absent = byte-identical; non-usage sources ignore lastInputTokens; usage-grade baseline wins max() uncharged) |
| 27c21ed | Pin §7-A② soft-degrade node: sidecar down ⇒ lane disengages silently (never a 400), armed world untouched, reopen resumes with a hit |
| c5ecd34 | Fixed a real MEDIUM bug found in review: creditReset cleared only the advisory ext replica while readGuard is memory-first, so a healthy turn did not actually clear this process's fault streak — 4 faults + 1 sound turn + 1 more fault parked the session 60m on a cumulative-but-not-consecutive 5th strike (violates the five-CONSECUTIVE contract, fastpath-v6.ts §8). Now resets the memory mirror whenever one exists; regression test §8-12 pins both clear paths (hit + no-progress ride) and is proven discriminating (fails pre-fix). Availability-scoped defect — baseline lanes kept serving throughout; no data-plane impact. |
Remaining known-untested / hygiene (deliberately deferred, low value/risk): dead-sid exported registry listing shape; hydrate-failed permanent-red loop escalation (rides A2/A3 windows); docs could name in-body id duplication explicitly next to reorder/rewrite in the coverage-boundary note; refold cycles append 2 harmless pf_log rows each (bounded by pfCompact).
Verified OK (selection)
- Non-cohort requests stay byte-identical: the v6 gate runs first and short-circuits; the old v5 gate only executes when v6 says "not mine" (prepare-openai.ts v6/v5 ordering + rollout percent 0).
- Hard-gate 400s are produced outside the pipeline tail, which would otherwise forward the raw refused body (handle.ts refusal mapping).
- Overflow-refold double evaluation is safe end-to-end: pass fix: keep system prompt byte-stable for prefix cache #1's commit is durable BEFORE forward (finalize inside prepare), so pass fix: address all code review findings (condense, routing, session-id, dead code) #2 re-evaluates against already-committed truth → empty set-diff → no-progress ride; an accidental duplicate insert would be a rolled-back tx (ledger PK + plain INSERT), never a clobber; the refolded body is fully materialized, so a still-overflowing retry bails on byte-equal comparison and passes the original 400 through.
- Duplicate msgids cannot double-register or renumber (header-list dups rejected at parse; body-internal dups ride frozen under the documented P3 ignore boundary;
pos = maxPos+1+kstrictly increasing). _Ncontinuation numbering matches full-parse oracle byte-for-byte (content-hash base ids are neighbor-independent; occurrences counted in strict pos order);windowCorescontains ONLY new-slot cores, empty array on rides, stale-leak sweep found none (mirror+pending evicted together; missing-pending serves baseline, never a stale window).- Stamp honesty holds on every path: T always comes from a fresh server-side scan stamped identically on arm/hit/degrade/finalize; refusals carry no v6 stamp; a stale-retained client stamp is inert (width gate recomputes server-side) — worst observable case is absence, never falsehood.
- Every render-plane fault string funnels to kill-or-red; no fault path blesses bytes lacking kernel evidence, modulo A1's overlap corner and A3's window.
CI: gate jobs green on prior heads; full suite re-running on this head (local full-suite pass also in flight). Branch MERGEABLE (BEHIND master — routine rebase at merge time).
Postscript (CI triage, after posting)
Two red jobs on the pre-fix head:
- static-gates (4×) —
npm run typecheckfailed on my own review-addedtests/issue5664-render-budget-base.test.ts(implicitany[]). Fixed in6bd9a9280;tsc --noEmitclean locally before push. - test (ubuntu-latest, 22, 2) —
lane matrix [openai] omp control keeps the surfacedied withSyntaxError: Unexpected end of JSON inputinside the test's OWN loopback fixture upstream server (JSON.parseof a truncated request body,failureType: uncaughtException).tests/lane-decisions-matrix.test.tsis untouched by this PR, passes locally, and every sibling subtest (all anthropic lanes, all windows shards) passed in the same run — consistent with a one-off transport-level flake on that runner, not a code regression. Watching the re-run; if it recurs, the fixture parse should be hardened (wrap in try/catch → fail the subtest deterministically instead of crashing the worker).
(ai: vllm-qwen/qwen3.8-27b) CI 自动修复车道(attempt 1/3):两条 Windows 红腿 = 在档负载 flake 家族同签名,零代码改动,已触发重跑 查重:不重复——本 PR 首次出现这两条红腿;按政策不开新 issue,结论已记 #4599(含完整证据链)。 红腿签名(run 42332732529 @ head 6bd9a92,每 shard 仅 1 fail / ~1880-1900 tests,其余全矩阵绿):
七问:
另注:上一 head 的 ubuntu(22,2) lane-decisions-matrix flake(owner 审查 postscript 提到的那条)在本轮新 head 的全量 run 中已自然转绿,无需动作。 结论:重跑在途,等结果;若干净 runner 同签名再红,按在档口径升档(记 Windows 时序硬化候选、复发再立项)。#4599 已留一行结论。 |
📦 Merged Build PublishedThis merge to master was published as npm install -g billion-context@0.0.1060-master.ce8f92e # this exact build
npm install -g billion-context@master # always the newest merged build
|
…dentity lane, ranxianglei#5754 image-shed cap, ranxianglei#5689 render-snapshot plane
…er merge (#5826) The merged fastpath-v6 wave (#5652/#5664/#5732) changed two pinned behaviors: PF_SLOT_UNKNOWN moved client->server (import fix), v6 F1 emits a fixed 64-id tail window instead of slicing at learned K, and v6 F2 makes any id-less/duplicate slot clear the whole captured table ('?' never travels). Re-pinned groups 3+4 of tests/msgid-rule-parity.test.ts to the post-merge verdicts with the ruling citations; added an over-cap case for the raised MAX_IDS (16384).
…ed cap, render-snapshot plane Upstream 2919794..ce8f92e (57 commits) lands three large planes: - ranxianglei#5652 fastpath-v6 identity lane (c295f90 storage layer, d55a50c composite identity, 9c1fb86 full-list wire, da6885d fixed tail window, plus the review follow-ups) - ranxianglei#5754 image-shed 64-item cap (6aed3b8) - ranxianglei#5689 render-snapshot plane (acca4db schema v12, 6d3ca30 O(1) steady turns, 49ba14d seal-shut probe) - ranxianglei#5721 witnessed rebase supplement Overlap with this lane was four files. src/plugin.ts auto-merged (upstream touches the handoff-reply import at :31 and handlePluginTool at :2337; this lane owns the strip entry points at :22 / :61 / :2640..:4554). The two CONFIGURATION files are generated and were regenerated from the seed. One real conflict, in tests/issue4666-migration-dedup.test.ts line 158: upstream re-swept the sqlite user_version pin to the literal 13, this lane had already derived it. Kept the derived form -- that is the whole point of the earlier sweep, and the literal is what goes stale on the next bump. That conflict resolution exposed a latent bug of mine. 3eb22b1 ("pin the mysql lock lane to the CURRENT schema version") derived the mysql stamp assertions from STORAGE_SCHEMA_VERSION as well. When it was written both numbers were 9; ranxianglei#5652/ranxianglei#5689 have since pushed the sqlite unified store to 13 while the MySQL backend stayed at 11, because the v12 identity plane and the v13 render-snapshot plane are sqlite-only. The mysql-contract lane therefore asserted "13" against a migrator that correctly stamps "11". Fixed by exporting MYSQL_SCHEMA_VERSION from src/storage/mysql.ts and pointing the four mysql-side assertions at it; the sqlite assertions keep deriving from STORAGE_SCHEMA_VERSION. Verified String(MYSQL_SCHEMA_VERSION) is "11", i.e. byte-identical to the literal upstream asserts. Verification on the merge tree: issue5175 58/0, tag-echo 79/0, issue2190-degen-close 32/0, golden-storage-render 5/0, storage-engine-proofs 12/0, native-compact-terminal 1/0, plugin-passthrough-tag-strip-chat 20/0, issue4666-migration-dedup 2/0 (the three mysql cases skip without BILI_MYSQL_TEST_DSN; no local MySQL or docker socket in this sandbox). tsc --noEmit clean, all four gates exit 0, generated docs byte-identical.
…f the fastpath-v6 lane Upstream c45ac21..bebc239 is a single revert: ranxianglei#5854 undoes ranxianglei#5652 (66aadbd "Revert feat(fastpath): v6 composite-identity incremental fastpath lane"). 38 files, -5838/+684 on net: src/server/fastpath-v6.ts, src/server/fastpath-v6-render.ts and their two test files are gone, and the sqlite unified store drops back from schema v13 to v11. That matters here for one specific reason. The previous sync resolved a derivation conflict in tests/issue4666-migration-dedup.test.ts by keeping the STACKED form, and the same merge added an export of MYSQL_SCHEMA_VERSION so the mysql-side stamp assertions stop borrowing the sqlite number. The revert collapses both numbers back to 11, which would have silently re-hidden the bug that fix exists to prevent, so the split is kept: the sqlite user_version pin keeps deriving from STORAGE_SCHEMA_VERSION, the four mysql stamp pins keep using MYSQL_SCHEMA_VERSION. Both currently equal 11, but they are different versions owned by different backends and will diverge again on the next plane. Only one conflict this time, same line 159 as before: upstream reverts the literal back to 11, this lane derives. Kept the derived form. src/plugin.ts auto-merged (upstream removes the fastpath hooks, this lane owns the strip entry points). The two CONFIGURATION files and the rollout/env-only seed yaml are generated and were regenerated. Verification on the merge tree: issue5175 58/0, tag-echo 79/0, issue2190-degen-close 32/0, golden-storage-render 5/0, storage-engine-proofs 12/0, issue4666-migration-dedup 2/0. tsc --noEmit clean, four gates exit 0, generated docs byte-identical. Lane symbols all survived the revert: stripDriftResidue 6, isDraftDump 4, containsRenderTagText 8, mayStartDegenerateRenderTag 6, DRIFT_BARE_MISMATCH 3, DRAFT_CLOSE_TAIL 3.
…stpath-v6 code was reverted, ranxianglei#5854) ranxianglei#5826 commit 33b2f82 re-pinned two msgid-rule-parity rows to the v6 F1/F2 rulings «after master merge»; revert ranxianglei#5854 then removed the fastpath-v6 code (ranxianglei#5652), leaving those pins asserting behavior that no longer exists — master failed the same two rows on pure fb18e7e (verified via detached worktree). This restores tests/msgid-rule-parity.test.ts to its bc44f77 state, i.e. exactly undoes the 33b2f82 hunks: PF_SLOT_UNKNOWN import back to pf-channel.js, per-slot "?" rides-again semantics, K-sliced tail window, and the removed OVER_CAP row (v6 MAX_IDS 16384 no longer applies).
…F2 ruling governs again Master's 613d290 restored these pins to pre-v6 verdicts on the explicit condition that 'fastpath-v6 code was reverted (#5854)'. This PR re-lands v6, so per KDD #17 (deliberate divergences re-pinned consciously, with stated rationale) the pins follow the code again: - pf-channel e2e: F2 owner ruling (2026-11-04, PR #5652 review follow-up) — any hole/duplicate clears the WHOLE captured table; '?' never travels from the client. Pre-v6 '?'-slice verdicts replaced by count-only verdicts. - pf-channel e2e: F1 fixed tail window (last <=64 ids) replaces K-based slicing; capture cap raised 2048 -> 16384 (cap still pinned via a 16385-id row so coverage does not shrink). - dsh pfSlotIdsOf: same F2 whole-table-clear (was '?' slot list). - PF_SLOT_UNKNOWN import moves from agent/pf-channel.js (constant removed client-side by F2) to server/fastpath.js (wire decoder still accepts legacy '?' segments from v5 traffic).
Closes #5643
Closes #5664
What this changes
A fresh implementation of the msgid-identity-driven fastpath ("v6") from clean master — the earlier #5576 branch was voided by owner ruling and none of its code was ported. Contract: issue #5643 (P1–P9 rulings); this PR implements only the v6 lane scope (no M1 observation layer, no canonical rewrite).
Per-turn flow for a v6 cohort request (shim family carrying
x-bili-plugin-conversation):Hard identity pre-gate. Fastpath participation now requires the full dual channel: the conversation carrier plus one real message id per body element. Four fault classes — channel missing, malformed list, width mismatch (
|R| != T), echo/consistency break — REJECT the request with zero side effects (no table/ext/watermark write; rejected => no trace) and an ERROR log. No silent legacy fallback, no count-guessing, no content-signature guessing. Five strikes park the sid for 60 minutes, after which traffic falls back to the normal baseline path loudly rather than looping 400s.Matching by composite key. Server-minted world ids (
pf_<hex12>), never client-supplied keys. Matching rules: echoedx-bili-pf-session(O(1) + spot-checked against carried ids), else a single global composite probe on(session carrier value, ledger_id)pairs, else mint a new world + one legal arm turn.Judgment = set difference only. NEW = carried ids not in the ledger; anything already known rides its frozen core untouched; a compaction turn (client shrank history) needs NO detection — surviving cores stay frozen, genuinely-new elements (the summary included) parse exactly like any other new element, wherever they sit.
tis restamped to the current body total every evaluated response.Incremental parse of only the scattered NEW spans, rekeyed absolutely against the whole ledger so
_Ncluster numbers and wire indices match a full-parse byte-for-byte.Storage plane: schema v12 adds three append-only sidecar tables (
pf_rows,pf_log,pf_ckpt) behind the existing sidecar mechanism; schema v13 adds the three render-plane tables (pf_render,pf_render_log,pf_render_ckpt) for the snapshot lane in item 7 — all pure CREATE IF NOT EXISTS, zero-byte migration, cascade-deleted with the session. Row+log commit is ONE SQLite transaction (mid-turn crash leaves zero trace); state is alwaysfold(ckpt, log-after-ckpt); compaction (>=64 entries / >=64KB / 30min idle) happens in finalize with checksum-bound meta; session deletion cascades all worlds. Sidecar-unavailable nodes softly disable the v6 lane (baseline behavior unchanged).Client wire change:
x-bili-pf-tail-idsnow carries the FULL captured element-id list (one percent-encoded segment per element, body order) instead of the last k-1 tail slice; learned world ids echo back viax-bili-pf-session. Old-format servers keep working: v5 lanes ignore unknown-list widths and fall back to count-only mode, which still emits exactlyx-bili-pf-countas before.Render-snapshot lane (fastpath v6 render snapshot plane: one-time full rewrite, steady-state rounds skip full view scan (#5643 sub-item) | fastpath v6 render 快照平面:全量改写只做一次,稳态轮跳过全视图扫描(#5643 子项) #5664, owner rulings 2026-11-04/11-05). On engaged v6 hit-turns, steady rounds no longer re-run the full-view pipeline scan: the frozen prefix rides previously-captured outbound core rows verbatim, and only the last W frozen cores (default 8) plus the new tail window pass through a bounded scratch kernel pass. Every green round re-verifies the window against the stored suffix at the post-rewrite core-form boundary (
verifyRenderWindow); any red gate condition (arm turn, title-gen, plane unavailable, pressure >= 90% of model limit, snapshot-lane, blocks-active, fold-pending, absorb-active, ccr-on, markers, hydrate-failed, caps-mismatch, scheduled audit every Nth round, rows-misaligned) falls back to the untouched full legacy path for that one turn — structurally byte-identical to pre-change when red. No-recast regime (owner ruling 2026-11-05): any structural divergence requiring a stored-row rewrite KILLS the plane for that sid permanently (persistedkind='dead'verdict, survives restarts) and the session rides the legacy full path from then on — byte-safety comes from stopping, not repairing. Scheduled audit (every N engaged green rounds, default 8) forces one full legacy pass whose capture diff re-verifies the stored rows end-to-end and rebaselines the cumulative estimate bases; any legacy round IS an audit.Config surface (AGENTS.md requirement)
rollout.features.watermarkV6MsgIdsrc/rollout.ts)percent: 0)BILI_ROLLOUT_WATERMARK_V6_MSG_ID=1. Percentage bucketing is nested underpluginFullResendWatermark(v6 cohorts are always inside the v5 feature population); env/config force overrides bypass the nesting.rollout.features.watermarkV6Rendersrc/rollout.ts)percent: 0)BILI_ROLLOUT_WATERMARK_V6_RENDER=1. Nested insidewatermarkV6MsgId(render cohorts are always inside the v6 population); requires the unified-storage sidecar (nodes without it stay on the baseline lanes unchanged).BILI_PF_RENDER_WINDOW/BILI_PF_RENDER_AUDIT_EVERYsrc/server/fastpath-v6-render.ts)The existing
pluginFullResendWatermarkfeature and its env are unchanged and continue serving all non-v6 traffic. The existingpluginFullResendWatermarkfeature and its env are unchanged and continue serving all non-v6 traffic.Behavior notes worth flagging
/compact).claude-nativefailures and fourstorage-engine-proofsgolden-drift failures reproduce identically on pristine master in this sandbox (environment, verified via clean worktree); everything else in the touched surface is green locally, full-suite verdict delegates to CI.Tests
tests/fastpath-v6-msgid.test.ts: the Snapshot-Centric Compression Foundation: Single-Row Table as Source of Truth + Compression = Insert/Delete/Update Events | Snapshot中心化的压缩底座:单行表真源 + 压缩=对表的增删改事件(非增量车道,#5652/v6 线定位纠正) #5643 matrix rows (pure-append parity vs full parse, cold-start arming, compaction-as-ignore incl. summary-with-real-id, scattered NEW rekeying, identity-boundary re-mint + archive retention, 3x restart across a real L1 fold hydration oracle, echo-header matching, carrier rotation, all four fault classes with park/recovery, caps, cascade deletion).tests/issue5664-render-snapshot.test.ts: the fastpath v6 render snapshot plane: one-time full rewrite, steady-state rounds skip full view scan (#5643 sub-item) | fastpath v6 render 快照平面:全量改写只做一次,稳态轮跳过全视图扫描(#5643 子项) #5664 matrix — golden A/B tier (render ON vs pure legacy arm over an identical 16-turn script incl. client-side compaction and a mid-script caps flip: every engaged turn's outbound bytes byte-equal, volume-discipline pins against duplicate appends), gate red-reason vocabulary (one assertion per condition), S4 tamper kill, structural-divergence permanent kill, death persistence across restart (no re-arm), thrown-read arm deferral without kill, session cascade deletion incl. the real removeSession path, teardown, audit cadence.tests/pf-channel.test.ts,tests/omp-msgids.test.ts: updated to the full-list wire form.STORAGE_SCHEMA_VERSION10 -> 11.tsc --noEmitclean; targeted suites green (fastpath family 237 tests, pf-channel 12, native-intercept 78, lane-decisions-matrix 99, storage suites above).Kernel untouched.
Fleet upgrade ordering (M1 from review)
Old shims talking to a v6-enabled node send the pre-F1 slice form → width/mismatch faults → per-session park (60 min) back to baseline. After this revision the residual mismatch shape narrows to over-window or stale-window lists only — same refuse-and-recover posture, no data mutation.
F1 landing (owner ruling): db6622e8 — fixed tail window N=64 (budget: measured host id segments ≤ ~70 bytes encoded across dsh/pi hex-dotted, opencode msg_+12hex, omp hints, wb uuid-without-dashes; 64×70 ≈ 4.5KB ≪ 16KB default × headroom 2); count retired from the lane; honest coverage boundary written into the #5643 contract (§3/§5: rewrites outside the carried window are NOT promised detectable — same class as the known total-unchanged mid-edit boundary); matrix line added for whole-window identity rewrite (with-echo → consistency-break fault storm → park; without-echo → legal re-arm, archive preserved).