@xbghc/warden 0.7.0 → 0.8.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/README.md CHANGED
@@ -6,6 +6,7 @@ with line comments you can copy back to the agent as a prompt.
6
6
  - Runs as a single local process per repository (`127.0.0.1` only, no auth, no database).
7
7
  - Diff sources: working tree, staged, working tree vs HEAD, a branch since it forked off its base (commits and
8
8
  uncommitted work together), any commit, any two refs, and git worktrees.
9
+ - Worktrees are made and taken down from the page, one per agent branch, with the path ready to paste.
9
10
  - Side-by-side **Unstaged** and **Staged** file lists: staged means reviewed. Stage from the UI by dragging
10
11
  over the lines you have read (or a hunk, or a file), and unstage the same way from the Staged view.
11
12
  - GitHub-style unified / side-by-side diff with syntax highlighting, collapsed file tree, lazy per-file loading, context expansion, virtual scrolling.
@@ -60,7 +61,8 @@ Several instances on the same repository can run at the same time.
60
61
  | Worktree, everything since base | `worktree:<path>:base:<ref>` | same, run inside the worktree |
61
62
 
62
63
  Refs accept anything git can resolve (`main`, `v1.2`, `HEAD~3`, a sha). `@` is `HEAD`.
63
- Worktrees are discovered with `git worktree list` and share the review state of the main repository.
64
+ Worktrees are discovered with `git worktree list` (and made in the *Worktrees* tab, see below) and
65
+ share the review state of the main repository.
64
66
  One whose directory is gone (git lists it as *prunable*) is not offered, and a remembered target
65
67
  inside a removed worktree falls back to the working tree on the next load. The comments and viewed
66
68
  flags kept under that worktree's key stay in the state file and come back if a worktree is created
@@ -92,6 +94,28 @@ pool of comments and a commit never deletes them: the round under review is not
92
94
  commits, so a comment whose lines changed stays *orphaned*, snippet and all, until you have checked
93
95
  the fix and delete or re-attach it.
94
96
 
97
+ ## Worktrees
98
+
99
+ Agents do their best work each in a worktree of its own, and the *Worktrees* tab in the top bar is
100
+ where those are made and taken down without a trip to the terminal:
101
+
102
+ - *新建 worktree* takes a branch and a base. A name that is not a branch yet becomes one from the
103
+ base (`main` or `master` unless you say otherwise; any ref goes) — `git worktree add -b <branch>
104
+ <path> <base>`; an existing branch is checked out as it is, unless another worktree already has it.
105
+ The path is suggested as a sibling of the main worktree named `<repo>-<branch>` (slashes become
106
+ dashes) and can be edited, within limits: it has to sit under the main worktree's parent directory,
107
+ outside every existing worktree, and be new or an empty directory.
108
+ - Each row names the checkout, its branch, and whether it is clean or how many paths `git status`
109
+ reports. *查看* switches the review to it (the kind of target carries over, as with the selector
110
+ in the top bar), *复制路径* is for the agent's prompt.
111
+ - *删除* runs `git worktree remove`, never with `--force` on its own: a worktree with uncommitted
112
+ changes is not removed until you confirm in the row, since those changes go with it, and whatever
113
+ else git refuses without `--force` is put to you the same way. With *一并删除已合并的分支* ticked
114
+ the branch goes too, by `git branch -d`: one that is not merged is kept and the toast says why. The
115
+ comments and viewed flags kept under the worktree's key stay in the state file, as before.
116
+ - A worktree whose directory was deleted behind git's back is listed struck through; *清理* drops that
117
+ one entry (`git worktree remove` handles it; nothing is pruned wholesale).
118
+
95
119
  ## Keyboard
96
120
 
97
121
  | Key | Action |
@@ -280,18 +304,24 @@ move into the matching scope the first time the file is read.
280
304
  Single user, local only. The server binds to `127.0.0.1` and executes git only through
281
305
  `execFile('git', [...])`. Reads go through an argument whitelist (`rev-parse`, `diff`, `show`, `log`,
282
306
  `worktree list`, `ls-files`, `status`, `merge-base`, `rev-list`) that refuses option-looking refs and any write-capable
283
- flag; requests that would need anything else get HTTP 400. The one write is `POST /api/targets/:key/stage`,
284
- which runs `git apply --cached` (with `--reverse` for the Staged view) on a patch the server itself builds
285
- from the diff it just produced — the patch is never taken from the request, only the line indices are,
286
- and they are checked against the diff's hash first. Nothing writes to the working tree, HEAD or the
287
- refs, and the review state lives outside the repository.
307
+ flag; requests that would need anything else get HTTP 400. The writes are few and each composes its
308
+ own arguments. `POST /api/targets/:key/stage` runs `git apply --cached` (with `--reverse` for the
309
+ Staged view) on a patch the server itself builds from the diff it just produced — the patch is never
310
+ taken from the request, only the line indices are, and they are checked against the diff's hash
311
+ first. `POST /api/worktrees` and `POST /api/worktrees/remove` run `git worktree add`, `git worktree
312
+ remove` and `git branch -d` with a branch name git has validated, a ref that resolves, and a
313
+ path confined to the main worktree's parent directory. Nothing writes to the working tree or HEAD of
314
+ an existing checkout; refs change only when a worktree is made (its new branch) or removed (its merged
315
+ branch, on request), and the review state lives outside the repository. A mutating request the
316
+ browser labels as coming from another site (`Sec-Fetch-Site: cross-site`) is refused with 403, so a
317
+ page from elsewhere cannot drive the server through the browser it is open in.
288
318
 
289
319
  ## Development
290
320
 
291
321
  ```sh
292
322
  pnpm install
293
323
  pnpm dev # API server on :4100 (tsx watch) + Vite dev server on :5173 with /api proxied
294
- pnpm test # vitest: diff parser, staging patches, anchoring, comment scopes, watcher, todos, export, state, HTTP API
324
+ pnpm test # vitest: diff parser, staging patches, anchoring, comment scopes, watcher, todos, worktrees, export, state, HTTP API
295
325
  pnpm typecheck
296
326
  pnpm build # dist/web (Vite) + dist/cli.js (tsup, zero runtime dependencies)
297
327
  node dist/cli.js path/to/repo
@@ -302,7 +332,7 @@ Layout:
302
332
  ```
303
333
  bin/cli.ts argument parsing, start server, open browser
304
334
  packages/shared types + target key / comment scope helpers (bundled into both sides)
305
- packages/server Hono API, git wrapper, diff parser, staging patches, targets, anchoring, watcher, state, export, nvim
335
+ packages/server Hono API, git wrapper, diff parser, staging patches, targets, worktrees, anchoring, watcher, state, export, nvim
306
336
  packages/web React + Vite UI (shiki highlighting, @tanstack/react-virtual, react-markdown)
307
337
  test/ API integration tests on a generated git repository
308
338
  ```