|
| 1 | +# Project Retrospective |
| 2 | + |
| 3 | +*A living document updated after each milestone. Lessons feed forward into future planning.* |
| 4 | + |
| 5 | +## Milestone: v1.0 — StravaMCP Go Rewrite |
| 6 | + |
| 7 | +**Shipped:** 2026-04-01 |
| 8 | +**Phases:** 3 | **Plans:** 8 |
| 9 | + |
| 10 | +### What Was Built |
| 11 | +- Complete Go rewrite of Strava MCP server with 11 tools across 5 categories |
| 12 | +- OAuth browser flow with singleflight token refresh and file-based token store |
| 13 | +- goreleaser v2 cross-platform release pipeline with Homebrew cask distribution |
| 14 | +- Portfolio-quality README with 8 badges, Mermaid architecture diagrams, 11-tool reference |
| 15 | +- GitHub Actions release workflow triggered on v* tags |
| 16 | + |
| 17 | +### What Worked |
| 18 | +- Strict 3-phase dependency chain (infra → tools → polish) prevented rework |
| 19 | +- Raw JSON pass-through for Strava data avoided schema coupling and maintenance burden |
| 20 | +- Handler closure pattern (HandleXxx(client) returns ToolHandlerFunc) made tool registration clean and testable |
| 21 | +- Map-based PUT body for update_activity avoided Go zero-value overwrite trap |
| 22 | +- singleflight.Group for token refresh coalescing was elegant and correct |
| 23 | + |
| 24 | +### What Was Inefficient |
| 25 | +- Phase 3 plan 03-01 (module path migration) required touching all 22 Go files for import path changes — could have been the module path from the start in Phase 1 |
| 26 | +- VHS terminal recording requires live OAuth which blocks automated execution — deferred to manual step |
| 27 | + |
| 28 | +### Patterns Established |
| 29 | +- stderr-only logging via slog (stdout reserved for MCP JSON-RPC) |
| 30 | +- Closure-over-client handler pattern for all MCP tools |
| 31 | +- FormatResponse/HandleToolError shared helpers for consistent tool output |
| 32 | +- Atomic write-then-rename for file-based token persistence |
| 33 | +- Tag-triggered releases via goreleaser + GitHub Actions |
| 34 | + |
| 35 | +### Key Lessons |
| 36 | +1. Set the correct Go module path from day one — migrating later touches every file |
| 37 | +2. goreleaser v2 homebrew_casks requires a separate PAT for cross-repo tap push — GITHUB_TOKEN is scoped to current repo only |
| 38 | +3. Raw JSON pass-through is the right default for API wrapper tools — Go structs add maintenance without value when the LLM consumes the JSON directly |
| 39 | + |
| 40 | +### Cost Observations |
| 41 | +- Model mix: primarily opus for execution, sonnet for verification |
| 42 | +- 3 phases completed across multiple sessions |
| 43 | +- Notable: parallel wave execution (plans 03-02 + 03-03) saved time in the final phase |
| 44 | + |
| 45 | +--- |
| 46 | + |
| 47 | +## Cross-Milestone Trends |
| 48 | + |
| 49 | +### Process Evolution |
| 50 | + |
| 51 | +| Milestone | Phases | Plans | Key Change | |
| 52 | +|-----------|--------|-------|------------| |
| 53 | +| v1.0 | 3 | 8 | Initial milestone — established GSD workflow with strict phase dependencies | |
| 54 | + |
| 55 | +### Cumulative Quality |
| 56 | + |
| 57 | +| Milestone | Tests | Packages | Zero-Dep Additions | |
| 58 | +|-----------|-------|----------|-------------------| |
| 59 | +| v1.0 | 80+ | 5 | 3 (mcp-go, browser, sync) | |
| 60 | + |
| 61 | +### Top Lessons (Verified Across Milestones) |
| 62 | + |
| 63 | +1. Set canonical identifiers (module paths, package names) in the first phase |
| 64 | +2. Raw JSON pass-through beats typed structs for API wrapper tools consumed by LLMs |
0 commit comments