All checks were successful
Deploy / deploy (push) Successful in 1m39s
New tests: - Yellow warning banner when token expires in 10 days (warning level) - Red critical banner when token expires in 5 days (critical level) - Expired token state shows token input for re-entry - Connection persists after page reload - Can reconnect after disconnecting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
6.5 KiB
6.5 KiB
PhaseFlow Implementation Plan
This file is maintained by Ralph. Run ./ralph-sandbox.sh plan 3 to generate tasks.
Current Status: Feature Complete
Test Coverage: 1014 unit tests (51 files) + 170 E2E tests (12 files) = 1184 total tests
All P0-P5 items are complete. The project is feature complete.
Architecture Summary
Tech Stack
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router) |
| Runtime | Node.js 24 |
| Database | PocketBase |
| Validation | Zod |
| Testing | Vitest + jsdom + Playwright |
| Linting | Biome |
Critical Business Rules
- Override Priority: flare > stress > sleep > pms (enforced in order)
- HRV Unbalanced: ALWAYS forces REST (highest algorithmic priority, non-overridable)
- Phase Limits: Strictly enforced per phase configuration
- Token Expiration Warnings: Email at 14 days and 7 days before expiry
- ICS Feed: Generates 90 days of phase events for calendar subscription
Completed Implementation
Library Files (12 files, 250+ tests)
| File | Tests | Key Functions |
|---|---|---|
cycle.ts |
22 | getCycleDay, getPhase, getPhaseConfig, dynamic phase boundaries |
nutrition.ts |
17 | getNutritionGuidance, getSeedSwitchAlert, phase-specific guidance |
email.ts |
32 | sendDailyEmail, sendPeriodConfirmationEmail, sendTokenExpirationWarning |
ics.ts |
33 | generateIcsFeed, 90-day events, period prediction feedback, CATEGORIES |
encryption.ts |
14 | AES-256-GCM encrypt/decrypt |
decision-engine.ts |
24 | getTrainingDecision, getDecisionWithOverrides, 8 priority rules |
garmin.ts |
33 | fetchHrvStatus, fetchBodyBattery, fetchIntensityMinutes, token validation |
pocketbase.ts |
10 | createPocketBaseClient, isAuthenticated, getCurrentUser, loadAuthFromCookies |
auth-middleware.ts |
12 | withAuth() wrapper, structured logging, IP logging |
middleware.ts |
12 | Next.js page protection, redirects |
logger.ts |
16 | Pino JSON output, log levels, child loggers |
metrics.ts |
33 | Prometheus metrics, counters, gauges, histograms |
API Routes (21 endpoints, 350+ tests)
| Route | Tests | Purpose |
|---|---|---|
| POST /api/auth/logout | 5 | Session logout |
| GET /api/user | 4 | User profile |
| PATCH /api/user | 17 | Update preferences |
| POST /api/cycle/period | 13 | Log period start with prediction tracking |
| GET /api/cycle/current | 10 | Current cycle state |
| GET /api/today | 24 | Daily snapshot with decision |
| POST/DELETE /api/overrides | 14 | Override management |
| POST/DELETE /api/garmin/tokens | 15 | Token storage |
| GET /api/garmin/status | 11 | Connection status |
| POST /api/cron/garmin-sync | 32 | Daily data sync |
| POST /api/cron/notifications | 20 | Email notifications |
| GET /api/calendar/[userId]/[token].ics | 11 | ICS feed |
| POST /api/calendar/regenerate-token | 9 | Token regeneration |
| GET /api/history | 19 | Daily log history |
| GET /api/period-history | 18 | Period log history |
| PATCH/DELETE /api/period-logs/[id] | 16 | Period log management |
| GET /api/health | 14 | Health check |
| GET /metrics | 15 | Prometheus metrics |
Pages (8 pages, 230+ tests)
| Page | Tests | Features |
|---|---|---|
Dashboard (/) |
28 | Decision card, data panel, nutrition, overrides, mini calendar |
Login (/login) |
32 | OIDC + email/password, rate limiting |
Settings (/settings) |
34 | Preferences, logout |
| Settings/Garmin | 27 | Token management, status |
Calendar (/calendar) |
23 | Month view, ICS subscription |
History (/history) |
26 | Daily log table |
| Period History | 27 | Period log table, edit/delete |
Plan (/plan) |
16 | Phase overview, training reference |
Components (10 components, 200+ tests)
| Component | Tests | Purpose |
|---|---|---|
| DecisionCard | 19 | Status display with color coding |
| DataPanel | 29 | Biometrics display, HRV color coding, progress bar |
| NutritionPanel | 16 | Seeds, carbs, keto guidance |
| OverrideToggles | 18 | Override buttons |
| DayCell | 32 | Calendar day with phase colors, period indicator |
| MiniCalendar | 23 | Dashboard calendar widget |
| OnboardingBanner | 16 | Setup prompts |
| MonthView | 31 | Full calendar with navigation, keyboard nav |
| PeriodDateModal | 22 | Period input modal |
| Skeletons | 29 | Loading states with shimmer |
E2E Tests (12 files, 165 tests)
| File | Tests | Coverage |
|---|---|---|
| smoke.spec.ts | 3 | Basic app functionality |
| auth.spec.ts | 14 | Login, protected routes |
| dashboard.spec.ts | 24 | Dashboard display, overrides |
| settings.spec.ts | 15 | Settings form, validation |
| garmin.spec.ts | 12 | Garmin connection, expiry warnings |
| period-logging.spec.ts | 14 | Period history, logging |
| calendar.spec.ts | 21 | Calendar view, ICS feed |
| decision-engine.spec.ts | 8 | Decision priority chain |
| cycle.spec.ts | 11 | Cycle tracking |
| history.spec.ts | 7 | History page |
| plan.spec.ts | 7 | Plan page |
| health.spec.ts | 3 | Health/observability |
E2E Test Enhancement Opportunities
These are optional enhancements to improve E2E coverage. Not required for feature completeness.
New Test Files (Lower Priority)
| File | Tests | Description |
|---|---|---|
| notifications.spec.ts | 3 | Notification preferences |
| dark-mode.spec.ts | 2 | System preference detection |
| mobile.spec.ts | 4 | Mobile viewport behavior |
Existing File Extensions
| File | Additional Tests | Focus Area |
|---|---|---|
| auth.spec.ts | +6 | OIDC flow, session persistence |
| period-logging.spec.ts | +5 | Future dates, dashboard updates |
| calendar.spec.ts | +13 | ICS content validation, responsive |
| settings.spec.ts | +6 | Persistence, timezone changes |
| garmin.spec.ts | +4 | Token refresh, network error recovery |
Notes
- TDD Approach: Write failing tests first, then implement
- Auth First: P0 items unlock all other work
- No Mock Mode: Use real data and APIs only
- ABOUTME Comments: All files start with 2-line ABOUTME
- Commit Format: Descriptive message + Claude footer
- Never use --no-verify: All commits go through pre-commit hooks
Revision History
- 2026-01-13: Added 5 Garmin E2E tests (expiry warnings, expired state, persistence, reconnection)
- 2026-01-13: Condensed plan after feature completion (reduced from 1514 to ~170 lines)
- 2026-01-12: Fixed spec gaps (email format, HRV colors, progress bar, emojis)
- 2026-01-11: Completed P5.1-P5.4 (period history, toast, CI, E2E)