docs(18): create initiative detail phase plan

Phase 18: Initiative Detail
- 4 plans in 2 waves
- 3 parallel (wave 1), 1 sequential (wave 2)
- Ready for execution
This commit is contained in:
Lukas May
2026-02-04 21:28:33 +01:00
parent cbf0ed28cb
commit 305809f0b2
4 changed files with 568 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
---
phase: 18-initiative-detail
plan: 04
type: execute
wave: 2
depends_on: ["18-01", "18-02", "18-03"]
files_modified:
- packages/web/src/routes/initiatives/$id.tsx
autonomous: true
---
<objective>
Assemble the Initiative Detail page by wiring all Phase 18 components into the $id.tsx route with tRPC data fetching, queue actions, and build verification.
Purpose: Replace the placeholder detail page with a fully functional initiative detail view that fetches data from the backend, renders the phase/task hierarchy, and provides queue action buttons.
Output: Working Initiative Detail page matching the wireframe specification.
</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
# Prior plan summaries — need to know what components were created
@.planning/phases/18-initiative-detail/18-01-SUMMARY.md
@.planning/phases/18-initiative-detail/18-02-SUMMARY.md
@.planning/phases/18-initiative-detail/18-03-SUMMARY.md
# Wireframe spec
@docs/wireframes/initiative-detail.md
# Existing page pattern to follow
@packages/web/src/routes/initiatives/index.tsx
# Components created in plans 01-03
@packages/web/src/components/InitiativeHeader.tsx
@packages/web/src/components/ProgressPanel.tsx
@packages/web/src/components/PhaseAccordion.tsx
@packages/web/src/components/TaskRow.tsx
@packages/web/src/components/DependencyIndicator.tsx
@packages/web/src/components/DecisionList.tsx
@packages/web/src/components/TaskDetailModal.tsx
# tRPC client and types
@packages/web/src/lib/trpc.ts
@packages/shared/src/types.ts
# tRPC router — need exact procedure signatures
@src/trpc/router.ts
</context>
<tasks>
<task type="auto">
<name>Task 1: Wire Initiative Detail page with data fetching and all components</name>
<files>packages/web/src/routes/initiatives/$id.tsx</files>
<action>
Replace the placeholder content with the full initiative detail page.
**Data fetching strategy:**
The page needs to assemble a nested data structure (initiative → phases → tasks) from multiple tRPC calls. Use React Query's `useQuery` hooks with proper `enabled` chaining.
1. `trpc.getInitiative.useQuery({ id })` — fetch initiative by route param `$id`
2. `trpc.listPhases.useQuery({ initiativeId: id })` — fetch all phases
3. For each phase, fetch plans: `trpc.listPlans.useQuery({ phaseId })` — but since hooks can't be called conditionally, use a pattern where the page fetches all plans for all phases. Use `trpc.useQueries()` if available, or fetch plans in a child component.
**Recommended approach for nested fetching:**
Create a helper component `PhaseWithTasks` that:
- Receives a phase
- Calls `trpc.listPlans.useQuery({ phaseId: phase.id })` to get plans
- For each plan, calls `trpc.listTasks.useQuery({ planId: plan.id })` to get tasks
- Flattens all tasks from all plans into a single array (hiding the Plan layer per decision 15-02)
- Calls `trpc.getPhaseDependencies.useQuery({ phaseId: phase.id })` for phase-level deps
- Renders PhaseAccordion with the assembled task data
This avoids the conditional hooks problem — each `PhaseWithTasks` instance has a stable hook call count.
**Page layout (matching wireframe):**
```
InitiativeHeader (back button, name, status, dates)
Two-column layout on desktop (grid-cols-1 lg:grid-cols-[1fr_340px]):
Left: PHASES section with PhaseWithTasks for each phase
Right: ProgressPanel + DecisionList (stacked)
TaskDetailModal (controlled by selectedTask state)
```
**State management:**
- `selectedTask`: `string | null` — ID of task with open modal
- For the modal, when a task is selected, look it up from the fetched data
**Back button:**
Use `useNavigate` from TanStack Router to navigate to `/initiatives`.
**Queue actions:**
- "Queue All" button in the PHASES section header — calls `trpc.queuePhase.useMutation()` for each pending phase (disabled if no pending phases)
- In TaskDetailModal, "Queue Task" calls `trpc.queueTask.useMutation()` with task ID
- After successful queue mutation, invalidate relevant queries
**Loading/error states:**
- Show skeleton/spinner while initiative loads (follow InitiativeList pattern)
- Show "Initiative not found" if getInitiative returns 404/error
- Individual PhaseWithTasks components show their own loading states
**DecisionList:**
Pass empty array for decisions: `decisions={[]}` — no backend endpoint exists yet.
**Progress calculation:**
Compute from phases data:
- `phasesComplete`: count phases with status 'completed'
- `phasesTotal`: phases.length
- `tasksComplete/tasksTotal`: sum across all PhaseWithTasks (or compute at page level by fetching all)
Since task counts require fetching all tasks (which happens in PhaseWithTasks children), lift the counts up via a callback or compute from the phase-level data. Simplest approach: use the phase statuses for the progress panel and skip exact task counts initially. Or pass task count via a state aggregation pattern.
Pragmatic approach: ProgressPanel shows phase-level progress only (`phasesComplete/phasesTotal`). Task counts show as "—" until the phase components have loaded their tasks. This avoids overcomplicating the initial implementation. If you find a clean way to aggregate task counts, do it, but don't over-engineer.
</action>
<verify>npx tsc --noEmit -p packages/web/tsconfig.app.json passes AND npx vite build in packages/web succeeds</verify>
<done>Initiative Detail page renders with header, progress, decisions placeholder, phase accordion with tasks, and task detail modal. Build passes.</done>
</task>
<task type="auto">
<name>Task 2: Verify full build and integration</name>
<files>packages/web/src/routes/initiatives/$id.tsx</files>
<action>
Run full verification:
1. `npx tsc --noEmit -p packages/web/tsconfig.app.json` — TypeScript check
2. `npx vite build` in packages/web — production build
3. `npm run build` in root — backend build (ensure no regressions)
4. Verify the route is accessible by checking routeTree.gen.ts includes the $id route
Fix any TypeScript errors or build failures discovered.
No new code unless fixing build issues.
</action>
<verify>All three build commands pass with zero errors</verify>
<done>Full project builds cleanly. Initiative detail page compiles and bundles correctly.</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] `npx tsc --noEmit -p packages/web/tsconfig.app.json` passes
- [ ] `npx vite build` in packages/web succeeds
- [ ] `npm run build` in root succeeds
- [ ] Navigating from dashboard card to /initiatives/$id renders the detail page
- [ ] Phase accordion expand/collapse works
- [ ] Task detail modal opens on task click
</verification>
<success_criteria>
- Initiative Detail page replaces placeholder with full implementation
- Data fetched from backend via tRPC (getInitiative, listPhases, listPlans, listTasks)
- Phase hierarchy renders with expand/collapse
- Task detail modal functional
- Queue actions wired to tRPC mutations
- All builds pass
</success_criteria>
<output>
After completion, create `.planning/phases/18-initiative-detail/18-04-SUMMARY.md`
</output>