Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Versions follow the merge of a `*_release-v*` branch; CI publishes to npm on tag

## [Unreleased]

### Removed
- **compress-at-fold-point 整功能移除(owner 指令 2026-11-10,#6132;v1 #5471 + 未发布的 v2 #5949)**:删除 `compress.compressAtFoldPoint` / `compress.compressAtFoldPointClearThinking` 配置键、`BILI_COMPRESS_AT_FOLD_POINT` / `BILI_COMPRESS_AT_FOLD_POINT_CLEAR_THINKING` env、kernel 的 `relocate-compress-carriers` 管线节点与 `relocateCompressCarriers` / `planRelocateCompressCarriers` 导出、`Config.reasoningDroppable`、v2 的 `already-folded-echo` 解析 kind、web 配置行与 i18n 文案、config-reference/站点文档与博客文章(owner 指令直接删除)。移除原因:9 天内在其目标模型家族(qwen3-27b 系)出现两次不同的真实事故——2026-11-08 v1 引发的自发重复压缩循环(#5949 现场报告,v2 的设计动机)与 2026-11-10 生产会话(v0.1.213,v1 语义)中的作者误认:同轮「回答 + compress」被重放时,压缩对挪位后该轮回答文本裸挂在 transcript 尾部(无 pending 工具调用、无工具结果、无用户输入),27B 模型把自己的最后一条发言当成用户消息(m00376 链),重复回答了自己的答案且错误认知被固化进折叠块主题。v2 从未发布(最新 tag v0.1.213 仍为 v1,`git tag --contains` 为空),移除零迁移成本:开关关闭时布局就是移除后的布局(字节级一致)。旧配置残留的键:一次性 INERT 警告(`warnInertRemovedCompressKeys`,含 top-level 残留)并忽略值。kernel 0.0.192 → 0.0.193。回归面:`tests/removed-compress-keys-inert.test.ts`(新增移除键用例)、`tests/compress-reject-reasons.test.ts`(删除 echo 用例)、`kernel/tests/parse-compress-input.test.ts`(删除两个 pointer-echo 用例)、`kernel/tests/pipeline.test.ts`(节点清单)。

### Changed
- **AGENTS.md 瘦身(owner 指令 2026-11-08):76 KB → 50.6 KB(−34%),规则零丢失,编号不变**。KDD 分两级:Tier A(#2/#4/#6/#7/#8/#10,每会话操作规则)留 AGENTS.md 全文;Tier B(#1/#3/#5/#9/#11–#18)全文逐字搬入新文件 `reference/design-decisions.md`(append-only 台账,**KDD 编号 = 稳定公共 API,原样保留**),AGENTS.md 每条留 1–3 行操作性后果 + 指针。Issue 分类与标签规则整节搬入 `reference/triage.md`(p1 口径与总账讨论链接留在正文)。E2E/Release 细则收敛为指向既有 `reference/testing.md` / `reference/release.md` 的硬规则。被反向引用的 heading 锚点(`#4-git-safety-rules-mandatory` 等 6 处)文本原样不动。
- **系统架构文档体系落地(owner 指令 2026-11-08):`docs/architecture/` 成为实时维护的架构枢纽**:新增 `docs/architecture.md` / `docs/architecture.zh-CN.md` 总枢纽(整体架构图中英双版转正 + 8 模块总表),首个样板模块页 `docs/architecture/storage.{md,zh-CN.md}`(统一存储:职责/原理/工作机制/硬不变量,配模块图中英双版)。文件级地图 `reference/architecture.md` 补齐 125 个缺失条目(新存储层 / marker / fastpath / lanes 等全部新模块)并升级为 CI 强制全量覆盖。新增 CI 车道 `architecture-docs`(`tools/check-architecture-docs.mjs`):地图覆盖全 `src/` 文件、总表↔页面成对、图 svg 优先 + png 备选齐备、SVG 基础良构(未转义 `&` 曾让英文图线上破图)。AGENTS.md「Documentation Layout」新增实时维护规则:改结构 ⇒ 同 PR 更新页 + 图 + 总表。其余 7 个模块页(pipeline / lanes / kernel / identity / fastpaths / webui / update)同一 PR 全部补齐——总表 8 行全 ✅(每页 = 中英双版文档 + 中英双版图)。
Expand Down
4 changes: 0 additions & 4 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,6 @@ This index is generated from `website/config-reference/*.yaml` — edit the seed
| `compress.maxSummaryLength` | number | kernel 20000 | — | Hard character cap on ONE generated summary; longer replies are rejected whole (no truncation, no retry). External summarizers are told this exact cap up front (#3635). 0 = unbounded. |
| `compress.minSummaryLength` | number | kernel 50 | — | Character floor for generated summaries: a single range must meet it alone; a multi-range batch passes when its combined summaries reach it (#5894). 0 = disabled. External summarizers remain held to the per-summary floor (#3635). |
| `compress.reconcile` | "off" \| "warn" \| "repair" | "repair" | BILI_FOLD_RECONCILE | Reconcile folded state when the client rewinds or rewrites history between turns. |
| `compress.compressAtFoldPoint` | boolean | false | BILI_COMPRESS_AT_FOLD_POINT | EXPERIMENTAL, default off: move a still-visible compress call/result pair from its original (tail-adjacent) slot to its own fold point in the re-sent view, i.e. [folded region] – [pair] – [protected messages], so weak-attention models stop reading a trailing tool exchange as a fresh command. View-only transform: refs and state untouched, recomputed identically on every turn; off = byte-identical layout. |
| `compress.compressAtFoldPointClearThinking` | boolean | false | BILI_COMPRESS_AT_FOLD_POINT_CLEAR_THINKING | Second opt-in riding on compress.compressAtFoldPoint: when the pair is repositioned, also drop the contiguous run of unsigned reasoning cores immediately preceding it (the model's thinking about this very fold), so the moved pair starts clean. Inert unless the main switch is on; signed thinking blocks and strict reasoning-echo sessions are never touched (#1658/#684). |
| `compress.promptPack` | string (builtin: "default", "lean") | builtin "default" | — | Compression prompt pack, resolved project pack → user pack → builtin; not gated by acknowledgePromptsRisk. |
| `compress.tiers` | boolean | true | — | Tiered T1→T3 distillation spreads folding cost across generations. |
| `compress.protectedTools` | string[] | none | — | Hard exclusion across all history: results of listed tools never fold. Path patterns (skill/<name>) select skills by name (#1947). |
Expand Down Expand Up @@ -1953,8 +1951,6 @@ File keys resolve only when the matching env var is unset. Defaults in parenthes
| `BILI_CLIENT_ERROR_BACKSTOP_MS` | `network.clientErrorBackstopMs` | 30000 |
| `BILI_CODEARTS_REF` | `resign` | {} (armed; built-in scheme sdk-hmac-sha256) |
| `BILI_CODEX_COMPACT` | `codexCompact` | "intercept" |
| `BILI_COMPRESS_AT_FOLD_POINT` | `compress.compressAtFoldPoint` | false |
| `BILI_COMPRESS_AT_FOLD_POINT_CLEAR_THINKING` | `compress.compressAtFoldPointClearThinking` | false |
| `BILI_DECODED_BODY_BYTES` | `network.decodedBodyBytes` | 10737418240 |
| `BILI_DECOMPRESS_TMP_CAP` | `decompressTmpCap` | 50 |
| `BILI_DSH_AUTHORED_COMPACTION` | `dsh.authoredCompaction` | true (on, #3901 flip) |
Expand Down
4 changes: 0 additions & 4 deletions docs/configuration.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,6 @@
| `compress.maxSummaryLength` | number | kernel 20000 | — | 单条生成摘要的硬字符上限;超长的回复被整段拒绝(不截断、不重试)。外部摘要模型会被提前告知这个确切上限(#3635)。0 = 不限制。 |
| `compress.minSummaryLength` | number | kernel 50 | — | 生成摘要的字符下限:单段压缩按自身判定;批量压缩按合计判定——一段偷懒不再拖垮整批(#5894)。0 = 禁用。外部摘要模型仍受逐段下限约束(#3635)。 |
| `compress.reconcile` | "off" \| "warn" \| "repair" | "repair" | BILI_FOLD_RECONCILE | 客户端在轮次之间回退或改写历史时校准已折叠状态。 |
| `compress.compressAtFoldPoint` | boolean | false | BILI_COMPRESS_AT_FOLD_POINT | 实验性,默认关闭:把仍可见的压缩调用/结果对从原位置(贴近尾部)移到它自己的折叠点,即 [已折叠区]–[调用对]–[保护消息],避免弱注意力模型把历史末尾的工具交换当成新命令。纯视图变换:refs 与状态不变、每轮重算结果一致;关闭时布局字节级不变。 |
| `compress.compressAtFoldPointClearThinking` | boolean | false | BILI_COMPRESS_AT_FOLD_POINT_CLEAR_THINKING | 依附于 compress.compressAtFoldPoint 的第二层开关:调用对被挪位的一瞬间,同时丢掉紧邻其前的未签名思考段(模型对本次折叠本身的思考),让挪位后的开头更干净。主开关关闭时无效;带签名的思考块与严格推理回显会话绝不受影响(#1658/#684)。 |
| `compress.promptPack` | string (builtin: "default", "lean") | builtin "default" | — | 压缩提示词包,按 项目包 → 用户包 → 内置 解析;不受 acknowledgePromptsRisk 门控。 |
| `compress.tiers` | boolean | true | — | T1→T3 分级蒸馏把折叠成本摊到多代。 |
| `compress.protectedTools` | string[] | none | — | 全历史硬排除:列出工具的结果永不折叠。路径模式(skill/<name>)可按名指定 skill(#1947)。 |
Expand Down Expand Up @@ -1930,8 +1928,6 @@ ACP 原生 agent(当前为 `pi` 扩展)会在每个进程内向代理上报
| `BILI_CLIENT_ERROR_BACKSTOP_MS` | `network.clientErrorBackstopMs` | 30000 |
| `BILI_CODEARTS_REF` | `resign` | {} (armed; built-in scheme sdk-hmac-sha256) |
| `BILI_CODEX_COMPACT` | `codexCompact` | "intercept" |
| `BILI_COMPRESS_AT_FOLD_POINT` | `compress.compressAtFoldPoint` | false |
| `BILI_COMPRESS_AT_FOLD_POINT_CLEAR_THINKING` | `compress.compressAtFoldPointClearThinking` | false |
| `BILI_DECODED_BODY_BYTES` | `network.decodedBodyBytes` | 10737418240 |
| `BILI_DECOMPRESS_TMP_CAP` | `decompressTmpCap` | 50 |
| `BILI_DSH_AUTHORED_COMPACTION` | `dsh.authoredCompaction` | true (on, #3901 flip) |
Expand Down
3 changes: 1 addition & 2 deletions docs/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@
| `BILI_OPENCODE_INLINE` | #3278 opencode 移植(#4687) | opencode inline 模式(需手动开启,默认保持旧行为 spawn,owner 决定不改默认):与 pi 同构——不起 proxy 进程,模型 URL 被 V2 route/intercept 改写成伪 origin 后由进程内引擎接住(bun 宿主已验:引擎 boot/dispatch 全绿);`=1/on/yes/TRUE` 或 file 家 `"opencode": {"inline": true}` 显式开启(显式开启压过 attach 目标);`bili opencode-inline` 一键车道 | 同 pi inline 车道节奏 | opt-in(不设置时 attach/spawn 行为与旧版完全一致) |
| `BILI_INLINE_DEBUG` | #4669 | 仅 inline 车道:引擎 stderr 日志腿默认静默(stderr 是 pi 的交互终端,日志会挤掉输入框;默认只写 bili.log),设 1 恢复 stderr 输出用于排查 | 随 inline 车道(#3278)走 | 排查逃生口 |
| 测试钩子:`BILI_DSH_RECOVERY_INTERVAL_MS` / `BILI_DSH_RETRY_INTERVAL_MS` / `BILI_MODEL_INFO_RETRY_MS` | #2082 等 | 缩短测试/运维节奏(dsh-native.ts;NODE_TEST_CONTEXT 感知,避免生产误缩) | 永久测试设施,随宿主代码走 | 测试钩子 |
| `BILI_COMPRESS_AT_FOLD_POINT` | #5470 | compress-at-fold-point 实验性 opt-in(**默认关**;2026-11-01 真实模型验证通过,owner 决定保持 opt-in):把重放视图中可见的 compress 调用对挪到它自己的折叠点(布局 [已折叠区]–[调用对]–[保护消息]),弱注意力模型不再把历史尾部的工具交换误读成新命令;纯视图变换,关时布局字节级不变;文件键 `compress.compressAtFoldPoint`;含 env-only opt-in 可达性修复(默认短路保持不变) | 更多真实模型积累后转正为默认开(走评审),或按废弃流程删除 | opt-in(默认关) |
| `BILI_COMPRESS_AT_FOLD_POINT_CLEAR_THINKING` | #5470 | 依附上一开关:挪位瞬间清紧邻的未签名思考段(默认 off,A 关时无效);strict-echo(#684) 或存在签名思考块(#1658)时整个机制不出手 | 同上 | opt-in(默认 off) |
| `BILI_PF_RENDER_WINDOW` / `BILI_PF_RENDER_AUDIT_EVERY` | #5664 v6 render-snapshot plane | 实验性渲染快照车道可调项(默认 OFF,嵌套于 watermarkV6MsgId cohort):W = 稳态轮回放的冻结核数(默认 8);N = 计划全量审计节奏(默认 8);读点 src/server/fastpath-v6-render.ts:50-60 | render 平面转正(rollout 100% 且审计计数归稳)后移 §2 常设面,或随车道退役删除 | opt-in(默认 OFF;仅由显式 rollout 开启) |
| `BILI_IDENTITY_HARVEST` | #5825 / PR #5842 | 身份信道采集 kill/scope 开关(src/identity-harvest.ts):缺省=OFF(接线以惰性状态出厂);`1`/`all`=全部已登记来源;逗号列表=按 roster 名圈定;须与 rollout `pluginLaneServerHistory` 及仅回环来源同时放行才生效 | harvest 车道(claude-code/codebuddy/mcode)站稳后按 #2028 模式退役 env(转 file 键)或移 §2 | opt-in(默认 off;rollout 0% 起灰度) |

Expand Down Expand Up @@ -238,6 +236,7 @@

## 5. 卫生记录

- **2026-11-10 compress-at-fold-point 整功能移除(owner 指令,#6132)**:实验性开关 `BILI_COMPRESS_AT_FOLD_POINT` / `BILI_COMPRESS_AT_FOLD_POINT_CLEAR_THINKING`(§1 两行)及文件键 `compress.compressAtFoldPoint` / `compress.compressAtFoldPointClearThinking` 整体删除(v1 #5471 + 未发布的 v2 #5949)。移除原因:9 天内在其目标模型家族上出现两次不同的真实事故——2026-11-08 v1 引发的自发重复压缩循环(#5949 现场报告)与 2026-11-10 v0.1.213(v1 语义)生产会话中的作者误认(模型把自己最后一句话当成用户消息,详见 #6132)。旧配置中残留的键会被一次性 INERT 警告(warnInertRemovedCompressKeys)并忽略值;博客文章按 owner 指令直接删除。
- **2026-11-08 文档集中化(owner 指令 2026-11-08)**:14 个根级设计/配置文档一次性迁入 `docs/`(CONFIGURATION→`docs/configuration`、CLIENTS→`docs/clients`、TECHNICAL-NOTES→`docs/technical-notes`、MESSAGE-IDENTITY→`docs/message-identity`、SESSION-IDENTITY→`docs/session-identity`、PLUGIN→`docs/plugin-protocol`、LIFECYCLE→`docs/lifecycle`、UNIFIED_LOOP_SPEC→`docs/unified-loop-spec`、AUTO-MERGE-GUARDRAILS→`docs/auto-merge-guardrails`,含 zh-CN 对);新 `docs/index.md` / `docs/index.zh-CN.md` 为文档总目录。原路径留单行重定向占位,**解除条件:1–2 个版本后且无外部链接反馈时删除占位**(届时同步删根级 stub)。CI `docs-sync` diff 路径与 `scripts/{config-surface-guard,lifecycle-ledger-guard}.mjs` 运行时路径、`package.json` files 数组已随迁。
- **2026-10-15 远端分支卫生(#3249 执行)**:删除 origin 已合并远端分支 **1394 条**(1386 条 = 已合并 PR 的同仓 head 分支 + 8 条 = 完全并入 master 但无对应 PR 记录:`2026-08-08_release-v0.1.14`、`2026-09-26_opencode-zen-mitm`、`2026-09-30_responses-side-compaction`、`2026-10-04_plugin-fork-context-provenance`、`2026-10-13_lastmessages-tabling`、`chore/pages-enablement`、`fix/codex-custom-tool-call-text-protocol`、`revert-3189-pages-enablement`)。删除前核对:与 open PR head 交集为空。删除后 origin 剩 361 个 head(其中 128 条为 open PR 分支、201 条 closed-unmerged 且未并入 master、30 条无 PR 未并入 = 废弃工作,均不动)。另执行一次 `git worktree prune` 清掉失效 worktree 登记。
- **2026-10-20 台账补登(本 PR)**:#3249 落地本台账时 `src/` 实际读取数已比登记数多 22(#3955 mysql、guardrails、#3128 网络预算、#3400 图像缩放、#3619 错峰、#3733 dsh compaction、#3756 snapshot shadow 等),守卫上线即全线红(master run 均被后续 push 取消所以未暴露)。本次 22 条全部补登(3 条 §1 + 19 条 §2)。
Expand Down
4 changes: 2 additions & 2 deletions kernel/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion kernel/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "acp-kernel",
"version": "0.0.192",
"version": "0.0.193",
"description": "Framework-agnostic context-compression engine (model-driven, 3-tier LSM). Pure core: no host dependency.",
"license": "MIT",
"author": "ranxianglei",
Expand Down
22 changes: 0 additions & 22 deletions kernel/src/compress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import { appendAbsorbPrompts, hideAbsorbedMessages } from "./absorb.js";
import { applyCrushToMessages } from "./crush.js";
import { applyRetrieve, ccrStoreNode, RETRIEVED_ID_PREFIX } from "./ccr.js";
import { preTransformSnapshotNode, viewLatchNode } from "./view-latch.js";
import { relocateCompressCarriers } from "./relocate-compress.js";
import type { ApplyRetrieveResult, CcrEffect } from "./ccr.js";
import type { EmergencyTruncateLatchEntry } from "./types.js";
import { createContentStore } from "./content-store.js";
Expand Down Expand Up @@ -1144,11 +1143,6 @@ export function createCore(ports: Ports = {}): CompressionCore {
absorbPromptNode,
filterNode,
hideCompressCallsNode,
// EXPERIMENTAL, default off (Config.compressAtFoldPoint): move still-visible
// carrier pairs onto their fold point. Must run AFTER hide-compress-calls
// (whose orphan sweep just settled which carriers survive) and BEFORE
// view-latch so the latch records the relocated bytes.
relocateCompressCarriersNode,
viewLatchNode,
recommendNode,
nudgeNode,
Expand Down Expand Up @@ -1463,22 +1457,6 @@ const hideCompressCallsNode: PipelineNode = {
},
};

const relocateCompressCarriersNode: PipelineNode = {
name: "relocate-compress-carriers",
run(io, ctx) {
const cfg = ctx.config;
if (!cfg.compressAtFoldPoint) return io;
return {
...io,
messages: relocateCompressCarriers(io.messages, io.state, {
isCompressTool: cfg.isCompressTool,
clearThinking: cfg.compressAtFoldPointClearThinking === true,
reasoningDroppable: cfg.reasoningDroppable,
}),
};
},
};

const recommendNode: PipelineNode = {
name: "recommend",
run(io, ctx) {
Expand Down
4 changes: 0 additions & 4 deletions kernel/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,6 @@ export type { HandoffInput, HandoffMeta, HandoffBlockFull } from "./handoff.js";
export { isToolMessage } from "./message-kind.js";
export { hideConsumedCompressCalls } from "./hide-consumed.js";
export type { HideConsumedResult } from "./hide-consumed.js";
// Experimental fold-point carrier relocation (default off) — host-side mirror
// sites (round-2 re-render, S4 plugin render) call the same pure function.
export { relocateCompressCarriers, planRelocateCompressCarriers } from "./relocate-compress.js";
export type { RelocateOptions, RelocatePlan, RelocateMove } from "./relocate-compress.js";
export {
ABSORB_TOOL_NAME,
ABSORB_TOOL,
Expand Down
19 changes: 0 additions & 19 deletions kernel/src/parse-compress-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,12 @@
import { clampPrefix } from "./truncate.js";
import type { CompressRangeSpec } from "./types.js";

// The ack text compressAtFoldPoint v2 writes into a completed compress call's
// rewritten args (see relocate-compress.ts on the branch that introduced it;
// mirrored here as a literal so this parser change lands independently of
// that one — keep the two strings identical when both are on master).
const RELOCATED_POINTER_MARKER =
"[bili] compression succeeded — summary relocated";

export type CompressParseKind =
| "ok"
| "empty-input"
| "not-object"
| "missing-content"
| "content-not-array"
| "already-folded-echo"
| "malformed-json"
| "truncated"
| "no-valid-ranges";
Expand Down Expand Up @@ -203,17 +195,6 @@ function parseObjectValue(
if (Array.isArray(content)) {
entries = content;
} else if (typeof content === "string") {
// compressAtFoldPoint v2 rewrites a completed compress call's args to a
// short ack pointer (relocate-compress.ts). A model that copies its most
// recent compress call as a template re-sends that pointer text as the
// content of a NEW call — observed live as bursts of identical
// content-not-array rejections, each receipt feeding the next retry.
// Classify it explicitly so hosts can ack a no-op instead of lecturing
// a format that was never wrong.
if (content.includes(RELOCATED_POINTER_MARKER)) {
diag.kind = "already-folded-echo";
return finish([], diag);
}
// Stringified content array: vLLM-style gateways stringify nested
// arrays, so `content` arrives as a JSON string of the array.
const parsed = parseContentArray(content);
Expand Down
Loading
Loading