dsh-worktree-switch 0.5.0 → 0.5.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # `dsh-worktree-switch`
2
2
 
3
- 在新会话屏幕的输入框工具行里放一个 **Worktree 开关**。默认打开(按项目记忆):
3
+ 在新会话屏幕的输入框工具行里放一个 **Worktree 开关**。默认打开(按项目的**隔离默认**):
4
4
  打开时立刻在 `<项目根>/.dsh/worktrees/<名字>` 建一份仓库副本,并把这条会话的工作
5
5
  目录切进去;在发出第一条消息之前再关掉,会话会被切回项目目录,开关自己刚建的干净
6
6
  副本也一并删掉——关掉就是撤销这次隔离。副本不会自动消失、也不会自动合并,用户可以
@@ -12,21 +12,27 @@
12
12
  [ADR-0005](../../docs/adr/0005-worktree-base-ref-deviates-from-claude-code.md)。
13
13
 
14
14
  「关掉」现在只做**撤销**,不叫回收:只有开关为这条会话创建、没有产生提交、也没有未提交
15
- 改动的副本,才会在离开时被删掉(检出与分支一起);有内容的、归属不明的副本一律保留,并
16
- 在界面上说明原因。归属记在副本自己的 Git admin dir 里,宿主重启后仍然可证;会话头部常驻
17
- `⎇ 分支名` badge,面板新增「遗留分支」分组。取舍见
15
+ 改动的副本,才会在离开时被删掉(检出与分支一起);有内容的副本保留并给一次性提示,归属
16
+ 不是这条会话的副本同样保留,但只在开关的 hover 里说明。归属记在副本自己的 Git admin dir
17
+ 里,宿主重启后仍然可证;会话头部常驻 `⎇ 分支名` badge,面板新增「遗留分支」分组。开关
18
+ 位置是会话状态、项目默认只决定新会话,见
19
+ [ADR-0007](../../docs/adr/0007-switch-position-is-session-state.md);离开即撤销的取舍见
18
20
  [ADR-0006](../../docs/adr/0006-worktree-leave-is-undo-not-reclaim.md)。
19
21
 
20
22
  ## 它做什么
21
23
 
22
24
  - **开关**(`conversation.input.left` 槽,只在空白新会话的 hero 上出现):显示本会话
23
25
  当前的副本状态——检查中 / 关闭 / 创建中 / 离开中 / 就绪(显示名字)/ 失败(显示原因 +
24
- 重试)/ 不可用(项目不是 Git 仓库)。开关位置本身记的是"这个项目的新会话要不要隔离"。
25
- - **创建**发生在开关打开的那一刻,早于第一条消息;**关闭**发生在第一条消息之前时,
26
- 会话被切回项目目录;只有开关为这条会话创建、仍在创建基点、也没有未提交改动的副本会被
27
- 撤销(检出和分支一起删)。有提交、有改动、或归属不明的副本留在池里,开关的 hover 带上
28
- 保留原因,界面顶部给一次性提示并提供「打开面板」。副本默认从创建前刚拉取到的
29
- `origin/<默认分支>` 起;
26
+ 重试)/ 不可用(项目不是 Git 仓库)。**开关位置表示这条会话在哪里运行**:会话在副本里
27
+ 时恒为开;不在副本时等于这个项目的**隔离默认**(新会话要不要隔离,按项目记忆)。项目
28
+ 默认不再决定一条已经在副本里的会话该不该搬走。会话在副本里、项目隔离默认为关时,hover
29
+ 说明「本会话在副本里运行;这个项目的新会话从源检出开始」。
30
+ - **创建**发生在开关打开的那一刻,早于第一条消息;**关闭**(拨回)把会话切回项目目录;
31
+ 只有开关为这条会话创建、仍在创建基点、也没有未提交改动的副本会被撤销(检出和分支一起
32
+ 删)。有提交或改动的副本留在池里,开关的 hover 带上保留原因,界面顶部给一次性提示并
33
+ 提供「打开面板」;归属不是本会话的副本(例如 `/new` 继承来的)同样留下,但只在 hover
34
+ 里说明,不弹提示。hover 的离开失败提示收窄成「拨回后没能离开」,只在有错误时出现。
35
+ 副本默认从创建前刚拉取到的 `origin/<默认分支>` 起;
30
36
  `baseRef: 'head'` 或远端取不到时回退为本地 `HEAD`(见「创建基点」)。副本名 = 分支名 = 池内
31
37
  目录名,形如 `quiet-harbor-3fa9`,由插件生成,短且唯一。
32
38
  - **归属记在副本里**:创建成功后,插件往该副本自己的 Git admin dir
@@ -62,12 +68,25 @@
62
68
  且只删分支。普通 feature 分支、以及仍被 checkout 的分支永远不会出现在这一组。
63
69
  - **当前副本**:面板按会话快照里当前主视图的那条会话推导「我在副本里」,给它高亮;不新增
64
70
  宿主事件。侧边栏入口在有东西要清理时显示计数。
65
- - **计数口径**:入口计数 = 遗留分支数 + 本次宿主生命周期内被保留的副本数(含删除失败后
66
- 留在磁盘上的那一份)。宿主重启后后者不可知,计数退化为只数遗留分支——这是有意说出来的
67
- 诚实下限,不是 bug。
71
+ - **计数口径**:入口计数 = 遗留分支数 + 本次宿主生命周期内被保留的副本数(有内容而保留、
72
+ 或删除失败后留在磁盘上的那一份)。归属别的会话、只在离开时留下来的副本不计入——它不是
73
+ 遗留。宿主重启后后者不可知,计数退化为只数遗留分支——这是有意说出来的诚实下限,不是
74
+ bug。
68
75
  - **会话身份不变**:会话仍然建在源项目的工作区里,起始目录不变,插件只改会话的工作
69
76
  目录(一条持久化事件,重开会话仍然生效)。
70
77
 
78
+ ## `/new` 继承的副本
79
+
80
+ `/new`(= `/clear`,由 [`dsh-new-session`](../dsh-new-session/README.md) 提供)在**原地**
81
+ 开一段新对话:新会话沿用当前会话的工作目录。会话在副本里时,新会话就继承同一份副本,
82
+ 既不会另建一份,也不会因为项目的隔离默认是关而被搬回源检出。开关跟着工作目录投影重查:
83
+ `/new` 继承、离开、宿主把会话搬回源检出,位置都会在重查后对齐事实;空白会话若因外部原因
84
+ 被搬回源检出、而隔离默认仍为开,会重新补建一份副本(只在还没发第一条消息时)。
85
+
86
+ 继承来的副本仍归**创建它的会话**所有。在新会话里拨回开关只是普通离开:会话回到源检出,
87
+ 副本留在磁盘上,不弹一次性提示,也不计入侧边栏的清理计数;hover 里那句「开关不删这份
88
+ 副本:它不是为这条会话建的」说明原因。这条跨插件前提也记在 `dsh-new-session` 的 README 里。
89
+
71
90
  ## 安装
72
91
 
73
92
  ```sh
@@ -96,9 +115,10 @@ dsh --profile web --dump-config # 应能看到 "# == dsh-worktree-switch" 和
96
115
  5. 想丢弃一份副本:点两次 Discard(第二次是确认);有未提交改动时按钮禁用并说明原因。
97
116
  遗留分支同样点两次删除;目录已丢失的副本行标「目录已丢失」,走同一套丢弃。
98
117
  6. 开关只在空白会话上出现:发第一条消息之前关掉,会把会话切回项目目录,并撤销开关刚建的
99
- 空副本;若副本里有提交或改动(或归属不明),副本保留,开关 hover 说明原因,页面顶部给
100
- 一次性提示与「打开面板」。发过消息之后开关消失,副本留在池里,由面板丢弃。拨开关同时
101
- 记住这个项目下次的默认位置。
118
+ 空副本;若副本里有提交或改动,副本保留,开关 hover 说明原因,页面顶部给一次性提示与
119
+ 「打开面板」;归属不是本会话的副本(比如从副本里 `/new` 出来的新会话)只回源检出、
120
+ 副本留在原处,不弹提示。发过消息之后开关消失,副本留在池里,由面板丢弃。拨开关同时
121
+ 记住这个项目的隔离默认。
102
122
 
103
123
  ## 配置
104
124
 
@@ -199,8 +219,14 @@ worktree,所以新旧目录的副本都会出现,可以照常丢弃。
199
219
  助手在副本里改的文件不会落到源检出的工作树里,但同一会话仍可写源项目根下的文件。
200
220
  主检出守卫只覆盖 bash 里明显指向主检出的 git 调用,是提示之外的兜底,不是权限。
201
221
  - 不自动合并、不自动回收、不支持多仓库、不识别旧插件的 `.worktree-space/` 目录。
202
- - **不追溯旧副本**:升级前留下的副本没有归属标记,离开时一律保留并提示「归属不明」,需要
203
- 在面板里手动丢弃。插件不会为了「修好这件事」而猜。
222
+ - **不追溯旧副本**:升级前留下的副本没有归属标记,离开时按 `not-owned` 保留——只在开关的
223
+ hover 里说明「开关不删这份副本:它不是为这条会话建的」,需要时在面板里手动丢弃。插件
224
+ 不会为了「修好这件事」而猜。
225
+ - **离开别人的副本不算遗留**:`/new` 继承来的、其他会话创建的副本,离开时返回
226
+ `keptReason: 'not-owned'`——会话回到源检出,副本留在磁盘上,不弹一次性提示、不计入清理
227
+ 计数,只在开关的 hover 里说明。它仍出现在面板里,由拥有它的会话或显式丢弃处理。
228
+ - **开关位置是会话状态**:项目的隔离默认只决定新会话要不要隔离;已经在副本里的会话只能由
229
+ 用户拨回离开,挂载与 `/new` 都不会搬动它。
204
230
  - **计数会退化**:「被保留的副本」只是本次宿主生命周期内的知识;宿主重启后入口计数只剩
205
231
  遗留分支可数(面板与本节都写明,避免用户以为计数一直准)。
206
232
  - **detached 副本永远不会被开关自动删掉**:只展示、只允许显式丢弃检出,且不删任何分支。
@@ -222,9 +248,9 @@ Fetch 路由(`src/host/routes.ts`),说 `client-request` / `server-response
222
248
  |---|---|---|
223
249
  | `status` | `{ sessionId }` | 解析仓库根、本会话是否已在某个 linked worktree 里、源仓库未提交改动数 |
224
250
  | `prepare` | `{ sessionId }` | 幂等;必要时经 `ctx.worktrees.create` 建副本并切目录,同名冲突自动换名重试 |
225
- | `release` | `{ sessionId }` | 把会话切回项目目录;仅在「有归属 + 仍在基点 + 工作区干净」时撤销副本(检出 + 分支),否则保留并返回 `keptReason`(`dirty` / `not-owned`)与原因;删除失败抛错,不吞成「保留」 |
251
+ | `release` | `{ sessionId }` | 把会话切回项目目录;仅在「有归属 + 仍在基点 + 工作区干净」时撤销副本(检出 + 分支),否则保留并返回 `keptReason`(`dirty` / `not-owned`)与原因。只有有内容(`dirty`)的保留,以及删除失败后抛错、副本留在磁盘上的那一次,登记为「宿主保留的副本」;`not-owned` 的离开不登记、不计入清理计数。删除失败抛错,不吞成「保留」 |
226
252
  | `scope` | `{ sessionId }` | 轻量回答「这条会话在副本里吗」:先读宿主内存里按会话记录的副本,读不到再对当前目录做一次检测;不读源仓库 status、不切目录 |
227
- | `list` | `{ path }` | 列出该仓库除主检出外的所有 linked worktree(名字/分支/路径/创建时间/改动数/prunable),外加遗留分支(提交数/最近提交/时间)与本次宿主保留的副本数 |
253
+ | `list` | `{ path }` | 列出该仓库除主检出外的所有 linked worktree(名字/分支/路径/创建时间/改动数/prunable),外加遗留分支(提交数/最近提交/时间)与本次宿主保留的副本数(有内容与删除失败的保留) |
228
254
  | `discard` | `{ path, name }` | 干净才删:`git worktree remove` + `git branch -D`;prunable 行先删分支再 prune;detached 副本只移除检出;改动非空则拒绝 |
229
255
  | `discardBranch` | `{ path, branch }` | 只删一个遗留分支:要求名字是生成格式、且不在任何 checkout 的 HEAD 上;已删过再删也算成功 |
230
256