@cleocode/worktree 2026.5.38 → 2026.5.40

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.
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copy-on-write file utility for `@cleocode/worktree`.
3
+ *
4
+ * Provides efficient path copying using filesystem-level copy-on-write
5
+ * (reflink / clonefile) when available, falling back to regular recursive copy.
6
+ *
7
+ * Platform support:
8
+ * - macOS (darwin): APFS clonefile via `cp -cR`
9
+ * - Linux: btrfs / xfs / zfs reflink via `cp -R --reflink=auto`
10
+ * - Windows: `fs.copyFile` with `COPYFILE_FICLONE` (Node 24+) for files,
11
+ * regular recursive copy for directories
12
+ *
13
+ * @task T1161
14
+ */
15
+ /**
16
+ * Copy multiple paths from a source directory to a target directory using
17
+ * copy-on-write when available.
18
+ *
19
+ * Each path in `paths` is treated as relative to `sourceDir` and copied to
20
+ * the corresponding location under `targetDir`.
21
+ *
22
+ * Missing source paths are skipped with a warning written to `stderr`.
23
+ * Existing target paths are skipped without overwriting.
24
+ *
25
+ * If a copy-on-write attempt fails, a regular recursive copy is attempted
26
+ * as fallback. If that also fails, the path is recorded in `failed`.
27
+ *
28
+ * @param paths - Array of relative paths to copy.
29
+ * @param sourceDir - Absolute path to the source directory.
30
+ * @param targetDir - Absolute path to the target directory.
31
+ * @returns Object with arrays of successfully copied and failed paths.
32
+ */
33
+ export declare function copyPathsWithReflock(paths: string[], sourceDir: string, targetDir: string): Promise<{
34
+ copied: string[];
35
+ failed: string[];
36
+ }>;
37
+ //# sourceMappingURL=copy-on-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-on-write.d.ts","sourceRoot":"","sources":["../src/copy-on-write.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAyCjD"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Copy-on-write file utility for `@cleocode/worktree`.
3
+ *
4
+ * Provides efficient path copying using filesystem-level copy-on-write
5
+ * (reflink / clonefile) when available, falling back to regular recursive copy.
6
+ *
7
+ * Platform support:
8
+ * - macOS (darwin): APFS clonefile via `cp -cR`
9
+ * - Linux: btrfs / xfs / zfs reflink via `cp -R --reflink=auto`
10
+ * - Windows: `fs.copyFile` with `COPYFILE_FICLONE` (Node 24+) for files,
11
+ * regular recursive copy for directories
12
+ *
13
+ * @task T1161
14
+ */
15
+ import { execFile } from 'node:child_process';
16
+ import { constants, existsSync, promises as fs, mkdirSync } from 'node:fs';
17
+ import { dirname, join } from 'node:path';
18
+ import { promisify } from 'node:util';
19
+ const execFileAsync = promisify(execFile);
20
+ /**
21
+ * Copy multiple paths from a source directory to a target directory using
22
+ * copy-on-write when available.
23
+ *
24
+ * Each path in `paths` is treated as relative to `sourceDir` and copied to
25
+ * the corresponding location under `targetDir`.
26
+ *
27
+ * Missing source paths are skipped with a warning written to `stderr`.
28
+ * Existing target paths are skipped without overwriting.
29
+ *
30
+ * If a copy-on-write attempt fails, a regular recursive copy is attempted
31
+ * as fallback. If that also fails, the path is recorded in `failed`.
32
+ *
33
+ * @param paths - Array of relative paths to copy.
34
+ * @param sourceDir - Absolute path to the source directory.
35
+ * @param targetDir - Absolute path to the target directory.
36
+ * @returns Object with arrays of successfully copied and failed paths.
37
+ */
38
+ export async function copyPathsWithReflock(paths, sourceDir, targetDir) {
39
+ const copied = [];
40
+ const failed = [];
41
+ for (const relativePath of paths) {
42
+ const sourcePath = join(sourceDir, relativePath);
43
+ const targetPath = join(targetDir, relativePath);
44
+ if (!existsSync(sourcePath)) {
45
+ process.stderr.write(`[copy-on-write] skipping missing source: ${sourcePath}\n`);
46
+ continue;
47
+ }
48
+ if (existsSync(targetPath)) {
49
+ continue;
50
+ }
51
+ try {
52
+ mkdirSync(dirname(targetPath), { recursive: true });
53
+ }
54
+ catch {
55
+ process.stderr.write(`[copy-on-write] failed to create parent directory for: ${targetPath}\n`);
56
+ failed.push(relativePath);
57
+ continue;
58
+ }
59
+ try {
60
+ await copyWithReflock(sourcePath, targetPath);
61
+ copied.push(relativePath);
62
+ }
63
+ catch {
64
+ try {
65
+ await copyRegular(sourcePath, targetPath);
66
+ copied.push(relativePath);
67
+ }
68
+ catch {
69
+ failed.push(relativePath);
70
+ }
71
+ }
72
+ }
73
+ return { copied, failed };
74
+ }
75
+ /**
76
+ * Attempt a copy-on-write copy from source to target.
77
+ *
78
+ * @param sourcePath - Absolute path to the source file or directory.
79
+ * @param targetPath - Absolute path to the target location.
80
+ * @throws Error if the copy operation fails or the platform is unsupported.
81
+ */
82
+ async function copyWithReflock(sourcePath, targetPath) {
83
+ const platform = process.platform;
84
+ if (platform === 'darwin') {
85
+ await execFileAsync('cp', ['-cR', sourcePath, targetPath]);
86
+ return;
87
+ }
88
+ if (platform === 'linux') {
89
+ await execFileAsync('cp', ['-R', '--reflink=auto', sourcePath, targetPath]);
90
+ return;
91
+ }
92
+ if (platform === 'win32') {
93
+ const stat = await fs.stat(sourcePath);
94
+ if (stat.isDirectory()) {
95
+ throw new Error('Windows directories do not support copy-on-write');
96
+ }
97
+ await fs.copyFile(sourcePath, targetPath, constants.COPYFILE_FICLONE);
98
+ return;
99
+ }
100
+ throw new Error(`Unsupported platform: ${platform}`);
101
+ }
102
+ /**
103
+ * Perform a regular recursive copy as fallback.
104
+ *
105
+ * @param sourcePath - Absolute path to the source file or directory.
106
+ * @param targetPath - Absolute path to the target location.
107
+ * @throws Error if the copy operation fails.
108
+ */
109
+ async function copyRegular(sourcePath, targetPath) {
110
+ const stat = await fs.stat(sourcePath);
111
+ if (stat.isDirectory()) {
112
+ await fs.cp(sourcePath, targetPath, { recursive: true });
113
+ }
114
+ else {
115
+ await fs.copyFile(sourcePath, targetPath);
116
+ }
117
+ }
118
+ //# sourceMappingURL=copy-on-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-on-write.js","sourceRoot":"","sources":["../src/copy-on-write.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -23,6 +23,7 @@
23
23
  export type { CreateWorktreeOptions, CreateWorktreeResult, DestroyWorktreeOptions, DestroyWorktreeResult, ListWorktreesOptions, PruneWorktreesOptions, PruneWorktreesResult, WorktreeHook, WorktreeHookResult, WorktreeIncludePattern, WorktreeListEntry, } from '@cleocode/contracts';
24
24
  export type { LegacyMergeResult, LegacyWorktreeConfig, LegacyWorktreeEntry, LegacyWorktreeHandle, LegacyWorktreeRequest, } from './compat.js';
25
25
  export { legacyCreateWorktree, legacyListWorktrees, legacyMergeWorktree, legacyResolveWorktreeRoot, } from './compat.js';
26
+ export { copyPathsWithReflock } from './copy-on-write.js';
26
27
  export { createWorktree } from './worktree-create.js';
27
28
  export { destroyWorktree } from './worktree-destroy.js';
28
29
  export { runWorktreeHooks } from './worktree-hooks.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -21,6 +21,7 @@
21
21
  * @adr ADR-055
22
22
  */
23
23
  export { legacyCreateWorktree, legacyListWorktrees, legacyMergeWorktree, legacyResolveWorktreeRoot, } from './compat.js';
24
+ export { copyPathsWithReflock } from './copy-on-write.js';
24
25
  export { createWorktree } from './worktree-create.js';
25
26
  export { destroyWorktree } from './worktree-destroy.js';
26
27
  export { runWorktreeHooks } from './worktree-hooks.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAwBH,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAwBH,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
@@ -12,20 +12,37 @@
12
12
  *
13
13
  * @task T1161
14
14
  */
15
- import type { CreateWorktreeOptions, CreateWorktreeResult } from '@cleocode/contracts';
15
+ import type { CreateWorktreeOptions, CreateWorktreeResult, WorktreeHookResult } from '@cleocode/contracts';
16
+ /**
17
+ * Extended result type including the bootstrap field.
18
+ *
19
+ * The contracts package will be updated separately to add this field to
20
+ * {@link CreateWorktreeResult}; this local extension allows the implementation
21
+ * to compile in the interim.
22
+ */
23
+ interface CreateWorktreeResultWithBootstrap extends CreateWorktreeResult {
24
+ bootstrap: {
25
+ copiedPaths: string[];
26
+ failedPaths: string[];
27
+ hookResults: WorktreeHookResult[];
28
+ };
29
+ }
16
30
  /**
17
31
  * Create a git worktree for an agent task.
18
32
  *
19
33
  * Steps:
20
34
  * 1. Resolve paths and project hash from the project root.
21
- * 2. Remove stale worktree at the same path if it exists.
35
+ * 2. Remove stale worktree at the same path if it exists (dirty worktrees are preserved).
22
36
  * 3. If `task/<taskId>` branch already exists (leftover from a prior aborted
23
37
  * spawn), attach to it via `git worktree add <path> <branch>` (no `-b`).
24
38
  * Otherwise create a new branch via `git worktree add -b <branch> <path> <baseRef>`.
25
39
  * 4. Optionally apply `git worktree lock` to prevent pruning.
26
40
  * 5. Run declarative `post-create` hooks.
27
41
  * 6. Apply `.cleo/worktree-include` glob patterns (symlinks).
28
- * 7. Build and return the {@link CreateWorktreeResult}.
42
+ * 7. Copy `node_modules` and `packages/ * /dist` via copy-on-write when not already
43
+ * covered by worktree-include patterns.
44
+ * 8. Run declarative `post-start` hooks.
45
+ * 9. Build and return the {@link CreateWorktreeResult}.
29
46
  *
30
47
  * Branch-reuse semantics: when a prior spawn aborted after creating the branch
31
48
  * but before the worker committed anything, the branch still points to
@@ -41,5 +58,6 @@ import type { CreateWorktreeOptions, CreateWorktreeResult } from '@cleocode/cont
41
58
  * @task T1161
42
59
  * @task T1878
43
60
  */
44
- export declare function createWorktree(projectRoot: string, options: CreateWorktreeOptions): Promise<CreateWorktreeResult>;
61
+ export declare function createWorktree(projectRoot: string, options: CreateWorktreeOptions): Promise<CreateWorktreeResultWithBootstrap>;
62
+ export {};
45
63
  //# sourceMappingURL=worktree-create.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worktree-create.d.ts","sourceRoot":"","sources":["../src/worktree-create.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAUvF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAsH/B"}
1
+ {"version":3,"file":"worktree-create.d.ts","sourceRoot":"","sources":["../src/worktree-create.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAEnB,MAAM,qBAAqB,CAAC;AAG7B;;;;;;GAMG;AACH,UAAU,iCAAkC,SAAQ,oBAAoB;IACtE,SAAS,EAAE;QACT,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,WAAW,EAAE,kBAAkB,EAAE,CAAC;KACnC,CAAC;CACH;AAiCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,iCAAiC,CAAC,CAmK5C"}
@@ -12,25 +12,53 @@
12
12
  *
13
13
  * @task T1161
14
14
  */
15
- import { existsSync, mkdirSync, rmSync } from 'node:fs';
15
+ import { existsSync, mkdirSync, readdirSync, rmSync } from 'node:fs';
16
16
  import { join } from 'node:path';
17
+ import { copyPathsWithReflock } from './copy-on-write.js';
17
18
  import { getGitRoot, gitSilent, gitSync, resolveHeadRef } from './git.js';
18
19
  import { computeProjectHash, resolveTaskWorktreePath, resolveWorktreeRootForHash, } from './paths.js';
19
20
  import { runWorktreeHooks } from './worktree-hooks.js';
20
21
  import { applyIncludePatterns, loadWorktreeIncludePatterns } from './worktree-include.js';
22
+ function isPathSpecifiedInInclude(patterns, targetPath) {
23
+ return patterns.some((p) => {
24
+ if (p.negated)
25
+ return false;
26
+ if (p.pattern === targetPath)
27
+ return true;
28
+ if (p.pattern.startsWith(`${targetPath}/`))
29
+ return true;
30
+ if (targetPath.startsWith(`${p.pattern}/`))
31
+ return true;
32
+ return false;
33
+ });
34
+ }
35
+ function isPackagesDistSpecifiedInInclude(patterns) {
36
+ return patterns.some((p) => {
37
+ if (p.negated)
38
+ return false;
39
+ if (p.pattern === 'packages/*/dist')
40
+ return true;
41
+ if (p.pattern.startsWith('packages/') && p.pattern.includes('/dist'))
42
+ return true;
43
+ return false;
44
+ });
45
+ }
21
46
  /**
22
47
  * Create a git worktree for an agent task.
23
48
  *
24
49
  * Steps:
25
50
  * 1. Resolve paths and project hash from the project root.
26
- * 2. Remove stale worktree at the same path if it exists.
51
+ * 2. Remove stale worktree at the same path if it exists (dirty worktrees are preserved).
27
52
  * 3. If `task/<taskId>` branch already exists (leftover from a prior aborted
28
53
  * spawn), attach to it via `git worktree add <path> <branch>` (no `-b`).
29
54
  * Otherwise create a new branch via `git worktree add -b <branch> <path> <baseRef>`.
30
55
  * 4. Optionally apply `git worktree lock` to prevent pruning.
31
56
  * 5. Run declarative `post-create` hooks.
32
57
  * 6. Apply `.cleo/worktree-include` glob patterns (symlinks).
33
- * 7. Build and return the {@link CreateWorktreeResult}.
58
+ * 7. Copy `node_modules` and `packages/ * /dist` via copy-on-write when not already
59
+ * covered by worktree-include patterns.
60
+ * 8. Run declarative `post-start` hooks.
61
+ * 9. Build and return the {@link CreateWorktreeResult}.
34
62
  *
35
63
  * Branch-reuse semantics: when a prior spawn aborted after creating the branch
36
64
  * but before the worker committed anything, the branch still points to
@@ -57,15 +85,22 @@ export async function createWorktree(projectRoot, options) {
57
85
  const baseRef = options.baseRef ?? resolveHeadRef(gitRoot);
58
86
  const worktreePath = resolveTaskWorktreePath(projectHash, taskId);
59
87
  // Remove stale worktree at this path if it exists (left from a prior run).
88
+ // Dirty worktrees are preserved to avoid losing uncommitted agent work.
60
89
  if (existsSync(worktreePath)) {
61
- gitSilent(['worktree', 'unlock', worktreePath], gitRoot);
62
- if (!gitSilent(['worktree', 'remove', '--force', worktreePath], gitRoot)) {
63
- rmSync(worktreePath, { recursive: true, force: true });
90
+ const porcelain = gitSync(['status', '--porcelain'], worktreePath);
91
+ if (porcelain.trim() !== '') {
92
+ process.stderr.write(`[worktree] WARNING: preserving dirty worktree at ${worktreePath} (uncommitted changes detected)\n`);
93
+ }
94
+ else {
95
+ gitSilent(['worktree', 'unlock', worktreePath], gitRoot);
96
+ if (!gitSilent(['worktree', 'remove', '--force', worktreePath], gitRoot)) {
97
+ rmSync(worktreePath, { recursive: true, force: true });
98
+ }
99
+ // Best-effort: delete the stale branch so we always start fresh when the
100
+ // directory existed (the branch-reuse path below handles the case where
101
+ // only the branch survives without a directory).
102
+ gitSilent(['branch', '-D', branch], gitRoot);
64
103
  }
65
- // Best-effort: delete the stale branch so we always start fresh when the
66
- // directory existed (the branch-reuse path below handles the case where
67
- // only the branch survives without a directory).
68
- gitSilent(['branch', '-D', branch], gitRoot);
69
104
  }
70
105
  // Check whether the branch already exists without a worktree directory.
71
106
  // This happens when a prior spawn created the branch but the worktree
@@ -99,13 +134,36 @@ export async function createWorktree(projectRoot, options) {
99
134
  }
100
135
  const createdAt = new Date().toISOString();
101
136
  // Run post-create hooks before returning the handle.
102
- const hookResults = await runWorktreeHooks(hooks, 'post-create', worktreePath);
137
+ const postCreateHookResults = await runWorktreeHooks(hooks, 'post-create', worktreePath);
103
138
  // Apply .cleo/worktree-include patterns.
104
139
  let appliedPatterns = [];
105
140
  if (applyInclude) {
106
141
  const patterns = loadWorktreeIncludePatterns(projectRoot);
107
142
  appliedPatterns = applyIncludePatterns(patterns, projectRoot, worktreePath);
108
143
  }
144
+ // Copy-on-write bootstrap: node_modules and packages/*/dist when not already
145
+ // specified in .cleo/worktree-include.
146
+ const pathsToCopy = [];
147
+ const includePatterns = applyInclude ? loadWorktreeIncludePatterns(projectRoot) : [];
148
+ if (!isPathSpecifiedInInclude(includePatterns, 'node_modules')) {
149
+ pathsToCopy.push('node_modules');
150
+ }
151
+ if (!isPackagesDistSpecifiedInInclude(includePatterns)) {
152
+ const packagesDir = join(projectRoot, 'packages');
153
+ if (existsSync(packagesDir)) {
154
+ for (const entry of readdirSync(packagesDir, { withFileTypes: true })) {
155
+ if (!entry.isDirectory())
156
+ continue;
157
+ const distRel = join('packages', entry.name, 'dist');
158
+ if (existsSync(join(projectRoot, distRel))) {
159
+ pathsToCopy.push(distRel);
160
+ }
161
+ }
162
+ }
163
+ }
164
+ const { copied: copiedPaths, failed: failedPaths } = await copyPathsWithReflock(pathsToCopy, projectRoot, worktreePath);
165
+ // Run post-start hooks after copy-on-write bootstrap.
166
+ const postStartHookResults = await runWorktreeHooks(hooks, 'post-start', worktreePath);
109
167
  // Build env vars for agent spawn.
110
168
  const currentPath = process.env['PATH'] ?? '';
111
169
  const shimDir = join(projectRoot, '.cleo', 'bin', 'git-shim');
@@ -149,8 +207,13 @@ export async function createWorktree(projectRoot, options) {
149
207
  reused,
150
208
  envVars,
151
209
  preamble,
152
- hookResults,
210
+ hookResults: postCreateHookResults,
153
211
  appliedPatterns,
212
+ bootstrap: {
213
+ copiedPaths,
214
+ failedPaths,
215
+ hookResults: postStartHookResults,
216
+ },
154
217
  };
155
218
  }
156
219
  //# sourceMappingURL=worktree-create.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worktree-create.js","sourceRoot":"","sources":["../src/worktree-create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worktree-create.js","sourceRoot":"","sources":["../src/worktree-create.ts"],"names":[],"mappings":"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"}
@@ -14,9 +14,12 @@ import type { DestroyWorktreeOptions, DestroyWorktreeResult } from '@cleocode/co
14
14
  * Destroy the git worktree for a task.
15
15
  *
16
16
  * Steps:
17
- * 1. Unlock the worktree (`git worktree unlock`).
18
- * 2. Remove the worktree directory (`git worktree remove --force`).
19
- * 3. Optionally delete the task branch.
17
+ * 1. Check for uncommitted changes (dirty detection).
18
+ * 2. Run pre-remove hooks.
19
+ * 3. Unlock the worktree (`git worktree unlock`).
20
+ * 4. Remove the worktree directory (`git worktree remove --force`).
21
+ * 5. Optionally delete the task branch.
22
+ * 6. Run post-destroy hooks.
20
23
  *
21
24
  * Integration (merging commits back to the target branch) is performed by
22
25
  * `completeAgentWorktreeViaMerge` before this function is called. Non-fatal
@@ -30,5 +33,5 @@ import type { DestroyWorktreeOptions, DestroyWorktreeResult } from '@cleocode/co
30
33
  * @task T1161
31
34
  * @adr ADR-062
32
35
  */
33
- export declare function destroyWorktree(projectRoot: string, options: DestroyWorktreeOptions): DestroyWorktreeResult;
36
+ export declare function destroyWorktree(projectRoot: string, options: DestroyWorktreeOptions): Promise<DestroyWorktreeResult>;
34
37
  //# sourceMappingURL=worktree-destroy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worktree-destroy.d.ts","sourceRoot":"","sources":["../src/worktree-destroy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAIzF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,qBAAqB,CAiDvB"}
1
+ {"version":3,"file":"worktree-destroy.d.ts","sourceRoot":"","sources":["../src/worktree-destroy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAKzF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CA0GhC"}
@@ -12,13 +12,17 @@
12
12
  import { existsSync, rmSync } from 'node:fs';
13
13
  import { getGitRoot, gitSilent, gitSync } from './git.js';
14
14
  import { computeProjectHash, resolveTaskWorktreePath } from './paths.js';
15
+ import { runWorktreeHooks } from './worktree-hooks.js';
15
16
  /**
16
17
  * Destroy the git worktree for a task.
17
18
  *
18
19
  * Steps:
19
- * 1. Unlock the worktree (`git worktree unlock`).
20
- * 2. Remove the worktree directory (`git worktree remove --force`).
21
- * 3. Optionally delete the task branch.
20
+ * 1. Check for uncommitted changes (dirty detection).
21
+ * 2. Run pre-remove hooks.
22
+ * 3. Unlock the worktree (`git worktree unlock`).
23
+ * 4. Remove the worktree directory (`git worktree remove --force`).
24
+ * 5. Optionally delete the task branch.
25
+ * 6. Run post-destroy hooks.
22
26
  *
23
27
  * Integration (merging commits back to the target branch) is performed by
24
28
  * `completeAgentWorktreeViaMerge` before this function is called. Non-fatal
@@ -32,8 +36,8 @@ import { computeProjectHash, resolveTaskWorktreePath } from './paths.js';
32
36
  * @task T1161
33
37
  * @adr ADR-062
34
38
  */
35
- export function destroyWorktree(projectRoot, options) {
36
- const { taskId, deleteBranch = true } = options;
39
+ export async function destroyWorktree(projectRoot, options) {
40
+ const { taskId, deleteBranch = true, force = false, hooks = [] } = options;
37
41
  const gitRoot = getGitRoot(projectRoot);
38
42
  const projectHash = computeProjectHash(projectRoot);
39
43
  const worktreePath = resolveTaskWorktreePath(projectHash, taskId);
@@ -41,7 +45,50 @@ export function destroyWorktree(projectRoot, options) {
41
45
  let worktreeRemoved = false;
42
46
  let branchDeleted = false;
43
47
  let error;
44
- // Step 1: Unlock + remove the worktree.
48
+ const hookResults = [];
49
+ // Step 1: Dirty detection.
50
+ let dirty = false;
51
+ if (existsSync(worktreePath)) {
52
+ try {
53
+ const status = gitSync(['status', '--porcelain'], worktreePath);
54
+ dirty = status.length > 0;
55
+ }
56
+ catch {
57
+ // If git status fails, assume not dirty to avoid blocking cleanup.
58
+ dirty = false;
59
+ }
60
+ }
61
+ if (dirty && !force) {
62
+ return {
63
+ taskId,
64
+ worktreeRemoved: false,
65
+ branchDeleted: false,
66
+ error: 'Worktree has uncommitted changes - destroy aborted',
67
+ dirty,
68
+ force,
69
+ hookResults,
70
+ };
71
+ }
72
+ // Step 2: Run pre-remove hooks.
73
+ if (hooks.length > 0 && existsSync(worktreePath)) {
74
+ try {
75
+ const preRemoveResults = await runWorktreeHooks(hooks, 'pre-remove', worktreePath);
76
+ hookResults.push(...preRemoveResults);
77
+ }
78
+ catch (err) {
79
+ const message = err instanceof Error ? err.message : String(err);
80
+ return {
81
+ taskId,
82
+ worktreeRemoved: false,
83
+ branchDeleted: false,
84
+ error: `Pre-remove hook failed: ${message}`,
85
+ dirty,
86
+ force,
87
+ hookResults,
88
+ };
89
+ }
90
+ }
91
+ // Step 3: Unlock + remove the worktree.
45
92
  if (existsSync(worktreePath)) {
46
93
  gitSilent(['worktree', 'unlock', worktreePath], gitRoot);
47
94
  if (gitSilent(['worktree', 'remove', '--force', worktreePath], gitRoot)) {
@@ -62,7 +109,7 @@ export function destroyWorktree(projectRoot, options) {
62
109
  else {
63
110
  worktreeRemoved = true; // already gone
64
111
  }
65
- // Step 2: Optionally delete the branch.
112
+ // Step 4: Optionally delete the branch.
66
113
  if (deleteBranch) {
67
114
  try {
68
115
  const branchExists = gitSync(['branch', '--list', branch], gitRoot);
@@ -80,6 +127,19 @@ export function destroyWorktree(projectRoot, options) {
80
127
  else {
81
128
  branchDeleted = false;
82
129
  }
83
- return { taskId, worktreeRemoved, branchDeleted, error };
130
+ // Step 5: Run post-destroy hooks (in git root since worktree is gone).
131
+ if (hooks.length > 0) {
132
+ try {
133
+ const postDestroyResults = await runWorktreeHooks(hooks, 'post-destroy', gitRoot);
134
+ hookResults.push(...postDestroyResults);
135
+ }
136
+ catch (err) {
137
+ const message = err instanceof Error ? err.message : String(err);
138
+ if (!error) {
139
+ error = `Post-destroy hook failed: ${message}`;
140
+ }
141
+ }
142
+ }
143
+ return { taskId, worktreeRemoved, branchDeleted, error, dirty, force, hookResults };
84
144
  }
85
145
  //# sourceMappingURL=worktree-destroy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worktree-destroy.js","sourceRoot":"","sources":["../src/worktree-destroy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAEzE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,eAAe,CAC7B,WAAmB,EACnB,OAA+B;IAE/B,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEhD,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,QAAQ,MAAM,EAAE,CAAC;IAEhC,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,KAAyB,CAAC;IAE9B,wCAAwC;IACxC,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,SAAS,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;QACzD,IAAI,SAAS,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,EAAE,CAAC;YACxE,eAAe,GAAG,IAAI,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,MAAM,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvD,eAAe,GAAG,IAAI,CAAC;YACzB,CAAC;YAAC,OAAO,IAAI,EAAE,CAAC;gBACd,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,KAAK,GAAG,8BAA8B,IAAI,YAAY,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9F,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,eAAe,GAAG,IAAI,CAAC,CAAC,eAAe;IACzC,CAAC;IAED,wCAAwC;IACxC,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;YACpE,IAAI,YAAY,EAAE,CAAC;gBACjB,OAAO,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;YAC7C,CAAC;YACD,aAAa,GAAG,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,GAAG,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACzF,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;AAC3D,CAAC"}
1
+ {"version":3,"file":"worktree-destroy.js","sourceRoot":"","sources":["../src/worktree-destroy.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.38",
3
+ "version": "2026.5.40",
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,8 +30,8 @@
30
30
  "author": "CLEO Code <hello@cleocode.dev>",
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@cleocode/contracts": "2026.5.38",
34
- "@cleocode/paths": "2026.5.38"
33
+ "@cleocode/contracts": "2026.5.40",
34
+ "@cleocode/paths": "2026.5.40"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^24.3.0",