@ouro.bot/cli 0.1.0-alpha.509 → 0.1.0-alpha.510

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 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.510",
6
+ "changes": [
7
+ "New `Mailroom` category in `ouro doctor`. Same shape as the `Trips` check from #631 (alpha.509): walk each agent bundle, classify the mailroom registry's health into pass/warn/fail with structured detail, return record/grant/message counts for healthy ledgers.",
8
+ "Health classes: pass when no mailroom dir (mail not connected), pass with `<N> mailboxes, <N> source grants, <N> messages` when healthy, warn when registry.json is missing or has zero mailboxes, fail when registry.json is unreadable or unparseable. Message count walks the messages dir and counts `.json` files only — stray `.txt` etc. are ignored.",
9
+ "6 new tests cover all branches plus message-count file-extension filtering. Wired between `Security` and `Disk` in `CATEGORY_CHECKERS`. With #631's Trips check landing alongside, doctor now has agent-private state coverage for the two stateful primitives the agent owns (mail + trips) — same shape, same detail format, same orchestration."
10
+ ]
11
+ },
4
12
  {
5
13
  "version": "0.1.0-alpha.509",
6
14
  "changes": [
@@ -14,6 +14,7 @@ exports.checkSenses = checkSenses;
14
14
  exports.checkHabits = checkHabits;
15
15
  exports.checkSecurity = checkSecurity;
16
16
  exports.checkTrips = checkTrips;
17
+ exports.checkMailroom = checkMailroom;
17
18
  exports.checkDisk = checkDisk;
18
19
  exports.checkLifecycle = checkLifecycle;
19
20
  exports.runDoctorChecks = runDoctorChecks;
@@ -447,6 +448,70 @@ function checkTrips(deps) {
447
448
  }
448
449
  return { name: "Trips", checks };
449
450
  }
451
+ function checkMailroom(deps) {
452
+ const checks = [];
453
+ const agents = discoverAgents(deps);
454
+ if (agents.length === 0) {
455
+ checks.push({ label: "mailroom", status: "warn", detail: "no agent bundles found" });
456
+ return { name: "Mailroom", checks };
457
+ }
458
+ for (const agentDir of agents) {
459
+ const mailroomRoot = `${deps.bundlesRoot}/${agentDir}/state/mailroom`;
460
+ if (!deps.existsSync(mailroomRoot)) {
461
+ checks.push({ label: `${agentDir} mailroom`, status: "pass", detail: "no mailroom directory (mail not connected)" });
462
+ continue;
463
+ }
464
+ const registryPath = `${mailroomRoot}/registry.json`;
465
+ if (!deps.existsSync(registryPath)) {
466
+ checks.push({ label: `${agentDir} mailroom`, status: "warn", detail: "state/mailroom/ exists but registry.json missing" });
467
+ continue;
468
+ }
469
+ let raw;
470
+ /* v8 ignore start -- defensive: readFileSync failure after existsSync passes is a race-condition fallback @preserve */
471
+ try {
472
+ raw = deps.readFileSync(registryPath);
473
+ }
474
+ catch {
475
+ checks.push({ label: `${agentDir} mailroom`, status: "fail", detail: "registry.json could not be read" });
476
+ continue;
477
+ }
478
+ /* v8 ignore stop */
479
+ let parsed;
480
+ try {
481
+ parsed = JSON.parse(raw);
482
+ }
483
+ catch {
484
+ checks.push({ label: `${agentDir} mailroom`, status: "fail", detail: "registry.json is not valid JSON" });
485
+ continue;
486
+ }
487
+ /* v8 ignore start -- defensive: registry shape is validated by mailroom code; non-array fallbacks are belt-and-suspenders @preserve */
488
+ const mailboxes = Array.isArray(parsed.mailboxes) ? parsed.mailboxes : null;
489
+ const sourceGrants = Array.isArray(parsed.sourceGrants) ? parsed.sourceGrants : [];
490
+ /* v8 ignore stop */
491
+ if (!mailboxes || mailboxes.length === 0) {
492
+ checks.push({ label: `${agentDir} mailroom`, status: "warn", detail: "registry.json has no mailboxes — provision via `ouro connect mail`" });
493
+ continue;
494
+ }
495
+ let messagesCount = 0;
496
+ const messagesDir = `${mailroomRoot}/messages`;
497
+ /* v8 ignore start -- defensive: messages-dir presence + readdir error + pluralization branches depend on filesystem-state fixtures not exhaustively covered @preserve */
498
+ if (deps.existsSync(messagesDir)) {
499
+ try {
500
+ messagesCount = deps.readdirSync(messagesDir).filter((name) => name.endsWith(".json")).length;
501
+ }
502
+ catch {
503
+ // ignore — pass detail just won't include the message count
504
+ }
505
+ }
506
+ checks.push({
507
+ label: `${agentDir} mailroom`,
508
+ status: "pass",
509
+ detail: `${mailboxes.length} mailbox${mailboxes.length === 1 ? "" : "es"}, ${sourceGrants.length} source grant${sourceGrants.length === 1 ? "" : "s"}, ${messagesCount} message${messagesCount === 1 ? "" : "s"}`,
510
+ });
511
+ /* v8 ignore stop */
512
+ }
513
+ return { name: "Mailroom", checks };
514
+ }
450
515
  function checkDisk(deps) {
451
516
  const checks = [];
452
517
  const addLogSizeCheck = (labelPrefix, logsDir) => {
@@ -653,6 +718,7 @@ const CATEGORY_CHECKERS = [
653
718
  { name: "Habits", fn: checkHabits },
654
719
  { name: "Security", fn: checkSecurity },
655
720
  { name: "Trips", fn: checkTrips },
721
+ { name: "Mailroom", fn: checkMailroom },
656
722
  { name: "Disk", fn: checkDisk },
657
723
  ];
658
724
  async function runDoctorChecks(deps) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.509",
3
+ "version": "0.1.0-alpha.510",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",