@sensigo/realm-cli 0.19.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/export.d.ts +64 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +131 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/gc.d.ts +47 -0
- package/dist/commands/gc.d.ts.map +1 -0
- package/dist/commands/gc.js +240 -0
- package/dist/commands/gc.js.map +1 -0
- package/dist/commands-registry.d.ts.map +1 -1
- package/dist/commands-registry.js +4 -0
- package/dist/commands-registry.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import type { RunRecord, RunStore, FailedAttemptRecord, TraceBufferStore } from '@sensigo/realm';
|
|
3
|
+
export interface ExportBundle {
|
|
4
|
+
realm_export_version: 1;
|
|
5
|
+
/** ISO-8601, stamped by the CLI at assembly time. */
|
|
6
|
+
exported_at: string;
|
|
7
|
+
/** The full RunRecord — steps, evidence, skip_details, claims, etc. */
|
|
8
|
+
run: RunRecord;
|
|
9
|
+
/** Parsed failed-attempt records; `[]` if none were ever recorded for this run. */
|
|
10
|
+
attempts: FailedAttemptRecord[];
|
|
11
|
+
/** True if the run hit the failed-attempt sidecar's 256KB ceiling — later attempts were dropped
|
|
12
|
+
* at write time (append-and-stop), so `attempts` is NOT exhaustive. */
|
|
13
|
+
attempts_capped: boolean;
|
|
14
|
+
/** `{ <stepId>: [...] }` — every buffered/WAL entry for the run, across all steps; `{}` if none. */
|
|
15
|
+
wal: Record<string, unknown[]>;
|
|
16
|
+
}
|
|
17
|
+
export interface ExportRunResult {
|
|
18
|
+
bundle: ExportBundle;
|
|
19
|
+
/**
|
|
20
|
+
* Set (to the warning text) when the run was non-terminal at export time — a best-effort
|
|
21
|
+
* snapshot, since its artifacts were read at slightly different instants and it may still be
|
|
22
|
+
* mid-flight. `undefined` for a terminal run (nothing to warn about — nothing changes post-seal).
|
|
23
|
+
* Returned as data, not printed here, so this stays assertable without a console spy (mirrors the
|
|
24
|
+
* `cleanup`/`purge` precedent of testing exported logic, not console output).
|
|
25
|
+
*/
|
|
26
|
+
warning: string | undefined;
|
|
27
|
+
}
|
|
28
|
+
export interface ExportStores {
|
|
29
|
+
runStore: Pick<RunStore, 'get'>;
|
|
30
|
+
failedAttemptStore: {
|
|
31
|
+
read(runId: string): Promise<{
|
|
32
|
+
records: FailedAttemptRecord[];
|
|
33
|
+
capped: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
36
|
+
traceBufferStore: Pick<TraceBufferStore, 'readAllForRun'>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Assembles the export bundle for `runId` from each store's existing read methods — never writes,
|
|
40
|
+
* never locks, never touches `runsDir`. Throws `STATE_RUN_NOT_FOUND` (propagated from
|
|
41
|
+
* `runStore.get`) for a nonexistent run; the CLI action maps that to an error message + exit(1).
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildExportBundle(runId: string, stores: ExportStores, now?: Date): Promise<ExportRunResult>;
|
|
44
|
+
export interface ResolveExportPathOptions {
|
|
45
|
+
runId: string;
|
|
46
|
+
/** The raw `--out` flag value, if given. */
|
|
47
|
+
out?: string | undefined;
|
|
48
|
+
/** `runStore.runsDirPath` — the export target must never resolve inside it. */
|
|
49
|
+
runsDir: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolves the final, absolute output path for an export, or throws (never writes anything
|
|
53
|
+
* itself — purely a path decision). Resolution order:
|
|
54
|
+
* 1. No `--out` → `<cwd>/<runId>.realm.json`.
|
|
55
|
+
* 2. `--out` names an EXISTING DIRECTORY → `<out>/<runId>.realm.json`.
|
|
56
|
+
* 3. Otherwise `--out` is treated as the literal file path.
|
|
57
|
+
* Then refuses (throws `WorkflowError`, code `VALIDATION_INPUT_SCHEMA`) if the resolved path is:
|
|
58
|
+
* - inside `runsDir` — export must never write into the store's own directory (would confuse
|
|
59
|
+
* `list()`'s naive `.json`-suffix filter, and clutters the space `gc`/`purge` manage); or
|
|
60
|
+
* - an already-existing file — export never clobbers; the operator picks a different `--out`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveExportPath(opts: ResolveExportPathOptions): string;
|
|
63
|
+
export declare const exportCommand: Command;
|
|
64
|
+
//# sourceMappingURL=export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGjG,MAAM,WAAW,YAAY;IAC3B,oBAAoB,EAAE,CAAC,CAAC;IACxB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,GAAG,EAAE,SAAS,CAAC;IACf,mFAAmF;IACnF,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC;4EACwE;IACxE,eAAe,EAAE,OAAO,CAAC;IACzB,oGAAoG;IACpG,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChC,kBAAkB,EAAE;QAClB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;YAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;YAAC,MAAM,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;KACnF,CAAC;IACF,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;CAC3D;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,YAAY,EACpB,GAAG,GAAE,IAAiB,GACrB,OAAO,CAAC,eAAe,CAAC,CAoB1B;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,GAAG,MAAM,CAqCxE;AAQD,eAAO,MAAM,aAAa,SA2CtB,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// export command — archive a run's evidence into one inspectable JSON bundle (issue #159).
|
|
2
|
+
//
|
|
3
|
+
// The read-only, evidence-preserving companion to `realm run purge` (#107): before (or instead of)
|
|
4
|
+
// permanently deleting a run's artifacts, `realm run export <id>` writes them into a single,
|
|
5
|
+
// self-contained, human-readable JSON file an operator can `cat`/`grep`/`git add`/attach to a bug
|
|
6
|
+
// report. Read-only and lock-free by construction — it only ever calls each store's existing PUBLIC
|
|
7
|
+
// READ methods (`runStore.get`, `failedAttemptStore.read`, `traceBufferStore.readAllForRun`); no
|
|
8
|
+
// filename layout is hard-coded here, and nothing is written to `runsDir`, unlinked, or locked.
|
|
9
|
+
//
|
|
10
|
+
// Works on ANY run, not just terminal ones — export's highest-value use is handing off a *stuck*
|
|
11
|
+
// (non-terminal) run for debugging, which a terminal-only gate would forbid, and read-only means
|
|
12
|
+
// there is no safety reason to restrict it. A non-terminal run gets a best-effort-snapshot warning
|
|
13
|
+
// instead (its artifacts are read at slightly different instants and may be mid-flight); a terminal
|
|
14
|
+
// run needs no warning, since nothing changes post-seal.
|
|
15
|
+
//
|
|
16
|
+
// The bundle deliberately excludes the idempotency-key pointer (`keys/<hash>.json`): that file is a
|
|
17
|
+
// rebuildable hash→run INDEX (regenerated by `reconcile`), not run evidence, and the key it maps is
|
|
18
|
+
// already present on the run record itself (`run.idempotency_key`).
|
|
19
|
+
import { existsSync, statSync } from 'node:fs';
|
|
20
|
+
import { writeFile } from 'node:fs/promises';
|
|
21
|
+
import { join, resolve, sep } from 'node:path';
|
|
22
|
+
import { Command } from 'commander';
|
|
23
|
+
import { WorkflowError, isTerminalPhase } from '@sensigo/realm';
|
|
24
|
+
/**
|
|
25
|
+
* Assembles the export bundle for `runId` from each store's existing read methods — never writes,
|
|
26
|
+
* never locks, never touches `runsDir`. Throws `STATE_RUN_NOT_FOUND` (propagated from
|
|
27
|
+
* `runStore.get`) for a nonexistent run; the CLI action maps that to an error message + exit(1).
|
|
28
|
+
*/
|
|
29
|
+
export async function buildExportBundle(runId, stores, now = new Date()) {
|
|
30
|
+
const run = await stores.runStore.get(runId);
|
|
31
|
+
const { records: attempts, capped: attemptsCapped } = await stores.failedAttemptStore.read(runId);
|
|
32
|
+
const wal = await stores.traceBufferStore.readAllForRun(runId);
|
|
33
|
+
const bundle = {
|
|
34
|
+
realm_export_version: 1,
|
|
35
|
+
exported_at: now.toISOString(),
|
|
36
|
+
run,
|
|
37
|
+
attempts,
|
|
38
|
+
attempts_capped: attemptsCapped,
|
|
39
|
+
wal,
|
|
40
|
+
};
|
|
41
|
+
const warning = !isTerminalPhase(run.run_phase)
|
|
42
|
+
? `best-effort snapshot: run '${runId}' is still ${run.run_phase}; its artifacts are read at ` +
|
|
43
|
+
`slightly different instants and may be mid-flight`
|
|
44
|
+
: undefined;
|
|
45
|
+
return { bundle, warning };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolves the final, absolute output path for an export, or throws (never writes anything
|
|
49
|
+
* itself — purely a path decision). Resolution order:
|
|
50
|
+
* 1. No `--out` → `<cwd>/<runId>.realm.json`.
|
|
51
|
+
* 2. `--out` names an EXISTING DIRECTORY → `<out>/<runId>.realm.json`.
|
|
52
|
+
* 3. Otherwise `--out` is treated as the literal file path.
|
|
53
|
+
* Then refuses (throws `WorkflowError`, code `VALIDATION_INPUT_SCHEMA`) if the resolved path is:
|
|
54
|
+
* - inside `runsDir` — export must never write into the store's own directory (would confuse
|
|
55
|
+
* `list()`'s naive `.json`-suffix filter, and clutters the space `gc`/`purge` manage); or
|
|
56
|
+
* - an already-existing file — export never clobbers; the operator picks a different `--out`.
|
|
57
|
+
*/
|
|
58
|
+
export function resolveExportPath(opts) {
|
|
59
|
+
let target;
|
|
60
|
+
if (opts.out === undefined) {
|
|
61
|
+
target = join(process.cwd(), `${opts.runId}.realm.json`);
|
|
62
|
+
}
|
|
63
|
+
else if (existsSync(opts.out) && statSync(opts.out).isDirectory()) {
|
|
64
|
+
target = join(opts.out, `${opts.runId}.realm.json`);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
target = opts.out;
|
|
68
|
+
}
|
|
69
|
+
const resolvedTarget = resolve(target);
|
|
70
|
+
const resolvedRunsDir = resolve(opts.runsDir);
|
|
71
|
+
if (resolvedTarget === resolvedRunsDir || resolvedTarget.startsWith(resolvedRunsDir + sep)) {
|
|
72
|
+
throw new WorkflowError(`Refusing to write the export inside runsDir ('${resolvedRunsDir}') — choose a different --out.`, {
|
|
73
|
+
code: 'VALIDATION_INPUT_SCHEMA',
|
|
74
|
+
category: 'VALIDATION',
|
|
75
|
+
agentAction: 'provide_input',
|
|
76
|
+
retryable: false,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (existsSync(resolvedTarget)) {
|
|
80
|
+
throw new WorkflowError(`Refusing to overwrite existing file '${resolvedTarget}'. Choose a different --out.`, {
|
|
81
|
+
code: 'VALIDATION_INPUT_SCHEMA',
|
|
82
|
+
category: 'VALIDATION',
|
|
83
|
+
agentAction: 'provide_input',
|
|
84
|
+
retryable: false,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return resolvedTarget;
|
|
88
|
+
}
|
|
89
|
+
function formatBytes(n) {
|
|
90
|
+
if (n < 1024)
|
|
91
|
+
return `${n} B`;
|
|
92
|
+
if (n < 1024 * 1024)
|
|
93
|
+
return `${(n / 1024).toFixed(1)} KB`;
|
|
94
|
+
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
95
|
+
}
|
|
96
|
+
export const exportCommand = new Command('export')
|
|
97
|
+
.description("Archive a run's evidence (record + failed-attempt sidecar + WAL traces) into one inspectable JSON bundle — read-only")
|
|
98
|
+
.argument('<run-id>', 'ID of the run to export')
|
|
99
|
+
.option('--out <path>', 'Output file or directory (default: ./<run-id>.realm.json)')
|
|
100
|
+
.action(async (runId, opts) => {
|
|
101
|
+
const { JsonFileStore, FailedAttemptStore } = await import('@sensigo/realm');
|
|
102
|
+
const { JsonTraceBufferStore } = await import('@sensigo/realm-mcp');
|
|
103
|
+
const runStore = new JsonFileStore();
|
|
104
|
+
const runsDir = runStore.runsDirPath;
|
|
105
|
+
const failedAttemptStore = new FailedAttemptStore(runsDir);
|
|
106
|
+
const traceBufferStore = new JsonTraceBufferStore(runsDir);
|
|
107
|
+
try {
|
|
108
|
+
const { bundle, warning } = await buildExportBundle(runId, {
|
|
109
|
+
runStore,
|
|
110
|
+
failedAttemptStore,
|
|
111
|
+
traceBufferStore,
|
|
112
|
+
});
|
|
113
|
+
if (warning !== undefined) {
|
|
114
|
+
console.warn(`⚠ ${warning}`);
|
|
115
|
+
}
|
|
116
|
+
if (bundle.attempts_capped) {
|
|
117
|
+
console.warn('⚠ failed-attempt log was truncated at its size ceiling — the exported attempts list is not exhaustive.');
|
|
118
|
+
}
|
|
119
|
+
const target = resolveExportPath({ runId, out: opts.out, runsDir });
|
|
120
|
+
const json = JSON.stringify(bundle, null, 2);
|
|
121
|
+
await writeFile(target, json, 'utf8');
|
|
122
|
+
const walStepCount = Object.keys(bundle.wal).length;
|
|
123
|
+
console.log(`Exported run '${runId}' to '${target}' (${formatBytes(Buffer.byteLength(json))}).\n` +
|
|
124
|
+
` phase: ${bundle.run.run_phase}, attempts: ${bundle.attempts.length}, WAL steps: ${walStepCount}`);
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
//# sourceMappingURL=export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,EAAE;AACF,mGAAmG;AACnG,6FAA6F;AAC7F,kGAAkG;AAClG,oGAAoG;AACpG,iGAAiG;AACjG,gGAAgG;AAChG,EAAE;AACF,iGAAiG;AACjG,iGAAiG;AACjG,mGAAmG;AACnG,oGAAoG;AACpG,yDAAyD;AACzD,EAAE;AACF,oGAAoG;AACpG,oGAAoG;AACpG,oEAAoE;AACpE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAqChE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,MAAoB,EACpB,MAAY,IAAI,IAAI,EAAE;IAEtB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClG,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAE/D,MAAM,MAAM,GAAiB;QAC3B,oBAAoB,EAAE,CAAC;QACvB,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE;QAC9B,GAAG;QACH,QAAQ;QACR,eAAe,EAAE,cAAc;QAC/B,GAAG;KACJ,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC;QAC7C,CAAC,CAAC,8BAA8B,KAAK,cAAc,GAAG,CAAC,SAAS,8BAA8B;YAC5F,mDAAmD;QACrD,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAUD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAA8B;IAC9D,IAAI,MAAc,CAAC;IACnB,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,aAAa,CAAC,CAAC;IAC3D,CAAC;SAAM,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACpE,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,aAAa,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC;IACpB,CAAC;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,cAAc,KAAK,eAAe,IAAI,cAAc,CAAC,UAAU,CAAC,eAAe,GAAG,GAAG,CAAC,EAAE,CAAC;QAC3F,MAAM,IAAI,aAAa,CACrB,iDAAiD,eAAe,gCAAgC,EAChG;YACE,IAAI,EAAE,yBAAyB;YAC/B,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE,eAAe;YAC5B,SAAS,EAAE,KAAK;SACjB,CACF,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,aAAa,CACrB,wCAAwC,cAAc,8BAA8B,EACpF;YACE,IAAI,EAAE,yBAAyB;YAC/B,QAAQ,EAAE,YAAY;YACtB,WAAW,EAAE,eAAe;YAC5B,SAAS,EAAE,KAAK;SACjB,CACF,CAAC;IACJ,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,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,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CACV,sHAAsH,CACvH;KACA,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC;KAC/C,MAAM,CAAC,cAAc,EAAE,2DAA2D,CAAC;KACnF,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,IAAsB,EAAE,EAAE;IACtD,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;IAE3D,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,iBAAiB,CAAC,KAAK,EAAE;YACzD,QAAQ;YACR,kBAAkB;YAClB,gBAAgB;SACjB,CAAC,CAAC;QAEH,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CACV,wGAAwG,CACzG,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACpE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7C,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAEtC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;QACpD,OAAO,CAAC,GAAG,CACT,iBAAiB,KAAK,SAAS,MAAM,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM;YACnF,YAAY,MAAM,CAAC,GAAG,CAAC,SAAS,eAAe,MAAM,CAAC,QAAQ,CAAC,MAAM,gBAAgB,YAAY,EAAE,CACtG,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,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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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands-registry.d.ts","sourceRoot":"","sources":["../src/commands-registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commands-registry.d.ts","sourceRoot":"","sources":["../src/commands-registry.ts"],"names":[],"mappings":"AA8BA,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,+BAQ5B,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,WAAW,+BAevB,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,+BAM5B,CAAC"}
|
|
@@ -9,6 +9,8 @@ import { abandonCommand } from './commands/abandon.js';
|
|
|
9
9
|
import { reclaimCommand } from './commands/reclaim.js';
|
|
10
10
|
import { cleanupCommand } from './commands/cleanup.js';
|
|
11
11
|
import { purgeCommand } from './commands/purge.js';
|
|
12
|
+
import { gcCommand } from './commands/gc.js';
|
|
13
|
+
import { exportCommand } from './commands/export.js';
|
|
12
14
|
import { reconcileCommand } from './commands/reconcile.js';
|
|
13
15
|
import { attemptsCommand } from './commands/attempts.js';
|
|
14
16
|
import { respondCommand } from './commands/respond.js';
|
|
@@ -47,6 +49,8 @@ export const runCommands = [
|
|
|
47
49
|
respondCommand,
|
|
48
50
|
cleanupCommand,
|
|
49
51
|
purgeCommand,
|
|
52
|
+
gcCommand,
|
|
53
|
+
exportCommand,
|
|
50
54
|
reconcileCommand,
|
|
51
55
|
attemptsCommand,
|
|
52
56
|
];
|
|
@@ -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,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,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,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,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,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,aAAa;IACb,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.
|
|
7
|
+
program.name('realm').description('Realm workflow engine CLI').version('0.21.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)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sensigo/realm-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.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.
|
|
65
|
-
"@sensigo/realm-mcp": "^0.
|
|
66
|
-
"@sensigo/realm-testing": "^0.
|
|
64
|
+
"@sensigo/realm": "^0.21.0",
|
|
65
|
+
"@sensigo/realm-mcp": "^0.21.0",
|
|
66
|
+
"@sensigo/realm-testing": "^0.21.0",
|
|
67
67
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
68
68
|
"chalk": "^5.0.0",
|
|
69
69
|
"commander": "^14.0.3",
|