Skip to content
This repository was archived by the owner on May 26, 2026. It is now read-only.

feat(kora): KR-FE-COCKPIT-NAV-RESTRUCTURE-AND-ALERT-VIEWER-VERIFICATION — sidebar groups + alert viewer aligned to real #197#202

Merged
rafe-walker merged 1 commit into
feature/phase2-upgradesfrom
feat/kora-KR-FE-COCKPIT-NAV-RESTRUCTURE-AND-ALERT-VIEWER-VERIFICATION-MEGABUCKET
May 24, 2026
Merged

feat(kora): KR-FE-COCKPIT-NAV-RESTRUCTURE-AND-ALERT-VIEWER-VERIFICATION — sidebar groups + alert viewer aligned to real #197#202
rafe-walker merged 1 commit into
feature/phase2-upgradesfrom
feat/kora-KR-FE-COCKPIT-NAV-RESTRUCTURE-AND-ALERT-VIEWER-VERIFICATION-MEGABUCKET

Conversation

@rafe-walker

Copy link
Copy Markdown
Owner

Summary

Two deliverables. Primary is the sidebar restructure CC#2 flagged in #198 (past 25 entries, hard to scan); secondary is the verification that AlertInvestigationsPage (built forward-compat in #198) actually renders correctly against real #197 alert payloads.

Per-deliverable status

Deliverable A — Sidebar restructure ✅

  • 43 nav entries grouped into 9 operator-friendly buckets:
    • Expanded by default: Overview / Watch / Email / Promotion Loops / Activity & Reasoning / Control & Tickets
    • Collapsed by default: Daemon & Listeners / Settings / Diagnostic & Docs
  • useSidebarGroupCollapse hook persists per-group state to localStorage["kora.sidebar.groupCollapse.v1"]; operator overrides win over group defaults.
  • SidebarNavGroup component (keyboard-actionable: aria-expanded / aria-controls).
  • Per-group badgeCount = sum of in-group items' badgeCount (operator sees "Promotion Loops 3" without expanding).
  • Plugin items keep their existing bottom section (no behavioral change).

Deliverable B — Alert viewer verification ✅

Type-assumption gaps found + fixed:

  1. ❌ Pre-feat(kora): KR-ALERT-WAKE-AND-EMAIL-INTENT-PROMOTION-AND-ROUTER-LOOSEN-MEGABUCKET — 3 deliverables #197 assumed alert.wake_requested seam exists → ✅ Reality: only alert.investigation_completed is emitted. Endpoint rewritten to iterate completed_rows as the primary signal.
  2. ❌ Pre-feat(kora): KR-ALERT-WAKE-AND-EMAIL-INTENT-PROMOTION-AND-ROUTER-LOOSEN-MEGABUCKET — 3 deliverables #197 speculated title + detail fields → ✅ Reality: no such fields in payload. FE drops them; operator-facing context comes from category + investigation_summary_text.
  3. ❌ Pre-feat(kora): KR-ALERT-WAKE-AND-EMAIL-INTENT-PROMOTION-AND-ROUTER-LOOSEN-MEGABUCKET — 3 deliverables #197 missed alert_id field → ✅ Added: surfaces as a font-mono chip on each card (first 12 chars of UUID) for cross-referencing the originating alert in /alerts.

Drill-down verified for alert IDs: _DRILL_DOWN_SUPPORTED_SEAMS includes alert.investigation_completed (added in #198); FastAPI's {caller_session_id:path} accepts the alert:category:severity literal. No BE changes needed — the drill-down endpoint already handles alert sessions.

Empty state preserved: when window has no completion rows, page renders the calm "Kora hasn't been woken by alerts" empty state.

Drift-guard pin summary (8 new / extended)

Pin Test Asserts
SIDEBAR_GROUP_KEYS_IN_ORDER exported test_canonical_group_order_pinned 9 groups in canonical operator-priority order
SIDEBAR_PATH_TO_GROUP exported test_no_orphan_paths Every nav path belongs to exactly one group (new pages added without a group placement fail at CI)
BUILTIN_NAV_REST derived from groups test_no_orphan_paths Flat list flatMaps from BUILTIN_NAV_GROUPS — can't drift
Operator-priority groups expanded by default test_default_collapsed_groups_are_the_less_used Only daemon / settings / diagnostic default collapsed
Sidebar render uses groups (not flat) test_sidebar_renders_grouped_not_flat sidebarNav.coreItems.map removed; sidebarGroups.map present
Endpoint drives off completed_rows test_endpoint_drives_off_completed_rows_not_wake Regression guard — prevents reverting to the speculative wake_rows iteration
FE type mirrors real BE emission test_alert_wake_consumer_emits_expected_payload_shape Walks wake_consumer.py + asserts every FE-rendered field has a BE emit-source
Drill-down supports alert sessions test_drill_down_supports_alert_session_id_prefix _DRILL_DOWN_SUPPORTED_SEAMS includes alert.investigation_completed + endpoint accepts path-style session ids

STOP-ASKs resolved inline

  1. Sidebar grouping conflicts with routing — no conflict; refactor kept BUILTIN_NAV_REST as a derived view (flatMap) for backward-compat with partitionSidebarNav + plugin-position insertion logic.
  2. Real feat(kora): KR-ALERT-WAKE-AND-EMAIL-INTENT-PROMOTION-AND-ROUTER-LOOSEN-MEGABUCKET — 3 deliverables #197 alert payload divergence — significant. Pre-feat(kora): KR-ALERT-WAKE-AND-EMAIL-INTENT-PROMOTION-AND-ROUTER-LOOSEN-MEGABUCKET — 3 deliverables #197 forward-compat in feat(kora): KR-FE-PROMOTION-REVIEW-MULTI-LOOP-EXTEND-MEGABUCKET — 5 new card variants + alert investigations viewer #198 assumed probe-parallel shape (wake row + title/detail). Reality is consumer-only emission with alert_id. FE shape adjusted; BE endpoint rewritten; drift-guards pinned the new alignment.
  3. Drill-down for alert IDs — no BE changes needed. _DRILL_DOWN_SUPPORTED_SEAMS already includes the alert seams (added in feat(kora): KR-FE-PROMOTION-REVIEW-MULTI-LOOP-EXTEND-MEGABUCKET — 5 new card variants + alert investigations viewer #198); the endpoint matches any literal caller_session_id so alert:cost_ladder:critical joins without endpoint changes.

Screenshots

All 3 in web/docs/cockpit-nav-restructure-and-alert-viewer-verification/:

  • sidebar_before.png — flat 43-entry sidebar (operator scans the whole list)
  • sidebar_after.png — 9 groups; operator-priority surfaces expanded; daemon/settings/diagnostic collapsed; "Promotion Loops 3" badge sum
  • alert_investigations_populated.png — 3 real-shape alert investigations rendering correctly (cost_ladder critical + webhook_dead_letter warning + reasoning_halted warning), each with id: <prefix> chip + drill link

Test plan

  • tsc -b clean
  • vite build clean
  • 115 new + retained tests pass (sidebar pins + alert verification + drift-guards)
  • Full tests/kora_cli/ regression: 0 new failures (76 vs 76 on base via stash)
  • Operator smoke: collapse "Daemon & Listeners" group → refresh page → confirm preference survives
  • Operator smoke: open /alert-investigations post-feat(kora): KR-ALERT-WAKE-AND-EMAIL-INTENT-PROMOTION-AND-ROUTER-LOOSEN-MEGABUCKET — 3 deliverables #197 → confirm real cards render with cost / model / DM status / alert_id chip
  • Operator smoke: click "drill" on an alert card → confirm InvestigationDrillDown surfaces the alert.investigation_completed audit row

Recommended next CC#2 dispatch

  • KR-FE-OPERATOR-FIRST-RUN-WIZARD — as Kora's pip-installable bundle gets closer, a first-run wizard would help operators get from pip install kora to a working cockpit faster (env vars, IsoKron auth, Slack DM channel ID, first probe wake). Single-deliverable bucket; pairs with the daemon migration work landing in parallel.
  • KR-FE-SIDEBAR-MOBILE-COLLAPSE-UX — the group-collapse pattern shipped here works well on desktop but mobile sidebar slides out as a full-screen overlay; need to verify collapse interaction works there + maybe a "collapse all" shortcut. Small follow-on.

🤖 Generated with Claude Code

…ON — sidebar groups + alert viewer aligned to real #197 shape

Two deliverables — primary is the sidebar restructure CC#2 flagged
in #198 (past 25 entries, hard to scan), secondary is the
verification that AlertInvestigationsPage (built forward-compat in
#198) actually renders correctly against real #197
alert.investigation_completed payloads.

A) KR-FE-COCKPIT-NAV-RESTRUCTURE
   * BUILTIN_NAV_REST replaced with BUILTIN_NAV_GROUPS — 9 groups:
     Overview / Watch / Email / Promotion Loops / Activity & Reasoning /
     Control & Tickets / Daemon & Listeners (collapsed) / Settings
     (collapsed) / Diagnostic & Docs (collapsed).
   * New SidebarNavGroup component with collapsible header,
     keyboard-actionable (aria-expanded / aria-controls).
   * Per-group badgeCount = sum of in-group items' badge values
     ("Promotion Loops 3" without expanding).
   * useSidebarGroupCollapse hook — localStorage-persisted
     per-group state (versioned key: kora.sidebar.groupCollapse.v1).
   * Operator-priority groups stay expanded by default; less-used
     groups (Daemon / Settings / Diagnostic) default collapsed.
   * Plugin items still render as their own bottom section
     (existing behavior preserved).
   * Drift-guards: SIDEBAR_GROUP_KEYS_IN_ORDER + SIDEBAR_PATH_TO_GROUP
     exports + orphan-path test (every nav path must belong to
     exactly one group; new pages added without a group placement
     fail at CI) + canonical group order pin + default-collapse
     set pin + render-uses-groups pin.

B) KR-FE-ALERT-VIEWER-VERIFICATION
   * SURPRISE: #197 does NOT emit a separate alert.wake_requested
     seam — only alert.investigation_completed. The forward-compat
     endpoint built in #198 iterated wake_rows (always []), so
     items would have been empty even with real data flowing.
     Fixed: endpoint now drives off completed_rows as the primary
     signal.
   * FE shape tightened to match real #197 emission:
     - Added: alert_id (real BE field, surfaces as a font-mono
       chip on each card with the first 12 chars of the alert UUID
       for /alerts cross-referencing)
     - Removed: title + detail (CC#2 speculation — not in real
       payload; operator-facing context comes from category +
       investigation_summary_text)
   * Pinned the alignment with multiple drift-guards:
     - test_endpoint_drives_off_completed_rows_not_wake — pins
       the BE iteration shape so a regression to wake_rows gets
       caught
     - test_alert_wake_consumer_emits_expected_payload_shape —
       walks kora_cli/alerts/wake_consumer.py + asserts every
       FE-rendered field has a corresponding BE-emitter source
     - test_real_197_payload_shape_renders_completely — exercises
       a synthetic-but-realistic payload through the endpoint
     - test_drill_down_supports_alert_session_id_prefix — verifies
       InvestigationDrillDown from #194 surfaces alert sessions
       via the existing _DRILL_DOWN_SUPPORTED_SEAMS allowlist
     - test_fe_dropped_speculative_title_detail_fields — pins the
       removal so a future refactor can't re-introduce them
   * SeamName Literal keeps alert.wake_requested as forward-compat
     for a future alert wake-emitter bucket (parallel to probe).

Tests: 115 new + retained tests pass. Full kora_cli regression
introduces zero new failures (76 vs 76 on base; pre-existing
PTY / cron_profiles / panel_view inventory / model_switch / engine
test failures confirmed identical on base via stash).

Screenshots: web/docs/cockpit-nav-restructure-and-alert-viewer-verification/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rafe-walker rafe-walker merged commit 4ca2e80 into feature/phase2-upgrades May 24, 2026
2 of 4 checks passed
@rafe-walker rafe-walker deleted the feat/kora-KR-FE-COCKPIT-NAV-RESTRUCTURE-AND-ALERT-VIEWER-VERIFICATION-MEGABUCKET branch May 24, 2026 09:19
rafe-walker added a commit that referenced this pull request May 24, 2026
…irst-run wizard + mobile sidebar polish (#205)

Two deliverables — primary is the operator-onboarding wizard CC#2
flagged in #202 (paired with CC#1 NousResearch#431 per-tenant cost ladder + CC#3
NousResearch#430 Marvin runnable plugin for the pip-installable Kora bundle
vision), secondary is the small mobile-sidebar follow-on from #202.

A) KR-FE-OPERATOR-FIRST-RUN-WIZARD
   * 5-step wizard: Welcome+tenant / Anthropic / IsoKron+Slack /
     Tutorial probe / Promotion intro. First-run detection
     combines marker-file absence + audit-log emptiness → swaps
     "/" to render WizardPage instead of DashboardPage.
   * 6 BE endpoints, each ≤30 LoC of substantive logic:
     - GET  /api/wizard/state (resume + first-run signal)
     - POST /api/wizard/validate-anthropic (1-token test inference)
     - POST /api/wizard/validate-substrate (PostgREST ping)
     - POST /api/wizard/validate-slack (auth.test)
     - POST /api/wizard/trigger-tutorial-probe (synthetic wake)
     - POST /api/wizard/complete (marker write + tenant_id persist)
   * Marker file at $KORA_HOME/wizard_config.json. Operator can
     re-open the wizard anytime at /wizard URL.
   * tenant_id wired through every step + the .env download +
     the tutorial probe — NOT hardcoded "default" — feeds CC#1
     NousResearch#431's per-tenant cost-ladder foundation.
   * .env download flow: wizard NEVER mutates operator shell;
     surfaces downloadable .env operator copies to $KORA_HOME/.env
     then restarts Kora. Per the security posture: never modify
     operator env without explicit consent.
   * Validation badges (success / auth_failure / network_failure /
     timeout) render inline so operator knows immediately why a
     credential failed.
   * Drift-guards: _WIZARD_STEPS + _WIZARD_VALIDATION_RESULTS
     allowlists pinned across BE/FE/page.

B) KR-FE-SIDEBAR-MOBILE-COLLAPSE-UX (small follow-on to #202)
   * Collapse-all / Expand-all shortcut at the top of the sidebar
     (mobile + desktop). Label flips with state (allCollapsed →
     "Expand all"; otherwise "Collapse all"). Tappable on the
     375px mobile overlay.
   * useSidebarGroupCollapse hook extended with allCollapsed +
     setAll public surface methods backing the shortcut.
   * Badge overflow: formatBadgeCount caps display at "99+" so a
     long backlog can't break the narrow mobile chip. Numeric
     aria-label keeps the exact count for screen readers.

Tests: 52 new tests covering wizard endpoints (5 state behaviours,
4 validation paths, tutorial-probe audit emission, complete-flow,
2 drift-guards + 5 FE source-pins) + sidebar overflow + collapse-all
(5 pins). Full kora_cli regression: 0 new failures (76 vs 76 on
base via stash — pre-existing PTY / cron / panel-view / engine
failures unchanged).

Screenshots: web/docs/operator-first-run-wizard-and-sidebar-mobile-ux/
(5 wizard steps + before/after mobile sidebar).

Co-authored-by: CC#2 Kora Web <kora-pm@stormhavenenterprises.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant