@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.
- package/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +237 -2
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +165 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/archive.d.ts +3 -0
- package/dist/commands/archive.d.ts.map +1 -0
- package/dist/commands/archive.js +55 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +54 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/context.d.ts +34 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +53 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/daemon.d.ts +3 -0
- package/dist/commands/daemon.d.ts.map +1 -0
- package/dist/commands/daemon.js +81 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +119 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/gc.d.ts +3 -0
- package/dist/commands/gc.d.ts.map +1 -0
- package/dist/commands/gc.js +98 -0
- package/dist/commands/gc.js.map +1 -0
- package/dist/commands/status.d.ts +4 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +52 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/watch.d.ts +10 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +41 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/core/apply.d.ts +47 -0
- package/dist/core/apply.d.ts.map +1 -0
- package/dist/core/apply.js +223 -0
- package/dist/core/apply.js.map +1 -0
- package/dist/core/archive.d.ts +69 -0
- package/dist/core/archive.d.ts.map +1 -0
- package/dist/core/archive.js +202 -0
- package/dist/core/archive.js.map +1 -0
- package/dist/core/config.d.ts +69 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +261 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/decide.d.ts +102 -0
- package/dist/core/decide.d.ts.map +1 -0
- package/dist/core/decide.js +148 -0
- package/dist/core/decide.js.map +1 -0
- package/dist/core/forge.d.ts +39 -0
- package/dist/core/forge.d.ts.map +1 -0
- package/dist/core/forge.js +190 -0
- package/dist/core/forge.js.map +1 -0
- package/dist/core/git.d.ts +63 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +194 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/plan.d.ts +75 -0
- package/dist/core/plan.d.ts.map +1 -0
- package/dist/core/plan.js +288 -0
- package/dist/core/plan.js.map +1 -0
- package/dist/core/render.d.ts +14 -0
- package/dist/core/render.d.ts.map +1 -0
- package/dist/core/render.js +128 -0
- package/dist/core/render.js.map +1 -0
- package/dist/core/scan.d.ts +22 -0
- package/dist/core/scan.d.ts.map +1 -0
- package/dist/core/scan.js +99 -0
- package/dist/core/scan.js.map +1 -0
- package/dist/core/sessions.d.ts +37 -0
- package/dist/core/sessions.d.ts.map +1 -0
- package/dist/core/sessions.js +300 -0
- package/dist/core/sessions.js.map +1 -0
- package/dist/core/size.d.ts +3 -0
- package/dist/core/size.d.ts.map +1 -0
- package/dist/core/size.js +11 -0
- package/dist/core/size.js.map +1 -0
- package/dist/daemon/lock.d.ts +10 -0
- package/dist/daemon/lock.d.ts.map +1 -0
- package/dist/daemon/lock.js +64 -0
- package/dist/daemon/lock.js.map +1 -0
- package/dist/daemon/service.d.ts +34 -0
- package/dist/daemon/service.d.ts.map +1 -0
- package/dist/daemon/service.js +257 -0
- package/dist/daemon/service.js.map +1 -0
- package/dist/daemon/state.d.ts +19 -0
- package/dist/daemon/state.d.ts.map +1 -0
- package/dist/daemon/state.js +32 -0
- package/dist/daemon/state.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/util/bytes.d.ts +4 -0
- package/dist/util/bytes.d.ts.map +1 -0
- package/dist/util/bytes.js +14 -0
- package/dist/util/bytes.js.map +1 -0
- package/dist/util/color.d.ts +16 -0
- package/dist/util/color.d.ts.map +1 -0
- package/dist/util/color.js +32 -0
- package/dist/util/color.js.map +1 -0
- package/dist/util/exec.d.ts +27 -0
- package/dist/util/exec.d.ts.map +1 -0
- package/dist/util/exec.js +57 -0
- package/dist/util/exec.js.map +1 -0
- package/dist/util/log.d.ts +29 -0
- package/dist/util/log.d.ts.map +1 -0
- package/dist/util/log.js +72 -0
- package/dist/util/log.js.map +1 -0
- package/dist/util/paths.d.ts +18 -0
- package/dist/util/paths.d.ts.map +1 -0
- package/dist/util/paths.js +87 -0
- package/dist/util/paths.js.map +1 -0
- package/dist/util/prompt.d.ts +3 -0
- package/dist/util/prompt.d.ts.map +1 -0
- package/dist/util/prompt.js +15 -0
- package/dist/util/prompt.js.map +1 -0
- package/dist/util/redact.d.ts +15 -0
- package/dist/util/redact.d.ts.map +1 -0
- package/dist/util/redact.js +44 -0
- package/dist/util/redact.js.map +1 -0
- package/dist/util/time.d.ts +13 -0
- package/dist/util/time.d.ts.map +1 -0
- package/dist/util/time.js +77 -0
- package/dist/util/time.js.map +1 -0
- package/docs/integrations.md +128 -0
- package/docs/safety.md +62 -0
- package/package.json +69 -4
- package/src/cli.ts +175 -0
- package/src/commands/archive.ts +72 -0
- package/src/commands/config.ts +57 -0
- package/src/commands/context.ts +86 -0
- package/src/commands/daemon.ts +86 -0
- package/src/commands/doctor.ts +131 -0
- package/src/commands/gc.ts +108 -0
- package/src/commands/status.ts +68 -0
- package/src/commands/watch.ts +48 -0
- package/src/core/apply.ts +276 -0
- package/src/core/archive.ts +269 -0
- package/src/core/config.ts +339 -0
- package/src/core/decide.ts +230 -0
- package/src/core/forge.ts +243 -0
- package/src/core/git.ts +254 -0
- package/src/core/plan.ts +431 -0
- package/src/core/render.ts +168 -0
- package/src/core/scan.ts +105 -0
- package/src/core/sessions.ts +339 -0
- package/src/core/size.ts +10 -0
- package/src/daemon/lock.ts +65 -0
- package/src/daemon/service.ts +321 -0
- package/src/daemon/state.ts +49 -0
- package/src/index.ts +36 -0
- package/src/util/bytes.ts +11 -0
- package/src/util/color.ts +33 -0
- package/src/util/exec.ts +80 -0
- package/src/util/log.ts +88 -0
- package/src/util/paths.ts +84 -0
- package/src/util/prompt.ts +13 -0
- package/src/util/redact.ts +43 -0
- 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"}
|