@proletariat/cli 0.3.95 → 0.3.97
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/dist/commands/config/index.js +1 -1
- package/dist/commands/config/index.js.map +1 -1
- package/dist/commands/db/repair.js +160 -35
- package/dist/commands/db/repair.js.map +1 -1
- package/dist/commands/gc.d.ts +14 -0
- package/dist/commands/gc.js +208 -0
- package/dist/commands/gc.js.map +1 -0
- package/dist/commands/linear/connect.d.ts +5 -0
- package/dist/commands/linear/connect.js +84 -0
- package/dist/commands/linear/connect.js.map +1 -1
- package/dist/commands/pr/merge.js +1 -1
- package/dist/commands/pr/merge.js.map +1 -1
- package/dist/commands/session/attach.d.ts +3 -3
- package/dist/commands/session/attach.js +37 -79
- package/dist/commands/session/attach.js.map +1 -1
- package/dist/commands/session/exec.js +1 -1
- package/dist/commands/session/exec.js.map +1 -1
- package/dist/commands/session/health.js +1 -1
- package/dist/commands/session/health.js.map +1 -1
- package/dist/commands/session/inspect.js +1 -1
- package/dist/commands/session/inspect.js.map +1 -1
- package/dist/commands/session/list.d.ts +1 -0
- package/dist/commands/session/list.js +111 -78
- package/dist/commands/session/list.js.map +1 -1
- package/dist/commands/session/peek.js +1 -1
- package/dist/commands/session/peek.js.map +1 -1
- package/dist/commands/session/poke.js +1 -1
- package/dist/commands/session/poke.js.map +1 -1
- package/dist/commands/session/prune.js +50 -11
- package/dist/commands/session/prune.js.map +1 -1
- package/dist/commands/session/restart.js +1 -1
- package/dist/commands/session/restart.js.map +1 -1
- package/dist/commands/session/watch.d.ts +1 -0
- package/dist/commands/session/watch.js +46 -2
- package/dist/commands/session/watch.js.map +1 -1
- package/dist/commands/{action → sync}/index.d.ts +2 -6
- package/dist/commands/sync/index.js +68 -0
- package/dist/commands/sync/index.js.map +1 -0
- package/dist/commands/sync/pause.d.ts +10 -0
- package/dist/commands/sync/pause.js +35 -0
- package/dist/commands/sync/pause.js.map +1 -0
- package/dist/commands/sync/queue.d.ts +10 -0
- package/dist/commands/sync/queue.js +106 -0
- package/dist/commands/sync/queue.js.map +1 -0
- package/dist/commands/sync/resume.d.ts +10 -0
- package/dist/commands/sync/resume.js +34 -0
- package/dist/commands/sync/resume.js.map +1 -0
- package/dist/commands/sync/start.d.ts +11 -0
- package/dist/commands/sync/start.js +73 -0
- package/dist/commands/sync/start.js.map +1 -0
- package/dist/commands/sync/status.d.ts +10 -0
- package/dist/commands/sync/status.js +40 -0
- package/dist/commands/sync/status.js.map +1 -0
- package/dist/commands/sync/stop.d.ts +10 -0
- package/dist/commands/sync/stop.js +39 -0
- package/dist/commands/sync/stop.js.map +1 -0
- package/dist/commands/ticket/create.js +1 -1
- package/dist/commands/ticket/create.js.map +1 -1
- package/dist/commands/ticket/edit.js +1 -1
- package/dist/commands/ticket/edit.js.map +1 -1
- package/dist/commands/ticket/list.js +1 -1
- package/dist/commands/ticket/list.js.map +1 -1
- package/dist/commands/ticket/update.js +1 -1
- package/dist/commands/ticket/update.js.map +1 -1
- package/dist/commands/work/complete.d.ts +1 -0
- package/dist/commands/work/complete.js +27 -25
- package/dist/commands/work/complete.js.map +1 -1
- package/dist/commands/work/drop.d.ts +14 -0
- package/dist/commands/work/drop.js +215 -0
- package/dist/commands/work/drop.js.map +1 -0
- package/dist/commands/work/ready.d.ts +1 -0
- package/dist/commands/work/ready.js +26 -25
- package/dist/commands/work/ready.js.map +1 -1
- package/dist/commands/work/resolve.js +1 -1
- package/dist/commands/work/resolve.js.map +1 -1
- package/dist/commands/work/ship.d.ts +1 -0
- package/dist/commands/work/ship.js +33 -32
- package/dist/commands/work/ship.js.map +1 -1
- package/dist/commands/work/start.d.ts +2 -0
- package/dist/commands/work/start.js +172 -125
- package/dist/commands/work/start.js.map +1 -1
- package/dist/commands/work/stop.d.ts +1 -0
- package/dist/commands/work/stop.js +40 -0
- package/dist/commands/work/stop.js.map +1 -1
- package/dist/lib/agents/commands.js +7 -5
- package/dist/lib/agents/commands.js.map +1 -1
- package/dist/lib/dashboard/data.js +1 -1
- package/dist/lib/dashboard/data.js.map +1 -1
- package/dist/lib/database/db-safety.d.ts +22 -0
- package/dist/lib/database/db-safety.js +91 -4
- package/dist/lib/database/db-safety.js.map +1 -1
- package/dist/lib/database/drizzle-schema.d.ts +17 -0
- package/dist/lib/database/drizzle-schema.js +1 -0
- package/dist/lib/database/drizzle-schema.js.map +1 -1
- package/dist/lib/database/index.d.ts +1 -1
- package/dist/lib/database/index.js +1 -1
- package/dist/lib/database/index.js.map +1 -1
- package/dist/lib/database/migrations/0017_drop_agent_work_fk.d.ts +13 -0
- package/dist/lib/database/migrations/0017_drop_agent_work_fk.js +85 -0
- package/dist/lib/database/migrations/0017_drop_agent_work_fk.js.map +1 -0
- package/dist/lib/database/migrations/0018_create_ticket_refs.d.ts +11 -0
- package/dist/lib/database/migrations/0018_create_ticket_refs.js +40 -0
- package/dist/lib/database/migrations/0018_create_ticket_refs.js.map +1 -0
- package/dist/lib/database/migrations/0019_gc_artifact_cleanup.d.ts +9 -0
- package/dist/lib/database/migrations/0019_gc_artifact_cleanup.js +23 -0
- package/dist/lib/database/migrations/0019_gc_artifact_cleanup.js.map +1 -0
- package/dist/lib/database/migrations/0020_transition_map.d.ts +2 -0
- package/dist/lib/database/migrations/0020_transition_map.js +27 -0
- package/dist/lib/database/migrations/0020_transition_map.js.map +1 -0
- package/dist/lib/database/migrations/index.js +8 -0
- package/dist/lib/database/migrations/index.js.map +1 -1
- package/dist/lib/execution/config.d.ts +10 -0
- package/dist/lib/execution/config.js +24 -0
- package/dist/lib/execution/config.js.map +1 -1
- package/dist/lib/execution/devcontainer.js +1 -1
- package/dist/lib/execution/devcontainer.js.map +1 -1
- package/dist/lib/execution/preflight.d.ts +51 -0
- package/dist/lib/execution/preflight.js +278 -0
- package/dist/lib/execution/preflight.js.map +1 -0
- package/dist/lib/execution/runners/docker-management.d.ts +9 -0
- package/dist/lib/execution/runners/docker-management.js +14 -3
- package/dist/lib/execution/runners/docker-management.js.map +1 -1
- package/dist/lib/execution/runners/prompt-builder.d.ts +6 -0
- package/dist/lib/execution/runners/prompt-builder.js +53 -10
- package/dist/lib/execution/runners/prompt-builder.js.map +1 -1
- package/dist/lib/execution/runners/shared.d.ts +1 -1
- package/dist/lib/execution/runners/shared.js +1 -1
- package/dist/lib/execution/runners/shared.js.map +1 -1
- package/dist/lib/execution/session-utils.d.ts +39 -0
- package/dist/lib/execution/session-utils.js +111 -0
- package/dist/lib/execution/session-utils.js.map +1 -1
- package/dist/lib/execution/spawner.d.ts +11 -1
- package/dist/lib/execution/spawner.js +46 -17
- package/dist/lib/execution/spawner.js.map +1 -1
- package/dist/lib/execution/storage.js +2 -1
- package/dist/lib/execution/storage.js.map +1 -1
- package/dist/lib/execution/ticket-refs.d.ts +71 -0
- package/dist/lib/execution/ticket-refs.js +125 -0
- package/dist/lib/execution/ticket-refs.js.map +1 -0
- package/dist/lib/execution/types.d.ts +7 -2
- package/dist/lib/execution/types.js +5 -3
- package/dist/lib/execution/types.js.map +1 -1
- package/dist/lib/external-issues/utils.d.ts +25 -0
- package/dist/lib/external-issues/utils.js +32 -0
- package/dist/lib/external-issues/utils.js.map +1 -0
- package/dist/lib/gc/index.d.ts +179 -0
- package/dist/lib/gc/index.js +655 -0
- package/dist/lib/gc/index.js.map +1 -0
- package/dist/lib/mcp/tools/action.js +1 -1
- package/dist/lib/mcp/tools/action.js.map +1 -1
- package/dist/lib/mcp/tools/ticket.js +1 -1
- package/dist/lib/mcp/tools/ticket.js.map +1 -1
- package/dist/lib/orchestrate/actions.js +30 -0
- package/dist/lib/orchestrate/actions.js.map +1 -1
- package/dist/lib/orchestrate/poller.js +3 -3
- package/dist/lib/orchestrate/poller.js.map +1 -1
- package/dist/lib/orchestrate/presets.js +2 -1
- package/dist/lib/orchestrate/presets.js.map +1 -1
- package/dist/lib/orchestrate/types.d.ts +1 -1
- package/dist/lib/orchestrate/types.js +1 -0
- package/dist/lib/orchestrate/types.js.map +1 -1
- package/dist/lib/pmo/index.js +1 -1
- package/dist/lib/pmo/index.js.map +1 -1
- package/dist/lib/pmo/markdown.js +1 -1
- package/dist/lib/pmo/markdown.js.map +1 -1
- package/dist/lib/pmo/schema.d.ts +3 -1
- package/dist/lib/pmo/schema.js +26 -2
- package/dist/lib/pmo/schema.js.map +1 -1
- package/dist/lib/pmo/storage/actions.js +1 -1
- package/dist/lib/pmo/storage/actions.js.map +1 -1
- package/dist/lib/pmo/storage/base.js +37 -15
- package/dist/lib/pmo/storage/base.js.map +1 -1
- package/dist/lib/pmo/storage/projects.js +2 -1
- package/dist/lib/pmo/storage/projects.js.map +1 -1
- package/dist/lib/pmo/storage/statuses.js +1 -1
- package/dist/lib/pmo/storage/statuses.js.map +1 -1
- package/dist/lib/pmo/storage/subtasks.js +1 -1
- package/dist/lib/pmo/storage/subtasks.js.map +1 -1
- package/dist/lib/pmo/storage/templates.js +1 -1
- package/dist/lib/pmo/storage/templates.js.map +1 -1
- package/dist/lib/pmo/storage/tickets.js +2 -1
- package/dist/lib/pmo/storage/tickets.js.map +1 -1
- package/dist/lib/pmo/storage/workflow-rules.js +1 -1
- package/dist/lib/pmo/storage/workflow-rules.js.map +1 -1
- package/dist/lib/pmo/utils.d.ts +6 -189
- package/dist/lib/pmo/utils.js +6 -306
- package/dist/lib/pmo/utils.js.map +1 -1
- package/dist/lib/prompt-json.d.ts +31 -0
- package/dist/lib/prompt-json.js.map +1 -1
- package/dist/lib/providers/auto-mapper.d.ts +45 -0
- package/dist/lib/providers/auto-mapper.js +115 -0
- package/dist/lib/providers/auto-mapper.js.map +1 -0
- package/dist/lib/providers/state-intents.d.ts +20 -0
- package/dist/lib/providers/state-intents.js +61 -7
- package/dist/lib/providers/state-intents.js.map +1 -1
- package/dist/lib/providers/state-resolution.d.ts +15 -11
- package/dist/lib/providers/state-resolution.js +54 -48
- package/dist/lib/providers/state-resolution.js.map +1 -1
- package/dist/lib/providers/transition-map.d.ts +59 -0
- package/dist/lib/providers/transition-map.js +113 -0
- package/dist/lib/providers/transition-map.js.map +1 -0
- package/dist/lib/session/heartbeat.js +1 -1
- package/dist/lib/session/heartbeat.js.map +1 -1
- package/dist/lib/session/index.d.ts +3 -1
- package/dist/lib/session/index.js +3 -1
- package/dist/lib/session/index.js.map +1 -1
- package/dist/lib/session/tmux-watchdog.d.ts +157 -0
- package/dist/lib/session/tmux-watchdog.js +424 -0
- package/dist/lib/session/tmux-watchdog.js.map +1 -0
- package/dist/lib/session/watcher.d.ts +22 -4
- package/dist/lib/session/watcher.js +66 -8
- package/dist/lib/session/watcher.js.map +1 -1
- package/dist/lib/sync/daemon-process.d.ts +9 -0
- package/dist/lib/sync/daemon-process.js +184 -0
- package/dist/lib/sync/daemon-process.js.map +1 -0
- package/dist/lib/sync/daemon.d.ts +39 -0
- package/dist/lib/sync/daemon.js +91 -0
- package/dist/lib/sync/daemon.js.map +1 -0
- package/dist/lib/sync/engine.d.ts +38 -0
- package/dist/lib/sync/engine.js +145 -0
- package/dist/lib/sync/engine.js.map +1 -0
- package/dist/lib/sync/merge-queue.d.ts +116 -0
- package/dist/lib/sync/merge-queue.js +321 -0
- package/dist/lib/sync/merge-queue.js.map +1 -0
- package/dist/lib/sync/reconciler.d.ts +44 -0
- package/dist/lib/sync/reconciler.js +88 -0
- package/dist/lib/sync/reconciler.js.map +1 -0
- package/dist/lib/utils/text.d.ts +44 -0
- package/dist/lib/utils/text.js +72 -0
- package/dist/lib/utils/text.js.map +1 -0
- package/dist/lib/work-lifecycle/post-execution.js +1 -1
- package/dist/lib/work-lifecycle/post-execution.js.map +1 -1
- package/dist/lib/work-lifecycle/settings.d.ts +138 -0
- package/dist/lib/work-lifecycle/settings.js +213 -0
- package/dist/lib/work-lifecycle/settings.js.map +1 -0
- package/dist/lib/work-lifecycle/transition.d.ts +73 -0
- package/dist/lib/work-lifecycle/transition.js +124 -0
- package/dist/lib/work-lifecycle/transition.js.map +1 -0
- package/oclif.manifest.json +3235 -3380
- package/package.json +1 -1
- package/dist/commands/action/create.d.ts +0 -26
- package/dist/commands/action/create.js +0 -245
- package/dist/commands/action/create.js.map +0 -1
- package/dist/commands/action/delete.d.ts +0 -18
- package/dist/commands/action/delete.js +0 -78
- package/dist/commands/action/delete.js.map +0 -1
- package/dist/commands/action/index.js +0 -103
- package/dist/commands/action/index.js.map +0 -1
- package/dist/commands/action/list.d.ts +0 -15
- package/dist/commands/action/list.js +0 -90
- package/dist/commands/action/list.js.map +0 -1
- package/dist/commands/action/run.d.ts +0 -20
- package/dist/commands/action/run.js +0 -188
- package/dist/commands/action/run.js.map +0 -1
- package/dist/commands/action/show.d.ts +0 -17
- package/dist/commands/action/show.js +0 -78
- package/dist/commands/action/show.js.map +0 -1
- package/dist/commands/action/update.d.ts +0 -27
- package/dist/commands/action/update.js +0 -288
- package/dist/commands/action/update.js.map +0 -1
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Garbage Collection Module
|
|
3
|
+
*
|
|
4
|
+
* Core logic for cleaning up agent artifacts after PR merge/close.
|
|
5
|
+
* Handles: worktree removal, container removal, branch pruning (local + remote),
|
|
6
|
+
* tmux session cleanup, Claude session cleanup, DB record marking, agent name recycling,
|
|
7
|
+
* and stale PR closure.
|
|
8
|
+
*
|
|
9
|
+
* Used by both the `prlt gc` command and the daemon's post-merge phase.
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'node:fs';
|
|
12
|
+
import * as path from 'node:path';
|
|
13
|
+
import { execSync } from 'node:child_process';
|
|
14
|
+
import { listAgentContainers, removeContainer, } from '../execution/container-cleanup.js';
|
|
15
|
+
import { getPRForBranch, closePR, } from '../pr/index.js';
|
|
16
|
+
/**
|
|
17
|
+
* Parse `git worktree list --porcelain` output into structured entries.
|
|
18
|
+
*/
|
|
19
|
+
export function parseWorktreeList(output) {
|
|
20
|
+
const blocks = output.split('\n\n').filter(Boolean);
|
|
21
|
+
const entries = [];
|
|
22
|
+
for (const block of blocks) {
|
|
23
|
+
const lines = block.split('\n');
|
|
24
|
+
const worktreeLine = lines.find(l => l.startsWith('worktree '));
|
|
25
|
+
const branchLine = lines.find(l => l.startsWith('branch '));
|
|
26
|
+
const isPrunable = lines.some(l => l.startsWith('prunable'));
|
|
27
|
+
if (!worktreeLine)
|
|
28
|
+
continue;
|
|
29
|
+
entries.push({
|
|
30
|
+
worktreePath: worktreeLine.replace('worktree ', ''),
|
|
31
|
+
branch: branchLine ? branchLine.replace('branch refs/heads/', '') : '',
|
|
32
|
+
isPrunable,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return entries;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* List all git worktrees for a given repo path.
|
|
39
|
+
*/
|
|
40
|
+
function listWorktrees(repoPath) {
|
|
41
|
+
try {
|
|
42
|
+
const output = execSync('git worktree list --porcelain', {
|
|
43
|
+
cwd: repoPath,
|
|
44
|
+
encoding: 'utf-8',
|
|
45
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
46
|
+
});
|
|
47
|
+
return parseWorktreeList(output);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Extract agent name from a worktree path.
|
|
55
|
+
* Worktrees are at: {hqPath}/agents/{subdir}/{agentName}/{repoName}
|
|
56
|
+
*/
|
|
57
|
+
export function extractAgentName(worktreePath, hqPath) {
|
|
58
|
+
const relative = path.relative(hqPath, worktreePath);
|
|
59
|
+
if (!relative.startsWith('agents/'))
|
|
60
|
+
return null;
|
|
61
|
+
const parts = relative.split(path.sep);
|
|
62
|
+
// agents / {subdir} / {agentName} / {repoName}
|
|
63
|
+
if (parts.length >= 4) {
|
|
64
|
+
return parts[2];
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
// =============================================================================
|
|
69
|
+
// Candidate Collection
|
|
70
|
+
// =============================================================================
|
|
71
|
+
/**
|
|
72
|
+
* Determine the GC status for a worktree based on its PR state.
|
|
73
|
+
*/
|
|
74
|
+
export function classifyArtifact(pr, staleDays) {
|
|
75
|
+
if (!pr) {
|
|
76
|
+
// No PR found — branch exists but no PR was ever created or it's been deleted.
|
|
77
|
+
// Treat as closed (safe to clean up).
|
|
78
|
+
return 'closed';
|
|
79
|
+
}
|
|
80
|
+
if (pr.state === 'MERGED')
|
|
81
|
+
return 'merged';
|
|
82
|
+
if (pr.state === 'CLOSED')
|
|
83
|
+
return 'closed';
|
|
84
|
+
// PR is open — check if stale
|
|
85
|
+
const updatedAt = new Date(pr.updatedAt);
|
|
86
|
+
const daysSinceUpdate = (Date.now() - updatedAt.getTime()) / (1000 * 60 * 60 * 24);
|
|
87
|
+
if (daysSinceUpdate >= staleDays)
|
|
88
|
+
return 'stale';
|
|
89
|
+
return 'active';
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Collect all GC candidates by scanning worktrees and checking PR status.
|
|
93
|
+
*
|
|
94
|
+
* Scans all repos in the HQ, finds worktrees inside the agents/ directory,
|
|
95
|
+
* checks PR status for each branch, and classifies them.
|
|
96
|
+
*/
|
|
97
|
+
export function collectGCCandidates(options) {
|
|
98
|
+
const { hqPath, staleDays = 7, log } = options;
|
|
99
|
+
const reposPath = path.join(hqPath, 'repos');
|
|
100
|
+
const candidates = [];
|
|
101
|
+
if (!fs.existsSync(reposPath))
|
|
102
|
+
return candidates;
|
|
103
|
+
// Get all repositories
|
|
104
|
+
let repoDirs;
|
|
105
|
+
try {
|
|
106
|
+
repoDirs = fs.readdirSync(reposPath).filter(d => fs.statSync(path.join(reposPath, d)).isDirectory());
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return candidates;
|
|
110
|
+
}
|
|
111
|
+
// Build container lookup: agentName → ContainerInfo
|
|
112
|
+
const containers = listAgentContainers();
|
|
113
|
+
const containerByAgent = new Map();
|
|
114
|
+
for (const c of containers) {
|
|
115
|
+
containerByAgent.set(c.agentName, c);
|
|
116
|
+
}
|
|
117
|
+
// Track branches we've already seen to avoid duplicate PR lookups
|
|
118
|
+
const seenBranches = new Map();
|
|
119
|
+
for (const repoName of repoDirs) {
|
|
120
|
+
const repoPath = path.join(reposPath, repoName);
|
|
121
|
+
const worktrees = listWorktrees(repoPath);
|
|
122
|
+
for (const wt of worktrees) {
|
|
123
|
+
// Skip the main worktree (the repo itself) and prunable entries
|
|
124
|
+
if (wt.worktreePath === repoPath || wt.isPrunable)
|
|
125
|
+
continue;
|
|
126
|
+
// Only consider worktrees inside agents/ directory
|
|
127
|
+
const agentName = extractAgentName(wt.worktreePath, hqPath);
|
|
128
|
+
if (!agentName && !wt.worktreePath.includes('/agents/'))
|
|
129
|
+
continue;
|
|
130
|
+
// Skip worktrees without a branch (detached HEAD)
|
|
131
|
+
if (!wt.branch)
|
|
132
|
+
continue;
|
|
133
|
+
// Look up PR status for this branch
|
|
134
|
+
let pr;
|
|
135
|
+
if (seenBranches.has(wt.branch)) {
|
|
136
|
+
pr = seenBranches.get(wt.branch);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
log?.(`Checking PR status for branch: ${wt.branch}`);
|
|
140
|
+
pr = getPRForBranch(wt.branch, repoPath);
|
|
141
|
+
seenBranches.set(wt.branch, pr);
|
|
142
|
+
}
|
|
143
|
+
const status = classifyArtifact(pr, staleDays);
|
|
144
|
+
candidates.push({
|
|
145
|
+
worktreePath: wt.worktreePath,
|
|
146
|
+
branch: wt.branch,
|
|
147
|
+
agentName,
|
|
148
|
+
repoName,
|
|
149
|
+
sourceRepoPath: repoPath,
|
|
150
|
+
pr,
|
|
151
|
+
status,
|
|
152
|
+
container: agentName ? containerByAgent.get(agentName) ?? null : null,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return candidates;
|
|
157
|
+
}
|
|
158
|
+
// =============================================================================
|
|
159
|
+
// Cleanup Execution
|
|
160
|
+
// =============================================================================
|
|
161
|
+
/**
|
|
162
|
+
* Delete a local git branch.
|
|
163
|
+
*/
|
|
164
|
+
function deleteLocalBranch(branch, cwd) {
|
|
165
|
+
try {
|
|
166
|
+
execSync(`git branch -D ${branch}`, {
|
|
167
|
+
cwd,
|
|
168
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
169
|
+
});
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Remove a git worktree.
|
|
178
|
+
*/
|
|
179
|
+
function removeWorktree(worktreePath, sourceRepoPath) {
|
|
180
|
+
try {
|
|
181
|
+
execSync(`git worktree remove "${worktreePath}" --force`, {
|
|
182
|
+
cwd: sourceRepoPath,
|
|
183
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
184
|
+
});
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// If git worktree remove fails, try removing the directory directly
|
|
189
|
+
try {
|
|
190
|
+
if (fs.existsSync(worktreePath)) {
|
|
191
|
+
fs.rmSync(worktreePath, { recursive: true, force: true });
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Prune stale worktree references for a repo.
|
|
202
|
+
*/
|
|
203
|
+
function pruneWorktreeRefs(repoPath) {
|
|
204
|
+
try {
|
|
205
|
+
execSync('git worktree prune', {
|
|
206
|
+
cwd: repoPath,
|
|
207
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
// Ignore prune errors
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Remove an agent's directory if it exists and is empty (or force).
|
|
216
|
+
*/
|
|
217
|
+
function removeAgentDir(agentDir) {
|
|
218
|
+
try {
|
|
219
|
+
if (fs.existsSync(agentDir)) {
|
|
220
|
+
fs.rmSync(agentDir, { recursive: true, force: true });
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Delete a remote git branch. Non-fatal if branch doesn't exist on remote.
|
|
231
|
+
*/
|
|
232
|
+
export function deleteRemoteBranch(branch, cwd) {
|
|
233
|
+
try {
|
|
234
|
+
execSync(`git push origin --delete "${branch}"`, {
|
|
235
|
+
cwd,
|
|
236
|
+
encoding: 'utf-8',
|
|
237
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
238
|
+
timeout: 30000,
|
|
239
|
+
});
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
// If the remote branch is already gone, that's fine
|
|
244
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
245
|
+
if (msg.includes('remote ref does not exist') || msg.includes('unable to delete')) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Kill tmux sessions inside a Docker container.
|
|
253
|
+
* Non-fatal if tmux is not running or container is not accessible.
|
|
254
|
+
*/
|
|
255
|
+
export function killTmuxInContainer(containerId) {
|
|
256
|
+
try {
|
|
257
|
+
execSync(`docker exec ${containerId} tmux kill-server`, {
|
|
258
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
259
|
+
timeout: 10000,
|
|
260
|
+
});
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Non-fatal — tmux may not be running in the container
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Clean up Claude session data from a Docker container's claude-credentials volume.
|
|
270
|
+
* Only removes session-specific files, preserving auth credentials.
|
|
271
|
+
*
|
|
272
|
+
* Session files to clean: projects/, .claude-*, statsig/
|
|
273
|
+
* Files to preserve: .credentials.json, credentials.json, .oauthtoken, settings.json
|
|
274
|
+
*/
|
|
275
|
+
export function cleanClaudeSessionData(containerId) {
|
|
276
|
+
try {
|
|
277
|
+
// Remove session-specific directories and files, preserve auth
|
|
278
|
+
// The cleanup script removes session state but keeps credentials
|
|
279
|
+
const script = 'rm -rf /home/node/.claude/projects 2>/dev/null; ' +
|
|
280
|
+
'rm -rf /home/node/.claude/statsig 2>/dev/null; ' +
|
|
281
|
+
'rm -f /home/node/.claude/.claude-session 2>/dev/null; ' +
|
|
282
|
+
'rm -f /home/node/.claude/.claude-conversation 2>/dev/null; ' +
|
|
283
|
+
'rm -f /home/node/.claude/.claude-history 2>/dev/null; ' +
|
|
284
|
+
'rm -rf /home/node/.claude/memory 2>/dev/null; ' +
|
|
285
|
+
'true';
|
|
286
|
+
execSync(`docker exec ${containerId} sh -c '${script}'`, {
|
|
287
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
288
|
+
timeout: 10000,
|
|
289
|
+
});
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// Non-fatal — container may not be accessible
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Mark execution records as GC-cleaned for the given agent names.
|
|
299
|
+
* Sets gc_cleaned_at timestamp on agent_work rows that are completed/failed.
|
|
300
|
+
*/
|
|
301
|
+
export function markExecutionRecordsCleaned(hqPath, agentNames) {
|
|
302
|
+
if (agentNames.length === 0)
|
|
303
|
+
return 0;
|
|
304
|
+
try {
|
|
305
|
+
const { openWorkspaceDatabase } = require('../database/workspace.js');
|
|
306
|
+
const db = openWorkspaceDatabase(hqPath);
|
|
307
|
+
try {
|
|
308
|
+
// Check if agent_work table exists
|
|
309
|
+
const tableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='agent_work'").get();
|
|
310
|
+
if (!tableExists)
|
|
311
|
+
return 0;
|
|
312
|
+
// Check if gc_cleaned_at column exists
|
|
313
|
+
const cols = db.prepare("PRAGMA table_info(agent_work)").all();
|
|
314
|
+
if (!cols.some(c => c.name === 'gc_cleaned_at'))
|
|
315
|
+
return 0;
|
|
316
|
+
const placeholders = agentNames.map(() => '?').join(',');
|
|
317
|
+
const now = new Date().toISOString();
|
|
318
|
+
const stmt = db.prepare(`UPDATE agent_work SET gc_cleaned_at = ? WHERE agent_name IN (${placeholders}) AND gc_cleaned_at IS NULL`);
|
|
319
|
+
const result = stmt.run(now, ...agentNames);
|
|
320
|
+
return result.changes;
|
|
321
|
+
}
|
|
322
|
+
finally {
|
|
323
|
+
db.close();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
catch {
|
|
327
|
+
return 0;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Purge (DELETE) execution records for the given agent names.
|
|
332
|
+
* Only deletes records that have already been marked as gc_cleaned.
|
|
333
|
+
*/
|
|
334
|
+
export function purgeExecutionRecords(hqPath, agentNames) {
|
|
335
|
+
if (agentNames.length === 0)
|
|
336
|
+
return 0;
|
|
337
|
+
try {
|
|
338
|
+
const { openWorkspaceDatabase } = require('../database/workspace.js');
|
|
339
|
+
const db = openWorkspaceDatabase(hqPath);
|
|
340
|
+
try {
|
|
341
|
+
const tableExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='agent_work'").get();
|
|
342
|
+
if (!tableExists)
|
|
343
|
+
return 0;
|
|
344
|
+
const placeholders = agentNames.map(() => '?').join(',');
|
|
345
|
+
const stmt = db.prepare(`DELETE FROM agent_work WHERE agent_name IN (${placeholders}) AND gc_cleaned_at IS NOT NULL`);
|
|
346
|
+
const result = stmt.run(...agentNames);
|
|
347
|
+
return result.changes;
|
|
348
|
+
}
|
|
349
|
+
finally {
|
|
350
|
+
db.close();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
return 0;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Mark agent names as recyclable (status='cleaned') in the database.
|
|
359
|
+
* Preserves the record for history but allows name reuse.
|
|
360
|
+
*/
|
|
361
|
+
export function recycleAgentNames(hqPath, agentNames) {
|
|
362
|
+
if (agentNames.length === 0)
|
|
363
|
+
return [];
|
|
364
|
+
const recycled = [];
|
|
365
|
+
try {
|
|
366
|
+
const { markAgentCleaned } = require('../database/agents.js');
|
|
367
|
+
for (const name of agentNames) {
|
|
368
|
+
try {
|
|
369
|
+
markAgentCleaned(hqPath, name);
|
|
370
|
+
recycled.push(name);
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
// Agent may not exist in DB — non-fatal
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
// DB access may fail — non-fatal
|
|
379
|
+
}
|
|
380
|
+
return recycled;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Execute garbage collection on the provided candidates.
|
|
384
|
+
*
|
|
385
|
+
* Processes candidates in order:
|
|
386
|
+
* 1. Close stale PRs
|
|
387
|
+
* 2. Kill tmux sessions in containers
|
|
388
|
+
* 3. Clean Claude session data in containers
|
|
389
|
+
* 4. Remove worktrees
|
|
390
|
+
* 5. Remove containers
|
|
391
|
+
* 6. Prune local branches
|
|
392
|
+
* 7. Delete remote branches
|
|
393
|
+
* 8. Clean up empty agent directories
|
|
394
|
+
* 9. Mark/purge DB execution records
|
|
395
|
+
* 10. Recycle agent names
|
|
396
|
+
*/
|
|
397
|
+
export function executeGC(candidates, options) {
|
|
398
|
+
const { execute = false, purgeDb = false, log, hqPath } = options;
|
|
399
|
+
const result = {
|
|
400
|
+
worktreesRemoved: [],
|
|
401
|
+
containersRemoved: [],
|
|
402
|
+
branchesPruned: [],
|
|
403
|
+
remoteBranchesDeleted: [],
|
|
404
|
+
tmuxSessionsCleaned: [],
|
|
405
|
+
claudeSessionsCleaned: [],
|
|
406
|
+
dbRecordsMarked: 0,
|
|
407
|
+
dbRecordsPurged: 0,
|
|
408
|
+
agentNamesRecycled: [],
|
|
409
|
+
stalePRsClosed: [],
|
|
410
|
+
errors: [],
|
|
411
|
+
skipped: [],
|
|
412
|
+
};
|
|
413
|
+
// Filter to only actionable candidates
|
|
414
|
+
const filterStatus = options.filterStatus ?? ['merged', 'closed', 'stale'];
|
|
415
|
+
const actionable = candidates.filter(c => filterStatus.includes(c.status));
|
|
416
|
+
const skipped = candidates.filter(c => !filterStatus.includes(c.status));
|
|
417
|
+
for (const c of skipped) {
|
|
418
|
+
result.skipped.push(`${c.branch} (${c.status})`);
|
|
419
|
+
}
|
|
420
|
+
// Track repos that need pruning and agent dirs that need cleanup
|
|
421
|
+
const reposToProcess = new Set();
|
|
422
|
+
const agentDirs = new Set();
|
|
423
|
+
const processedContainers = new Set();
|
|
424
|
+
const processedAgentNames = new Set();
|
|
425
|
+
const processedBranches = new Set();
|
|
426
|
+
for (const candidate of actionable) {
|
|
427
|
+
// 1. Close stale PRs
|
|
428
|
+
if (candidate.status === 'stale' && candidate.pr) {
|
|
429
|
+
if (execute) {
|
|
430
|
+
log?.(`Closing stale PR #${candidate.pr.number}: ${candidate.pr.title}`);
|
|
431
|
+
const closeResult = closePR(candidate.pr.number, {
|
|
432
|
+
comment: 'Closing stale PR — no activity for 7+ days. Worktree archived by GC.',
|
|
433
|
+
cwd: candidate.sourceRepoPath,
|
|
434
|
+
});
|
|
435
|
+
if (closeResult.success) {
|
|
436
|
+
result.stalePRsClosed.push(candidate.pr.number);
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
result.errors.push(`Failed to close PR #${candidate.pr.number}: ${closeResult.error}`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
log?.(`[dry-run] Would close stale PR #${candidate.pr.number}: ${candidate.pr.title}`);
|
|
444
|
+
result.stalePRsClosed.push(candidate.pr.number);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
// 2. Kill tmux sessions + 3. Clean Claude session data (before container removal)
|
|
448
|
+
if (candidate.container && !processedContainers.has(candidate.container.containerId)) {
|
|
449
|
+
if (execute) {
|
|
450
|
+
// Kill tmux sessions inside the container
|
|
451
|
+
log?.(`Killing tmux sessions in container: ${candidate.container.containerName}`);
|
|
452
|
+
if (killTmuxInContainer(candidate.container.containerId)) {
|
|
453
|
+
result.tmuxSessionsCleaned.push(candidate.container.containerName);
|
|
454
|
+
}
|
|
455
|
+
// tmux cleanup failure is non-fatal
|
|
456
|
+
// Clean Claude session data
|
|
457
|
+
log?.(`Cleaning Claude session data in container: ${candidate.container.containerName}`);
|
|
458
|
+
if (cleanClaudeSessionData(candidate.container.containerId)) {
|
|
459
|
+
result.claudeSessionsCleaned.push(candidate.container.containerName);
|
|
460
|
+
}
|
|
461
|
+
// Claude session cleanup failure is non-fatal
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
log?.(`[dry-run] Would kill tmux sessions in container: ${candidate.container.containerName}`);
|
|
465
|
+
result.tmuxSessionsCleaned.push(candidate.container.containerName);
|
|
466
|
+
log?.(`[dry-run] Would clean Claude session data in container: ${candidate.container.containerName}`);
|
|
467
|
+
result.claudeSessionsCleaned.push(candidate.container.containerName);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
// 4. Remove worktree
|
|
471
|
+
if (execute) {
|
|
472
|
+
log?.(`Removing worktree: ${candidate.worktreePath}`);
|
|
473
|
+
if (removeWorktree(candidate.worktreePath, candidate.sourceRepoPath)) {
|
|
474
|
+
result.worktreesRemoved.push(candidate.worktreePath);
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
result.errors.push(`Failed to remove worktree: ${candidate.worktreePath}`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
log?.(`[dry-run] Would remove worktree: ${candidate.worktreePath}`);
|
|
482
|
+
result.worktreesRemoved.push(candidate.worktreePath);
|
|
483
|
+
}
|
|
484
|
+
// 5. Remove container (deduplicate by agent)
|
|
485
|
+
if (candidate.container && !processedContainers.has(candidate.container.containerId)) {
|
|
486
|
+
processedContainers.add(candidate.container.containerId);
|
|
487
|
+
if (execute) {
|
|
488
|
+
log?.(`Removing container: ${candidate.container.containerName}`);
|
|
489
|
+
const rmResult = removeContainer(candidate.container.containerId);
|
|
490
|
+
if (rmResult.success) {
|
|
491
|
+
result.containersRemoved.push(candidate.container.containerName);
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
result.errors.push(`Failed to remove container ${candidate.container.containerName}: ${rmResult.error}`);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
log?.(`[dry-run] Would remove container: ${candidate.container.containerName}`);
|
|
499
|
+
result.containersRemoved.push(candidate.container.containerName);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
// 6. Prune local branch
|
|
503
|
+
if (candidate.branch) {
|
|
504
|
+
if (execute) {
|
|
505
|
+
if (deleteLocalBranch(candidate.branch, candidate.sourceRepoPath)) {
|
|
506
|
+
result.branchesPruned.push(candidate.branch);
|
|
507
|
+
log?.(`Pruned local branch: ${candidate.branch}`);
|
|
508
|
+
}
|
|
509
|
+
// Branch deletion failure is non-fatal (may already be deleted)
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
log?.(`[dry-run] Would prune local branch: ${candidate.branch}`);
|
|
513
|
+
result.branchesPruned.push(candidate.branch);
|
|
514
|
+
}
|
|
515
|
+
// 7. Delete remote branch (deduplicate across repos for same branch)
|
|
516
|
+
if (!processedBranches.has(candidate.branch)) {
|
|
517
|
+
processedBranches.add(candidate.branch);
|
|
518
|
+
if (execute) {
|
|
519
|
+
log?.(`Deleting remote branch: ${candidate.branch}`);
|
|
520
|
+
if (deleteRemoteBranch(candidate.branch, candidate.sourceRepoPath)) {
|
|
521
|
+
result.remoteBranchesDeleted.push(candidate.branch);
|
|
522
|
+
}
|
|
523
|
+
// Remote branch deletion failure is non-fatal (may already be deleted)
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
log?.(`[dry-run] Would delete remote branch: ${candidate.branch}`);
|
|
527
|
+
result.remoteBranchesDeleted.push(candidate.branch);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
reposToProcess.add(candidate.sourceRepoPath);
|
|
532
|
+
// Track agent directory and name for cleanup
|
|
533
|
+
if (candidate.agentName) {
|
|
534
|
+
const agentDir = path.dirname(candidate.worktreePath);
|
|
535
|
+
agentDirs.add(agentDir);
|
|
536
|
+
processedAgentNames.add(candidate.agentName);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
// 8. Prune worktree refs and clean up empty agent directories
|
|
540
|
+
if (execute) {
|
|
541
|
+
for (const repoPath of reposToProcess) {
|
|
542
|
+
pruneWorktreeRefs(repoPath);
|
|
543
|
+
}
|
|
544
|
+
for (const agentDir of agentDirs) {
|
|
545
|
+
// Only remove if directory is now empty or doesn't exist
|
|
546
|
+
if (fs.existsSync(agentDir)) {
|
|
547
|
+
try {
|
|
548
|
+
const contents = fs.readdirSync(agentDir);
|
|
549
|
+
if (contents.length === 0) {
|
|
550
|
+
removeAgentDir(agentDir);
|
|
551
|
+
log?.(`Removed empty agent directory: ${agentDir}`);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
catch {
|
|
555
|
+
// Ignore
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// 9. Mark/purge DB execution records
|
|
561
|
+
const agentNameList = [...processedAgentNames];
|
|
562
|
+
if (agentNameList.length > 0) {
|
|
563
|
+
if (execute) {
|
|
564
|
+
// Always mark records as gc_cleaned
|
|
565
|
+
const marked = markExecutionRecordsCleaned(hqPath, agentNameList);
|
|
566
|
+
result.dbRecordsMarked = marked;
|
|
567
|
+
if (marked > 0) {
|
|
568
|
+
log?.(`Marked ${marked} execution record(s) as gc_cleaned`);
|
|
569
|
+
}
|
|
570
|
+
// Optionally purge (DELETE) if --purge-db was passed
|
|
571
|
+
if (purgeDb) {
|
|
572
|
+
const purged = purgeExecutionRecords(hqPath, agentNameList);
|
|
573
|
+
result.dbRecordsPurged = purged;
|
|
574
|
+
if (purged > 0) {
|
|
575
|
+
log?.(`Purged ${purged} execution record(s)`);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
log?.(`[dry-run] Would mark execution records as gc_cleaned for ${agentNameList.length} agent(s)`);
|
|
581
|
+
if (purgeDb) {
|
|
582
|
+
log?.(`[dry-run] Would purge execution records for ${agentNameList.length} agent(s)`);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
// 10. Recycle agent names
|
|
587
|
+
if (agentNameList.length > 0) {
|
|
588
|
+
if (execute) {
|
|
589
|
+
log?.(`Recycling ${agentNameList.length} agent name(s)`);
|
|
590
|
+
const recycled = recycleAgentNames(hqPath, agentNameList);
|
|
591
|
+
result.agentNamesRecycled = recycled;
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
log?.(`[dry-run] Would recycle ${agentNameList.length} agent name(s)`);
|
|
595
|
+
result.agentNamesRecycled = agentNameList;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return result;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* In-memory scheduler for daemon GC with grace periods.
|
|
602
|
+
* Tracks branches that need cleanup after their grace period expires.
|
|
603
|
+
*/
|
|
604
|
+
export class GCScheduler {
|
|
605
|
+
pending = new Map();
|
|
606
|
+
gracePeriodMs;
|
|
607
|
+
constructor(gracePeriodMs = 60 * 60 * 1000 /* 1 hour */) {
|
|
608
|
+
this.gracePeriodMs = gracePeriodMs;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Schedule a branch for GC after the grace period.
|
|
612
|
+
*/
|
|
613
|
+
schedule(branch) {
|
|
614
|
+
if (this.pending.has(branch))
|
|
615
|
+
return;
|
|
616
|
+
const now = Date.now();
|
|
617
|
+
this.pending.set(branch, {
|
|
618
|
+
branch,
|
|
619
|
+
scheduledAt: now,
|
|
620
|
+
graceUntil: now + this.gracePeriodMs,
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Get branches whose grace period has expired.
|
|
625
|
+
*/
|
|
626
|
+
getReady() {
|
|
627
|
+
const now = Date.now();
|
|
628
|
+
const ready = [];
|
|
629
|
+
for (const [branch, entry] of this.pending) {
|
|
630
|
+
if (now >= entry.graceUntil) {
|
|
631
|
+
ready.push(branch);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
return ready;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Remove a branch from the schedule (after cleanup).
|
|
638
|
+
*/
|
|
639
|
+
complete(branch) {
|
|
640
|
+
this.pending.delete(branch);
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Get all pending cleanups (for status/debugging).
|
|
644
|
+
*/
|
|
645
|
+
getPending() {
|
|
646
|
+
return [...this.pending.values()];
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Number of pending cleanups.
|
|
650
|
+
*/
|
|
651
|
+
get size() {
|
|
652
|
+
return this.pending.size;
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/gc/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EACL,mBAAmB,EACnB,eAAe,GAEhB,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EACL,cAAc,EACd,OAAO,GAER,MAAM,gBAAgB,CAAA;AAmFvB;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACnD,MAAM,OAAO,GAAoB,EAAE,CAAA;IAEnC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAC/B,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAA;QAC/D,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAA;QAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAA;QAE5D,IAAI,CAAC,YAAY;YAAE,SAAQ;QAE3B,OAAO,CAAC,IAAI,CAAC;YACX,YAAY,EAAE,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YACnD,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;YACtE,UAAU;SACX,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,QAAgB;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,+BAA+B,EAAE;YACvD,GAAG,EAAE,QAAQ;YACb,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAA;QACF,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,YAAoB,EAAE,MAAc;IACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACpD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAA;IAEhD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACtC,+CAA+C;IAC/C,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED,gFAAgF;AAChF,uBAAuB;AACvB,gFAAgF;AAEhF;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAiB,EAAE,SAAiB;IACnE,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,+EAA+E;QAC/E,sCAAsC;QACtC,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,IAAI,EAAE,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC1C,IAAI,EAAE,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAE1C,8BAA8B;IAC9B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CAAA;IACxC,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;IAClF,IAAI,eAAe,IAAI,SAAS;QAAE,OAAO,OAAO,CAAA;IAEhD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAkB;IACpD,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAA;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5C,MAAM,UAAU,GAAkB,EAAE,CAAA;IAEpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,UAAU,CAAA;IAEhD,uBAAuB;IACvB,IAAI,QAAkB,CAAA;IACtB,IAAI,CAAC;QACH,QAAQ,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC9C,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CACnD,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,oDAAoD;IACpD,MAAM,UAAU,GAAG,mBAAmB,EAAE,CAAA;IACxC,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAyB,CAAA;IACzD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IACtC,CAAC;IAED,kEAAkE;IAClE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyB,CAAA;IAErD,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QAC/C,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;QAEzC,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;YAC3B,gEAAgE;YAChE,IAAI,EAAE,CAAC,YAAY,KAAK,QAAQ,IAAI,EAAE,CAAC,UAAU;gBAAE,SAAQ;YAE3D,mDAAmD;YACnD,MAAM,SAAS,GAAG,gBAAgB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;YAC3D,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAAE,SAAQ;YAEjE,kDAAkD;YAClD,IAAI,CAAC,EAAE,CAAC,MAAM;gBAAE,SAAQ;YAExB,oCAAoC;YACpC,IAAI,EAAiB,CAAA;YACrB,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;gBAChC,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAE,CAAA;YACnC,CAAC;iBAAM,CAAC;gBACN,GAAG,EAAE,CAAC,kCAAkC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAA;gBACpD,EAAE,GAAG,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;gBACxC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;YACjC,CAAC;YAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;YAE9C,UAAU,CAAC,IAAI,CAAC;gBACd,YAAY,EAAE,EAAE,CAAC,YAAY;gBAC7B,MAAM,EAAE,EAAE,CAAC,MAAM;gBACjB,SAAS;gBACT,QAAQ;gBACR,cAAc,EAAE,QAAQ;gBACxB,EAAE;gBACF,MAAM;gBACN,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI;aACtE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED,gFAAgF;AAChF,oBAAoB;AACpB,gFAAgF;AAEhF;;GAEG;AACH,SAAS,iBAAiB,CAAC,MAAc,EAAE,GAAW;IACpD,IAAI,CAAC;QACH,QAAQ,CAAC,iBAAiB,MAAM,EAAE,EAAE;YAClC,GAAG;YACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,YAAoB,EAAE,cAAsB;IAClE,IAAI,CAAC;QACH,QAAQ,CAAC,wBAAwB,YAAY,WAAW,EAAE;YACxD,GAAG,EAAE,cAAc;YACnB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YAC3D,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,QAAgB;IACzC,IAAI,CAAC;QACH,QAAQ,CAAC,oBAAoB,EAAE;YAC7B,GAAG,EAAE,QAAQ;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YACrD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,GAAW;IAC5D,IAAI,CAAC;QACH,QAAQ,CAAC,6BAA6B,MAAM,GAAG,EAAE;YAC/C,GAAG;YACH,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,OAAO,EAAE,KAAK;SACf,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,oDAAoD;QACpD,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAClE,IAAI,GAAG,CAAC,QAAQ,CAAC,2BAA2B,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAClF,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,IAAI,CAAC;QACH,QAAQ,CAAC,eAAe,WAAW,mBAAmB,EAAE;YACtD,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,OAAO,EAAE,KAAK;SACf,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;QACvD,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,WAAmB;IACxD,IAAI,CAAC;QACH,+DAA+D;QAC/D,iEAAiE;QACjE,MAAM,MAAM,GACV,kDAAkD;YAClD,iDAAiD;YACjD,wDAAwD;YACxD,6DAA6D;YAC7D,wDAAwD;YACxD,gDAAgD;YAChD,MAAM,CAAA;QAER,QAAQ,CAAC,eAAe,WAAW,WAAW,MAAM,GAAG,EAAE;YACvD,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;YAC/B,OAAO,EAAE,KAAK;SACf,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;QAC9C,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAc,EACd,UAAoB;IAEpB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IAErC,IAAI,CAAC;QACH,MAAM,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAA;QACrE,MAAM,EAAE,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAA;QACxC,IAAI,CAAC;YACH,mCAAmC;YACnC,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,yEAAyE,CAC1E,CAAC,GAAG,EAAE,CAAA;YACP,IAAI,CAAC,WAAW;gBAAE,OAAO,CAAC,CAAA;YAE1B,uCAAuC;YACvC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,+BAA+B,CAAC,CAAC,GAAG,EAAwB,CAAA;YACpF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC;gBAAE,OAAO,CAAC,CAAA;YAEzD,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACxD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;YAEpC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,gEAAgE,YAAY,6BAA6B,CAC1G,CAAA;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,CAAA;YAC3C,OAAO,MAAM,CAAC,OAAO,CAAA;QACvB,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,KAAK,EAAE,CAAA;QACZ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAA;IACV,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAc,EACd,UAAoB;IAEpB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAA;IAErC,IAAI,CAAC;QACH,MAAM,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAA;QACrE,MAAM,EAAE,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAA;QACxC,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,yEAAyE,CAC1E,CAAC,GAAG,EAAE,CAAA;YACP,IAAI,CAAC,WAAW;gBAAE,OAAO,CAAC,CAAA;YAE1B,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAExD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CACrB,+CAA+C,YAAY,iCAAiC,CAC7F,CAAA;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,CAAA;YACtC,OAAO,MAAM,CAAC,OAAO,CAAA;QACvB,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,KAAK,EAAE,CAAA;QACZ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAA;IACV,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,UAAoB;IAEpB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAEtC,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAA;QAC7D,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,IAAI,CAAC;gBACH,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;gBAC9B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,wCAAwC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,SAAS,CACvB,UAAyB,EACzB,OAAkB;IAElB,MAAM,EAAE,OAAO,GAAG,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;IAEjE,MAAM,MAAM,GAAa;QACvB,gBAAgB,EAAE,EAAE;QACpB,iBAAiB,EAAE,EAAE;QACrB,cAAc,EAAE,EAAE;QAClB,qBAAqB,EAAE,EAAE;QACzB,mBAAmB,EAAE,EAAE;QACvB,qBAAqB,EAAE,EAAE;QACzB,eAAe,EAAE,CAAC;QAClB,eAAe,EAAE,CAAC;QAClB,kBAAkB,EAAE,EAAE;QACtB,cAAc,EAAE,EAAE;QAClB,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,EAAE;KACZ,CAAA;IAED,uCAAuC;IACvC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC1E,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAC1E,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAExE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;IAClD,CAAC;IAED,iEAAiE;IACjE,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAA;IACxC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;IACnC,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7C,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7C,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAA;IAE3C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,qBAAqB;QACrB,IAAI,SAAS,CAAC,MAAM,KAAK,OAAO,IAAI,SAAS,CAAC,EAAE,EAAE,CAAC;YACjD,IAAI,OAAO,EAAE,CAAC;gBACZ,GAAG,EAAE,CAAC,qBAAqB,SAAS,CAAC,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAA;gBACxE,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE;oBAC/C,OAAO,EAAE,sEAAsE;oBAC/E,GAAG,EAAE,SAAS,CAAC,cAAc;iBAC9B,CAAC,CAAA;gBACF,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;oBACxB,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAA;gBACjD,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,SAAS,CAAC,EAAE,CAAC,MAAM,KAAK,WAAW,CAAC,KAAK,EAAE,CAAC,CAAA;gBACxF,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,GAAG,EAAE,CAAC,mCAAmC,SAAS,CAAC,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAA;gBACtF,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAA;YACjD,CAAC;QACH,CAAC;QAED,kFAAkF;QAClF,IAAI,SAAS,CAAC,SAAS,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;YACrF,IAAI,OAAO,EAAE,CAAC;gBACZ,0CAA0C;gBAC1C,GAAG,EAAE,CAAC,uCAAuC,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAA;gBACjF,IAAI,mBAAmB,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;oBACzD,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;gBACpE,CAAC;gBACD,oCAAoC;gBAEpC,4BAA4B;gBAC5B,GAAG,EAAE,CAAC,8CAA8C,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAA;gBACxF,IAAI,sBAAsB,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC5D,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;gBACtE,CAAC;gBACD,8CAA8C;YAChD,CAAC;iBAAM,CAAC;gBACN,GAAG,EAAE,CAAC,oDAAoD,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAA;gBAC9F,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;gBAClE,GAAG,EAAE,CAAC,2DAA2D,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAA;gBACrG,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;YACtE,CAAC;QACH,CAAC;QAED,qBAAqB;QACrB,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,EAAE,CAAC,sBAAsB,SAAS,CAAC,YAAY,EAAE,CAAC,CAAA;YACrD,IAAI,cAAc,CAAC,SAAS,CAAC,YAAY,EAAE,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;gBACrE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;YACtD,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,SAAS,CAAC,YAAY,EAAE,CAAC,CAAA;YAC5E,CAAC;QACH,CAAC;aAAM,CAAC;YACN,GAAG,EAAE,CAAC,oCAAoC,SAAS,CAAC,YAAY,EAAE,CAAC,CAAA;YACnE,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;QACtD,CAAC;QAED,6CAA6C;QAC7C,IAAI,SAAS,CAAC,SAAS,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC;YACrF,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;YACxD,IAAI,OAAO,EAAE,CAAC;gBACZ,GAAG,EAAE,CAAC,uBAAuB,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAA;gBACjE,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;gBACjE,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;oBACrB,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;gBAClE,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,SAAS,CAAC,SAAS,CAAC,aAAa,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;gBAC1G,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,GAAG,EAAE,CAAC,qCAAqC,SAAS,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC,CAAA;gBAC/E,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;YAClE,CAAC;QACH,CAAC;QAED,wBAAwB;QACxB,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;YACrB,IAAI,OAAO,EAAE,CAAC;gBACZ,IAAI,iBAAiB,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;oBAClE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;oBAC5C,GAAG,EAAE,CAAC,wBAAwB,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;gBACnD,CAAC;gBACD,gEAAgE;YAClE,CAAC;iBAAM,CAAC;gBACN,GAAG,EAAE,CAAC,uCAAuC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;gBAChE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;YAC9C,CAAC;YAED,qEAAqE;YACrE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7C,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;gBACvC,IAAI,OAAO,EAAE,CAAC;oBACZ,GAAG,EAAE,CAAC,2BAA2B,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;oBACpD,IAAI,kBAAkB,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;wBACnE,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;oBACrD,CAAC;oBACD,uEAAuE;gBACzE,CAAC;qBAAM,CAAC;oBACN,GAAG,EAAE,CAAC,yCAAyC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;oBAClE,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;gBACrD,CAAC;YACH,CAAC;QACH,CAAC;QAED,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA;QAE5C,6CAA6C;QAC7C,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;YACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,CAAC,CAAA;YACrD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACvB,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QAC9C,CAAC;IACH,CAAC;IAED,8DAA8D;IAC9D,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;YACtC,iBAAiB,CAAC,QAAQ,CAAC,CAAA;QAC7B,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,yDAAyD;YACzD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;oBACzC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBAC1B,cAAc,CAAC,QAAQ,CAAC,CAAA;wBACxB,GAAG,EAAE,CAAC,kCAAkC,QAAQ,EAAE,CAAC,CAAA;oBACrD,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,MAAM,aAAa,GAAG,CAAC,GAAG,mBAAmB,CAAC,CAAA;IAC9C,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,IAAI,OAAO,EAAE,CAAC;YACZ,oCAAoC;YACpC,MAAM,MAAM,GAAG,2BAA2B,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;YACjE,MAAM,CAAC,eAAe,GAAG,MAAM,CAAA;YAC/B,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBACf,GAAG,EAAE,CAAC,UAAU,MAAM,oCAAoC,CAAC,CAAA;YAC7D,CAAC;YAED,qDAAqD;YACrD,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;gBAC3D,MAAM,CAAC,eAAe,GAAG,MAAM,CAAA;gBAC/B,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;oBACf,GAAG,EAAE,CAAC,UAAU,MAAM,sBAAsB,CAAC,CAAA;gBAC/C,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,GAAG,EAAE,CAAC,4DAA4D,aAAa,CAAC,MAAM,WAAW,CAAC,CAAA;YAClG,IAAI,OAAO,EAAE,CAAC;gBACZ,GAAG,EAAE,CAAC,+CAA+C,aAAa,CAAC,MAAM,WAAW,CAAC,CAAA;YACvF,CAAC;QACH,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,EAAE,CAAC,aAAa,aAAa,CAAC,MAAM,gBAAgB,CAAC,CAAA;YACxD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;YACzD,MAAM,CAAC,kBAAkB,GAAG,QAAQ,CAAA;QACtC,CAAC;aAAM,CAAC;YACN,GAAG,EAAE,CAAC,2BAA2B,aAAa,CAAC,MAAM,gBAAgB,CAAC,CAAA;YACtE,MAAM,CAAC,kBAAkB,GAAG,aAAa,CAAA;QAC3C,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAYD;;;GAGG;AACH,MAAM,OAAO,WAAW;IACd,OAAO,GAAG,IAAI,GAAG,EAA4B,CAAA;IAC7C,aAAa,CAAQ;IAE7B,YAAY,gBAAwB,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,YAAY;QAC7D,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;IACpC,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,MAAc;QACrB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,OAAM;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE;YACvB,MAAM;YACN,WAAW,EAAE,GAAG;YAChB,UAAU,EAAE,GAAG,GAAG,IAAI,CAAC,aAAa;SACrC,CAAC,CAAA;IACJ,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACtB,MAAM,KAAK,GAAa,EAAE,CAAA;QAE1B,KAAK,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,IAAI,GAAG,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACpB,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,MAAc;QACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC7B,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACnC,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAA;IAC1B,CAAC;CACF"}
|