# Upgrade Guide — vNEXT

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

## What Changed

The Mandates dashboard tab was overhauled after a real operator failed to
issue a mandate through it (2026-06-05). Four fixes:

1. **Layout**: the panel (and the Process Health / Machines / Preferences
   panels, which shared the bug) rendered squashed into the 280px sidebar
   grid column. All `.ph-root` panels now span the full grid.
2. **Pre-fills**: Agent A is pre-filled with this agent's own routing
   fingerprint (fetched from `/threadline/health`); expiry is pre-filled to
   one week out. The operator no longer pastes hex strings the system
   already knows.
3. **Validation**: clicking Issue with missing/invalid fields now reports
   EVERY problem at once in plain English, client-side, before anything is
   sent. Previously an empty form POSTed, the server refused, and the only
   feedback was a transient toast.
4. **Persistent feedback**: errors and the "✓ Mandate issued" confirmation
   are persistent banners, not 8-second toasts. A silent failure is no
   longer possible; success is unmissable.

The last knowingly-stale entry from the 2026-06-05 test-debt triage is
resolved: the TunnelManager unit suite — parked in the CI skip-list because it
predated the tunnel provider/tier rewrite (22 of its 29 tests could never
pass) — has been rewritten against the current architecture and turned back
on. The tunnel layer's core lifecycle is now gated in CI at the manager level:
provider-pool fallback, the reachability probe, the owner-consent flow for
backup relays (including the single-use nonce and the decline cooldown), the
self-heal stability gate, and mandatory credential rotation after a relay
episode.

## What to Tell Your User

If you ever tried to issue a coordination mandate from the dashboard and
nothing seemed to happen, that flow is fixed: the form now fills in
everything the system already knows, tells you exactly what is missing
before submitting, and shows an unmissable confirmation when the mandate is
issued. The Mandates, Process Health, Machines, and Preferences tabs also
now use the full width of the page instead of a narrow column.

Nothing user-visible. This hardens the safety net around the tunnel/backup-
relay machinery your dashboard links depend on — regressions in that
machinery now fail PRs instead of shipping.

## Summary of New Capabilities

- Mandates tab: pre-filled Agent A fingerprint + default one-week expiry,
  all-at-once client-side validation, persistent success/error banners,
  plain-English field hints, and the issue form auto-opens when no mandates
  exist yet.
- Layout fix for all `.ph-root` dashboard panels (Mandates, Process Health,
  Machines, Preferences Learning): full-grid width instead of the sidebar
  column.
- Maturity: stable (UI-only change over the existing PIN-gated issuance
  API; no server surface changed).

- `tests/unit/TunnelManager.test.ts` runs in CI again (removed from the
  vitest.push.config.ts quarantine): 51 deterministic tests driven entirely
  through the constructor injection seams (`injections.providers`,
  `injections.fetch`) and the public deterministic drivers
  (`runSelfHealCheck()`, `grantConsent()`, `declineConsent()`) — no real
  timers, processes, or network.
- Maturity: stable (test-only change + quarantine re-arm; no production code
  touched).

## Evidence

Born from a live operator report (2026-06-05): "I clicked 'Issue Mandate'
after entering my PIN… this UI/UX is TERRIBLE. Very confusing, unclear, and
squashed to the side" — the mandate never registered server-side and the
failure was invisible. 24 tests green in the mandates tab suite (squash
regression pin, every-problem-at-once validation, persistence under fake
timers, prefill + never-overwrite, auto-open); 80 green across all dashboard
suites; tsc clean.

Three consecutive green runs (51/51, ~0.8s each), including under the push
config; the full 11-file tunnel test family passes together (165/165);
`npx tsc --noEmit` clean. The rewrite-era sibling suites
(tunnel-manager-rewrite / tunnel-self-heal / tunnel-consent-state-machine /
tunnel-credential-rotation) already covered parts of this surface — this
suite consolidates the manager-level coverage, adds the previously-untested
edge paths (persisted-state restore, corrupted state file, nonce replay,
cooldown suppression across restart, rotation-failure flag retention,
probe-handle release), and retires the stale file that occupied the
canonical TunnelManager.test.ts name.
