Frontend & UI Review + Improvement Plan

Document: FRONTEND_UI_IMPROVEMENT_PLAN.md Scope: miz-oki-command-center-ui/ (Command Center UI — the primary operator frontend), with reference notes on apps/web/ and the # MIZ OKI 3.5/ marketing site Date: August 5, 2026 Status: Review complete — plan proposed, not yet executed Claim label: All figures below are measured results from the repository at the time of review unless labeled otherwise.


Table of Contents

  1. Executive Summary
  2. What Was Reviewed
  3. Current-State Architecture
  4. Backend Wiring Assessment
  5. Best-Practices Conformance Scorecard
  6. Key Findings (Ranked by Severity)
  7. Target Architecture
  8. Improvement Plan — Phases 0–5
  9. UX / Ease-of-Use Redesign
  10. Expansion Opportunities
  11. Risk Register & Rollout Strategy
  12. Success Metrics
  13. Appendix A — Measured Inventory

1. Executive Summary

The Command Center UI is a very large, feature-rich Next.js application (155 pages, 210 API routes, 243 components, 65 hooks, 135 lib modules) that is genuinely well-wired into the backend fleet: it has a real BFF (backend-for-frontend) layer of Next.js API routes that proxy to Cloud Run services with OIDC authentication, SSE streaming, Zustand global state, React Query, and OpenTelemetry instrumentation. This is far beyond a typical dashboard scaffold.

However, the app has accumulated significant structural and quality debt that undermines its strengths:

Dimension Grade One-line verdict
Backend wiring B+ Real BFF + OIDC proxying + SSE, but 391 hardcoded run.app URLs bypass the config layer
Architecture C+ Modular but bloated: 16 app/boss* route directories (7 archived variants shipped in the bundle), duplicate providers
Type safety D strict: false, ignoreBuildErrors: true — the compiler is present but disarmed (baseline ~556 known errors per repo records)
Linting D Good custom rules (navigation safety) but ignoreDuringBuilds: true neutralizes them in CI
Testing F Zero test files in the UI package; Jest is installed but unconfigured and unused
Rendering strategy C dynamic = 'force-dynamic' globally + 311 client components — almost no server-rendering benefit is realized
UX / navigation C+ Powerful but overwhelming: ~87 top-level route groups with no progressive disclosure, no global command palette on all pages, inconsistent loading/empty/error states
Dependencies C Modern core (Next 15.5.21, React 19), but heavy/duplicated graph libs and AI SDKs shipped to the client

Bottom line: the plumbing is real and mostly good; the airframe needs consolidation. The plan below is sequenced so that the safety net comes first (types, lint, tests, CI gates), consolidation second (dead route removal, single API client, config-driven URLs), and UX/expansion third — because refactoring 155 pages without tests or type checking is how regressions ship silently. This ordering matters more than any individual item.


2. What Was Reviewed

2.1 Frontend surfaces in the monorepo

Surface Path Stack Role
Command Center UI (primary) miz-oki-command-center-ui/ Next.js 15.5.21, React 19 (locked 19.2.7), TypeScript 5, Tailwind, Zustand, React Query, Radix UI Operator console for the entire cell fleet, Boss Agent, KG, campaigns
Secondary web app apps/web/ Next.js 16.2.11, React 19.2.3 Smaller app; frontend-guard.yml CI currently targets it (repo docs flag retiring it)
Marketing site # MIZ OKI 3.5/ Flask + static HTML/CSS/JS Public site — canon-locked, human-approval deploys only; explicitly out of scope for changes
Chrome extension chrome-boss-agent-extension/ Manifest V3, vanilla JS Boss Agent browser access — out of scope
VS Code extension vscode-boss-agent-extension/ TypeScript Boss Agent IDE access — out of scope

This plan targets the Command Center UI. The marketing site is governed by the design-canon lock and must not be touched by this effort.

2.2 Measured inventory (Command Center UI)

Metric Count Notes
Pages (page.tsx) 155 Across ~87 top-level app/ route groups
API routes (route.ts) 210 The BFF layer
Components 243 components/
Hooks 65 hooks/
Lib modules 135 lib/ — API clients, auth, telemetry, utils
Store files 10 Zustand slices + provider
Client components ('use client') 311 The overwhelming majority of the UI
Hardcoded run.app URL references 391 Scattered across pages, components, hooks, lib
app/boss* route directories 16 Of which 7 are archived variants still shipped
Test files 0 Jest deps installed, no config, no tests
Known TypeScript errors (repo baseline) ~556 Per CLAUDE.md delta-tsc records; builds pass because errors are ignored

3. Current-State Architecture

3.1 System context

flowchart LR
    subgraph Browser
        UI[Command Center UI<br/>Next.js 15 / React 19<br/>311 client components]
    end

    subgraph "Next.js server (Cloud Run: miz-oki-command-center-ui)"
        BFF[210 API routes<br/>BFF / OIDC proxy layer]
        MW[middleware.ts<br/>Supabase session refresh]
        OTEL[instrumentation.ts<br/>OpenTelemetry]
    end

    subgraph "Cloud Run backend fleet (us-central1)"
        BOSS[boss-agent-adk<br/>1,137+ MCP tools]
        MOA[miz-oki-moa-controller]
        MOE[miz-oki-moe-router]
        CELLS[36 cells<br/>cell01..cell32 + ORACLE 33-36]
        GOV[10 service-* governance services]
    end

    subgraph "Data plane"
        FS[(Firestore<br/>28+ collections)]
        BQ[(BigQuery)]
        NEO[(Neo4j KG)]
        SB[(Supabase Auth)]
        FB[(Firebase)]
    end

    UI -->|fetch /api/*| BFF
    UI -.->|"391 hardcoded run.app URLs (bypass ⚠️)"| CELLS
    UI <-->|SSE / Socket.io| BFF
    BFF -->|OIDC identity tokens| BOSS
    BFF -->|OIDC| MOA & MOE
    BFF -->|"same-origin /api/orchestration proxy"| CELLS
    BOSS --> FS & BQ & NEO
    MW --> SB
    BFF --> FB

The critical wiring flaw is the dotted line: since the Phase-8 IAM lockdown (see CLAUDE.md MIZ-FIN-2026-005), browser code cannot mint Cloud Run OIDC tokens, so every one of the 391 direct *.run.app references in client code is either (a) hitting one of the shrinking set of intended-public services, (b) silently failing with 403, or (c) working only until that service gets IAM-locked. The repo's own records confirm this failure class ("Browser callers cannot mint Cloud Run OIDC — health/widgets against IAM-locked services need a same-origin nodejs proxy"). The BFF pattern already exists (app/api/orchestration/[svc]/[...path]) — it just isn't used consistently.

3.2 Frontend internal architecture (as-is)

flowchart TD
    subgraph "app/ — 87 top-level route groups, 155 pages"
        LAYOUT["layout.tsx<br/>force-dynamic ⚠️<br/>headers()-based auth-route check"]
        PAGES[Feature pages<br/>dashboard, boss, agents, kg,<br/>campaigns, cells, channels ...]
        DEAD["16 app/boss* dirs<br/>7 archived variants still shipped ⚠️"]
        API[210 API routes]
    end

    subgraph "State & data"
        STORE[Zustand store<br/>10 files: slices for agents,<br/>kernels, realtime, ui, workflows]
        RQ[React Query<br/>QueryClientProvider]
        SSE[useSSE / useMultiSSE<br/>global stream in providers.tsx]
        POLL["setInterval polling in providers.tsx<br/>1m / 2m / 5m ⚠️ redundant with SSE"]
    end

    subgraph "lib/ — 135 modules"
        CLIENTS["Multiple overlapping API clients ⚠️<br/>api-service.ts, cloud-run-client.ts,<br/>a2a-client.ts, boss-*-client(s), ..."]
        AUTHZ[supabase/server.ts + client.ts<br/>firebase-client.ts, jwt.ts]
        TEL[telemetry.ts withToolSpan]
        SAFE[safe-navigation.ts toSafeUrl]
    end

    LAYOUT --> PAGES
    PAGES --> STORE & RQ
    PAGES -->|"direct fetch/axios in components ⚠️"| API
    STORE --> SSE
    STORE --> POLL
    PAGES --> CLIENTS
    CLIENTS --> API

Notable as-is properties:


4. Backend Wiring Assessment

4.1 What is genuinely good

Strength Evidence
Real BFF layer 210 API routes proxy browser calls server-side; app/api/orchestration/[svc]/[...path] provides a generic OIDC proxy for locked services
OIDC-aware server fetches lib/service-auth.ts / authedFetch pattern (added during the Phase-8 IAM waves) mints identity tokens server-side
Streaming support SSE routes (app/api/stream, app/api/streaming), useSSE/useMultiSSE hooks, Socket.io client — real-time is a first-class citizen
Observability instrumentation.ts boots OpenTelemetry; withToolSpan/withCellSpan wrap operations; OTel collector sidecar deploy config exists
Auth done twice, both correctly Supabase SSR (@supabase/ssr, cookie sessions, middleware refresh, /auth/callback) plus Firebase for Firestore-backed features
Navigation safety toSafeUrl() + custom ESLint no-restricted-syntax rules to prevent [object Object] URL bugs
Config centralization exists lib/cloud-run-client.ts exposes CLOUD_RUN_CONFIG — the right idea, inconsistently adopted

4.2 Where the wiring is broken or fragile

# Issue Measured evidence Consequence
W1 391 hardcoded *.run.app URLs in UI source grep across app/, components/, hooks/, lib/ Client-side calls to IAM-locked services fail with 403/CORS; URL changes require mass edits; no env separation
W2 In-memory state in API routes app/api/boss/chat/route.ts keeps conversationMemory in a module-level Map Cloud Run scales to N instances / scales to zero → conversations silently lost or split between instances
W3 Direct fetch/axios inside components Widespread pattern alongside React Query No caching, no dedup, no retry policy, inconsistent error handling
W4 Polling + SSE duplication providers.tsx intervals vs global SSE stream Wasted backend load; two sources of truth for the same entities
W5 Known-broken route fixed only recently Repo records: /api/boss/srdal/trace was "a pre-existing broken fetch (served by neither name)"; SSE endpoint 404 until dfab1d8b Symptom of no integration tests — broken wiring ships and lingers
W6 Stale service registries in UI code Cell registry naming issues (cell16/cell18 class) documented in repo records Health widgets can show false outages

4.3 Verdict

Wiring quality is bimodal: the server-side BFF/OIDC/streaming layer is production-grade; the client-side consumption of it is undisciplined. The fix is not new infrastructure — it is funneling all data access through one typed client that only talks to the BFF, and deleting the 391 bypasses.


5. Best-Practices Conformance Scorecard

Assessed against current Next.js 15 / React 19 guidance (App Router, Server Components, streaming, typed APIs) and general frontend engineering practice.

Practice State in repo Conforms?
App Router structure Yes — full app/ directory ✅
React Server Components used meaningfully No — 311/~340 components are client; root layout forces dynamic ❌
loading.tsx / not-found.tsx / global-error.tsx conventions Only app/error.tsx exists; the other three are missing at root ❌
Route groups (group) for organization Not used — 87 flat top-level dirs ❌
TypeScript strict strict: false, target: es2015 ❌
Type-checked builds typescript.ignoreBuildErrors: true ❌
Lint-gated builds eslint.ignoreDuringBuilds: true ❌
Automated tests (unit/integration/E2E) None (0 files) ❌
CI quality gate for the UI frontend-guard.yml targets apps/web, not this app; next build is the only gate and it ignores errors ❌
Data fetching via a caching layer React Query installed; usage inconsistent (W3) ⚠️
Centralized, env-driven service config Exists (CLOUD_RUN_CONFIG) but bypassed 391 times ⚠️
Accessibility (a11y) discipline Radix primitives help; no eslint-plugin-jsx-a11y config, no audits ⚠️
Bundle hygiene Heavy libs (4 graph libs: cytoscape, d3, react-force-graph, reactflow; AI SDKs; langchain) in client deps; no bundle analysis in CI ❌
Error/telemetry reporting OTel server-side ✅; no client error boundary reporting (e.g., no Sentry-class capture) ⚠️
Design system / tokens Tailwind + Radix + class-variance-authority — foundation exists, no documented token system or Storybook ⚠️
Dead code hygiene 7 archived boss variants shipped in the production bundle ❌

Score: 2 ✅ / 6 ⚠️ / 9 ❌. The app is modern in framework version but not in framework usage.


6. Key Findings (Ranked by Severity)

🔴 Critical

F1 — The safety net is disarmed. strict: false + ignoreBuildErrors + ignoreDuringBuilds + zero tests means the only thing standing between a bad change and production is a successful next build. The repo's own history proves the cost: the UI carried a ~556-error TypeScript baseline, a broken SSE endpoint, and a fetch served by no route — all shipped under green CI. Every other improvement in this plan is unsafe to execute until this is fixed.

F2 — 391 hardcoded backend URLs in a fleet that is being IAM-locked. The platform is actively removing public access from services (Phase-8 waves, 47 services flipped to ingress=all + IAM). Browser code cannot mint OIDC tokens. Every hardcoded client-side run.app call is a latent 403.

F3 — Stateful API routes on stateless infrastructure. The in-memory conversationMemory Map in app/api/boss/chat/route.ts (and any similar module-level state) loses data on scale-down and splits sessions across instances. The file's own comment says "replace with Redis/DB in production" — it is in production.

🟠 High

F4 — Dead weight shipped to users. 7 archived app/boss-* variants, duplicated provider trees, and 4 overlapping graph-visualization libraries inflate build time, bundle size, and cognitive load. 155 pages is likely 2–3× the number of pages operators actually use.

F5 — Server-rendering benefits thrown away. force-dynamic on the root layout + near-universal 'use client' means Next.js is being used as an SPA host with extra steps. The auth-route check that forces this belongs in middleware.

F6 — No state-ownership rules. Zustand slices, React Query, SSE stream, polling intervals, and component-local fetches all manage overlapping data. This produces stale-data bugs and makes every new feature a judgment call.

🟡 Medium

F7 — Missing UX conventions. No root loading.tsx/not-found.tsx/global-error.tsx; loading/empty/error states are hand-rolled per page and inconsistent; no skeleton system.

F8 — Navigation overload. ~87 top-level route groups surface in an app with a sidebar that must enumerate them. There is no progressive disclosure, no per-role landing experience, and command-palette (cmdk is installed!) is not wired as the universal navigator.

F9 — Dependency risk. pydantic (a Python package) is listed in package.json dependencies; react-json-view is React-18-era; AI SDKs (openai, @anthropic-ai/sdk, langchain) in the client dependency graph invite accidental client-side key usage.


7. Target Architecture

7.1 Data-flow after the plan

flowchart LR
    subgraph Browser
        RSC[Server Components<br/>initial data, static shells]
        CC[Client components<br/>interactivity only]
        HOOKS[Typed hooks<br/>useQuery / useMutation]
    end

    subgraph "Next.js server"
        GW["lib/api/gateway.ts<br/>ONE typed client<br/>(zod-validated, env-driven)"]
        BFFX[Consolidated BFF routes<br/>~120 after dedup]
        KV[(Redis / Firestore<br/>session + conversation state)]
    end

    subgraph Backend
        FLEET[Cloud Run fleet<br/>OIDC-locked]
    end

    RSC --> GW
    CC --> HOOKS --> BFFX
    BFFX --> GW
    GW -->|OIDC, retries, tracing| FLEET
    BFFX --> KV

    style GW fill:#0a5,stroke:#333,color:#fff

Rules encoded by this architecture (enforced by ESLint, not convention):

  1. Zero run.app strings outside lib/config/services.ts. One env-driven registry; a lint rule bans the literal elsewhere.
  2. Browser code talks only to same-origin /api/*. The BFF is the only path to the fleet.
  3. Server state lives in React Query; UI state lives in Zustand; nothing lives in module scope.
  4. SSE invalidates React Query caches instead of polling — one source of truth, real-time by default.

7.2 Route information architecture (target)

flowchart TD
    ROOT["/ — Role-aware home"]
    ROOT --> OPS["(operations)/<br/>dashboard, cells, health, deployments"]
    ROOT --> AGENTS["(agents)/<br/>boss, agent-ide, moa-moe, launcher"]
    ROOT --> INTEL["(intelligence)/<br/>kg, causal, oracle-intent, analytics"]
    ROOT --> MKTG["(marketing)/<br/>campaigns, channels, creatives, attribution"]
    ROOT --> ADMIN["(admin)/<br/>settings, auth, api-keys, audit"]
    ROOT --> CMDK[["⌘K command palette<br/>universal navigation + actions"]]

    style CMDK fill:#7c3aed,color:#fff

87 flat directories become 5 route groups + a command palette. Archived variants are deleted (they remain in git history). Every page inside a group inherits the group's layout, breadcrumbs, and loading/error conventions.


8. Improvement Plan — Phases 0–5

Sequenced by dependency: each phase makes the next one safe. No calendar estimates; effort is characterized by invasiveness.

Phase 0 — Safety net (low-invasiveness, highest leverage)

# Action Detail
0.1 Type-check gate with a ratchet Keep ignoreBuildErrors for now, but add a CI job running tsc --noEmit against a checked-in baseline (the delta-tsc pattern already used in this repo for the SRDAL migration). Any new error fails CI. Baseline shrinks over time.
0.2 Lint gate with a ratchet Same pattern for ESLint; add eslint-plugin-jsx-a11y and a no-restricted-syntax rule banning run.app literals outside the config module.
0.3 Test harness Configure Vitest + React Testing Library (fast, ESM-native — supersede the unused Jest deps) and Playwright for E2E. Seed with: (a) smoke tests for the 10 most-used pages, (b) contract tests for the 20 most-critical BFF routes, (c) one E2E: login → dashboard → boss chat round-trip.
0.4 CI wiring Point frontend-guard.yml (or a new workflow) at miz-oki-command-center-ui with: typecheck-ratchet, lint-ratchet, unit tests, build.
0.5 Root convention files Add app/loading.tsx, app/not-found.tsx, app/global-error.tsx (with client error reporting in the global boundary).

Exit gate: CI red on any new type/lint error; ≥30 tests passing; conventions present.

Phase 1 — Wiring correctness (medium invasiveness)

# Action Detail
1.1 Service registry module lib/config/services.ts: every backend URL from env vars with typed accessors; dev/staging/prod parity.
1.2 Eliminate the 391 hardcoded URLs Mechanical migration in slices of ~40, each slice verified by the Phase-0 smoke tests. Client-side call sites route through the BFF (/api/orchestration/[svc]/... where a dedicated route doesn't exist).
1.3 Externalize API-route state Move conversationMemory (and any module-level Maps found by an audit for new Map( at module scope in app/api/) to Firestore (already a platform dependency) or Memorystore.
1.4 One gateway client lib/api/gateway.ts wrapping authedFetch with zod response validation, retry/backoff, and withToolSpan tracing. Deprecate api-service.ts / cloud-run-client.ts / per-feature clients by re-exporting through the gateway, then delete.
1.5 SSE→Query invalidation Replace providers.tsx polling intervals with SSE-event-driven queryClient.invalidateQueries calls.

Exit gate: grep -r "run.app" app/ components/ hooks/ lib/ --include='*.ts*' returns only lib/config/services.ts; chat memory survives instance restarts (verified by test).

Phase 2 — Consolidation & dead-code removal (medium-high invasiveness)

# Action Detail
2.1 Delete archived routes Remove the 7 app/boss-*archived* variants + boss-versions-archived-react (git history preserves them). Add 307 redirect shims only for any route with measured traffic.
2.2 Merge boss surfaces Consolidate remaining boss* directories into one (agents)/boss area with tabs — repo history shows this consolidation pattern already worked for /boss-srdal → /boss-srpvdal.
2.3 Single provider tree Merge app/providers.tsx and components/providers.tsx; document the provider order.
2.4 Route groups Reorganize app/ into the 5 groups from §7.2. Next.js route groups don't change URLs, so this is a file-move refactor guarded by the smoke tests + a redirect map for any URL that does change.
2.5 Dependency prune Remove pydantic (Python package in npm deps), react-json-view (replace with a maintained JSON viewer), pick one graph library per use case (recommend keeping reactflow for DAG editing + cytoscape for large KG rendering; drop react-force-graph, jsplumb), move AI SDKs out of client-reachable code paths, dedupe @types/react 18 vs React 19.
2.6 BFF route dedup Audit the 210 API routes for orphans (no caller in app//components//hooks/) — the same 0-importer methodology used in the repo's SRDAL cleanup — and delete or consolidate. Target ~120.

Exit gate: page count reduced ≥25%; bundle size reduced (measured via @next/bundle-analyzer added in this phase); no route 404s in the E2E crawl.

Phase 3 — Rendering & performance (high invasiveness, incremental)

# Action Detail
3.1 Move auth-route detection to middleware Delete the headers() call from app/layout.tsx; drop the global force-dynamic.
3.2 Server-first pages Convert page shells to Server Components with Suspense streaming; keep interactivity in leaf client components. Start with the top-10 pages by traffic.
3.3 loading.tsx per group + skeleton system One skeleton component library; every route group gets streaming loading states.
3.4 Code-split heavy visualizations next/dynamic for cytoscape/reactflow/chart-heavy panels with skeleton fallbacks.
3.5 TypeScript strictening Flip strict: true with the ratchet baseline absorbing existing errors; raise target to es2022; burn down the ~556 baseline opportunistically per touched file.

Exit gate: Lighthouse performance ≥85 on dashboard and boss chat (from a measured pre-phase baseline); TS baseline reduced ≥50%.

Phase 4 — UX overhaul (see §9)

Phase 5 — Expansion (see §10)


9. UX / Ease-of-Use Redesign

9.1 Problems observed

  1. No progressive disclosure — a new operator faces ~87 nav destinations with equal visual weight.
  2. No universal search/actions — cmdk is installed but not surfaced as a global ⌘K palette across pages.
  3. Inconsistent feedback — loading, empty, and error states differ per page; some pages render blank while fetching.
  4. No role-aware entry — an analyst, a media buyer, and a platform operator all land on the same home.
  5. Real-time is invisible — SSE data updates silently; there's no connection-status affordance or "live" indicators.

9.2 Redesign pillars

flowchart LR
    P1["1. Command Palette<br/>⌘K everywhere:<br/>navigate, run MCP tools,<br/>ask Boss"] --> UX((Operator<br/>Experience))
    P2["2. Role-aware Home<br/>3 presets: Operator,<br/>Analyst, Media Buyer"] --> UX
    P3["3. Unified feedback<br/>skeletons, empty states,<br/>error boundaries, toasts —<br/>one component kit"] --> UX
    P4["4. Live-status system<br/>SSE connection badge,<br/>freshness timestamps,<br/>optimistic mutations"] --> UX
    P5["5. Design tokens +<br/>component docs<br/>(Storybook or Ladle)"] --> UX

Concrete deliverables:

Deliverable Description
Global ⌘K palette Fuzzy navigation over all routes + "Ask Boss" free-text handoff + recent items. Single highest-leverage ease-of-use win; cmdk already in deps.
Home dashboard presets Three saved layouts (Operator / Analyst / Media Buyer) selectable at first login, persisted in Zustand + Supabase profile.
Feedback kit <PageSkeleton/>, <EmptyState/>, <ErrorState retry/>, <LiveBadge/> used by every page — enforced by review checklist.
Navigation shell v2 Sidebar shows the 5 groups (collapsed by default) + pinned favorites; breadcrumbs from route groups; mobile sheet retained.
Boss chat as a persistent dock The Boss Agent (the platform's superpower) becomes a slide-over available on every page, not a destination — with page-context automatically attached to prompts.
A11y pass jsx-a11y lint + keyboard traversal audit of the top-20 pages + focus management in dialogs (Radix gives most of this free).

10. Expansion Opportunities

Ordered by value-to-effort once the foundation phases are done:

# Expansion Why
E1 ORACLE/Intent surfaces Cells 33–36 are live with 8 intent_* tools and hourly scoring; the UI has no first-class pages for intent cohorts, transitions, consent stats, or incrementality reports. This is shipped backend capability with no operator window.
E2 Governance console The 10 service-* governance services (passports, DEL scores, approvals, authorizations, audit replay) currently have no unified UI. A "Decision Inbox" (pending approvals with one-click approve/reject + full DecisionProof rendering) directly serves the platform's two-key autonomy model.
E3 Fleet health board Replace scattered health widgets with one board driven by the control-plane truth (Ready + latestReady==latestCreated), encoding the repo's hard-won failure-class rules (403=locked-healthy, 404=no-route, 503=real, timeout=cold-start).
E4 Notification center SSE-driven inbox for guardrail breaches, drift alerts, deploy events — currently these land only in logs.
E5 Saved views & shareable state URL-serialized filters for analytics pages so operators can share exact views.
E6 Mobile/tablet operator mode The nav shell is responsive but data-dense pages are not; a read-only mobile mode for health + approvals covers the on-call use case.

11. Risk Register & Rollout Strategy

Risk Likelihood Impact Mitigation
Refactor regressions on untested pages High (pre-Phase-0) High Phase ordering — no consolidation before the test harness exists; smoke tests per migration slice
URL/route changes breaking bookmarks & external links Medium Medium Redirect shims (the repo's proven 307 dual-accept pattern); crawl-based 404 check in CI
Hardcoded-URL migration breaking a niche page Medium Low-Med Migrate in ~40-URL slices; each slice behind a PR with its own smoke run
Strict-mode flip flooding CI with failures Certain (if unratcheted) Medium Baseline ratchet: existing errors grandfathered, new errors blocked
Bundle/regression from dependency swaps Low Medium @next/bundle-analyzer in CI from Phase 2; size budget check
Team velocity dip during consolidation Medium Medium Phases 1–3 are incremental and per-slice mergeable; no long-lived branch

Rollout: every phase lands as a series of small PRs on main behind the CI gates from Phase 0. No big-bang branch. The dashboard and boss-chat pages get canary attention (manual verification) on every consolidation PR since they are the highest-traffic surfaces.


12. Success Metrics

Metric Baseline (measured) Target
Hardcoded run.app refs in UI source 391 0 (outside config module)
Test files 0 ≥150 unit/contract + ≥10 E2E flows
TypeScript errors (baseline) ~556 ≤250 after Phase 3; trending to 0
CI quality gates on this app build only (errors ignored) typecheck + lint + tests + bundle budget
Top-level app/ route dirs ~87 ≤40 within 5 route groups
app/boss* directories 16 ≤3
Pages shipped 155 ≤115
Client components share 311 (~92%) ≤60% of components
Root convention files 1 of 4 4 of 4
Lighthouse perf (dashboard) unmeasured — capture in Phase 0 ≥85
Time-to-first-meaningful-action for a new operator unmeasured ≤2 clicks or 1 ⌘K query to any core surface

Appendix A — Measured Inventory

All values measured directly from the working tree on the review date.

miz-oki-command-center-ui/
├── app/            155 page.tsx · 210 route.ts · ~87 top-level dirs
│   ├── boss*       16 directories (7 archived variants)
│   ├── error.tsx   ✅ present
│   ├── loading.tsx ❌ missing   not-found.tsx ❌ missing   global-error.tsx ❌ missing
├── components/     243 files (incl. duplicate providers.tsx vs app/providers.tsx)
├── hooks/          65 files (useSSE, useMultiSSE, useBossAgentChat, useCellStatus, ...)
├── lib/            135 files (api-service, cloud-run-client, a2a-client, supabase/,
│                   firebase-client, telemetry, safe-navigation, edge-inference/, ...)
├── store/          10 files (Zustand slices: agents, kernels, realtime, ui, workflows)
├── middleware.ts   ✅ Supabase session refresh
├── instrumentation.ts ✅ OpenTelemetry boot
├── next.config.mjs ⚠️ eslint.ignoreDuringBuilds + typescript.ignoreBuildErrors
├── tsconfig.json   ⚠️ strict:false · target:es2015 · skipLibCheck:true
├── .eslintrc.json  ✅ navigation-safety rules (neutralized in builds)
└── tests           ❌ none (jest deps installed, unconfigured)

Key versions (package-lock.json):
  next 15.5.21 · react 19.2.7 · typescript 5.x · node engine unpinned (env: v22.14.0)

Cross-cutting measurements:
  'use client' occurrences ........ 311
  hardcoded *.run.app references ... 391
  known TS error baseline .......... ~556 (per repo delta-tsc records)

End of plan. This document proposes changes only; no application code was modified as part of this review.

← All docsView source on GitHub →