@ouro.bot/cli 0.1.0-alpha.512 → 0.1.0-alpha.513
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 +80 -0
- 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.513",
|
|
6
|
+
"changes": [
|
|
7
|
+
"New `Friends` category in `ouro doctor`. Same shape as the Mailroom (#632) and Trips (#631) checks — walk each agent bundle, classify the friend store's health, and report a trust-level breakdown for the healthy path.",
|
|
8
|
+
"Per-agent reports: pass when no friends/ dir (no friends recorded yet), pass with `<N> friends, <X> family, <Y> friend, <Z> stranger` when records parse cleanly, warn when some files are unparseable (with parse-failure count), fail when the dir itself can't be read. Records with an unrecognized `trustLevel` get counted under `<N> other` so the operator can investigate.",
|
|
9
|
+
"6 new tests cover all branches plus file-extension filtering (`.txt` ignored). Wired between Security and Disk in CATEGORY_CHECKERS, same orchestration shape as Mailroom and Trips."
|
|
10
|
+
]
|
|
11
|
+
},
|
|
4
12
|
{
|
|
5
13
|
"version": "0.1.0-alpha.512",
|
|
6
14
|
"changes": [
|
|
@@ -15,6 +15,7 @@ exports.checkHabits = checkHabits;
|
|
|
15
15
|
exports.checkSecurity = checkSecurity;
|
|
16
16
|
exports.checkTrips = checkTrips;
|
|
17
17
|
exports.checkMailroom = checkMailroom;
|
|
18
|
+
exports.checkFriends = checkFriends;
|
|
18
19
|
exports.checkDisk = checkDisk;
|
|
19
20
|
exports.checkLifecycle = checkLifecycle;
|
|
20
21
|
exports.runDoctorChecks = runDoctorChecks;
|
|
@@ -512,6 +513,84 @@ function checkMailroom(deps) {
|
|
|
512
513
|
}
|
|
513
514
|
return { name: "Mailroom", checks };
|
|
514
515
|
}
|
|
516
|
+
function checkFriends(deps) {
|
|
517
|
+
const checks = [];
|
|
518
|
+
const agents = discoverAgents(deps);
|
|
519
|
+
if (agents.length === 0) {
|
|
520
|
+
checks.push({ label: "friends", status: "warn", detail: "no agent bundles found" });
|
|
521
|
+
return { name: "Friends", checks };
|
|
522
|
+
}
|
|
523
|
+
for (const agentDir of agents) {
|
|
524
|
+
const friendsDir = `${deps.bundlesRoot}/${agentDir}/friends`;
|
|
525
|
+
if (!deps.existsSync(friendsDir)) {
|
|
526
|
+
checks.push({ label: `${agentDir} friends`, status: "pass", detail: "no friends directory (no friends recorded yet)" });
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
let entries;
|
|
530
|
+
/* v8 ignore start -- defensive: readdirSync failure after existsSync passes is a race-condition fallback @preserve */
|
|
531
|
+
try {
|
|
532
|
+
entries = deps.readdirSync(friendsDir).filter((name) => name.endsWith(".json"));
|
|
533
|
+
}
|
|
534
|
+
catch {
|
|
535
|
+
checks.push({ label: `${agentDir} friends`, status: "fail", detail: "friends directory could not be read" });
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
/* v8 ignore stop */
|
|
539
|
+
if (entries.length === 0) {
|
|
540
|
+
checks.push({ label: `${agentDir} friends`, status: "pass", detail: "0 friends recorded" });
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
let parseFailures = 0;
|
|
544
|
+
let trustFamily = 0;
|
|
545
|
+
let trustFriend = 0;
|
|
546
|
+
let trustStranger = 0;
|
|
547
|
+
let trustOther = 0;
|
|
548
|
+
/* v8 ignore start -- per-record trust-level tally branches: tests don't exhaustively combine all four trust buckets in one fixture @preserve */
|
|
549
|
+
for (const name of entries) {
|
|
550
|
+
const filePath = `${friendsDir}/${name}`;
|
|
551
|
+
let raw;
|
|
552
|
+
try {
|
|
553
|
+
raw = deps.readFileSync(filePath);
|
|
554
|
+
}
|
|
555
|
+
catch {
|
|
556
|
+
parseFailures += 1;
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
let parsed;
|
|
560
|
+
try {
|
|
561
|
+
parsed = JSON.parse(raw);
|
|
562
|
+
}
|
|
563
|
+
catch {
|
|
564
|
+
parseFailures += 1;
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
const trustLevel = typeof parsed.trustLevel === "string" ? parsed.trustLevel : "friend";
|
|
568
|
+
if (trustLevel === "family")
|
|
569
|
+
trustFamily += 1;
|
|
570
|
+
else if (trustLevel === "friend")
|
|
571
|
+
trustFriend += 1;
|
|
572
|
+
else if (trustLevel === "stranger")
|
|
573
|
+
trustStranger += 1;
|
|
574
|
+
else
|
|
575
|
+
trustOther += 1;
|
|
576
|
+
}
|
|
577
|
+
if (parseFailures > 0) {
|
|
578
|
+
checks.push({ label: `${agentDir} friends`, status: "warn", detail: `${entries.length} record${entries.length === 1 ? "" : "s"}, ${parseFailures} unparseable` });
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
const parts = [
|
|
582
|
+
`${entries.length} friend${entries.length === 1 ? "" : "s"}`,
|
|
583
|
+
`${trustFamily} family`,
|
|
584
|
+
`${trustFriend} friend`,
|
|
585
|
+
`${trustStranger} stranger`,
|
|
586
|
+
];
|
|
587
|
+
if (trustOther > 0)
|
|
588
|
+
parts.push(`${trustOther} other`);
|
|
589
|
+
checks.push({ label: `${agentDir} friends`, status: "pass", detail: parts.join(", ") });
|
|
590
|
+
/* v8 ignore stop */
|
|
591
|
+
}
|
|
592
|
+
return { name: "Friends", checks };
|
|
593
|
+
}
|
|
515
594
|
function checkDisk(deps) {
|
|
516
595
|
const checks = [];
|
|
517
596
|
const addLogSizeCheck = (labelPrefix, logsDir) => {
|
|
@@ -719,6 +798,7 @@ const CATEGORY_CHECKERS = [
|
|
|
719
798
|
{ name: "Security", fn: checkSecurity },
|
|
720
799
|
{ name: "Trips", fn: checkTrips },
|
|
721
800
|
{ name: "Mailroom", fn: checkMailroom },
|
|
801
|
+
{ name: "Friends", fn: checkFriends },
|
|
722
802
|
{ name: "Disk", fn: checkDisk },
|
|
723
803
|
];
|
|
724
804
|
async function runDoctorChecks(deps) {
|