Repository navigation
Releases: ScreamingMaggot/rcs-context
Release list
v0.1.27 — 折叠压缩比口径修正(并按历史重算)
症状
面板「最近一次折叠」的百分比失真。真机读数: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。
v0.1.26 — 折叠不再吃掉仍在飞的那一轮(修重复回答)
症状
思考强度 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通过
v0.1.25 — 可作为 DSH 插件包直接安装(目录重构)
从"下载 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)
files白名单必须列cordis.patch.yml—— 漏了就是"装上了但没有补丁层";dsh plugin add不自动激活 bundle,必须手动选进dsh.profile.bundles;- 本地 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)
一个被上一个 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)
修了什么
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)
兼容性
- 已验证: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);计费中位 最低
- 样本量较小尚未通过显著性检验