Skip to content

Releases: ScreamingMaggot/rcs-context

v0.1.27 — 折叠压缩比口径修正(并按历史重算)

Choose a tag to compare

@ScreamingMaggot ScreamingMaggot released this 30 Sep 08:01

症状

面板「最近一次折叠」的百分比失真。真机读数:659%、917%、382400%。

根因:分子分母来自不同折

shrink = transcriptBytes / shadowedBytes
         └─ 累计转录(foldText 全长)   └─ 本折遮蔽字节

首次折叠时二者同源(累计=本折),所以看着正常;增量折叠上分子含历史全部转录、分母只算本折 ⇒ 结构性大于 1,且折得越多越离谱。这不是"折叠没收益",是混合口径。同源问题还有两处 console 输出。

修法

  • 抽出纯函数 foldShrinkOf():本折口径 = 本次新增转录 ÷ 本次被转写的新原料;缺增量数据的旧记录回退旧算式,字段恒为数值
  • 三处消费方(fold-attempt 日志 / fold-committed 日志 / last-fold 落盘)全部改走它;记录自带 foldShrinkScope 说明口径
  • transcriptBytes(累计转录长度)原样保留 —— 它本身没错,只是不该当收益指标
  • 面板改为显示本折的 incrementalRawBytes → appendedBytes B (占比%),旧记录缺字段时自动回退

按历史重算

重算 12 个文件,跳过 11 个(v1.10.25 之前的记录无增量字段,按设计不动)

session-de4959d2   6.5863 (659%)     → 0.6230 (1.61×)
session-5fe3512e   9.1685 (917%)     → 0.3464 (2.89×)
session-ffab17e9   3824.05 (382400%) → 0.9000 (1.11×)
session-8e692134   0.1004            → 0.1434 (6.97×)
session-bbfd2f6a   0.1998            → 0.0973 (10.28×)

每个文件先备份(.bak-<stamp>-before-shrinkfix),旧值另存 shrinkLegacy,不做无痕覆盖。

正确读数(真机会话 5fe3512e 五笔,可对外引用)

第 1 折 465,068 →  57,099 B   7.84×      第 4 折 197,939 →  37,186 B   5.32×
第 2 折 648,362 → 114,123 B   5.68×      第 5 折   4,946 →   3,162 B   1.56×
第 3 折 293,978 →  80,954 B   3.63×      合计  1,610,293 → 292,524 B   5.50×

验收

tests/fold-ratio.test.mjs 11 条断言全绿(含用真机读数当基准、两笔天文数字的回归、分母缺失回退、以及一条"本折口径 ≠ 累计除本折"的反回归断言)。同仓另三套仍全绿:当前轮保护 7、漂移 #11 18、toolfold 单行契约 16。

⚠️ 需重启 dsh web 生效(插件与面板都在内存里)。

v0.1.26 — 折叠不再吃掉仍在飞的那一轮(修重复回答)

Choose a tag to compare

@ScreamingMaggot ScreamingMaggot released this 30 Sep 07:54

症状

思考强度 off(启用外置推理)的会话里,压缩未完成时发送用户消息,主对话对同一条消息回复两次。

证据(真机 session-de4959d2,回合 2)

seq247  15:47:07  user/message  src=user           "怎么样你觉得好玩吗"
seq251  15:47:10  assistant/message                "好玩。而且我觉得这一轮…"     ← 第一次回答
seq254  15:47:21  user/message  src=plugin:CONTEXTinjector
                  surfaceOp = replace 247..251    ← 转录吞掉了本轮的一问一答
seq255  15:47:21  step/start   turn=2 step=2
seq259  15:47:24  assistant/message                "好玩。不是客套。……"          ← 第二次回答同一条

根因

closedPrefixEnd 在"所有 tool-call 都配到 result"时返回表面末端。于是当 pre-step 折落在本轮第 2 步(本轮首个工具已闭合)时,遮蔽集覆盖到本轮末尾 → 本轮的 user 消息和刚产出的助手回复被一起替换成转录 → 表面尾部变成 user 角色节点 → 宿主读作"未回答的用户轮" → 再跑一步 → 重复回答。

代码里此前没有任何"进行中内容不进遮蔽集"的判据 —— 而设计文档里那句"只折叠已经彻底结束的内容"是有的。本版把它从"靠 closed-prefix 的偶然性满足"变成显式守卫。

修法

新增纯函数 openRoundClampEnd(entries, session, end):

  • 找最后一个真人轮起点(plugin:CONTEXTinjector 自身节点不被误认);
  • 该起点之后有 turn/end ⇒ 该轮已结束 ⇒ 不钳制(轮末折的主路径不受影响);
  • 没有 ⇒ 仍在飞 ⇒ 遮蔽终点钳到该起点之前(钳成 <0 则本轮不折);
  • 事件不可得/异常 ⇒ 不钳制,退回旧行为(不让折叠因查询失败永久停摆)。

判据与既有 collectDeadCalls 的"该轮已结束 ⇔ 其后有 turn/end"同源,不引入新语义。

同一会话五笔折叠用新守卫重判:seq254、seq275(两笔吃掉当前轮的)被钳制;seq244、seq245、seq262(折已结束内容)照常放行。

验收

  • tests/round-guard.test.mjs:7 条断言全绿(仍在飞→钳制 / 已结束→不钳制 / 无轮起点→不钳制 / 自身节点不误认 / 轮起点在 0 → 延后 / 事件不可得→回退 / end<0 原样返回)
  • 同仓另两套回归仍全绿:漂移 #11(18 断言)、toolfold 单行契约(16 断言)
  • 三份副本(安装位 / 仓库 / 交付包)同步,node --check 通过

⚠️ 装好需重启 dsh web 才生效(插件在内存里)。

v0.1.25 — 可作为 DSH 插件包直接安装(目录重构)

Choose a tag to compare

@ScreamingMaggot ScreamingMaggot released this 30 Sep 07:28

从"下载 zip 跑脚本"到"一条 add 命令"

此前安装只有一条路:git clone → install.ps1。实测 pnpm add github:ScreamingMaggot/rcs-context 会解析成功但写出占位清单(_pnpmPlaceholder),因为仓库根没有 package.json —— cordis 无从加载。

本版把仓库改造成合法的插件包,同时保留脚本安装路径。

改动

  • contextinjector.mjs / logcompiler.mjs / extreason.mjs → web/;toolfold.mjs → toolfold/(git mv,历史保留)
  • 新增根 package.json(声明 dsh.bundle.patch)与根 cordis.patch.yml(四条 insert,包内相对路径)
  • install.ps1 只改源路径,落位/备份/回滚逻辑未动;两个回归测试的夹具源路径同步更新

目录分成 web/ + condense/ + toolfold/ 不是随手排的:插件源码里写的是 ../condense/chunk.mjs、../toolfold/toolfold.mjs,而这个布局与装进 DSH_HOME/profiles/ 后的布局同构 —— 两条安装路共用同一份源码,零分叉。

安装

dsh plugin --profile web add github:ScreamingMaggot/rcs-context
# 再把它选进 <DSH_HOME>/profiles/web/package.json 的 dsh.profile.bundles,然后重启 dsh web

装成功并激活后,启动日志应出现四条装载行:[CONTEXTinjector] armed …、[logcompiler] v3 …、[EXTREASON] armed …、[contextinjector-webui] … ready。dsh plugin add 不会自动激活 bundle —— 少这一步就只有文件、没有加载。

验收(隔离 DSH home 实测)

路径 结果
dsh plugin add "git+file:///…/RCS" 装成 rcs-context@0.1.25,内容清单正确;选进 bundles 后四条装载行齐出
install.ps1 -DSH_HOME <隔离家> 备份 → 落位 → 补丁层四项 insert → 九条装载行,四个插件全 armed

回归测试(漂移 #11 覆盖 18 断言、toolfold 单行契约 16 断言)重构后全绿;六份 .mjs 全部 node --check 通过。

三个会花掉你时间的坑(已写进 RCS-0.1.25-改进与保留项.txt)

  1. files 白名单必须列 cordis.patch.yml —— 漏了就是"装上了但没有补丁层";
  2. dsh plugin add 不自动激活 bundle,必须手动选进 dsh.profile.bundles;
  3. 本地 git 规格要写 git+file:///C:/…(三段斜杠),少一段 pnpm 会把盘符的冒号吃掉。

另:本 bundle 刻意不关 plugin-package-inventory-deepseek。该扩展与折叠互斥只发生在 0.1.7-rc.2 一代,而 bundle 补丁无法探测扩展是否存在,对不存在的 id 做 config 覆盖不安全 —— 那一代仍由 install.ps1 按探测结果处理。

v0.1.24 — 行式日志的单行契约(escVal 补转 CR)

Choose a tag to compare

@ScreamingMaggot ScreamingMaggot released this 29 Sep 13:40

一个被上一个 bug 藏起来的 bug

重建事故会话被漂移 #11 写坏的 118 行 [T] 时(按源重放、调用真实 foldOne),覆写后自检发现:逻辑行 218,物理行 642。

toolfold.mjs 的 escVal 转义了 \n,漏了 \r。Windows 工具正文是 \r\n,于是 cmd= / head= / tail= 里留下裸 CR;写进行式日志后 CR 自身被当换行 ⇒ 一行撑成多行 ⇒ 面板 parseTranscript 与任何按行解析的下游读到垃圾续行。

原事故日志里没暴露,纯属侥幸:漂移 #11 让 action='?' 走了 fallbackRule,根本没生成携带正文的字段。两个 bug 互相遮蔽,修好前者才让后者现形。

改动与验收

  • escVal:special 判定加入 \r,并补 .replace(/\r/g,'\r')。foldOne 的每条 [T]/[V] 保证单行。
  • 新增 tests/toolfold-single-line.test.mjs:pwsh / read / edit / grep / 未知工具五类输入(正文一律含 \r\n)断言单行契约。反证:把 escVal 退回修复前,同一输入 → 旧版输出含裸 CR: true,测试确实抓得住。
  • 重建后的只增日志自检:物理行 218 = 逻辑行 218、无标记续行 0、问号行 0;[T] 118 行(域分布 fs 54 / shell 46 / web 11 / jobs 4 / todo 2 / fs-search 1),66 行带真实目标路径,另新增 11 行 [V] 数值锚点。行尾与原文件一致(宿主本就写 CRLF)。

v0.1.23 — 折叠不再丢工具痕迹(DSH 0.1.7 漂移 #11)

Choose a tag to compare

@ScreamingMaggot ScreamingMaggot released this 29 Sep 12:00

修了什么

DSH 0.1.7 改了"工具结果放在哪":结果消息不再是 content:[{type:'tool-result',…}],而是 {role:'tool', toolCallId, isError, content:[{type:'text'}]} —— 没有 tool-result 块,id 与 isError 上移到消息层。

转录器只在块级分支产 [T] 行,于是整类节点被静默跳过。真机后果(会话 5fe3512e,107 步 / 118 次工具调用):

修复前 修复后
一次折叠遮蔽 205 节点 / 465,068 B 同
产出转录 87 行,其中 [T] = 0 行 192 行,其中 [T] = 114 行,退化 0 行
模型看到的历史 只剩 65 句助手发言,不知道工具动过什么 每次调用一行:shell|pwsh|…

改动

  • 双形态识别:isToolResultMsg / toolResultCallId,callId 依次取 块 → 消息 → source;块级与消息级共用同一个 emitter,老宿主输出逐字不变。
  • 新增覆盖守卫(本版真正想留下的):增量里每个工具结果必须产出一行 [T],got < want ⇒ 整次折叠拒绝、本轮按原文发送。旧的五项提交前校验比的是字节与关键值,对"少产出行"不敏感——本次事故照样判通过并提交。
  • LOGcompiler 同步回落消息层(修掉日志里可见的 ?|?)。
  • 事件层索引 callIndexFromEvents 作为兜底保留。
  • 回归测试 tests/drift11-toolcall-event-index.test.mjs:18 条断言;先把交付文件装配成安装布局(profiles/web + condense + toolfold)再 import,顺带验证交付包结构本身可加载。

一条更正

v0.1.22 交付说明里的"v4 兼容性已全验(23 次折叠 / 0 错误 / 前缀单调)"结论作废。那些指标在丢内容时同样全部成立。缺的正是本版补上的覆盖比对——验证"压缩没出错"不能只看压缩器自己的账,必须看压缩后还剩什么。详见 RCS-0.1.23-改进与保留项.txt。

v0.1.22 — 适配 DSH 0.1.7-rc.2(session-format v4)

Choose a tag to compare

@ScreamingMaggot ScreamingMaggot released this 29 Sep 06:23

兼容性

  • 已验证:DSH 0.1.7-rc.2(会话格式 v4 全链路:折叠提交、审计、回放、外置推理注入)
  • 同时保留双代兼容层:同一份文件在 0.1.5-rc.2 上照常运行

本版改动

  • 宿主 v4 退役的消息来源标记 → 写侧改为 producer-owned 形态,读侧双形态识别(防自转录 / 注入避让 / 分类器共 13 处)
  • 事件枚举改为 ownEvents() 兜底,消除旧写法在事件数组移除后的静默降级
  • 外派助手接口改名适配:followup → sendMessage、一次性 start 归一到 startContinuable
  • 安装器新增一条按宿主探测的兼容补丁:关闭与折叠互斥的 dsh_plugin_packages 请求扩展(旧宿主不写此项)
  • README 新增:终端安装路径、成本提示(压缩通道务必指向本地/廉价模型)、权限与网络依赖声明、真实界面截图

实测读数(详见仓库内账本)

  • 折叠:每步计费输入约为不开的 0.476 / 0.487(T1/T4 配对中位,284 局);前缀缓存命中 93.6%
  • 外置推理:所有测试中最难题 17/18 vs 基线 13/18、15/18;合并 51 局"被旧值带偏" 1 次(外置推理) vs 6 次(无推理) vs 6 次(思考强度HIGH);计费中位 最低
  • 样本量较小尚未通过显著性检验