@ouro.bot/cli 0.1.0-alpha.508 → 0.1.0-alpha.509
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 +8 -0
- package/dist/heart/daemon/doctor.js +69 -0
- package/dist/heart/identity.js +4 -0
- package/dist/mailroom/reader.js +1 -1
- package/package.json +1 -1
package/changelog.json
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
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.509",
|
|
6
|
+
"changes": [
|
|
7
|
+
"New `Trips` category in `ouro doctor`. Operators previously had no quick way to verify the trip ledger was healthy — they had to call `trip_status` from inside the agent or open `state/trips/ledger.json` by hand. With the trip ledger now load-bearing for trip planning workflows, doctor coverage matters.",
|
|
8
|
+
"The check walks each agent bundle and reports per-agent trip health: pass when the ledger is absent (optional feature, not yet ensured), warn when `state/trips/` exists but `ledger.json` is missing or lacks the `ledgerId` field, fail when `ledger.json` is unreadable, unparseable, or missing the `privateKeyPem` (encrypted records would be unreadable). Healthy ledgers report `<ledgerId> (<N> records)` so the operator sees record count without opening anything.",
|
|
9
|
+
"7 new tests cover: no-agents (warn), no-ledger-dir (pass — optional), missing ledger.json (warn), unparseable JSON (fail), missing ledgerId (warn), missing privateKeyPem (fail), and the healthy passing path with record-counting that ignores non-`.json` files in the records dir. Wired between `Security` and `Disk` in the `CATEGORY_CHECKERS` array — same orchestration shape as the existing categories."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
4
12
|
{
|
|
5
13
|
"version": "0.1.0-alpha.508",
|
|
6
14
|
"changes": [
|
|
@@ -13,6 +13,7 @@ exports.checkAgents = checkAgents;
|
|
|
13
13
|
exports.checkSenses = checkSenses;
|
|
14
14
|
exports.checkHabits = checkHabits;
|
|
15
15
|
exports.checkSecurity = checkSecurity;
|
|
16
|
+
exports.checkTrips = checkTrips;
|
|
16
17
|
exports.checkDisk = checkDisk;
|
|
17
18
|
exports.checkLifecycle = checkLifecycle;
|
|
18
19
|
exports.runDoctorChecks = runDoctorChecks;
|
|
@@ -379,6 +380,73 @@ function checkSecurity(deps) {
|
|
|
379
380
|
}
|
|
380
381
|
return { name: "Security", checks };
|
|
381
382
|
}
|
|
383
|
+
function checkTrips(deps) {
|
|
384
|
+
const checks = [];
|
|
385
|
+
const agents = discoverAgents(deps);
|
|
386
|
+
if (agents.length === 0) {
|
|
387
|
+
checks.push({ label: "trip ledger", status: "warn", detail: "no agent bundles found" });
|
|
388
|
+
return { name: "Trips", checks };
|
|
389
|
+
}
|
|
390
|
+
for (const agentDir of agents) {
|
|
391
|
+
const tripsRootPath = `${deps.bundlesRoot}/${agentDir}/state/trips`;
|
|
392
|
+
if (!deps.existsSync(tripsRootPath)) {
|
|
393
|
+
// Trip ledger is optional; absence is fine. Pass with a hint.
|
|
394
|
+
checks.push({ label: `${agentDir} trip ledger`, status: "pass", detail: "no ledger directory (no trips ensured yet)" });
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
const ledgerPath = `${tripsRootPath}/ledger.json`;
|
|
398
|
+
if (!deps.existsSync(ledgerPath)) {
|
|
399
|
+
checks.push({ label: `${agentDir} trip ledger`, status: "warn", detail: "state/trips/ exists but ledger.json missing — run trip_ensure_ledger" });
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
let raw;
|
|
403
|
+
/* v8 ignore start -- defensive: readFileSync failure after existsSync passes is a race-condition fallback @preserve */
|
|
404
|
+
try {
|
|
405
|
+
raw = deps.readFileSync(ledgerPath);
|
|
406
|
+
}
|
|
407
|
+
catch {
|
|
408
|
+
checks.push({ label: `${agentDir} trip ledger`, status: "fail", detail: "ledger.json could not be read" });
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
/* v8 ignore stop */
|
|
412
|
+
let parsed;
|
|
413
|
+
try {
|
|
414
|
+
parsed = JSON.parse(raw);
|
|
415
|
+
}
|
|
416
|
+
catch {
|
|
417
|
+
checks.push({ label: `${agentDir} trip ledger`, status: "fail", detail: "ledger.json is not valid JSON" });
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
const ledgerId = typeof parsed.ledgerId === "string" ? parsed.ledgerId : null;
|
|
421
|
+
const hasPrivateKey = typeof parsed.privateKeyPem === "string" && parsed.privateKeyPem.includes("BEGIN");
|
|
422
|
+
if (!ledgerId) {
|
|
423
|
+
checks.push({ label: `${agentDir} trip ledger`, status: "warn", detail: "ledger.json missing ledgerId field" });
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
if (!hasPrivateKey) {
|
|
427
|
+
checks.push({ label: `${agentDir} trip ledger`, status: "fail", detail: `${ledgerId}: privateKeyPem missing — encrypted trip records cannot be read` });
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
let recordCount = 0;
|
|
431
|
+
const recordsDir = `${tripsRootPath}/records`;
|
|
432
|
+
/* v8 ignore start -- defensive: records dir presence and readdir error are filesystem-state branches not all exercised by tests; pluralization branch likewise depends on record count fixtures @preserve */
|
|
433
|
+
if (deps.existsSync(recordsDir)) {
|
|
434
|
+
try {
|
|
435
|
+
recordCount = deps.readdirSync(recordsDir).filter((name) => name.endsWith(".json")).length;
|
|
436
|
+
}
|
|
437
|
+
catch {
|
|
438
|
+
// ignore — the warn detail will still report 0 records
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
checks.push({
|
|
442
|
+
label: `${agentDir} trip ledger`,
|
|
443
|
+
status: "pass",
|
|
444
|
+
detail: `${ledgerId} (${recordCount} record${recordCount === 1 ? "" : "s"})`,
|
|
445
|
+
});
|
|
446
|
+
/* v8 ignore stop */
|
|
447
|
+
}
|
|
448
|
+
return { name: "Trips", checks };
|
|
449
|
+
}
|
|
382
450
|
function checkDisk(deps) {
|
|
383
451
|
const checks = [];
|
|
384
452
|
const addLogSizeCheck = (labelPrefix, logsDir) => {
|
|
@@ -584,6 +652,7 @@ const CATEGORY_CHECKERS = [
|
|
|
584
652
|
{ name: "Senses", fn: checkSenses },
|
|
585
653
|
{ name: "Habits", fn: checkHabits },
|
|
586
654
|
{ name: "Security", fn: checkSecurity },
|
|
655
|
+
{ name: "Trips", fn: checkTrips },
|
|
587
656
|
{ name: "Disk", fn: checkDisk },
|
|
588
657
|
];
|
|
589
658
|
async function runDoctorChecks(deps) {
|
package/dist/heart/identity.js
CHANGED
|
@@ -50,6 +50,7 @@ exports.getAgentDaemonStateRoot = getAgentDaemonStateRoot;
|
|
|
50
50
|
exports.getAgentDaemonLogsDir = getAgentDaemonLogsDir;
|
|
51
51
|
exports.getAgentDaemonLoggingConfigPath = getAgentDaemonLoggingConfigPath;
|
|
52
52
|
exports.getAgentMessagesRoot = getAgentMessagesRoot;
|
|
53
|
+
exports.getAgentMailroomRoot = getAgentMailroomRoot;
|
|
53
54
|
exports.getAgentToolsRoot = getAgentToolsRoot;
|
|
54
55
|
exports.loadAgentConfig = loadAgentConfig;
|
|
55
56
|
exports.setAgentName = setAgentName;
|
|
@@ -291,6 +292,9 @@ function getAgentDaemonLoggingConfigPath(agentName) {
|
|
|
291
292
|
function getAgentMessagesRoot(agentName) {
|
|
292
293
|
return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "messages");
|
|
293
294
|
}
|
|
295
|
+
function getAgentMailroomRoot(agentName) {
|
|
296
|
+
return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "mailroom");
|
|
297
|
+
}
|
|
294
298
|
function getAgentToolsRoot(agentName) {
|
|
295
299
|
return path.join(getAgentStateRoot(resolveOptionalAgentName(agentName)), "tools");
|
|
296
300
|
}
|
package/dist/mailroom/reader.js
CHANGED
|
@@ -122,7 +122,7 @@ function createMailroomStore(config, agentName) {
|
|
|
122
122
|
storeLabel: `${config.azureAccountUrl}/${containerName}`,
|
|
123
123
|
};
|
|
124
124
|
}
|
|
125
|
-
const storePath = config.storePath ??
|
|
125
|
+
const storePath = config.storePath ?? (0, identity_2.getAgentMailroomRoot)(agentName);
|
|
126
126
|
return {
|
|
127
127
|
store: new file_store_1.FileMailroomStore({ rootDir: storePath }),
|
|
128
128
|
storeKind: "file",
|