dsh-plugin-message-edit 1.0.0 → 1.1.0

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/LICENSE CHANGED
@@ -1,24 +1,24 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 SpookySandwich
4
-
5
- Portions of the host-side branching logic are derived from dsh-message-edit,
6
- Copyright (c) Moeblack, also released under the MIT License.
7
-
8
- Permission is hereby granted, free of charge, to any person obtaining a copy
9
- of this software and associated documentation files (the "Software"), to deal
10
- in the Software without restriction, including without limitation the rights
11
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
- copies of the Software, and to permit persons to whom the Software is
13
- furnished to do so, subject to the following conditions:
14
-
15
- The above copyright notice and this permission notice shall be included in all
16
- copies or substantial portions of the Software.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SpookySandwich
4
+
5
+ Portions of the host-side branching logic are derived from dsh-message-edit,
6
+ Copyright (c) Moeblack, also released under the MIT License.
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
package/README.en.md CHANGED
@@ -2,8 +2,10 @@
2
2
 
3
3
  English | [简体中文](README.md)
4
4
 
5
+ [![npm](https://img.shields.io/npm/v/dsh-plugin-message-edit?color=cb3837&logo=npm)](https://www.npmjs.com/package/dsh-plugin-message-edit)
6
+ [![CI](https://github.com/SpookySandwich/dsh-plugin-message-edit/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/SpookySandwich/dsh-plugin-message-edit/actions/workflows/ci.yml)
5
7
  [![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
6
- [![dsh](https://img.shields.io/badge/dsh-0.1.0--rc.7-4b8dff)](https://github.com/deepseek-ai/deepseek-harness)
8
+ [![dsh](https://img.shields.io/badge/dsh-0.1.5--rc.2-4b8dff)](https://github.com/deepseek-ai/deepseek-harness)
7
9
  [![stars](https://img.shields.io/github/stars/SpookySandwich/dsh-plugin-message-edit?style=flat&label=stars)](https://github.com/SpookySandwich/dsh-plugin-message-edit/stargazers)
8
10
 
9
11
  Edit a message you already sent and the conversation **rewinds and branches** from that point, the way ChatGPT, Claude and DeepSeek all do it. The old version is not overwritten — a `‹ 2/4 ›` counter appears under the bubble, and a Versions tab draws the whole tree.
@@ -68,11 +70,24 @@ For technical details and developer guides, see:
68
70
  - [Tree Data Model & Algorithms](docs/TREE_DATA_MODEL.md): Turn-level message tree projection, sibling fan-out, ghost recovery, and active path calculation.
69
71
  - [Development & Testing Guide](docs/DEVELOPMENT.md): Build pipeline, automated test suite, and local installation instructions.
70
72
 
71
- ## Compatibility
73
+ ## Compatibility
74
+
75
+ Version `1.1.0`: Fix seeded edit/retry creation, clear inherited pending input before publication, identify version markers by session ownership, preserve reasoning effort, and read persisted branches through disposable session observations.
76
+
77
+ The declared host range is `>=0.1.5-rc.2 <0.1.6-0`; the official `0.1.5-rc.2` runtime was verified. DSH `0.1.6` alpha is not claimed compatible. Keep the previous plugin release on older DSH. [Validation record](.github/reviews/dsh-0.1.5.md).
78
+
79
+ Download the archive from the [GitHub Release](https://github.com/SpookySandwich/dsh-plugin-message-edit/releases/tag/v1.1.0), then run `dsh plugin --profile desktop add ./dsh-plugin-message-edit-1.1.0.tgz`.
80
+
81
+ Version `1.1.0` has been verified in an isolated DSH `0.1.5-rc.2` Web environment:
82
+ plugin loading, images, edit/retry, nested branches, and restored sessions. Model
83
+ responses use a local test adapter; remote model services were not exercised.
84
+
85
+ The compatibility layer retains the older `events` / `seedLength` interfaces,
86
+ covered by automated tests. Later DSH releases need separate verification.
87
+ Restart DSH after updating the plugin.
72
88
 
73
89
  Coexists with [dsh-plugin-smooth-stream](https://github.com/SpookySandwich/dsh-plugin-smooth-stream) and [dsh-plugin-rollout-scout](https://github.com/SpookySandwich/dsh-plugin-rollout-scout).
74
90
 
75
91
  ## License
76
92
 
77
93
  MIT © SpookySandwich. Portions of the host half derive from dsh-message-edit (MIT © Moeblack).
78
-
package/README.md CHANGED
@@ -2,8 +2,10 @@
2
2
 
3
3
  [English](README.en.md) | 简体中文
4
4
 
5
+ [![npm](https://img.shields.io/npm/v/dsh-plugin-message-edit?color=cb3837&logo=npm)](https://www.npmjs.com/package/dsh-plugin-message-edit)
6
+ [![CI](https://github.com/SpookySandwich/dsh-plugin-message-edit/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/SpookySandwich/dsh-plugin-message-edit/actions/workflows/ci.yml)
5
7
  [![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
6
- [![dsh](https://img.shields.io/badge/dsh-0.1.0--rc.7-4b8dff)](https://github.com/deepseek-ai/deepseek-harness)
8
+ [![dsh](https://img.shields.io/badge/dsh-0.1.5--rc.2-4b8dff)](https://github.com/deepseek-ai/deepseek-harness)
7
9
  [![stars](https://img.shields.io/github/stars/SpookySandwich/dsh-plugin-message-edit?style=flat&label=stars)](https://github.com/SpookySandwich/dsh-plugin-message-edit/stargazers)
8
10
 
9
11
  编辑一条已经发出的消息,对话会从那一刻 **真正回溯并分叉**——和 ChatGPT、Claude、DeepSeek 的做法一致。旧版本不会被覆盖:气泡下方出现 `‹ 2/4 ›` 计数,「版本」标签页则画出整棵树。
@@ -68,11 +70,20 @@ DSH 的会话是仅追加的事件日志,本身不支持会话内分支,因
68
70
  - [树数据模型与算法 (Tree Data Model)](docs/TREE_DATA_MODEL.md):轮次级消息树构建、同级展开、删除会话(Ghost)桥接与高亮路径计算。
69
71
  - [开发与测试指南 (Development)](docs/DEVELOPMENT.md):构建流程、单元测试与本地安装说明。
70
72
 
71
- ## 兼容性
73
+ ## 兼容性
74
+
75
+ 版本 `1.1.0`:修复编辑/重试的 seed 边界,发布分支前清空继承的待发送输入,按会话身份识别版本标记,保留推理强度,并通过会话观察接口恢复持久分支。
76
+
77
+ 声明兼容范围为 `>=0.1.5-rc.2 <0.1.6-0`;已验证官方 `0.1.5-rc.2`,不声明兼容 `0.1.6` alpha。旧版 DSH 请保留上一插件版本。[验证记录](.github/reviews/dsh-0.1.5.md)。
78
+
79
+ 可从 [GitHub Release](https://github.com/SpookySandwich/dsh-plugin-message-edit/releases/tag/v1.1.0) 下载发布包,然后执行 `dsh plugin --profile desktop add ./dsh-plugin-message-edit-1.1.0.tgz`。
80
+
81
+ `1.1.0` 已在 DSH `0.1.5-rc.2` 的隔离 Web 环境验证:插件加载、图片显示、编辑与重试、深层分支,以及持久会话的恢复读取。模型回复使用本地测试实现,未调用远程模型服务。
82
+
83
+ 兼容层保留了旧版 `events` / `seedLength` 接口支持,并由自动测试覆盖。DSH 仍在快速迭代,尚未验证的后续版本不在此保证范围内。更新插件后请重启 DSH。
72
84
 
73
85
  可与 [dsh-plugin-smooth-stream](https://github.com/SpookySandwich/dsh-plugin-smooth-stream)、[dsh-plugin-rollout-scout](https://github.com/SpookySandwich/dsh-plugin-rollout-scout) 共存。
74
86
 
75
87
  ## 许可
76
88
 
77
89
  MIT © SpookySandwich。宿主端部分逻辑源自 dsh-message-edit(MIT © Moeblack)。
78
-
package/cordis.patch.yml CHANGED
@@ -1,7 +1,7 @@
1
- # The loader entry id stays `message-tree` on purpose: Moeblack's
2
- # dsh-message-edit uses the id `message-edit`, and two entries sharing an id
3
- # collide when both plugins are installed. `name` is the package to import,
4
- # so it follows the package rename.
5
- - insert:
6
- - id: message-tree
7
- name: dsh-plugin-message-edit
1
+ # The loader entry id stays `message-tree` on purpose: Moeblack's
2
+ # dsh-message-edit uses the id `message-edit`, and two entries sharing an id
3
+ # collide when both plugins are installed. `name` is the package to import,
4
+ # so it follows the package rename.
5
+ - insert:
6
+ - id: message-tree
7
+ name: dsh-plugin-message-edit
@@ -1,156 +1,168 @@
1
- # Architecture Overview
2
-
3
- `dsh-plugin-message-edit` provides ChatGPT/Claude-style conversation branching and message editing for [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness).
4
-
5
- Because DSH session event logs are append-only without native in-session branching, this plugin splits responsibilities across a **Node.js Host Service** and a **Browser/Web Client**.
6
-
7
- ---
8
-
9
- ## 1. System Components
10
-
11
- ```
12
- ┌─────────────────────────────────────────────────────────────┐
13
- │ DSH Desktop / Web │
14
- │ │
15
- │ ┌──────────────────────┐ ┌──────────────────────┐ │
16
- │ │ Client Half │ HTTP │ Host Half │ │
17
- │ │ (plugin.client.js) │<───────>│ (lib/index.js) │ │
18
- │ └──────────┬───────────┘ └──────────┬───────────┘ │
19
- │ │ │ │
20
- │ Shadow User Message Cordis Services: │
21
- │ Versions Tab (Graph) - sessions │
22
- │ Settings UI - agents │
23
- │ - webServer │
24
- │ - sessionPersistence │
25
- └─────────────────────────────────────────────────────────────┘
26
- ```
27
-
28
- ### 1.1 Host Half (`lib/index.js`)
29
- - Runs in the Node.js backend process via Cordis lifecycle injection.
30
- - Registers the `/message-tree` HTTP route on `ctx.webServer`.
31
- - Owns branch creation transactions (`POST /message-tree`):
32
- 1. Truncates parent events up to the target turn.
33
- 2. Seeds a new DSH session with the prefix events.
34
- 3. Appends a durable `message-tree/version` marker with `ignorable: true`.
35
- 4. Submits the edited prompt into the new session.
36
- - Owns graph queries (`GET /message-tree?sessionId=...`):
37
- - Traverses the session family DAG.
38
- - Recovers deleted/ghost ancestors from surviving descendants' event logs.
39
- - Extracts turn event boundaries for turn-level rendering.
40
-
41
- ### 1.2 Client Half (`plugin.client.js`)
42
- - Runs in the browser / renderer process.
43
- - Injects a shadowed `user` message renderer at priority `-1` to add the edit/copy/retry toolbar and `‹ n/m ›` version ring without modifying agent responses, tool calls, or reasoning blocks.
44
- - Adds the **Versions** tab (`VIEW_ORDER: 16`) providing an interactive pan/zoom graph with spring physics.
45
- - Adds settings options in **Settings → Message Edit** with live layout switching (ChatGPT, DeepSeek, Claude styles).
46
-
47
- ---
48
-
49
- ## 2. Durable Storage Model
50
-
51
- DSH sessions are immutable append-only logs. When branching:
52
-
53
- 1. **Seed Inheritance**: A new session is initialized whose log begins with an exact clone of the parent's event log up to the start of the edited turn (`seedLength`).
54
- 2. **Durable Marker**: The host appends a custom event:
55
- ```json
56
- {
57
- "type": "message-tree/version",
58
- "data": {
1
+ # Architecture Overview
2
+
3
+ `dsh-plugin-message-edit` provides ChatGPT/Claude-style conversation branching and message editing for [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness).
4
+
5
+ Because DSH session event logs are append-only without native in-session branching, this plugin splits responsibilities across a **Node.js Host Service** and a **Browser/Web Client**.
6
+
7
+ ---
8
+
9
+ ## 1. System Components
10
+
11
+ ```
12
+ ┌─────────────────────────────────────────────────────────────┐
13
+ │ DSH Desktop / Web │
14
+ │ │
15
+ │ ┌──────────────────────┐ ┌──────────────────────┐ │
16
+ │ │ Client Half │ HTTP │ Host Half │ │
17
+ │ │ (plugin.client.js) │<───────>│ (lib/index.js) │ │
18
+ │ └──────────┬───────────┘ └──────────┬───────────┘ │
19
+ │ │ │ │
20
+ │ Shadow User Message Cordis Services: │
21
+ │ Versions Tab (Graph) - sessions │
22
+ │ Settings UI - agents │
23
+ │ - webServer │
24
+ │ - sessionPersistence │
25
+ └─────────────────────────────────────────────────────────────┘
26
+ ```
27
+
28
+ ### 1.1 Host Half (`lib/index.js`)
29
+ - Runs in the Node.js backend process via Cordis lifecycle injection.
30
+ - Normalizes DSH sessions through `lib/session-record.js`: current live sessions
31
+ expose `snapshotEvents()`, query snapshots carry their header in `session`,
32
+ and older records expose `events` / `header`. Invalid logs fail explicitly.
33
+ - DSH 0.1.5 branches use `meta.isSeeded` plus `inheritedEventCount`, which must
34
+ equal the complete constructor seed length. New markers carry their owning
35
+ `sessionId`; old markers without that field use the legacy inherited cut.
36
+ Cold logs use `observeSession(..., { projectionMode: 'none' })` and release
37
+ the observation lease; this restores seeded sessions through the correct API.
38
+ - Registers the `/message-tree` HTTP route on `ctx.webServer`.
39
+ - Owns branch creation transactions (`POST /message-tree`):
40
+ 1. Truncates parent events up to the target turn.
41
+ 2. Adds an ignorable `message-tree/version` marker to the constructor seed.
42
+ 3. Creates the agent and clears both inherited inbox queues in its setup,
43
+ before publication can schedule the rewound original input.
44
+ 4. Flushes the branch and submits the edited prompt exactly once.
45
+ - Owns graph queries (`GET /message-tree?sessionId=...`):
46
+ - Traverses the session family DAG.
47
+ - Recovers deleted/ghost ancestors from surviving descendants' event logs.
48
+ - Extracts turn event boundaries for turn-level rendering.
49
+
50
+ ### 1.2 Client Half (`plugin.client.js`)
51
+ - Runs in the browser / renderer process.
52
+ - Injects a shadowed `user` message renderer at priority `-1` to add the edit/copy/retry toolbar and `‹ n/m ›` version ring without modifying agent responses, tool calls, or reasoning blocks.
53
+ - Adds the **Versions** tab (`VIEW_ORDER: 16`) providing an interactive pan/zoom graph with spring physics.
54
+ - Adds settings options in **Settings Message Edit** with live layout switching (ChatGPT, DeepSeek, Claude styles).
55
+
56
+ ---
57
+
58
+ ## 2. Durable Storage Model
59
+
60
+ DSH sessions are immutable append-only logs. When branching:
61
+
62
+ 1. **Seed Inheritance**: Copy the parent prefix before the edited turn, then add the plugin marker. The full constructor seed is inherited on DSH 0.1.5; the kernel adds its own `session/end-seed` afterwards.
63
+ 2. **Durable Marker**: The seed carries a custom event with explicit child ownership:
64
+ ```json
65
+ {
66
+ "type": "message-tree/version",
67
+ "data": {
59
68
  "schemaVersion": 1,
60
- "effect": {
61
- "operation": "edit",
62
- "targetTurn": 1,
63
- "targetEventSeq": 5,
64
- "before": "Original message text",
65
- "after": "Edited message text"
66
- },
67
- "inverse": {
68
- "kind": "restore-version",
69
- "sessionId": "parent-session-id"
70
- }
71
- }
72
- }
73
- ```
74
- 3. **`ignorable` Flag**: Custom plugin event types fall outside DSH's core schema. The event envelope must set `ignorable: true`; otherwise, DSH's built-in event reader will reject the entire session log.
75
-
76
- ---
77
-
78
- ## 3. HTTP API
79
-
80
- ### `GET /message-tree?sessionId={id}`
81
- Returns the entire conversation family surrounding the requested session.
82
-
83
- **Response Schema:**
84
- ```json
85
- {
86
- "sessionId": "current-session-id",
87
- "versions": [
88
- {
89
- "sessionId": "session-a",
90
- "createdAt": 1724334000000,
91
- "depth": 0,
92
- "current": false,
93
- "onCurrentPath": true,
94
- "turns": [
95
- { "turn": 1, "text": "Hello", "time": 1724334001000 },
96
- { "turn": 2, "text": "Tell me more", "time": 1724334005000 }
97
- ]
98
- },
99
- {
100
- "sessionId": "session-b",
101
- "parentSessionId": "session-a",
102
- "createdAt": 1724334020000,
103
- "depth": 1,
104
- "current": true,
105
- "onCurrentPath": true,
106
- "operation": "edit",
107
- "targetTurn": 1,
108
- "before": "Hello",
109
- "after": "Hello world",
110
- "turns": [
111
- { "turn": 1, "text": "Hello world", "time": 1724334021000 },
112
- { "turn": 2, "text": "What is next?", "time": 1724334025000 }
113
- ]
114
- }
115
- ]
116
- }
117
- ```
118
-
119
- ### `POST /message-tree`
120
- Performs branch creation or reactivation.
121
-
122
- - **`edit`**: Rewinds to before the specified user turn, creates a new branched session, appends a durable `message-tree/version` marker, and submits the replacement prompt.
123
- - **`retry`**: Rewinds to before the target turn, creates a child session, and replays the original user prompt.
124
- - **`activate`**: Unarchives an archived version session via the host registry queue so the client can navigate to it.
125
-
126
- ---
127
-
128
- ## 4. Performance & In-Memory Caching
129
-
130
- 1. **Host-Side Parsed Session Cache (`sessionParsedCache`)**:
131
- - Parses turn boundaries (`extractTurns`) and version headers once per immutable event sequence.
132
- - Bounded to 500 session entries with key invalidation on live event count / disk mtime changes.
133
- - Subsequent `tree()` queries across siblings in the family hit in-memory cache in sub-millisecond time.
134
-
135
- 2. **Client-Side Family SWR Store (`treeStore`)**:
136
- - Maps every non-deleted branch in a tree to the shared family structure upon fetch.
137
- - Switching between sibling branches (`‹ n/m ›` or Versions view) is 100% synchronous (0ms lag, zero indicator flicker).
138
- - Uses monotonic request timestamps to prevent race-condition overwrites from out-of-order responses.
139
- - Optimistically seeds newly created edit/retry branches before navigation.
140
-
141
- ---
142
-
143
- ## 5. Security and Error Resilience
144
-
145
- - **Ignorable Event Envelope**: `ignorable: true` ensures foreign event markers do not crash the core DSH log parser.
146
- - **Fail-Safe Mutation Recovery**: Transaction reversals (`child.dispose()`) on failures prevent dangling session artifacts.
147
- - **Memory Bounded Stores**: LRU bounds (500 sessions) prevent unbounded memory growth in long-running processes.
148
-
149
- ## 6. Naming & Namespaces
150
-
151
- - **NPM Package**: `dsh-plugin-message-edit`
152
- - **Cordis Service Name**: `message-tree`
153
- - **HTTP Path**: `/message-tree`
154
- - **Durable Event Type**: `message-tree/version`
155
-
156
- > The package uses `dsh-plugin-message-edit` for discovery, but retains `message-tree` in routes, cordis IDs, and event types to prevent collisions with prior third-party plugins (such as `dsh-message-edit`) and ensure seamless side-by-side operation.
69
+ "sessionId": "child-session-id",
70
+ "effect": {
71
+ "operation": "edit",
72
+ "targetTurn": 1,
73
+ "targetEventSeq": 5,
74
+ "before": "Original message text",
75
+ "after": "Edited message text"
76
+ },
77
+ "inverse": {
78
+ "kind": "restore-version",
79
+ "sessionId": "parent-session-id"
80
+ }
81
+ }
82
+ }
83
+ ```
84
+ 3. **`ignorable` Flag**: Custom plugin event types fall outside DSH's core schema. The event envelope must set `ignorable: true`; otherwise, DSH's built-in event reader will reject the entire session log.
85
+
86
+ ---
87
+
88
+ ## 3. HTTP API
89
+
90
+ ### `GET /message-tree?sessionId={id}`
91
+ Returns the entire conversation family surrounding the requested session.
92
+
93
+ **Response Schema:**
94
+ ```json
95
+ {
96
+ "sessionId": "current-session-id",
97
+ "versions": [
98
+ {
99
+ "sessionId": "session-a",
100
+ "createdAt": 1724334000000,
101
+ "depth": 0,
102
+ "current": false,
103
+ "onCurrentPath": true,
104
+ "turns": [
105
+ { "turn": 1, "text": "Hello", "time": 1724334001000 },
106
+ { "turn": 2, "text": "Tell me more", "time": 1724334005000 }
107
+ ]
108
+ },
109
+ {
110
+ "sessionId": "session-b",
111
+ "parentSessionId": "session-a",
112
+ "createdAt": 1724334020000,
113
+ "depth": 1,
114
+ "current": true,
115
+ "onCurrentPath": true,
116
+ "operation": "edit",
117
+ "targetTurn": 1,
118
+ "before": "Hello",
119
+ "after": "Hello world",
120
+ "turns": [
121
+ { "turn": 1, "text": "Hello world", "time": 1724334021000 },
122
+ { "turn": 2, "text": "What is next?", "time": 1724334025000 }
123
+ ]
124
+ }
125
+ ]
126
+ }
127
+ ```
128
+
129
+ ### `POST /message-tree`
130
+ Performs branch creation or reactivation.
131
+
132
+ - **`edit`**: Rewinds to before the specified user turn, creates a new branched session, appends a durable `message-tree/version` marker, and submits the replacement prompt.
133
+ - **`retry`**: Rewinds to before the target turn, creates a child session, and replays the original user prompt.
134
+ - **`activate`**: Unarchives an archived version session via the host registry queue so the client can navigate to it.
135
+
136
+ ---
137
+
138
+ ## 4. Performance & In-Memory Caching
139
+
140
+ 1. **Host-Side Parsed Session Cache (`sessionParsedCache`)**:
141
+ - Parses turn boundaries (`extractTurns`) and version headers once per immutable event sequence.
142
+ - Bounded to 500 entries per plugin context. Live keys use session identity
143
+ and event count; unchanged modern logs do not need a new snapshot.
144
+ - Cold logs are read before comparing their event count. Creation timestamps
145
+ cannot invalidate append-only history and must not be used as revisions.
146
+
147
+ 2. **Client-Side Family SWR Store (`treeStore`)**:
148
+ - Maps every non-deleted branch in a tree to the shared family structure upon fetch.
149
+ - Switching between sibling branches (`‹ n/m ›` or Versions view) is 100% synchronous (0ms lag, zero indicator flicker).
150
+ - Uses monotonic request timestamps to prevent race-condition overwrites from out-of-order responses.
151
+ - Optimistically seeds newly created edit/retry branches before navigation.
152
+
153
+ ---
154
+
155
+ ## 5. Security and Error Resilience
156
+
157
+ - **Ignorable Event Envelope**: `ignorable: true` ensures foreign event markers do not crash the core DSH log parser.
158
+ - **Fail-Safe Mutation Recovery**: Transaction reversals (`child.dispose()`) on failures prevent dangling session artifacts.
159
+ - **Memory Bounded Stores**: LRU bounds (500 sessions) prevent unbounded memory growth in long-running processes.
160
+
161
+ ## 6. Naming & Namespaces
162
+
163
+ - **NPM Package**: `dsh-plugin-message-edit`
164
+ - **Cordis Service Name**: `message-tree`
165
+ - **HTTP Path**: `/message-tree`
166
+ - **Durable Event Type**: `message-tree/version`
167
+
168
+ > The package uses `dsh-plugin-message-edit` for discovery, but retains `message-tree` in routes, cordis IDs, and event types to prevent collisions with prior third-party plugins (such as `dsh-message-edit`) and ensure seamless side-by-side operation.