|
2 | 2 |
|
3 | 3 | *A living document updated after each milestone. Lessons feed forward into future planning.* |
4 | 4 |
|
| 5 | +## Milestone: v3.2 — UX Improvements and Monthly Updates |
| 6 | + |
| 7 | +**Shipped:** 2026-05-19 |
| 8 | +**Phases:** 4 (31–34) | **Plans:** 14 | **Timeline:** 7 days (2026-05-10 → 2026-05-17) | **Commits:** 96 |
| 9 | + |
| 10 | +### What Was Built |
| 11 | + |
| 12 | +- `vendor-guard.yml` + `scripts/sync_vendored.py` — automated CI drift detection for vendored gps2asp mirror; 27-test TDD suite; strings.json byte-sync |
| 13 | +- Three-tier date-aware sensor format ("⚠ Today, H:MM AM" / "Tomorrow, H:MM AM" / "Weekday (M/D), H:MM AM"); HA-local timezone Today gate; `now_ha_local()` helper |
| 14 | +- `index_io.py` + three new HA entities — download-from-GitHub-releases, atomic dir swap, zip-slip refusal, `asyncio.Lock` concurrency guard, `SpatialIndex.reset()` |
| 15 | +- `caldav_sync.py` — pure async CalDAV glue (SHA-256 UID, VEVENT build, validate/list/write/delete); coordinator suspension choke-point; Store-persisted UID; `async_remove_entry` cleanup; credentials redacted from diagnostics |
| 16 | + |
| 17 | +### What Worked |
| 18 | + |
| 19 | +- **CI guard shipped first (Phase 31)** — all subsequent phases inherited vendored-mirror protection automatically; zero drift incidents in Phases 32-34 |
| 20 | +- **now_ha_local() extracted early** — Phase 32 introduced the helper; Phase 34 reused it without duplication; forward-planned dependencies paid off |
| 21 | +- **Suspension choke-point refactor (Phase 34)** — consolidating 6 scattered suspension-mutation sites into one method (`_async_apply_suspension_state`) eliminated Pitfall 8 entirely; clean and testable |
| 22 | +- **SHA-256 deterministic UID** — decided before any code was written; persists correctly across restarts without storing state in options (which would trigger reload) |
| 23 | + |
| 24 | +### What Was Inefficient |
| 25 | + |
| 26 | +- **ROADMAP.md and STATE.md not updated after Phase 34 execution** — milestone was marked "shipped" in STATE.md but internal position and CALDAV requirements were left stale; forensic audit at milestone close caught it |
| 27 | +- **Phase 33 live-HA UAT deferred again** — same pattern as Phase 25 (Phase 22 before that); human UAT requiring a live HA instance continues to be deferred rather than integrated |
| 28 | +- **HANDOFF.json from Phase 17 was never cleaned up** — orphaned for 7+ weeks across two milestone closings; forensic audit finally surfaced it |
| 29 | + |
| 30 | +### Patterns Established |
| 31 | + |
| 32 | +- CI guard ships first in a milestone — protects all subsequent phases automatically |
| 33 | +- Suspension choke-point pattern — single method owns all suspension-state mutation; never scatter suspension writes |
| 34 | +- `Store` for cross-restart UID persistence — `entry.options` triggers reload; `hass.data` is lost on restart; `Store` is the right tool |
| 35 | +- `caldav_sync.py` as HA-specific glue NOT mirrored — CalDAV is integration-only; keep the CI guard clean by not adding exception lists |
| 36 | + |
| 37 | +### Key Lessons |
| 38 | + |
| 39 | +1. **Update tracking files at execution time, not at milestone close** — Phase 34's ROADMAP.md progress row and CALDAV-* requirements checkboxes were left stale for days; update the row in ROADMAP.md when you write the SUMMARY |
| 40 | +2. **Clean up HANDOFF.json at the end of every session** — if work was paused and then resumed from a different entry point, delete the old handoff immediately |
| 41 | +3. **Schedule live-HA UAT as a concrete calendar item** — three milestones running, live-HA scenarios keep being deferred; it won't happen unless it's explicitly scheduled |
| 42 | +4. **forensic --forensic catches what yolo mode skips** — the forensic progress check found 4 issues that would have been invisible in a standard progress check |
| 43 | + |
| 44 | +### Cost Observations |
| 45 | + |
| 46 | +- Model mix: claude-sonnet-4-6 throughout (switched from opus to reduce cost) |
| 47 | +- Sessions: ~8 distinct execution sessions over 7 days |
| 48 | +- Notable: 96 commits in 7 days — highest commit velocity of any milestone; indicates tight TDD discipline (RED/GREEN/commit rhythm) |
| 49 | + |
| 50 | +--- |
| 51 | + |
5 | 52 | ## Milestone: v3.0 — Suspension Handling |
6 | 53 |
|
7 | 54 | **Shipped:** 2026-04-30 |
|
0 commit comments