diff --git a/.planning/STATE.md b/.planning/STATE.md index 6196fab..8f786de 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -9,19 +9,19 @@ See: .planning/PROJECT.md (updated 2026-02-04) ## Current Position -Phase: 20 of 21 (Real-Time Subscriptions) - IN PROGRESS -Plan: 1 of 2 in current phase -Status: Completed 20-01 (SSE Streaming & Subscription Procedures) -Last activity: 2026-02-04 - Completed 20-01-PLAN.md (SSE backend) +Phase: 20 of 21 (Real-Time Subscriptions) - COMPLETE +Plan: 2 of 2 in current phase (all complete) +Status: Completed 20-02 (Frontend SSE Subscription Hooks) +Last activity: 2026-02-04 - Completed 20-02-PLAN.md (frontend subscriptions) Progress: █████████░ 99% ## Performance Metrics **Velocity:** -- Total plans completed: 71 +- Total plans completed: 72 - Average duration: 3 min -- Total execution time: 201 min +- Total execution time: 204 min **By Phase (v1.0):** @@ -229,6 +229,10 @@ Recent decisions affecting current work: - 20-01: tracked() wrapper on each event for client-side reconnection via lastEventId - 20-01: Fallback AbortSignal (new AbortController().signal) when opts.signal is undefined - 20-01: Vite proxy works for SSE without changes (http-proxy streams chunked responses by default) +- 20-02: httpSubscriptionLink (stable export) over unstable_ prefix — both available in @trpc/client v11 +- 20-02: Subscription-driven invalidation (not local state) — simplest approach, reuses existing React Query cache +- 20-02: Silent onError callbacks — pages degrade to manual refresh when backend is not running +- 20-02: No new packages needed — splitLink and httpSubscriptionLink ship with @trpc/client v11 ### Pending Todos @@ -251,5 +255,5 @@ None. ## Session Continuity Last session: 2026-02-04 -Stopped at: Completed 20-01 (SSE Streaming & Subscription Procedures) +Stopped at: Completed 20-02 (Frontend SSE Subscription Hooks) — Phase 20 complete Resume file: None diff --git a/.planning/phases/20-real-time-subscriptions/20-02-SUMMARY.md b/.planning/phases/20-real-time-subscriptions/20-02-SUMMARY.md new file mode 100644 index 0000000..d3acc47 --- /dev/null +++ b/.planning/phases/20-real-time-subscriptions/20-02-SUMMARY.md @@ -0,0 +1,112 @@ +--- +phase: 20-real-time-subscriptions +plan: 02 +subsystem: frontend +tags: [trpc, sse, subscriptions, react-query, live-updates, splitLink] + +requires: + - phase: 20-real-time-subscriptions + plan: 01 + provides: SSE subscription procedures (onEvent, onAgentUpdate, onTaskUpdate) + - phase: 16-frontend-scaffold + provides: tRPC client and React Query setup + +provides: + - splitLink routing subscriptions to httpSubscriptionLink (SSE) + - Live update hooks on all three UI pages (dashboard, detail, inbox) + - Automatic React Query cache invalidation on domain events + +affects: [21-frontend-polish] + +tech-stack: + added: [] + patterns: [splitLink for operation-type routing, subscription-driven cache invalidation] + +key-files: + modified: + - packages/web/src/lib/trpc.ts + - packages/web/src/routes/initiatives/index.tsx + - packages/web/src/routes/initiatives/$id.tsx + - packages/web/src/routes/inbox.tsx + +key-decisions: + - "httpSubscriptionLink (stable export) over unstable_ prefix — both available in @trpc/client v11" + - "Subscription-driven invalidation (not local state) — simplest approach, reuses existing React Query cache" + - "Silent onError callbacks — pages degrade to manual refresh when backend is not running" + - "No new packages needed — splitLink and httpSubscriptionLink ship with @trpc/client v11" + +patterns-established: + - "useSubscription + useUtils().invalidate for live updates on any page" + +duration: 3min +completed: 2026-02-04 +--- + +# Plan 20-02: Frontend SSE Subscription Hooks Summary + +**Wire frontend tRPC client with SSE subscriptions and live update hooks on all three UI pages** + +## Performance + +- **Duration:** 3 min +- **Started:** 2026-02-04 +- **Completed:** 2026-02-04 +- **Tasks:** 2 +- **Files modified:** 4 + +## Accomplishments +- Replaced single httpBatchLink with splitLink routing subscriptions to httpSubscriptionLink (SSE) +- Added onTaskUpdate subscription to dashboard page (invalidates listInitiatives + listPhases) +- Added onTaskUpdate + onAgentUpdate subscriptions to initiative detail page (invalidates phases, tasks, plans, agents) +- Added onAgentUpdate subscription to inbox page (invalidates listWaitingAgents + listMessages) + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Update tRPC client with splitLink for SSE subscriptions** - `eaf3f10` (feat) +2. **Task 2: Add live update hooks to all three UI pages** - `170ac55` (feat) + +## Files Modified +- `packages/web/src/lib/trpc.ts` - splitLink routing subscriptions to httpSubscriptionLink +- `packages/web/src/routes/initiatives/index.tsx` - onTaskUpdate subscription for dashboard +- `packages/web/src/routes/initiatives/$id.tsx` - onTaskUpdate + onAgentUpdate subscriptions for detail +- `packages/web/src/routes/inbox.tsx` - onAgentUpdate subscription for inbox + +## Decisions Made +- 20-02: httpSubscriptionLink (stable export) used over unstable_ prefix variant +- 20-02: Subscription-driven invalidation pattern — no local event state, just invalidate React Query caches +- 20-02: Silent onError callbacks so pages degrade gracefully without backend +- 20-02: No new packages — splitLink and httpSubscriptionLink are core @trpc/client v11 exports + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 3 - Blocking] Duplicate useUtils() declaration in inbox.tsx** +- **Found during:** Task 2 (inbox page) +- **Issue:** Adding `const utils = trpc.useUtils()` for the subscription created a duplicate declaration (already existed lower in the function for mutations) +- **Fix:** Moved the existing `useUtils()` call above the subscription hook and removed the duplicate +- **Files modified:** packages/web/src/routes/inbox.tsx +- **Verification:** `npm run build` succeeds +- **Committed in:** 170ac55 (Task 2 commit) + +--- + +**Total deviations:** 1 auto-fixed (1 blocking) +**Impact on plan:** Trivial reorder of existing code. No scope creep. + +## Issues Encountered +None + +## User Setup Required +None - SSE works over standard HTTP through the existing Vite dev proxy. + +## Next Phase Readiness +- Phase 20 (Real-Time Subscriptions) is now complete +- All three UI pages receive live updates via SSE when domain events fire +- Phase 21 (Frontend Polish) can proceed + +--- +*Phase: 20-real-time-subscriptions* +*Completed: 2026-02-04*