Skip to content

Inbound markers: one declarative strip engine for all four wires (#2789, #2798, #2811 plan B) - #2815

Merged
ranxianglei merged 48 commits into
masterfrom
2026-10-11_marker-declarative
Oct 13, 2026
Merged

ranxianglei merged 48 commits into
masterfrom
2026-10-11_marker-declarative

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

What

Implements plan B (marker 声明化) from #2811 for the raw (inbound) stage: one declarative engine, stripRawStage(parsed, wire), replaces the per-prepare wiring of panel → status-marker → chain-carrier strippers, and closes the two leaks the #2811 leak-matrix audit pinned:

Structure

  • src/marker/spec.ts — the class table (10 ids): what exists, who strips it, at which layer.
  • src/marker/engine.ts — the walk. Order matters and is documented in-code:
    1. chain carriers first (strict whole-PART exact match per protocol — running the lenient tag stripper first downgrades carriers to whitespace zombies, starves the plugin-mode sessions: #1421 outbound chain stamps accumulate in the model-visible transcript (+1 user message per request) #1542 log line, and un-orphans the message);
    2. panels + nudge echoes — whole-message classes, spliced;
    3. per-text-slot: status body blocks → marker LINES only (render-tag spans deliberately excluded, see below).
  • src/marker/status-body.ts — the block consumer (head regex + 26-prefix section whitelist + continuation rules; stops at unknown lines, empty-slot degrades to one space so tool_calls are never orphaned).
  • src/marker/anchors.ts — single home for MARKER_INTEGRITY_NOTE / MARKER_SILENCE_CLAUSE + isNudgeEchoText (compress-tool.ts re-exports).
  • Wiring: all four prepares (prepare-anthropic/openai/responses/google) call one line each; both fork-adoption paths (fork-adopt.ts, fork-adoption.ts) get the same engine — adopted children were another leak vector.
  • tests/marker-lane-coverage.test.ts — the leak matrix as a contract: every raw-stage class stripped on every wire, downstream-owned shapes (summary anchors → state layer, codex handoff → absorb) preserved, plugin-mode sessions: #1421 outbound chain stamps accumulate in the model-visible transcript (+1 user message per request) #1542 zombie guard pinned.

Behavior notes

  • Nudge echo splicing is new at this layer, gated on whole-message exact tail match. Verified safe empirically: a CAS join of 6 weeks of dogfood sessions (440+) found zero user-role nudge echoes persisted — the class is model-side rendering, not user data.
  • Render tags (<acp …> spans) are deliberately NOT raw-stage (bug(chain): ACP tag literals in normal history can permanently force fresh proxy sessions into passthrough #1357 user-data boundary, enforced by anthropic-pck-verbatim T2): a foreign literal tag in user text survives byte-intact at this layer; bili's own echoes are handled at the projection layer and tag-echo-filter.ts stays byte-identical to master. An interim keepBiliArtifacts param on stripAcpTags was superseded by this stricter split (the parameter no longer exists).
  • The responses nudge splice covers string-content messages; array-content user messages keep their shape (text slots cleaned) — wire-realistic form.
  • The coverage contract caught a real engine bug immediately: nudge splices ran inside a forward for..of, silently skipping the message after a splice. Fixed with a reverse-index walk (matching the google/responses walks).

Review round 2 fixes

  • KDD release v0.1.3 #10: signed reasoning rides byte-for-byte — explicit gates skip thought:true/thoughtSignature parts (google), thinking/redacted_thinking blocks (anthropic/openai, and responses parts), reasoning items (responses type-gated already). Byte-equality fixtures per wire pin the invariance (tests/marker-lane-coverage.test.ts).
  • Render contract (tests/marker-render-contract.test.ts): drives the REAL handleAcpStatus renderer over six report variants and asserts the section whitelist consumes each whole — adding/renaming a report section now fails CI instead of silently re-leaking. This test immediately caught three missing section heads (Compressible ranges (, COMPRESSED — , Sorted by size/time) that hand-maintenance had missed.
  • Paste guard: the LATEST user message is the current turn — status-body consumption skips it (a pasted report for a bug report survives), marker head lines still strip; resent positions consume as before.
  • Spec note: array-content nudge echoes are not whole-message spliced on anthropic/openai/responses (string content only); google's parts walk covers all shapes.

Tests

All green locally: marker-echo 23, acp-panel 26, e2e-tag-echo 2, bili-artifact-strip 16, adapter-google 12, e2e-google-compress 4, issue1542 13, issue1086 21, issue1029 5, issue2658 6, issue2407 ×2 5, preflight-google 2, issue1204 2, fix-1117 3, 2260-inert 4, 2709 ×2 11, decode-fail 4, advisory-panel 1, marker-lane-coverage 4, fork family 129/129.

The only reds in the full fork family are the two pre-existing master regressions tracked in #2814 (fork-adoption-wires.test.ts:477, issue2601-persona-fork-lineage.test.ts:125) — red on origin/master@525b4f51 before this branch, unaffected by it.

Out of scope (deliberate)

The audit's step "prepare-shared orchestrator" is descoped from this PR: on inspection the four prepares' stage-level code interleaves protocol quirks throughout (codex gates, cache-control, hardenOpenaiAssistantContent, …) — the 80% clone is the import block and call shape, not movable stage bodies. Extracting an orchestrator would be a rewrite of 1.8 K lines, not a move; it belongs in its own PR under #2811 once this engine has soaked. State-layer classes (summary anchors, absorb) and the outbound stripper are untouched by design.

Fixes #2798
Fixes #2789
Refs #2811


prepared by an agent under the local git identity (ranxianglei), human merge required

Rollout step: unified storage defaults to shadow (5aced73)

resolveStorageMode now lands on shadow when neither storage.unified nor BILI_STORAGE_UNIFIED is set — the JSON envelope stays the sole source of truth (zero behavior change), every session write mirrors into index.db with digest reconciliation, and drift surfaces as [storage] DIGEST DRIFT logs: fleet-wide parity telemetry before the full-mode default flip. Explicit legacy opts out; garbage still degrades to legacy; engine-less lanes stay legacy-only (#2825 contract). The repo test corpus runs on an explicit legacy baseline (tests/preload-storage-baseline.mjs in npm test + scripts/run-ci-tests.mjs); the storage family pins/overrides its own modes and the resolveStorageMode matrices + web-sessions stamp test pin the new default.

Note on history: the dev-build version bump (0.1.197-dev.1) was dropped to satisfy version-guard — releases bump versions, dev branches don't. Machine installs are self-contained tarballs with autoUpdate: false, unaffected.

@github-actions

github-actions Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-11_marker-declarative (200b78e)

Option A — Install this exact build (recommended)

npm install -g billion-context@0.0.3379-pr.2815.e60bde1

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-pr2815.tgz
npm install -g package

Install instructions are refreshed on each push.

@ranxianglei
ranxianglei force-pushed the 2026-10-11_marker-declarative branch from ae702d6 to 9b480c9 Compare October 11, 2026 15:45
ranxianglei pushed a commit that referenced this pull request Oct 11, 2026
The lane-coverage contract wrote complete well-formed ACP/bili-chain tags
as literal angle brackets in source. KDD#2 requires \x3c/\x3e escapes because
tooling strips well-formed tags: if that ever touches these files, the
RENDER_TAG_PROSE pin silently degrades to plain-prose (a tautology — render-tag
stripping regression would go undetected) and the CHAIN_CARRIER fixture breaks
its carriers>=1 assertion. Convert the four occurrences (test fixtures +
spec.ts render_tag note) to hex escapes; runtime strings are byte-identical
(verified by re-running marker-lane-coverage.test.ts, still 4/4 green).
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 Review 结论:#2815 声明式 inbound marker 引擎(plan B)— 可合(人合)

先说结论:方向和实现都对,我把分支 rebase 到当前 master 后独立跑了定向测试 + typecheck,并顺手修了一处 KDD#2 违规(已推独立 commit)。下面是结构化八问。

① 是什么问题
两条 wire 的 inbound(重放历史)marker 剥离不完整:#2798 google 的 content.parts[].text 对象形状旧通用 walker 看不见,google 除了 chain carrier 基本啥都不剥;#2789 anthropic/openai/responses 只删了 acp_status 的 head line,后面连续的报告体(ACTIVE SURFACE / CONTEXT BREAKDOWN / COMPRESSED BLOCKS / BILLED INPUT)每个 resend turn 堆 0.5–1.5K。

② 什么原因导致的
根因是「per-prepare 三处各自接线」+「通用 walker 只认 content: string | part[]」:google 的对象 part 形状落在盲区,status body 只有 head 被 MARKER_LINE 吃掉、body 无人认领。plan B 用一个声明式引擎 stripRawStage(parsed, wire) 统一四条 wire 的遍历,从结构上消除盲区,而不是再打补丁。

③ 影响范围与严重程度
受影响面:所有会重放历史的 client(proxy/MITM/plugin 三种 lane 的 prepare 前置阶段);触发条件:client 持久化并回送过代理渲染产物(面板/status body/render tag/nudge echo/carrier)。严重度:泄漏本身是 token 累积 + 读流污染(不是功能损坏);修复后为纯收益。修复引入的行为变化见 ⑤。

④ 怎么修复的
一个引擎、有序三段(顺序在代码里写明):chain carrier 先跑(strict whole-PART,避免被 lenient tag stripper 降成空白僵尸、饿死 #1542 日志、解除孤儿),再整消息类(panel/nudge echo splice),最后逐 text slot(status body block → stripAcpTags)。google/responses 走 reverse-index 遍历(nudge splice 后前向 for..of 会漏一条——coverage 契约当场抓到并修了)。

⑤ 是否有回归问题 —— 我审过的既有行为,逐条结论:

⑥ 是否破坏缓存
不破坏,反而改善。每 turn 确定性地剥掉同一批泄漏物,resend 前缀跨 turn 保持稳定;#2789 那个「每 turn 堆 0.5–1.5K body」本身就是 prefix 漂移源,去掉后缓存更健康。无重试/游标/去重键失效。

⑦ 是否改了设计方向
是轻微整合,不是转向:per-prepare 三处接线 → 一个声明式引擎 + spec.ts 类表(且 9b480c9 把它从「文档」升级成「强制 gate」:coverage 断言 spec 表 raw-stage id 集合与引擎计数形状双向一致)。审计里的「prepare-shared orchestrator」刻意 descoped(四条 prepare 的 stage 级代码交错着 codex gate/cache-control/hardenOpenaiAssistantContent,抽出来是 1.8K 行重写而非搬移,留给 #2811 后续)——这个克制是对的。state 层(summary anchor)、outbound stripper 按设计不动。

⑧ 是否引入新配置
无。没有新 env/config/knob/默认值。


验证(rebase 到当前 master@9fb91641b 之上):

  • rebase 干净:master 领先的 2 commit 只碰 affinity-neutral.ts/prefix-affinity.ts/server/handle.ts,与 PR 文件零重叠。
  • 定向测试全绿:marker-lane-coverage / marker-echo / acp-panel / e2e-tag-echo / bili-artifact-strip / tag-echo = 146,issue1542 / visibility-markers / issue1029 / store-marker-gate = 29;typecheck exit 0。最终头(含新增 parity gate + 我的 fix)coverage 5/5。

我顺手修的一处(小问题直接修,已推): tests/marker-lane-coverage.test.ts 的 fixture(CHAIN_CARRIER、RENDER_TAG_PROSE)和 src/marker/spec.ts 的 render_tag note 里写了字面量 well-formed ACP/bili-chain tag。KDD#2 要求源码里 ACP tag 用 \x3c/\x3e hex escape,因为工具链会剥 well-formed tag——一旦碰这些文件,RENDER_TAG_PROSE 会静默退化成纯 prose(render-tag pin 变恒真,回归抓不到),CHAIN_CARRIER 会让 carriers>=1 断言红。尤其隐蔽的是新增的 parity gate 只查 spec 表 id、不查 fixture 字节,所以这个 rot 向量不会让任何测试变红。已转 hex escape(runtime 字节等价,重跑仍绿),作为独立标注 commit 0bb30c775 fast-forward 推到分支(未 force)。

两处非阻塞 nit(供合并时定夺,我没动): 新增 parity-gate 测试里 for (const s of MARKER_SPECS) void scopeOf(s); 是空操作,assert.equal(Object.keys(...).length, counted.length + 1) 表意不直白(实为 counts 对象 key 数漂移检查)。建议要么删掉 scopeOf+该 loop+对应 type import,要么把六个 count 字段名列全用 deepEqual。纯可读性,不影响 gate 的牙。

判定:可合(人合)。 非 auto-merge 候选(wire/message-shape 变更、双模式影响,§7.4 必须人合)。rebase 干净、定向测试绿、行为变更均已披露。请 owner 确认 ⑤ 第一条(inbound render-tag span 现在也被剥)符合预期后合并即可。

ework-agent added 6 commits October 12, 2026 03:23
…f-download (#2833)

Engine acquisition no longer depends on host install-time build-script
approval (the strictDepBuilds gate behind #2823/#2825):

- detectEngine order: built-in node:sqlite (Node >= 22.5) -> host
  better-sqlite3 require probe -> registered self-downloaded loader ->
  none (legacy-only per the #2825 contract)
- new src/storage/engine-bootstrap.ts: one-time download of the pinned
  better-sqlite3 13.0.3 npm tarball (in-tarball N-API prebuilds for all
  8 platform-arch targets, no build scripts), sha512-pinned in-repo,
  extracted via a dependency-free gunzip+ustar reader into
  <cache>/sqlite/better-sqlite3-<version>, atomic publish, 6h cooldown
  after failure, proxy-aware via the existing network.proxy chain
- storage.sqliteAutoDownload (default true) / BILI_SQLITE_AUTO_DOWNLOAD
  gate the network fetch only; a cached copy is used even when false
- wired into bili start before the first store open (bounded ~10s);
  enablement log now records engine/source for field diagnosis
…unpassable

assert.equal from node:assert/strict is strictEqual: comparing the fake
driver's get() result against a fresh { ok: true } literal always fails on
reference equality, so the test could never pass. Use deepEqual to assert
the actual value (the point: the registered self-downloaded loader drives a
real open through the driver).

Review fix for PR #2845 (found by local run of the suite: 20/21 with this
line failing).
downloadAndInstall published via fsp.rename(tmpDir, finalDir) only. When a
stale/partial final dir already exists (killed run, local tampering), the
rename fails ENOTEMPTY over the non-empty dir, so every retry re-downloads
and fails at publish, re-arming the 6h cooldown indefinitely — contradicting
the documented 'corrupt cache dir is skipped' contract. Before publishing:
a usable existing dir means a concurrent process already published the same
pinned artifact (treat as success); an unusable one is removed and replaced.
Adds the hermetic regression test (stale dir -> downloaded, complete cache,
no cooldown marker).

Review fix for PR #2845.
…xports gate

OpenedDatabase (driver.ts) and EngineBootstrapSpec/DEFAULT_ENGINE_SPEC/
BootstrapStatus/EnsureSqliteEngineOptions (engine-bootstrap.ts) have no
references outside their declaring files and tsup emits no d.ts, so the
exports are pure surface bloat. Unexport them; behavior unchanged.

Review fix for PR #2845 (CI unused-exports job).
…blocks

The PR hand-edited the generated param-ref/env-map blocks instead of adding
a seed entry, which broke docs-sync/docs-coverage/config-surface-guard. Add
the seed to website/config-reference/process.yaml and regenerate (also fixes
the env-map row ordering the generator sorts by name). Sync the static zh
long-form BILI_STORAGE_UNIFIED entry to the new engine-resolution wording.

Review fix for PR #2845.
@ranxianglei

Copy link
Copy Markdown
Owner Author

KDD #10 follow-up from the #2811 matrix review (comment 6110433698) is in: the google inbound walk did strip p.text on thought parts — a resent {text, thought:true} part whose thinking echoed a marker line would have been rewritten and desynced from its signature. e470784 gates every signed channel explicitly (google thought/thoughtSignature, anthropic thinking/redacted_thinking, responses reasoning parts; openai reasoning_content was never a strip slot) and adds the byte-invariance fixture the review asked for: marker-shaped text inside each signed slot, JSON-equal before/after, with control slots stripping on the same body. One divergence from the review, from implementation itself: render_tag stays OUT of the raw walk — anthropic-pck-verbatim T2 pins the #1357 user-data boundary (foreign literal tags survive advisory processing byte-intact), so stripAcpTags is not wired inbound at all; tag-echo-filter.ts is byte-identical to master. #2797 / #2805 are superseded by this PR's engine if the owner prefers one implementation (Fixes #2798, Fixes #2789 already on the body).

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 Upstream conflict resolved & re-verified — no push needed from me

The merge_conflict wake arrived while I was mid-resolution, but by the time I finished the branch already carried a concurrent master-merge (311e54b10, pulling in newer master incl. #2836/#2840). My own local merge was built on the older base (011bf5ea5) and is strictly subsumed by it, so I deliberately did not force-push mine over the cleaner/newer one. I adopted the remote tip as source of truth and re-verified that:

  • CHANGELOG conflict = clean union: both [Unreleased] bullets kept (marker-engine L7 + 0.1.189更新失败,插件市场更新报错 #2823 better-sqlite3 L28), zero conflict markers.
  • All three load-bearing commits are ancestors of the tip: my round-1 KDD#2 fix 0bb30c775, plus d52e81cc8 and e470784c1.
  • Gates on the true tip 311e54b10: storage-render golden 5/5 (google.json reproduces exactly), marker-lane-coverage 11/11, tsc --noEmit exit 0.

Re-review of the two fix commits added since my first pass:

The Google storage-render golden change (the one item I wanted proven safe): only google.json moved among the four wire goldens → delta isolated to stripGoogleContents (#2798's home — the old generic walker never traversed google parts[].text). The committed snapshot reproduces exactly on the merged head, so it is consistent with the code, not a stale/arbitrary regen. Cause: google inbound resends now drop their previously-leaked marker lines / nudge-echo messages (~268 B/late-turn shrink); signed thinking is gated out and user prose is untouched. Intended #2798 effect, safe.


中文结构化结论(八问)

  1. 是什么问题:PR 分支与 master 的 upstream merge_conflict;顺带复核 round-1 之后新增的两个 fix commit。
  2. 什么原因导致:master 已推进(release v0.1.194 + dsh anthropic-messages lane bypasses native-intercept fetch patch: anonymous pfa-* session, fold ledger orphaned, silent ~182s re-fold on cross-protocol switch #2791 affinity ×2 + fix: silence best-effort probe exec stderr leaking to host terminal (#2834) #2836/fix: preflight classifies normal-stop zero-text summaries as deterministic (#2832) #2840)越过分支基线;双方都改了 CHANGELOG [Unreleased] → 纯文本冲突,无代码交互。
  3. 影响范围与严重度:仅 CHANGELOG.md 文本冲突,零行为影响;两个新 commit 属正确收敛。无回归。
  4. 怎么修:冲突已由远端并发 merge(311e54b10)以 union 方式解决(两条 bullet 都保留)。我基于真实远端 tip 独立复核,未强推自己的旧基线 merge(避免覆盖更新、更干净的合并)。
  5. 是否有回归:审过既有行为——google outbound body + persisted state(golden 5/5 复现)、marker 剥离矩阵(11/11)、typecheck 0。高危模式逐项:语义漂移=无(inbound render-tag 已退回 master 语义);fail-fast 变吞错=无;阈值/时序/输出格式=无(golden 证明 wire bytes 稳定);signed-thinking 已显式门控(KDD#10)。→ 无回归。
  6. 是否破坏缓存:不涉及缓存失效策略变更;persisted-state digest 变化是内容剥离的预期结果,非游标/去重键漂移。golden harness 里的 prefix-seam warning 是其故意 mid-history edit 触发,与本 PR 无关。
  7. 是否改设计方向:不改架构方向;反而把 round-1 我标记的「inbound 剥 render-tag」收敛回 projection-layer(bug(chain): ACP tag literals in normal history can permanently force fresh proxy sessions into passthrough #1357 边界),并补 KDD#10 签名通道门控——是修正,不是转向。
  8. 是否引入新配置:不涉及新 env/config/默认值。

判定:分支现状(远端 311e54b10)可合(人合)。wire/message-shape 变更且涉及双压缩模式 → §7.4 必须人合、非 auto-merge。无需我再 push——远端合并已含全部三个关键 commit。#2797/#2805 是否由本引擎取代按你的决定走,我不擅动。

ranxianglei and others added 9 commits October 12, 2026 21:29
Single table (src/marker/spec.ts) for the ten inbound marker classes;
raw-stage engine (src/marker/engine.ts) walks anthropic/openai/google/
responses wire shapes through one ordered pipeline: per-slot status-body
consumer (#2789) + stripAcpTags, whole-message panels/nudge echoes/
carriers. Google walk is new — the old generic walk could not see
content.parts objects (#2798). Integrity note + silence clause moved to
the leaf src/marker/anchors.ts so the inbound nudge-echo matcher shares
the emitter bytes (single-source); compress-tool.ts re-exports.

Pure addition: no prepare wires the engine yet (next commit).
…tion

Every raw-stage consumer now runs one engine instead of per-protocol ad-hoc
sequences: prepare-anthropic/openai/responses replace their three-step loops
with logRawStripCounts(stripRawStage(parsed, wire)); prepare-google gains the
full stage (fixes #2798: panels/status/markers were never stripped there —
the generic walk was blind to content.parts objects); fork adoption paths
(fork-adoption.ts responses/google/messages, agent/fork-adopt.ts
openai/anthropic/responses) strip through the same engine, fixing #2789's
head-only consumption (whole status bodies are now eaten by the block
consumer while prose lines survive).

Two orderings preserved by construction:
- carriers FIRST: chain-checkpoint's whole-PART exact stripper must run
  before the lenient tag walk, or whole carriers degrade into whitespace
  zombies instead of being spliced (#1542's log line would starve).
- keepBiliArtifacts on the inbound walk: the #1634 artifact family
  (chain tags, forged handoff headers, captured summary blocks) is
  model-OUTPUT stripping; inbound history keeps user-data semantics
  (#1039/#1395) — strict carriers and state-layer anchors own those shapes.
Pins the #2811 leak matrix: every raw-stage marker class (panel message,
acp_status report body incl. contiguous sections, confirmation/failure
marker lines, render-tag spans, chain carriers, nudge echoes) is stripped
on anthropic/openai/responses/google through the one engine, while
downstream-owned shapes (summary anchors, codex handoff) and surrounding
prose are preserved.

Fixes a latent engine bug the contract caught immediately: nudge splices
in stripMessagesArray ran inside a forward for..of, so removing a message
skipped the next one entirely (a multi-part message after a nudge echo
was never walked). Reverse index now, matching the google/responses walks.

The responses nudge splice covers string-content messages; array-content
user messages keep their shape (text slots cleaned) — the wire-realistic
form, and the dogfood corpus join (issue #2811) found zero user-role
nudge echoes in 440+ sessions.
…ts spec/engine parity

The unused-exports gate flagged MARKER_SPECS as DEAD and the marker
types as INTERNAL_ONLY. Instead of waiving, the coverage test now
imports the declarative table and pins both directions: every raw-stage
id declared in the spec is one this file proves behaviorally, and the
engine's counts shape is unchanged (no silently-added class). engine.ts
annotates its consumeAcpStatusBody result with StatusBodyResult.
The lane-coverage contract wrote complete well-formed ACP/bili-chain tags
as literal angle brackets in source. KDD#2 requires \x3c/\x3e escapes because
tooling strips well-formed tags: if that ever touches these files, the
RENDER_TAG_PROSE pin silently degrades to plain-prose (a tautology — render-tag
stripping regression would go undetected) and the CHAIN_CARRIER fixture breaks
its carriers>=1 assertion. Convert the four occurrences (test fixtures +
spec.ts render_tag note) to hex escapes; runtime strings are byte-identical
(verified by re-running marker-lane-coverage.test.ts, still 4/4 green).
…oundary)

The CI battery caught the overreach: anthropic-pck-verbatim T2 pins that a
FOREIGN literal <acp> tag in user text survives advisory processing
byte-intact — it is user data. stripTextSlot now runs the marker-LINE
stripper only (same semantics as the old stripAcpStatusMarkers wiring);
tag-echo-filter.ts is back to byte-identical with master (the short-lived
keepBiliArtifacts param is gone with its only caller). spec.ts moves
render_tag to a new 'render' stage with the boundary note; the coverage
contract pins both directions (raw ids exclude render_tag; the literal tag
survives raw on every wire).

Google storage goldens regenerated: they were committed snapshots of the
storage-render/golden-storage-render/engine-proofs + the full marker and
fork families green.
…k (KDD #10)

Review of the leak matrix (issue #2811 comment 6110433698) pinned the
fatality class before implementation did: any rewrite of signed text
desyncs it from its signature and bricks replay (#1882/#1960). The google
inbound walk DID strip p.text on thought parts — a resent
{text, thought:true} / {text, thoughtSignature} part whose thinking
echoed a marker line would have been rewritten. Now gated explicitly:

- google: parts with thought===true or thoughtSignature are skipped
- anthropic/openai: thinking/redacted_thinking content blocks are skipped
  (structurally safe — their text lives in .thinking — but the gate pins
  the shape against future drift)
- responses: thinking/redacted_thinking/reasoning content parts skipped
  (top-level reasoning items were already type-gated out)

Coverage gains a byte-invariance fixture per signed channel: marker-shaped
text inside every signed slot, JSON.stringify-equal before/after the walk,
with non-signed control slots still stripping on the same body.
@ranxianglei
ranxianglei force-pushed the 2026-10-11_marker-declarative branch from 311e54b to b6da1cd Compare October 12, 2026 13:31
…section heads), latest-user paste guard, spec note for array nudges

- tests/marker-render-contract.test.ts drives the REAL handleAcpStatus
  renderer over six report variants and asserts consumeAcpStatusBody eats
  each whole. It immediately caught three section heads missing from
  SECTION_HEADS ('Compressible ranges (', 'COMPRESSED — ', 'Sorted by
  size/time') — hand-maintained whitelists drift; the render contract
  cannot.
- status-body consumption now skips the LATEST user message on every wire
  (#2815 review pt 3): the current turn is not an echo; a user pasting an
  acp_status report to report a bug keeps it. Marker head lines still
  strip (review acknowledged). Resent positions consume as before.
- spec.ts: array-content nudge echoes documented as not whole-message
  spliced on anthropic/openai/responses (google parts walk covers all).
@ranxianglei

Copy link
Copy Markdown
Owner Author

Review round 2 — all four points addressed in d4032e0:

  1. PR body — superseded keepBiliArtifacts wording replaced with the actual bug(chain): ACP tag literals in normal history can permanently force fresh proxy sessions into passthrough #1357 split (tag-echo-filter.ts byte-identical to master); a "Review round 2 fixes" section documents the rest.

  2. Ghost test is now real — tests/marker-render-contract.test.ts drives the actual handleAcpStatus renderer over six report variants (default/uncompressed×sort×view/compressed×view) and asserts the section whitelist consumes each report whole, embedded and standalone. You were right that the whitelist had drifted: the test caught three missing section heads on its first run — Compressible ranges (, COMPRESSED — , Sorted by size/time — the default report (the one echoed most often) leaked its ranges section. Fixed in the same commit; renderer changes now fail CI the moment the two sides diverge.

  3. Paste guard — status-body consumption now skips the LATEST user message on all four wires (that's the current turn, not an echo); a pasted report survives to the model. Marker head lines still strip, as your note acknowledged. Coverage pins both directions: latest-user paste kept, older user/assistant echo consumed (statusBodies===1 exactly).

  4. Spec note — array-content nudge limitation recorded on the nudge_echo row (string-content splice on anthropic/openai/responses; google parts walk covers all shapes).

Local: marker families + goldens + wire-contract + #1542 all green; tsc clean.

#2821 replay: a mid-session model switch re-minted every tool-call id on
re-projection (content byte-identical). Both Pass 0 flank scans died at
their FIRST cell (changed preamble at the head, appended turn at the tail):
byPos=0, 3289 covered ids missing, three drift passes -> "substrate
destroyed" -> total unfold -> ~4MB raw out -> doomed-probe 502. The order
was intact the whole time; only its evidence was id-gated.

Owner rule (2026-10-12): 顺序为中心, hash 为辅助 — order is the carrier,
content the per-cell gate, the id a fast path; no single dimension's miss
may cascade into total unfold.

- Pass 0 resync: a fingerprint mismatch is a gap, not a wall — scans
  resync at the next run of MIN_RESYNC_RUN consecutive same-index
  agreements (gaps bounded by MAX_RESYNC_GAPS) and keep claiming verified
  spans behind the break; order breaks are observable
  ("N order break(s) resynced" in the drift line).
- Pass 1.5 (#2396 detection promoted to claiming): re-minted tool-call
  ids with byte-identical normalized content are claimed k-th-to-k-th
  with the byNorm length guard — the fallback when no stored positional
  copy exists. After one churn pass the self-saved {ids, canon} copy
  upgrades recovery back to the positional path.
- Escalation semantics: "substrate destroyed" only counts gaps that
  survived resync AND the content passes.
- unchanged: "never fuzzy similarity" — the hash stays a HARD per-cell
  gate (mis-attribution discipline); genuinely edited cells stay
  honestly unmatched and re-enter the wire.

AGENTS.md §2 gains the order-centric principle as design decision #11.
Tests: tests/issue2915-order-centric-reconcile.test.ts (2821 replay,
mid-island resync, insertion offset, twin claiming incl. rerun-twin
rejection + k-th families, three-generation escalation lifecycle).
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 Round 2 fixes verified — all four points hold, empirically

Re-cloned the branch tip (d4032e07d) into a scratch worktree, built kernel+pi-subagents, and ran the suites rather than take the summary at face value.

Empirical checks

Per point

  1. PR body — verified via API: line 23 now says the interim keepBiliArtifacts param "was superseded … (the parameter no longer exists)", states the bug(chain): ACP tag literals in normal history can permanently force fresh proxy sessions into passthrough #1357 user-data boundary + "tag-echo-filter.ts stays byte-identical to master", and a ## Review round 2 fixes section is present. Accurate, not stale.
  2. Ghost → real test — tests/marker-render-contract.test.ts imports the real handleAcpStatus, builds a real session + real fold, drives six report variants, asserts whole-body consumption AND embedded-prose preservation AND a non-over-consume negative control. I mutation-proved the teeth: deleting "Compressible ranges (" from SECTION_HEADS flips it to not ok, leaking exactly \nCompressible ranges (1, oldest first):\n m00007–m00007 … STORAGE — …\n (a genuine rendered body, not a canned string). The 5 added heads are a superset of the 3 the test caught.
  3. Paste guard — noStatusBody skips only status-body consumption at the latest user index across all three walkers (messages/google/responses); marker head lines still strip. Splice-safe (reverse walk, user-only splices, lastUserIdx is the highest user index so lower indices never shift); responses correctly scopes to type==="message"|undefined. Coverage pins both directions (statusBodies===1, pasted body survives, older echo consumed) on all four wires.
  4. Spec note — nudge_echo row now documents the array-content limitation (string-only whole-splice on anthropic/openai/responses; google parts walk covers all shapes).

Behavior changes flagged (§Deliverables #4)

No new issues found while reviewing — the four facets are one mechanism, handled together.


中文结构化结论(八问)

  1. 是什么问题:复核 round-2 四个修复点(render-contract 真测试、paste guard、spec note、PR wording)是否真实落地。
  2. 什么原因导致(原缺陷根因):①section-head 白名单是手写镜像,与真实 renderer 漂移→默认报告 ranges 段在重发时泄漏(acp_status visibility markers: stripMarkerLines removes the head line but leaves the multi-line report body in incoming history (#1029 follow-up) #2789);②raw 层无法区分「回显的报告」与「用户粘贴来报 bug 的报告」→会吃掉当前轮粘贴体。
  3. 影响范围与严重度:①影响所有会重发 acp_status 报告的会话(default 报告最常被回显)——上下文污染级,非崩溃;②影响「用户粘贴报告报障」这一低频但真实场景——数据丢失级(吃掉用户正文)。两者均已修。
  4. 怎么修复的:①用真 renderer 驱动的契约测试钉死 render↔consume 两侧 + 补齐缺失 head(白名单从「手工维护」变「测试兜底」);②latest-user-index 跳过 status-body 消费(保留 marker 头行剥离),四条 wire 统一;spec 记录 array-nudge 局限。
  5. 是否有回归:审过既有行为——inbound 剥离矩阵(lane)、golden storage-render(复现)、wire-contract、plugin-mode sessions: #1421 outbound chain stamps accumulate in the model-visible transcript (+1 user message per request) #1542、ACP 状态标记被拼接进用户消息文本块;跨会话代际 stale refs 压缩整批失败 #1029 全绿;tsc 0。高危模式逐项:语义漂移=无(tag-echo-filter 与 master 逐字节相同,inbound render-tag 仍走 projection 层);fail-fast 变吞错=无;阈值/时序=无;输出格式=无(golden 证明 wire bytes 稳定);signed-thinking 门控保持。→ 无回归。
  6. 是否破坏缓存:不涉及缓存失效策略;persisted-state digest 变化是内容剥离的预期结果,非游标/去重键漂移。
  7. 是否改设计方向:不改架构方向;是把「手维护白名单」升级为「renderer 契约测试兜底」+ 补 paste-guard 边界,属机制内加固,不是转向。
  8. 是否引入新配置:不涉及新 env/config/默认值。

判定:d4032e07d 四个修复点全部实证成立(201/201 绿、tsc 0、mutation 证明测试有牙、tag-echo-filter 与 master 逐字节一致、merge-tree 干净无冲突)。可合(人合)——wire/message-shape 变更且跨双压缩模式 → §7.4 必须人合、非 auto-merge。本轮我仅验证,未 push(分支现状即你推的 d4032e0)。

ranxianglei and others added 2 commits October 12, 2026 23:13
…twin-claim pass

Review supplement for #2939: the comment claimed 'both claim passes key on
the toolCallId itself', which stopped being true once Pass 1.5 (#2915)
promoted content-identical twins from detection to claiming. Reworded to
state what the counter actually reports now: suspects that survived EVERY
claim pass (length-guard rejects, exhausted duplicate families, real
edits) — detection evidence only, never a repair target.
@ranxianglei

Copy link
Copy Markdown
Owner Author

Proof-angle review (independent verification, additive; nothing pushed to this branch)

Verified green in a clean worktree: marker-lane-coverage 4, marker-render-contract 2, marker-echo 23, bili-artifact-strip 16, e2e-tag-echo 2 — plus code-order checks that stripRawStage never touches tool_calls[].function.arguments / tool_use.input (#1039 byte-exactness holds) and that affinity resolve() at handle.ts runs on pre-strip raw bytes, so anonymous chain identity survives the upgrade.

The PR proves its own axis thoroughly. One axis is missing, and it is the conjunctive one (same class as the #2807 review gap): fold-state continuity across the strip transition.

Mechanism: ids are minted by openaiToCore after stripRawStage (prepare-openai.ts:81→88), but every pre-upgrade fold's covered ids were minted from marker-laden bytes. A stateless client resends its stored history forever — so every marker-carrying covered message churns its id on every post-upgrade turn.

Probe (unit-level, real engine + real adapter, repair mode, 12 marker-laden assistant turns + 12 user turns, block covering all 24):

pass1..4: reaped=0 blocks=1 cov={p:12,r:0,t:24,e:1,z:0} driftStreak=1..4
pass3: [error] compression substrate appears destroyed: 12 covered id(s) missing
       with NO anchor match for 3 consecutive passes — consistent with a host-native
       compaction landing outside bili's knowledge ...
       escalated=true

Findings:

  1. Fold state survives — user-turn ids ride verbatim (p ≥ half in any realistic shape; 2*(p+r) < hardIds never trips, z stays 0, no reap). Worth pinning so it stays true.
  2. Bounded billing window — churned assistant content rides raw until the next re-fold nests/retires the old block (the post-fold double prefix-cache penalty: the request AFTER a fold matches only the ~11K head (one-build wire drift after compress) #2741/fix(kernel): fold summaries may never precede the pinned first user message (#2733) #2755 chain). Also worth pinning: converges, no perpetual zombie carrier.
  3. Misdiagnosis (real) — sessions with ≥10 marker-laden covered turns (exactly the acp_status visibility markers: stripMarkerLines removes the head line but leaves the multi-line report body in incoming history (#1029 follow-up) #2789 victim population) latch foldDriftEscalated with the "substrate destroyed / host-native compaction" error, while compression is actually healthy. Same class as the reasoning-drop misdiagnosis fixed in Per-wire continuity proofs + reasoning-drop tolerance (model-switch / fork-adoption / mode-upgrade) #2732 (sanctioned churn treated as destruction). Cheap host-side fix candidate: when a pass saw statusBodies/markerLines/nudges > 0 stripped, count text-id churn against the escalation gate (or tolerate it outright); alternatively document-and-accept, but then the pin should assert the latch is one-time and self-clears on re-fold.

Suggested additions (happy to follow up with the test if wanted):

  • marker-lane-coverage-style continuity test: existing fold + marker-laden resent history → strip active → assert no reap, re-fold heals, old block retires via nesting, churned ids stop warning after the re-fold.
  • Decision on 3 (fix vs accept) — currently the field will log error-level "destroyed" for every marker-heavy session right after upgrade.

Two boundary notes (not blockers): non-latest user positions carrying a pasted report still get consumed (marker-lines already had this policy — fine, just documenting); affinity pre-strip ordering is currently load-bearing and unpinned — one cheap test (resolve before/after strip → same session) would keep it that way.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 Fold-state continuity: verified real — and I found one more concrete harm than the list

Re-verified the mechanism in a clean worktree (not just your probe). It holds, and I traced the blast radius further than the writeup.

Mechanism confirmed (code-level)

  • src/server/prepare-openai.ts:81 runs stripRawStage(parsed, "openai") before openaiToCore(parsed) at :88 → core ids are minted from stripped bytes. Pre-upgrade fold anchors were minted from marker-laden bytes. A stateless client resends stored history forever → every marker-carrying covered message churns its id each post-upgrade turn. Same ordering on all four wires.
  • The gate (src/fold-reconcile.ts:1249–1285) already has the sanctioned-drop carve-out you cited — but it's reasoningOnlyDrop, which matches only contentType === "reasoning". Strip-churned text falls through to totalDrift → accrues the streak → trips at FOLD_DRIFT_ESCALATE_PASSES=3 && nonReasoningUnmatched >= FOLD_DRIFT_ESCALATE_MIN_UNMATCHED=10. That's exactly your "≥10 marker-laden covered turns."
  • Pre-existing in limited form (master's stripAcpStatusMarkers stripped marker lines), but this PR sharpens it: stripRawStage now strips full status bodies + nudges + panels across all four wires, so ≥10-unmatched is reliably reached for the acp_status visibility markers: stripMarkerLines removes the head line but leaves the multi-line report body in incoming history (#1029 follow-up) #2789 population. Correctly owned here.

Blast radius — one harm beyond the list. Not just the error log. Once latched, src/stream.ts:356 (compressFailureCause) re-labels any "cannot be anchored" compress failure as "substrate-destruction … structural, report it" instead of the correct "content-changed — carry new refs now." In marker-heavy sessions that misdirection hits precisely when it's most plausible (the model cites an old ref whose message just churned) — steering the agent away from the benign re-ref recovery toward "report a structural problem." Plus a possible spurious native-compaction-inferred conflict record when a dsh witness coincides (§2709). What it does not do: reap blocks or disable compression (your probe's z=0, confirmed — reap needs z≥3). So functional harm = false alarm + model misdirection, not data loss. Severity: medium, concentrated on this PR's own target population.

Your findings 1 & 2: agree with both; both should become pins (no-reap under strip-churn; bounded-window convergence via #2741/#2755 nesting/retirement), not behavior changes.

Decision on finding 3: FIX, in this PR, before merge — not document-and-accept. Shipping #2815 alone introduces a false ERROR + model-misdirection on exactly the sessions it exists to help. A scary-but-wrong "substrate destroyed" also erodes trust in the real destruction alert.

Proposed fix (Tier 1, minimal, mirrors the existing carve-out):

  • Thread the already-computed strip signal into the gate: stripRawStage returns RawStripCounts at prepare:81 — pass a strippedArtifactsThisPass total into reconcileFoldCoverage(...) options.
  • Extend the non-drift carve-out next to reasoningOnlyDrop: treat the pass as non-destructive (no streak accrual, no ESCALATED latch) when the churn is strip-sanctioned. stream.ts:356 then auto-corrects to "content-changed."
  • Anti-masking guards (the part I want your eyes on before I touch the safety net):
    1. Never override a positive dshNativeCompactionWitness(session) — if there's real compaction evidence, keep the destruction verdict.
    2. Scope the tolerance to unmatched ids that still have a live same-slot candidate (resent-but-modified), so genuine total-loss (message actually gone) still escalates. Note the nudge-splice edge: whole-message removal can drop a covered id with no candidate — the predicate must not mistake that for destruction either.

If you'd rather go deeper (Tier 2): re-anchor strip-churned ids onto their same-slot candidate by normalizing both sides through the strip before identity-compare — then churn stops accruing at all (also closes finding 2 faster). Bigger blast radius (id assignment); better long-term; fine as a follow-up issue if so.

Tests I'd add: continuity (existing fold + marker-laden resend → assert no reap, no escalation/latch, re-fold heals, old block retires, churn stops warning, compressFailureCause→"content-changed"); anti-masking regression (real total-loss still escalates); affinity pre-strip pin (resolve() before/after strip → same session); pins for findings 1 & 2. Boundary note on non-latest-user pasted reports: acknowledged as documented policy, no action.

Give me the nod on Tier 1 (+ the anti-masking predicate) and I'll implement in this PR with the tests; or say Tier 2 / split-to-follow-up and I'll route accordingly.


中文结构化结论(八问)

  1. 是什么问题:PR 的 inbound 剥离引擎漏了「剥离过渡期的 fold-state 连续性」→ 对 marker 密集的会话误判为 substrate 被毁。
  2. 什么原因导致:core id 在 stripRawStage(prepare-openai.ts:81)之后才由 openaiToCore(:88)铸造;升级前的 fold 锚点却来自带 marker 的字节;无状态客户端永远重发存储历史 → 每条带 marker 的 covered 消息每轮都 churn id。drift 门只特判 reasoning 丢弃(Per-wire continuity proofs + reasoning-drop tolerance (model-switch / fork-adoption / mode-upgrade) #2732),strip-churn 的文本落入 totalDrift。本 PR 把「剥 marker 行」扩成「四条 wire 全剥 body/nudge/panel」,使 ≥10 阈值被稳定触发。
  3. 影响范围与严重度:≥10 条 marker-covered 轮次、连续 ≥3 pass(即 acp_status visibility markers: stripMarkerLines removes the head line but leaves the multi-line report body in incoming history (#1029 follow-up) #2789 受害群体)。危害:①假 ERROR「substrate destroyed」日志;②可能误写 native-compaction-inferred conflict;d)我补的一条——stream.ts:356 一旦 latch,会把「cannot be anchored」误标为「结构性破坏,去报告」而非「内容已变,用新 ref」,主动误导模型放弃良性重引用恢复。非数据丢失(不 reap、不停压缩,re-fold 自愈)。严重度:中。
  4. 怎么修复(方案):仿现有 reasoningOnlyDrop carve-out——把已在 prepare:81 算好的 RawStripCounts 总量传入 reconcile 门,把 strip-sanctioned churn 判为非破坏性(不累加 streak、不 latch)。反掩盖双闸:不覆盖真实 dsh compaction witness;仅对「仍有同槽 live 候选」的 unmatched 生效,保证真 total-loss 仍升级。
  5. 是否有回归:该修复本身收窄了 destroy 触发面(新增容忍),风险是掩盖真破坏——由两闸 + 一条「真 total-loss 仍升级」的反掩盖回归测试兜底;需实测确认。
  6. 是否破坏缓存:不涉及缓存/重试/游标/去重键;Tier 1 不改 id 铸造,只改 drift 门容忍逻辑。
  7. 是否改设计方向:不转向架构;是把既有「sanctioned churn 容忍」模式(reasoningOnlyDrop)扩展到第二个 sanctioned 类。
  8. 是否引入新配置:不涉及新 env/config/默认值;仅内部 option 字段。

判定:发现 #3 实证成立且可修;建议本 PR 内修(Tier 1),反掩盖谓词待你点头后我落地(含测试);#1/#2 转 pin;边界注记采纳。此轴未闭合前不合——这是本 PR 在其自身目标群体上引入的回归。

ranxianglei added a commit that referenced this pull request Oct 13, 2026
…es that exercise it (#2989)

The #2815 stack rewired production session identity to
personaConversationOrder (src/session-resolve.ts) and retired
src/persona-anchor.ts from the wiring, but the proof surface kept
driving the retired module: three suites pin its ladder, six suites
reset only its (now inert) anchor map while the LIVE order skeletons
never reset, and nothing pinned the new resolver's contract directly.

- tests/session-resolve-twins.test.ts: live twins for the full ladder
  (claim/shallow tag claim/|sub:aux, match/ride, fork-lane byte
  continuity vs a locally computed sha256-16 so persisted pre-upgrade
  lanes keep their keys, grown/compacted reanchor, line-confined model
  switch migration, post-restart chain-race rescue + control, head
  truncation, #150 task lane) plus the two DESIGNED divergences from
  the retired ladder pinned explicitly: (a) header-corroborated
  absorption is looser (any persona change + declared model switch),
  (b) tag-less shallow first sight derives |sub:aux.
- Old-vs-new parity was probed exhaustively first: every scenario the
  retired pins cover agrees at the key level except (a)/(b).
- Mark the three retired-module suites as retired pins; do not extend.
- resetSessionOrderForTest() beside every resetPersonaAnchorsForTest()
  call site (incl. dsh-persona-fingerprint's startRig) so test
  isolation covers the live state.

Refs #2989
ranxianglei added a commit that referenced this pull request Oct 13, 2026
…es that exercise it (#2989)

The #2815 stack rewired production session identity to
personaConversationOrder (src/session-resolve.ts) and retired
src/persona-anchor.ts from the wiring, but the proof surface kept
driving the retired module: three suites pin its ladder, six suites
reset only its (now inert) anchor map while the LIVE order skeletons
never reset, and nothing pinned the new resolver's contract directly.

- tests/session-resolve-twins.test.ts: live twins for the full ladder
  (claim/shallow tag claim/|sub:aux, match/ride, fork-lane byte
  continuity vs a locally computed sha256-16 so persisted pre-upgrade
  lanes keep their keys, grown/compacted reanchor, line-confined model
  switch migration, post-restart chain-race rescue + control, head
  truncation, #150 task lane) plus the two DESIGNED divergences from
  the retired ladder pinned explicitly: (a) header-corroborated
  absorption is looser (any persona change + declared model switch),
  (b) tag-less shallow first sight derives |sub:aux.
- Old-vs-new parity was probed exhaustively first: every scenario the
  retired pins cover agrees at the key level except (a)/(b).
- Mark the three retired-module suites as retired pins; do not extend.
- resetSessionOrderForTest() beside every resetPersonaAnchorsForTest()
  call site (incl. dsh-persona-fingerprint's startRig) so test
  isolation covers the live state.

Refs #2989
YunzhouLi-hub pushed a commit to YunzhouLi-hub/billion-context that referenced this pull request Oct 13, 2026
…session-resolver (ranxianglei#2989)

The ranxianglei#2815 stack swapped production session-identity wiring to
personaConversationOrder (src/session-resolve.ts); persona-anchor.ts is
retired from production but at least seven suites still pinned it.

- issue2601-model-drift-absorption: 7 live-twin tests over the same
  corpus — shared expectations where OLD and NEW agree (absorption keeps
  the raw key, fork keys byte-identical), designed divergences marked:
  v2 folds model-switch absorption into the reanchor branch (no separate
  action), requires a deep main-shaped history (shallow switches fork),
  and never parses system line-diff (drift + header change rides raw).
- dsh-persona-continuity: twin unit block with one shared key
  expectation per old-ladder row; e2e rigs already run through live
  wiring and pass unchanged.
- issue2601-persona-fork-lineage: twin for the resolvePersonaKey
  migrate row — the re-serialized switch rides raw via the continuation
  branch on order+fragment evidence; control arm proves unproven
  switches still fork. Part-A chainContinues rows kept: prefix-affinity
  stays LIVE (server.ts anonymous-ladder).
- Category B (fingerprint/durable-tool-identity/issue2419/2446/2447/
  2481/responses-instructions-drift): rig hygiene now resets the live
  session-order registry instead of the retired anchor ladder
  (dsh-persona-fingerprint's import was dead — its absence leaked
  skeletons across rigs; now reset in startRig like every sibling).
- issue2944-neutral-skeleton / session-continuity-proof: label stale
  references to the retired module.

Targeted verification: 12 suites, 91 tests green; typecheck clean;
new import-graph gate passes.
ranxianglei added a commit that referenced this pull request Oct 13, 2026
…ows EBUSY)

The full-mode leg leaked the sidecar handle (cancelAll does not close
index.db) and used plain rmSync — EBUSY on the windows runners. Same fix
pattern as #2815's export-jsonl legs.
RodrigoHamuy pushed a commit to RodrigoHamuy/billion-context that referenced this pull request Oct 13, 2026
…l full-suite runs

Local full-suite runs are environment noise (firewalled live lanes, port
collisions with a concurrently running bili — claude-native on 18787, ranxianglei#394 —
cross-file interference): the ranxianglei#2815 review session saw ~20 env-failure false
positives locally while the CI test lanes (scripts/run-ci-tests.mjs, ranxianglei#2816)
were the ground truth — including catching the real codex-turn-isolation
regression. Codify: targeted suites locally, full-suite green/red from the
pushed head's CI test lanes (§7.2, §7.4 item 3, §3 command table).
@github-actions github-actions Bot mentioned this pull request Oct 14, 2026
@ranxianglei
ranxianglei deleted the 2026-10-11_marker-declarative branch October 15, 2026 05:33
aolshevskiy pushed a commit to aolshevskiy/billion-context that referenced this pull request Oct 19, 2026
…eanups (ranxianglei#3818)

- resolveStorageMode: absent-everywhere default shadow -> full (ranxianglei#3818;
  the shadow dry-run reconciled cleanly since ranxianglei#2815 - JSON envelopes
  keep being written, legacy remains the one-line escape hatch)
- writerOff saves: a mid-build 3-strike sidecar disable now lands one
  synchronous JSON envelope write in the same tick (ranxianglei#3135 1)
- persistence disabled (BILI_PERSIST=0 / enabled:false) is recorded as
  an intentional opt-out - no fabricated storage-degraded banner (ranxianglei#3135 2)
- the storageMode stamp follows the live instance: a dead/absent sidecar
  stamps legacy so records describe the copy that actually holds data
  (ranxianglei#3135 3)
- verifyDrift + driftedSessions on the /__bili/status wire; drifted
  sessions serve from the JSON envelope until a clean sample (ranxianglei#3135 4)
- self-bootstrap: an unloadable cached engine copy is removed and one
  pinned sha512 download retried instead of warn-forever-stuck (ranxianglei#3135 5)
- bounded boot unions index-only sessions so jsonWriter=off sessions
  stay enumerable after restart (ranxianglei#3135 6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant