dsh-recency-guard 0.11.3 → 0.12.1
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/README.md +84 -0
- package/dist/client.js +841 -164
- package/dist/index.js +799 -246
- package/locale/en.json +22 -4
- package/locale/zh.json +21 -3
- package/package.json +27 -18
package/README.md
CHANGED
|
@@ -65,6 +65,90 @@
|
|
|
65
65
|
|
|
66
66
|
当某个插件把 DSH 拖垮时,本插件会在崩溃的那一刻记录下"谁最可疑",并在**下一次启动时、在崩溃插件的代码被加载之前**把它挡在门外。反复崩溃时,关闭的插件会逐个增加(第 1 次关最近更新的 1 个,仍崩溃则关最近更新的 2 个)。稳定之后,除首要嫌疑外,其余被关闭的配置会自动恢复。
|
|
67
67
|
|
|
68
|
+
## v0.12.1 修复(两条均由真机用户旅程发现)
|
|
69
|
+
|
|
70
|
+
- **崩溃信号补第二条通道(P0 检测缺口)**:崩溃信号此前**只有哨兵文件**,而哨兵写在
|
|
71
|
+
`process.on('exit')` 里 —— SIGKILL / OOM killer / 断电 / 原生段错误**根本不运行
|
|
72
|
+
exit 处理器**。真机实测:强杀后 `bootMarker` 残留(pid 已死)而 `crashSeq` 仍是 0,
|
|
73
|
+
下一次启动报「启动时未发现上次崩溃」。
|
|
74
|
+
危险的不是少记一次,而是**崩溃循环失去升级依据**:插件以原生方式撞死宿主时,
|
|
75
|
+
每一轮都只看到残留标记、每一轮都被当成干净启动清零计数 ⇒ 永远停在「关 0 个」。
|
|
76
|
+
新增 `classifyAbnormalExit` 四种结局:
|
|
77
|
+
- `clean`(无残留 / 有哨兵)⇒ 归零;有哨兵时走既有通道、**不重复计数**;
|
|
78
|
+
- `self-reload`(残留 pid == 本进程,热重载/HMR)⇒ 归零 + 留痕;
|
|
79
|
+
- `concurrent`(残留 pid 仍活着且不是自己)⇒ 归零 + 留痕「另一个实例在运行」;
|
|
80
|
+
- `abnormal`(残留 pid 已死)⇒ 计数 +1,累计到 `confirmRounds` 才动手。
|
|
81
|
+
异常终止按**概率性证据**处理(残留标记也可由人为杀进程/关机产生):第 1 轮只观察、
|
|
82
|
+
第 2 轮才行动,达阈值后复用既有 `recover()` 通道关闭(不另写一套关闭逻辑,
|
|
83
|
+
避免两条通道的隔离语义各自漂移)。真机两次强杀验证:
|
|
84
|
+
`1/2 轮 act=false` → `2/2 轮 act=true 关闭 1 个`。
|
|
85
|
+
顺带修了引出它的二阶缺陷:原 `recovering && !crashedLastRun` 把「没有哨兵」
|
|
86
|
+
当「活过了启动」的代理,新通道下异常终止同样没有哨兵 ⇒ 会把「关了嫌疑 → 又死一次」
|
|
87
|
+
读成「崩溃已过」而恢复全部插件,亲手拆掉刚建立的隔离。现改为要求
|
|
88
|
+
`exitClass === 'clean'`,并拆成纯函数 `shouldRestoreAfterBoot` 用 5 条单测钉住。
|
|
89
|
+
- **小地图点击无反应(真机 GUI 实测)**:`setPointerCapture?.(id)` 排在
|
|
90
|
+
`onNavigate(...)` **之前**,而可选链只保护「方法不存在」、**不保护方法抛异常**。
|
|
91
|
+
浏览器在 pointerId 失效时按规范抛 `NotFoundError` ⇒ 整条 handler 中断 ⇒
|
|
92
|
+
点小地图毫无反应(只有控制台有痕迹)。一个只为「拖拽连续性」存在的可选优化,
|
|
93
|
+
否决了「定位到那一块」这个主功能。
|
|
94
|
+
修法:捕获/释放各自 `try` 包裹并抽成 `capturePointer`/`releasePointer`;
|
|
95
|
+
新增 3 条**源码门**(`minimap-gesture.test.ts`)钉住「不得出现裸调用」,
|
|
96
|
+
并经**变异自证**会响(写回裸调用 ⇒ 恰 1 条断言 FAIL)。真机复验:
|
|
97
|
+
导航生效且 0 未捕获异常。
|
|
98
|
+
|
|
99
|
+
## v0.12 新增(命令窗口显示接线 · 乐观并发 · L4 审计线 · 依赖代际对齐)
|
|
100
|
+
|
|
101
|
+
- **命令窗口显示修复(根因级)**:`presentCall` / `presentResult` /
|
|
102
|
+
`output.presentationMeta` 三个展示投影**此前写好了却没接进 `defineTool`** ——
|
|
103
|
+
宿主因此落回通用回退卡片:标题是裸工具名 `recency_guard`、正文是整坨参数 JSON。
|
|
104
|
+
接线后待执行卡片显示人话摘要(`事件时间线 · 最多 40 条`),完成卡片显示
|
|
105
|
+
带标题与可折叠分区。同时把本地视图类型换成宿主词汇(`ToolCallView` /
|
|
106
|
+
`ToolResultView`,`content` 是 `ContentBlock[]` 而非 `string`)—— 类型漂移
|
|
107
|
+
正是「写了不消费」的恶果。反漂移双门:契约源码门 + 宿主行为门(走宿主同一条
|
|
108
|
+
数据流 `execute → presentationMeta → presentResult`,含旧记录回放的诚实降级)。
|
|
109
|
+
- **乐观并发 revision(防「过期按钮」)**:面板快照带一枚从
|
|
110
|
+
state+decision+journal 尾派生的 12 hex 哈希;动作请求携带
|
|
111
|
+
`expectedRevision`,凭证过期 ⇒ **409 且动作不执行**(不是执行了再报错),
|
|
112
|
+
并回传当前凭证供重读。用哈希而非计数器:计数器需要单调持久位点,崩溃时
|
|
113
|
+
会落后于状态(假冲突/假放行),哈希幂等 ⇒ 崩溃重启后同一事实必得同一枚。
|
|
114
|
+
缺参数 400 优先于 409;不带凭证放行(agent 主动修复路径);跨分区只读视图
|
|
115
|
+
恒 `null`(只读无可改事实,带凭证必然假冲突)。面板动作已带凭证 + 冲突提示条。
|
|
116
|
+
**同源性是结构保证**:两处装配唯一收敛到 `Guard.revisionFactsFrom`,
|
|
117
|
+
并由端到端门断言「面板凭证 == 动作路径凭证」,该门经变异实验自证会响。
|
|
118
|
+
- **L4 审计线**:写动作(recover/restore/reenable/archive)在**执行之前**
|
|
119
|
+
落一条审计行 `{actor, action, justification}`(崩溃发生在动作中间时理由已在盘上);
|
|
120
|
+
读动作零噪声(否则面板每 5s 轮询会把崩溃因果链冲掉)。复用 journal 的 `note`
|
|
121
|
+
通道而不是新开 kind —— kind 是跨层词汇表,漏改任一处审计行就在事件流里静默消失。
|
|
122
|
+
- **依赖代际对齐宿主(阻断级修复)**:`cordis` peer 从 `~4.0.5` 改为
|
|
123
|
+
`>=4.0.5 <5.0.0`。宿主实际携带 cordis **4.1.0** ⇒ 旧范围下 npm 安装会被
|
|
124
|
+
兼容闸门**整体拒绝并回滚**;桌面端用 `link:` 直连源码从不走闸门,所以这个洞
|
|
125
|
+
在本机完全不可见。devDependencies 同时从 0.2.1-rc.5 全量对齐装机代际
|
|
126
|
+
**0.2.2-rc.1**(此前测试跑在一个从未有人装过机器的代际上:绿灯不代表装机绿)。
|
|
127
|
+
新增「以宿主真实事实为见证」的契约门 11 条:逐 peer 用 `runtime/`(从 app.asar
|
|
128
|
+
解出)的装机版本做 `semver.satisfies` 判定 + devDep == 装机版本断言。
|
|
129
|
+
- **dsh.compatibility.dshReleases**:逐发布线声明 compatible(借鉴 dsh-context),
|
|
130
|
+
市场索引与兼容闸门可逐版本判定,而不是只看 engines 区间。
|
|
131
|
+
- **图谱交互补齐**:k 跳邻域聚焦(原「只看关联」是传递闭包 ⇒ 连通图上等于
|
|
132
|
+
不过滤,即「点了没反应」)、小地图 Overview(可点可拖的缩略导航,往返误差
|
|
133
|
+
< 1e-9)、边宽 = 连接度对数刻度、键盘方向键二维导航 + `aria-keyshortcuts`。
|
|
134
|
+
- **技术债清理**:数据层显示截断 4 处(「报 N 只列 5」同族,含搜索指示器
|
|
135
|
+
对 20 个命中说「第 1/8 个」的假话)改为数据给全量 + 渲染层显式省略计数;
|
|
136
|
+
i18n parity 测试补上(回退链会掩盖缺键:只在 zh 加键则英文露中文原文而 CI 全绿);
|
|
137
|
+
路由日志面桥回宿主 logger(console.error 不进宿主日志采集面);
|
|
138
|
+
防抖计时器持有 + `unref()` + dispose 清理(热重载不留幽灵定时器)。
|
|
139
|
+
- **复杂度治理**:工具注册抽出 `tool-registration.ts`;小地图几何抽出
|
|
140
|
+
`minimap-model.ts`(graph-model 117 → 101;且刻意从 `LAYOUT` 各自直读避免
|
|
141
|
+
graph-model ⇄ minimap-model 循环依赖 —— 循环里的常量 TDZ 会让
|
|
142
|
+
「小地图矩形尺寸随机为 0」只在一台机器上复现)。
|
|
143
|
+
|
|
144
|
+
## v0.11.4 触屏双指缩放(图谱交互补齐)
|
|
145
|
+
|
|
146
|
+
- **双指捏合缩放**:两指同时按下即进入捏合 —— 中点下的世界点在缩放中保持
|
|
147
|
+
不动(与单指缩放同一不变式),同时中点位移会带动画布平移;捏合期间取消
|
|
148
|
+
画布平移拖拽,抬指后清空取样。退化输入(两指重合/非有限)返回原视口,
|
|
149
|
+
绝不产生 Infinity。
|
|
150
|
+
- 回归:viewport 新增 4 条捏合断言(翻倍缩放/锚点不动/跟随平移/退化与上界)。
|
|
151
|
+
|
|
68
152
|
## v0.11.3 图谱交互补齐(边可交互 + 布局过渡)
|
|
69
153
|
|
|
70
154
|
- **边可交互(审计 P0 收尾)**:此前边完全不可点击、`edge.label` 是死数据。
|