sync-worktrees 4.2.0 → 5.0.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.
Files changed (60) hide show
  1. package/README.md +133 -55
  2. package/dist/components/WorktreeStatusView.d.ts.map +1 -1
  3. package/dist/constants.d.ts +22 -0
  4. package/dist/constants.d.ts.map +1 -1
  5. package/dist/errors/index.d.ts +7 -0
  6. package/dist/errors/index.d.ts.map +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +2052 -448
  10. package/dist/index.js.map +4 -4
  11. package/dist/mcp/context.d.ts +1 -1
  12. package/dist/mcp/context.d.ts.map +1 -1
  13. package/dist/mcp/handlers.d.ts +0 -5
  14. package/dist/mcp/handlers.d.ts.map +1 -1
  15. package/dist/mcp/server.d.ts.map +1 -1
  16. package/dist/mcp/worktree-summary.d.ts.map +1 -1
  17. package/dist/mcp-server.js +2068 -499
  18. package/dist/mcp-server.js.map +4 -4
  19. package/dist/services/InteractiveUIService.d.ts.map +1 -1
  20. package/dist/services/clone-sync.service.d.ts +13 -2
  21. package/dist/services/clone-sync.service.d.ts.map +1 -1
  22. package/dist/services/config-loader.service.d.ts +2 -0
  23. package/dist/services/config-loader.service.d.ts.map +1 -1
  24. package/dist/services/git-maintenance.service.d.ts +44 -0
  25. package/dist/services/git-maintenance.service.d.ts.map +1 -0
  26. package/dist/services/git.service.d.ts +19 -1
  27. package/dist/services/git.service.d.ts.map +1 -1
  28. package/dist/services/removal-audit.service.d.ts +19 -0
  29. package/dist/services/removal-audit.service.d.ts.map +1 -0
  30. package/dist/services/sync-outcome.d.ts +1 -1
  31. package/dist/services/sync-outcome.d.ts.map +1 -1
  32. package/dist/services/trash-migration.service.d.ts +18 -0
  33. package/dist/services/trash-migration.service.d.ts.map +1 -0
  34. package/dist/services/trash-reaper.service.d.ts +18 -0
  35. package/dist/services/trash-reaper.service.d.ts.map +1 -0
  36. package/dist/services/trash.service.d.ts +91 -0
  37. package/dist/services/trash.service.d.ts.map +1 -0
  38. package/dist/services/worktree-metadata.service.d.ts +7 -0
  39. package/dist/services/worktree-metadata.service.d.ts.map +1 -1
  40. package/dist/services/worktree-mode-sync-runner.d.ts +11 -1
  41. package/dist/services/worktree-mode-sync-runner.d.ts.map +1 -1
  42. package/dist/services/worktree-status.service.d.ts +5 -2
  43. package/dist/services/worktree-status.service.d.ts.map +1 -1
  44. package/dist/services/worktree-sync.service.d.ts +16 -0
  45. package/dist/services/worktree-sync.service.d.ts.map +1 -1
  46. package/dist/types/index.d.ts +60 -2
  47. package/dist/types/index.d.ts.map +1 -1
  48. package/dist/types/sync-metadata.d.ts +6 -0
  49. package/dist/types/sync-metadata.d.ts.map +1 -1
  50. package/dist/utils/atomic-write.d.ts +2 -0
  51. package/dist/utils/atomic-write.d.ts.map +1 -0
  52. package/dist/utils/file-exists.d.ts +2 -0
  53. package/dist/utils/file-exists.d.ts.map +1 -1
  54. package/dist/utils/filename-timestamp.d.ts +2 -0
  55. package/dist/utils/filename-timestamp.d.ts.map +1 -0
  56. package/dist/utils/lock-path.d.ts +1 -0
  57. package/dist/utils/lock-path.d.ts.map +1 -1
  58. package/dist/utils/quarantine.d.ts +2 -0
  59. package/dist/utils/quarantine.d.ts.map +1 -0
  60. package/package.json +1 -1
package/README.md CHANGED
@@ -258,24 +258,23 @@ Open `Settings` → `AI` → `Manage MCP Servers` → `+ Add` (see [Warp MCP doc
258
258
 
259
259
  ### Available tools
260
260
 
261
- | Tool | Purpose |
262
- |------|---------|
263
- | `detect_context` | Inspect a path, resolve the bare repo, enumerate sibling worktrees, report config-driven sibling repositories and capabilities. Pass `includeAllWorktrees: true` to include every configured repo's worktrees keyed by repo name. |
264
- | `list_worktrees` | List worktrees with status label (`clean`/`dirty`/`stale`/`current`), divergence, `safeToRemove`, last sync. Without `repoName` and with a loaded config, results are grouped across all configured repos. |
265
- | `get_worktree_status` | Detailed status for one worktree (dirty files, unpushed commits, stashes, operation in progress). |
266
- | `create_worktree` | Create a worktree for a branch; optionally create the branch from `baseBranch`. Newly created branches are pushed to origin unless `push=false`. |
267
- | `remove_worktree` | Remove a worktree after safety checks; `force=true` skips validation. |
268
- | `update_worktree` | Fast-forward one worktree to match upstream. |
269
- | `sync` | Full sync cycle (fetch, create, prune, update). Requires config. Streams progress notifications. |
270
- | `initialize` | Clone the bare repo and create the main worktree. Requires config. Streams progress. |
271
- | `load_config` | Load or reload a config file at runtime. |
272
- | `set_current_repository` | Select the active repo when multiple are configured. |
261
+ | Tool | Purpose |
262
+ | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
263
+ | `detect_context` | Inspect a path, resolve the bare repo, enumerate sibling worktrees, report config-driven sibling repositories and capabilities. Pass `includeAllWorktrees: true` to include every configured repo's worktrees keyed by repo name. |
264
+ | `list_worktrees` | List worktrees with status label (`clean`/`dirty`/`stale`/`current`), divergence, `safeToRemove`, last sync. Without `repoName` and with a loaded config, results are grouped across all configured repos. |
265
+ | `get_worktree_status` | Detailed status for one worktree (dirty files, unpushed commits, stashes, operation in progress). |
266
+ | `create_worktree` | Create a worktree for a branch; optionally create the branch from `baseBranch`. Newly created branches are pushed to origin unless `push=false`. |
267
+ | `update_worktree` | Fast-forward one worktree to match upstream. |
268
+ | `sync` | Full sync cycle (fetch, create, prune, update). Requires config. Streams progress notifications. |
269
+ | `initialize` | Clone the bare repo and create the main worktree. Requires config. Streams progress. |
270
+ | `load_config` | Load or reload a config file at runtime. |
271
+ | `set_current_repository` | Select the active repo when multiple are configured. |
273
272
 
274
273
  All tools that target a single repo accept an optional `repoName`. When omitted, they use the current repository — set by auto-detect, the first entry in the config, or `set_current_repository`.
275
274
 
276
275
  ### Safety
277
276
 
278
- - `remove_worktree` refuses to delete worktrees with uncommitted changes, unpushed commits, stashes, or operations in progress (merge/rebase/cherry-pick/revert/bisect). Pass `force=true` to override.
277
+ - The MCP surface exposes no removal or trash operations an agent cannot delete a worktree or touch the trash through it. Removal happens via sync's own safety-gated pruning or manual git commands.
279
278
  - `create_worktree` rejects sanitized-path collisions (e.g. `feature/foo` vs `feature-foo` both resolving to `feature-foo/`) before touching disk.
280
279
  - Branches created by sync-worktrees use `--no-track` first, then publish with `git push -u origin <branch>`, so they do not inherit `origin/main` as their upstream.
281
280
  - Path-targeted tools verify the supplied path is a registered worktree of the selected repository.
@@ -286,19 +285,19 @@ Running `sync-worktrees` without `runOnce` drops you into an interactive termina
286
285
 
287
286
  ### Keybindings
288
287
 
289
- | Key | Action |
290
- |-----|--------|
291
- | `s` | Manually trigger sync for all repositories |
292
- | `c` | Create a new branch (wizard) |
293
- | `o` | Open a worktree in terminal or editor (wizard) |
294
- | `w` | View worktree status across repos |
295
- | `r` | Reload configuration and re-sync |
296
- | `?` / `h` | Toggle help screen |
297
- | `q` / `Esc` | Gracefully quit |
298
- | `j` / `↓` | Scroll log down one line |
299
- | `k` / `↑` | Scroll log up one line |
300
- | `gg` | Jump to top of log |
301
- | `G` | Jump to bottom (re-enables auto-scroll) |
288
+ | Key | Action |
289
+ | ----------- | ---------------------------------------------- |
290
+ | `s` | Manually trigger sync for all repositories |
291
+ | `c` | Create a new branch (wizard) |
292
+ | `o` | Open a worktree in terminal or editor (wizard) |
293
+ | `w` | View worktree status across repos |
294
+ | `r` | Reload configuration and re-sync |
295
+ | `?` / `h` | Toggle help screen |
296
+ | `q` / `Esc` | Gracefully quit |
297
+ | `j` / `↓` | Scroll log down one line |
298
+ | `k` / `↑` | Scroll log up one line |
299
+ | `gg` | Jump to top of log |
300
+ | `G` | Jump to bottom (re-enables auto-scroll) |
302
301
 
303
302
  ### Wizards
304
303
 
@@ -306,25 +305,26 @@ Running `sync-worktrees` without `runOnce` drops you into an interactive termina
306
305
  - **Branch creation wizard (`c`)** — pick a repo, pick a base branch from a live-filtered list, type the new branch name. Names are validated against Git's rules; if the desired name already exists, a numeric suffix (`-2`, `-3`, …) is suggested automatically.
307
306
  - **Worktree status view (`w`)** — flat list of every worktree across every configured repo, each tagged with status flags:
308
307
 
309
- | Flag | Meaning |
310
- |------|---------|
311
- | `✓` | Clean |
312
- | `M` | Modified / uncommitted changes |
313
- | `↑` | Unpushed commits |
314
- | `S` | Stashed changes |
315
- | `⚠` | Operation in progress (merge/rebase/cherry-pick/revert/bisect) |
316
- | `⊞` | Modified submodules |
317
- | `✗` | Upstream branch is gone |
308
+ | Flag | Meaning |
309
+ | ---- | -------------------------------------------------------------- |
310
+ | `✓` | Clean |
311
+ | `M` | Modified / uncommitted changes |
312
+ | `↑` | Unpushed commits |
313
+ | `⇡` | Commits absent from every remote but fully pushed before the remote branch was deleted (likely squash-merged) |
314
+ | `S` | Stashed changes |
315
+ | `⚠` | Operation in progress (merge/rebase/cherry-pick/revert/bisect) |
316
+ | `⊞` | Modified submodules |
317
+ | `✗` | Upstream branch is gone |
318
318
 
319
319
  Press `Enter` on an entry to expand file/commit/stash counts. The view also surfaces `.diverged/` directories preserved from past force-pushes; press `d` (with `y`/`n` confirmation) to delete one after reviewing.
320
320
 
321
321
  ### Terminal mode environment variables
322
322
 
323
- | Variable | Purpose | Default behavior |
324
- |----------|---------|------------------|
325
- | `SYNC_WORKTREES_TERMINAL` | Override the terminal launcher on any platform. Value is a command string; the tmux invocation is appended via `sh -c`. Example: `SYNC_WORKTREES_TERMINAL="alacritty -e"`. | See per-platform defaults below. |
326
- | `TERMINAL` | Linux-only fallback when `SYNC_WORKTREES_TERMINAL` is unset. Same format. | Probes `gnome-terminal`, `konsole`, `alacritty`, `kitty`, `xterm` in order. |
327
- | `EDITOR` / `VISUAL` | Editor mode launcher. | Falls back to `code`. |
323
+ | Variable | Purpose | Default behavior |
324
+ | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
325
+ | `SYNC_WORKTREES_TERMINAL` | Override the terminal launcher on any platform. Value is a command string; the tmux invocation is appended via `sh -c`. Example: `SYNC_WORKTREES_TERMINAL="alacritty -e"`. | See per-platform defaults below. |
326
+ | `TERMINAL` | Linux-only fallback when `SYNC_WORKTREES_TERMINAL` is unset. Same format. | Probes `gnome-terminal`, `konsole`, `alacritty`, `kitty`, `xterm` in order. |
327
+ | `EDITOR` / `VISUAL` | Editor mode launcher. | Falls back to `code`. |
328
328
 
329
329
  Per-platform terminal defaults (when no env override is set):
330
330
 
@@ -364,8 +364,8 @@ export default config;
364
364
  /** @satisfies {import("sync-worktrees").SyncWorktreesConfig} */
365
365
  const config = {
366
366
  defaults: {
367
- cronSchedule: "0 * * * *", // hourly
368
- branchMaxAge: "30d", // ignore stale branches
367
+ cronSchedule: "0 * * * *", // hourly
368
+ branchMaxAge: "30d", // ignore stale branches
369
369
  branchExclude: ["wip-*", "tmp-*"],
370
370
  updateExistingWorktrees: true,
371
371
  },
@@ -382,7 +382,7 @@ const config = {
382
382
  name: "frontend",
383
383
  repoUrl: "https://github.com/company/frontend.git",
384
384
  worktreeDir: "./worktrees/frontend",
385
- cronSchedule: "*/30 * * * *", // override default
385
+ cronSchedule: "*/30 * * * *", // override default
386
386
  },
387
387
  {
388
388
  name: "backend",
@@ -390,7 +390,7 @@ const config = {
390
390
  worktreeDir: "/absolute/path/backend-worktrees",
391
391
  branchMaxAge: "6m",
392
392
  branchInclude: ["feature/*", "release-*", "main"],
393
- retry: { maxAttempts: 10 }, // per-repo override
393
+ retry: { maxAttempts: 10 }, // per-repo override
394
394
  },
395
395
  ],
396
396
  };
@@ -418,9 +418,9 @@ Set `mode: "clone"` to clone one checked-out branch directly into `worktreeDir`
418
418
  }
419
419
  ```
420
420
 
421
- Clone mode keeps the normal `+refs/heads/*:refs/remotes/origin/*` fetch refspec, so `git branch -r` and `git fetch --all --prune` can see all remote branches. `branch` controls the checked-out branch that sync-worktrees fast-forwards on each sync. Omit `branch` and the remote HEAD is resolved at clone time.
421
+ Clone mode keeps only the checked-out branch materialized as a local `origin/*` ref. Branch discovery uses remote metadata, so the tool can list remote branches without downloading object closure for every branch tip. `branch` controls the checked-out branch that sync-worktrees fast-forwards on each sync. Omit `branch` and the remote HEAD is resolved at clone time.
422
422
 
423
- `depth` is valid only for clone-mode repositories and must be a positive safe integer. Shallow clones use `--no-single-branch` so all remote branch refs remain visible at the configured depth. If you later remove `depth` from the config, the next sync unshallows the existing clone with `git fetch --unshallow`.
423
+ `depth` is valid only for clone-mode repositories and must be a positive safe integer. Shallow clones use `--single-branch --no-tags`, and sync fetches keep only the tracked branch at the configured depth. If you later remove `depth` from the config, the next sync unshallows the existing clone with `git fetch --unshallow --no-tags`.
424
424
 
425
425
  Clone mode rejects `branchInclude`, `branchExclude`, `branchMaxAge`, `updateExistingWorktrees`, and `bareRepoDir` at validation time (whether set directly or inherited via `defaults`) — they have no meaning for a single-branch checkout.
426
426
 
@@ -463,6 +463,25 @@ If you set `exclude` or `!`-prefixed patterns while `mode: "cone"` is explicit,
463
463
 
464
464
  **Narrowing safety:** When a sync would narrow an existing worktree's sparse patterns (remove a previously included path), it first checks the worktree is clean. If there are uncommitted changes, unpushed commits, or in-progress operations, the sparse update is skipped with a warning.
465
465
 
466
+ ### Maintenance
467
+
468
+ Over time a repository accumulates unreachable Git objects — clone mode leaves them behind when single-branch fetches narrow refs, and both modes churn objects as branches come and go. The optional `maintenance` block runs `git gc` periodically to reclaim that storage and consolidate pack files. It applies to both modes and runs at the tail of a successful sync, under the same repository operation lock as the sync itself (so it never races a fetch, merge, or worktree operation).
469
+
470
+ ```javascript
471
+ defaults: {
472
+ maintenance: {
473
+ enabled: true, // default: true
474
+ interval: "7d", // default: "7d" — minimum time between runs
475
+ aggressive: false, // default: false
476
+ },
477
+ }
478
+ ```
479
+
480
+ - **`interval`** is a duration string (`h`/`d`/`w`/`m`/`y`). The last run is timestamped in the object store (`<bare-repo>/sync-worktrees-maintenance.json`, or `<worktreeDir>/.git/…` in clone mode), so throttling survives daemon restarts and repeated `runOnce` invocations.
481
+ - **`aggressive: false`** (default) runs plain `git gc`, which honors Git's two-week grace period — recently-unreachable objects (and anything reachable from a branch, tag, stash, or reflog) are always preserved.
482
+ - **`aggressive: true`** runs `git gc --prune=now`, pruning recently-unreachable objects immediately. Use it only for explicit reclamation; the default is the safe choice. The repository operation lock only serializes sync-worktrees' own operations — `--prune=now` can still race manual `git` work happening in the checkout outside the daemon, so avoid enabling it on repositories you also edit by hand concurrently.
483
+ - A maintenance failure is logged as a warning and never fails the sync. The attempt is still timestamped, so a broken `gc` is throttled instead of retried every tick.
484
+
466
485
  ### Branch filtering
467
486
 
468
487
  Two filters can be combined:
@@ -508,14 +527,73 @@ The TUI's worktree status view (`w`) lists diverged directories and offers a gui
508
527
 
509
528
  Clean rebases where file content matches the upstream are auto-applied with no detour through `.diverged/`. Diverged-but-no-local-commits is also handled without preservation, since there's no user work to keep.
510
529
 
530
+ With trash enabled (the default), the preserved copy lands in `.trash/` instead of `.diverged/`, so it ages out under the retention policy and can be restored as a full worktree — see [Trash and restore](#trash-and-restore). The `.diverged/` layout above applies when trash is disabled.
531
+
532
+ ### Trash and restore
533
+
534
+ Every removal — age-based prune, orphan cleanup, and diverged-branch replacement — is reversible by default. Instead of deleting, sync-worktrees moves the directory into a per-workspace trash with a manifest describing how to put it back:
535
+
536
+ ```
537
+ my-repo-worktrees/
538
+ ├── main/
539
+ ├── feature-a/
540
+ └── .trash/
541
+ └── 2026-06-06T18-30-00-000Z-feature-x-a1b2c3/
542
+ ├── manifest.json # branch, reason, original path, HEAD commit, expiry
543
+ └── payload/ # the directory exactly as it was, including uncommitted work
544
+ ```
545
+
546
+ When the removed directory was a branch worktree, a pin ref (`refs/sync-worktrees/trash/<id>`) keeps the trashed HEAD's objects alive through `git gc` for the whole retention window — even though the local branch ref itself is deleted after trashing. Each entry expires on its own clock; a reaper deletes expired entries at the tail of a successful sync.
547
+
548
+ ```javascript
549
+ defaults: {
550
+ trash: {
551
+ enabled: true, // default: true — disabling restores direct deletion
552
+ retentionDays: 30, // default: 30
553
+ warnSizeBytes: 5e9, // optional: warn when total trash exceeds this
554
+ migrateLegacy: true, // default: true — adopt old .removed/ and .diverged/ entries
555
+ },
556
+ }
557
+ ```
558
+
559
+ Trash entries are deliberately not exposed through the MCP server — listing, restoring, and purging are human operations.
560
+
561
+ **Restoring**: read `manifest.json` for the entry's `branch`, `headOid`, and `originalPath`, then either copy `payload/` wherever you need the files, or rebuild the worktree yourself:
562
+
563
+ ```bash
564
+ cd my-repo-worktrees/.trash/<id>
565
+ cat manifest.json
566
+ git -C <bare-repo> branch <branch> <headOid>
567
+ git -C <bare-repo> worktree add --no-checkout <originalPath> <branch>
568
+ cp -R payload/. <originalPath>/ # then restore the .git link git wrote:
569
+ git -C <bare-repo> worktree repair <originalPath>
570
+ git -C <originalPath> reset # index at HEAD, payload shows as unstaged changes
571
+ cd .. && rm -rf <id> # discard the trash entry when done
572
+ git -C <bare-repo> update-ref -d refs/sync-worktrees/trash/<id> # drop the pin
573
+ ```
574
+
575
+ Notes:
576
+
577
+ - Trash applies to worktree mode only; clone mode never removes its checkout.
578
+ - Anything in `.trash/` without a valid manifest is left alone by the reaper and reported, never deleted.
579
+ - Pin refs whose trash entry is gone (e.g. a failed cleanup, a manually emptied `.trash/`) are swept by the reaper on the next sync, so nothing stays pinned forever.
580
+ - A failure to move a directory into trash (e.g. trash on a different filesystem) skips the removal entirely — the worktree stays in place.
581
+ - Worktrees containing submodules are preserved byte-for-byte; nested submodule state is restored as-is but submodules are not re-registered automatically.
582
+
511
583
  ### Retry and LFS
512
584
 
513
585
  The tool retries network errors (timeouts, DNS failures, access issues) and filesystem race conditions automatically:
514
586
 
515
587
  ```javascript
516
- retry: { maxAttempts: 5 } // try 5 times then stop
517
- retry: { maxAttempts: "unlimited" } // keep trying forever (default)
518
- retry: { maxDelayMs: 60000 } // cap retry delay at 1 minute
588
+ retry: {
589
+ maxAttempts: 5;
590
+ } // try 5 times then stop
591
+ retry: {
592
+ maxAttempts: "unlimited";
593
+ } // keep trying forever (default)
594
+ retry: {
595
+ maxDelayMs: 60000;
596
+ } // cap retry delay at 1 minute
519
597
  ```
520
598
 
521
599
  For repositories with Git LFS issues or large files you don't need, set `skipLfs: true` in `defaults` or per repository. The tool also retries LFS-specific failures with LFS disabled (configurable via `retry.maxLfsRetries`).
@@ -535,12 +613,12 @@ For every knob (timeouts, parallelism, jitter, sparse-update behavior, retry tun
535
613
 
536
614
  The CLI loads a config file and runs it. Most run-mode settings (branch filters, retry, parallelism, LFS, clone mode, depth, etc.) live in the config file. Use `--runOnce` for an ad-hoc one-shot run without editing config.
537
615
 
538
- | Option | Alias | Description | Default |
539
- |--------|-------|-------------|---------|
540
- | `--config` | `-c` | Path to JavaScript config file (auto-detected in CWD when omitted) | - |
541
- | `--runOnce` | - | Run a sync once and exit, overriding config `runOnce` settings for this invocation | `false` |
542
- | `--help` | `-h` | Show help | - |
543
- | `--version` | - | Print version | - |
616
+ | Option | Alias | Description | Default |
617
+ | ----------- | ----- | ---------------------------------------------------------------------------------- | ------- |
618
+ | `--config` | `-c` | Path to JavaScript config file (auto-detected in CWD when omitted) | - |
619
+ | `--runOnce` | - | Run a sync once and exit, overriding config `runOnce` settings for this invocation | `false` |
620
+ | `--help` | `-h` | Show help | - |
621
+ | `--version` | - | Print version | - |
544
622
 
545
623
  Subcommands:
546
624
 
@@ -1 +1 @@
1
- {"version":3,"file":"WorktreeStatusView.d.ts","sourceRoot":"","sources":["../../src/components/WorktreeStatusView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAIjF,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAGlB,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAIpC,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,wBAAwB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC5E,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACzE,6BAA6B,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACpF,uBAAuB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA2GD,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAqiBzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"WorktreeStatusView.d.ts","sourceRoot":"","sources":["../../src/components/WorktreeStatusView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAIjF,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAGlB,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAIpC,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC,wBAAwB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAC5E,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACzE,6BAA6B,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IACpF,uBAAuB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAqHD,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA4iBzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -6,6 +6,10 @@ export declare const GIT_CONSTANTS: {
6
6
  readonly COMMON_DEFAULT_BRANCHES: readonly ["main", "master", "develop", "trunk"];
7
7
  readonly BARE_DIR_NAME: ".bare";
8
8
  readonly DIVERGED_DIR_NAME: ".diverged";
9
+ readonly REMOVED_DIR_NAME: ".removed";
10
+ readonly TRASH_DIR_NAME: ".trash";
11
+ readonly TRASH_REF_PREFIX: "refs/sync-worktrees/trash/";
12
+ readonly KEEP_REF_PREFIX: "refs/sync-worktrees/keep/";
9
13
  readonly LFS_HEADER: "version https://git-lfs.github.com/spec/";
10
14
  readonly SUBMODULE_STATUS_ADDED: "+";
11
15
  readonly SUBMODULE_STATUS_REMOVED: "-";
@@ -52,6 +56,15 @@ export declare const DEFAULT_CONFIG: {
52
56
  readonly CLONE_TIMEOUT_MS: 900000;
53
57
  readonly LOCK_STALE_MS: 600000;
54
58
  readonly LOCK_UPDATE_MS: 30000;
59
+ readonly MAINTENANCE: {
60
+ readonly ENABLED: true;
61
+ readonly INTERVAL: "7d";
62
+ };
63
+ readonly TRASH: {
64
+ readonly ENABLED: true;
65
+ readonly RETENTION_DAYS: 30;
66
+ readonly MIGRATE_LEGACY: true;
67
+ };
55
68
  };
56
69
  export declare const ERROR_MESSAGES: {
57
70
  readonly GIT_NOT_INITIALIZED: "Git service not initialized. Call initialize() first.";
@@ -77,6 +90,15 @@ export declare const PATH_CONSTANTS: {
77
90
  readonly CLONE_INIT_MARKER: ".sync-worktrees-clone-init";
78
91
  };
79
92
  export declare const CONFIG_FILE_NAMES: readonly ["sync-worktrees.config.js", "sync-worktrees.config.mjs", "sync-worktrees.config.cjs"];
93
+ export declare const MAINTENANCE_CONSTANTS: {
94
+ readonly STATE_FILENAME: "sync-worktrees-maintenance.json";
95
+ };
96
+ export declare const TRASH_CONSTANTS: {
97
+ readonly MANIFEST_FILENAME: "manifest.json";
98
+ readonly PAYLOAD_DIRNAME: "payload";
99
+ readonly BUNDLE_FILENAME: "commits.bundle";
100
+ readonly SCHEMA_VERSION: 1;
101
+ };
80
102
  export declare const METADATA_CONSTANTS: {
81
103
  readonly MAX_HISTORY_ENTRIES: 10;
82
104
  readonly METADATA_FILENAME: "sync-metadata.json";
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;CAoBhB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;CAOjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;CAyBjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;CAiBjB,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,aAAa;;;;CAIhB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,eAAO,MAAM,iBAAiB,iGAIpB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;;;;CASrB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;CAgBjB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;CAwBhB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;CAOjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;CAiBjB,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,aAAa;;;;CAIhB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,eAAO,MAAM,iBAAiB,iGAIpB,CAAC;AAEX,eAAO,MAAM,qBAAqB;;CAExB,CAAC;AAEX,eAAO,MAAM,eAAe;;;;;CAKlB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;;;;;;CASrB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;CAgBjB,CAAC"}
@@ -50,6 +50,13 @@ export declare class PathResolutionError extends SyncWorktreesError {
50
50
  readonly reason: string;
51
51
  constructor(path: string, reason: string);
52
52
  }
53
+ export declare class TrashError extends SyncWorktreesError {
54
+ constructor(message: string, code: string, cause?: Error);
55
+ }
56
+ export declare class TrashOperationError extends TrashError {
57
+ readonly operation: string;
58
+ constructor(operation: string, details: string, cause?: Error);
59
+ }
53
60
  export declare class LfsError extends GitError {
54
61
  constructor(message: string, cause?: Error);
55
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAEA,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,IAAI,EAAE,MAAM;aACZ,KAAK,CAAC,EAAE,KAAK;gBAF7B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,KAAK,YAAA;CAShC;AAED,qBAAa,QAAS,SAAQ,kBAAkB;gBAClC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,sBAAuB,SAAQ,QAAQ;;CAInD;AAED,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG9D;AAED,qBAAa,gBAAiB,SAAQ,QAAQ;aAE1B,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM,EAClC,KAAK,CAAC,EAAE,KAAK;CAIhB;AAED,qBAAa,aAAc,SAAQ,kBAAkB;gBACvC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,0BAA2B,SAAQ,aAAa;aAEzC,IAAI,EAAE,MAAM;aACZ,UAAU,EAAE,MAAM;gBADlB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM;CAIrC;AAED,qBAAa,qBAAsB,SAAQ,aAAa;aAEpC,IAAI,EAAE,MAAM;aACZ,OAAO,EAAE,MAAM,EAAE;gBADjB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE;CAIpC;AAED,qBAAa,WAAY,SAAQ,kBAAkB;gBACrC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,qBAAsB,SAAQ,WAAW;aAElC,KAAK,EAAE,MAAM;aACb,MAAM,EAAE,MAAM;gBADd,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;CAIjC;AAED,qBAAa,uBAAwB,SAAQ,WAAW;aAC1B,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM;CAG/C;AAED,qBAAa,qBAAsB,SAAQ,WAAW;aACxB,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM;CAG/C;AAED,qBAAa,mBAAoB,SAAQ,kBAAkB;aAEvC,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM;gBADd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAIjC;AAED,qBAAa,QAAS,SAAQ,QAAQ;gBACxB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG3C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGjE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGhE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAEA,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,IAAI,EAAE,MAAM;aACZ,KAAK,CAAC,EAAE,KAAK;gBAF7B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,KAAK,YAAA;CAShC;AAED,qBAAa,QAAS,SAAQ,kBAAkB;gBAClC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,sBAAuB,SAAQ,QAAQ;;CAInD;AAED,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG9D;AAED,qBAAa,gBAAiB,SAAQ,QAAQ;aAE1B,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM,EAClC,KAAK,CAAC,EAAE,KAAK;CAIhB;AAED,qBAAa,aAAc,SAAQ,kBAAkB;gBACvC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,0BAA2B,SAAQ,aAAa;aAEzC,IAAI,EAAE,MAAM;aACZ,UAAU,EAAE,MAAM;gBADlB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM;CAIrC;AAED,qBAAa,qBAAsB,SAAQ,aAAa;aAEpC,IAAI,EAAE,MAAM;aACZ,OAAO,EAAE,MAAM,EAAE;gBADjB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE;CAIpC;AAED,qBAAa,WAAY,SAAQ,kBAAkB;gBACrC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,qBAAsB,SAAQ,WAAW;aAElC,KAAK,EAAE,MAAM;aACb,MAAM,EAAE,MAAM;gBADd,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;CAIjC;AAED,qBAAa,uBAAwB,SAAQ,WAAW;aAC1B,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM;CAG/C;AAED,qBAAa,qBAAsB,SAAQ,WAAW;aACxB,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM;CAG/C;AAED,qBAAa,mBAAoB,SAAQ,kBAAkB;aAEvC,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM;gBADd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAIjC;AAED,qBAAa,UAAW,SAAQ,kBAAkB;gBACpC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,mBAAoB,SAAQ,UAAU;aAE/B,SAAS,EAAE,MAAM;gBAAjB,SAAS,EAAE,MAAM,EACjC,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,KAAK;CAIhB;AAED,qBAAa,QAAS,SAAQ,QAAQ;gBACxB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG3C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGjE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGhE"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import type { ConfigFile, RepositoryConfig } from "./types";
3
- export type { SyncWorktreesConfig, SyncWorktreesDefaults, SyncWorktreesHooksConfig, SyncWorktreesParallelismConfig, SyncWorktreesRepository, SyncWorktreesRepositoryMode, SyncWorktreesRetryConfig, SyncWorktreesSparseCheckoutConfig, SyncWorktreesSparseCheckoutMode, } from "./types";
3
+ export type { SyncWorktreesConfig, SyncWorktreesDefaults, SyncWorktreesHooksConfig, SyncWorktreesParallelismConfig, SyncWorktreesRepository, SyncWorktreesRepositoryMode, SyncWorktreesRetryConfig, SyncWorktreesSparseCheckoutConfig, SyncWorktreesSparseCheckoutMode, SyncWorktreesTrashConfig, } from "./types";
4
4
  export declare function runMultipleRepositories(configFile: ConfigFile, repositories: RepositoryConfig[], configPath?: string): Promise<void>;
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAsBA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG5D,YAAY,EACV,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,EACxB,8BAA8B,EAC9B,uBAAuB,EACvB,2BAA2B,EAC3B,wBAAwB,EACxB,iCAAiC,EACjC,+BAA+B,GAChC,MAAM,SAAS,CAAC;AAIjB,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,gBAAgB,EAAE,EAChC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA+Jf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAsBA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG5D,YAAY,EACV,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,EACxB,8BAA8B,EAC9B,uBAAuB,EACvB,2BAA2B,EAC3B,wBAAwB,EACxB,iCAAiC,EACjC,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,SAAS,CAAC;AAIjB,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,gBAAgB,EAAE,EAChC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA+Jf"}