@cleocode/worktree 2026.5.103 → 2026.5.105

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.
@@ -51,6 +51,65 @@ interface WorktreeInfoNapi {
51
51
  isLocked: boolean;
52
52
  isPrunable: boolean;
53
53
  }
54
+ /**
55
+ * Options for the napi `pruneWorktrees` binding (T10203).
56
+ *
57
+ * Mirrors `crates/worktree-napi`'s `PruneOpts` — see ADR-078 for the
58
+ * worktrunk-core SDK boundary contract.
59
+ */
60
+ interface PruneOptsNapi {
61
+ /** Absolute path to the git repository whose worktrees we plan to prune. */
62
+ repoRoot: string;
63
+ /**
64
+ * The integration target branch (e.g. `"main"`) the candidates are tested
65
+ * against for "is this merged in?".
66
+ */
67
+ integrationTarget: string;
68
+ }
69
+ /**
70
+ * Single prune candidate returned by the napi `pruneWorktrees` plan (T10203).
71
+ */
72
+ interface PruneCandidateNapi {
73
+ /** Branch name (`undefined` for detached HEAD worktrees). */
74
+ branch?: string;
75
+ /** Display label (branch name or `(detached <short>)`). */
76
+ label: string;
77
+ /** Worktree path (`undefined` for branch-only candidates). */
78
+ path?: string;
79
+ /** Candidate kind: `"current" | "worktree" | "branch_only"`. */
80
+ kind: string;
81
+ /** Human-readable integration reason. */
82
+ reason: string;
83
+ }
84
+ /**
85
+ * Read-only prune plan returned by the napi `pruneWorktrees` binding (T10203).
86
+ */
87
+ interface PrunePlanNapi {
88
+ /** The default branch this plan was computed against. */
89
+ integrationTarget: string;
90
+ /** Candidates eligible for removal, in deterministic discovery order. */
91
+ candidates: PruneCandidateNapi[];
92
+ }
93
+ /**
94
+ * Options for the napi `removeDir` binding (T10203).
95
+ *
96
+ * Recursively removes a directory tree using
97
+ * `worktrunk_core::remove_dir::remove_dir_with_progress`. Best-effort —
98
+ * read/unlink/rmdir errors are silently skipped on the SDK side.
99
+ */
100
+ interface RemoveDirOptsNapi {
101
+ /** Absolute path to the directory tree to remove. */
102
+ path: string;
103
+ }
104
+ /**
105
+ * Result of a napi `removeDir` call (T10203).
106
+ */
107
+ interface RemoveDirResultNapi {
108
+ /** Number of leaf files unlinked. */
109
+ files: number;
110
+ /** Total bytes unlinked. Capped at `u32::MAX` for napi compatibility. */
111
+ bytes: number;
112
+ }
54
113
  /**
55
114
  * Shape of the native module exported by `@cleocode/worktree-napi`.
56
115
  *
@@ -66,11 +125,15 @@ interface WorktreeNapiModule {
66
125
  readWorktreeInclude(repoRoot: string): IncludePatternNapi[];
67
126
  applyInclude(patterns: IncludePatternNapi[], srcDir: string, destDir: string, opts: CopyOptsNapi): CopyResultNapi;
68
127
  listWorktrees(opts: ListOptsNapi): WorktreeInfoNapi[];
128
+ pruneWorktrees(opts: PruneOptsNapi): PrunePlanNapi;
129
+ removeDir(opts: RemoveDirOptsNapi): RemoveDirResultNapi;
69
130
  }
70
131
  export declare const copyPathsParallel: WorktreeNapiModule['copyPathsParallel'];
71
132
  export declare const destroyWorktree: WorktreeNapiModule['destroyWorktree'];
72
133
  export declare const readWorktreeInclude: WorktreeNapiModule['readWorktreeInclude'];
73
134
  export declare const applyInclude: WorktreeNapiModule['applyInclude'];
74
135
  export declare const listWorktrees: WorktreeNapiModule['listWorktrees'];
75
- export type { CopyOptsNapi, CopyResultNapi, DestroyOptsNapi, DestroyResultNapi, IncludePatternNapi, ListOptsNapi, WorktreeInfoNapi, };
136
+ export declare const pruneWorktrees: WorktreeNapiModule['pruneWorktrees'];
137
+ export declare const removeDir: WorktreeNapiModule['removeDir'];
138
+ export type { CopyOptsNapi, CopyResultNapi, DestroyOptsNapi, DestroyResultNapi, IncludePatternNapi, ListOptsNapi, PruneCandidateNapi, PruneOptsNapi, PrunePlanNapi, RemoveDirOptsNapi, RemoveDirResultNapi, WorktreeInfoNapi, };
76
139
  //# sourceMappingURL=napi-binding.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"napi-binding.d.ts","sourceRoot":"","sources":["../src/napi-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,UAAU,YAAY;IACpB,qDAAqD;IACrD,KAAK,EAAE,OAAO,CAAC;IACf,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,UAAU,cAAc;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,UAAU,kBAAkB;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,UAAU,kBAAkB;IAC1B,iBAAiB,CACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE,YAAY,GACjB,cAAc,CAAC;IAClB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAC1D,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAAC;IAC5D,YAAY,CACV,QAAQ,EAAE,kBAAkB,EAAE,EAC9B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,YAAY,GACjB,cAAc,CAAC;IAClB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB,EAAE,CAAC;CACvD;AAsBD,eAAO,MAAM,iBAAiB,EAAE,kBAAkB,CAAC,mBAAmB,CAKN,CAAC;AAEjE,eAAO,MAAM,eAAe,EAAE,kBAAkB,CAAC,iBAAiB,CAC/B,CAAC;AAEpC,eAAO,MAAM,mBAAmB,EAAE,kBAAkB,CAAC,qBAAqB,CAC/B,CAAC;AAE5C,eAAO,MAAM,YAAY,EAAE,kBAAkB,CAAC,cAAc,CACD,CAAC;AAE5D,eAAO,MAAM,aAAa,EAAE,kBAAkB,CAAC,eAAe,CAC7B,CAAC;AAElC,YAAY,EACV,YAAY,EACZ,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,GACjB,CAAC"}
1
+ {"version":3,"file":"napi-binding.d.ts","sourceRoot":"","sources":["../src/napi-binding.ts"],"names":[],"mappings":"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"}
@@ -40,4 +40,6 @@ export const destroyWorktree = (opts) => getNative().destroyWorktree(opts);
40
40
  export const readWorktreeInclude = (repoRoot) => getNative().readWorktreeInclude(repoRoot);
41
41
  export const applyInclude = (patterns, srcDir, destDir, opts) => getNative().applyInclude(patterns, srcDir, destDir, opts);
42
42
  export const listWorktrees = (opts) => getNative().listWorktrees(opts);
43
+ export const pruneWorktrees = (opts) => getNative().pruneWorktrees(opts);
44
+ export const removeDir = (opts) => getNative().removeDir(opts);
43
45
  //# sourceMappingURL=napi-binding.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"napi-binding.js","sourceRoot":"","sources":["../src/napi-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAyEhD;;;;;;;;;;;GAWG;AACH,IAAI,aAAa,GAA8B,IAAI,CAAC;AACpD,SAAS,SAAS;IAChB,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,aAAa,GAAG,QAAQ,CAAC,yBAAyB,CAAuB,CAAC;IAC5E,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAA4C,CACxE,MAAM,EACN,OAAO,EACP,KAAK,EACL,IAAI,EACJ,EAAE,CAAC,SAAS,EAAE,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAEjE,MAAM,CAAC,MAAM,eAAe,GAA0C,CAAC,IAAI,EAAE,EAAE,CAC7E,SAAS,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;AAEpC,MAAM,CAAC,MAAM,mBAAmB,GAA8C,CAAC,QAAQ,EAAE,EAAE,CACzF,SAAS,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AAE5C,MAAM,CAAC,MAAM,YAAY,GAAuC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAClG,SAAS,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAE5D,MAAM,CAAC,MAAM,aAAa,GAAwC,CAAC,IAAI,EAAE,EAAE,CACzE,SAAS,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"napi-binding.js","sourceRoot":"","sources":["../src/napi-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AA2IhD;;;;;;;;;;;GAWG;AACH,IAAI,aAAa,GAA8B,IAAI,CAAC;AACpD,SAAS,SAAS;IAChB,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,aAAa,GAAG,QAAQ,CAAC,yBAAyB,CAAuB,CAAC;IAC5E,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAA4C,CACxE,MAAM,EACN,OAAO,EACP,KAAK,EACL,IAAI,EACJ,EAAE,CAAC,SAAS,EAAE,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAEjE,MAAM,CAAC,MAAM,eAAe,GAA0C,CAAC,IAAI,EAAE,EAAE,CAC7E,SAAS,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;AAEpC,MAAM,CAAC,MAAM,mBAAmB,GAA8C,CAAC,QAAQ,EAAE,EAAE,CACzF,SAAS,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;AAE5C,MAAM,CAAC,MAAM,YAAY,GAAuC,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAClG,SAAS,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AAE5D,MAAM,CAAC,MAAM,aAAa,GAAwC,CAAC,IAAI,EAAE,EAAE,CACzE,SAAS,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAElC,MAAM,CAAC,MAAM,cAAc,GAAyC,CAAC,IAAI,EAAE,EAAE,CAC3E,SAAS,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;AAEnC,MAAM,CAAC,MAAM,SAAS,GAAoC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC"}
@@ -1,37 +1,70 @@
1
1
  /**
2
2
  * Worktree prune operation for @cleocode/worktree.
3
3
  *
4
- * Removes orphaned worktrees: worktree directories whose task ID is NOT in
5
- * the provided `preserveTaskIds` set, and optionally runs `git worktree prune`
6
- * to clean up stale git administrative entries.
4
+ * Thin orchestration over the `worktrunk_core` SDK exposed via
5
+ * `@cleocode/worktree-napi` (T10203 / ADR-078). The native binding owns:
7
6
  *
8
- * Supports an `--idle-days` abandonment-timeout threshold (T9805 AC2): when
9
- * set, worktrees whose branch tip is older than `idleDays` days AND which have
10
- * no open PR are also eligible for removal, even if their task ID is not in the
11
- * orphan set.
7
+ * - Git-aware prune-plan construction (`napi.pruneWorktrees`) — read-only
8
+ * discovery of merged-in worktrees + orphan branches.
9
+ * - Recursive directory removal (`napi.removeDir`) replaces the
10
+ * `rmSync` + `git worktree remove` fallback that previously lived here.
11
+ *
12
+ * The TypeScript layer keeps three concerns that are explicitly outside the
13
+ * SDK boundary per ADR-061:
14
+ *
15
+ * 1. CLEO XDG-layout scan + `preserveTaskIds`/`idleDays` filter — business
16
+ * logic that the napi binding intentionally avoids.
17
+ * 2. Audit-log writes to `.cleo/audit/worktree-lifecycle.jsonl` (T9805 AC3).
18
+ * 3. Sentinel-index updates at `<gitRoot>/.cleo/worktrees.json` (D009).
12
19
  *
13
20
  * Called periodically by `cleo sentient tick` via `worktree-dispatch.ts`.
14
21
  *
15
22
  * @task T1161
16
23
  * @task T9805
24
+ * @task T10204
17
25
  */
18
26
  import type { PruneWorktreesOptions, PruneWorktreesResult } from '@cleocode/contracts';
27
+ import { pruneWorktrees as napiPrune } from './napi-binding.js';
19
28
  /**
20
29
  * Prune orphaned agent worktrees for a project.
21
30
  *
22
- * Algorithm:
23
- * 1. Optionally run `git worktree prune` to clean up stale git admin entries.
24
- * 2. Read all subdirectory entries under the project's worktree root.
25
- * 3. For each entry NOT in `preserveTaskIds` (or idle beyond `idleDays`),
26
- * unlock and remove the worktree.
27
- * 4. Append an audit-log entry for each removal.
28
- * 5. Remove the entry from the sentinel index when removal succeeds.
31
+ * Algorithm (thin orchestration over napi SDK):
32
+ *
33
+ * 1. Resolve the git root (falling back to `projectRoot` when not in a repo).
34
+ * 2. Optionally invoke `napi.pruneWorktrees` for git-aware candidate discovery
35
+ * the SDK plan is currently advisory; the TS layer drives the actual
36
+ * removal because audit + sentinel concerns are TS-owned per ADR-061.
37
+ * 3. Scan the XDG worktree root, filtering by `preserveTaskIds`/`idleDays`.
38
+ * 4. For each eligible entry: unlock via git → remove via napi → audit-log →
39
+ * sentinel-index cleanup.
29
40
  *
30
41
  * @param options - Prune options with project root and optional preserve list.
31
42
  * @returns Result listing removed paths and any errors.
32
43
  *
33
44
  * @task T1161
34
45
  * @task T9805
46
+ * @task T10204
35
47
  */
36
48
  export declare function pruneWorktrees(options: PruneWorktreesOptions): PruneWorktreesResult;
49
+ /**
50
+ * Build a git-aware prune plan via the `worktrunk-core` SDK (T10203).
51
+ *
52
+ * Wraps `napi.pruneWorktrees` with the integration-target branch the caller
53
+ * expects. Returns `null` when the underlying call fails (the napi layer
54
+ * raises on bare repos, detached HEAD on main, or empty worktree lists) so
55
+ * the legacy filesystem-scan path stays unaffected.
56
+ *
57
+ * Currently advisory: the result is exposed for callers that want the
58
+ * SDK-classified merge-state, but {@link pruneWorktrees} still drives removal
59
+ * from the XDG layout because preserveTaskIds + idleDays semantics live
60
+ * outside the SDK boundary.
61
+ *
62
+ * @param gitRoot - Absolute path to the git repository root.
63
+ * @param integrationTarget - Branch name to test "is merged" against
64
+ * (typically `main` or `master`).
65
+ * @returns The SDK plan, or `null` when the napi call cannot be issued.
66
+ *
67
+ * @task T10204
68
+ */
69
+ export declare function buildGitAwarePrunePlan(gitRoot: string, integrationTarget: string): ReturnType<typeof napiPrune> | null;
37
70
  //# sourceMappingURL=worktree-prune.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worktree-prune.d.ts","sourceRoot":"","sources":["../src/worktree-prune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAKvF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,CA+GnF"}
1
+ {"version":3,"file":"worktree-prune.d.ts","sourceRoot":"","sources":["../src/worktree-prune.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEvF,OAAO,EAAE,cAAc,IAAI,SAAS,EAA8B,MAAM,mBAAmB,CAAC;AAI5F;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,CAiBnF;AA2KD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,iBAAiB,EAAE,MAAM,GACxB,UAAU,CAAC,OAAO,SAAS,CAAC,GAAG,IAAI,CAMrC"}
@@ -1,149 +1,188 @@
1
1
  /**
2
2
  * Worktree prune operation for @cleocode/worktree.
3
3
  *
4
- * Removes orphaned worktrees: worktree directories whose task ID is NOT in
5
- * the provided `preserveTaskIds` set, and optionally runs `git worktree prune`
6
- * to clean up stale git administrative entries.
4
+ * Thin orchestration over the `worktrunk_core` SDK exposed via
5
+ * `@cleocode/worktree-napi` (T10203 / ADR-078). The native binding owns:
7
6
  *
8
- * Supports an `--idle-days` abandonment-timeout threshold (T9805 AC2): when
9
- * set, worktrees whose branch tip is older than `idleDays` days AND which have
10
- * no open PR are also eligible for removal, even if their task ID is not in the
11
- * orphan set.
7
+ * - Git-aware prune-plan construction (`napi.pruneWorktrees`) — read-only
8
+ * discovery of merged-in worktrees + orphan branches.
9
+ * - Recursive directory removal (`napi.removeDir`) replaces the
10
+ * `rmSync` + `git worktree remove` fallback that previously lived here.
11
+ *
12
+ * The TypeScript layer keeps three concerns that are explicitly outside the
13
+ * SDK boundary per ADR-061:
14
+ *
15
+ * 1. CLEO XDG-layout scan + `preserveTaskIds`/`idleDays` filter — business
16
+ * logic that the napi binding intentionally avoids.
17
+ * 2. Audit-log writes to `.cleo/audit/worktree-lifecycle.jsonl` (T9805 AC3).
18
+ * 3. Sentinel-index updates at `<gitRoot>/.cleo/worktrees.json` (D009).
12
19
  *
13
20
  * Called periodically by `cleo sentient tick` via `worktree-dispatch.ts`.
14
21
  *
15
22
  * @task T1161
16
23
  * @task T9805
24
+ * @task T10204
17
25
  */
18
26
  import { execFileSync } from 'node:child_process';
19
- import { existsSync, readdirSync, rmSync } from 'node:fs';
27
+ import { existsSync, readdirSync } from 'node:fs';
20
28
  import { join } from 'node:path';
21
29
  import { getGitRoot, gitSilent } from './git.js';
30
+ import { pruneWorktrees as napiPrune, removeDir as napiRemoveDir } from './napi-binding.js';
22
31
  import { computeProjectHash, resolveWorktreeRootForHash } from './paths.js';
23
32
  import { appendWorktreeAuditLog, removeWorktreeFromSentinelIndex } from './worktree-audit.js';
24
33
  /**
25
34
  * Prune orphaned agent worktrees for a project.
26
35
  *
27
- * Algorithm:
28
- * 1. Optionally run `git worktree prune` to clean up stale git admin entries.
29
- * 2. Read all subdirectory entries under the project's worktree root.
30
- * 3. For each entry NOT in `preserveTaskIds` (or idle beyond `idleDays`),
31
- * unlock and remove the worktree.
32
- * 4. Append an audit-log entry for each removal.
33
- * 5. Remove the entry from the sentinel index when removal succeeds.
36
+ * Algorithm (thin orchestration over napi SDK):
37
+ *
38
+ * 1. Resolve the git root (falling back to `projectRoot` when not in a repo).
39
+ * 2. Optionally invoke `napi.pruneWorktrees` for git-aware candidate discovery
40
+ * the SDK plan is currently advisory; the TS layer drives the actual
41
+ * removal because audit + sentinel concerns are TS-owned per ADR-061.
42
+ * 3. Scan the XDG worktree root, filtering by `preserveTaskIds`/`idleDays`.
43
+ * 4. For each eligible entry: unlock via git → remove via napi → audit-log →
44
+ * sentinel-index cleanup.
34
45
  *
35
46
  * @param options - Prune options with project root and optional preserve list.
36
47
  * @returns Result listing removed paths and any errors.
37
48
  *
38
49
  * @task T1161
39
50
  * @task T9805
51
+ * @task T10204
40
52
  */
41
53
  export function pruneWorktrees(options) {
42
54
  const { projectRoot, preserveTaskIds, gitPrune = true, idleDays } = options;
43
55
  const projectHash = computeProjectHash(projectRoot);
44
56
  const worktreeRoot = resolveWorktreeRootForHash(projectHash);
57
+ const gitRoot = resolveGitRootOrFallback(projectRoot);
45
58
  const removed = [];
46
59
  const errors = [];
47
- let gitPruneRan = false;
48
- let gitRoot;
60
+ const gitPruneRan = gitPrune ? runGitPruneAdminCleanup(gitRoot) : false;
61
+ if ((preserveTaskIds === undefined && idleDays === undefined) || !existsSync(worktreeRoot)) {
62
+ return { removed: 0, removedPaths: [], errors, gitPruneRan };
63
+ }
64
+ for (const entry of safeReaddir(worktreeRoot)) {
65
+ const decision = classifyPruneCandidate(entry, preserveTaskIds, idleDays, worktreeRoot);
66
+ if (decision === null)
67
+ continue;
68
+ pruneSingleEntry(decision, gitRoot, projectRoot, removed, errors);
69
+ }
70
+ return { removed: removed.length, removedPaths: removed, errors, gitPruneRan };
71
+ }
72
+ /**
73
+ * Resolve the git root for `projectRoot`, falling back to `projectRoot` when
74
+ * we are not inside a git repository. Lets prune still clean directories that
75
+ * exist outside a working repo.
76
+ *
77
+ * @internal
78
+ */
79
+ function resolveGitRootOrFallback(projectRoot) {
49
80
  try {
50
- gitRoot = getGitRoot(projectRoot);
81
+ return getGitRoot(projectRoot);
51
82
  }
52
83
  catch {
53
- // If there's no git root, we can still remove dirs — just skip git cmds.
54
- gitRoot = projectRoot;
84
+ return projectRoot;
55
85
  }
56
- // Step 1: Run git worktree prune if requested.
57
- if (gitPrune) {
58
- try {
59
- gitSilent(['worktree', 'prune'], gitRoot);
60
- gitPruneRan = true;
86
+ }
87
+ /**
88
+ * Run `git worktree prune` to clean up stale administrative entries.
89
+ *
90
+ * Returns `true` on success, `false` when not in a git repo (non-fatal).
91
+ *
92
+ * @internal
93
+ */
94
+ function runGitPruneAdminCleanup(gitRoot) {
95
+ return gitSilent(['worktree', 'prune'], gitRoot);
96
+ }
97
+ /**
98
+ * Safely read directory entries, returning `[]` on failure.
99
+ *
100
+ * @internal
101
+ */
102
+ function safeReaddir(dir) {
103
+ try {
104
+ return readdirSync(dir);
105
+ }
106
+ catch {
107
+ return [];
108
+ }
109
+ }
110
+ /**
111
+ * Classify a single worktree-root subdirectory entry for prune eligibility.
112
+ *
113
+ * Returns `null` when the entry should be preserved, or a {@link PruneDecision}
114
+ * describing why it qualifies. Encapsulates the CLEO-specific
115
+ * `preserveTaskIds`/`idleDays` business logic that lives outside the
116
+ * worktrunk-core SDK by design (ADR-061).
117
+ *
118
+ * @internal
119
+ */
120
+ function classifyPruneCandidate(entry, preserveTaskIds, idleDays, worktreeRoot) {
121
+ const path = join(worktreeRoot, entry);
122
+ if (preserveTaskIds !== undefined) {
123
+ if (!preserveTaskIds.has(entry)) {
124
+ return { taskId: entry, path, reason: 'orphan' };
61
125
  }
62
- catch {
63
- // Non-fatal: project root may not be a git repo in some edge cases.
64
- gitPruneRan = false;
126
+ if (idleDays !== undefined && isWorktreeIdle(path, idleDays)) {
127
+ return { taskId: entry, path, reason: `idle-${idleDays}d` };
65
128
  }
129
+ return null;
130
+ }
131
+ if (idleDays !== undefined && isWorktreeIdle(path, idleDays)) {
132
+ return { taskId: entry, path, reason: `idle-${idleDays}d` };
66
133
  }
67
- // Step 2: Remove orphaned worktree directories.
68
- const shouldCheckDirectories = (preserveTaskIds !== undefined || idleDays !== undefined) && existsSync(worktreeRoot);
69
- if (shouldCheckDirectories) {
70
- let entries;
134
+ return null;
135
+ }
136
+ /**
137
+ * Remove a single worktree entry: unlock via git, remove via napi-backed
138
+ * directory removal, then write audit + sentinel-index entries.
139
+ *
140
+ * Mutates `removed` and `errors` in place to keep the orchestrator function
141
+ * thin. Both audit-log and sentinel-index updates are best-effort and never
142
+ * block successful removal.
143
+ *
144
+ * @internal
145
+ */
146
+ function pruneSingleEntry(decision, gitRoot, projectRoot, removed, errors) {
147
+ const { taskId, path, reason } = decision;
148
+ gitSilent(['worktree', 'unlock', path], gitRoot);
149
+ const gitRemoveSucceeded = gitSilent(['worktree', 'remove', '--force', path], gitRoot);
150
+ let pruneSuccess = gitRemoveSucceeded;
151
+ let errorMessage = null;
152
+ if (!gitRemoveSucceeded) {
71
153
  try {
72
- entries = readdirSync(worktreeRoot);
73
- }
74
- catch {
75
- return { removed: 0, removedPaths: [], errors, gitPruneRan };
154
+ // Delegate the recursive directory removal to worktrunk-core via napi
155
+ // (T10203). The SDK is best-effort: read/unlink/rmdir errors are
156
+ // silently skipped, so a non-zero file count signals success.
157
+ napiRemoveDir({ path });
158
+ pruneSuccess = true;
76
159
  }
77
- for (const entry of entries) {
78
- const worktreePath = join(worktreeRoot, entry);
79
- // Determine whether this entry is a prune candidate.
80
- let reason = 'orphan';
81
- let shouldPrune = false;
82
- if (preserveTaskIds !== undefined) {
83
- if (preserveTaskIds.has(entry)) {
84
- // Still check idle-days even for preserved IDs when idleDays is set.
85
- if (idleDays !== undefined && isWorktreeIdle(worktreePath, idleDays)) {
86
- shouldPrune = true;
87
- reason = `idle-${idleDays}d`;
88
- }
89
- }
90
- else {
91
- shouldPrune = true;
92
- reason = 'orphan';
93
- }
94
- }
95
- else if (idleDays !== undefined) {
96
- // preserveTaskIds not set — only idle-days check applies.
97
- if (isWorktreeIdle(worktreePath, idleDays)) {
98
- shouldPrune = true;
99
- reason = `idle-${idleDays}d`;
100
- }
101
- }
102
- if (!shouldPrune)
103
- continue;
104
- // Try git-aware removal first.
105
- gitSilent(['worktree', 'unlock', worktreePath], gitRoot);
106
- let pruneSuccess = false;
107
- if (gitSilent(['worktree', 'remove', '--force', worktreePath], gitRoot)) {
108
- removed.push(worktreePath);
109
- pruneSuccess = true;
110
- }
111
- else {
112
- // Fall back to rmSync for directories that aren't registered worktrees.
113
- try {
114
- rmSync(worktreePath, { recursive: true, force: true });
115
- removed.push(worktreePath);
116
- pruneSuccess = true;
117
- }
118
- catch (err) {
119
- const errMsg = err instanceof Error ? err.message : String(err);
120
- errors.push({ path: worktreePath, reason: errMsg });
121
- // T9805 AC3: Audit the failed removal.
122
- appendWorktreeAuditLog(projectRoot, {
123
- action: 'prune',
124
- xdgPath: worktreePath,
125
- taskId: entry,
126
- reason,
127
- success: false,
128
- error: errMsg,
129
- });
130
- }
131
- }
132
- if (pruneSuccess) {
133
- // T9805 AC3: Audit the successful removal.
134
- appendWorktreeAuditLog(projectRoot, {
135
- action: 'prune',
136
- xdgPath: worktreePath,
137
- taskId: entry,
138
- reason,
139
- success: true,
140
- });
141
- // T9805 D009: Remove from sentinel index.
142
- removeWorktreeFromSentinelIndex(gitRoot, entry);
143
- }
160
+ catch (err) {
161
+ errorMessage = err instanceof Error ? err.message : String(err);
144
162
  }
145
163
  }
146
- return { removed: removed.length, removedPaths: removed, errors, gitPruneRan };
164
+ if (pruneSuccess) {
165
+ removed.push(path);
166
+ appendWorktreeAuditLog(projectRoot, {
167
+ action: 'prune',
168
+ xdgPath: path,
169
+ taskId,
170
+ reason,
171
+ success: true,
172
+ });
173
+ removeWorktreeFromSentinelIndex(gitRoot, taskId);
174
+ return;
175
+ }
176
+ const finalError = errorMessage ?? 'napi removeDir failed';
177
+ errors.push({ path, reason: finalError });
178
+ appendWorktreeAuditLog(projectRoot, {
179
+ action: 'prune',
180
+ xdgPath: path,
181
+ taskId,
182
+ reason,
183
+ success: false,
184
+ error: finalError,
185
+ });
147
186
  }
148
187
  /**
149
188
  * Check whether the last commit on a worktree's branch is older than
@@ -177,4 +216,32 @@ function isWorktreeIdle(worktreePath, thresholdDays) {
177
216
  return false;
178
217
  }
179
218
  }
219
+ /**
220
+ * Build a git-aware prune plan via the `worktrunk-core` SDK (T10203).
221
+ *
222
+ * Wraps `napi.pruneWorktrees` with the integration-target branch the caller
223
+ * expects. Returns `null` when the underlying call fails (the napi layer
224
+ * raises on bare repos, detached HEAD on main, or empty worktree lists) so
225
+ * the legacy filesystem-scan path stays unaffected.
226
+ *
227
+ * Currently advisory: the result is exposed for callers that want the
228
+ * SDK-classified merge-state, but {@link pruneWorktrees} still drives removal
229
+ * from the XDG layout because preserveTaskIds + idleDays semantics live
230
+ * outside the SDK boundary.
231
+ *
232
+ * @param gitRoot - Absolute path to the git repository root.
233
+ * @param integrationTarget - Branch name to test "is merged" against
234
+ * (typically `main` or `master`).
235
+ * @returns The SDK plan, or `null` when the napi call cannot be issued.
236
+ *
237
+ * @task T10204
238
+ */
239
+ export function buildGitAwarePrunePlan(gitRoot, integrationTarget) {
240
+ try {
241
+ return napiPrune({ repoRoot: gitRoot, integrationTarget });
242
+ }
243
+ catch {
244
+ return null;
245
+ }
246
+ }
180
247
  //# sourceMappingURL=worktree-prune.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worktree-prune.js","sourceRoot":"","sources":["../src/worktree-prune.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worktree-prune.js","sourceRoot":"","sources":["../src/worktree-prune.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/worktree",
3
- "version": "2026.5.103",
3
+ "version": "2026.5.105",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Native CLEO worktree backend SDK — createWorktree, destroyWorktree, listWorktrees, pruneWorktrees with XDG path canon and declarative hooks (T1161)",
@@ -30,15 +30,17 @@
30
30
  "author": "CLEO Code <hello@cleocode.dev>",
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@cleocode/contracts": "2026.5.103",
34
- "@cleocode/worktree-napi": "2026.5.103",
35
- "@cleocode/paths": "2026.5.103"
33
+ "@cleocode/contracts": "2026.5.105",
34
+ "@cleocode/paths": "2026.5.105"
35
+ },
36
+ "optionalDependencies": {
37
+ "@cleocode/worktree-napi": "2026.5.105"
36
38
  },
37
39
  "devDependencies": {
38
40
  "@types/node": "^24.3.0",
39
41
  "typescript": "^6.0.2",
40
42
  "vitest": "^4.1.4",
41
- "@cleocode/core": "2026.5.103"
43
+ "@cleocode/core": "2026.5.105"
42
44
  },
43
45
  "repository": {
44
46
  "type": "git",