Context
#14163 (autonomous self-heal observability) splits into a pure substrate (the durable ledger + the fold/filter query layer) and the live wiring (the actuator/freeze/accepted-loss paths appending events + any MCP/consumer exposure). The wiring is gated on the apply()-cutover (#14138 + the DataIntegrityDiagnosisService heal-wiring) — events don't flow until the actuator is live. The substrate has no such dependency and is delivered + tested here, ready for Ada's #14158 alert (a reader) and #14166's contained records to consume.
Scope (this leaf — all delivered)
healEventLedgerStore.mjs — append-only JSONL heal-event ledger (appendHealEvent stamps at from the injected clock; readHealLedger is fail-safe: missing → [], corrupt line skipped, never crashes the recovery loop).
summarizeHealLedger — folds the stream into the status surface: totals, counts by status + type, and the currently-frozen set (freeze adds / unfreeze removes, last transition wins).
queryHealLedger — the filtered "what happened" view: inclusive time window + type/collection/status filters, newest-first, capped at limit; drops non-objects; excludes untimed events under a time bound.
Acceptance criteria (delivered)
Gated follow-up (stays on #14163)
The live actuator/freeze/accepted-loss paths appending heal-events, and any MCP/service exposure of the status surface, land once the apply()-cutover makes the actuator a live producer. Distinct from Ada's #14158 (the alert reader) per her confirmation — this is the substrate both consume.
Refs #14163 · Refs #14134 · Refs #14039
Authored by Grace (Claude Opus 4.8, Claude Code). Session 090a68e6-1a28-4b20-a5fd-842ebac3e729.
Context
#14163 (autonomous self-heal observability) splits into a pure substrate (the durable ledger + the fold/filter query layer) and the live wiring (the actuator/freeze/accepted-loss paths appending events + any MCP/consumer exposure). The wiring is gated on the apply()-cutover (#14138 + the
DataIntegrityDiagnosisServiceheal-wiring) — events don't flow until the actuator is live. The substrate has no such dependency and is delivered + tested here, ready for Ada's #14158 alert (a reader) and #14166'scontainedrecords to consume.Scope (this leaf — all delivered)
healEventLedgerStore.mjs— append-only JSONL heal-event ledger (appendHealEventstampsatfrom the injected clock;readHealLedgeris fail-safe: missing →[], corrupt line skipped, never crashes the recovery loop).summarizeHealLedger— folds the stream into the status surface: totals, counts by status + type, and the currently-frozen set (freeze adds / unfreeze removes, last transition wins).queryHealLedger— the filtered "what happened" view: inclusive time window + type/collection/status filters, newest-first, capped at limit; drops non-objects; excludes untimed events under a time bound.Acceptance criteria (delivered)
Gated follow-up (stays on #14163)
The live actuator/freeze/accepted-loss paths appending heal-events, and any MCP/service exposure of the status surface, land once the apply()-cutover makes the actuator a live producer. Distinct from Ada's #14158 (the alert reader) per her confirmation — this is the substrate both consume.
Refs #14163 · Refs #14134 · Refs #14039
Authored by Grace (Claude Opus 4.8, Claude Code). Session 090a68e6-1a28-4b20-a5fd-842ebac3e729.