fix(historian): break stuck "compacting history" notification loop
Closes #85.
Symptom: the `⏳ Context at 95% — Magic Context is compacting history`
notification fired on every turn even though real context usage was
tiny (3.7% in the reporter's case), with zero historian failures
recorded.
Root cause: an earlier transient overflow error armed
`needs_emergency_recovery=true` on the session_meta row. The flag was
cleared in only two places:
1. inside the publish transaction, after historian successfully
wrote new compartments
2. on a model switch
The 95%-block transform path:
- bumped synthetic percentage to 95% because the flag was armed
- started a real historian run
- historian hit one of two SILENT no-op returns at the top of
`runCompartmentAgent`:
- `protectedTailStart <= offset` (no eligible raw history)
- `chunk.text empty || chunk.messageCount === 0` (everything
filtered out as noise — ignored notifications, structural
messages)
- returned before any publish path could clear the flag, AND
without recording any historian failure
- notification + run repeated next turn forever
Oracle analysis confirmed via `transform-compartment-phase.ts:125-163`
that `awaitCompartmentRun` reports "completed" for any settled promise,
which is why the user's log showed `compartmentPhase elapsed=24.3ms`
followed by "completed" — that's the silent return path bailing
before the first real await at `client.session.get(...)`.
Fix:
- both silent no-op returns now log a clear reason AND call
`clearEmergencyRecovery(db, sessionId)` before returning. The
detected context limit stays — that's authoritative provider data
that remains useful for pressure math.
- while in here, also record `incrementHistorianFailure()` on two
other previously-silent paths that Oracle flagged
(`existing-validation`, `chunk-coverage`). These ARE real
failures (corrupt stored state, unsafe chunk shape) — without
recording them, `doctor --issue` reports a clean session while
the user is stuck.
Verification:
- plugin: 1431 tests pass (no new tests needed — the existing
coverage of the publish-side clear is the regression suite; this
fix just propagates the same call to the no-op return sites)
- lint, typecheck, build all clean U
ualtinok committed
9267af60f93f2b453ed944fd3404e6cd86d63d83
Parent: 801802f