# Upgrade Guide — vNEXT

<!-- assembled-by: assemble-next-md -->
<!-- bump: patch -->

## What Changed

Hardened the messaging layer against a failure seen in the field: when the
encrypted-secrets read fails at startup, the unresolved secret marker used to flow
into the messaging adapter as-is — crash-looping the server on a type error and
leaving the message poller spinning uselessly against a dead address. Now the
adapter recognizes an unusable credential, announces it loudly, and runs in a
well-defined reduced mode instead: no polling, relay sends still work, and the
reason is visible in its status. The deeper at-the-source fix (per-agent keychain
keys and a loud, fail-fast secrets merge) ships separately; this change makes the
messaging layer structurally unable to crash or go silently deaf regardless.

The standby presence watcher no longer reports "agent is actively working"
while a session is actually paused on Claude's session limit. The honest
"paused on its usage limit — resets at HH:MM" message already existed, but
the newer limit-banner wording ("Session limit reached ∙ resets 10:30pm" —
no parenthesized timezone) matched none of its detection patterns, so the
watcher fell back to the generic busy message (the 2026-06-05 topic-2169
incident). Three patterns added; "approaching session limit" deliberately
does not trigger it.

## What to Tell Your User

If your agent ever starts up while its encrypted secrets are unreadable, it now
boots in a clearly-announced reduced messaging mode instead of crashing or going
silently deaf — and a normal restart brings everything back. Nothing changes during
ordinary startups.

If a session hits its Claude limit, my check-in messages now say exactly
that — paused, nothing running, resets at HH:MM — instead of claiming I'm
busy while you wait on a silent machine.

## Summary of New Capabilities

- The messaging adapter refuses to poll with an unusable credential and reports the
  reason in its status, rather than spinning forever against a dead address.
- The server boots through an unresolved messaging credential instead of
  crash-looping on it.
- Maturity: stable; behavior on healthy startups is unchanged.

- Session-limit banners (all current wordings) produce the honest paused
  message across all three presence tiers.

## Evidence

`tests/unit/presence-proxy-quota.test.ts` 21/21 — 5 new (verbatim incident
banner, comma/middot variants, bare reset time, and two negative cases:
"approaching" and prose "resets"). tsc + lint clean.
