dsh-live-compact 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +260 -0
- package/README.md +72 -211
- package/index.js +365 -119
- package/package.json +5 -2
- package/plan.js +41 -11
- package/raw.js +6 -4
- package/shadow-save-worker.mjs +24 -0
- package/shadow.js +168 -17
- package/shell.js +4 -2
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
一段对话做久了,读过的日志、跑过的命令和工具输出会越积越多。Live Compact 会在每轮结束时检查,能安全收短的长输出就整理一下。这一步在本机做,无需再请求模型。只替换选中的一段,切点前面的内容保持原样。整理前会备份原文,备份失败就保留原来的内容。
|
|
4
4
|
|
|
5
|
+
版本变更见 [CHANGELOG.md](CHANGELOG.md)。
|
|
6
|
+
|
|
5
7
|
## 云端和本地怎么用
|
|
6
8
|
|
|
7
9
|
- **用 DeepSeek、GLM 这类云端 API**,按下面的命令安装即可。先看答案是否正确,再一起看缓存命中、未命中输入和实际费用。命中率的百分比不是费用本身,输入变少时要连同 token 数一起比较。
|
|
@@ -14,13 +16,13 @@
|
|
|
14
16
|
headless:
|
|
15
17
|
|
|
16
18
|
```sh
|
|
17
|
-
dsh plugin --profile headless add dsh-live-compact@1.1.
|
|
19
|
+
dsh plugin --profile headless add dsh-live-compact@1.1.5
|
|
18
20
|
```
|
|
19
21
|
|
|
20
22
|
网页端:
|
|
21
23
|
|
|
22
24
|
```sh
|
|
23
|
-
dsh plugin --profile web add dsh-live-compact@1.1.
|
|
25
|
+
dsh plugin --profile web add dsh-live-compact@1.1.5
|
|
24
26
|
```
|
|
25
27
|
|
|
26
28
|
想先装到本机看版本:
|
|
@@ -30,252 +32,98 @@ npm install -g dsh-live-compact
|
|
|
30
32
|
dsh-live-compact --version
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
##
|
|
34
|
-
|
|
35
|
-
- 修复 #34:空闲维护的大段 catch-up 改为分批让出事件循环;Windows 阴影文件短暂忙时按 8 次上限和退避自动重试,永久失败保持 fail-closed,不阻塞轮次结束返回。
|
|
36
|
-
- 游标和 retryable 结果按会话缓存,避免长历史重复扫描;工具结果、raw/meta 字节与 SHA256 在重启恢复后继续校验。
|
|
37
|
-
- 本地门禁 `npm run test:gate` 通过 508/508;Windows 2022 x64 与 Windows 11 ARM 的标准用户长会话验收均通过,含 29 轮、进程重启边界和 15,001 事件/356 个工具结果的双阶段捕获恢复。
|
|
38
|
-
|
|
39
|
-
## 1.1.3
|
|
40
|
-
|
|
41
|
-
- 修复 #34:工具结果事件不再同步执行 shadow/ACL 文件操作,改为事件循环后排队并按 toolCallId 去重;维护开始前会等待已排队捕获,`captureNew` 仍负责补抓和重试。
|
|
42
|
-
- 这条路径避免在模型收到工具结果前被同步磁盘操作卡住;权限失败仍然只拒绝备份,不让宿主 fatal 退出。
|
|
43
|
-
- Windows hosted 验收:Windows 11 ARM、Windows 2022 x64 的 Node 22/24 core,以及三套 DSH 0.2.0/0.2.1 普通用户 runtime 均通过;官方 Desktop 普通用户安装、启用、设置保存和重启读取在 Windows 11 ARM 与 Windows 2022 均通过。
|
|
44
|
-
- 同一候选又做了 29 轮持久会话回放:Windows 2022 用时 14 分 05 秒,Windows 11 ARM 用时 17 分 08 秒,含第 21 轮进程重启边界和 58 次工具结果捕获。原报告的 93M/第 29 轮冻结没有在这组受控回放中重现;Node 24 首次双进程 cursor 测试的 299/300 竞态重跑通过,作为后续观察项保留。
|
|
45
|
-
- Config、验证/头脑风暴模式和自动主题分类继续后置,不改变 1.1.2 的小切默认参数。
|
|
46
|
-
|
|
47
|
-
## 1.1.2
|
|
48
|
-
|
|
49
|
-
- 常用压缩参数可以在 DSH 插件设置里改,保留原有环境变量用法。
|
|
50
|
-
- 专用备份目录确认只有一个插件进程使用时,低于用量水线可以跳过全目录扫描;完整校准满 60 秒后,下次轮转会重新扫描。默认目录和共享目录继续按原规则检查、清理。
|
|
51
|
-
- 扫描不完整或计量不合法时拒绝本次备份。无法确认其他会话已经退出时,不删除它的正文。
|
|
52
|
-
- 失败工具结果保留退出码、错误类型、标准错误和标准输出里的关键原因;过长时保留原因和首尾,不能把失败卡片写成正常完成。`npm run test:gate` 也会检查这条路径。
|
|
53
|
-
- 提交小切前重新检查 checkpoint、用户边界和工具配对;等待期间出现的新消息也会重新检查。
|
|
54
|
-
- 账号模式没有显式地址、恢复旧官方卡片和精确的过程通知可以组合工作;真实用户消息与未知通知仍保留边界。
|
|
55
|
-
- 重启后会核验已有备份和游标,再从最近的工作位置继续。
|
|
56
|
-
- Windows 会重新设置备份访问权限,失败时停止写备份并保留原工具输出。
|
|
57
|
-
|
|
58
|
-
### Windows 备份权限
|
|
59
|
-
|
|
60
|
-
Windows 双用户实测(Actions run `42367713007`,Windows 11 Enterprise ARM / Server 2022 x64)确认:1.1.1 的 `/inheritance:r /grant:r` 会留下其他主体的显式 ACE,第二个普通用户仍能读取备份。1.1.2 改为完整替换 DACL。1.1.3 候选又通过了 hosted Windows core/runtime、官方 Desktop 普通用户安装与设置保存/重启,以及 29 轮持久会话回放;原报告的 93M/第 29 轮冻结未在受控回放中重现,慢存储、超大历史和共享目录压力仍属于后续观察范围。
|
|
61
|
-
|
|
62
|
-
权限写入改为固定的 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe`(Windows PowerShell 5.1 / .NET Framework),使用 `-NoProfile -NonInteractive -EncodedCommand`。脚本固定内嵌在已打包的 `shadow.js`,路径、SID、文件类型通过子进程环境传递,不拼进脚本。当前用户 SID 仍由固定 System32 `whoami.exe` 每进程获取一次,脚本再对照自身 Windows 身份。新建受保护的 DACL,只允许当前用户、SYSTEM、Administrators 完全控制;目录 ACE 带 OI/CI,直接修正的文件 ACE 不带继承标志。只修改 DACL,不提权,不改 owner、group 或 SACL,不使用临时宽松 ACL。写后读取实际 DACL,核验保护位、完整 ACE 数量、SID、Allow、权限及继承标志,收到确认才缓存。工具失败、超时、SID 非法或读回不符都会熔断本进程后续备份,不回退到 chmod。
|
|
63
|
-
|
|
64
|
-
目录缓存核对规范路径、设备/文件编号及创建时间;替换目录或改指向的已知别名会拒绝后续备份。经确认目录内以 `wx` 新建的空文件,核对已打开句柄与路径指向同一文件后,使用继承的 allowlist,不逐文件启动子进程,写入正文前完成检查。既有文件不能只凭父目录缓存获得信任:仅在本进程已确认同一文件身份时复用缓存,否则对被请求的文件单独替换 DACL。拒绝文件符号链接、非普通文件及多硬链接文件。不扫描或批量修复历史备份;捕获/恢复所请求的旧 raw、meta、cursor 文件在使用时修正。未触及的旧文件(包括直接外部读取或 shadow-search 读取的旧文件)不保证已修复,也无法撤回此前泄露的数据。不要把 shadow 指向混有其他文件的目录。
|
|
65
|
-
|
|
66
|
-
缓存信任同一用户和管理员不在进程运行期间原地改写 ACL;元数据核对不能发现同一文件上的 ACL 原地变更,也不能消除同用户/管理员并发改路径的全部竞态。SystemRoot/windir 必须指向可信 Windows 安装;文件系统须提供稳定文件身份并支持 Windows DACL,工具缺失或策略禁止运行时拒绝备份。Unix 仍使用目录 0700 / 文件 0600。切点、token/cap 策略、#27 根目录协调与重启口径不变。
|
|
67
|
-
|
|
68
|
-
离线门禁用 `npm run test:gate`。其中 Windows 权限测试用注入的文件系统和命令验证失败分支。真实权限另用两个 Windows 普通账户验证,分别检查写入、可读的对照文件和备份的读取结果。评分器的离线测试用 `npm run test:live-gate`。
|
|
69
|
-
|
|
70
|
-
## 1.1.1
|
|
71
|
-
|
|
72
|
-
1. Windows 上取 SID 和写权限不再走 PATH。固定调用 `%SystemRoot%\System32` 下的 `whoami.exe` 和 `icacls.exe`。环境变量不是盘符绝对路径时,这次备份直接跳过,不退回裸命令名。
|
|
73
|
-
2. 当时用 `/inheritance:r /grant:r` 替代 `icacls /restore`;后续双用户实测确认它保留其他显式 ACE,不能实现完整 allowlist。修正及验证限制见上面的 1.1.2 候选说明。
|
|
74
|
-
3. 权限失败不再把宿主打退出。这次备份不落盘,不退回 `chmod`,只提示一次。压缩照常进行。
|
|
75
|
-
4. 进程重启后补抓工具结果,只补最近 3 轮。已经记下的位置还在,就从那里接着记。记下的位置比当前日志还大,按重启口径补最近 3 轮,不从 0 把整份日志再扫一遍。
|
|
76
|
-
5. 一轮里有不少于 1000 token 的 `read`,这一刀只切这一轮,不把要留的后 3 轮短结果一起卷进去。这一轮里单个工具结果达到 3.2 万,只留指针。这一轮切不下来,才按原来的规则切更早的轮。
|
|
77
|
-
6. 65 万、4.8 万、3.2 万、`CHUNK_MIN` 1000、云端默认 `0.8` / `65536` / `8192`、`SPINE_THUNDER` 默认关闭,都没改。没有加「省下的必须盖过重写」这种新门槛。备份目录快满时仍是先扫再判断,这版没改,留到 1.1.2。
|
|
78
|
-
|
|
79
|
-
## 1.1.0
|
|
80
|
-
|
|
81
|
-
1. Issue #19 里下一轮输入回到 21 万到 24 万、前缀被打掉的那一刀,是切点走到了已有卡片左边。1.1.0 把最新一张卡片当成地板。往左走到卡片就停。切点右边还有更新的卡片,这一刀不切。已进缓存的前缀不再被后面的刀改写。
|
|
82
|
-
2. 同一次收尾可以连切,这是现有设计,没有改。改的是记账。以前每一刀都把尾巴算进重写,四刀就把同一段尾巴乘了四次。现在一次收尾只记一次:第一刀之后的前缀,减去后面几刀省下的。`dsh-live-compact stats` 的 `rewrite` 用这个数。逐刀明细在 shadow 目录的 `spine-cuts.jsonl`,只有序号、token 和切点,没有消息原文。
|
|
83
|
-
3. 没有加「省下的必须盖过重写」这种新门槛。加了会把同一次收尾里后面的刀切掉。65 万停切线、收尾停在 3.2 万、`CHUNK_MIN` 默认 1000、云端默认 `0.8` / `65536` / `8192`,都没改。`SPINE_THUNDER` 仍是默认关闭。
|
|
84
|
-
4. 今天桌面端长时间卡住,是每回合、每个工具结果都在拷贝整份会话日志,并反复计量。1.1.0 一个空闲回合只拷贝一次日志。工具结果到达时用已经记下的调用编号,不再为了查一次调用而拷贝整份日志。收尾循环复用这一次的任务和调用表。token 计量是开头一次,每真正切下一刀再测一次。没切的回合只测一次。切哪一段没改。
|
|
85
|
-
|
|
86
|
-
## 门禁和复测
|
|
87
|
-
|
|
88
|
-
`npm run test:gate` 已过。Windows 取权限、宿主不退出、重启只补最近 3 轮、长 `read` 只切自己那一轮,都在这道门禁里。65 万、3.2 万、`CHUNK_MIN` 1000、云端默认值没改。
|
|
89
|
-
|
|
90
|
-
这轮连的是插件版。10 组同一套 31 轮填日志,组内串行,两个模型同时开。原版 DSH 压缩对比留到 1.1.2。Coder 390 27B 这轮没跑,后补。测评图在下面,也在 [v1.1.1](https://github.com/Tranquillitatis-Lab/dsh-live-compact/releases/tag/v1.1.1)。
|
|
91
|
-
|
|
92
|
-
下面三张图沿用已完成的 1.1.1 实测数据;1.1.2 只更新运行时修复和门禁,图标题按当前发布版本标注。
|
|
93
|
-
|
|
94
|
-
看图时,先看日志题答对多少,再看首步缓存和压缩节省。首步缓存取每轮第一个 `step_end`,把命中 token 加起来,再除以这些请求的总输入 token。压缩节省是 `spine-cuts.jsonl` 里 `saved` 的合计。压缩轮次耗时是发生压缩的各轮总耗时之和,压缩操作本身为毫秒级。任务墙钟是从第 1 轮开始到第 31 轮结束的实际用时。结束上下文取最后一轮的 `totalTokens`,包含此前保留下来的内容。
|
|
95
|
-
|
|
96
|
-
DS V4.1 Flash 跑了 10 组,填日志 230/230,跳过 0。首步缓存 98.64%,压缩节省 65 180 token,总墙钟 36 分 18 秒。多数组结束在 3.5 万到 4.6 万 token。第 1 组读了 25 次全文,4 次压缩共节省 21 493 token,结束时仍有 282 871。第 2 组几乎只用 bash,只读了一次全文,未触发压缩,结束时是 37 781。图中的“含切割轮次墙钟”是整轮模型、工具和网络等待,不是插件小切耗时;小切操作本身为毫秒级。
|
|
97
|
-
|
|
98
|
-
GLM 5.3 Flash 用了同一个插件、同一套题。完整跑完的 7 组为 23/23;第 5、6 组连接失败;第 7 组前段连接失败,完成 14/23。有用量记录的轮次,首步缓存是 98.97%。第 1、2 组主要用 grep,未触发压缩,结束时分别是 39 511 和 29 987 token。第 4、9 组反复读全文,结束时分别是 285 535 和 281 515。GLM 图只展示插件实测;没有对应 stock 配对数据的地方不推断原版差值。
|
|
99
|
-
|
|
100
|
-

|
|
101
|
-
|
|
102
|
-

|
|
103
|
-
|
|
104
|
-

|
|
105
|
-
|
|
106
|
-
## 1.0.9
|
|
107
|
-
|
|
108
|
-
1. 云端和本地按当前配置里这一家的地址区分。请求头通常只有 provider 名。配置里的 `baseURL` 优先,没有再看官方 DeepSeek 和内置目录。公网地址按云端切,回环和内网按本地。读不到地址仍按本地。`SPINE_ENGINE=local` 或 `cloud` 可以强制指定。这不改官方大门的 headroom。
|
|
109
|
-
2. 官方大压缩的三项可以在启动前用环境变量覆盖:`SPINE_THRESHOLD_RATIO`、`SPINE_HEADROOM_TOKENS`、`SPINE_RETAIN_TOKENS`。云端默认仍是 `0.8`、`65536`、`8192`,不按地址改小。TUI 的 `/settings` 没有这一项。要改当前配置,直接改 `cordis.patch.yml` 里的对应字段。
|
|
110
|
-
3. 发版门禁是 `npm run test:gate`,不连模型。8 组 31 轮在 `test/live-fill`,要连模型。这两部分都在 GitHub 测试集里。
|
|
111
|
-
4. 测评分两个口径。云端看题对不对,以及每轮第一个 `step_end` 的缓存命中。本地看题对不对和切掉的 token。DS V4.1 Flash,8 组,184/184,跳过 0,缓存 98.22%,题末最高 35334,切掉 97306,估算费用 $0.208。GLM 5.3 Flash,同一套 8 组,184/184,同一公式缓存 74.66%。Coder 390 27B,3 组 31 轮,填日志 69/69,切掉 20635。费用是离峰用量估算,不是账单。
|
|
112
|
-
5. 安装用 npm 的 `dsh-live-compact@1.0.9`。上不了 npm 时用镜像包 https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.0.9.tgz 。页面在 https://download.merkyorlynn.com/live-compact.html 。测评图在当时的 [v1.0.9](https://github.com/Tranquillitatis-Lab/dsh-live-compact/releases/tag/v1.0.9)。
|
|
113
|
-
|
|
114
|
-

|
|
115
|
-
|
|
116
|
-

|
|
117
|
-
|
|
118
|
-
## 两场测评
|
|
119
|
-
|
|
120
|
-
两场不混在一张表里。150 道是编程短题,串在同一次对话里。20 题是 WebUniverse 长链路。
|
|
121
|
-
|
|
122
|
-

|
|
123
|
-
|
|
124
|
-

|
|
125
|
-
|
|
126
|
-
短题 150 道,Aider `polyglot-benchmark` `7e0611e`。Python、Go、JavaScript、Rust、Java 各 30 题,没有 C++,按字母序穿插。从 `python-affine-cipher`、`go-alphametics`、`javascript-affine-cipher`、`rust-accumulate`、`java-affine-cipher` 往下走。
|
|
127
|
-
|
|
128
|
-
| | 原版 | Live Compact |
|
|
129
|
-
|---|---:|---:|
|
|
130
|
-
| 通过 | 150/150 | 150/150 |
|
|
131
|
-
| 全程命中率 | 99.55% | 99.56% |
|
|
132
|
-
| 缓存命中 | 335.0M | 244.3M |
|
|
133
|
-
| 缓存未命中 | 1.498M | 1.088M |
|
|
134
|
-
| 费用 | $1.50 | $1.15,预热 0 |
|
|
135
|
-
| 上下文峰值 | 679K | 589K |
|
|
136
|
-
| 压缩 | 1 次,12.8 秒 | 145 刀,2.2 秒 |
|
|
137
|
-
| 墙钟 | 8,531 秒 | 6,105 秒 |
|
|
138
|
-
|
|
139
|
-
便宜约 23%。145 刀切掉约 474K token。峰值 589,414,结束 589,554,没到 65 万。墙钟 6,105 秒这轮只跑了插件一边,快出来的时间不能全算在插件上。
|
|
35
|
+
## 云端和本地怎么切
|
|
140
36
|
|
|
141
|
-
|
|
37
|
+
云端和本地按当前配置里这一家的地址区分。请求头通常只有 provider 名。配置里的 `baseURL` 优先,没有再看官方 DeepSeek 和内置目录。公网地址按云端切,回环和内网按本地。读不到地址仍按本地。`SPINE_ENGINE=local` 或 `cloud` 可以强制指定。这不改官方大门的 headroom。
|
|
142
38
|
|
|
143
|
-
|
|
39
|
+
云端和本地分开切。官方 DeepSeek 按公网地址切。服务商名含 strata,或地址是本机、私网、读不到,按本地切,不越过最后一条用户消息。
|
|
144
40
|
|
|
145
|
-
|
|
41
|
+
账号模式没有显式地址、恢复旧官方卡片和精确的过程通知可以组合工作;真实用户消息与未知通知仍保留边界。
|
|
146
42
|
|
|
147
|
-
|
|
148
|
-
|---|---|---|
|
|
149
|
-
| 15 道回忆题 | 15/15,15/15 | 15/15,15/15 |
|
|
150
|
-
| 违反约束 | 1 次轻微,0 | 0,0 |
|
|
151
|
-
| 日志中段 3 个细节 | 1/3;另一次 3/3,靠解压会话日志,多 10 次工具 | 3/3,3/3,查自己的备份 |
|
|
152
|
-
| 每次请求上下文 | 约 15K | 约 29K |
|
|
43
|
+
最后一条用户消息不进切段。较早的用户原文写成单行 JSON,留在卡片里。
|
|
153
44
|
|
|
154
|
-
|
|
45
|
+
## 卡片和切点
|
|
155
46
|
|
|
156
|
-
|
|
47
|
+
卡片不使用官方的 `<compacted-summary>` 和 `compact-checkpoint`。官方压缩会把那种节点当成上一版摘要再摘一次,切片摘要会越压越短。新卡片用 `spine-checkpoint`。已经写过的旧卡片仍会停住,不会再切一遍。
|
|
157
48
|
|
|
158
|
-
|
|
49
|
+
Issue #19 里下一轮输入回到 21 万到 24 万、前缀被打掉的那一刀,是切点走到了已有卡片左边。最新一张卡片当成地板。往左走到卡片就停。切点右边还有更新的卡片,这一刀不切。已进缓存的前缀不再被后面的刀改写。这是故意的。卡片已经换过一次,再穿过去会改掉已经进缓存的前缀。最新一段不够 1000,就跳过,不回头凑。
|
|
159
50
|
|
|
160
|
-
|
|
51
|
+
一轮里有不少于 1000 token 的 `read`,这一刀只切这一轮,不把要留的后 3 轮短结果一起卷进去。这一轮里单个成功或状态未知的工具结果达到 3.2 万,只留指针;已识别失败的结果保留完整诊断或原段。这一轮切不下来,才按原来的规则切更早的轮。
|
|
161
52
|
|
|
162
|
-
|
|
53
|
+
单个成功或状态未知的工具结果超过 3.2 万 token 才只留指针,并连同对应调用一起换掉。已识别的失败结果不走只留指针分支。要自己调,启动前设 `SPINE_POINTER_TOKENS`,例如 `8000`。不按占比算。
|
|
163
54
|
|
|
164
|
-
|
|
165
|
-
|---|---:|
|
|
166
|
-
| 填日志回合 | 184 |
|
|
167
|
-
| 跳过工具直接报数字 | 0 |
|
|
168
|
-
| WARN | 184/184 |
|
|
169
|
-
| NOTICE | 184/184 |
|
|
170
|
-
| 假 NOTICE | 0 |
|
|
171
|
-
| 切过的会话 | 8/8,共 17 刀 |
|
|
55
|
+
小切的停切线是 65 万。窗口更大时,过了 65 万仍会停掉小切。同一次收尾可以连切。一次收尾只记一次:第一刀之后的前缀,减去后面几刀省下的。`dsh-live-compact stats` 的 `rewrite` 用这个数。逐刀明细在 shadow 目录的 `spine-cuts.jsonl`,只有序号、token 和切点,没有消息原文。没有「省下的必须盖过重写」这种门槛。加了会把同一次收尾里后面的刀切掉。
|
|
172
56
|
|
|
173
|
-
|
|
57
|
+
提交小切前重新检查 checkpoint、用户边界和工具配对;等待期间出现的新消息也会重新检查。
|
|
174
58
|
|
|
175
|
-
|
|
59
|
+
一个空闲回合只拷贝一次日志。工具结果到达时用已经记下的调用编号,不再为了查一次调用而拷贝整份日志。收尾循环复用这一次的任务和调用表。token 计量是开头一次,每真正切下一刀再测一次。没切的回合只测一次。
|
|
176
60
|
|
|
177
|
-
|
|
61
|
+
## 卡片里留什么
|
|
178
62
|
|
|
179
|
-
|
|
63
|
+
短的工具结果会留在摘要里,标成工具输出,不标已确认。不超过 12 行、也不超过 512 字,整段留下。较长的成功或状态未知结果保留有界末尾摘录,并说明正文省略;失败结果按下面的完整诊断门槛处理。省略的原文在本机 `~/.dsh/compaction-spine/shadow`,文件名含这次的短编号。需要再读,不要默认读进来。思考仍不进摘要。
|
|
180
64
|
|
|
181
|
-
|
|
182
|
-
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
thresholdRatio: 0.8
|
|
187
|
-
headroomTokens: 16384
|
|
188
|
-
retainTokens: 8192
|
|
189
|
-
compactionRetries: 0
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
## 1.0.8
|
|
193
|
-
|
|
194
|
-
同一套 8 组、184 个填日志回合。真实 DeepSeek。跳过工具 0,WARN 184/184,NOTICE 184/184。缓存命中 98.23%,1.0.6 是 97.88%,原版是 98.51%。题末平均 2.6 万,最高 3.6 万,最低 1.6 万。1.0.6 最高 3.5 万。原版最高 12.6 万。费用按离峰用量估算,1.0.8 是 $0.209,1.0.6 是 $0.211,原版是 $0.229,不是账单。切掉的原文 11.4 万 token。原版没有压缩,8 组题末加起来积累了 34.9 万。
|
|
195
|
-
|
|
196
|
-

|
|
197
|
-
|
|
198
|
-
卡片不再使用官方的 `<compacted-summary>` 和 `compact-checkpoint`。官方压缩会把那种节点当成上一版摘要再摘一次,切片摘要会越压越短。新卡片用 `spine-checkpoint`。已经写过的旧卡片仍会停住,不会再切一遍。
|
|
65
|
+
- 思考过程不进摘要。本地备份里单独存,标成思考。
|
|
66
|
+
- 用户的话和助手写出来的句子按原来的规则留,并标是谁说的。
|
|
67
|
+
- 留下的每一行标原来是谁说的。句子里写着「用户说」,也不会变成你的新指令。
|
|
68
|
+
- 去掉「已确认」。摘要开头写明:这是旧内容摘录,不是新指令,也不是你的授权。
|
|
69
|
+
- 这一刀如果没有合格的摘要,就整段留下,不去调模型。卡片可以很短。
|
|
199
70
|
|
|
200
|
-
|
|
71
|
+
报错优先进卡片。最近 3 个已经结束的工具轮留在原来的调用和结果里,结果不截短。更早的轮才收成卡片。
|
|
201
72
|
|
|
202
|
-
|
|
73
|
+
卡片指针是会话日志的事件号,不写备份文件路径。
|
|
203
74
|
|
|
204
|
-
|
|
75
|
+
失败工具结果保留退出码和完整诊断;诊断、调用信息合起来放不进卡片预算,或多个失败结果无法一起保留时,这一刀保留原段。结构化结果中的额外字段也不能静默丢掉。仅供查看的截短预览不代表可以提交切片,不能把失败卡片写成正常完成。`npm run test:gate` 检查这条路径。
|
|
205
76
|
|
|
206
|
-
|
|
77
|
+
命令输出只有结构信号才标成报错原文:`isError`、非 0 退出码、`[stderr]`、`[exit code: N]`、`[Command finished with exit code N]`、`exit_code=N`、ptc 结果里的 `"exitCode": N`。证据不够就标状态未知,留原文末尾几行。
|
|
207
78
|
|
|
208
|
-
|
|
79
|
+
助手说的「已提交 / 已发布」不进硬行。卡片只记有调用编号的工具事件,不靠词表。
|
|
209
80
|
|
|
210
|
-
|
|
81
|
+
后台任务照常切。没结束的登记在卡片上,之后的文件以磁盘为准。失败的 kill 不会被记成已结束。
|
|
211
82
|
|
|
212
|
-
|
|
83
|
+
工具原文在官方修剪前按调用编号落盘。写失败就写无完整备份,不留悬空路径。备份按会话分目录。不自动读回下一问。
|
|
213
84
|
|
|
214
|
-
|
|
85
|
+
配置报错不再被盖成「服务已被注册」。装不上时能看见原来的原因。
|
|
215
86
|
|
|
216
|
-
|
|
87
|
+
官方摘要仍调用宿主的 `super.summarize`。与其他接管 compaction-basic 的插件并用时,若宿主返回空或不可用的摘要,本插件会明确警告并保留原段;不保证能绕过另一个插件独立生成摘要。
|
|
217
88
|
|
|
218
|
-
|
|
89
|
+
## 重启和捕获
|
|
219
90
|
|
|
220
|
-
|
|
221
|
-
- 最后一条用户消息不进切段。较早的用户原文写成单行 JSON,留在卡片里。
|
|
222
|
-
- 卡片指针是会话日志的事件号,不写备份文件路径。最近 3 个已结束的工具轮仍留原文。
|
|
223
|
-
- 单个超过 3.2 万 token 的工具结果只留序号指针,并连同对应调用一起换掉。
|
|
224
|
-
- 备份默认上限 256MB。快满时仍删最老的。`SPINE_SHADOW_MAX_BYTES` 和 `SPINE_SHADOW_MAX_MB` 还能改。
|
|
225
|
-
- 切完可看累计:`dsh-live-compact stats`。估算按未命中输入 $0.15/M,不扣重写成本。
|
|
226
|
-
- 当前会话备份可以另查:`import { searchShadow } from "dsh-live-compact/shadow-search"`。插件自己不会去搜。
|
|
227
|
-
- 65 万停切线没改。
|
|
91
|
+
进程重启后补抓工具结果,只补最近 3 轮。已经记下的位置还在,就从那里接着记。记下的位置比当前日志还大,按重启口径补最近 3 轮,不从 0 把整份日志再扫一遍。重启后会核验已有备份和游标,再从最近的工作位置继续。
|
|
228
92
|
|
|
229
|
-
|
|
93
|
+
游标和 retryable 结果按会话缓存,避免长历史重复扫描;工具结果、raw/meta 字节与 SHA256 在重启恢复后继续校验。
|
|
230
94
|
|
|
231
|
-
|
|
95
|
+
工具结果的 shadow/ACL 捕获在事件循环后排队,并按 toolCallId 去重。`finishTurn` 不等待整批历史补抓;后台队列分批恢复和重试,切片只检查选中原段需要的 raw。目标未就绪、校验失败或权限拒绝时保留原段。原始捕获和冷目录权限初始化仍有同步文件操作;排队本身不等于所有 I/O 都已异步。
|
|
232
96
|
|
|
233
|
-
-
|
|
234
|
-
- 备份按会话分目录。卡片只指向这一份文件所在的目录。
|
|
235
|
-
- 报错优先进卡片。最近 3 个已经结束的工具轮留在原来的调用和结果里,结果不截短。更早的轮才收成卡片。
|
|
236
|
-
- 助手说的「已提交 / 已发布」不进硬行。卡片只记有调用编号的工具事件,不靠词表。
|
|
237
|
-
- 后台任务照常切。没结束的登记在卡片上,之后的文件以磁盘为准。失败的 kill 不会被记成已结束。
|
|
238
|
-
- 工具原文在官方修剪前按调用编号落盘。卡片给路径、哈希和字节数。写失败就写无完整备份,不留悬空路径。
|
|
239
|
-
- 65 万停切线没改。窗口更大时,过了 65 万仍会停掉小切。
|
|
97
|
+
空闲维护的大段 catch-up 分批让出事件循环。Windows 阴影文件短暂忙时按 8 次上限和退避自动重试,永久失败保持 fail-closed,不阻塞轮次结束返回。
|
|
240
98
|
|
|
241
|
-
##
|
|
99
|
+
## 预设
|
|
242
100
|
|
|
243
|
-
|
|
101
|
+
网页和 Desktop 的四个预设在加载时会把组里的原版压缩换成这个包。换不上就落回原版,预设仍能起来。TUI 不碰。
|
|
244
102
|
|
|
245
103
|
- 预设不再硬等 gate。gate 加载失败时,网页预设不会卡在等待。换包前先试加载,失败就保留原版名字。
|
|
246
104
|
- 换上之后带上 0.8、65536、8192。预设里已有的配置优先。
|
|
247
105
|
- 预设 id 写在外层或内层都能换。standard、ptc、cordis、minimal 在 0.2.1-rc.5 上都会换。TUI 仍不碰。
|
|
248
|
-
- 命令输出只有结构信号才标成报错原文:`isError`、非 0 退出码、`[stderr]`、`[exit code: N]`、`[Command finished with exit code N]`、`exit_code=N`、ptc 结果里的 `"exitCode": N`。证据不够就标状态未知,留原文末尾几行。
|
|
249
|
-
- 长输出要先把备份写成功,卡片才指向那个文件。写失败就不切,也不指向一个还不存在的文件。
|
|
250
|
-
- 备份写成一个确定的文件,编号不存在共享引擎上。卡片里写这次备份的实际路径。
|
|
251
|
-
- 官方工具结果修剪器裁掉的内容不进这份备份。备份默认上限 256MB。满了先删最老的,删不出空间才不切。
|
|
252
106
|
- 外壳先加载。引擎装不上时,这一会话不挂起。能改用原版就用原版,并记下「本会话未接管」。原版也装不上时,`/compact` 马上返回错误。
|
|
253
107
|
- headless 的宿主包自己关掉了原版压缩。插件不能把那一行重新打开。网页预设不注入 gate,漏换这一轮就继续用原版。
|
|
254
108
|
|
|
255
|
-
##
|
|
256
|
-
|
|
257
|
-
1.0.4 安装地址是新的。1.0.0 到 1.0.3 的旧包还在原来的链接上。
|
|
109
|
+
## Windows 备份权限
|
|
258
110
|
|
|
259
|
-
|
|
111
|
+
Windows 会重新设置备份访问权限,失败时停止写备份并保留原工具输出。权限失败不再把宿主打退出,不退回 `chmod`,只提示一次;依赖该备份的修剪或切片跳过。主线程与受管 worker 共享本进程的权限熔断状态,worker 回收或重建不会解除熔断。
|
|
260
112
|
|
|
261
|
-
|
|
113
|
+
双用户实测(Actions run `42367713007`,Windows 11 Enterprise ARM / Server 2022 x64)确认:`/inheritance:r /grant:r` 会留下其他主体的显式 ACE,第二个普通用户仍能读取备份。Windows 备份完整替换 DACL。慢存储、超大历史和共享目录压力仍属于后续观察范围。
|
|
262
114
|
|
|
263
|
-
|
|
115
|
+
权限写入改为固定的 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe`(Windows PowerShell 5.1 / .NET Framework),使用 `-NoProfile -NonInteractive -EncodedCommand`。脚本固定内嵌在已打包的 `shadow.js`,路径、SID、文件类型通过子进程环境传递,不拼进脚本。当前用户 SID 仍由固定 System32 `whoami.exe` 在各权限执行上下文获取并缓存,worker 重建后重新获取,脚本再对照自身 Windows 身份。新建受保护的 DACL,只允许当前用户、SYSTEM、Administrators 完全控制;目录 ACE 带 OI/CI,直接修正的文件 ACE 不带继承标志。只修改 DACL,不提权,不改 owner、group 或 SACL,不使用临时宽松 ACL。写后读取实际 DACL,核验保护位、完整 ACE 数量、SID、Allow、权限及继承标志,收到确认才缓存。工具失败、超时、SID 非法或读回不符都会熔断本进程后续备份,不回退到 chmod。
|
|
264
116
|
|
|
265
|
-
|
|
117
|
+
目录缓存核对规范路径、设备/文件编号及创建时间;替换目录或改指向的已知别名会拒绝后续备份。经确认目录内以 `wx` 新建的空文件,核对已打开句柄与路径指向同一文件后,使用继承的 allowlist,不逐文件启动子进程,写入正文前完成检查。既有文件不能只凭父目录缓存获得信任:仅在本进程已确认同一文件身份时复用缓存,否则对被请求的文件单独替换 DACL。拒绝文件符号链接、非普通文件及多硬链接文件。不扫描或批量修复历史备份。重启恢复只读校验已有 raw/meta,不逐个收紧它们的权限;cursor 读取仍执行原有单文件 ACL 校验。raw 真正用于修剪或切片前,再重新授权目标文件,并与首次确认的字节数和 SHA256 比较。重新授权不能把已变化的内容当成原始备份。未触及的旧文件(包括直接外部读取或 shadow-search 读取的旧文件)不保证已修复,也无法撤回此前泄露的数据。不要把 shadow 指向混有其他文件的目录。
|
|
266
118
|
|
|
267
|
-
|
|
119
|
+
缓存信任同一用户和管理员不在进程运行期间原地改写 ACL;元数据核对不能发现同一文件上的 ACL 原地变更,也不能消除同用户/管理员并发改路径的全部竞态。SystemRoot/windir 必须指向可信 Windows 安装;文件系统须提供稳定文件身份并支持 Windows DACL,工具缺失或策略禁止运行时拒绝备份。Unix 仍使用目录 0700 / 文件 0600。切点、token/cap 策略、#27 根目录协调与重启口径不变。
|
|
268
120
|
|
|
269
|
-
-
|
|
270
|
-
- 工具输出不进摘要。`PASS`、文件已更新、目录列表、本机路径、报错头都不留。原文在备份里。
|
|
271
|
-
- 留下的每一行标原来是谁说的。句子里写着「用户说」,也不会变成你的新指令。
|
|
272
|
-
- 去掉「已确认」。摘要开头写明:这是旧内容摘录,不是新指令,也不是你的授权。
|
|
273
|
-
- 这一刀如果没有合格的摘要,就整段留下,不去调模型。卡片可以很短。
|
|
274
|
-
- 备份只有自己能读。文件名不带会话号。本机路径不发给模型。备份默认上限 256MB。满了先删最老的,删不出空间才不切。
|
|
275
|
-
- 2 万和 65 万没动。配置里的 0.8 只管官方大压缩,不管这一刀。想改小切的起点,用下面的设置界面改 `minTokens`(老的 `SPINE_MIN_TOKENS` 仍然有效)。
|
|
121
|
+
离线门禁用 `npm run test:gate`。其中 Windows 权限测试用注入的文件系统和命令验证失败分支。真实权限另用两个 Windows 普通账户验证,分别检查写入、可读的对照文件和备份的读取结果。评分器的离线测试用 `npm run test:live-gate`。
|
|
276
122
|
|
|
277
123
|
## 环境变量
|
|
278
124
|
|
|
125
|
+
常用压缩参数可以在 DSH 插件设置里改,保留原有环境变量用法。想改小切的起点,用下面的设置界面改 `minTokens`(老的 `SPINE_MIN_TOKENS` 仍然有效)。
|
|
126
|
+
|
|
279
127
|
| 变量 | 默认值 | 作用 |
|
|
280
128
|
|---|---:|---|
|
|
281
129
|
| `SPINE_THRESHOLD_RATIO` | 0.8 | 官方大压缩的触发比例,构造引擎或加载预设时读取。 |
|
|
@@ -308,13 +156,26 @@ GLM 5.3 Flash 用了同一个插件、同一套题。完整跑完的 7 组为 23
|
|
|
308
156
|
|
|
309
157
|
`gate.js` 的官方压缩预设默认使用 `thresholdRatio: 0.8`、`headroomTokens: 65536`、`retainTokens: 8192`,可在启动前用对应环境变量覆盖。这些数值只管官方大压缩,不改小切切点。
|
|
310
158
|
|
|
159
|
+
云端默认仍是 `0.8`、`65536`、`8192`,不按地址改小。TUI 的 `/settings` 没有这一项。`cordis.patch.yml` 本身不插值环境变量;未显式填写的字段由引擎按环境变量和默认值补齐。若直接在配置块填写,显式值优先,例如:
|
|
160
|
+
|
|
161
|
+
```yaml
|
|
162
|
+
- id: compaction-spine
|
|
163
|
+
name: dsh-live-compact
|
|
164
|
+
config:
|
|
165
|
+
auto: true
|
|
166
|
+
thresholdRatio: 0.8
|
|
167
|
+
headroomTokens: 16384
|
|
168
|
+
retainTokens: 8192
|
|
169
|
+
compactionRetries: 0
|
|
170
|
+
```
|
|
171
|
+
|
|
311
172
|
## 安装
|
|
312
173
|
|
|
313
174
|
从 npm 装。headless 和网页是两个 profile,要各装一次。桌面端是另一个 profile,普通 `dsh plugin --profile desktop` 会被拒绝。
|
|
314
175
|
|
|
315
176
|
```sh
|
|
316
|
-
dsh plugin --profile headless add dsh-live-compact@1.1.
|
|
317
|
-
dsh plugin --profile web add dsh-live-compact@1.1.
|
|
177
|
+
dsh plugin --profile headless add dsh-live-compact@1.1.5
|
|
178
|
+
dsh plugin --profile web add dsh-live-compact@1.1.5
|
|
318
179
|
```
|
|
319
180
|
|
|
320
181
|
想先装到本机看版本:
|
|
@@ -327,9 +188,9 @@ dsh-live-compact --version
|
|
|
327
188
|
上不了 npm 时的镜像安装命令:
|
|
328
189
|
|
|
329
190
|
```sh
|
|
330
|
-
dsh plugin --profile headless add https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.
|
|
331
|
-
dsh plugin --profile web add https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.
|
|
332
|
-
npm install -g --force "https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.
|
|
191
|
+
dsh plugin --profile headless add https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.5.tgz
|
|
192
|
+
dsh plugin --profile web add https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.5.tgz
|
|
193
|
+
npm install -g --force "https://download.merkyorlynn.com/downloads/plugins/dsh-live-compact-1.1.5.tgz"
|
|
333
194
|
dsh-live-compact --version
|
|
334
195
|
```
|
|
335
196
|
|
|
@@ -337,7 +198,7 @@ dsh-live-compact --version
|
|
|
337
198
|
|
|
338
199
|
DSH-TUI 同样换不掉预设里的原版压缩,先不要装。
|
|
339
200
|
|
|
340
|
-
被切掉的原文会写到 `~/.dsh/compaction-spine/shadow`。Unix 权限为目录 0700 / 文件 0600;Windows 新建/修正后的备份允许当前用户、SYSTEM、Administrators,历史文件及缓存限制见上面的 ACL 说明。上限 256MB。快满时删最老的备份。卡片里的序号是会话日志的事件号。要在当前会话的备份里找一行,用 `import { searchShadow } from "dsh-live-compact/shadow-search"
|
|
201
|
+
被切掉的原文会写到 `~/.dsh/compaction-spine/shadow`。Unix 权限为目录 0700 / 文件 0600;Windows 新建/修正后的备份允许当前用户、SYSTEM、Administrators,历史文件及缓存限制见上面的 ACL 说明。上限 256MB。快满时删最老的备份。卡片里的序号是会话日志的事件号。要在当前会话的备份里找一行,用 `import { searchShadow } from "dsh-live-compact/shadow-search"`。插件自己不会去搜。
|
|
341
202
|
|
|
342
203
|
`dsh-live-compact stats` 的 `saved` 是切完当下少掉的 token,`rewrite` 是同一次收尾实际要重写的尾巴,只记一次。同一步连切不会按刀数把尾巴乘上去。这两个数口径不同,比值不是盈亏。桌面端没有终端,`rg "spine cut"` 只在终端输出里找得到。逐刀明细在 shadow 目录的 `spine-cuts.jsonl`。
|
|
343
204
|
|
|
@@ -357,16 +218,16 @@ rm -f ~/.dsh/compaction-spine/shadow/*/*.txt ~/.dsh/compaction-spine/shadow/*.tx
|
|
|
357
218
|
|
|
358
219
|
默认目录(包括 `DSH_HOME` 下的目录)和未声明独占的目录,每次仍执行完整轮换扫描,可继续与旧版 writer 共用。仅设置 `SPINE_SHADOW_DIR` 不开启估算。需要减少扫描时,可将它指向一个**专用本地目录**,并另设 `SPINE_SHADOW_SINGLE_PROCESS=1`;即使显式指定默认目录,也不会开启。这个声明要求整个目录只由本进程的这一份插件使用,不能与旧版、不遵守协调协议的 writer、外部修改目录树或正文的程序共用。自定义代码调用底层备份函数时,必须传入同一 `root`,不能把会话子目录当根。无法满足契约时保持默认设置。
|
|
359
220
|
|
|
360
|
-
专用根首次完整扫描后,只有目录身份、容量和所有权不变、预计用量严格低于 80%,且完整校准还不到 60 秒时,才省去正文遍历。60
|
|
221
|
+
专用根首次完整扫描后,只有目录身份、容量和所有权不变、预计用量严格低于 80%,且完整校准还不到 60 秒时,才省去正文遍历。60 秒到期后,在下一次轮转时重新扫描;没有后台定时清理。快返回和写入都不会延长有效期。时钟异常或回退也改走全扫。扫描不完整或计量不合法时拒绝本次需要容量准入的备份,保留原内容,不用漏算后的数字放行。
|
|
361
222
|
|
|
362
|
-
正常锁路径下,所有普通 raw/cut/official 写入先在根目录取得原子锁并检查协作标记;cut/official 的容量检查和正文写入也在同一临界区。按 UTF-8 或 Buffer 的实际正文长度保守计账,覆盖写和失败清理不随意扣回,完整扫描后再校正。raw 沿用原来的捕获规则,写入本身不触发容量轮转;连续 raw 写入可能先超过限额,由下一次轮转处理。容量沿用正文口径,不含伴随 meta、owner、统计或锁文件,不是整个目录的物理占用硬配额。超大备份例外和删除顺序、引用保护不变;其他会话进程只有明确已死亡才按原规则清理,权限不足或 owner
|
|
223
|
+
正常锁路径下,所有普通 raw/cut/official 写入先在根目录取得原子锁并检查协作标记;cut/official 的容量检查和正文写入也在同一临界区。按 UTF-8 或 Buffer 的实际正文长度保守计账,覆盖写和失败清理不随意扣回,完整扫描后再校正。raw 沿用原来的捕获规则,写入本身不触发容量轮转;连续 raw 写入可能先超过限额,由下一次轮转处理。容量沿用正文口径,不含伴随 meta、owner、统计或锁文件,不是整个目录的物理占用硬配额。超大备份例外和删除顺序、引用保护不变;其他会话进程只有明确已死亡才按原规则清理,权限不足或 owner 状态不明时保守保留。普通 cut/official 的容量扫描、删除和发布事务在受管 worker 中执行,同一个 root 的任务串行,空闲 worker 自动回收;共享目录仍完整扫描,不以估算跳过。底层同步 API 和原始 raw 捕获保留各自的同步语义。
|
|
363
224
|
|
|
364
|
-
`.spine-rotation.owner`
|
|
225
|
+
`.spine-rotation.owner` 保存 PID 与随机生命周期标识。没有 shared 围栏、记录格式有效且旧 PID 明确已死亡时,新生命周期可安全重建所有权并重新完整扫描;不能确认死亡时不得抢占。第二个参与进程、worker 或插件副本(含路径别名)会先创建 `.spine-rotation.shared`,再写正文;之后此根一直退回完整扫描,另一进程退出也不自动恢复估算。该标记只检测协作方,不能发现旧版或外部 writer。锁由同目录临时文件完整写入、刷盘并关闭后,通过原子硬链接发布为 `.spine-rotation.lock`,包含持有者 PID 和每次事务唯一的随机标识。发布成功后的临时名称清理失败不会丢失锁的精确所有权,也不会阻断后续备份;可能残留不参与轮换的临时名称。
|
|
365
226
|
|
|
366
227
|
仅当硬链接操作本身返回 `ENOTSUP`、`EOPNOTSUPP` 或 `ENOSYS` 时,先刷盘 shared 围栏,再确认没有先前的活跃或潜在独占事务,才允许原来的完整轮换和 raw/cut/official/游标写入;此根不再启用独占估算。正文写入前继续核验围栏和锁状态。`EPERM`、`EACCES`、`EIO`、`EXDEV`、`EINVAL` 等不明确错误,以及其他步骤返回的 unsupported 错误,都拒绝本次备份。该回退沿用旧共享并发语义,不提供独占容量保证。
|
|
367
228
|
|
|
368
229
|
活跃锁、PID 已复用、旧版空目录锁、记录损坏或无法确认死亡时,本次备份被拒绝,原文保留;不按锁龄抢占,`EPERM` 和未知错误也不代表死亡。只有 `process.kill(pid, 0)` 明确返回 `ESRCH`,才先持久化 shared 标记、清除估算,并将该锁的完整身份原子记录到 `.spine-rotation.recovered`;硬链接不支持时以 `.spine-rotation.recovered-<pid>-<事务标识>` 空文件的完整名称记录并刷盘,避免半写 JSON。原锁始终保留作围栏,不删除、不替换;之后所有协作实例对这个已确认死亡的身份均走原来的完整轮换和正文写入,PID 后来复用也不改变该身份已经死亡的事实。恢复后共享操作沿用原来的并发语义,不再提供独占容量临界区。标记文件均刷盘,POSIX 另刷目录;Windows 的 Node 接口不能刷目录句柄,不承诺突然断电后的目录项持久性。
|
|
369
230
|
|
|
370
|
-
|
|
231
|
+
正常重启没有遗留锁时,仅格式有效且 PID 明确死亡的 owner 可以重建;旧版无 PID 的 owner、已有 shared 围栏和无法确认的记录仍保守退回全扫。主线程与 worker 的不同生命周期也可能触发 shared,因此该开关不保证每次生产写入都使用估算。需要人工重新启用独占估算时,应选新专用目录,或仅在所有使用者停止后清除 `.spine-rotation.lock`、`.spine-rotation.owner`、`.spine-rotation.shared`、`.spine-rotation.recovered` 及该根的事务专属 recovered 空文件。旧版空锁等不明确的记录也只能在确认全部使用者停止后人工处理。与不遵守协议的旧版 writer 共用时,仍不得声明专用目录契约。
|
|
371
232
|
|
|
372
233
|
MIT,见 `LICENSE`。
|