diff --git a/.planning/HANDOFF.json b/.planning/HANDOFF.json new file mode 100644 index 0000000..ea6662c --- /dev/null +++ b/.planning/HANDOFF.json @@ -0,0 +1,36 @@ +{ + "version": "1.0", + "timestamp": "2026-06-04T19:28:41.530Z", + "phase": "02", + "phase_name": "calendar-display", + "phase_dir": ".planning/phases/02-calendar-display", + "plan": 1, + "task": 0, + "total_tasks": 5, + "status": "paused", + "stage": "planned-not-executed", + "completed_tasks": [ + {"id": "research", "name": "Phase 2 research (RESEARCH.md) + Nyquist VALIDATION.md", "status": "done", "commit": "a707f8d"}, + {"id": "patterns", "name": "Pattern map (PATTERNS.md) — 23 files, 19 analogs", "status": "done", "commit": "5e14413"}, + {"id": "plans", "name": "5 PLAN.md files in 4 waves; plan-checker PASSED on iteration 2", "status": "done", "commit": "fc4cc2c"}, + {"id": "backlog", "name": "Backlog item 999.1 — treat Fastmail as a calendar provider, support adding more", "status": "done", "commit": "8bd52c6"}, + {"id": "config", "name": "GSD config: adaptive profile, TDD on, per-milestone branching, auto-advance on; saved as global defaults", "status": "done", "commit": "uncommitted"} + ], + "remaining_tasks": [ + {"id": "execute", "name": "Execute Phase 2 — run all 5 plans across 4 waves", "status": "not_started"} + ], + "blockers": [], + "human_actions_pending": [ + {"action": "Wave 2 checkpoint: designate the shared-family calendar via UPDATE calendars SET is_shared=1 WHERE id=", "context": "Plan 02-02 Task 3 is autonomous:false — which calendar is 'shared-family' cannot be derived from data; the broker account exposes multiple calendars", "blocking": true}, + {"action": "Wave 4 checkpoint: visual + functional verification of the 4 success criteria (color coding, 4 views, DST recurrence, all-day no-shift)", "context": "Plan 02-05 Task 3 is autonomous:false — human-verify of the rendered calendar", "blocking": true} + ], + "decisions": [ + {"decision": "Server-side recurrence expansion via ICAL.RecurExpansion with VTIMEZONE registered before expansion", "rationale": "rrule alone needs manual EXDATE handling; VTIMEZONE registration is mandatory or DST events show wrong wall-clock time", "phase": "02"}, + {"decision": "Schedule-X calendarId routed by occ.isShared ? 'shared' : String(occ.ownerUserId), never String(occ.calendarId)", "rationale": "calendars config is keyed by userId; using DB calendar-row id breaks color routing for members owning multiple calendars", "phase": "02"}, + {"decision": "Resolve shared-calendar identity via a calendars.isShared column + operator checkpoint", "rationale": "Cannot derive 'shared' deterministically from Fastmail data; chose explicit marking over fragile displayName matching", "phase": "02"}, + {"decision": "Adopted Adaptive model profile, TDD mode on, per-milestone git branching, auto-advance on; saved as global defaults", "rationale": "User preference set via /gsd-config this session", "phase": "global"} + ], + "uncommitted_files": [".planning/config.json"], + "next_action": "Run /gsd-execute-phase 2 to execute the 5 verified plans. NOTE: auto-advance is now ON — execution may chain stages; interrupt if you want to inspect output between waves.", + "context_notes": "Phase 2 (calendar-display) is fully planned and verified (plan-checker PASSED iteration 2). MVP vertical-slice mode: Wave 1 foundation (schema has_rrule/is_shared + BLOCKING drizzle-kit push + dev-auth bypass + PWA vitest harness + ICS fixtures + RED stubs), Wave 2 backend slice ∥ frontend foundation, Wave 3 first real vertical slice (CalendarShell renders real events, 4 views), Wave 4 UX polish + human verify. Phase 1 already shipped (apps/api + apps/pwa monorepo). TDD was turned on AFTER Phase 2 was planned, so Phase 2 plans do NOT carry TDD gates — only Phase 3+ will. Critical correctness constraints (DST/VTIMEZONE, all-day no-shift, calendarId routing, firstDayOfWeek 0->7, has_rrule pre-filter) are baked into the plans." +} diff --git a/.planning/config.json b/.planning/config.json index 3159ec8..ea34c68 100644 --- a/.planning/config.json +++ b/.planning/config.json @@ -1,5 +1,5 @@ { - "model_profile": "balanced", + "model_profile": "adaptive", "commit_docs": true, "parallelization": true, "search_gitignored": false, @@ -7,7 +7,7 @@ "firecrawl": false, "exa_search": false, "git": { - "branching_strategy": "none", + "branching_strategy": "milestone", "create_tag": true, "phase_branch_template": "gsd/phase-{phase}-{slug}", "milestone_branch_template": "gsd/{milestone}-{slug}", @@ -18,13 +18,13 @@ "plan_check": true, "verifier": true, "nyquist_validation": true, - "auto_advance": false, + "auto_advance": true, "node_repair": true, "node_repair_budget": 2, "ui_phase": true, "ui_safety_gate": true, "ai_integration_phase": true, - "tdd_mode": false, + "tdd_mode": true, "human_verify_mode": "end-of-phase", "text_mode": false, "research_before_questions": false, diff --git a/.planning/phases/02-calendar-display/.continue-here.md b/.planning/phases/02-calendar-display/.continue-here.md new file mode 100644 index 0000000..bc2f96e --- /dev/null +++ b/.planning/phases/02-calendar-display/.continue-here.md @@ -0,0 +1,91 @@ +--- +context: phase +phase: 02-calendar-display +task: 0 +total_tasks: 5 +status: planned-not-executed +last_updated: 2026-06-04T19:28:41.530Z +--- + + +Phase 2 (calendar-display) is **fully planned and verified, not yet executed**. The +plan-checker PASSED on iteration 2 (the initial check found 2 blockers + 3 warnings; +all were fixed). 5 PLAN.md files exist across 4 waves. Phase 1 already shipped a working +pnpm monorepo (apps/api Hono+Drizzle+CalDAV broker, apps/pwa React+Vite). + +The immediate next step is execution: `/gsd-execute-phase 2`. + +One uncommitted file: `.planning/config.json` (this session's settings changes). + + + + +This session: +- Phase 2 RESEARCH.md + Nyquist VALIDATION.md written and committed (a707f8d) +- PATTERNS.md written — 23 files classified, 19 analogs from Phase 1 code (5e14413) +- 5 PLAN.md files created in 4 waves; plan-checker PASSED iteration 2 (fc4cc2c) + - Requirements coverage 3/3 (CAL-02, CAL-03, CAL-07); decision coverage 10/10 +- Backlog item 999.1 added — "treat Fastmail as a calendar provider, support more" (8bd52c6) +- GSD config changed via /gsd-config: Adaptive profile, TDD on, per-milestone branching, + auto-advance on; saved as global defaults (~/.gsd/defaults.json). **config.json uncommitted.** + + + + +- Execute Phase 2 — run all 5 plans across 4 waves: + - Wave 1: 02-01 — schema (has_rrule/is_shared) + **[BLOCKING] drizzle-kit push** + dev-auth + bypass + PWA vitest/jsdom harness + ICS fixtures + RED stubs + - Wave 2: 02-02 (backend: expandOccurrences + windowed /api/events) ∥ 02-03 (frontend + foundation: tokens, colorUtils, calendarConfig, hydrateEvents, Zustand store) — no file overlap + - Wave 3: 02-04 — CalendarShell renders REAL windowed Fastmail events, color-coded, 4 views + - Wave 4: 02-05 — EventDetailPopover + ColorLegend + nav/toolbar + skeleton/empty/error + human verify + + + + +- Server-side recurrence expansion via `ICAL.RecurExpansion`, with VTIMEZONE registered + BEFORE expansion (or DST events render at wrong wall-clock time). +- Schedule-X `calendarId = occ.isShared ? 'shared' : String(occ.ownerUserId)` — NOT + `String(occ.calendarId)`. The calendars config is keyed by userId; using the DB + calendar-row id silently breaks color routing for members owning multiple calendars. +- Shared-family calendar identified via a `calendars.is_shared` column + operator checkpoint + (chosen over fragile displayName matching). +- This-session GSD config: Adaptive profile, TDD on, per-milestone branching, auto-advance on. + + + +- None. Clean pause between plan and execute. + + +## Required Reading (in order) +1. `.planning/phases/02-calendar-display/02-01-PLAN.md` … `02-05-PLAN.md` — the plans to execute +2. `.planning/phases/02-calendar-display/02-RESEARCH.md` — DST/VTIMEZONE, Schedule-X Temporal, + firstDayOfWeek 0→7, has_rrule pre-filter (the landmines) +3. `.planning/phases/02-calendar-display/02-VALIDATION.md` — per-task verification map (Nyquist) +4. `.planning/phases/02-calendar-display/02-PATTERNS.md` — analog files in the Phase 1 codebase + +## Critical Anti-Patterns (do NOT repeat these) +- Do NOT skip the `[BLOCKING] npx drizzle-kit push` task in Wave 1 (02-01). Build/types pass + without it because TS types come from config, not the live DB → false-positive verification. +- Do NOT stamp `String(occ.calendarId)` as the Schedule-X calendarId — use isShared/ownerUserId. +- Do NOT expand recurrences before registering VTIMEZONE; do NOT shift all-day events through + UTC (keep them as 'YYYY-MM-DD' / Temporal.PlainDate). + +## Infrastructure State +- Branch: `main`. git.branching_strategy is now `milestone` — execute may create a milestone branch. +- Phase 1 shipped: apps/api + apps/pwa, MariaDB via docker-compose. No background processes running. +- TDD is ON globally now, but Phase 2 plans were written PRE-TDD — they carry no TDD gates. + Only Phase 3+ will get TDD. (Re-plan Phase 2 if you want TDD gates here.) + + +Everything went smoothly — no failures discovered, no rework beyond the one planned +revision loop. The plans are execution-ready. The only thing a fresh agent must internalize +is the auto-advance + per-milestone branching change made this session, and that TDD won't +retroactively apply to Phase 2's already-written plans. + + + +Start with: `/gsd-execute-phase 2`. Two human checkpoints will pause execution — marking the +shared-family calendar (Wave 2, plan 02-02) and final visual verification of the 4 success +criteria (Wave 4, plan 02-05). Consider committing `.planning/config.json` first. +