Archive v0.2 (UI Overhaul and Optimization) to milestones/: - milestones/v0.2-ROADMAP.md — full phase archive (Phases 8–11, 33 plans) - milestones/v0.2-REQUIREMENTS.md — all 40 requirements marked complete - milestones/v0.2-MILESTONE-AUDIT.md — audit artifact (passed, 40/40) - MILESTONES.md — new living milestone index - RETROSPECTIVE.md — new living retrospective with v0.2 section - PROJECT.md — full evolution review: v0.2 requirements moved to Validated, 5 new Key Decisions added - STATE.md — updated to milestone-complete status - ROADMAP.md — v0.2 phases collapsed into <details> with progress table updated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.9 KiB
6.9 KiB
DocuVault — Project Retrospective
A living document updated after each milestone. Lessons feed forward into future planning.
Milestone: v0.2 — UI Overhaul and Optimization
Shipped: 2026-06-17 Phases: 4 (8–11) | Plans: 33 | Duration: 10 days (2026-06-07 → 2026-06-17) Git: 198 commits, 236 files changed, +39,557 / −6,288 lines
What Was Built
- Backend monolith decomposition — three router monoliths (934L, 852L, 825L) split into focused sub-packages with zero URL or behavior changes; shared schemas extracted to
api/schemas.py - Frontend client decomposition —
client.js(635L) → 7 domain modules + barrel re-export; 35+ consumer files unchanged - Admin panel rearchitecture — standalone
/admin/*route subtree;AdminLayout.vue;AdminSidebar.vuewith 5 nav links; 5 deep-linkable views;to.matched.some()auth guard fix;GET /api/admin/overviewaggregate endpoint - UX interaction layer —
EmptyState.vue, skeleton loaders, keyboard shortcuts (/,U,N,Escape),OsDragOverlay.vue, Pinia toast store +ToastContainer.vue,BreadcrumbBar.vue, drag-to-move with Teleport dropdowns,AppIcon.vue(66 SVG instances centralized) - Responsive design + visual polish — hamburger sidebar drawer (below
lg), adaptive document list columns, 36px touch targets, scrollable modals,@tailwindcss/formsbaseline, consistent Tailwind-only spacing/typography/focus-visible/hover states - Bundle optimization — all admin routes lazy-loaded; dead code deleted; bundle −81 kB (−30.6%) from baseline
What Worked
- Wave parallelization — executing independent plans in parallel (e.g., CODE-01/02/03/04 in Phase 8 Wave 2) dramatically reduced wall-clock time; the wave structure in PLAN.md made this trivial to execute
- Barrel re-export pattern — decomposing
client.jswith a barrel kept all 35+ consumer files unchanged; zero regressions, zero migration cost - Foundation-then-wire order — building
EmptyState.vue,BreadcrumbBar.vue,AppIcon.vue, and the toast store as isolated components in Phase 10 Wave 0 before wiring them in Wave 1 kept each step reviewable and testable - Teleport for dropdowns — solving viewport-edge clipping with
Teleport to="body"+getBoundingClientRect()was the right call; future virtual scrolling is now unblocked - UAT gap closure plans — having dedicated plans (10-13, 11-07) for UAT gaps rather than patching in-flight kept the execution clean and the gap closure auditable
What Was Inefficient
- Phase 8 progress table not updated — the ROADMAP progress table showed "4/8 In Progress" for Phase 8 even after completion, discovered at milestone close. Progress table updates should be part of the plan execution checklist.
- Admin auth guard bug caught late — the
to.meta.requiresAdmin→to.matched.some()fix is a security-relevant change that wasn't caught until Phase 9. Nested route guards should be explicitly tested in Phase scaffolding. - 11-07 mobile toolbar gap — the mobile compact toolbar fix was a UAT gap rather than planned; the RESP-02 success criterion should have been clearer about the 550px threshold from the start.
- Multiple SUMMARY.md formats — some phase summaries used
**One-liner:**and some used## One-liner; extracting them required heuristic grep patterns. A consistent frontmatter schema would help.
Patterns Established
- Sub-router NO-prefix rule —
APIRouter()in sub-packages must carry noprefix; the parentinclude_router(sub, prefix=...)propagates. This is now in CLAUDE.md. - FastAPI 0.128+ empty-path restriction —
@router.get("")on a sub-router with empty include prefix raisesFastAPIError; root routes must be registered on the parent aggregator directly. to.matched.some()for Vue Router 4 meta inheritance — Vue Router 4 does not propagatemetato children automatically; directto.metachecks are a security regression.- AdminLayout as route component, not App.vue branch — router resolves
AdminLayoutas the/admincomponent; its<router-view>renders children.App.vueneeds no layout branching logic. - Lazy-load all non-critical routes — admin views and other non-initial-path routes should always be lazy-loaded by default; synchronous imports for non-critical routes are a bundle regression.
Key Lessons
- Verify test coverage includes nested route behavior. The
to.matched.some()fix was a security-relevant change that required a specific negative test (non-admin navigating directly to/admin/users). Add nested-route auth tests to the scaffolding checklist for any phase that touches routing. - Write success criteria with explicit thresholds. "Mobile responsive" in RESP-02 should have said "toolbar fits without horizontal scrolling at 375px and 550px" rather than leaving it implicit. Explicit viewport thresholds eliminate UAT guesswork.
- Archive progress table state in the phase summary. The ROADMAP progress table is read by the milestone close process; phases should update it as part of the "plan complete" ritual, not leave it for the orchestrator to discover at close.
- Barrel re-export is the zero-friction decomposition pattern. When splitting a large module, start with the barrel and establish the public API first. Consumer files never change; the decomposition is invisible to callers.
Cost Observations
- Model: Claude Sonnet 4.6 throughout
- No haiku or opus usage in v0.2
- Notable: wave parallelization (3–5 independent plans per wave) was the primary efficiency lever; sequential execution of the same work would have taken ~2–3x longer
Cross-Milestone Trends
Process Evolution
| Milestone | Duration | Phases | Key Process Change |
|---|---|---|---|
| v0.1 | ~16 days (2026-05-21→2026-06-06) | 11 (1–7.4) | Feature-first; security gates added mid-stream |
| v0.2 | 10 days (2026-06-07→2026-06-17) | 4 (8–11) | Quality-first; wave parallelization; milestone audit before close |
Cumulative Quality
| Milestone | Tests at close | Notes |
|---|---|---|
| v0.1 | 347 | 1 pre-existing failure (missing module) |
| v0.2 | 277 | Reduction reflects dead test file deletion; coverage per line improved |
Top Lessons (Verified Across Milestones)
- Security gates must run before phase advance, not as a post-close checklist. Both milestones had late-discovered security issues (v0.1: IDOR stubs, v0.2: auth guard). Bake the security agent into the plan execution ritual.
- Explicit success criteria with measurable thresholds eliminate UAT gaps. Vague criteria ("responsive") always produce UAT gap closure plans. Precise criteria ("at 375px and 550px viewport") do not.
- Milestone audits before archival are worth the overhead. The v0.2 audit caught stale artifacts and the esbuild CVE before the milestone was tagged. Running the audit as a prerequisite rather than a post-mortem saves remediation cost.