{
  "slug": "app-shell",
  "spec_file": "docs/specs/2026-05-30-app-shell.md",
  "findings": [
    {
      "id": "app-shell-001",
      "severity": "P0",
      "type": "broken",
      "summary": "Sidebar Dashboard links to /dashboard but no such route exists",
      "spec_ref": "Sidebar Navigation — Dashboard",
      "code_ref": "apps/zync-app/src/shell/nav-model.ts:48",
      "evidence": "NAV_MODEL sets Dashboard to '/dashboard'; routes/index.tsx registers home only at path '' (/) and grep finds no 'dashboard' path under moduleRoutes.",
      "repro": "Login → click Dashboard in sidebar → URL is /dashboard with empty main content."
    },
    {
      "id": "app-shell-002",
      "severity": "P0",
      "type": "broken",
      "summary": "Tenant switch hard-reloads to /dashboard which has no route",
      "spec_ref": "Tenant Switcher — Switch flow step 4",
      "code_ref": "apps/zync-app/src/shell/TenantSwitcher.tsx:92",
      "evidence": "switchTenant success calls window.location.assign('/dashboard'); no /dashboard route registered in main.tsx or routes/index.tsx.",
      "repro": "Multi-tenant user → Switch workspace → lands on blank /dashboard."
    },
    {
      "id": "app-shell-003",
      "severity": "P0",
      "type": "broken",
      "summary": "Profile nav targets /profile but no profile route is registered",
      "spec_ref": "Sidebar — User avatar links to /profile",
      "code_ref": "apps/zync-app/src/shell/Sidebar.tsx:349",
      "evidence": "Sidebar and UserMenu navigate to '/profile'; grep of apps/zync-app/src routes/modules shows no profile route (only /staff/profile).",
      "repro": "Open user menu → Profile → blank shell outlet at /profile."
    },
    {
      "id": "app-shell-004",
      "severity": "P2",
      "type": "divergent",
      "summary": "Marketing nav has expandable children; spec lists flat Marketing item",
      "spec_ref": "Sidebar Navigation — Business group",
      "code_ref": "apps/zync-app/src/shell/nav-model.ts:97",
      "evidence": "nav-model Marketing item defines children (pipeline, proposals, campaigns, catalog); spec tree shows single Marketing entry only.",
      "repro": ""
    },
    {
      "id": "app-shell-005",
      "severity": "P2",
      "type": "divergent",
      "summary": "Reports nav uses expandable children; spec limits one-level children to Invoices",
      "spec_ref": "Invoices sub-nav — only Financials item with children",
      "code_ref": "apps/zync-app/src/shell/nav-model.ts:236",
      "evidence": "Reports item has children array (analytics + seven tax routes); spec states Invoices is the only Financials item using inline expandable children.",
      "repro": ""
    },
    {
      "id": "app-shell-006",
      "severity": "P2",
      "type": "missing",
      "summary": "Sidebar tenant name is not clickable TenantSwitcher entry point",
      "spec_ref": "Tenant Switcher — Entry points #2",
      "code_ref": "apps/zync-app/src/shell/Sidebar.tsx:304",
      "evidence": "Sidebar top renders static tenant slug text; TenantSwitcher is only mounted in UserMenu.tsx, not sidebar branding area.",
      "repro": ""
    },
    {
      "id": "app-shell-007",
      "severity": "P2",
      "type": "missing",
      "summary": "Mobile overlay sidebar not wired; Header only toggles desktop collapse",
      "spec_ref": "Mobile (< 768px) — overlay on hamburger tap",
      "code_ref": "apps/zync-app/src/shell/Header.tsx:48",
      "evidence": "Header onClick calls setSidebarCollapsed; mobileSidebarOpen exists in Shell but MobileSidebarOverlay is never imported/mounted (grep only finds its own file).",
      "repro": ""
    },
    {
      "id": "app-shell-008",
      "severity": "P2",
      "type": "missing",
      "summary": "Single-tenant sidebar lacks Create new workspace link at bottom",
      "spec_ref": "Single-tenant users — Create new workspace in sidebar",
      "code_ref": "apps/zync-app/src/shell/Sidebar.tsx:337",
      "evidence": "Sidebar bottom has Settings, Profile, collapse toggle only; create link exists only inside TenantSwitcher popover footer.",
      "repro": ""
    },
    {
      "id": "app-shell-009",
      "severity": "P3",
      "type": "cosmetic",
      "summary": "Session bootstrap shows spinner instead of AppSkeleton",
      "spec_ref": "Route-Level Code Splitting — Suspense fallback AppSkeleton",
      "code_ref": "apps/zync-app/src/shell/Shell.tsx:87",
      "evidence": "isLoading branch renders animate-spin div; AppSkeleton/ModuleSkeleton used only inside Suspense around Outlet.",
      "repro": ""
    }
  ],
  "summary": { "P0": 3, "P1": 0, "P2": 5, "P3": 1, "total": 9 }
}
