dsh-plugin-worktrees 0.1.1 → 0.1.2

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 CHANGED
@@ -5,6 +5,48 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.2] - 2026-08-27
9
+
10
+ Fixes for the two load-failure issues reported against 0.1.1. **Upgrade is
11
+ required for npm-based installs** — 0.1.x cannot load at all from an
12
+ `dsh plugin add dsh-plugin-worktrees` install.
13
+
14
+ ### Fixed
15
+
16
+ - **npm installs: plugin tree failed to load with `ERR_MODULE_NOT_FOUND`
17
+ (issue #1).** The patch entry in `cordis.patch.yml` said `name:
18
+ dsh-worktrees` (the repo name) while the npm package is
19
+ `dsh-plugin-worktrees`; the cordis loader imports the entry's `name` as a
20
+ module specifier against the profile's node_modules, so every npm-based
21
+ install died. The patch `name`, `package.json` name, and the module's
22
+ `export const name` are now identical (family convention), and
23
+ `test/cordis-patch.test.js` pins the invariant so the drift cannot
24
+ silently return.
25
+ - **`config:` parsing to null rejected by zod strict (issue #2).** A patch
26
+ `config:` key holding only comments parses as YAML `null`;
27
+ `validateConfig` now treats `null`/`undefined` as "no configuration" and
28
+ applies defaults instead of failing with `(root): Expected object,
29
+ received null`. The shipped patch uses an explicit `config: {}`. Other
30
+ non-object shapes (e.g. an array) still fail loudly with a precise root
31
+ message.
32
+ - **Source-tree (tsx) launcher: dual-instance self-check misfired fatally
33
+ (issue #2).** Under `pnpm dsh web` the harness resolves `dsh-tools` to its
34
+ src build while the plugin gets the lib build — two module instances, two
35
+ `TOOL_RUNTIME_SCHEDULER` Symbols — and `assertSingleDshToolsInstance`'s
36
+ fatal branch killed the boot even though the plugin works fine (its tools
37
+ only use the public `ctx.tools.register` API and never touch the Symbol).
38
+ The check is now an advisory warning naming the `setup:peer` escape hatch;
39
+ `npm run setup:peer` remains the fix for a genuine second copy whose tool
40
+ calls do fail with `Cannot read properties of undefined (reading
41
+ 'prepare')`.
42
+
43
+ ### Tests
44
+
45
+ - 295 → 310: new `test/cordis-patch.test.js` (patch/name/config shape
46
+ guard), null-config and missing-config boot coverage, array-config
47
+ failure coverage, and the softened self-check branches re-pinned (Symbol
48
+ split now expects warn + full six-tool registration instead of a throw).
49
+
8
50
  ## [0.1.1] - 2026-08-18
9
51
 
10
52
  First release through the npm trusted-publishing pipeline (OIDC, tag
package/README.md CHANGED
@@ -44,8 +44,17 @@ dsh --profile web
44
44
  **Expected result:** a new session exposes `worktree_create`, `worktree_list`,
45
45
  `worktree_status`, `worktree_merge`, `worktree_queue`, `worktree_cleanup`.
46
46
 
47
+ > **Both launchers work (0.1.2).** The dual-instance check that 0.1.x turned
48
+ > into a hard failure is now an advisory warning: under the source-tree (tsx)
49
+ > launcher the harness loads the `src` build of `dsh-tools` while the plugin
50
+ > gets the `lib` build, which used to kill the boot with a false positive.
51
+ > This plugin only uses the public `ctx.tools.register` API, so the two
52
+ > copies coexist safely; the warning points at `setup:peer` for the rare case
53
+ > where tool calls DO fail with `Cannot read properties of undefined
54
+ > (reading 'prepare')`.
55
+
47
56
  > **Local checkout instead of npm?** Run `npm install && npm run setup:peer`
48
- > inside the repo first (avoids a second copy of `dsh-tools`, which crashes
57
+ > inside the repo first (avoids a second copy of `dsh-tools`, which can crash
49
58
  > every tool call), then `dsh plugin --profile web add "$(pwd)"`.
50
59
 
51
60
  > **Want agents to work inside the worktrees?** The stock harness silently
@@ -163,8 +172,10 @@ row in your profile's `cordis.patch.yml`; unknown keys fail loudly at startup.
163
172
  integration branch; `worktree_queue(action: "list")`, then `resolve` or
164
173
  `retry` it.
165
174
  - **Every tool call dies with `Cannot read properties of undefined
166
- (reading 'prepare')`** — local checkout without `npm run setup:peer`;
167
- re-run it after `npm install` here or a dsh upgrade.
175
+ (reading 'prepare')`** — a genuine second `dsh-tools` copy (typically a
176
+ local checkout without `npm run setup:peer`); re-run it after `npm
177
+ install` here or a dsh upgrade. A startup *warning* alone is expected and
178
+ harmless — see the note under Install.
168
179
 
169
180
  ## Development
170
181
 
package/README.zh.md CHANGED
@@ -29,7 +29,9 @@ dsh --profile web
29
29
 
30
30
  **预期结果:** 新会话里出现 `worktree_create`、`worktree_list`、`worktree_status`、`worktree_merge`、`worktree_queue`、`worktree_cleanup` 六个工具。
31
31
 
32
- > **用本地检出而不是 npm?** 先在仓库里跑 `npm install && npm run setup:peer`(避免出现第二份 dsh-tools,否则每次工具调用都会崩),再 `dsh plugin --profile web add "$(pwd)"`。
32
+ > **两种启动方式都支持(0.1.2 起)。** 0.1.x 曾把 dsh-tools 双实例检查做成硬失败,现在是建议性告警:源码树(tsx)启动器下宿主加载 dsh-tools 的 `src` 构建、插件拿到 `lib` 构建,旧版会被这个假阳性直接卡死启动。本插件只用公开的 `ctx.tools.register` API,两份拷贝可以安全共存;告警里指明的 `setup:peer` 只在工具调用真的报 `Cannot read properties of undefined (reading 'prepare')` 时才需要跑。
33
+
34
+ > **用本地检出而不是 npm?** 先在仓库里跑 `npm install && npm run setup:peer`(避免出现第二份 dsh-tools,否则每次工具调用都可能崩),再 `dsh plugin --profile web add "$(pwd)"`。
33
35
 
34
36
  > **想让 agent 直接在 worktree 里干活?** 官方宿主会静默丢弃子代理的 `cwd`。安装
35
37
  > [dsh-plugin-subagents](https://github.com/Luck9Star/dsh-plugin-subagents)
@@ -122,7 +124,7 @@ worktree_cleanup({ worktree_id: id1 }) // 移除 worktree 和分
122
124
  - **一个仓库的合并只走一个 dsh 会话。** 队列是进程内的;不支持两个宿主并发合并同一仓库。
123
125
  - **`cwd` 被忽略了?** 官方宿主会丢弃它 —— 装 dsh-plugin-subagents 并跑它的 `patches/install.sh`。
124
126
  - **`active_job_exists` 报错** —— 更早的一个冲突作业占着集成分支;`worktree_queue(action: "list")`,然后 `resolve` 或 `retry` 它。
125
- - **每次工具调用都报 `Cannot read properties of undefined (reading 'prepare')`** —— 本地检出没跑 `npm run setup:peer`;在本仓库 `npm install` 后、或 dsh 升级后重跑。
127
+ - **每次工具调用都报 `Cannot read properties of undefined (reading 'prepare')`** —— 真正的第二份 dsh-tools 拷贝(典型:本地检出没跑 `npm run setup:peer`);在本仓库 `npm install` 后、或 dsh 升级后重跑。仅启动时出现一条*告警*是预期且无害的 —— 见「安装」下的说明。
126
128
 
127
129
  ## 开发
128
130
 
package/cordis.patch.yml CHANGED
@@ -1,4 +1,4 @@
1
- # dsh-worktrees bundle patch (T11, DESIGN §8.3).
1
+ # dsh-plugin-worktrees bundle patch (T11, DESIGN §8.3).
2
2
  #
3
3
  # 用途:把 dsh-worktrees 插件实例挂进 profile 的层序。本插件是纯 tool
4
4
  # 插件——六件工具(worktree_create / list / status / merge / queue /
@@ -7,24 +7,31 @@
7
7
  # 零宿主补丁(本仓库没有 patches/ 目录)。形态对齐 dsh-ssh 的单
8
8
  # insert 写法。
9
9
  #
10
- # 安装方式:`dsh plugin --profile <name> add dsh-worktrees`(或 add
10
+ # 安装方式:`dsh plugin --profile <name> add dsh-plugin-worktrees`(或 add
11
11
  # <本地路径>)——reconcile 解析 package.json 的 dsh.bundle.patch 字段,
12
- # 自动把本 patch 层追加到 bundles 尾部,insert 行随即生效。之后在本
13
- # 仓库跑 `npm run setup:peer`(dsh-tools 单实例 symlink,peer 纪律见
14
- # README),再重启 dsh 开新会话。要覆盖配置,在 profile 层同 id 行
15
- # config(profile 层覆盖 bundle 层),键表见 README「配置」。
12
+ # 自动把本 patch 层追加到 bundles 尾部,insert 行随即生效。
13
+ #
14
+ # 两条曾经踩过的坑(0.1.2 修复,勿回退):
15
+ # 1. name 必须等于 npm 包名(package.json 的 name)——loader 拿这个
16
+ # 字段作为 import specifier 去 profile 的 node_modules 解析;写成
17
+ # 仓库名 dsh-worktrees 会让整个插件树 ERR_MODULE_NOT_FOUND(issue #1)。
18
+ # test/cordis-patch.test.js 钉死 patch name === package.json name。
19
+ # 2. config 必须是显式的 `{}` —— 只跟注释的裸 `config:` 键会被 YAML
20
+ # 解析成 null,zod strict 拒收(issue #2)。要覆盖配置,请在
21
+ # profile 层的同 id 行写 config(profile 层覆盖 bundle 层),键表见
22
+ # README「配置」:
23
+ # maxWorktrees: 16 # 非终态 worktree 全局上限(跨 repo 计数)
24
+ # allowedRoots: ["~/Documents/dev/Agents"] # repo 门禁额外放行的根(realpath 子树判定)
25
+ # 其余键:worktreeRoot / statePath / defaultBaseRef / gitTimeoutMs /
26
+ # mergeTimeoutMs / requireWorkspaceRegistration / autoCollect /
27
+ # retainJobHistory / register 六开关 —— 逐键说明见 README。
16
28
  #
17
29
  # 互斥:无。新名字工具不与官方行或同族插件冲突,可与 dsh-plugin-
18
30
  # subagents 等任意 bundle 并存(正交组合正是本插件的卖点)。
19
31
 
20
32
  - insert:
21
33
  # 本行即 host-plane Cordis 插件实例;六件 worktree_* 工具由它注册。
34
+ # config 显式空表 = lib/config.js 的 zod strict 全默认。
22
35
  - id: worktrees
23
- name: dsh-worktrees
24
- config:
25
- # —— 全部键省略即走 lib/config.js 的 zod strict 默认;示例(注释):
26
- # maxWorktrees: 16 # 非终态 worktree 全局上限(跨 repo 计数)
27
- # allowedRoots: ["~/Documents/dev/Agents"] # repo 门禁额外放行的根(realpath 子树判定)
28
- # 其余键:worktreeRoot / statePath / defaultBaseRef / gitTimeoutMs /
29
- # mergeTimeoutMs / requireWorkspaceRegistration / autoCollect /
30
- # retainJobHistory / register 六开关 —— 逐键说明见 README。
36
+ name: dsh-plugin-worktrees
37
+ config: {}
package/docs/DESIGN.md CHANGED
@@ -628,22 +628,26 @@ dsh-worktrees/
628
628
  ### 8.3 cordis.patch.yml(形态)
629
629
 
630
630
  ```yaml
631
- # dsh-worktrees bundle patch — 单行 insert(新名字工具在全局层天然可见,
631
+ # dsh-plugin-worktrees bundle patch — 单行 insert(新名字工具在全局层天然可见,
632
632
  # 无需 disable 任何官方行;对齐 dsh-ssh 的单 insert 形态)。
633
633
  - insert:
634
634
  - id: worktrees
635
- name: dsh-worktrees
636
- config:
637
- # 全部键省略走 lib/config.js 默认;示例:
638
- # maxWorktrees: 16
639
- # allowedRoots: ["~/Documents/dev/Agents"]
635
+ name: dsh-plugin-worktrees
636
+ config: {}
640
637
  ```
641
638
 
642
- insert 行写法学自:dsh-ssh `cordis.patch.yml`(单 insert 双面插件)与 dsh-web-ui-all 聚合 patch(`- insert:` + `- id:` + `name:` 两键缩进形态)。`dsh plugin --profile <name> add dsh-worktrees` 后 reconcile 自动追加层序(分析 §4:解析 `dsh.bundle.patch` 依赖按序追加 bundles 尾部)。
639
+ insert 行写法学自:dsh-ssh `cordis.patch.yml`(单 insert 双面插件)与 dsh-web-ui-all 聚合 patch(`- insert:` + `- id:` + `name:` 两键缩进形态)。`dsh plugin --profile <name> add dsh-plugin-worktrees` 后 reconcile 自动追加层序(分析 §4:解析 `dsh.bundle.patch` 依赖按序追加 bundles 尾部)。
643
640
 
644
- ### 8.4 peer 双实例防御(C6)
641
+ **0.1.2 修订(issue #1 + #2,两条都是这个文件的 drift,已由 `test/cordis-patch.test.js` 钉死):**
645
642
 
646
- `@deepseek-ai/dsh-tools` 声明 peer;README 安装步骤含 `npm run setup:peer`(symlink live harness 根,脚本照搬 subagents `scripts/link-harness-dsh-tools.sh` 模式);`apply()` 开头做 subagents 同款 `assertSingleDshToolsInstance` 自检(`TOOL_RUNTIME_SCHEDULER` Symbol 探测,失败即 logger.fatal + throw —— 分析 §4-C6 的既证失效面)。
643
+ 1. **`name` 必须等于 npm 包名**(package.json `name`)。cordis loader entry `name` 作为 import specifier 去 profile 的 node_modules 解析(`cordis-plugin-loader` `_init()` `tree.import(this.options.name, …)`)——0.1.x 写成仓库名 `dsh-worktrees` 而 npm 发的是 `dsh-plugin-worktrees`,所有 npm 安装路径死于 `ERR_MODULE_NOT_FOUND`。家族惯例(dsh-plugin-subagents)三名一致:package name === patch name === 模块导出 `export const name`。
644
+ 2. **`config` 必须显式写 `{}`**。只跟注释的裸 `config:` 键被 YAML 解析成 `null`,zod strict 报 `(root): Expected object, received null`(宿主把 entry config 原样传进 apply())。注释示例移到文件头注释,行内只留空表;`lib/config.js` 同时对 null 走默认值兜底(双保险)。
645
+
646
+ ### 8.4 peer 双实例防御(C6)—— 0.1.2 起为建议性告警
647
+
648
+ `@deepseek-ai/dsh-tools` 声明 peer;README 安装步骤含 `npm run setup:peer`(symlink 到 live harness 根,脚本照搬 subagents `scripts/link-harness-dsh-tools.sh` 模式);`apply()` 开头保留 subagents 同款 `assertSingleDshToolsInstance` 探测(`TOOL_RUNTIME_SCHEDULER` Symbol)。
649
+
650
+ **0.1.2 修订(issue #2):分支 2(Symbol 缺失 + ToolRuntime 形状 ⇒ fatal + throw)软化为 warn + 继续注册。** 原设计照搬 dsh-plugin-subagents,但在源码树(tsx)启动器下必然误杀:宿主经 tsconfig paths 把 `@deepseek-ai/dsh-tools` 解析到 **src 构建**,插件经普通 ESM 从 profile node_modules 解析到 **lib 构建** —— 两个物理实例、两个 Symbol,`setup:peer` 的 symlink 只能指向 lib 构建、无法统一。软化是安全的:本插件六件工具全部经公开 `ctx.tools.register` API 注册、用 `defineTool` 纯定义对象,工具体从不触碰 scheduler Symbol(该 Symbol 由 dsh-agent-loop 消费、且永远作用于宿主自己的 dsh-tools 实例)——双实例对本插件无功能影响。告警文案保留 `setup:peer` 提示,覆盖真正双实例(工具调用报 `Cannot read properties of undefined (reading 'prepare')`)的场景。
647
651
 
648
652
  ---
649
653
 
package/lib/config.js CHANGED
@@ -101,6 +101,15 @@ export const SCALAR_DEFAULTS = Object.freeze({
101
101
  * clear message)
102
102
  */
103
103
  export function validateConfig(config = {}) {
104
+ // A comment-only `config:` key in a host YAML layer parses as null (issue
105
+ // #2) — an absent configuration, not an invalid one, so it takes the same
106
+ // defaults path as an omitted key. Any other non-object still fails loud.
107
+ if (config === null || config === undefined) config = {}
108
+ if (typeof config !== 'object' || Array.isArray(config)) {
109
+ throw new Error(
110
+ `dsh-worktrees: invalid config — (root): expected an object, got ${Array.isArray(config) ? 'array' : typeof config}`,
111
+ )
112
+ }
104
113
  const result = pluginConfigSchema.safeParse(config)
105
114
  if (!result.success) {
106
115
  const issues = result.error.issues.map(
package/lib/index.js CHANGED
@@ -9,14 +9,15 @@
9
9
  * apply() order (DESIGN §3 diagram + §7.3 "before tool registration"):
10
10
  *
11
11
  * a. validateConfig (lib/config.js zod strict; unknown keys fail loud);
12
- * b. assertSingleDshToolsInstance — the @deepseek-ai/dsh-tools dual-
13
- * instance self-check (§8.4, pattern carried over verbatim from
14
- * dsh-plugin-subagents lib/index.js): the host ToolRuntime carries its
15
- * scheduler under the dsh-tools module-level TOOL_RUNTIME_SCHEDULER
16
- * Symbol; a second physical copy of the package makes
17
- * `ctx.tools[Symbol]` undefined and every tool call dies with
18
- * "Cannot read properties of undefined (reading 'prepare')"fatal at
19
- * apply time, with the setup:peer re-link hint;
12
+ * b. assertSingleDshToolsInstance — the @deepseek-ai/dsh-tools
13
+ * dual-instance ADVISORY probe (§8.4, softened at 0.1.2 per issue #2):
14
+ * the host ToolRuntime carries its scheduler under the dsh-tools
15
+ * module-level TOOL_RUNTIME_SCHEDULER Symbol; when that Symbol is not
16
+ * visible on ctx.tools (a second physical copy of the package, or the
17
+ * src/lib split under the source-tree tsx launcher) the probe warns
18
+ * with the setup:peer hint and lets the boot continue this plugin
19
+ * only uses the public ctx.tools.register API, so a split instance
20
+ * cannot break its tool calls (see the function comment for history);
20
21
  * c. createGitPort (timeoutMs = gitTimeoutMs) + createStateStore +
21
22
  * store.load() (a corrupt state file aborts the boot loudly);
22
23
  * d. reconcile — the crash reconciliation (§7.3), BEFORE any tool is
@@ -59,7 +60,13 @@ import { registerWorktreeMergeTool } from './tools/worktree-merge.js'
59
60
  import { registerWorktreeQueueTool } from './tools/worktree-queue.js'
60
61
  import { registerWorktreeCleanupTool } from './tools/worktree-cleanup.js'
61
62
 
62
- export const name = 'dsh-worktrees'
63
+ // Plugin identity must equal the npm package name (package.json "name"):
64
+ // the cordis loader resolves the patch entry's `name` as an import specifier
65
+ // against the profile's node_modules, and the family convention (dsh-plugin-
66
+ // subagents) keeps package name === patch name === module export name. The
67
+ // 0.1.x drift (patch said `dsh-worktrees`, npm said `dsh-plugin-worktrees`)
68
+ // broke every npm-based install with ERR_MODULE_NOT_FOUND (issue #1).
69
+ export const name = 'dsh-plugin-worktrees'
63
70
 
64
71
  // workspaceRegistry is used through OPTIONAL probing (§8.2 peer-face
65
72
  // minimisation: headless hosts without a workspace registry still boot) —
@@ -81,38 +88,42 @@ function realPathBestEffort(target) {
81
88
  }
82
89
 
83
90
  /**
84
- * dsh-tools dual-instance self-check (§8.4; the verbatim probe pattern from
85
- * dsh-plugin-subagents lib/index.js):
91
+ * dsh-tools dual-instance advisory probe (§8.4; softened at 0.1.2, issue #2).
92
+ *
93
+ * History: this used to be a fatal check modelled on dsh-plugin-subagents —
94
+ * Symbol absent + ToolRuntime shape ⇒ throw. That misfires under the
95
+ * source-tree (tsx) harness launcher: the harness resolves dsh-tools to its
96
+ * src build (via tsconfig path mappings) while the plugin, loaded from the
97
+ * profile's node_modules by plain ESM, gets the lib build — two PHYSICAL
98
+ * module instances, two Symbols, and `npm run setup:peer` cannot unify them
99
+ * (its symlink points at the lib build only). The fatal then made the plugin
100
+ * outright unusable there.
101
+ *
102
+ * Why softening is safe: every tool this plugin registers goes through the
103
+ * PUBLIC `ctx.tools.register` API and plain `defineTool` definition objects.
104
+ * The tool bodies never touch the scheduler Symbol — that Symbol is consumed
105
+ * by dsh-agent-loop when dispatching the HOST's tools, always against the
106
+ * host's own dsh-tools instance. A second dsh-tools copy only matters if
107
+ * plugin code reached for cross-instance identity (ours never does), so a
108
+ * missing Symbol degrades to a warning that names the diagnostic rule of
109
+ * thumb, never a load failure.
86
110
  *
87
111
  * 1. `ctx.tools[TOOL_RUNTIME_SCHEDULER] !== undefined` → same physical
88
- * module — healthy;
89
- * 2. Symbol absent but ctx.tools looks like a real ToolRuntime
90
- * (view + schemas) → a true second copy: logger.fatal + throw (apply
91
- * failing beats every tool call dying after load), pointing at the
92
- * peer re-link (npm run setup:peer);
93
- * 3. anything else (fake ctx / an unseen host shape) → cannot reliably
94
- * judge; warn only. Tests and non-standard hosts must not be killed by
95
- * a false positive.
112
+ * module — healthy, silent;
113
+ * 2. Symbol absent (fake ctx, src/lib split, or a true second copy) →
114
+ * warn only, keep booting.
96
115
  */
97
116
  function assertSingleDshToolsInstance(ctx) {
98
117
  const tools = ctx && ctx.tools
99
118
  if (!tools || typeof tools.register !== 'function') return
100
119
  if (tools[TOOL_RUNTIME_SCHEDULER] !== undefined) return // same physical module — healthy
101
- const looksLikeToolRuntime =
102
- typeof tools.view === 'function' && typeof tools.schemas === 'function'
103
- if (looksLikeToolRuntime) {
104
- const detail =
105
- 'dsh-worktrees: detected a second @deepseek-ai/dsh-tools module instance — '
106
- + "every tool call from this plugin would die with \"Cannot read properties of undefined (reading 'prepare')\". "
107
- + 'Run npm run setup:peer (scripts/link-harness-dsh-tools.sh) in the dsh-worktrees package '
108
- + 'so its dsh-tools copy resolves to the live harness root, then restart dsh.'
109
- if (ctx.logger && typeof ctx.logger.fatal === 'function') ctx.logger.fatal(detail)
110
- throw new Error(detail)
111
- }
112
120
  if (ctx.logger && typeof ctx.logger.warn === 'function') {
113
121
  ctx.logger.warn(
114
- 'dsh-worktrees: could not reliably verify the @deepseek-ai/dsh-tools single-instance invariant '
115
- + 'from this ctx (no scheduler symbol, no ToolRuntime shape) run npm run setup:peer to check the dedupe link',
122
+ 'dsh-worktrees: the @deepseek-ai/dsh-tools scheduler Symbol is not visible on ctx.tools '
123
+ + '(a second dsh-tools copy, or the src/lib split under the source-tree tsx launcher). '
124
+ + "This plugin only uses the public ctx.tools.register API, so tool calls are unaffected; "
125
+ + 'if you DO see "Cannot read properties of undefined (reading \'prepare\')", run '
126
+ + 'npm run setup:peer (scripts/link-harness-dsh-tools.sh) in this package and restart dsh.',
116
127
  )
117
128
  }
118
129
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-worktrees",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "git worktree parallel write isolation + serial merge integration plugin for the DeepSeek Harness",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",