Skip to content

fix: teach code-mode (PTC/run_code) harnesses the ACP calling conventions + name the project in the system prompt (#3252) - #3298

Merged
ranxianglei merged 11 commits into
masterfrom
2026-10-15_ptc-runcode-support
Oct 16, 2026
Merged

ranxianglei merged 11 commits into
masterfrom
2026-10-15_ptc-runcode-support

Conversation

@ranxianglei

@ranxianglei ranxianglei commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

(ai: zhipuai-lb/glm-5.3)

Fixes #3252

What breaks today

Two code-mode (PTC) problems, plus one identity problem:

  1. Plugin lane (what the reporter actually hit): in a dsh PTC session, the model occasionally calls compress directly as a JSON tool call. dsh refuses it (PTC collapses everything except run_code into SDK bindings), the model sees the error and self-corrects — a wasted turn, sometimes a confusing loop.
  2. Pure proxy lane: dsh's PTC preset tells the model "only run_code is callable directly", so the model writes await tools.compress(...) inside a run_code program. Under pure proxy there is no such SDK binding — that call fails and the model falls back to a direct call, which the proxy happily executes server-side. Again a wasted turn.
  3. Models using billion-context generally have no idea they are: nothing in the prompts says what provides their context management or where problems should go.

Fix 1 — plugin lane: manifest descriptions carry the calling convention

The tool descriptions served by /__bili/plugin/manifest (the single description source for every host runtime: pi, omp, dsh, opencode, MCP shim) now end with a conditional note:

Calling convention: if this environment only allows run_code to be called directly (code-mode/PTC harness), call this tool from inside a run_code program via the harness's generated SDK; otherwise call it directly as a tool.

One wording serves both dsh presets (native = direct call, PTC = via run_code), because it is conditional. Applied to all five ACP tools on all three wires.

Fix 2 — pure proxy lane: auto-detect run_code, declare the exception

When a proxied request's own tools array contains a tool literally named run_code (the wire signal every code-mode harness already sends — no new config, no dsh changes, no headers), the injected descriptions switch to the opposite wording:

If a harness rule says only run_code may be called directly, this tool is the exception: it has no run_code SDK binding, so call it DIRECTLY as a normal tool call — the proxy executes it server-side.

This is deliberately the mirror image of fix 1: under pure proxy there IS no binding, so teaching the model to use run_code would guarantee a failure; declaring the exception is the only correct advice. Requests without a run_code tool get descriptions byte-identical to today's.

Fix 3 — both lanes: the system prompt names the project

One static line appended to the injected compress system prompt on all four wires:

Context management for this conversation is provided by billion-context (github.com/ranxianglei/billion-context). Report billion-context problems to that project's issue tracker.

Plugin mode injects the system prompt too (it skips only TOOL injection — the host registers manifest tools natively; pinned by tests/plugin-nudge-injection.test.ts #451), so both lanes get it. Static string, so the system block stays byte-stable across turns and the prefix-cache anchor survives (one-time invalidation on upgrade only).

Pack discipline

Tool descriptions explicitly overridden by a compress.promptPack are skipped verbatim-landing style — pack text must land byte-for-byte (pinned by tests/prompt-pack-tool-prompts.test.ts + tests/anthropic-pck-verbatim.test.ts). The other four tools still get the notes.

Scope / constraints

  • Zero kernel/ changes (kernel boundary untouched; kernel.json golden byte-identical).
  • No new config keys or env vars — everything is auto-detected from the wire.
  • Golden regen (manifest-default.json / manifest-optin.json only — the five tools' descriptions × 3 wires): regenerated explicitly via node --import tsx scripts/update-wire-contract-goldens.ts.

Tests

  • New tests/ptc-runcode-tools.test.ts (12 cases): four wires × with/without run_code (exempt note appears only with run_code; binding note never on proxy lane), URL note only on compress, manifest serves binding note + URL, pack description override lands verbatim while others keep notes, byte-stability (same input → identical output twice), client tool arrays untouched, injectSystem carries the attribution line while the client system block stays byte-exact.
  • Re-run green: prompt-pack-tool-prompts, anthropic/openai-pck-identity, anthropic-pck-verbatim, wire-contract-golden, wire-contract, absorb-plugin, dsh-acp, ccr-plugin, cache-friendly-proxy/plugin, fix-920, external-summary-autofold, plugin-protocol, e2e-compress-prompts, loop-strict-echo, e2e-proxy-smoke, e2e-plugin-tool-routing, anthropic-cache-control, mcp-native-thread, plugin-nudge-injection, e2e-stable-system-anchor.
  • typecheck clean. Full suite left to CI.

Review fixes (independent review, commits after the author's four)

fix: apply project attribution on the round-2 relay rebuild (5f0591b)

The first head wrapped the four steady prepare sites (src/server/inject.ts, prepare-openai/responses/google.ts) but missed the in-turn re-request rebuild at src/server/relay.ts (stream branch). After an ephemeral compress fold the re-request system prompt lost the attribution line, mutating head bytes across every fold boundary — the whole byte-stability family failed (cache-proof 10/13 locally; CI shards red). Fix: same outermost withProjectAttribution(...) composition as the four steady sites. Verified by A/B: cache-proof 10/13 → 13/13.

Behavior change disclosure (old → new)

The attribution line grows the injected compress system prompt by ~78 est-tokens of wire overhead on EVERY proxy-mode request (all wires; plugin manifest lane unchanged). Consequence at the boundary: a session whose post-preflight-fold payload estimate lands within that margin of the model window now trips the #330 soft-recent-zone relaxation gate (fold the soft-protected recent zone oldest-first until it fits) instead of forwarding the still-slightly-over-window payload verbatim. Old: such boundary sessions forwarded verbatim (estimates are conservative; upstream usually accepts). New: they lose the tail's verbatim form into the summary (restorable via decompress). This is inherent to adding any bytes to the steady system prompt — no config surface added or changed.

test: restore margin in preflight fixtures knife-edged by the attribution line (4f83173 + f2d5ed0)

Three test files sized their 12-message conversations so the post-fold estimate landed ~16 est-tokens UNDER the 10k window (instrumented traces: 9984 master / 10062 this branch). The +78-token line flipped the #330 soft-zone relaxation gate and ate the protected tail deterministically: tests/preflight-hold.test.ts (#568), tests/preflight-compress-responses.test.ts (#280), and tests/preflight-max-output-tokens.test.ts (#663 anthropic variant — there the over-fold leaves a single anchor message that the mock's shape classifier misreads as a summary call). Fixture fix only: repeat(250) → repeat(235) restores ~700 est-tokens of margin on BOTH master and this branch; all assertions unchanged (markers 1-3 folded, marker 11 protected, summary carrier, lastInputTokens). Verified green on both trees for each file.

Storage-render goldens regenerated on-branch (d37fe6f, concurrent agent commit)

The four tests/golden/storage-render/*.json snapshots were rebaselined on this branch via scripts/update-storage-render-goldens.ts: they now carry the attribution line + compress-tool URL note (+318 bytes on the chat snapshot) and also absorb the #3295/#3080 state-shape drift that red-masters master today (#3313/#3315 sub-defect 1). Local verify at tip: golden-storage-render + storage-engine-proofs 17/17 green. Merge-order interaction: #3314 (master-side rebaseline WITHOUT the attribution line) collides with these files — whichever of #3298/#3314 lands second must re-run the golden regen script; the post-#3298 master goldens are exactly this branch's set.

Red-master note (out of scope here)

golden-storage-render ×4 wires and storage engine: full-mode restart invisible ×4 wires fail identically on PURE master (6ee4a2a) — locally and in CI (master's own CI run is red). Not caused by this branch; tracked separately.

Verification at this head (local, targeted)

ptc-runcode-tools 12/12 · wire-contract 20/20 · wire-contract-golden 5/5 · cache-proof 13/13 · preflight-hold 4/4 · preflight-compress-responses 1/1 · typecheck clean. Full-suite verdict = remote CI on 4f83173.

ework-agent and others added 3 commits October 15, 2026 22:21
…ions (#3252)

Code-mode harnesses (dsh "PTC" preset, Cloudflare-style code mode) collapse
every registered tool behind one directly-callable run_code tool. That hit
the ACP surface differently per lane:

- plugin lane: the model slips a direct compress call the harness rejects
  (ToolNotFoundError: only run_code is callable directly), wasting a turn
  before self-healing — the #3252 report.
- proxy lane: the injected ACP tools have no run_code SDK binding, so a
  program-side call can only fail, while a direct call is executed by the
  proxy's tool loop upstream of the harness.

Fix, description-side at both serving sites (zero config, zero kernel
changes):

- manifest (handlePluginManifest): every ACP entry gets a conditional
  binding note ("if only run_code is callable, call from inside a run_code
  program via the harness SDK; otherwise call directly") — one manifest
  serves native and code-mode hosts alike.
- proxy (injectTool/injectOpenaiTool/injectGoogleTool/injectResponsesTool):
  when the client's own tools array carries run_code, the ACP entries get
  the exempt note ("this tool is the exception — call it DIRECTLY; the
  proxy executes it server-side").
- compress additionally names the project (owner request): billion-context
  attribution + issue-tracker URL, both lanes.
- a pack toolPrompt with an explicit description override still lands
  verbatim — the notes are skipped for exactly those tool names
  (pck-verbatim contract preserved).

Golden regen: manifest-default/manifest-optin re-pinned via
scripts/update-wire-contract-goldens.ts (description strings only; kernel
schema bytes untouched).

Fixes #3252
Owner request: the model should know what provides its context
management and where problems belong. Append one static line naming
the project and its issue tracker to the compress system prompt on
all four wires (anthropic/openai/google/responses).

Both lanes get it: plugin mode skips only TOOL injection — the system
prompt still rides the proxied request (pinned by
tests/plugin-nudge-injection.test.ts #451). The line is a static
string, so the system block stays byte-stable across turns and the
prefix-cache anchor survives (one-time invalidation on upgrade).

Refs #3252
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-10-15_ptc-runcode-support (dc47d2a)

Option A — Install this exact build (recommended)

npm install -g billion-context@0.0.3913-pr.3298.d9724aa

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

Install instructions are refreshed on each push.

ework-agent and others added 2 commits October 15, 2026 23:02
The type is only consumed inside src/compress-tool.ts (acpNoteFor /
withAcpNotes* / ptcNoteMode signatures) — export removed so the CI
unused-exports guard stays green. Behavior unchanged.

Refs #3252
Sync with master after #3266 (image-compression removal) landed: resolve the
three import-line conflicts in prepare-{google,openai,responses}.ts by union —
keep #3266's IMAGE_FULL_TOOL_* removals and add this PR's withProjectAttribution.
Typecheck + targeted suites (ptc-runcode-tools, wire-contract, golden, packs,
plugin-nudge-injection) green on the merged head.
@ranxianglei
ranxianglei force-pushed the 2026-10-15_ptc-runcode-support branch from 745614b to 58cf3d6 Compare October 15, 2026 15:43
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

查重:不重复 —— 按 PTC / run_code / calling convention / #3252 检索了 open+closed 的 issue 和 PR,同症状/同机制只有原 issue #3252,本 PR 是它的唯一实现条目,无并列修复。

审核方式说明:本 PR 是 agent 提交(zhipuai-lb/glm-5.3),我独立重读了全部 diff(9 文件 +342/-47)、对照当前 master 逐条核实了 PR 声明,并在本地临时 worktree 做了 master 同步 + 定向测试。结论如下。

① 方向关(审原 issue #3252)

#3252 根因 = ACP 工具描述字节归 bili 所有、注入在 dsh 与上游之间,措辞一律"直接调用",与 dsh PTC 的"仅 run_code 可直接调"约定冲突。PR 的方向(描述层同时教两种约定 + proxy 侧自动检测 run_code + 系统提示词点名项目)打的是根因层,且对非 PTC 客户端零行为变化——成立。#3252 floor-2 分析给过零代码 pack 方案并把"自动应用"列为待决策项;本 PR 实现的就是其中的自动检测变体(比"等 dsh 发信号头"更省事,且无需 dsh 配合)。

② 回归审查(既有行为清点)

  • 四条 wire 全覆盖已逐行核实:anthropic 走 src/server/inject.ts 的 injectSystem/injectTool(prepare-anthropic.ts:319/327),openai/google/responses 各走自己的 prepare 文件,共 4 个系统提示词注入点 + 4 个工具注入点。
  • 双模式推理:plugin 模式只跳过工具注入,系统提示词仍随请求走(prepare-anthropic.ts:319 无条件调 injectSystem)→ attribution 行两种模式都生效,与 PR 声明一致。
  • pack verbatim 契约保持:packOwnsDescription 只跳过 description 被 pack 整段接管的工具;仅 paramDescriptions 覆盖的工具仍挂注记(有测试钉住)。
  • 默认面字节稳定:无 run_code 的请求,描述字节不变(byte-stable 测试钉住);attribution 行是静态字符串,升级时前缀缓存一次性失效,之后跨轮稳定——PR 正文已披露。
  • 高危模式逐项过:无阈值/时序/输出格式漂移;错误处理语义未变;无 fail-fast 变吞错。
  • kernel/ 零改动、不碰 update.ts、无新配置键/env var(config-surface 纪律合规)。

③ 代码审查

逻辑干净:ptcNoteMode 精确名匹配 run_code;withAcpNotes/withAcpNotesOpenAI 只动 ACP 工具名内的条目,非 ACP 条目原样透传;Google wire 正确跨 functionDeclarations 收集名字。注释讲为什么且有 issue 锚点,风格与仓库一致。

④ 测试有效性

新测试 12 case 全是对真实函数的真断言(injectTool/injectOpenaiTool/injectResponsesTool/injectGoogleTool/handlePluginManifest/injectSystem),覆盖双 lane × 多 wire × pack 交互 × byte-stability × attribution 行落位。有牙:任何一条注记回归或 pack 契约破坏都会红。不是 mock 自嗨。

⑤ diff 整洁度 & 发现的问题(已修)

diff 本身干净(每行都服务于 #3252)。但发现一个实际问题:分支落后 master 31 个提交,窗口内 #3266(移除 image-compression/image_full,feat!)改到了同一批文件——直接合并会在 prepare-{google,openai,responses}.ts 三处 import 行产生文本冲突,mergeable 状态为 dirty。

已处置(小问题直接修):我把当前 master 合入 PR 分支(union 解法:保留 #3266 的 IMAGE_FULL_TOOL_* 移除 + 本 PR 的 withProjectAttribution),push 到分支,新 head 58cf3d66b。合并树上本地验证:typecheck clean;tests/ptc-runcode-tools.test.ts 12/12;wire-contract 20/20;wire-contract-golden 5/5(golden 无需重新生成——manifest 本来就不含 image_full);packs/plugin-nudge-injection/cache-ledger 相关 34/34 绿。

残余风险(一行)

proxy lane 的 exempt 注记依赖 dsh PTC 代理请求的 tools 数组里确实带名为 run_code 的工具——这是 dsh 侧实现细节,我从这里无法验证;若 dsh 把它剥掉,注记不触发,退回原行为(不会更坏)。建议合并后让 #3252 报告者实测一轮确认。

结构化八问

  1. 是什么问题:dsh PTC(code-mode)下模型按 bili 注入的描述直接调 compress/decompress 等 ACP 工具,被 harness 拒绝,浪费往返。
  2. 什么原因导致的:ACP 工具描述由 bili 注入且措辞固定为"直接调用",PTC 的调用约定变更无处落地,两套指令冲突。
  3. 影响范围与严重程度:仅「proxy 模式 + code-mode/PTC harness」组合;每次发生 = 一轮无效往返(harness 报错会引导自纠),无数据丢失;其他客户端/模式零影响。
  4. 怎么修复的:描述层双轨教学——plugin lane manifest 恒挂"条件式"注记(两种约定都教);proxy lane 检测到客户端自带 run_code 时改挂"豁免"注记(这些工具没有 SDK 绑定,直调反而对);另在压缩系统提示词静态点名 billion-context 及 issue tracker。
  5. 是否有回归问题:审过的既有行为(四 wire 注入、双模式、pack verbatim、byte-stable、golden ledger)均保持;attribution 行使所有部署的系统块在升级时变一次字节(一次性缓存失效,已披露)。
  6. 是否破坏缓存:仅升级瞬间一次性前缀失效;稳态下注记/attribution 均为静态字符串,跨轮字节稳定,不反复失效。
  7. 是否改了设计方向:没有。
  8. 是否引入了新的配置:没有新 key/env var/默认值。

判定:可合(暂扣最终确认) —— 代码与回归审查全部通过,master 同步已推(新 head 58cf3d66b,12 个 CI 任务已排队)。按本地测试纪律,全量套件以远程 CI 为准;CI 绿后我回帖确认收工。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

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

进度汇报(上一条完整 review 之后):我这边进程在等 CI 时被平台重启了一次,现补报当前状态——

  • CI(新 head 58cf3d66b,含我推的 master 同步合并):12 个任务里 11 个已全绿——全部 e2e lane(real codex / fake-codex / codex-persona / native-dsh / native-opencode / native-pi / pi-codex-ws / dsh-plugin-lane / local-registry)、Windows codex overlay、PR Build Artifact。这些 e2e 正是真客户端穿过请求管线的全生命周期回归,对本 PR 触碰的注入路径覆盖最直接。
  • 仅剩主 CI(hermetic 全量测试:3 shards × ubuntu/windows × node 22/24)还在跑。它绿了我立刻回帖确认收工;若红,我会定向排查后报告。

代码审查结论维持上一条不变:可合(待主 CI 绿)。无其他阻塞。

…am parity, #3298)

The PR added withProjectAttribution to the four steady prepare* sites but missed the in-turn re-request rebuild in relay.ts (stream branch). After an ephemeral compress fold the re-request system prompt lost the attribution line, so head/system bytes mutated across every fold boundary - cache-proof failed 10/13 on the merged tree (pure master: 13/13). Wrapping this site identically (attribution outermost, mirroring prepare* composition) restores byte-stability.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

进展汇报:CI 全红已定位并修复,修复 commit 已推到 PR 分支,等新一轮 CI。

上一轮我报「11/12 绿」时 main CI 还没跑完——现在结果出来了:main CI 的 12 个测试 shard 全红。我没有直接当环境噪声放过,做了 A/B 隔离:

  • 纯 master(6ee4a2ac9)本地跑 tests/cache-proof.test.ts:13/13 通过 → master 不红;
  • PR 合并树跑同一文件:10/13 失败,报错全是缓存缝字节稳定性家族(fold mutated pre-anchor element[0] / fold mutated the head)。

根因(本 PR 引入的真回归):PR 把「系统提示尾部的项目署名行」(withProjectAttribution)加在了四个稳态 prepare 路径上,但漏了轮内二次请求的重建点 src/server/relay.ts:1440。后果是:触发压缩那一轮的外发请求带署名行,而 ephemeral compress 折叠后的重发请求把这一行丢了 → 每次折叠边界处头部/system 字节漂移 → 前缀缓存断缝。这正是 cache-proof 套件钉住的不变量(该处注释本来就写着必须与稳态路径逐字节一致)。

修复:在 relay.ts 同一位置按相同顺序包上 withProjectAttribution(署名行在最外层,与四个稳态点完全一致),5 行改动,独立标注 commit:

本地定向验证(修复后):typecheck 干净;cache-proof 13/13(修复前 10/13);本 PR 新增 ptc-runcode-tools 12/12;wire-contract 20/20 + golden 5/5。全量回归交给远端 CI。

等 5f01b1c 这轮的 CI 结果出来我再给最终确认(八问结论以那轮为准)。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

更正上一条最后一行笔误:修复 commit 是 5f0591b1c(不是 5f01b1c),等这轮 CI 结果。

…tion line (#3298)

The two preflight regression fixtures sized their 12-message conversations so that the post-fold payload estimate landed ~16 est-tokens UNDER the 10k window. The project-attribution line added by this PR grows the injected system prompt (~78 est-tokens of wire overhead), which pushed the same post-fold view ~78 tokens higher — across the window — and flipped the #330 soft-recent-zone relaxation gate from 'fits, stop' to 'overflow, fold the protected zone'. Result: e2e #280 (Responses) and #568 (preflight-hold) lost their protected tail on every run.

Fix: repeat(250) -> repeat(235) in both fixtures restores ~700 est-tokens of margin on both master and this branch (verified A/B with instrumented preflight traces: old landing 9984/10062 vs new ~9212/~9290 against the 10000 target). Assertions are unchanged — markers 1-3 still folded, marker 11 still protected, summary carrier and lastInputTokens assertions intact. The guard now pins behavior instead of a knife-edge that any future system-prompt growth would trip.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

第二组回归已定位并修复,新 head 4f83173 已推上分支,等 CI。

机制(instrumented A/B trace 钉死):两个 preflight 回归测试的 fixture 是刀口尺寸——12 条消息折完后的 payload 估算值落在 10k 窗口下仅 ~16 est-tokens(master 9984 / 本分支 10062,目标 10000)。本 PR 的署名行给每次请求的注入 system prompt 增加 ~78 est-tokens wire overhead,把同一视图从「刚好低于窗口」推到「高于窗口」,翻转了 #330 软保护区松弛门:master 在保住最近 5 条原文处停手,本分支多折一刀把受保护尾部吃掉。e2e #280(Responses)与 #568(preflight-hold)因此确定性失败。两树各自插桩跑同一测试,逐轮 decisionTokens 差值恒为 +78,与署名行长度精确吻合。

修复(只动测试 fixture,断言零改动):两处 repeat(250) → repeat(235),恢复 ~700 est-tokens 余量;marker 1-3 仍被折、marker 11 仍受保护、summary 载体与 lastInputTokens 断言原样。master 树与本分支树双向验证全绿(guard 现在钉行为而不是钉刀口——未来任何 system prompt 增长都不会再触发同样的假失败)。

行为变更披露(旧→新,必须让你知道):署名行让每个 proxy-mode 请求的稳态 system prompt 永久 +~78 est-tokens。边界效应:post-fold 估算值落在窗口下 ±78 tokens 内的会话,以前会按原文转发(估算偏保守、上游通常接受),现在会触发 #330 软区松弛、把受保护尾部折进 summary(decompress 可还原)。这是往稳态 system prompt 里加任何字节的固有代价,无新增配置面。PR 描述已补完整披露节。

红 master 说明(非本 PR 引入,查重后不另立项):golden-storage-render ×4 与 storage-engine full-mode restart ×4 在纯 master 6ee4a2a 上本地+CI 同样失败——已有 #3313(记录)、#3314(金标 rebaseline PR 在途)、#3315(含偶发用例),签名一致,属存量问题。

本地定向验证(4f83173d3):ptc-runcode-tools 12/12 · wire-contract 20/20 · wire-contract-golden 5/5 · cache-proof 13/13 · preflight-hold 4/4 · preflight-compress-responses 1/1 · typecheck clean。全量以 CI 为准,绿了我发最终确认。

ework-agent and others added 2 commits October 16, 2026 02:47
…am (#3252)

The compress/absorb loop's round-2 replay rebuilt its system prompt
without the project attribution line, so the trigger turn and the
replay diverged in the pre-summary head — every cache-friendly,
cache-proof and seam-probe leg went red. Wrap the relay loop's
buildCompressSystemPrompt output with withProjectAttribution (inner
wrap: attribution lands between the compress prompt and the absorb
section, byte-matching the inject/prepare shape).

Storage-render goldens regenerated via
scripts/update-storage-render-goldens.ts: wire bodies now carry the
attribution line and the compress tool URL note (+318 bytes on the
chat snapshot); they were also stale from #3295/#3080.
@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

第 3 轮 CI(head 4f83173)已出:11/12 lane 绿,main CI 红——失败全部完成分类,其中发现第三个刀口 fixture,已修复并推上 f2d5ed0。

先前两个 preflight 回归确认已在 CI 转绿:ok 1382 e2e #280、ok 1385/1388 #568。

第 3 轮失败逐条定性:

当前状态:分支 tip f2d5ed0(= 署名行 + relay seam 修复 + 三个刀口 fixture + 金标重基线),等第 4 轮 CI。预期剩余红面只有 #3317 未合入前的 T5 与偶发 AC12;若还有别的红我继续追。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

第 4 轮 CI(head f2d5ed0)已出,审核收尾。此前「可合(暂扣最终确认)」升级为:可合。

CI 终态:main CI 7/12 shard 全绿;5 个红 shard 的失败全部为已跟踪存量,与本 PR 无关——#1086 T5 liveness ×4(红 master 确定性,修复在途 #3317)+ plugin-terminal-usage windows/22 超时 flake ×1(恰好 10000ms testTimeoutFailure,本地 Linux 9/9 确定性通过,签名已补进 #3315)。本 PR 相关的全部 lane(ptc-runcode-tools、wire-contract、golden、cache-proof、三个 preflight fixture、storage-render/storage-engine 金标、AC12)本轮全绿。

结构化八问:

  1. 是什么问题:原 issue PTC模式下 模型直接调用了 compress工具, 没有走run_code, 这块能不能在 billion-context 的几个工具中明确一下PTC要走run_code调用? #3252——PTC/code-mode harness 只允许直调 run_code,模型直调 bili 注入的 ACP 工具被拒、浪费一轮;本 PR 教工具描述与系统提示词两种调用约定,并在署名上点明项目名。
  2. 什么原因导致的:审核中发现本 PR 自身引入两类回归——(a) round-2 relay 重建(src/server/relay.ts stream 分支)漏了署名行 wrap,fold 边界后 system prompt 字节漂移,击穿整套 byte-stability 门禁;(b) 署名行给每次请求 +~78 est-tokens wire overhead,把三个 preflight 测试的刀口 fixture(折完估算 9984→10062 vs 窗口 10000)翻过 preflight fail-fast × soft-protection livelock: over-window payload with nothing foldable outside the protected zone 502s forever #330 软区松弛门,受保护尾部被多折一刀。
  3. 影响范围与严重程度:行为变更面 = 所有 proxy-mode 请求(system prompt 永久 +~78 est-tok);边界会话(post-fold 估算落在窗口 ±78 tok 内)从「按原文转发」变为「触发软区松弛、尾部折进 summary(decompress 可还原)」——这是往稳态 system prompt 加字节的固有代价,体验级而非数据丢失;无 run_code 的请求工具描述逐字节不变。
  4. 怎么修复的:(a) relay.ts round-2 站点按四个稳态 prepare 站点同样的最外层 withProjectAttribution(...) 组合补齐(cache-seam parity,A/B 验证 cache-proof 10/13→13/13);(b) 三个刀口 fixture repeat(250)→repeat(235) 恢复 ~700 est-tok 余量,断言零改动,两树双向验证;(c) storage-render 金标在分支上重基线(并发 commit d37fe6f),顺带吸收红 master 的 state 漂移。
  5. 是否有回归问题:无本 PR 引入的残留回归。既有行为逐项过:两条压缩模式(plugin manifest / proxy 注入)×四条 wire 的描述与 system 组装、pack 覆盖纪律(promptPack 自持 description 不追加)、客户端 system 块前缀稳定性、cache-seam 字节稳定(fold 前后)、preflight 折叠语义(仅刀口余量恢复)——本地定向全绿 + CI 四轮收敛验证。
  6. 是否破坏缓存:否,恰恰相反——修复 (a) 的目的就是恢复 fold 边界的字节稳定;署名行是静态行、追加在客户端 system 块之后,请求间不变,前缀缓存锚点不受影响。
  7. 是否改了设计方向:否。wire 形状不变、无新配置面(未新增任何 env/config key,符合配置面纪律)、kernel/ 零改动。
  8. 是否引入了新的配置:无。

合入顺序交互(已在 PR 描述披露):#3314(master 侧金标 rebaseline,无署名行版本)与本分支的四个 storage-render 金标文件冲突——#3298 与 #3314 谁后合谁重跑一次 scripts/update-storage-render-goldens.ts;#3298 合入后的 master 金标本应等于本分支这套。T5 的红面要等 #3317 合入后才清。

最终判定:可合(合并动作按规矩留给你;PR 分支 tip f2d5ed0,描述已含完整披露节)。

@ranxianglei

Copy link
Copy Markdown
Owner Author

(ai: zhipuai-lb/glm-5.3)

Remaining red on this branch is inherited from master, not introduced here.

  • Heads d37fe6f/f2d5ed0b fail 4/4 shard-2 legs on #1086 T5 liveness (nonEmptyReplies 25/60).
  • Master's own push run 38767006158 (6ee4a2a, no PR code) fails the same T5 on 9 legs, plus AC12 and the storage-render goldens.
  • Locally T5 passes on this branch under node 22 and 25, alone, 4× concurrent, and via CI_TEST_SHARD=2/3 node scripts/run-ci-tests.mjs — could not reproduce outside CI runners.

Branch-local deltas beyond that are verified green locally: round-2 relay attribution parity (cache-friendly/cache-proof/seam-probes 37/37 — the relay site rebuilds the system prompt with withProjectAttribution between the compress prompt and the absorb section, byte-matching the prepare* shape), storage-render goldens regenerated (+318 bytes = attribution + compress URL note, they were also stale from #3295/#3080), issue1086 suite 21/21, typecheck clean.

Suggest merging after master's T5/AC12 stabilization lands (tracked separately), or rerunning this branch's matrix once master is green.

@ranxianglei

Copy link
Copy Markdown
Owner Author

(ai: zhipuai-lb/glm-5.3)

Remaining reds on f2d5ed0b are inherited from master, not introduced by this PR.

  • The 4 failing shard-2 legs all fail #1086 T5 liveness ("every client turn must get a visible reply", nonEmptyReplies 25/60).
  • Master's own CI run 38767006158 (push 6ee4a2ac, no PR code involved) fails the exact same T5 signature on 9 legs, plus AC12 multi-hop grandchild and the 4 storage-render goldens.
  • Re-running the failed jobs on this PR reproduces T5 4/4 — deterministic on CI runners, but not reproducible locally in any configuration: tests/issue1086-chain-self-exemption.test.ts is 21/21 under node 22.14 and node 25, standalone, 4× concurrent copies, and via the exact CI shard runner (CI_TEST_SHARD=2 node scripts/run-ci-tests.mjs).
  • CI failure logs show [acp-loop] round 1: upstream stream truncated (no completion event; 0 text chars) on the affected turns — a stream-level truncation under runner conditions, orthogonal to the byte-level changes in this PR.

This PR's own deltas are verified locally: 37/37 targeted tests, cache-friendly / cache-proof / cache-seam-probes / storage-render goldens all green after the round-2 attribution parity fix (relay.ts), the PTC tool notes, and the golden regen.

Suggestion: wait for master's stabilization (in flight), then re-run this PR's matrix — no further changes needed on the branch unless the rerun surfaces something new.

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

与我们第 4 轮(head f2d5ed0)的分类完全一致,无分歧:剩余红面只剩 #1086 T5 ×4(四个 s2 lane,master 自身 run 同样红,修复在途 #3317)+ 一个 windows/22 的 plugin-terminal-usage 恰好 10s 超时 flake(本地 Linux 9/9 确定性通过,签名已记入 #3315;本轮 AC12 反而过了)。分支内改动相关 lane 全绿这一点两边独立验证吻合。

同意你的收尾建议:等 #3317 合入、master 转绿后本分支重跑一次矩阵即可拿到全绿徽章再合;若不想等,按我最终判定「可合」直接合也行——残留红面均已有独立跟踪项,不构成本 PR 的合并阻塞。合并动作留给你。

@ranxianglei

Copy link
Copy Markdown
Owner Author

🤖 Powered by ework · qwen3.8-27b

[bot] 🏷 (ai: vllm-qwen/qwen3.8-27b)

补一个独立佐证:我从自己保存的第 4 轮 CI 日志里直接核到了你说的截断签名——u22s2/u24s2 两个 T5 腿日志各含 39 处 [sess=liveness-1] [acp-loop] round 1: upstream stream truncated (no completion event; round 1, 0 text chars),全部落在 issue1086 liveness 会话上。即「runner 环境下的流级截断」这条机制链两边各自从原始日志独立钉死,与 PR 的字节级改动正交这一点成立。

结论不变:分支无需再动(f2d5ed0b)。两条路任选——等 #3317/master 转绿后重跑矩阵拿全绿徽章;或按我的最终判定「可合」直接合,残留红面均有独立跟踪项。决定留给你。

ework-agent added 2 commits October 16, 2026 09:12
…3312-#3320 batch)

- keep #3298 changes on master's post-absorb shapes: relay round-2 rebuild
  and all four prepare* paths keep withProjectAttribution; absorb imports/
  sections dropped with #3309
- storage-render goldens: metadata-section drift after the merge (absorb
  fields gone from session metadata) — regenerated via
  scripts/update-storage-render-goldens.ts, wire-body sections unchanged
@ranxianglei
ranxianglei merged commit 204bb98 into master Oct 16, 2026
41 of 42 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

📦 Merged Build Published

This merge to master was published as 0.0.481-master.204bb98 (rolling master tag).

npm install -g billion-context@0.0.481-master.204bb98  # this exact build
npm install -g billion-context@master  # always the newest merged build

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

ranxianglei added a commit that referenced this pull request Oct 16, 2026
Restore the absorb machinery reverted by #3309, as the base for the
media-scoped revival (#3398): conflicts resolved keeping both the restored
absorb wiring and post-#3309 additions (withProjectAttribution #3298,
withAcpNotes #3252). src/proxy-tool.ts is deleted again — its only export
isProxyToolFor moves back to absorb.ts (absorb-aware, pre-#3309 shape).

This revert is intentionally NOT pushed alone; the media-only scope
restriction lands on top in the same PR.
ranxianglei added a commit that referenced this pull request Oct 16, 2026
Restore the absorb machinery reverted by #3309, as the base for the
media-scoped revival (#3398): conflicts resolved keeping both the restored
absorb wiring and post-#3309 additions (withProjectAttribution #3298,
withAcpNotes #3252). src/proxy-tool.ts is deleted again — its only export
isProxyToolFor moves back to absorb.ts (absorb-aware, pre-#3309 shape).

This revert is intentionally NOT pushed alone; the media-only scope
restriction lands on top in the same PR.
ranxianglei added a commit that referenced this pull request Oct 17, 2026
Restore the absorb machinery reverted by #3309, as the base for the
media-scoped revival (#3398): conflicts resolved keeping both the restored
absorb wiring and post-#3309 additions (withProjectAttribution #3298,
withAcpNotes #3252). src/proxy-tool.ts is deleted again — its only export
isProxyToolFor moves back to absorb.ts (absorb-aware, pre-#3309 shape).

This revert is intentionally NOT pushed alone; the media-only scope
restriction lands on top in the same PR.
ranxianglei added a commit that referenced this pull request Oct 17, 2026
Restore the absorb machinery reverted by #3309, as the base for the
media-scoped revival (#3398): conflicts resolved keeping both the restored
absorb wiring and post-#3309 additions (withProjectAttribution #3298,
withAcpNotes #3252). src/proxy-tool.ts is deleted again — its only export
isProxyToolFor moves back to absorb.ts (absorb-aware, pre-#3309 shape).

This revert is intentionally NOT pushed alone; the media-only scope
restriction lands on top in the same PR.
ranxianglei added a commit that referenced this pull request Oct 17, 2026
Restore the absorb machinery reverted by #3309, as the base for the
media-scoped revival (#3398): conflicts resolved keeping both the restored
absorb wiring and post-#3309 additions (withProjectAttribution #3298,
withAcpNotes #3252). src/proxy-tool.ts is deleted again — its only export
isProxyToolFor moves back to absorb.ts (absorb-aware, pre-#3309 shape).

This revert is intentionally NOT pushed alone; the media-only scope
restriction lands on top in the same PR.
@github-actions github-actions Bot mentioned this pull request Oct 17, 2026
ranxianglei pushed a commit that referenced this pull request Oct 18, 2026
…em prompt

Six margin-tuned scenarios sat within the ~300 est-tok (~1.2KB) the approved prompt growth adds to every outbound request. Each keeps its documented shape; constants old -> new (measured):

- e2e-relay-5xx-selfheal (#604): BIG 12_000 -> 11_500 chars/tool_result. Request-1 estimate was 31851 vs the 32k window (margin ~150); the growth moved it to 32150 and tripped preflight, which the scenario forbids. Now ~30.7k; the full body stays above the relay's hidden 29.5k tolerance.
- issue1933 F2: longMessages(15,4000) -> (14,4000). Estimate was 20014 vs the 20k target (14 over after growth); 14 measures ~19k (no fire), billed 24184 > 20k keeps the stale-baseline regression shape.
- issue2672: protectText repeat 167 -> 106 (~2562 -> ~1700 chars each). Post-half-fold payload was 8106 vs the 8k window -> preflight exhausted -> 413; protected mass is packing-excluded, so range geometry is unchanged and the payload lands ~7.4k.
- preflight-compress-responses (#280), preflight-hold (#568), preflight-max-output-tokens (#663-anthropic): MARKER repeat 235 -> 208. Post-fold residual had only ~80 est-tok of real headroom under the 10k window (the #3298 '~700' comment overestimated it); the growth flipped the same #330 soft-zone relaxation they pin. 208 restores ~600 tok; pre-fold ~15.7k stays well over the trigger.
ranxianglei pushed a commit that referenced this pull request Oct 22, 2026
… tags-only surface

Two coverage gaps found in #4308 review:
- The compress-loop round-2 rebuild recomposes the ACP standing system by
  hand; nothing pinned that a boundary-ACTIVE session keeps byte-identical
  system bytes between the steady request and the post-fold re-request
  (the same seam class #3298/#2499 fixed for attribution/cache marks). New
  tests/issue4305-round2-seam.test.ts drives one real fold through the
  anthropic wire with previous-generation residue seeded in the early turns
  and asserts round-2 system === round-1 system byte-for-byte.
- The tags-only ACP surface (plugin/dsh lane, compressSurfaceOff — the lane
  that produced the #4305 incident) had no injection assertion; added a
  positive+negative pair to tests/generation-boundary.test.ts.
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