Back to home

whitelonng

dsh-worktree

No description

Stars
0
Language
JavaScript
Created
Aug 15, 2026
Updated
Aug 15, 2026

Introduction

dsh-worktree

A DeepSeek Harness (DSH) plugin: a git worktree slot pool that lets multiple sessions (conversations) work on the same repository in parallel without stepping on each other — with a constant branch count that never grows.

The design borrows from TalkCody's worktree pool: a fixed number of slots, a fixed set of branches, reused instead of recreated.

Problems it solves

ScenarioWithout the poolWith the pool
Multiple sessions editing one repoSame working tree, silent lost updatesEach session gets a physical worktree
One branch per conversationHundreds/thousands of branches pile upBranches stay fixed at dsh-slot-0..N-1
Forgot to merge, opened a new sessionOld branch becomes history junkacquire guard refuses to clobber unmerged commits
Pool exhaustedStructured occupancy report; the model relays it and the user decides

Core mechanics

  • Fixed slots: pool size poolSize (default 3). Slot dirs live at <repo>/.worktrees/pool-{n}, branches are always <prefix>-{n} (default dsh-slot-0/1/2).
  • Reuse, not recreate: re-acquiring a free slot does reset --hard main && clean -ffd in place — much faster than worktree add on large repos.
  • Release ≠ lose work: wt_release only hands the directory back. All commits stay on the branch and can be merged later with wt_merge.
  • Double guardrail: reuse/release checks uncommitted changes (reason=dirty) and unmerged commits (reason=unmerged); both need an explicit autocommit or force.
  • Merge frees the slot: a successful wt_merge (fast-forward or merge commit) auto-releases the slot; conflicts return reason=conflict plus the file list.
  • Self-healing: wt_gc auto-releases slots whose branch is already merged, and warns about slots idle longer than maxIdleDays.
  • Concurrency-safe: atomic state-file writes plus an mkdir lock (with stale-lock takeover) — simultaneous calls from multiple sessions cannot corrupt state.

What happens when the pool is full (model protocol)

wt_acquire returns a structured result when the pool is full, and the plugin injects this protocol into every session's system prompt:

If wt_acquire returns reason=pool-full: relay each slot's occupant, idle time, and uncommitted/unmerged counts to the user verbatim, and ask "which slot should be released or merged". Only after explicit user confirmation may you call wt_release / wt_merge. Never use force on your own.

The pool being full is therefore not a dead end: the user chooses — release (work stays on the branch) or merge (work lands in main) — and the slot returns to the pool.

Installation

Via DSH plugin install (recommended)

In DSH, install the plugin from this git repository:

https://github.com/whitelonng/dsh-worktree.git

Restart the app, then in a session inside a git repository:

  1. wt_init (or wt_init(size=5) to resize)
  2. wt_acquire(label="feature-a") → get the slot path, work inside it
  3. wt_merge(slot=0) when done; wt_release(slot=0) if discarding

Manual cordis.yml registration

plugins:
  - id: dsh-worktree
    name: '@whitelonng/dsh-worktree'
    config:
      poolSize: 3
      poolDir: .worktrees
      branchPrefix: dsh-slot
      maxIdleDays: 7

Tools

ToolPurposeKey results
wt_init(workdir, size?)Initialize the pool{ ok, poolSize, poolDir }
wt_status(workdir)Whole-pool statusPer slot: occupant/idle/dirty/unmerged/merged
wt_acquire(workdir, label, autocommit?, force?)Take a slot{ ok, slot, path } or reason: pool-full / dirty / unmerged
wt_release(workdir, slot, autocommit?, force?)Hand the slot backCommits stay on the branch, mergeable anytime
wt_merge(workdir, slot, message?)Merge into mainAuto-release on success; reason=conflict + file list
wt_gc(workdir, maxIdleDays?)Self-heal{ released: [...], stale: [...] }

All tools accept workdir (defaults to the process cwd); the plugin resolves the repo root via git rev-parse.

Safety guarantees

  • Never loses committed work: release/reuse never deletes commits on a branch; only an explicit force discards (uncommitted changes; unmerged commits require force too).
  • Never silently picks a side: merge conflicts return only the file list; the user arbitrates (rerere can record resolutions for reuse).
  • Never breaks main: merge pre-checks that the main repo is clean and refuses otherwise.

DSH sandbox note

DSH's file sandbox usually only allows writes inside the session workspace, so the pool directory defaults to .worktrees/ inside the repo (it is added to .gitignore automatically by wt_init). Without sandbox restrictions, poolDir can point anywhere (e.g. ~/.talkcody/<project>).

Credits

The slot-pool design borrows from TalkCody's worktree pool (MAX_POOL_SIZE=3, fixed-branch reuse, WORKTREE_HAS_CHANGES guardrail, merge-frees-the-slot). This plugin is pure Node with zero runtime dependencies, built for DSH.

License

MIT