Files
Santhosh Janardhanan b8262bbcaf docs(openspec): archive completed changes and sync main specs
Archive three completed changes to archive/:
- api-resource-standard (70 tasks, 14 resource classes)
- capacity-expert-mode (68 tasks, expert mode planning grid)
- enhanced-allocation (62 tasks, planning fidelity + reporting)

Sync all delta specs to main specs/:
- api-resource-standard: API response standardization
- capacity-expert-mode: Expert mode toggle, grid, KPIs, batch API
- resource-allocation: Month execution comparison, bulk, untracked
- untracked-allocation: Null team member support
- allocation-indicators: Variance indicators (red/amber/neutral)
- monthly-budget: Explicit project-month planning

All changes verified and tested (157 tests passing).
2026-03-08 19:13:28 -04:00

7.8 KiB
Raw Permalink Blame History

1. Backend: Batch Availability Endpoint (Phase 1 - Tests RED)

  • 1.1 Write feature test: POST /api/capacity/availability/batch saves multiple updates and returns 200 with saved count
  • 1.2 Write feature test: batch endpoint returns 422 when availability value is not in [0, 0.5, 1]
  • 1.3 Write feature test: batch endpoint returns 422 when team_member_id does not exist
  • 1.4 Write feature test: empty updates array returns 200 with saved count 0
  • 1.5 Write unit test: CapacityService::batchUpsertAvailability() upserts all entries and flushes cache once

2. Backend: Batch Availability Endpoint (Phase 2 - Implement GREEN)

  • 2.1 Add batchUpsertAvailability(array $updates, string $month): int to CapacityService — upserts all rows, flushes month-level cache once after all upserts
  • 2.2 Add batchUpdateAvailability(Request $request): JsonResponse to CapacityController — validate month + updates array, call service, return { data: { saved, month } }
  • 2.3 Add route: POST /api/capacity/availability/batch in routes/api.php
  • 2.4 Run pint and all backend tests — confirm all pass

3. Backend: Batch Availability Endpoint (Phase 3 - Refactor & Document)

  • 3.1 Add Scribe docblock to batchUpdateAvailability() with request/response examples
  • 3.2 Confirm no N+1 queries in batch upsert (cache flush is single, queries are acceptable for batch size)

4. Frontend: Expert Mode Toggle (Phase 1 - Tests RED)

  • 4.1 Write unit test: expertMode store reads from localStorage key headroom.capacity.expertMode, defaults to false
  • 4.2 Write unit test: toggling expertMode persists new value to localStorage
  • 4.3 Write component test: Expert Mode toggle renders right-aligned on tabs row
  • 4.4 Write component test: toggle reflects current expertMode store value
  • 4.5 Write component test: switching mode with dirty cells shows confirmation dialog

5. Frontend: Expert Mode Toggle (Phase 2 - Implement GREEN)

  • 5.1 Create frontend/src/lib/stores/expertMode.ts — writable store backed by localStorage key headroom.capacity.expertMode, default false
  • 5.2 Add Expert Mode toggle (label + DaisyUI toggle switch) to capacity/+page.svelte, right-aligned on tabs row
  • 5.3 Wire toggle to expertModeStore — on change, persist to localStorage
  • 5.4 When toggling off with dirty cells: show confirm dialog; discard changes on confirm, cancel toggle on dismiss
  • 5.5 Run type-check and unit tests — confirm all pass

6. Frontend: Expert Mode Grid Component (Phase 1 - Tests RED)

  • 6.1 Write component test: CapacityExpertGrid renders a row per active team member
  • 6.2 Write component test: CapacityExpertGrid renders a column per day of the month
  • 6.3 Write unit test: token normalization — H{ rawToken: "H", numericValue: 0, valid: true }
  • 6.4 Write unit test: token normalization — O{ rawToken: "O", numericValue: 0, valid: true }
  • 6.5 Write unit test: token normalization — .5{ rawToken: "0.5", numericValue: 0.5, valid: true }
  • 6.6 Write unit test: token normalization — 0.5{ rawToken: "0.5", numericValue: 0.5, valid: true }
  • 6.7 Write unit test: token normalization — 1{ rawToken: "1", numericValue: 1, valid: true }
  • 6.8 Write unit test: token normalization — 0{ rawToken: "0", numericValue: 0, valid: true }
  • 6.9 Write unit test: token normalization — 2{ rawToken: "2", numericValue: null, valid: false }
  • 6.10 Write unit test: auto-render — 0 on weekend column → rawToken becomes O
  • 6.11 Write unit test: auto-render — 0 on holiday column → rawToken becomes H
  • 6.12 Write component test: invalid cell shows red border on blur
  • 6.13 Write component test: Submit button disabled when any invalid cell exists
  • 6.14 Write component test: Submit button disabled when no dirty cells exist

7. Frontend: Expert Mode Grid Component (Phase 2 - Implement GREEN)

  • 7.1 Create frontend/src/lib/utils/expertModeTokens.ts — export normalizeToken(raw, isWeekend, isHoliday) returning { rawToken, numericValue, valid }
  • 7.2 Create frontend/src/lib/components/capacity/CapacityExpertGrid.svelte:
    • Props: month, teamMembers, holidays
    • On mount: fetch all members' individual capacity in parallel
    • Render grid: members × days, cells as <input> elements
    • On blur: run normalizeToken, apply auto-render rule, mark dirty
    • Invalid cell: red border
    • Emit dirty and valid state to parent
  • 7.3 Wire capacity/+page.svelte: when Expert Mode on, render CapacityExpertGrid instead of calendar tab content
  • 7.4 Add batchUpdateAvailability(month, updates) to frontend/src/lib/api/capacity.ts
  • 7.5 Add Submit button to Expert Mode view — disabled when !hasDirty || !allValid; on click, call batch API, show success/error toast
  • 7.6 Run type-check and component tests — confirm all pass

8. Frontend: Live KPI Bar (Phase 1 - Tests RED)

  • 8.1 Write unit test: KPI bar capacity = sum of all members' numeric cell values / 1 (person-days)
  • 8.2 Write unit test: KPI bar revenue = sum(member person-days × hourly_rate × 8)
  • 8.3 Write unit test: invalid cells contribute 0 to KPI totals (not null/NaN)
  • 8.4 Write component test: KPI bar updates when a cell value changes

9. Frontend: Live KPI Bar (Phase 2 - Implement GREEN)

  • 9.1 Create frontend/src/lib/components/capacity/ExpertModeKpiBar.svelte (integrated into CapacityExpertGrid)
    • Props: gridState (reactive cell map), teamMembers (with hourly_rate)
    • Derived: totalPersonDays, projectedRevenue
    • Render: two stat cards (Capacity in person-days, Projected Revenue)
  • 9.2 Mount ExpertModeKpiBar above the grid in Expert Mode view
  • 9.3 Confirm KPI bar reactively updates on every cell change without API call
  • 9.4 Run type-check and component tests — confirm all pass

10. Frontend: Expert Mode Grid (Phase 3 - Refactor)

  • 10.1 Extract cell rendering into a ExpertModeCell.svelte sub-component if grid component exceeds ~150 lines (skipped - optional refactor, grid at 243 lines is acceptable)
  • 10.2 Add horizontal scroll container for wide grids (months with 2831 days)
  • 10.3 Ensure weekend columns have muted background, holiday columns have distinct header marker
  • 10.4 Verify toggle is hidden on mobile (< md breakpoint) using Tailwind responsive classes

11. E2E Tests

  • 11.1 Write E2E test: Expert Mode toggle appears on Capacity page and persists after reload
  • 11.2 Write E2E test: grid renders all team members as rows for selected month
  • 11.3 Write E2E test: typing invalid token shows red cell and disables Submit
  • 11.4 Write E2E test: typing valid tokens and clicking Submit saves and shows success toast
  • 11.5 Write E2E test: KPI bar updates when cell value changes
  • 11.6 Write E2E test: switching off Expert Mode with dirty cells shows confirmation dialog

12. Timezone & Accessibility Fixes

  • 12.1 Fix weekend detection: use new Date(dateStr + 'T00:00:00') to avoid local timezone drift
  • 12.2 Update weekend styling: use bg-base-300 solid background + border-base-400 for accessibility
  • 12.3 Update holiday styling: use bg-warning/40 + border-warning with bold H marker
  • 12.4 Prefill weekend cells with O on grid load (not 1)
  • 12.5 Prefill holiday cells with H on grid load (not 1)
  • 12.6 Add backend timezone helper using America/New_York for weekend/holiday checks
  • 12.7 Ensure backend seeds weekends with availability: 0 (to match frontend O)
  • 12.8 Ensure backend seeds holidays with availability: 0 (to match frontend H)
  • 12.9 Run all tests and verify weekend shading aligns correctly for April 2026 (4th/5th = Sat/Sun)