Commit 95f62fe
Brain Health PR-2: wire helpers + heartbeat anomaly aggregation + nell health CLI (#19)
* feat(health): wire attempt_heal/save_with_backup into config + state files — Health T9
PersonaConfig, UserPreferences, HeartbeatConfig._load_internal, and
HeartbeatState all now route through attempt_heal() (corrupt → quarantine
+ .bak restore) and save_with_backup() (atomic .bak rotation). Each class
gains a load_with_anomaly classmethod returning (instance, BrainAnomaly|None);
existing load() delegates and logs at WARNING on anomaly. HeartbeatConfig
gains _load_internal_with_anomaly parallel to _load_internal. 8 new tests
cover quarantine-and-reset + restore-from-bak paths. 578→586 passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(health): wire attempt_heal/save_with_backup into identity files — Health T10
InterestSet, ReflexArcSet, ReflexLog, load_persona_vocabulary, growth
scheduler's _read_current_vocabulary_names and _append_to_vocabulary all
now route through attempt_heal() (corrupt → quarantine + .bak restore)
and save_with_backup() (atomic .bak rotation). Each affected class gains
a load_with_anomaly classmethod returning (instance, BrainAnomaly|None);
existing load() delegates and logs at WARNING on anomaly. 9 new tests
cover quarantine-and-restore-from-bak + corrupt-no-bak-reset-to-default
paths. 586→595 passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(health): generalize read_jsonl_skipping_corrupt to all log readers — Health T11
- brain/growth/log.py: read_growth_log now delegates the inline
splitlines+json.loads loop to read_jsonl_skipping_corrupt, then
calls _event_from_dict per entry. Removes ~15 lines of duplicate
parse logic; schema-error on a well-formed JSON line is still caught
and logged via the module logger. Test updated to match the shared
helper's warning text ("malformed jsonl line").
- brain/engines/research.py: ResearchLog.load now routes through
attempt_heal with a schema validator; corrupt files are quarantined
and the most recent .bak is restored automatically. save() upgraded
from bare tmp+os.replace to save_with_backup, feeding the
adaptive-treatment layer. Unused json/os imports removed.
- brain/engines/reflex.py: ReflexLog.load gets the same attempt_heal
treatment; a WARNING with anomaly kind/action/file is emitted on
corruption, matching the ReflexArcSet pattern already in place.
- heartbeat.py / dream.py: confirmed no-op — two json.loads calls in
heartbeat are post-write verification, not log readers; dream engine
has no reader.
- 6 new tests added (3 reflex, 3 research): corrupt-quarantines-warns,
heals-from-bak, and load-missing-returns-empty for both log types.
Full suite 601/601 green; ruff clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(health): heartbeat anomaly aggregation + audit log + cross-file walk + compact CLI — Health T12
- HeartbeatResult gains anomalies: tuple[BrainAnomaly, ...] and pending_alarms_count: int
- HeartbeatConfig.load() refactored through load_with_anomaly() so the merge logic is shared
- run_tick collects anomalies from config + state loads via _with_anomaly variants
- >=2 anomalies per tick triggers walk_persona() cross-file scan (deduped by file+kind)
- compute_pending_alarms() called every tick; count written to audit log + HeartbeatResult
- audit log entries always carry "anomalies": [...] and "pending_alarms_count": int
- compact CLI: banner above engine status when pending_alarms_count > 0; 🩹 line when
self-healed anomalies exist but no pending alarms
- 7 new tests (4 heartbeat engine, 3 CLI); 608/608 passing; ruff clean
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(health): nell health show/check/acknowledge CLI — Health T13
Three read-only / audit-append subcommands wired to brain.health:
- `nell health show --persona X` prints pending alarms + recent self-treatments from the heartbeats audit log (last 7 days).
- `nell health check --persona X` runs walk_persona, prints per-file ✅/1 parent edbb39c commit 95f62fe
22 files changed
Lines changed: 1665 additions & 215 deletions
File tree
- brain
- emotion
- engines
- growth
- health
- tests/unit/brain
- emotion
- engines
- growth
- health
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
23 | 26 | | |
24 | 27 | | |
25 | 28 | | |
26 | 29 | | |
27 | 30 | | |
28 | 31 | | |
| 32 | + | |
29 | 33 | | |
30 | 34 | | |
31 | 35 | | |
| |||
185 | 189 | | |
186 | 190 | | |
187 | 191 | | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
188 | 201 | | |
189 | 202 | | |
190 | 203 | | |
| |||
216 | 229 | | |
217 | 230 | | |
218 | 231 | | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
219 | 247 | | |
220 | 248 | | |
221 | 249 | | |
| |||
396 | 424 | | |
397 | 425 | | |
398 | 426 | | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
| 481 | + | |
| 482 | + | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
399 | 581 | | |
400 | 582 | | |
401 | 583 | | |
| |||
605 | 787 | | |
606 | 788 | | |
607 | 789 | | |
| 790 | + | |
| 791 | + | |
| 792 | + | |
| 793 | + | |
| 794 | + | |
| 795 | + | |
| 796 | + | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
| 801 | + | |
| 802 | + | |
| 803 | + | |
| 804 | + | |
| 805 | + | |
| 806 | + | |
| 807 | + | |
| 808 | + | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
608 | 828 | | |
609 | 829 | | |
610 | 830 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | 12 | | |
14 | 13 | | |
| 14 | + | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
20 | 23 | | |
21 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
22 | 76 | | |
23 | 77 | | |
24 | 78 | | |
| |||
32 | 86 | | |
33 | 87 | | |
34 | 88 | | |
35 | | - | |
| 89 | + | |
36 | 90 | | |
37 | 91 | | |
38 | 92 | | |
39 | 93 | | |
40 | 94 | | |
41 | 95 | | |
42 | 96 | | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | | - | |
47 | | - | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
| 97 | + | |
| 98 | + | |
53 | 99 | | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | 100 | | |
| 101 | + | |
| 102 | + | |
61 | 103 | | |
62 | | - | |
| 104 | + | |
63 | 105 | | |
64 | 106 | | |
65 | 107 | | |
| |||
75 | 117 | | |
76 | 118 | | |
77 | 119 | | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
82 | 120 | | |
83 | 121 | | |
84 | 122 | | |
| |||
0 commit comments