@sensigo/realm-cli 0.18.0 → 0.20.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.
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAyB1D;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EAChD,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC;IAAE,QAAQ,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC,CAgCpC;AAED,eAAO,MAAM,cAAc,SAsBvB,CAAC"}
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAI1D;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EAChD,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC;IAAE,QAAQ,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC,CAgCpC;AAED,eAAO,MAAM,cAAc,SAsBvB,CAAC"}
@@ -1,24 +1,7 @@
1
1
  // cleanup command — marks idle non-terminal runs as abandoned.
2
2
  import { Command } from 'commander';
3
- import { WorkflowError, WAITING_PHASES } from '@sensigo/realm';
4
- /**
5
- * Parses a duration string such as "30d", "6h", or "10m" into milliseconds.
6
- */
7
- function parseDuration(s) {
8
- const match = /^(\d+)(d|h|m)$/.exec(s);
9
- if (match === null) {
10
- throw new WorkflowError(`Invalid duration '${s}'. Use format: <number>(d|h|m), e.g. 30d, 6h, 10m`, {
11
- code: 'VALIDATION_INPUT_SCHEMA',
12
- category: 'VALIDATION',
13
- agentAction: 'provide_input',
14
- retryable: false,
15
- });
16
- }
17
- const value = parseInt(match[1], 10);
18
- const unit = match[2];
19
- const multipliers = { d: 86_400_000, h: 3_600_000, m: 60_000 };
20
- return value * multipliers[unit];
21
- }
3
+ import { WAITING_PHASES } from '@sensigo/realm';
4
+ import { parseDuration } from '../lib/parse-duration.js';
22
5
  /**
23
6
  * List all non-terminal runs idle for longer than `olderThan` and mark them abandoned.
24
7
  * @param options `olderThan` is a duration string; `dryRun` skips writes.
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/commands/cleanup.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAgD,EAChD,QAAkB;IAElB,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAElC,MAAM,QAAQ,GAAgB,EAAE,CAAC;IACjC,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;YACvB,SAAS;QACX,CAAC;QACD,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACtC,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;QACxD,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,QAAQ,CAAC,MAAM,CAAC;gBACpB,GAAG,GAAG;gBACN,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACtC,SAAS,EAAE,WAAW;gBACtB,cAAc,EAAE,IAAI;gBACpB,eAAe,EAAE,mCAAmC;aACrD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,0CAA0C,CAAC;KACvD,cAAc,CACb,yBAAyB,EACzB,iEAAiE,CAClE;KACA,MAAM,CAAC,WAAW,EAAE,8DAA8D,CAAC;KACnF,MAAM,CAAC,KAAK,EAAE,IAA6C,EAAE,EAAE;IAC9D,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC1B,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,uBAAuB,CAAC,CAAC;QACtD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,uBAAuB,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { Command } from 'commander';
2
+ export interface SweepOrphansOptions {
3
+ /** Minimum age (ms) a `.tmp` must have to be reaped. Rejected below `FLOOR_MS` — see above. */
4
+ olderThanMs: number;
5
+ /** true (default caller behavior): report only, never unlink. */
6
+ dryRun: boolean;
7
+ /** Injected clock for deterministic age math in tests; defaults to `new Date()`. */
8
+ now?: Date;
9
+ }
10
+ export interface SweepOrphansResult {
11
+ /** Reaped (force mode) or would-be-reaped (dry-run) `.tmp` paths. */
12
+ reaped: string[];
13
+ /** A candidate vanished on its own (lstat or unlink hit ENOENT) — benign, never a failure. */
14
+ already_gone: string[];
15
+ /** A candidate lstat'd to something other than ENOENT/regular-file/symlink (e.g. a directory
16
+ * unexpectedly named `*.tmp`), or a genuine unlink error (permissions, I/O). Loud on purpose —
17
+ * a type mismatch is never silently swallowed, in either dry-run or force mode. */
18
+ failed: Array<{
19
+ path: string;
20
+ error: string;
21
+ }>;
22
+ }
23
+ /**
24
+ * Reaps orphaned atomic-write `.tmp` files older than `options.olderThanMs`. `FLOOR_MS` is
25
+ * checked FIRST, before any filesystem access, so no caller — CLI action, test, or future
26
+ * consumer — can reach a delete without crossing it.
27
+ *
28
+ * Per-candidate rule (uses `lstat`, never `readdir({ withFileTypes: true })` — on WSL/9p
29
+ * `Dirent.d_type` can be `DT_UNKNOWN`, which would make every type check false and the sweep
30
+ * reap nothing):
31
+ * - `lstat` ENOENT (vanished before we could even examine it, or during the later `unlink`) →
32
+ * `already_gone`, in either mode — a benign race, never a failure.
33
+ * - a **symlink** → skipped silently (appears in no bucket). Never `unlink`ed, never followed.
34
+ * - anything else that is **not a regular file** (a directory unexpectedly named `*.tmp`, a
35
+ * socket, …) → `failed`, loud, in either mode — a type mismatch is never an ENOENT-style
36
+ * silent swallow, because it signals something anomalous in `runsDir` worth surfacing even
37
+ * from a dry-run.
38
+ * - a **future mtime** (negative age — clock skew) → skipped silently, never reaped.
39
+ * - a regular file younger than `olderThanMs` → skipped silently (almost certainly an in-flight
40
+ * write's temp).
41
+ * - a regular file older than `olderThanMs` → a reap candidate: in dry-run, its path lands in
42
+ * `reaped` (interpreted as "would reap") without any filesystem mutation; in force mode, it is
43
+ * `unlink`ed — success → `reaped`; ENOENT → `already_gone`; anything else → `failed`.
44
+ */
45
+ export declare function sweepOrphans(runsDir: string, options: SweepOrphansOptions): Promise<SweepOrphansResult>;
46
+ export declare const gcCommand: Command;
47
+ //# sourceMappingURL=gc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gc.d.ts","sourceRoot":"","sources":["../../src/commands/gc.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,MAAM,WAAW,mBAAmB;IAClC,+FAA+F;IAC/F,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,oFAAoF;IACpF,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,MAAM,WAAW,kBAAkB;IACjC,qEAAqE;IACrE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,8FAA8F;IAC9F,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB;;wFAEoF;IACpF,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAuBD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAsE7B;AA+DD,eAAO,MAAM,SAAS,SAwDlB,CAAC"}
@@ -0,0 +1,240 @@
1
+ // gc command — sweep orphaned atomic-write temps (issue #160, Phase 1: .tmp only).
2
+ //
3
+ // atomicWriteFile (packages/core/src/store/atomic-write.ts) writes a unique sibling temp
4
+ // (`${path}.<pid>.<counter>.tmp`) then POSIX-renames it over the target. A process dying between
5
+ // the write and the rename orphans that temp forever — it is not runId-keyed for the key-pointer
6
+ // case (`keys/<hash>.json.<pid>.*.tmp`), so `realm run purge` (#107), which acts by runId, can
7
+ // never reach it. Temps are invisible to `list()` (no `.json` suffix) but accumulate on disk
8
+ // regardless. Windows never produces a temp at all (`atomicWriteFile` falls back to plain
9
+ // `writeFile` on win32) — this sweep is a documented no-op there, not a design driver.
10
+ //
11
+ // Reaping a `.tmp` is unconditionally safe: if the sweep unlinks a temp mid-rename, the pending
12
+ // `rename` gets ENOENT, `atomicWriteFile`'s own catch best-effort-unlinks its temp + rethrows — the
13
+ // TARGET file is never touched (worst case: a spurious write error surfaces to the writer, never a
14
+ // torn file). Combined with the 1h floor below, an in-flight write's temp (age ≪ floor) is never
15
+ // even selected.
16
+ //
17
+ // Phase 1 = `.tmp` only. `.lock` reaping is deliberately split to #164 (deferred — proper-lockfile
18
+ // self-heals a live-path lock; only a purged-target's lock lingers, which is negligible). Run-less
19
+ // `trace-buffer-*.jsonl` WAL cleanup is #163. Neither is this command's job — see the report footer.
20
+ import { readdir, lstat, unlink, stat } from 'node:fs/promises';
21
+ import { join } from 'node:path';
22
+ import { Command } from 'commander';
23
+ import { WorkflowError } from '@sensigo/realm';
24
+ import { parseDuration } from '../lib/parse-duration.js';
25
+ /**
26
+ * Minimum `--older-than` the sweep will ever honor (1 hour) — a conservative floor for hygiene of
27
+ * non-urgent crash residue, and, forward-consistency-wise, the safety guard the deferred `.lock`
28
+ * reaping (#164) will also require; enforcing it here means #164 inherits an already-tested guard.
29
+ * Temps themselves are safe to reap at any age past a few seconds (see the module doc above) — this
30
+ * floor is conservatism, not the temp-safety mechanism. Module-private: the only way to reach a
31
+ * delete is through `sweepOrphans`, which checks this FIRST, before any filesystem access.
32
+ */
33
+ const FLOOR_MS = 3_600_000;
34
+ /**
35
+ * Every top-level `*.tmp` in `runsDir`, plus one level of recursion into `runsDir/keys/*.tmp` —
36
+ * `keys/` is the ONLY subdirectory any store ever creates in `runsDir` (verified: `JsonFileStore`'s
37
+ * `keysDir()`/`mkdir` calls are the only subdirectory creation anywhere in this codebase's
38
+ * `runsDir` usage). A plain `readdir(runsDir)` sees the `keys` entry itself (no `.json`/`.tmp`
39
+ * suffix, so it's filtered out) but NOT what's inside it — hence the explicit second `readdir`.
40
+ * Nothing else is recursed into; nothing else is globbed (no `*.lock` — that's #164).
41
+ * Tolerates a missing `runsDir` or a missing `keys/` (a fresh install, or one that never wrote a
42
+ * keyed run, legitimately lacks either) — a missing directory yields zero candidates, not a throw.
43
+ */
44
+ async function findTempCandidates(runsDir) {
45
+ const topLevel = await readdir(runsDir).catch(() => []);
46
+ const paths = topLevel.filter((f) => f.endsWith('.tmp')).map((f) => join(runsDir, f));
47
+ const keysDir = join(runsDir, 'keys');
48
+ const keysEntries = await readdir(keysDir).catch(() => []);
49
+ paths.push(...keysEntries.filter((f) => f.endsWith('.tmp')).map((f) => join(keysDir, f)));
50
+ return paths;
51
+ }
52
+ /**
53
+ * Reaps orphaned atomic-write `.tmp` files older than `options.olderThanMs`. `FLOOR_MS` is
54
+ * checked FIRST, before any filesystem access, so no caller — CLI action, test, or future
55
+ * consumer — can reach a delete without crossing it.
56
+ *
57
+ * Per-candidate rule (uses `lstat`, never `readdir({ withFileTypes: true })` — on WSL/9p
58
+ * `Dirent.d_type` can be `DT_UNKNOWN`, which would make every type check false and the sweep
59
+ * reap nothing):
60
+ * - `lstat` ENOENT (vanished before we could even examine it, or during the later `unlink`) →
61
+ * `already_gone`, in either mode — a benign race, never a failure.
62
+ * - a **symlink** → skipped silently (appears in no bucket). Never `unlink`ed, never followed.
63
+ * - anything else that is **not a regular file** (a directory unexpectedly named `*.tmp`, a
64
+ * socket, …) → `failed`, loud, in either mode — a type mismatch is never an ENOENT-style
65
+ * silent swallow, because it signals something anomalous in `runsDir` worth surfacing even
66
+ * from a dry-run.
67
+ * - a **future mtime** (negative age — clock skew) → skipped silently, never reaped.
68
+ * - a regular file younger than `olderThanMs` → skipped silently (almost certainly an in-flight
69
+ * write's temp).
70
+ * - a regular file older than `olderThanMs` → a reap candidate: in dry-run, its path lands in
71
+ * `reaped` (interpreted as "would reap") without any filesystem mutation; in force mode, it is
72
+ * `unlink`ed — success → `reaped`; ENOENT → `already_gone`; anything else → `failed`.
73
+ */
74
+ export async function sweepOrphans(runsDir, options) {
75
+ if (options.olderThanMs < FLOOR_MS) {
76
+ throw new WorkflowError(`--older-than must resolve to at least 1h (got ${options.olderThanMs}ms) — gc refuses to ` +
77
+ `reap crash residue younger than that, even with --force.`, {
78
+ code: 'VALIDATION_INPUT_SCHEMA',
79
+ category: 'VALIDATION',
80
+ agentAction: 'provide_input',
81
+ retryable: false,
82
+ details: { olderThanMs: options.olderThanMs, floorMs: FLOOR_MS },
83
+ });
84
+ }
85
+ const now = options.now ?? new Date();
86
+ const candidatePaths = await findTempCandidates(runsDir);
87
+ const result = { reaped: [], already_gone: [], failed: [] };
88
+ const toReap = [];
89
+ for (const path of candidatePaths) {
90
+ let info;
91
+ try {
92
+ info = await lstat(path);
93
+ }
94
+ catch (err) {
95
+ if (err.code === 'ENOENT') {
96
+ result.already_gone.push(path); // vanished between readdir and lstat
97
+ }
98
+ else {
99
+ result.failed.push({ path, error: err instanceof Error ? err.message : String(err) });
100
+ }
101
+ continue;
102
+ }
103
+ if (info.isSymbolicLink())
104
+ continue; // never unlink or follow a symlink — silent skip
105
+ if (!info.isFile()) {
106
+ result.failed.push({
107
+ path,
108
+ error: 'expected a regular file but found a different type (unexpected for a *.tmp name)',
109
+ });
110
+ continue;
111
+ }
112
+ const ageMs = now.getTime() - info.mtime.getTime();
113
+ if (ageMs < 0)
114
+ continue; // future mtime (clock skew) — skip, never reap
115
+ if (ageMs <= options.olderThanMs)
116
+ continue; // too fresh — most likely an in-flight write's temp
117
+ toReap.push(path);
118
+ }
119
+ if (options.dryRun) {
120
+ result.reaped = toReap;
121
+ return result;
122
+ }
123
+ for (const path of toReap) {
124
+ try {
125
+ await unlink(path);
126
+ result.reaped.push(path);
127
+ }
128
+ catch (err) {
129
+ if (err.code === 'ENOENT') {
130
+ result.already_gone.push(path); // vanished between lstat and unlink
131
+ }
132
+ else {
133
+ result.failed.push({ path, error: err instanceof Error ? err.message : String(err) });
134
+ }
135
+ }
136
+ }
137
+ return result;
138
+ }
139
+ /** Best-effort total bytes for a known list of paths — reporting-only, never gates reaping.
140
+ * Called against a fresh dry-run preview, so the paths are still on disk when stat'd. */
141
+ async function statPathBytes(paths) {
142
+ let total = 0;
143
+ await Promise.all(paths.map(async (p) => {
144
+ try {
145
+ const info = await stat(p);
146
+ total += info.size;
147
+ }
148
+ catch {
149
+ // vanished between the preview pass and this stat — best-effort, ignore.
150
+ }
151
+ }));
152
+ return total;
153
+ }
154
+ function formatBytes(n) {
155
+ if (n < 1024)
156
+ return `${n} B`;
157
+ if (n < 1024 * 1024)
158
+ return `${(n / 1024).toFixed(1)} KB`;
159
+ return `${(n / (1024 * 1024)).toFixed(1)} MB`;
160
+ }
161
+ /** So an operator doesn't distrust the tool when `runsDir` still holds residue gc deliberately
162
+ * does not touch — printed on every report, dry-run or force, empty or not. */
163
+ const NOT_REAPED_FOOTER = 'gc does NOT reap orphaned .lock dirs (deferred — issue #164) or run-less trace-buffer-*.jsonl ' +
164
+ 'WAL files (issue #163). Their presence in runsDir is expected and not a sign gc is broken.';
165
+ /** Prints the dry-run / force report shared by both code paths. `previewBytes` always comes from
166
+ * the initial (always non-destructive) preview pass — see the action below for why. */
167
+ function printGcReport(result, previewBytes, dryRun) {
168
+ const nothingToReport = result.reaped.length === 0 && result.already_gone.length === 0 && result.failed.length === 0;
169
+ if (nothingToReport) {
170
+ console.log('No orphaned .tmp files found to reap.');
171
+ }
172
+ else if (dryRun) {
173
+ console.log(`${result.reaped.length} orphaned .tmp file(s) WOULD be reaped (${formatBytes(previewBytes)} to free):`);
174
+ for (const p of result.reaped)
175
+ console.log(` • ${p}`);
176
+ if (result.already_gone.length > 0) {
177
+ console.log(`(${result.already_gone.length} candidate(s) already vanished on their own.)`);
178
+ }
179
+ }
180
+ else {
181
+ console.log(`Reaped ${result.reaped.length} orphaned .tmp file(s) (${formatBytes(previewBytes)} freed). ` +
182
+ `${result.already_gone.length} already gone, ${result.failed.length} failed.`);
183
+ }
184
+ for (const f of result.failed) {
185
+ console.error(` ✗ ${f.path}: ${f.error}`);
186
+ }
187
+ if (dryRun && !nothingToReport) {
188
+ console.log('\nRe-run with --force to actually delete.');
189
+ }
190
+ console.log(`\n${NOT_REAPED_FOOTER}`);
191
+ }
192
+ export const gcCommand = new Command('gc')
193
+ .description('Sweep orphaned atomic-write .tmp files — crash residue from a process that died mid-write (dry-run by default)')
194
+ .requiredOption('--older-than <duration>', 'Reap temps idle at least this long (minimum 1h; e.g. 1h, 6h, 30d)')
195
+ .option('--force', 'Actually delete (without this, gc only reports what WOULD be reaped)')
196
+ .action(async (opts) => {
197
+ let olderThanMs;
198
+ try {
199
+ olderThanMs = parseDuration(opts.olderThan);
200
+ }
201
+ catch (err) {
202
+ console.error(err instanceof Error ? err.message : String(err));
203
+ process.exit(1);
204
+ return;
205
+ }
206
+ // Defense-in-depth over sweepOrphans's own floor check — reject before touching the
207
+ // filesystem at all, with a CLI-friendly message naming the flag the operator just typed.
208
+ if (olderThanMs < FLOOR_MS) {
209
+ console.error(`--older-than must be at least 1h (got '${opts.olderThan}'). gc refuses to reap crash ` +
210
+ `residue younger than that, even with --force.`);
211
+ process.exit(1);
212
+ return;
213
+ }
214
+ const { JsonFileStore } = await import('@sensigo/realm');
215
+ const runsDir = new JsonFileStore().runsDirPath;
216
+ const now = new Date();
217
+ try {
218
+ // Always preview first — this NEVER mutates, in either mode — because it is the only
219
+ // reliable moment to `stat()` the candidates for the report's byte total: a force-mode
220
+ // reap deletes the files before sweepOrphans returns, so statting them afterward is
221
+ // impossible. The preview and the (optional) real pass share the same olderThanMs/now, so
222
+ // the candidate set is consistent bar a narrow, benign concurrent-activity window — which
223
+ // already_gone exists to absorb.
224
+ const preview = await sweepOrphans(runsDir, { olderThanMs, dryRun: true, now });
225
+ const bytes = await statPathBytes(preview.reaped);
226
+ if (opts.force !== true) {
227
+ printGcReport(preview, bytes, true);
228
+ return;
229
+ }
230
+ const result = await sweepOrphans(runsDir, { olderThanMs, dryRun: false, now });
231
+ printGcReport(result, bytes, false);
232
+ if (result.failed.length > 0)
233
+ process.exit(1);
234
+ }
235
+ catch (err) {
236
+ console.error(err instanceof Error ? err.message : String(err));
237
+ process.exit(1);
238
+ }
239
+ });
240
+ //# sourceMappingURL=gc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gc.js","sourceRoot":"","sources":["../../src/commands/gc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ import { Command } from 'commander';
2
+ import type { RunRecord, RunStore, PerRunArtifactStore } from '@sensigo/realm';
3
+ export type PurgeEligibility = {
4
+ eligible: true;
5
+ overriddenClaimStep?: string | undefined;
6
+ } | {
7
+ eligible: false;
8
+ reason: string;
9
+ };
10
+ /**
11
+ * The safety-critical selection predicate (mirrors `isAutoReclaimable` in reclaim.ts) — mode-aware
12
+ * (issue #107 correction): the caller MUST state whether this is an explicit single-id purge
13
+ * (`explicit: true` — the operator named this exact run) or a batch/cron sweep (`explicit: false`).
14
+ * There is no default; a future call site is forced to pick a mode rather than silently inheriting
15
+ * the more permissive one.
16
+ *
17
+ * Worst-claim-wins ordering across every in-progress claim on the run:
18
+ * 1. `healthy` (future deadline) → REFUSE in both modes. No override — the runner is provably
19
+ * still alive; this is the one hard line purge will never cross.
20
+ * 2. `claim_unknown_age` (no deadline — agent step / finalizer-bearing / pre-#101 run) → refuse in
21
+ * batch (a cron sweep cannot prove the runner is dead and must not guess — mirrors
22
+ * `reclaim.isAutoReclaimable`'s own refusal of this exact state), but ELIGIBLE when explicit —
23
+ * the operator named this run directly, which is deliberate judgment a batch sweep can't make.
24
+ * 3. `claim_stale` (past deadline) or no in-progress claim at all → eligible in both modes.
25
+ *
26
+ * A run this predicate rejects can never enter `selected`; an explicit-mode acceptance of case 2
27
+ * carries `overriddenClaimStep` so the report can surface that the override fired.
28
+ */
29
+ export declare function isPurgeEligible(run: RunRecord, opts: {
30
+ explicit: boolean;
31
+ now?: Date;
32
+ }): PurgeEligibility;
33
+ export interface PurgeCandidate {
34
+ run: RunRecord;
35
+ bytes: number;
36
+ resumable: boolean;
37
+ /**
38
+ * Set (to the step name) when this run was selected ONLY because an explicit single-id purge
39
+ * accepted a `claim_unknown_age` (indeterminate-age) claim that batch mode would have skipped
40
+ * (issue #107 correction). Always undefined for a batch-mode selection.
41
+ */
42
+ overriddenClaimStep?: string | undefined;
43
+ }
44
+ export interface PurgeRunsResult {
45
+ /** Runs selected for purge (eligible, and — in batch mode — past the age threshold). */
46
+ selected: PurgeCandidate[];
47
+ /** Runs considered but rejected by `isPurgeEligible`, with the reason. */
48
+ skipped: Array<{
49
+ runId: string;
50
+ reason: string;
51
+ }>;
52
+ /** Populated only when `dryRun` is false: runs actually deleted. */
53
+ purged: string[];
54
+ /** Populated only when `dryRun` is false: a concurrent/prior purge had already removed it — never a failure. */
55
+ already_purged: string[];
56
+ /** Populated only when `dryRun` is false: deletion genuinely failed. */
57
+ failed: Array<{
58
+ runId: string;
59
+ error: string;
60
+ }>;
61
+ }
62
+ export interface PurgeRunsOptions {
63
+ /** Single-run mode: the run to purge. Mutually exclusive with `olderThan`. */
64
+ runId?: string | undefined;
65
+ /** Batch mode: purge every eligible run idle at least this long (e.g. "30d", "6h"). */
66
+ olderThan?: string | undefined;
67
+ /** Batch mode: restrict to runs of this workflow. */
68
+ workflow?: string | undefined;
69
+ /** Default true (safe). Only when explicitly false does this function delete anything. */
70
+ dryRun?: boolean | undefined;
71
+ }
72
+ /**
73
+ * Selects eligible run(s) (single `runId` or a batch aged past `olderThan`), reports bytes and
74
+ * resumability, and — when `dryRun` is false — deletes them via `artifactStores`, in the order
75
+ * given (LOAD-BEARING: `runStore`, the `JsonFileStore` element, must be last — see purge.ts's
76
+ * command wiring and `purge-guard.test.ts`). Continue-on-error across the batch: a
77
+ * `STATE_RUN_NOT_FOUND` hit while deleting (a concurrent purge already removed it) is bucketed as
78
+ * `already_purged`, never `failed` — a benign race must not be reported as a failure.
79
+ */
80
+ export declare function purgeRuns(options: PurgeRunsOptions, runStore: Pick<RunStore, 'get' | 'list'> & {
81
+ readonly runsDirPath: string;
82
+ }, artifactStores: PerRunArtifactStore[]): Promise<PurgeRunsResult>;
83
+ export declare const purgeCommand: Command;
84
+ //# sourceMappingURL=purge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"purge.d.ts","sourceRoot":"","sources":["../../src/commands/purge.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAS/E,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAC5D;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,SAAS,EACd,IAAI,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAA;CAAE,GACtC,gBAAgB,CAiClB;AA+BD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,SAAS,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,wFAAwF;IACxF,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,0EAA0E;IAC1E,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClD,oEAAoE;IACpE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gHAAgH;IAChH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,wEAAwE;IACxE,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,gBAAgB;IAC/B,8EAA8E;IAC9E,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,0FAA0F;IAC1F,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,GAAG,MAAM,CAAC,GAAG;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAC3E,cAAc,EAAE,mBAAmB,EAAE,GACpC,OAAO,CAAC,eAAe,CAAC,CAsF1B;AAuED,eAAO,MAAM,YAAY,SAoEtB,CAAC"}
@@ -0,0 +1,297 @@
1
+ // purge command — the operator-invoked, IRREVERSIBLE run-deletion primitive (issue #107).
2
+ //
3
+ // Deletes a terminal/abandoned run and ALL its co-located on-disk artifacts (run file + the
4
+ // idempotency-key pointer when owned, the failed-attempt sidecar, orphaned WAL trace-buffer files)
5
+ // via the PerRunArtifactStore marker — no store or command hard-codes another store's filename
6
+ // layout; each store deletes only its own artifacts. Dry-run by default; `--force` to actually
7
+ // delete (a single <id> ALSO requires `--force` — naming a run is selection, not consent).
8
+ //
9
+ // Non-negotiable invariants (do not weaken): terminal-only (never a non-terminal or `gate_waiting`
10
+ // run). Claim posture (issue #107 correction) is mode-aware: a `healthy` (future-deadline) claim is
11
+ // NEVER purged, in either mode — there is no override, because a live runner is provably still
12
+ // working it. A `claim_unknown_age` (null-deadline) claim — load-bearing for `abandoned` runs, which
13
+ // do not clear `claims` (see cleanup.ts) — is skipped+warned in BATCH mode (a cron sweep cannot prove
14
+ // the runner is dead and must not guess), but IS purgeable via an explicit single-id
15
+ // `realm run purge <id> --force` — the operator named this exact run, a deliberate judgment call
16
+ // `reclaim`'s own batch mode also refuses to make automatically. A `claim_stale` (past-deadline)
17
+ // claim, or no in-progress claim at all, is purgeable in both modes.
18
+ import { readdir, stat } from 'node:fs/promises';
19
+ import { join } from 'node:path';
20
+ import { Command } from 'commander';
21
+ import { WorkflowError, TERMINAL_PHASES, RESUMABLE_PHASES, classifyInProgressClaims, } from '@sensigo/realm';
22
+ import { parseDuration } from '../lib/parse-duration.js';
23
+ /**
24
+ * The safety-critical selection predicate (mirrors `isAutoReclaimable` in reclaim.ts) — mode-aware
25
+ * (issue #107 correction): the caller MUST state whether this is an explicit single-id purge
26
+ * (`explicit: true` — the operator named this exact run) or a batch/cron sweep (`explicit: false`).
27
+ * There is no default; a future call site is forced to pick a mode rather than silently inheriting
28
+ * the more permissive one.
29
+ *
30
+ * Worst-claim-wins ordering across every in-progress claim on the run:
31
+ * 1. `healthy` (future deadline) → REFUSE in both modes. No override — the runner is provably
32
+ * still alive; this is the one hard line purge will never cross.
33
+ * 2. `claim_unknown_age` (no deadline — agent step / finalizer-bearing / pre-#101 run) → refuse in
34
+ * batch (a cron sweep cannot prove the runner is dead and must not guess — mirrors
35
+ * `reclaim.isAutoReclaimable`'s own refusal of this exact state), but ELIGIBLE when explicit —
36
+ * the operator named this run directly, which is deliberate judgment a batch sweep can't make.
37
+ * 3. `claim_stale` (past deadline) or no in-progress claim at all → eligible in both modes.
38
+ *
39
+ * A run this predicate rejects can never enter `selected`; an explicit-mode acceptance of case 2
40
+ * carries `overriddenClaimStep` so the report can surface that the override fired.
41
+ */
42
+ export function isPurgeEligible(run, opts) {
43
+ if (!TERMINAL_PHASES.has(run.run_phase)) {
44
+ return { eligible: false, reason: `not terminal (phase: '${run.run_phase}')` };
45
+ }
46
+ const now = opts.now ?? new Date();
47
+ const claims = classifyInProgressClaims(run, now);
48
+ const healthyClaim = claims.find((c) => c.state === 'healthy');
49
+ if (healthyClaim !== undefined) {
50
+ return {
51
+ eligible: false,
52
+ reason: `run carries a future-deadline claim on step '${healthyClaim.step}' ` +
53
+ `(deadline: ${healthyClaim.deadline}) — a live runner may still be working it`,
54
+ };
55
+ }
56
+ const unknownAgeClaim = claims.find((c) => c.state === 'claim_unknown_age');
57
+ if (unknownAgeClaim !== undefined) {
58
+ if (!opts.explicit) {
59
+ return {
60
+ eligible: false,
61
+ reason: `run carries an indeterminate-age claim on step '${unknownAgeClaim.step}' ` +
62
+ `(no deadline recorded — a runner may or may not still be working it); skipped in batch; ` +
63
+ `run 'realm run purge ${run.id} --force' to purge it explicitly.`,
64
+ };
65
+ }
66
+ return { eligible: true, overriddenClaimStep: unknownAgeClaim.step };
67
+ }
68
+ return { eligible: true };
69
+ }
70
+ /**
71
+ * Best-effort on-disk bytes for `runId`: stat every `runsDir` entry whose name CONTAINS the runId
72
+ * (the run file `<id>.json`, `trace-buffer-<id>-*.jsonl`, `<id>.attempts.jsonl`). Reporting-only —
73
+ * this never gates or drives deletion (that stays exclusively behind each store's own
74
+ * `deleteAllForRun`) — and may under-count by the idempotency-key pointer's few dozen bytes: that
75
+ * file is content-addressed by `sha256(workflow_id\0key)`, not the runId, so a runId-substring scan
76
+ * structurally cannot find it (by design — that hash is JsonFileStore-private, and this function
77
+ * must not replicate another store's filename layout to go looking for it).
78
+ */
79
+ async function statMatchedBytes(runsDir, runId, dirEntries) {
80
+ const matched = dirEntries.filter((f) => f.includes(runId));
81
+ let total = 0;
82
+ await Promise.all(matched.map(async (f) => {
83
+ try {
84
+ const info = await stat(join(runsDir, f));
85
+ total += info.size;
86
+ }
87
+ catch {
88
+ // vanished between the scan and this stat — best-effort, ignore.
89
+ }
90
+ }));
91
+ return total;
92
+ }
93
+ /**
94
+ * Selects eligible run(s) (single `runId` or a batch aged past `olderThan`), reports bytes and
95
+ * resumability, and — when `dryRun` is false — deletes them via `artifactStores`, in the order
96
+ * given (LOAD-BEARING: `runStore`, the `JsonFileStore` element, must be last — see purge.ts's
97
+ * command wiring and `purge-guard.test.ts`). Continue-on-error across the batch: a
98
+ * `STATE_RUN_NOT_FOUND` hit while deleting (a concurrent purge already removed it) is bucketed as
99
+ * `already_purged`, never `failed` — a benign race must not be reported as a failure.
100
+ */
101
+ export async function purgeRuns(options, runStore, artifactStores) {
102
+ const dryRun = options.dryRun ?? true;
103
+ const now = new Date();
104
+ const runsDir = runStore.runsDirPath;
105
+ const candidates = [];
106
+ const skipped = [];
107
+ if (options.runId !== undefined) {
108
+ const run = await runStore.get(options.runId);
109
+ // explicit: true — the operator named this exact run, so a claim_unknown_age claim is an
110
+ // eligible override, never a healthy one (issue #107 correction).
111
+ const verdict = isPurgeEligible(run, { explicit: true, now });
112
+ if (verdict.eligible) {
113
+ candidates.push({ run, overriddenClaimStep: verdict.overriddenClaimStep });
114
+ }
115
+ else {
116
+ skipped.push({ runId: run.id, reason: verdict.reason });
117
+ }
118
+ }
119
+ else {
120
+ const thresholdMs = options.olderThan !== undefined ? parseDuration(options.olderThan) : 0;
121
+ const all = await runStore.list(options.workflow);
122
+ for (const run of all) {
123
+ // explicit: false — a batch/cron sweep cannot prove an indeterminate-age claim's runner is
124
+ // dead, so claim_unknown_age is refused here (skipped+warned below), not overridden.
125
+ const verdict = isPurgeEligible(run, { explicit: false, now });
126
+ if (!verdict.eligible) {
127
+ // Only a terminal-but-blocked run (a future or indeterminate-age claim) is a noteworthy
128
+ // skip+warn — a plain non-terminal run isn't a purge candidate in the first place and
129
+ // needn't be noisy.
130
+ if (TERMINAL_PHASES.has(run.run_phase)) {
131
+ skipped.push({ runId: run.id, reason: verdict.reason });
132
+ }
133
+ continue;
134
+ }
135
+ const idleMs = now.getTime() - new Date(run.updated_at).getTime();
136
+ if (idleMs < thresholdMs)
137
+ continue;
138
+ candidates.push({ run, overriddenClaimStep: verdict.overriddenClaimStep });
139
+ }
140
+ }
141
+ // One readdir up front (batch or single) → passed as dirEntries to every store, so a batch of N
142
+ // runs costs O(readdir) once, not O(N × readdir) per JsonTraceBufferStore glob scan.
143
+ let dirEntries;
144
+ try {
145
+ dirEntries = await readdir(runsDir);
146
+ }
147
+ catch {
148
+ dirEntries = [];
149
+ }
150
+ const selected = [];
151
+ for (const { run, overriddenClaimStep } of candidates) {
152
+ const bytes = await statMatchedBytes(runsDir, run.id, dirEntries);
153
+ selected.push({
154
+ run,
155
+ bytes,
156
+ resumable: RESUMABLE_PHASES.has(run.run_phase),
157
+ overriddenClaimStep,
158
+ });
159
+ }
160
+ const result = { selected, skipped, purged: [], already_purged: [], failed: [] };
161
+ if (dryRun)
162
+ return result;
163
+ for (const { run } of selected) {
164
+ try {
165
+ // Re-check the run still exists immediately before deleting — closes the window against a
166
+ // concurrent purge that already removed it between selection and here. A STATE_RUN_NOT_FOUND
167
+ // surfacing here means "already gone," which the catch below routes to already_purged.
168
+ await runStore.get(run.id);
169
+ for (const store of artifactStores) {
170
+ await store.deleteAllForRun(run.id, dirEntries);
171
+ }
172
+ result.purged.push(run.id);
173
+ }
174
+ catch (err) {
175
+ if (err instanceof WorkflowError && err.code === 'STATE_RUN_NOT_FOUND') {
176
+ result.already_purged.push(run.id);
177
+ }
178
+ else {
179
+ result.failed.push({
180
+ runId: run.id,
181
+ error: err instanceof Error ? err.message : String(err),
182
+ });
183
+ }
184
+ }
185
+ }
186
+ return result;
187
+ }
188
+ function formatBytes(n) {
189
+ if (n < 1024)
190
+ return `${n} B`;
191
+ if (n < 1024 * 1024)
192
+ return `${(n / 1024).toFixed(1)} KB`;
193
+ return `${(n / (1024 * 1024)).toFixed(1)} MB`;
194
+ }
195
+ /**
196
+ * The override-transparency phrase (issue #107 correction): every candidate purged only because an
197
+ * explicit single-id override accepted its indeterminate-age claim must say so, in both dry-run and
198
+ * force output — this can only ever be non-empty for a single-id selection (batch always calls
199
+ * `isPurgeEligible` with `explicit: false`, so a `claim_unknown_age` run there lands in `skipped`,
200
+ * never `selected` — see `purgeRuns`).
201
+ */
202
+ function overriddenClaimPhrase(step, dryRun) {
203
+ const verb = dryRun ? 'would purge' : 'purged';
204
+ return (`${verb} despite an indeterminate-age claim on step '${step}' (no deadline recorded — a runner ` +
205
+ `may or may not still be working it; explicit single-run override proceeds anyway)`);
206
+ }
207
+ /** Prints the dry-run / force report shared by both single-run and batch mode. */
208
+ function printPurgeReport(result, dryRun) {
209
+ for (const s of result.skipped) {
210
+ console.warn(`⚠ skipping ${s.runId}: ${s.reason}`);
211
+ }
212
+ if (result.selected.length === 0) {
213
+ console.log('No eligible runs found to purge.');
214
+ return;
215
+ }
216
+ const totalBytes = result.selected.reduce((sum, c) => sum + c.bytes, 0);
217
+ const resumableCount = result.selected.filter((c) => c.resumable).length;
218
+ const resumableLine = `${resumableCount} of ${result.selected.length} selected run(s) ` +
219
+ `${dryRun ? 'are' : 'were'} resumable via 'realm resume' — ` +
220
+ `purging ${dryRun ? 'would destroy' : 'has destroyed'} that path ${dryRun ? 'permanently' : 'for them'}.`;
221
+ if (dryRun) {
222
+ console.log(`${result.selected.length} run(s) WOULD be purged (${formatBytes(totalBytes)} to free):`);
223
+ for (const c of result.selected) {
224
+ const override = c.overriddenClaimStep !== undefined
225
+ ? ` — ${overriddenClaimPhrase(c.overriddenClaimStep, true)}`
226
+ : '';
227
+ console.log(` • ${c.run.id} (${c.run.run_phase}, ${formatBytes(c.bytes)})${override}`);
228
+ }
229
+ console.log(`\n${resumableLine}\nRe-run with --force to actually delete.`);
230
+ return;
231
+ }
232
+ console.log(`Purged ${result.purged.length}/${result.selected.length} run(s) (${formatBytes(totalBytes)} freed). ` +
233
+ `${result.already_purged.length} already gone, ${result.failed.length} failed.`);
234
+ for (const c of result.selected) {
235
+ if (c.overriddenClaimStep !== undefined) {
236
+ console.log(` ⚠ ${c.run.id}: ${overriddenClaimPhrase(c.overriddenClaimStep, false)}`);
237
+ }
238
+ }
239
+ for (const f of result.failed) {
240
+ console.error(` ✗ ${f.runId}: ${f.error}`);
241
+ }
242
+ console.log(resumableLine);
243
+ }
244
+ export const purgeCommand = new Command('purge')
245
+ .description('Permanently delete a terminal run and all its co-located artifacts (IRREVERSIBLE — dry-run by default)')
246
+ .argument('[run-id]', 'ID of the run to purge; omit when using --older-than for batch mode')
247
+ .option('--force', 'Actually delete (without this, purge only reports what WOULD be deleted)')
248
+ .option('--older-than <duration>', 'Batch mode: purge every eligible run idle at least this long (e.g. 30d, 6h, 10m)')
249
+ .option('--workflow <id>', 'With --older-than: only consider runs of this workflow')
250
+ .action(async (runId, opts) => {
251
+ if (runId !== undefined && opts.olderThan !== undefined) {
252
+ console.error('Cannot combine a <run-id> with --older-than. Use one or the other.');
253
+ process.exit(1);
254
+ }
255
+ if (runId === undefined && opts.olderThan === undefined) {
256
+ console.error('Provide a <run-id> to purge, or use --older-than for batch mode.');
257
+ process.exit(1);
258
+ }
259
+ if (runId !== undefined && opts.workflow !== undefined) {
260
+ console.error('--workflow is only valid with --older-than.');
261
+ process.exit(1);
262
+ }
263
+ const { JsonFileStore, FailedAttemptStore } = await import('@sensigo/realm');
264
+ const { JsonTraceBufferStore } = await import('@sensigo/realm-mcp');
265
+ const runStore = new JsonFileStore();
266
+ const runsDir = runStore.runsDirPath;
267
+ const failedAttemptStore = new FailedAttemptStore(runsDir);
268
+ const traceBufferStore = new JsonTraceBufferStore(runsDir);
269
+ // Orchestration order is LOAD-BEARING (issue #107): runStore MUST be last — a crash mid-purge
270
+ // leaves the run record in place, so the run is re-enumerated and the purge is retried
271
+ // idempotently. purge-guard.test.ts asserts this exact order via source-text — do not
272
+ // reorder these three lines without updating that test.
273
+ const artifactStores = [
274
+ traceBufferStore, // JsonTraceBufferStore
275
+ failedAttemptStore, // FailedAttemptStore
276
+ runStore, // JsonFileStore — LAST: crash-anchor (issue #107)
277
+ ];
278
+ const dryRun = opts.force !== true;
279
+ try {
280
+ const result = await purgeRuns({ runId, olderThan: opts.olderThan, workflow: opts.workflow, dryRun }, runStore, artifactStores);
281
+ if (runId !== undefined && result.selected.length === 0) {
282
+ // Single-run mode, rejected by isPurgeEligible: a REFUSAL (exit 1), not a quiet skip —
283
+ // mirrors reclaim.ts's explicit per-step refusals.
284
+ const reason = result.skipped[0]?.reason ?? 'not eligible';
285
+ console.error(`Refusing to purge '${runId}': ${reason}.`);
286
+ process.exit(1);
287
+ }
288
+ printPurgeReport(result, dryRun);
289
+ if (result.failed.length > 0)
290
+ process.exit(1);
291
+ }
292
+ catch (err) {
293
+ console.error(err instanceof Error ? err.message : String(err));
294
+ process.exit(1);
295
+ }
296
+ });
297
+ //# sourceMappingURL=purge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"purge.js","sourceRoot":"","sources":["../../src/commands/purge.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,EAAE;AACF,4FAA4F;AAC5F,mGAAmG;AACnG,+FAA+F;AAC/F,+FAA+F;AAC/F,2FAA2F;AAC3F,EAAE;AACF,mGAAmG;AACnG,oGAAoG;AACpG,+FAA+F;AAC/F,qGAAqG;AACrG,sGAAsG;AACtG,qFAAqF;AACrF,iGAAiG;AACjG,iGAAiG;AACjG,qEAAqE;AACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAMzD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAc,EACd,IAAuC;IAEvC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,yBAAyB,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;IACjF,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACnC,MAAM,MAAM,GAAG,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAElD,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IAC/D,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO;YACL,QAAQ,EAAE,KAAK;YACf,MAAM,EACJ,gDAAgD,YAAY,CAAC,IAAI,IAAI;gBACrE,cAAc,YAAY,CAAC,QAAQ,2CAA2C;SACjF,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,mBAAmB,CAAC,CAAC;IAC5E,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO;gBACL,QAAQ,EAAE,KAAK;gBACf,MAAM,EACJ,mDAAmD,eAAe,CAAC,IAAI,IAAI;oBAC3E,0FAA0F;oBAC1F,wBAAwB,GAAG,CAAC,EAAE,mCAAmC;aACpE,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,mBAAmB,EAAE,eAAe,CAAC,IAAI,EAAE,CAAC;IACvE,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,KAAK,UAAU,gBAAgB,CAC7B,OAAe,EACf,KAAa,EACb,UAA6B;IAE7B,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,OAAO,CAAC,GAAG,CACf,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACtB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAC1C,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,iEAAiE;QACnE,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC;AAsCD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,OAAyB,EACzB,QAA2E,EAC3E,cAAqC;IAErC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC;IACtC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC;IAErC,MAAM,UAAU,GAAwE,EAAE,CAAC;IAC3F,MAAM,OAAO,GAA6C,EAAE,CAAC;IAE7D,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9C,yFAAyF;QACzF,kEAAkE;QAClE,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9D,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,WAAW,GAAG,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3F,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClD,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;YACtB,2FAA2F;YAC3F,qFAAqF;YACrF,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC/D,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACtB,wFAAwF;gBACxF,sFAAsF;gBACtF,oBAAoB;gBACpB,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACvC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC1D,CAAC;gBACD,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;YAClE,IAAI,MAAM,GAAG,WAAW;gBAAE,SAAS;YACnC,UAAU,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,gGAAgG;IAChG,qFAAqF;IACrF,IAAI,UAAoB,CAAC;IACzB,IAAI,CAAC;QACH,UAAU,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,GAAG,EAAE,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,KAAK,MAAM,EAAE,GAAG,EAAE,mBAAmB,EAAE,IAAI,UAAU,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAClE,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG;YACH,KAAK;YACL,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC;YAC9C,mBAAmB;SACpB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAoB,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAClG,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC;YACH,0FAA0F;YAC1F,6FAA6F;YAC7F,uFAAuF;YACvF,MAAM,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3B,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAClD,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,aAAa,IAAI,GAAG,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;gBACvE,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;oBACjB,KAAK,EAAE,GAAG,CAAC,EAAE;oBACb,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,CAAS;IAC5B,IAAI,CAAC,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC;IAC9B,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAC1D,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,SAAS,qBAAqB,CAAC,IAAY,EAAE,MAAe;IAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC/C,OAAO,CACL,GAAG,IAAI,gDAAgD,IAAI,qCAAqC;QAChG,mFAAmF,CACpF,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,SAAS,gBAAgB,CAAC,MAAuB,EAAE,MAAe;IAChE,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACxE,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;IACzE,MAAM,aAAa,GACjB,GAAG,cAAc,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,mBAAmB;QACjE,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,kCAAkC;QAC5D,WAAW,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,cAAc,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC;IAE5G,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CACT,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,4BAA4B,WAAW,CAAC,UAAU,CAAC,YAAY,CACzF,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,QAAQ,GACZ,CAAC,CAAC,mBAAmB,KAAK,SAAS;gBACjC,CAAC,CAAC,MAAM,qBAAqB,CAAC,CAAC,CAAC,mBAAmB,EAAE,IAAI,CAAC,EAAE;gBAC5D,CAAC,CAAC,EAAE,CAAC;YACT,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC,CAAC;QAC3F,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,aAAa,2CAA2C,CAAC,CAAC;QAC3E,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CACT,UAAU,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,YAAY,WAAW,CAAC,UAAU,CAAC,WAAW;QACpG,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,kBAAkB,MAAM,CAAC,MAAM,CAAC,MAAM,UAAU,CAClF,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,qBAAqB,CAAC,CAAC,CAAC,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CACV,wGAAwG,CACzG;KACA,QAAQ,CAAC,UAAU,EAAE,qEAAqE,CAAC;KAC3F,MAAM,CAAC,SAAS,EAAE,0EAA0E,CAAC;KAC7F,MAAM,CACL,yBAAyB,EACzB,kFAAkF,CACnF;KACA,MAAM,CAAC,iBAAiB,EAAE,wDAAwD,CAAC;KACnF,MAAM,CACL,KAAK,EACH,KAAyB,EACzB,IAAgE,EAChE,EAAE;IACF,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACxD,OAAO,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACxD,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC7E,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC;IACrC,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC3D,8FAA8F;IAC9F,uFAAuF;IACvF,sFAAsF;IACtF,wDAAwD;IACxD,MAAM,cAAc,GAA0B;QAC5C,gBAAgB,EAAE,uBAAuB;QACzC,kBAAkB,EAAE,qBAAqB;QACzC,QAAQ,EAAE,kDAAkD;KAC7D,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAC5B,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,EACrE,QAAQ,EACR,cAAc,CACf,CAAC;QAEF,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,uFAAuF;YACvF,mDAAmD;YACnD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,cAAc,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,sBAAsB,KAAK,MAAM,MAAM,GAAG,CAAC,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"reclaim.d.ts","sourceRoot":"","sources":["../../src/commands/reclaim.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAerF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,cAAc,CAAC,EACvD,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAWT;AAED,eAAO,MAAM,cAAc,SA8NxB,CAAC"}
1
+ {"version":3,"file":"reclaim.d.ts","sourceRoot":"","sources":["../../src/commands/reclaim.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAGrF;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,cAAc,CAAC,EACvD,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,IAAI,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAWT;AAED,eAAO,MAAM,cAAc,SA8NxB,CAAC"}
@@ -6,18 +6,7 @@
6
6
  // default, `--force` to act — ONLY claims that are provably safe: author-declared `idempotent`,
7
7
  // carrying a concrete past-deadline (`claim_stale`), non-gated. Everything else stays per-step-only.
8
8
  import { Command } from 'commander';
9
- /** Parses a duration string such as "30d", "6h", or "10m" into milliseconds.
10
- * Mirrors cleanup.ts's private parseDuration (kept local — cleanup.ts is out of this PR's scope). */
11
- function parseDuration(s) {
12
- const match = /^(\d+)(d|h|m)$/.exec(s);
13
- if (match === null) {
14
- throw new Error(`Invalid duration '${s}'. Use format: <number>(d|h|m), e.g. 30d, 6h, 10m`);
15
- }
16
- const value = parseInt(match[1], 10);
17
- const unit = match[2];
18
- const multipliers = { d: 86_400_000, h: 3_600_000, m: 60_000 };
19
- return value * multipliers[unit];
20
- }
9
+ import { parseDuration } from '../lib/parse-duration.js';
21
10
  /**
22
11
  * The SAFETY-CRITICAL selection rule for `--all` auto-reclaim (issue #101 Phase 2, §3).
23
12
  * A claim is auto-reclaimable IFF ALL hold:
@@ -1 +1 @@
1
- {"version":3,"file":"reclaim.js","sourceRoot":"","sources":["../../src/commands/reclaim.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,sGAAsG;AACtG,qGAAqG;AACrG,+FAA+F;AAC/F,gGAAgG;AAChG,qGAAqG;AACrG,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC;sGACsG;AACtG,SAAS,aAAa,CAAC,CAAS;IAC9B,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,mDAAmD,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;IACvB,MAAM,WAAW,GAA2B,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACvF,OAAO,KAAK,GAAG,WAAW,CAAC,IAAI,CAAE,CAAC;AACpC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAuD,EACvD,KAA0B,EAC1B,OAAmC,EACnC,IAA2C;IAE3C,IAAI,GAAG,CAAC,cAAc;QAAE,OAAO,KAAK,CAAC,CAAC,OAAO;IAC7C,IAAI,KAAK,CAAC,KAAK,KAAK,aAAa;QAAE,OAAO,KAAK,CAAC,CAAC,+CAA+C;IAChG,IAAI,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,YAAY,EAAE,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,8BAA8B;IAC5F,IAAI,OAAO,EAAE,UAAU,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC,CAAC,0CAA0C;IAC1F,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACnC,mGAAmG;QACnG,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAC1C,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;IACrF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,mEAAmE,CAAC;KAChF,QAAQ,CAAC,UAAU,EAAE,sEAAsE,CAAC;KAC5F,MAAM,CAAC,eAAe,EAAE,4DAA4D,CAAC;KACrF,MAAM,CAAC,SAAS,EAAE,mEAAmE,CAAC;KACtF,MAAM,CACL,OAAO,EACP,8GAA8G,CAC/G;KACA,MAAM,CAAC,iBAAiB,EAAE,iDAAiD,CAAC;KAC5E,MAAM,CACL,yBAAyB,EACzB,gEAAgE,CACjE;KACA,MAAM,CACL,KAAK,EACH,KAAyB,EACzB,IAMC,EACD,EAAE;IACF,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,wBAAwB,EAAE,GAC/E,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAElC,4FAA4F;IAC5F,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CACX,qFAAqF,CACtF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,iFAAiF;IACjF,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACtB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,WAA+B,CAAC;QACpC,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,iBAAiB,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAyD,EAAE,CAAC;QAC1E,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,GAAG,CAAC,cAAc;oBAAE,SAAS;gBACjC,MAAM,MAAM,GAAG,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAClC,sFAAsF;gBACtF,oFAAoF;gBACpF,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBAC5E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC3B,MAAM,OAAO,GAAG,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACvC,MAAM,OAAO,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;oBAC3E,IAAI,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;wBACpD,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC1C,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CACT,qFAAqF,CACtF,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACxB,qEAAqE;YACrE,OAAO,CAAC,GAAG,CACT,GAAG,QAAQ,CAAC,MAAM,6EAA6E,CAChG,CAAC;YACF,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,QAAS,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC;gBAChF,OAAO,CAAC,GAAG,CACT,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,eAAe,KAAK,CAAC,QAAQ,KAAK,MAAM,SAAS,CAC5E,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,GAAG,CACT,+EAA+E;gBAC7E,gGAAgG,CACnG,CAAC;YACF,OAAO;QACT,CAAC;QAED,uFAAuF;QACvF,OAAO,CAAC,IAAI,CACV,qBAAqB,QAAQ,CAAC,MAAM,oEAAoE,CACzG,CAAC;QACF,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC7C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACzD,IAAI,MAAM,CAAC,OAAO,KAAK,WAAW;oBAAE,SAAS,IAAI,CAAC,CAAC;gBACnD,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC;YAC1F,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,wEAAwE;gBACxE,OAAO,CAAC,KAAK,CACX,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAClF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,aAAa,SAAS,IAAI,QAAQ,CAAC,MAAM,qBAAqB,CAAC,CAAC;QAC5E,OAAO;IACT,CAAC;IAED,iFAAiF;IACjF,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChE,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,0FAA0F;IAC1F,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACnD,OAAO,CAAC,KAAK,CACX,kGAAkG,CACnG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAEnC,2CAA2C;QAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,CACX,wBAAwB,IAAI,CAAC,IAAI,wDAAwD;oBACvF,sDAAsD,CACzD,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,IAAI,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7E,IAAI,IAAI,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,CACV,MAAM,IAAI,CAAC,IAAI,qEAAqE;oBAClF,0DAA0D,CAC7D,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,IAAI,CACV,iBAAiB,IAAI,CAAC,IAAI,aAAa,KAAK,+BAA+B;gBACzE,8BAA8B,CACjC,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1D,IAAI,MAAM,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,CACT,cAAc,IAAI,CAAC,IAAI,UAAU,MAAM,CAAC,UAAU,qCAAqC;oBACrF,wCAAwC,KAAK,sBAAsB,CACtE,CAAC;YACJ,CAAC;iBAAM,IAAI,MAAM,CAAC,OAAO,KAAK,iBAAiB,EAAE,CAAC;gBAChD,OAAO,CAAC,GAAG,CACT,IAAI,IAAI,CAAC,IAAI,qEAAqE,CACnF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CACT,IAAI,IAAI,CAAC,IAAI,kFAAkF,CAChG,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QAED,8EAA8E;QAC9E,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CACT,QAAQ,KAAK,kBAAkB,GAAG,CAAC,SAAS,iCAAiC,CAC9E,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CACT,QAAQ,KAAK,MAAM,GAAG,CAAC,SAAS,kDAAkD,CACnF,CAAC;YACF,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,GAAG,CAAC,SAAS,yBAAyB,CAAC,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,EAAE,SAAS,KAAK,CAAC,CAAC,IAAI,CAAC;YACrD,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,oBAAoB,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,gBAAgB,QAAQ,GAAG,CAAC,CAAC;YAClE,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,oDAAoD,KAAK,iBAAiB,CAAC,CAAC;YAC1F,CAAC;iBAAM,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,oCAAoC,KAAK,WAAW,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG,CACT,wEAAwE;YACtE,wFAAwF,CAC3F,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"reclaim.js","sourceRoot":"","sources":["../../src/commands/reclaim.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,sGAAsG;AACtG,qGAAqG;AACrG,+FAA+F;AAC/F,gGAAgG;AAChG,qGAAqG;AACrG,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAuD,EACvD,KAA0B,EAC1B,OAAmC,EACnC,IAA2C;IAE3C,IAAI,GAAG,CAAC,cAAc;QAAE,OAAO,KAAK,CAAC,CAAC,OAAO;IAC7C,IAAI,KAAK,CAAC,KAAK,KAAK,aAAa;QAAE,OAAO,KAAK,CAAC,CAAC,+CAA+C;IAChG,IAAI,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,YAAY,EAAE,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,8BAA8B;IAC5F,IAAI,OAAO,EAAE,UAAU,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC,CAAC,0CAA0C;IAC1F,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACnC,mGAAmG;QACnG,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAC1C,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;IACrF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,mEAAmE,CAAC;KAChF,QAAQ,CAAC,UAAU,EAAE,sEAAsE,CAAC;KAC5F,MAAM,CAAC,eAAe,EAAE,4DAA4D,CAAC;KACrF,MAAM,CAAC,SAAS,EAAE,mEAAmE,CAAC;KACtF,MAAM,CACL,OAAO,EACP,8GAA8G,CAC/G;KACA,MAAM,CAAC,iBAAiB,EAAE,iDAAiD,CAAC;KAC5E,MAAM,CACL,yBAAyB,EACzB,gEAAgE,CACjE;KACA,MAAM,CACL,KAAK,EACH,KAAyB,EACzB,IAMC,EACD,EAAE;IACF,MAAM,EAAE,aAAa,EAAE,iBAAiB,EAAE,WAAW,EAAE,wBAAwB,EAAE,GAC/E,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAElC,4FAA4F;IAC5F,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CACX,qFAAqF,CACtF,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,iFAAiF;IACjF,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;QACtB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;YAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,WAA+B,CAAC;QACpC,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC;gBACH,WAAW,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,MAAM,aAAa,GAAG,IAAI,iBAAiB,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,QAAQ,GAAyD,EAAE,CAAC;QAC1E,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,IAAI,GAAG,CAAC,cAAc;oBAAE,SAAS;gBACjC,MAAM,MAAM,GAAG,wBAAwB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;gBACtD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAS;gBAClC,sFAAsF;gBACtF,oFAAoF;gBACpF,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBAC5E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBAC3B,MAAM,OAAO,GAAG,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACvC,MAAM,OAAO,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;oBAC3E,IAAI,iBAAiB,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;wBACpD,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;oBAC1C,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CACT,qFAAqF,CACtF,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACxB,qEAAqE;YACrE,OAAO,CAAC,GAAG,CACT,GAAG,QAAQ,CAAC,MAAM,6EAA6E,CAChG,CAAC;YACF,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,QAAS,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC;gBAChF,OAAO,CAAC,GAAG,CACT,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,eAAe,KAAK,CAAC,QAAQ,KAAK,MAAM,SAAS,CAC5E,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,GAAG,CACT,+EAA+E;gBAC7E,gGAAgG,CACnG,CAAC;YACF,OAAO;QACT,CAAC;QAED,uFAAuF;QACvF,OAAO,CAAC,IAAI,CACV,qBAAqB,QAAQ,CAAC,MAAM,oEAAoE,CACzG,CAAC;QACF,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC7C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACzD,IAAI,MAAM,CAAC,OAAO,KAAK,WAAW;oBAAE,SAAS,IAAI,CAAC,CAAC;gBACnD,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,CAAC,UAAU,GAAG,CAAC,CAAC;YAC1F,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,wEAAwE;gBACxE,OAAO,CAAC,KAAK,CACX,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAClF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,aAAa,SAAS,IAAI,QAAQ,CAAC,MAAM,qBAAqB,CAAC,CAAC;QAC5E,OAAO;IACT,CAAC;IAED,iFAAiF;IACjF,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChE,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,qEAAqE,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,0FAA0F;IAC1F,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACnD,OAAO,CAAC,KAAK,CACX,kGAAkG,CACnG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAEnC,2CAA2C;QAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,CACX,wBAAwB,IAAI,CAAC,IAAI,wDAAwD;oBACvF,sDAAsD,CACzD,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,IAAI,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7E,IAAI,IAAI,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC9B,OAAO,CAAC,IAAI,CACV,MAAM,IAAI,CAAC,IAAI,qEAAqE;oBAClF,0DAA0D,CAC7D,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,IAAI,CACV,iBAAiB,IAAI,CAAC,IAAI,aAAa,KAAK,+BAA+B;gBACzE,8BAA8B,CACjC,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1D,IAAI,MAAM,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;gBACnC,OAAO,CAAC,GAAG,CACT,cAAc,IAAI,CAAC,IAAI,UAAU,MAAM,CAAC,UAAU,qCAAqC;oBACrF,wCAAwC,KAAK,sBAAsB,CACtE,CAAC;YACJ,CAAC;iBAAM,IAAI,MAAM,CAAC,OAAO,KAAK,iBAAiB,EAAE,CAAC;gBAChD,OAAO,CAAC,GAAG,CACT,IAAI,IAAI,CAAC,IAAI,qEAAqE,CACnF,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CACT,IAAI,IAAI,CAAC,IAAI,kFAAkF,CAChG,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QAED,8EAA8E;QAC9E,IAAI,GAAG,CAAC,cAAc,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CACT,QAAQ,KAAK,kBAAkB,GAAG,CAAC,SAAS,iCAAiC,CAC9E,CAAC;YACF,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CACT,QAAQ,KAAK,MAAM,GAAG,CAAC,SAAS,kDAAkD,CACnF,CAAC;YACF,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,GAAG,CAAC,SAAS,yBAAyB,CAAC,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,EAAE,SAAS,KAAK,CAAC,CAAC,IAAI,CAAC;YACrD,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,oBAAoB,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,KAAK,gBAAgB,QAAQ,GAAG,CAAC,CAAC;YAClE,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,oDAAoD,KAAK,iBAAiB,CAAC,CAAC;YAC1F,CAAC;iBAAM,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,oCAAoC,KAAK,WAAW,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;QACD,OAAO,CAAC,GAAG,CACT,wEAAwE;YACtE,wFAAwF,CAC3F,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"commands-registry.d.ts","sourceRoot":"","sources":["../src/commands-registry.ts"],"names":[],"mappings":"AA2BA,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,+BAQ5B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,WAAW,+BAYvB,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,+BAM5B,CAAC"}
1
+ {"version":3,"file":"commands-registry.d.ts","sourceRoot":"","sources":["../src/commands-registry.ts"],"names":[],"mappings":"AA6BA,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,+BAQ5B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,WAAW,+BAcvB,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,+BAM5B,CAAC"}
@@ -8,6 +8,8 @@ import { resumeCommand } from './commands/resume.js';
8
8
  import { abandonCommand } from './commands/abandon.js';
9
9
  import { reclaimCommand } from './commands/reclaim.js';
10
10
  import { cleanupCommand } from './commands/cleanup.js';
11
+ import { purgeCommand } from './commands/purge.js';
12
+ import { gcCommand } from './commands/gc.js';
11
13
  import { reconcileCommand } from './commands/reconcile.js';
12
14
  import { attemptsCommand } from './commands/attempts.js';
13
15
  import { respondCommand } from './commands/respond.js';
@@ -45,6 +47,8 @@ export const runCommands = [
45
47
  reclaimCommand,
46
48
  respondCommand,
47
49
  cleanupCommand,
50
+ purgeCommand,
51
+ gcCommand,
48
52
  reconcileCommand,
49
53
  attemptsCommand,
50
54
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"commands-registry.js","sourceRoot":"","sources":["../src/commands-registry.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,+EAA+E;AAC/E,6CAA6C;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,WAAW;IACX,eAAe;IACf,eAAe;IACf,YAAY;IACZ,UAAU;IACV,WAAW;IACX,cAAc;CACf,CAAC;AAEF,gEAAgE;AAChE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,WAAW;IACX,cAAc;IACd,aAAa;IACb,WAAW;IACX,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,cAAc;IACd,gBAAgB;IAChB,eAAe;CAChB,CAAC;AAEF,sDAAsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU;IACV,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,aAAa;CACd,CAAC"}
1
+ {"version":3,"file":"commands-registry.js","sourceRoot":"","sources":["../src/commands-registry.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,+EAA+E;AAC/E,6CAA6C;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,WAAW;IACX,eAAe;IACf,eAAe;IACf,YAAY;IACZ,UAAU;IACV,WAAW;IACX,cAAc;CACf,CAAC;AAEF,gEAAgE;AAChE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,WAAW;IACX,cAAc;IACd,aAAa;IACb,WAAW;IACX,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,cAAc;IACd,YAAY;IACZ,SAAS;IACT,gBAAgB;IAChB,eAAe;CAChB,CAAC;AAEF,sDAAsD;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU;IACV,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,aAAa;CACd,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import 'dotenv/config';
4
4
  import { Command } from 'commander';
5
5
  import { workflowCommands, runCommands, topLevelCommands } from './commands-registry.js';
6
6
  const program = new Command();
7
- program.name('realm').description('Realm workflow engine CLI').version('0.18.0');
7
+ program.name('realm').description('Realm workflow engine CLI').version('0.20.0');
8
8
  // realm workflow — operations on workflow definitions
9
9
  const workflowCmd = new Command('workflow').description('Manage workflow definitions');
10
10
  for (const cmd of workflowCommands)
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Parses a duration string such as "30d", "6h", or "10m" into milliseconds.
3
+ * Throws a `WorkflowError` (code `VALIDATION_INPUT_SCHEMA`) on a malformed string — this is
4
+ * cleanup.ts's original error shape; reclaim.ts previously threw a plain `Error` for the same
5
+ * condition, unified here onto the typed form.
6
+ */
7
+ export declare function parseDuration(s: string): number;
8
+ //# sourceMappingURL=parse-duration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-duration.d.ts","sourceRoot":"","sources":["../../src/lib/parse-duration.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAiB/C"}
@@ -0,0 +1,28 @@
1
+ // parse-duration.ts — shared duration-string parser for CLI commands (issue #107).
2
+ //
3
+ // Extracted from cleanup.ts / reclaim.ts, which each carried their own byte-identical copy (a
4
+ // deliberate deferral noted in reclaim.ts's original comment: "cleanup.ts is out of this PR's
5
+ // scope"). Both commands, plus the new `purge` command, now import this single implementation.
6
+ import { WorkflowError } from '@sensigo/realm';
7
+ /**
8
+ * Parses a duration string such as "30d", "6h", or "10m" into milliseconds.
9
+ * Throws a `WorkflowError` (code `VALIDATION_INPUT_SCHEMA`) on a malformed string — this is
10
+ * cleanup.ts's original error shape; reclaim.ts previously threw a plain `Error` for the same
11
+ * condition, unified here onto the typed form.
12
+ */
13
+ export function parseDuration(s) {
14
+ const match = /^(\d+)(d|h|m)$/.exec(s);
15
+ if (match === null) {
16
+ throw new WorkflowError(`Invalid duration '${s}'. Use format: <number>(d|h|m), e.g. 30d, 6h, 10m`, {
17
+ code: 'VALIDATION_INPUT_SCHEMA',
18
+ category: 'VALIDATION',
19
+ agentAction: 'provide_input',
20
+ retryable: false,
21
+ });
22
+ }
23
+ const value = parseInt(match[1], 10);
24
+ const unit = match[2];
25
+ const multipliers = { d: 86_400_000, h: 3_600_000, m: 60_000 };
26
+ return value * multipliers[unit];
27
+ }
28
+ //# sourceMappingURL=parse-duration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-duration.js","sourceRoot":"","sources":["../../src/lib/parse-duration.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,EAAE;AACF,8FAA8F;AAC9F,8FAA8F;AAC9F,+FAA+F;AAC/F,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,CAAS;IACrC,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,aAAa,CACrB,qBAAqB,CAAC,mDAAmD,EACzE;YACE,IAAI,EAAE,yBAAyB;YAC/B,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE,eAAe;YAC5B,SAAS,EAAE,KAAK;SACjB,CACF,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;IACvB,MAAM,WAAW,GAA2B,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;IACvF,OAAO,KAAK,GAAG,WAAW,CAAC,IAAI,CAAE,CAAC;AACpC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sensigo/realm-cli",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -61,9 +61,9 @@
61
61
  "vitest": "^4.1.0"
62
62
  },
63
63
  "dependencies": {
64
- "@sensigo/realm": "^0.18.0",
65
- "@sensigo/realm-mcp": "^0.18.0",
66
- "@sensigo/realm-testing": "^0.18.0",
64
+ "@sensigo/realm": "^0.20.0",
65
+ "@sensigo/realm-mcp": "^0.20.0",
66
+ "@sensigo/realm-testing": "^0.20.0",
67
67
  "@modelcontextprotocol/sdk": "1.29.0",
68
68
  "chalk": "^5.0.0",
69
69
  "commander": "^14.0.3",