@ouro.bot/cli 0.1.0-alpha.451 → 0.1.0-alpha.453
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.json +16 -0
- package/dist/heart/daemon/doctor.js +17 -9
- package/dist/heart/daemon/logs-prune.js +14 -9
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.453",
|
|
6
|
+
"changes": [
|
|
7
|
+
"`ouro logs prune` now rotates oversized active launchd `.log` streams alongside `.ndjson` daemon streams, so doctor's bundle-local log-size remediation can compact the legacy stderr/stdout files it counts.",
|
|
8
|
+
"Log pruning still skips compressed and historical generation files, keeping rotation safe and idempotent while letting `rotateIfNeeded` handle generation shifting.",
|
|
9
|
+
"Regression coverage now locks `.log` pruning and the historical-file skip behavior for daemon logs."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"version": "0.1.0-alpha.452",
|
|
14
|
+
"changes": [
|
|
15
|
+
"`ouro doctor` now checks the canonical bundle-local daemon log directory for each agent instead of the obsolete `~/.ouro-cli/logs` path.",
|
|
16
|
+
"Disk health output now names the owning agent for daemon log-size checks, so humans and agents can connect the warning directly to the right bundle and `ouro logs prune` target.",
|
|
17
|
+
"Doctor coverage now locks the bundle-local log path, missing-log-dir warning, and per-agent log-size thresholds."
|
|
18
|
+
]
|
|
19
|
+
},
|
|
4
20
|
{
|
|
5
21
|
"version": "0.1.0-alpha.451",
|
|
6
22
|
"changes": [
|
|
@@ -329,12 +329,7 @@ function checkSecurity(deps) {
|
|
|
329
329
|
}
|
|
330
330
|
function checkDisk(deps) {
|
|
331
331
|
const checks = [];
|
|
332
|
-
|
|
333
|
-
const logsDir = `${deps.homedir}/.ouro-cli/logs`;
|
|
334
|
-
if (!deps.existsSync(logsDir)) {
|
|
335
|
-
checks.push({ label: "daemon logs dir", status: "warn", detail: `${logsDir} not found` });
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
332
|
+
const addLogSizeCheck = (labelPrefix, logsDir) => {
|
|
338
333
|
let totalSize = 0;
|
|
339
334
|
try {
|
|
340
335
|
const files = deps.readdirSync(logsDir);
|
|
@@ -353,13 +348,26 @@ function checkDisk(deps) {
|
|
|
353
348
|
}
|
|
354
349
|
const sizeMB = totalSize / (1024 * 1024);
|
|
355
350
|
if (sizeMB > 500) {
|
|
356
|
-
checks.push({ label:
|
|
351
|
+
checks.push({ label: `${labelPrefix} daemon log size`, status: "fail", detail: `${sizeMB.toFixed(1)}MB — exceeds 500MB limit` });
|
|
357
352
|
}
|
|
358
353
|
else if (sizeMB > 100) {
|
|
359
|
-
checks.push({ label:
|
|
354
|
+
checks.push({ label: `${labelPrefix} daemon log size`, status: "warn", detail: `${sizeMB.toFixed(1)}MB — consider pruning with \`ouro logs prune\`` });
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
checks.push({ label: `${labelPrefix} daemon log size`, status: "pass", detail: `${sizeMB.toFixed(1)}MB` });
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
const agents = discoverAgents(deps);
|
|
361
|
+
if (agents.length === 0) {
|
|
362
|
+
checks.push({ label: "daemon logs dir", status: "warn", detail: "no agent bundles found for bundle-local logs" });
|
|
363
|
+
}
|
|
364
|
+
for (const agentDir of agents) {
|
|
365
|
+
const logsDir = `${deps.bundlesRoot}/${agentDir}/state/daemon/logs`;
|
|
366
|
+
if (!deps.existsSync(logsDir)) {
|
|
367
|
+
checks.push({ label: `${agentDir} daemon logs dir`, status: "warn", detail: `${logsDir} not found` });
|
|
360
368
|
}
|
|
361
369
|
else {
|
|
362
|
-
|
|
370
|
+
addLogSizeCheck(agentDir, logsDir);
|
|
363
371
|
}
|
|
364
372
|
}
|
|
365
373
|
// Check AgentBundles root
|
|
@@ -7,6 +7,15 @@ const crypto_1 = require("crypto");
|
|
|
7
7
|
const nerves_1 = require("../../nerves");
|
|
8
8
|
const runtime_1 = require("../../nerves/runtime");
|
|
9
9
|
const identity_1 = require("../identity");
|
|
10
|
+
function isActiveLogStream(name) {
|
|
11
|
+
if (name.endsWith(".ndjson")) {
|
|
12
|
+
return !/\.\d+\.ndjson$/.test(name);
|
|
13
|
+
}
|
|
14
|
+
if (name.endsWith(".log")) {
|
|
15
|
+
return !/\.\d+\.log$/.test(name);
|
|
16
|
+
}
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
10
19
|
function pruneDaemonLogs(options = {}) {
|
|
11
20
|
/* v8 ignore next -- defensive: tests always pass logsDir to avoid prod paths @preserve */
|
|
12
21
|
const logsDir = options.logsDir ?? (0, identity_1.getAgentDaemonLogsDir)(options.agentName);
|
|
@@ -35,17 +44,13 @@ function pruneDaemonLogs(options = {}) {
|
|
|
35
44
|
}
|
|
36
45
|
let filesCompacted = 0;
|
|
37
46
|
let bytesFreed = 0;
|
|
38
|
-
// Enumerate and rotate each active
|
|
39
|
-
// .gz and other files — only the active
|
|
40
|
-
// candidate. Legacy
|
|
41
|
-
// rotateIfNeeded's generation-shift step, so we skip them here to
|
|
47
|
+
// Enumerate and rotate each active structured stream plus legacy launchd
|
|
48
|
+
// .log streams. We explicitly skip .gz and other files — only the active
|
|
49
|
+
// stream can be a rotation candidate. Legacy generation files are handled
|
|
50
|
+
// inside rotateIfNeeded's generation-shift step, so we skip them here to
|
|
42
51
|
// avoid double-rotating.
|
|
43
52
|
for (const name of (0, fs_1.readdirSync)(logsDir)) {
|
|
44
|
-
if (!name
|
|
45
|
-
continue;
|
|
46
|
-
// Skip legacy generation files like daemon.1.ndjson; rotateIfNeeded
|
|
47
|
-
// will migrate them on the next rotation of their parent stream.
|
|
48
|
-
if (/\.\d+\.ndjson$/.test(name))
|
|
53
|
+
if (!isActiveLogStream(name))
|
|
49
54
|
continue;
|
|
50
55
|
const filePath = (0, path_1.join)(logsDir, name);
|
|
51
56
|
let sizeBefore;
|