danielmiessler / danielmiessler/LifeOS
Memory health permanently WARNs on memory-retrievals.jsonl: CortexHealth checks a stream MemoryRetriever never writes
- Dominant language
- TypeScript
- Stars
- 19k
- Forks
- 2.5k
- Avg merge
- 8d 17h
- Merged PRs (30d)
- 1
Description
# Title
Memory health permanently WARNs on `memory-retrievals.jsonl`: CortexHealth checks a stream MemoryRetriever never writes
# Body
## What happens
On a fresh 7.40.4 install, `bun LIFEOS/TOOLS/MemoryHealthCheck.ts` reports `overall: warn` with:
```
retrieval-missing: No retrieval evidence within 86400000ms freshness window.
```
The statusline renders this as `🧠 NEEDS ATTENTION · NO RETRIEVAL EVIDENCE WITHIN 86400000MS FRESHNESS…` and it never clears, no matter how much retrieval actually happens. The `` block is injected every turn, so retrieval is working; it just isn't recorded.
## Why
The stream was designed but the writer was never built, and a health check was later added that assumes it exists.
- `ObservabilitySystem.md:55` still carries the original note: `MemoryRetriever.getRelevantContext()` (ISC-107..112; **not yet populated as of 2026-05-23; infrastructure ready**).
- `MemorySystem.md` lists the stream as "Per-turn retrievals — written by MemoryRetriever".
- Release 7.40.4 (`be9e8ef`) added `CortexHealth.ts`, which reads `MEMORY/OBSERVABILITY/memory-retrievals.jsonl` and WARNs when the latest row is missing or older than 24h. `CortexContract.md:203` codifies it: "Retrieval evidence freshness | 24 hours | WARN when missing/stale".
- `git grep memory-retrievals` over the whole tree returns only readers: `CortexHealth.ts`, `MemoryStatus.ts`, and three docs. `MemoryRetriever.ts` has never contained the string in any commit.
- No test references the stream, so a check shipping without its producer could not fail anywhere.
## Fix
PR: https://github.com/danielmiessler/LifeOS/pull/2094
Adds the writer to `getRelevantContext()`. Every uncached exit funnels through one `finish()` closure that appends a row shaped exactly as `CortexHealth.validRetrievalRow` requires: `{ts, query_hash, returned_count, duration_ms}` plus optional `top_score`.
Design choices worth a look:
- **Empty-result paths are recorded.** An empty retrieval is still evidence the retriever ran this turn, which is what the freshness check is asking about.
- **Cache hits are not recorded.** They do no ranking work; the stream is described as a "per-turn BM25 audit".
- **The query is never persisted.** It is the principal's prompt. The row carries a 16-hex sha256 prefix of the cache key, enough to correlate repeats.
- **Writes are best-effort and swallowed.** The retriever sits on every turn's critical path; a full disk must not turn into a thrown error.
Adds `bun MemoryRetriever.ts test`, following the self-test convention `MemoryReviewer` and seven other TOOLS already use. It runs the real hot-path entry point in a child process against a throwaway corpus and validates the rows with the real `collectCortexEvidence` / `assessCortexEvidence`. 12 assertions.
Updates the `ObservabilitySystem.md:55` note from "not yet populated" to the landed behavior.
## Verified
- `bun MemoryRetriever.ts test` → PASS (12/12)
- `MemoryHealthCheck.ts` on a live install: `warn {critical:0, warn:1}` → `ok {critical:0, warn:0, ok:26}`
- Existing CLI (`--help`, positional query, corpus-missing error) unchanged
## Diff footprint
```
LIFEOS/DOCUMENTATION/Observability/ObservabilitySystem.md | 2 +-
LIFEOS/TOOLS/MemoryRetriever.ts | 166 +++++++++++++--
```
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with LIFEOS/TOOLS/MemoryRetriever.ts and the retrieval freshness logic in CortexHealth.ts, then run `bun MemoryRetriever.ts test` to inspect the existing self-test and expected evidence rows. Done means retrieval activity produces valid stream evidence, the health check clears on a live install, existing CLI behavior remains unchanged, and the note in ObservabilitySystem.md is current.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- documentation, observability, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 25/100