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>
81 lines
6.9 KiB
Markdown
81 lines
6.9 KiB
Markdown
# 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.vue` with 5 nav links; 5 deep-linkable views; `to.matched.some()` auth guard fix; `GET /api/admin/overview` aggregate 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/forms` baseline, 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.js` with 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 no `prefix`; the parent `include_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 raises `FastAPIError`; root routes must be registered on the parent aggregator directly.
|
||
- **`to.matched.some()` for Vue Router 4 meta inheritance** — Vue Router 4 does not propagate `meta` to children automatically; direct `to.meta` checks are a security regression.
|
||
- **AdminLayout as route component, not App.vue branch** — router resolves `AdminLayout` as the `/admin` component; its `<router-view>` renders children. `App.vue` needs 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
|
||
|
||
1. **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.
|
||
2. **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.
|
||
3. **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.
|
||
4. **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)
|
||
|
||
1. **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.
|
||
2. **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.
|
||
3. **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.
|