---
phase: 21-polish-integration
plan: 02
type: execute
wave: 1
depends_on: []
files_modified: [packages/web/src/components/Skeleton.tsx, packages/web/src/components/InitiativeList.tsx, packages/web/src/components/InboxList.tsx, packages/web/src/routes/initiatives/$id.tsx]
autonomous: true
---

<objective>
Replace plain-text "Loading..." messages with skeleton loading states across all three screens.

Purpose: Every page currently shows bare "Loading initiatives..." / "Loading inbox..." text. Skeleton placeholders communicate structure and reduce perceived latency. This is purely visual polish — no data-fetching changes.
Output: Skeleton component and skeleton loading states on dashboard, detail, and inbox pages.
</objective>

<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md

@packages/web/src/components/InitiativeList.tsx
@packages/web/src/components/InboxList.tsx
@packages/web/src/routes/initiatives/$id.tsx
@packages/web/src/routes/inbox.tsx
</context>

<tasks>

<task type="auto">
  <name>Task 1: Create Skeleton component and apply to dashboard + inbox list views</name>
  <files>packages/web/src/components/Skeleton.tsx, packages/web/src/components/InitiativeList.tsx, packages/web/src/components/InboxList.tsx</files>
  <action>
  1. Create `packages/web/src/components/Skeleton.tsx` — a simple animated placeholder component. Props: `className?: string`. Renders a `<div>` with classes `animate-pulse rounded-md bg-muted`. The className prop is merged via `cn()` so callers can set width/height. Export as named export.

  2. In `InitiativeList.tsx`: Replace the "Loading initiatives..." text block with 3 skeleton cards. Each skeleton card should match the InitiativeCard layout shape: a Card with a skeleton title bar (h-5 w-48), skeleton status badge (h-5 w-16), skeleton progress bar (h-2 w-full), and skeleton phase count (h-4 w-24). Wrap in a `<div className="space-y-3">` to match the existing card list spacing. Use `Array.from({ length: 3 })` to render three.

  3. In `InboxList.tsx`: Replace the "Loading inbox..." text block with 4 skeleton message rows. Each row: a skeleton circle (h-3 w-3 rounded-full), skeleton name (h-4 w-32), skeleton preview (h-3 w-full), skeleton time (h-3 w-16). Match the MessageCard layout. Use `Array.from({ length: 4 })`.
  </action>
  <verify>
  - `npx tsc --noEmit -p packages/web/tsconfig.app.json` passes
  - `npm run --workspace=packages/web build` succeeds
  </verify>
  <done>Dashboard and inbox show skeleton placeholders instead of text during loading.</done>
</task>

<task type="auto">
  <name>Task 2: Add skeleton loading states to initiative detail page</name>
  <files>packages/web/src/routes/initiatives/$id.tsx</files>
  <action>
  1. Replace the "Loading initiative..." text in InitiativeDetailPage with a skeleton layout that matches the page structure:
     - Header skeleton: back arrow placeholder (h-4 w-4), title bar (h-7 w-64), status badge (h-5 w-20)
     - Two-column grid matching `grid-cols-1 lg:grid-cols-[1fr_340px]`:
       - Left: 2 skeleton phase accordions (each: h-12 w-full border rounded)
       - Right: skeleton ProgressPanel (h-24 w-full), skeleton DecisionList (h-20 w-full)

  2. Replace "Loading phases..." text (inside the phases section) with 3 skeleton phase accordion bars (h-10 w-full with animate-pulse, spaced with gap-1).

  Keep the existing error state as-is (it already has proper UI).
  </action>
  <verify>
  - `npx tsc --noEmit -p packages/web/tsconfig.app.json` passes
  - `npm run --workspace=packages/web build` succeeds
  </verify>
  <done>Detail page shows structured skeleton layout during all loading states.</done>
</task>

</tasks>

<verification>
Before declaring plan complete:
- [ ] `npx tsc --noEmit -p packages/web/tsconfig.app.json` passes
- [ ] `npm run --workspace=packages/web build` succeeds
- [ ] No "Loading..." plain text remains in InitiativeList, InboxList, or $id.tsx loading paths
- [ ] Skeleton component exported and used consistently
</verification>

<success_criteria>

- All tasks completed
- All verification checks pass
- All three screens use skeleton loading states
- Skeleton component is reusable
  </success_criteria>

<output>
After completion, create `.planning/phases/21-polish-integration/21-02-SUMMARY.md`
</output>
