@bli-cockpit/cli 0.2.170 → 0.2.174
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/adapters/raw-evidence-collection-state.js +52 -6
- package/dist/adapters/raw-evidence-completeness.js +6 -0
- package/dist/adapters/raw-evidence-git-diff-reader.js +2 -2
- package/dist/adapters/raw-evidence-image-reader.js +5 -2
- package/dist/adapters/raw-evidence-transcript-file.js +2 -2
- package/dist/commands/backfill-upload.js +12 -0
- package/dist/commands/doctor-disk-words.js +20 -0
- package/dist/commands/doctor-pipeline.js +34 -7
- package/dist/commands/local-args-tower-logs.js +72 -0
- package/dist/commands/local-args-tower.js +1 -0
- package/dist/commands/local-args.js +3 -1
- package/dist/commands/local-command-shapes-logs.js +6 -0
- package/dist/commands/local-help-commands-tower-ops.js +34 -0
- package/dist/commands/local-help.js +2 -0
- package/dist/commands/local.js +3 -0
- package/dist/commands/logs-stored.js +56 -0
- package/dist/commands/logs.js +84 -0
- package/dist/commands/public-root.js +1 -1
- package/dist/commands/sync-followups-staging.js +8 -1
- package/dist/disk-prune.js +35 -3
- package/dist/disk-retention.js +31 -1
- package/dist/staging-gate-receipt.js +131 -0
- package/dist/staging-gate.js +214 -0
- package/dist/state-dir-audit.js +5 -4
- package/dist/state-dir-prune.js +84 -0
- package/package.json +4 -4
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounds the two state-dir writers that had no bound (BLI-12832 audit).
|
|
3
|
+
*
|
|
4
|
+
* `read-cache/` keeps one response file per distinct Tower read (the key folds
|
|
5
|
+
* in the request body, so every different `memory search` is its own file) and
|
|
6
|
+
* overwrote only on a repeat of the SAME read. `memory-hook-samples/` keeps
|
|
7
|
+
* hourly timing samples and was "not yet pruned". Both are disposable: a cache
|
|
8
|
+
* miss re-reads from Tower, an old timing sample is history nobody consults.
|
|
9
|
+
* Neither is evidence, so deleting from them can never lose anything.
|
|
10
|
+
*
|
|
11
|
+
* Every other state-dir entry is bounded where it is written (see the table in
|
|
12
|
+
* `state-dir-audit.ts`). Runs on every sync tick, never throws, logs counts.
|
|
13
|
+
*/
|
|
14
|
+
import fs from "node:fs/promises";
|
|
15
|
+
import path from "node:path";
|
|
16
|
+
import { describeError } from "./health-detail.js";
|
|
17
|
+
export const READ_CACHE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
18
|
+
export const READ_CACHE_MAX_BYTES = 32 * 1024 * 1024;
|
|
19
|
+
export const HOOK_SAMPLES_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000;
|
|
20
|
+
async function listFiles(dir) {
|
|
21
|
+
const out = [];
|
|
22
|
+
const entries = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
23
|
+
for (const entry of entries) {
|
|
24
|
+
const full = path.join(dir, entry.name);
|
|
25
|
+
if (entry.isDirectory()) {
|
|
26
|
+
out.push(...(await listFiles(full)));
|
|
27
|
+
}
|
|
28
|
+
else if (entry.isFile()) {
|
|
29
|
+
const info = await fs.stat(full).catch(() => null);
|
|
30
|
+
if (info)
|
|
31
|
+
out.push({ file: full, bytes: info.size, mtime_ms: info.mtimeMs });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
async function removeAll(files) {
|
|
37
|
+
let removed = 0;
|
|
38
|
+
let bytes = 0;
|
|
39
|
+
for (const fact of files) {
|
|
40
|
+
const ok = await fs.rm(fact.file, { force: true }).then(() => true, () => false);
|
|
41
|
+
if (!ok)
|
|
42
|
+
continue;
|
|
43
|
+
removed += 1;
|
|
44
|
+
bytes += fact.bytes;
|
|
45
|
+
}
|
|
46
|
+
return { removed, bytes };
|
|
47
|
+
}
|
|
48
|
+
export async function pruneStateDirCaches(paths, now = new Date()) {
|
|
49
|
+
const result = {
|
|
50
|
+
read_cache_removed: 0,
|
|
51
|
+
read_cache_bytes_freed: 0,
|
|
52
|
+
hook_samples_removed: 0,
|
|
53
|
+
hook_samples_bytes_freed: 0,
|
|
54
|
+
};
|
|
55
|
+
try {
|
|
56
|
+
const cache = await listFiles(path.join(paths.state_dir, "read-cache"));
|
|
57
|
+
const fresh = cache.filter((fact) => now.getTime() - fact.mtime_ms <= READ_CACHE_MAX_AGE_MS);
|
|
58
|
+
const doomed = cache.filter((fact) => !fresh.includes(fact));
|
|
59
|
+
let kept = fresh.reduce((sum, fact) => sum + fact.bytes, 0);
|
|
60
|
+
for (const fact of [...fresh].sort((a, b) => a.mtime_ms - b.mtime_ms)) {
|
|
61
|
+
if (kept <= READ_CACHE_MAX_BYTES)
|
|
62
|
+
break;
|
|
63
|
+
doomed.push(fact);
|
|
64
|
+
kept -= fact.bytes;
|
|
65
|
+
}
|
|
66
|
+
const freed = await removeAll(doomed);
|
|
67
|
+
result.read_cache_removed = freed.removed;
|
|
68
|
+
result.read_cache_bytes_freed = freed.bytes;
|
|
69
|
+
const samples = await listFiles(path.join(paths.state_dir, "memory-hook-samples"));
|
|
70
|
+
const stale = samples.filter((fact) => now.getTime() - fact.mtime_ms > HOOK_SAMPLES_MAX_AGE_MS);
|
|
71
|
+
const sampleFreed = await removeAll(stale);
|
|
72
|
+
result.hook_samples_removed = sampleFreed.removed;
|
|
73
|
+
result.hook_samples_bytes_freed = sampleFreed.bytes;
|
|
74
|
+
console.error("[collector prune] state-dir caches bounded", JSON.stringify({
|
|
75
|
+
reason: freed.removed + sampleFreed.removed > 0 ? "caches_trimmed" : "caches_within_bounds",
|
|
76
|
+
...result,
|
|
77
|
+
read_cache_kept_bytes: kept,
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
console.error("[collector prune] state-dir cache prune failed, nothing else is affected", JSON.stringify({ reason: "state_dir_cache_prune_failed", ...describeError(error) }));
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bli-cockpit/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.174",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"test": "node dist/cli.js --help && node ../../scripts/assert-public-cli-routing.mjs && node ../../scripts/assert-public-cli-verb-help.mjs && node ../../scripts/assert-public-cli-surface-doors.mjs && node ../../scripts/assert-public-cli-runtime-files.mjs && node ../../scripts/assert-public-cli-exit-contract.mjs && node ../../scripts/assert-public-cli-no-fleet-posts.mjs && node ../../scripts/assert-public-cli-doctor-json.mjs && node ../../scripts/assert-public-package-pack.mjs --workspace=@bli-cockpit/cli"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@bli-cockpit/memory-mcp": "0.1.
|
|
31
|
-
"@bli-cockpit/mcp": "0.1.
|
|
32
|
-
"@bli-cockpit/telemetry-core": "0.1.
|
|
30
|
+
"@bli-cockpit/memory-mcp": "0.1.48",
|
|
31
|
+
"@bli-cockpit/mcp": "0.1.90",
|
|
32
|
+
"@bli-cockpit/telemetry-core": "0.1.60"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|