@yoavsh/treekeeper 0.0.0-stage → 0.1.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 (166) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +237 -2
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +165 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/archive.d.ts +3 -0
  9. package/dist/commands/archive.d.ts.map +1 -0
  10. package/dist/commands/archive.js +55 -0
  11. package/dist/commands/archive.js.map +1 -0
  12. package/dist/commands/config.d.ts +2 -0
  13. package/dist/commands/config.d.ts.map +1 -0
  14. package/dist/commands/config.js +54 -0
  15. package/dist/commands/config.js.map +1 -0
  16. package/dist/commands/context.d.ts +34 -0
  17. package/dist/commands/context.d.ts.map +1 -0
  18. package/dist/commands/context.js +53 -0
  19. package/dist/commands/context.js.map +1 -0
  20. package/dist/commands/daemon.d.ts +3 -0
  21. package/dist/commands/daemon.d.ts.map +1 -0
  22. package/dist/commands/daemon.js +81 -0
  23. package/dist/commands/daemon.js.map +1 -0
  24. package/dist/commands/doctor.d.ts +3 -0
  25. package/dist/commands/doctor.d.ts.map +1 -0
  26. package/dist/commands/doctor.js +119 -0
  27. package/dist/commands/doctor.js.map +1 -0
  28. package/dist/commands/gc.d.ts +3 -0
  29. package/dist/commands/gc.d.ts.map +1 -0
  30. package/dist/commands/gc.js +98 -0
  31. package/dist/commands/gc.js.map +1 -0
  32. package/dist/commands/status.d.ts +4 -0
  33. package/dist/commands/status.d.ts.map +1 -0
  34. package/dist/commands/status.js +52 -0
  35. package/dist/commands/status.js.map +1 -0
  36. package/dist/commands/watch.d.ts +10 -0
  37. package/dist/commands/watch.d.ts.map +1 -0
  38. package/dist/commands/watch.js +41 -0
  39. package/dist/commands/watch.js.map +1 -0
  40. package/dist/core/apply.d.ts +47 -0
  41. package/dist/core/apply.d.ts.map +1 -0
  42. package/dist/core/apply.js +223 -0
  43. package/dist/core/apply.js.map +1 -0
  44. package/dist/core/archive.d.ts +69 -0
  45. package/dist/core/archive.d.ts.map +1 -0
  46. package/dist/core/archive.js +202 -0
  47. package/dist/core/archive.js.map +1 -0
  48. package/dist/core/config.d.ts +69 -0
  49. package/dist/core/config.d.ts.map +1 -0
  50. package/dist/core/config.js +261 -0
  51. package/dist/core/config.js.map +1 -0
  52. package/dist/core/decide.d.ts +102 -0
  53. package/dist/core/decide.d.ts.map +1 -0
  54. package/dist/core/decide.js +148 -0
  55. package/dist/core/decide.js.map +1 -0
  56. package/dist/core/forge.d.ts +39 -0
  57. package/dist/core/forge.d.ts.map +1 -0
  58. package/dist/core/forge.js +190 -0
  59. package/dist/core/forge.js.map +1 -0
  60. package/dist/core/git.d.ts +63 -0
  61. package/dist/core/git.d.ts.map +1 -0
  62. package/dist/core/git.js +194 -0
  63. package/dist/core/git.js.map +1 -0
  64. package/dist/core/plan.d.ts +75 -0
  65. package/dist/core/plan.d.ts.map +1 -0
  66. package/dist/core/plan.js +288 -0
  67. package/dist/core/plan.js.map +1 -0
  68. package/dist/core/render.d.ts +14 -0
  69. package/dist/core/render.d.ts.map +1 -0
  70. package/dist/core/render.js +128 -0
  71. package/dist/core/render.js.map +1 -0
  72. package/dist/core/scan.d.ts +22 -0
  73. package/dist/core/scan.d.ts.map +1 -0
  74. package/dist/core/scan.js +99 -0
  75. package/dist/core/scan.js.map +1 -0
  76. package/dist/core/sessions.d.ts +37 -0
  77. package/dist/core/sessions.d.ts.map +1 -0
  78. package/dist/core/sessions.js +300 -0
  79. package/dist/core/sessions.js.map +1 -0
  80. package/dist/core/size.d.ts +3 -0
  81. package/dist/core/size.d.ts.map +1 -0
  82. package/dist/core/size.js +11 -0
  83. package/dist/core/size.js.map +1 -0
  84. package/dist/daemon/lock.d.ts +10 -0
  85. package/dist/daemon/lock.d.ts.map +1 -0
  86. package/dist/daemon/lock.js +64 -0
  87. package/dist/daemon/lock.js.map +1 -0
  88. package/dist/daemon/service.d.ts +34 -0
  89. package/dist/daemon/service.d.ts.map +1 -0
  90. package/dist/daemon/service.js +257 -0
  91. package/dist/daemon/service.js.map +1 -0
  92. package/dist/daemon/state.d.ts +19 -0
  93. package/dist/daemon/state.d.ts.map +1 -0
  94. package/dist/daemon/state.js +32 -0
  95. package/dist/daemon/state.js.map +1 -0
  96. package/dist/index.d.ts +26 -0
  97. package/dist/index.d.ts.map +1 -0
  98. package/dist/index.js +19 -0
  99. package/dist/index.js.map +1 -0
  100. package/dist/util/bytes.d.ts +4 -0
  101. package/dist/util/bytes.d.ts.map +1 -0
  102. package/dist/util/bytes.js +14 -0
  103. package/dist/util/bytes.js.map +1 -0
  104. package/dist/util/color.d.ts +16 -0
  105. package/dist/util/color.d.ts.map +1 -0
  106. package/dist/util/color.js +32 -0
  107. package/dist/util/color.js.map +1 -0
  108. package/dist/util/exec.d.ts +27 -0
  109. package/dist/util/exec.d.ts.map +1 -0
  110. package/dist/util/exec.js +57 -0
  111. package/dist/util/exec.js.map +1 -0
  112. package/dist/util/log.d.ts +29 -0
  113. package/dist/util/log.d.ts.map +1 -0
  114. package/dist/util/log.js +72 -0
  115. package/dist/util/log.js.map +1 -0
  116. package/dist/util/paths.d.ts +18 -0
  117. package/dist/util/paths.d.ts.map +1 -0
  118. package/dist/util/paths.js +87 -0
  119. package/dist/util/paths.js.map +1 -0
  120. package/dist/util/prompt.d.ts +3 -0
  121. package/dist/util/prompt.d.ts.map +1 -0
  122. package/dist/util/prompt.js +15 -0
  123. package/dist/util/prompt.js.map +1 -0
  124. package/dist/util/redact.d.ts +15 -0
  125. package/dist/util/redact.d.ts.map +1 -0
  126. package/dist/util/redact.js +44 -0
  127. package/dist/util/redact.js.map +1 -0
  128. package/dist/util/time.d.ts +13 -0
  129. package/dist/util/time.d.ts.map +1 -0
  130. package/dist/util/time.js +77 -0
  131. package/dist/util/time.js.map +1 -0
  132. package/docs/integrations.md +128 -0
  133. package/docs/safety.md +62 -0
  134. package/package.json +69 -4
  135. package/src/cli.ts +175 -0
  136. package/src/commands/archive.ts +72 -0
  137. package/src/commands/config.ts +57 -0
  138. package/src/commands/context.ts +86 -0
  139. package/src/commands/daemon.ts +86 -0
  140. package/src/commands/doctor.ts +131 -0
  141. package/src/commands/gc.ts +108 -0
  142. package/src/commands/status.ts +68 -0
  143. package/src/commands/watch.ts +48 -0
  144. package/src/core/apply.ts +276 -0
  145. package/src/core/archive.ts +269 -0
  146. package/src/core/config.ts +339 -0
  147. package/src/core/decide.ts +230 -0
  148. package/src/core/forge.ts +243 -0
  149. package/src/core/git.ts +254 -0
  150. package/src/core/plan.ts +431 -0
  151. package/src/core/render.ts +168 -0
  152. package/src/core/scan.ts +105 -0
  153. package/src/core/sessions.ts +339 -0
  154. package/src/core/size.ts +10 -0
  155. package/src/daemon/lock.ts +65 -0
  156. package/src/daemon/service.ts +321 -0
  157. package/src/daemon/state.ts +49 -0
  158. package/src/index.ts +36 -0
  159. package/src/util/bytes.ts +11 -0
  160. package/src/util/color.ts +33 -0
  161. package/src/util/exec.ts +80 -0
  162. package/src/util/log.ts +88 -0
  163. package/src/util/paths.ts +84 -0
  164. package/src/util/prompt.ts +13 -0
  165. package/src/util/redact.ts +43 -0
  166. package/src/util/time.ts +75 -0
@@ -0,0 +1,288 @@
1
+ import { stat } from "node:fs/promises";
2
+ import { basename } from "node:path";
3
+ import { loadRepoConfig } from "./config.js";
4
+ import { decideBranch, decideWorktree } from "./decide.js";
5
+ import { selectPr } from "./forge.js";
6
+ import * as git from "./git.js";
7
+ import { dirSizeKb } from "./size.js";
8
+ import { createActivityContext, detectActivity, isActive } from "./sessions.js";
9
+ import { isInside, matchGlob } from "../util/paths.js";
10
+ import { parseDuration } from "../util/time.js";
11
+ export function policyFromConfig(cfg, force = false) {
12
+ return {
13
+ minAgeMs: parseDuration(cfg.minAge),
14
+ closedPrGraceMs: parseDuration(cfg.closedPrGrace),
15
+ onDirty: cfg.onDirty,
16
+ onClosedPr: cfg.onClosedPr,
17
+ onExtraCommits: cfg.onExtraCommits,
18
+ force,
19
+ };
20
+ }
21
+ export async function buildPlan(opts) {
22
+ const now = opts.now ?? Date.now();
23
+ const cwd = opts.cwd ?? process.cwd();
24
+ const warnings = [];
25
+ const activity = await createActivityContext(opts.config, opts.logger, now);
26
+ const repos = [];
27
+ for (const repo of opts.repos) {
28
+ const repoPlan = await planRepo(repo, { ...opts, now, cwd }, activity, warnings);
29
+ repos.push(repoPlan);
30
+ }
31
+ if (opts.forge.unavailableReason)
32
+ warnings.push(opts.forge.unavailableReason);
33
+ return {
34
+ version: 1,
35
+ generatedAt: new Date(now).toISOString(),
36
+ now,
37
+ roots: opts.config.roots,
38
+ repos,
39
+ summary: summarize(repos),
40
+ warnings,
41
+ };
42
+ }
43
+ async function planRepo(repo, opts, activity, warnings) {
44
+ const name = basename(repo);
45
+ const { config: cfg, warnings: cfgWarnings } = await loadRepoConfig(repo, opts.config);
46
+ for (const w of cfgWarnings)
47
+ warnings.push(w);
48
+ const empty = {
49
+ repo, name, defaultBranch: "", forgeAvailable: false,
50
+ worktrees: [], branches: [], skipped: null,
51
+ };
52
+ if (!cfg.enabled)
53
+ return { ...empty, skipped: "disabled in .treekeeper.json" };
54
+ const policy = policyFromConfig(cfg, opts.force ?? false);
55
+ const defaultBranch = await git.defaultBranch(repo);
56
+ const prIndex = await opts.forge.lookup(repo);
57
+ const bases = await resolveBases(repo, defaultBranch);
58
+ const worktrees = await git.listWorktrees(repo);
59
+ if (worktrees.length === 0) {
60
+ return { ...empty, defaultBranch, skipped: "not a readable git repo" };
61
+ }
62
+ const wtCandidates = [];
63
+ for (const wt of worktrees) {
64
+ if (wt.bare)
65
+ continue;
66
+ if (opts.skipWorktrees) {
67
+ wtCandidates.push(skippedWorktree(repo, name, wt));
68
+ continue;
69
+ }
70
+ wtCandidates.push(await planWorktree(repo, name, wt, {
71
+ cfg, policy, bases, prIndex, activity, now: opts.now, cwd: opts.cwd,
72
+ allSizes: opts.allSizes ?? false, logger: opts.logger,
73
+ }));
74
+ }
75
+ const branches = cfg.pruneBranches
76
+ ? await planBranches(repo, name, {
77
+ cfg, policy, bases, prIndex, defaultBranch, worktrees, wtCandidates, now: opts.now,
78
+ })
79
+ : [];
80
+ return {
81
+ repo,
82
+ name,
83
+ defaultBranch,
84
+ forgeAvailable: prIndex !== null,
85
+ worktrees: wtCandidates,
86
+ branches,
87
+ skipped: null,
88
+ };
89
+ }
90
+ function skippedWorktree(repo, repoName, wt) {
91
+ return {
92
+ repo,
93
+ repoName,
94
+ path: wt.path,
95
+ branch: wt.branch,
96
+ head: wt.head,
97
+ sizeKb: null,
98
+ verdict: wt.isMain
99
+ ? { action: "keep", reason: "the repo's main worktree", code: "main-worktree", risks: [] }
100
+ : { action: "keep", reason: "worktrees not considered (--branches-only)", code: "branches-only", risks: [] },
101
+ merge: { kind: "no-branch" },
102
+ activity: null,
103
+ lastTouched: 0,
104
+ dirty: false,
105
+ dirtyCount: 0,
106
+ };
107
+ }
108
+ async function planWorktree(repo, repoName, wt, ctx) {
109
+ const merge = wt.isMain || wt.detached || !wt.branch
110
+ ? { kind: "no-branch" }
111
+ : await mergeStatus(repo, wt.branch, wt.head, ctx.bases, ctx.prIndex);
112
+ // Only pay for the expensive probes when the worktree could actually go.
113
+ const cheapKeep = wt.isMain || isProtectedPath(ctx.cfg, wt.path) || wt.locked;
114
+ const finished = isFinished(merge);
115
+ let dirty = false;
116
+ let dirtyCount = 0;
117
+ let hit = null;
118
+ let lastTouched = 0;
119
+ if (!cheapKeep) {
120
+ try {
121
+ const st = await stat(wt.path);
122
+ lastTouched = st.mtimeMs;
123
+ }
124
+ catch {
125
+ lastTouched = 0;
126
+ }
127
+ if (finished) {
128
+ const d = await git.dirtyState(wt.path);
129
+ dirty = d.dirty;
130
+ dirtyCount = d.count;
131
+ hit = await detectActivity(ctx.activity, wt.path);
132
+ if (hit)
133
+ lastTouched = Math.max(lastTouched, hit.lastActivity);
134
+ }
135
+ }
136
+ const facts = {
137
+ now: ctx.now,
138
+ isMain: wt.isMain,
139
+ detached: wt.detached,
140
+ locked: wt.locked,
141
+ lockReason: wt.lockReason,
142
+ branch: wt.branch,
143
+ protectedBranch: wt.branch !== null && isProtectedBranch(ctx.cfg, wt.branch),
144
+ protectedPath: isProtectedPath(ctx.cfg, wt.path),
145
+ isCwd: isInside(wt.path, ctx.cwd),
146
+ merge,
147
+ dirty,
148
+ dirtyCount,
149
+ activity: hit,
150
+ activityIsRecent: isActive(ctx.activity, hit),
151
+ lastTouched,
152
+ inUse: hit?.detector === "process" ||
153
+ (ctx.activity.processCwds?.some((p) => isInside(wt.path, p)) ?? false),
154
+ };
155
+ const verdict = decideWorktree(facts, ctx.policy);
156
+ const sizeKb = verdict.action === "reclaim" || ctx.allSizes ? await dirSizeKb(wt.path) : null;
157
+ return {
158
+ repo,
159
+ repoName,
160
+ path: wt.path,
161
+ branch: wt.branch,
162
+ head: wt.head,
163
+ sizeKb,
164
+ verdict,
165
+ merge,
166
+ activity: hit,
167
+ lastTouched,
168
+ dirty,
169
+ dirtyCount,
170
+ };
171
+ }
172
+ async function planBranches(repo, repoName, ctx) {
173
+ // Branches whose worktree survives this sweep must survive with it. Branches
174
+ // whose worktree is being reclaimed are deleted as part of that removal, so
175
+ // they are not listed here twice.
176
+ const keptByWorktree = new Set();
177
+ const removedWithWorktree = new Set();
178
+ for (const c of ctx.wtCandidates) {
179
+ if (!c.branch)
180
+ continue;
181
+ if (c.verdict.action === "reclaim")
182
+ removedWithWorktree.add(c.branch);
183
+ else
184
+ keptByWorktree.add(c.branch);
185
+ }
186
+ const mainWt = ctx.worktrees.find((w) => w.isMain);
187
+ const currentBranch = mainWt?.branch ?? null;
188
+ const out = [];
189
+ for (const branch of await git.localBranches(repo)) {
190
+ if (removedWithWorktree.has(branch.name))
191
+ continue;
192
+ const merge = await mergeStatus(repo, branch.name, branch.head, ctx.bases, ctx.prIndex);
193
+ const facts = {
194
+ now: ctx.now,
195
+ name: branch.name,
196
+ isDefault: branch.name === ctx.defaultBranch,
197
+ protectedBranch: isProtectedBranch(ctx.cfg, branch.name),
198
+ hasWorktree: keptByWorktree.has(branch.name),
199
+ isCurrent: branch.name === currentBranch,
200
+ merge,
201
+ lastCommit: null,
202
+ };
203
+ const verdict = decideBranch(facts, ctx.policy);
204
+ if (verdict.action === "reclaim") {
205
+ out.push({ repo, repoName, name: branch.name, head: branch.head, verdict, merge });
206
+ }
207
+ }
208
+ return out;
209
+ }
210
+ /** Candidate base refs for ancestry checks, remote first. */
211
+ async function resolveBases(repo, defaultBranch) {
212
+ const bases = [];
213
+ for (const ref of [`refs/remotes/origin/${defaultBranch}`, `refs/heads/${defaultBranch}`]) {
214
+ if (await git.refExists(repo, ref))
215
+ bases.push(ref);
216
+ }
217
+ return bases;
218
+ }
219
+ export async function mergeStatus(repo, branch, tip, bases, prIndex) {
220
+ const head = tip ?? (await git.revParse(repo, `refs/heads/${branch}`));
221
+ if (!head)
222
+ return { kind: "unmerged", forgeAvailable: prIndex !== null };
223
+ for (const base of bases) {
224
+ if (await git.isAncestor(repo, head, base)) {
225
+ return { kind: "merged-ancestor", base: base.replace(/^refs\/(remotes|heads)\//, "") };
226
+ }
227
+ }
228
+ const pr = selectPr(prIndex?.get(branch), head);
229
+ if (!pr)
230
+ return { kind: "unmerged", forgeAvailable: prIndex !== null };
231
+ if (pr.state === "MERGED") {
232
+ if (pr.headRefOid === head)
233
+ return { kind: "merged-pr", pr };
234
+ const base = bases[0];
235
+ const extra = base ? (await git.commitsNotIn(repo, base, branch)).length : 0;
236
+ return extra > 0 ? { kind: "merged-pr-extra", pr, extra } : { kind: "merged-pr", pr };
237
+ }
238
+ if (pr.state === "CLOSED")
239
+ return { kind: "closed-pr", pr };
240
+ return { kind: "open-pr", pr };
241
+ }
242
+ function isFinished(merge) {
243
+ return (merge.kind === "merged-ancestor" ||
244
+ merge.kind === "merged-pr" ||
245
+ merge.kind === "merged-pr-extra" ||
246
+ merge.kind === "closed-pr");
247
+ }
248
+ export function isProtectedBranch(cfg, branch) {
249
+ return cfg.protectBranches.some((p) => (p.includes("*") || p.includes("?") ? matchGlob(p, branch) : p === branch));
250
+ }
251
+ export function isProtectedPath(cfg, path) {
252
+ return cfg.protectPaths.some((p) => p.includes("*") || p.includes("?") ? matchGlob(p, path) : isInside(p, path));
253
+ }
254
+ function summarize(repos) {
255
+ let worktreesScanned = 0;
256
+ let worktreesReclaimable = 0;
257
+ let worktreesKept = 0;
258
+ let branchesDeletable = 0;
259
+ let reclaimKb = 0;
260
+ for (const r of repos) {
261
+ for (const w of r.worktrees) {
262
+ if (w.verdict.code === "main-worktree")
263
+ continue;
264
+ worktreesScanned += 1;
265
+ if (w.verdict.action === "reclaim") {
266
+ worktreesReclaimable += 1;
267
+ reclaimKb += w.sizeKb ?? 0;
268
+ }
269
+ else {
270
+ worktreesKept += 1;
271
+ }
272
+ }
273
+ branchesDeletable += r.branches.length;
274
+ }
275
+ return {
276
+ repos: repos.filter((r) => r.skipped === null).length,
277
+ worktreesScanned,
278
+ worktreesReclaimable,
279
+ worktreesKept,
280
+ branchesDeletable,
281
+ reclaimKb,
282
+ };
283
+ }
284
+ /** Every worktree the plan would remove, flattened. */
285
+ export function reclaimable(plan) {
286
+ return plan.repos.flatMap((r) => r.worktrees.filter((w) => w.verdict.action === "reclaim"));
287
+ }
288
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/core/plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ApplyResult } from "./apply.js";
2
+ import type { Plan } from "./plan.js";
3
+ export interface RenderOptions {
4
+ /** Show kept worktrees too (default: only when there are few). */
5
+ verbose?: boolean;
6
+ /** Only the summary line. */
7
+ quiet?: boolean;
8
+ }
9
+ /** The human-readable plan. */
10
+ export declare function renderPlan(plan: Plan, opts?: RenderOptions): string;
11
+ export declare function summaryLine(plan: Plan): string;
12
+ /** What actually happened, after `--apply`. */
13
+ export declare function renderApply(result: ApplyResult, plan: Plan): string;
14
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/core/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,IAAI,EAA+B,MAAM,WAAW,CAAC;AAKnE,MAAM,WAAW,aAAa;IAC5B,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,+BAA+B;AAC/B,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,GAAE,aAAkB,GAAG,MAAM,CAkBvE;AAgED,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAa9C;AAED,+CAA+C;AAC/C,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAuDnE"}
@@ -0,0 +1,128 @@
1
+ import { formatKb } from "../util/bytes.js";
2
+ import { color, padEndVisible, visibleWidth } from "../util/color.js";
3
+ import { shortenPath } from "../util/paths.js";
4
+ /** The human-readable plan. */
5
+ export function renderPlan(plan, opts = {}) {
6
+ const out = [];
7
+ if (opts.quiet)
8
+ return summaryLine(plan);
9
+ for (const repo of plan.repos) {
10
+ const block = renderRepo(repo, opts);
11
+ if (block.length > 0) {
12
+ out.push(...block, "");
13
+ }
14
+ }
15
+ for (const warning of plan.warnings) {
16
+ out.push(color.yellow(`note ${warning}`));
17
+ }
18
+ if (plan.warnings.length > 0)
19
+ out.push("");
20
+ out.push(summaryLine(plan));
21
+ return out.join("\n");
22
+ }
23
+ function renderRepo(repo, opts) {
24
+ if (repo.skipped) {
25
+ return opts.verbose ? [`${color.bold(repo.name)} ${color.gray(`skipped — ${repo.skipped}`)}`] : [];
26
+ }
27
+ const reclaim = repo.worktrees.filter((w) => w.verdict.action === "reclaim");
28
+ const kept = repo.worktrees.filter((w) => w.verdict.action === "keep" && w.verdict.code !== "main-worktree");
29
+ const showKept = opts.verbose ? kept : [];
30
+ if (reclaim.length === 0 && showKept.length === 0 && repo.branches.length === 0)
31
+ return [];
32
+ const rows = [];
33
+ for (const w of reclaim)
34
+ rows.push(row(w, true));
35
+ for (const w of showKept)
36
+ rows.push(row(w, false));
37
+ const widths = [0, 0, 0, 0];
38
+ for (const r of rows) {
39
+ for (let i = 0; i < 4; i += 1) {
40
+ widths[i] = Math.max(widths[i], visibleWidth(r[i]));
41
+ }
42
+ }
43
+ const head = `${color.bold(repo.name)} ${color.gray(`(${repo.defaultBranch})`)}${repo.forgeAvailable ? "" : color.gray(" [no PR data]")}`;
44
+ const lines = [head];
45
+ for (const r of rows) {
46
+ const cells = [
47
+ padEndVisible(r[0], widths[0]),
48
+ padEndVisible(r[1], widths[1]),
49
+ padEndVisible(r[2], widths[2]),
50
+ padEndVisible(r[3], widths[3]),
51
+ r[4],
52
+ ];
53
+ lines.push(` ${cells.join(" ").trimEnd()}`);
54
+ }
55
+ if (repo.branches.length > 0) {
56
+ const names = repo.branches.map((b) => b.name);
57
+ const shown = names.slice(0, 6).join(" ");
58
+ const more = names.length > 6 ? color.gray(` +${names.length - 6} more`) : "";
59
+ lines.push(` ${color.red("DELETE")} ${names.length} merged branch${names.length === 1 ? "" : "es"}: ${color.gray(shown)}${more}`);
60
+ }
61
+ return lines;
62
+ }
63
+ function row(w, reclaim) {
64
+ const action = reclaim ? color.red("RECLAIM") : color.gray("keep ");
65
+ const path = reclaim ? shortenPath(w.path) : color.gray(shortenPath(w.path));
66
+ const branch = w.branch ? color.cyan(`[${w.branch}]`) : color.gray("[detached]");
67
+ const size = w.sizeKb === null ? "" : (reclaim ? color.yellow(formatKb(w.sizeKb)) : color.gray(formatKb(w.sizeKb)));
68
+ const risks = w.verdict.risks.length > 0 ? color.yellow(` (${w.verdict.risks.join(", ")})`) : "";
69
+ const reason = (reclaim ? color.gray(w.verdict.reason) : color.gray(w.verdict.reason)) + risks;
70
+ return [action, path, branch, size, reason];
71
+ }
72
+ export function summaryLine(plan) {
73
+ const s = plan.summary;
74
+ if (s.worktreesReclaimable === 0 && s.branchesDeletable === 0) {
75
+ return color.green(`nothing to clean — ${s.worktreesScanned} worktree${s.worktreesScanned === 1 ? "" : "s"} across ${s.repos} repo${s.repos === 1 ? "" : "s"} all still in play`);
76
+ }
77
+ return [
78
+ `would reclaim ${color.bold(String(s.worktreesReclaimable))} worktree${s.worktreesReclaimable === 1 ? "" : "s"}`,
79
+ `(${color.bold(formatKb(s.reclaimKb))})`,
80
+ `and delete ${color.bold(String(s.branchesDeletable))} branch${s.branchesDeletable === 1 ? "" : "es"}`,
81
+ color.gray(`· ${s.worktreesKept} kept`),
82
+ ].join(" ");
83
+ }
84
+ /** What actually happened, after `--apply`. */
85
+ export function renderApply(result, plan) {
86
+ const out = [];
87
+ for (const r of result.removedWorktrees) {
88
+ const parts = [
89
+ color.green("reclaimed"),
90
+ shortenPath(r.path),
91
+ r.branch ? color.cyan(`[${r.branch}]`) : "",
92
+ color.yellow(formatKb(r.sizeKb)),
93
+ color.gray(`— ${r.reason}`),
94
+ ].filter((p) => p !== "");
95
+ out.push(parts.join(" "));
96
+ }
97
+ const branchOnly = result.deletedBranches.filter((b) => !result.removedWorktrees.some((w) => w.branch === b.name && w.repo === b.repo));
98
+ if (branchOnly.length > 0) {
99
+ out.push(`${color.green("deleted")} ${branchOnly.length} branch${branchOnly.length === 1 ? "" : "es"} ${color.gray(branchOnly.slice(0, 8).map((b) => b.name).join(" "))}`);
100
+ }
101
+ const archived = result.archives.filter((a) => a.bundle || a.patch || a.untracked);
102
+ if (archived.length > 0) {
103
+ out.push("");
104
+ out.push(color.gray(`archived unique work from ${archived.length} of them:`));
105
+ for (const a of archived.slice(0, 10)) {
106
+ const bits = [
107
+ a.bundle ? `${a.bundle.commits} commit${a.bundle.commits === 1 ? "" : "s"}` : null,
108
+ a.patch ? "uncommitted diff" : null,
109
+ a.untracked ? `${a.untracked.count} untracked` : null,
110
+ ].filter(Boolean);
111
+ out.push(color.gray(` ${shortenPath(a.dir)} (${bits.join(", ")})`));
112
+ }
113
+ }
114
+ for (const f of result.failures) {
115
+ out.push(color.yellow(`kept ${shortenPath(f.target)} — ${f.message}`));
116
+ }
117
+ if (out.length > 0)
118
+ out.push("");
119
+ const nothing = result.removedWorktrees.length === 0 && result.deletedBranches.length === 0;
120
+ out.push(nothing
121
+ ? color.green("nothing to clean")
122
+ : `${color.bold("reclaimed")} ${formatKb(result.reclaimedKb)} · ` +
123
+ `${result.removedWorktrees.length} worktree${result.removedWorktrees.length === 1 ? "" : "s"}, ` +
124
+ `${result.deletedBranches.length} branch${result.deletedBranches.length === 1 ? "" : "es"} · ` +
125
+ color.gray(`${plan.summary.worktreesKept} kept`));
126
+ return out.join("\n");
127
+ }
128
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/core/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Logger } from "../util/log.js";
2
+ export interface ScanOptions {
3
+ roots: string[];
4
+ maxDepth: number;
5
+ protectPaths?: string[];
6
+ logger?: Logger;
7
+ }
8
+ /**
9
+ * Find the main worktree of every git repo under `roots`.
10
+ *
11
+ * A linked worktree found during the walk resolves to its parent clone, so a
12
+ * repo is discovered whether the root holds the clone, the worktrees, or both.
13
+ */
14
+ export declare function discoverRepos(opts: ScanOptions): Promise<string[]>;
15
+ /**
16
+ * Resolve the repos implied by explicit CLI paths. A path inside a repo or
17
+ * worktree resolves to that repo; a plain directory is scanned shallowly.
18
+ */
19
+ export declare function reposFromPaths(paths: string[], opts: Omit<ScanOptions, "roots">): Promise<string[]>;
20
+ /** True when any root contains the given path — used to sanity-check config. */
21
+ export declare function underAnyRoot(roots: string[], path: string): boolean;
22
+ //# sourceMappingURL=scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../src/core/scan.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAS7C,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAsDxE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAazG;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnE"}
@@ -0,0 +1,99 @@
1
+ import { readdir, stat } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { isGitRepo, mainRepoPath } from "./git.js";
4
+ import { isInside, matchAnyGlob } from "../util/paths.js";
5
+ /** Directories never worth descending into when hunting for repos. */
6
+ const SKIP_DIRS = new Set([
7
+ "node_modules", ".git", ".svn", ".hg", "vendor", "target", "dist", "build",
8
+ ".next", ".nuxt", ".venv", "venv", "__pycache__", ".cache", ".pnpm-store",
9
+ "Library", "Applications", ".Trash", ".cargo", ".rustup", ".gradle", ".m2",
10
+ ]);
11
+ /**
12
+ * Find the main worktree of every git repo under `roots`.
13
+ *
14
+ * A linked worktree found during the walk resolves to its parent clone, so a
15
+ * repo is discovered whether the root holds the clone, the worktrees, or both.
16
+ */
17
+ export async function discoverRepos(opts) {
18
+ const found = new Set();
19
+ const seen = new Set();
20
+ const walk = async (dir, depth) => {
21
+ if (seen.has(dir))
22
+ return;
23
+ seen.add(dir);
24
+ if (opts.protectPaths && matchAnyGlob(opts.protectPaths, dir))
25
+ return;
26
+ let entries;
27
+ try {
28
+ entries = await readdir(dir, { withFileTypes: true });
29
+ }
30
+ catch (err) {
31
+ const code = err.code;
32
+ if (code !== "ENOENT" && code !== "EACCES" && code !== "ENOTDIR" && code !== "EPERM") {
33
+ opts.logger?.debug(`scan: cannot read ${dir}: ${err.message}`);
34
+ }
35
+ return;
36
+ }
37
+ const hasGit = entries.some((e) => e.name === ".git");
38
+ if (hasGit) {
39
+ const main = await mainRepoPath(dir);
40
+ if (main) {
41
+ found.add(main);
42
+ // Stop here: `git worktree list` from the main repo enumerates the rest,
43
+ // and nested repos inside a checkout are not ours to garbage-collect.
44
+ return;
45
+ }
46
+ }
47
+ if (depth >= opts.maxDepth)
48
+ return;
49
+ for (const entry of entries) {
50
+ if (!entry.isDirectory() && !entry.isSymbolicLink())
51
+ continue;
52
+ if (entry.name.startsWith(".") && entry.name !== ".worktrees")
53
+ continue;
54
+ if (SKIP_DIRS.has(entry.name))
55
+ continue;
56
+ const child = join(dir, entry.name);
57
+ if (entry.isSymbolicLink()) {
58
+ // Follow a symlinked root one level, but never let a loop trap the walk.
59
+ try {
60
+ const st = await stat(child);
61
+ if (!st.isDirectory())
62
+ continue;
63
+ }
64
+ catch {
65
+ continue;
66
+ }
67
+ }
68
+ await walk(child, depth + 1);
69
+ }
70
+ };
71
+ for (const root of opts.roots) {
72
+ await walk(root, 0);
73
+ }
74
+ return [...found].sort();
75
+ }
76
+ /**
77
+ * Resolve the repos implied by explicit CLI paths. A path inside a repo or
78
+ * worktree resolves to that repo; a plain directory is scanned shallowly.
79
+ */
80
+ export async function reposFromPaths(paths, opts) {
81
+ const out = new Set();
82
+ for (const p of paths) {
83
+ if (await isGitRepo(p)) {
84
+ const main = await mainRepoPath(p);
85
+ if (main) {
86
+ out.add(main);
87
+ continue;
88
+ }
89
+ }
90
+ for (const repo of await discoverRepos({ ...opts, roots: [p] }))
91
+ out.add(repo);
92
+ }
93
+ return [...out].sort();
94
+ }
95
+ /** True when any root contains the given path — used to sanity-check config. */
96
+ export function underAnyRoot(roots, path) {
97
+ return roots.some((r) => isInside(r, path));
98
+ }
99
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../src/core/scan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Config, SessionCommand } from "./config.js";
2
+ import type { Logger } from "../util/log.js";
3
+ export interface ActivityHit {
4
+ /** Which detector saw it: "claude-code", "process", "mtime", … */
5
+ detector: string;
6
+ /** Epoch ms of the most recent activity. */
7
+ lastActivity: number;
8
+ detail: string;
9
+ }
10
+ export interface ActivityContext {
11
+ now: number;
12
+ graceMs: number;
13
+ detectors: Set<string>;
14
+ extraPaths: string[];
15
+ commands: SessionCommand[];
16
+ logger?: Logger;
17
+ /** Absolute paths that are the cwd of some live process; null when unknown. */
18
+ processCwds: string[] | null;
19
+ }
20
+ export declare function createActivityContext(cfg: Config, logger?: Logger, now?: number): Promise<ActivityContext>;
21
+ /**
22
+ * Is an agent (or a human) still working in this worktree?
23
+ *
24
+ * Detectors are deliberately layered: the harness-specific ones give a precise
25
+ * answer with a timestamp, while `process` and `mtime` are the catch-all that
26
+ * makes this work with harnesses treekeeper has never heard of.
27
+ */
28
+ export declare function detectActivity(ctx: ActivityContext, worktreePath: string): Promise<ActivityHit | null>;
29
+ /** `true` when the hit falls inside the session grace window. */
30
+ export declare function isActive(ctx: ActivityContext, hit: ActivityHit | null): boolean;
31
+ /**
32
+ * Claude Code stores one JSONL transcript per session under
33
+ * `~/.claude/projects/<slugified-cwd>/`, so the newest transcript mtime is the
34
+ * last time an agent did anything in that worktree.
35
+ */
36
+ export declare function claudeProjectSlugs(worktreePath: string): string[];
37
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/core/sessions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI7C,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC9B;AAYD,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,MAAM,EACf,GAAG,SAAa,GACf,OAAO,CAAC,eAAe,CAAC,CAe1B;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,eAAe,EACpB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA8D7B;AAED,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAG/E;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,CAIjE"}