V1 Web PWA · Surface walkthrough

Arete Progress Maps Workspace

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
8sections4 minread

On this page

Context. surface customer · domain arete · route /domains/arete/progress · auth signed-in · source apps/oshun/web/src/app/domains/arete/progress/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md

Purpose#

Internal /domains/arete/* progress-maps workspace. "Read momentum as a map, not just a score." Tracks where progress is compounding, where it's slipping, and which patterns are strong enough to carry into the next review. Tied to @oshun/domain-arete canonical builders for friction summary, coaching shell, and a progress-map export.

Entry points#

  • Direct URL / bookmark — yes (signed-in)
  • Back navigation — page passes onBack={() => router.back()}
  • No link from /arete polished surface — verify

Layout regions#

page.tsx is a 'use client' page using useRouter(). Renders <AreteProgressMapsWorkspace onBack={() => router.back()} />. Component at apps/oshun/web/src/components/domains/arete/AreteProgressMapsWorkspace.tsx.

  • Container (section): cream-paper radial gradient + linear gradient background; column flex; padding 24px (desktop) / 16px
  • Header tile: Back button (aria-label="Go back"), eyebrow "Arete progress maps" + BarChart3 icon, h1 "Read momentum as a map, not just a score.", lede paragraph, "Open analysis assistant" CTA (dispatches dispatchOshunAssistantOpen with focus object, pattern cluster, and momentum note in the seeded prompt)
  • Window selector (role="group", aria-label="Progress map time window"): 3 pill buttons — weekly, monthly, quarterly (data-arete-progress-maps-period, aria-pressed={active}, aria-label="Show <window> progress map")
  • Below window selector (per source, continues beyond line ~881):
    • Focus entity filterentityFilter state with options all / goal / habit; selectable filter
    • Focus entity list — driven by filteredEntities from concat of goals and habits fixtures (each is a FocusEntity with kind, title, progressPercent, momentumLabel, patternLabel)
    • Pattern cluster list — driven by patternClusters fixture (each is a PatternCluster)
    • Chart stripchartProfiles[window] array of bars (visual momentum bar chart)
    • Friction summarysummarizeAreteFrictionLogs(frictionLogs) → primary category, evidence
    • Coaching briefbuildAreteCoachingSummaryShellModel({ summary, frictionLogs }) produces card title and assistant seededPrompt
    • Artifact actionsAreteArtifactActionPanel save / export / share via saveAreteArtifact / triggerAreteArtifactDownload / buildAreteProgressMapExport

States#

  • Loading — N/A: client component with sync builders
  • Window toggled (weekly / monthly / quarterly) — re-derives chartBars from chartProfiles[window], updates the progress summary, regenerates the coaching brief
  • Entity filter toggledentityFilter filters goals ∪ habits to a kind
  • Entity selectedsetSelectedEntityId(...); if filtered out, falls back to first filtered, then to original list, then to first entity
  • Cluster selectedsetSelectedClusterId(...)
  • Artifact savedsetArtifactSavedAt updates after save; the artifactId is arete-progress-map:{window}:{entityId}:{clusterId} so changing any of the three rotates the saved record
  • Saved-at hydrateduseEffect reads localStorage for the current artifactId
  • Error (recoverable) — relies on app-level error boundary
  • Offline — purely client; identical offline
  • Gated — N/A (no policy gates on this surface in source head)
  • Standalone PWA — no shell chrome around the page

Interactions#

Top bar#

  • Back button (aria-label="Go back")
    • Function: calls router.back() via onBack prop
  • "Open analysis assistant" (button, data-arete-progress-maps-open-assistant)
    • Function: dispatches dispatchOshunAssistantOpen with source arete-progress-maps:<window> and a prompt referencing the selected entity, cluster, and momentum label
    • Touch target: padding 12px 16px

Window selector (3 buttons)#

  • Weekly / Monthly / Quarterly (pill buttons)
    • Function: setWindow(option)
    • aria-pressed={active}, aria-label="Show <window> progress map"
    • data-arete-progress-maps-period

Below-the-fold (per source body)#

  • Entity filter toggle — verify in the lower component body
  • Entity selector buttonssetSelectedEntityId
  • Cluster selector buttonssetSelectedClusterId
  • Artifact action panel buttons — save / share / export
  • Chart bars — presentational; driven by chartProfiles[window]

A full enumeration of buttons and per-region accessibility requires reading lines beyond ~890 — flag for deeper walk.

Data & contracts#

  • Reads: imports from @oshun/domain-arete: buildAreteProgressMapExport, buildAreteCoachingSummaryShellModel, buildCanonicalAreteCoachingSummary, buildCanonicalAreteFrictionLog, buildCanonicalAreteGoal, buildCanonicalAreteHabit, buildCanonicalAreteReview, getAreteArtifactPolicy, summarizeAreteFrictionLogs. Types: AreteCanonicalCoachingSummary, AreteCanonicalGoal, AreteCanonicalHabit, AreteCanonicalReview, AreteFrictionLog. In-file fixtures: goals, habits, patternClusters, frictionLogs, chartProfiles, windowLabel.
  • Writes: saveAreteArtifact (localStorage); export triggers triggerAreteArtifactDownload(buildAreteProgressMapExport({...})); no BFF write
  • Realtime: none
  • Caching: client bundle + localStorage
  • Auth/role check: app-level middleware

Cross-references#

  • Domain hub: arete.md
  • Polished counterpart: arete-patterns.md — the static cross-section view
  • Sibling internal alternates:
  • Component source: apps/oshun/web/src/components/domains/arete/AreteProgressMapsWorkspace.tsx
  • Library: libs/domain-arete/* (@oshun/domain-arete)
  • Assistant dispatch: apps/oshun/web/src/navigation/assistant-entry.ts
  • Artifact support: apps/oshun/web/src/components/domains/arete/areteArtifactSupport.ts, AreteArtifactActionPanel.tsx

Open questions / known gaps#

  • No shared chrome with /arete polished surface
  • Saved artifacts live in localStorage only; no server persistence
  • Full per-region inventory requires reading source past line ~890; the bars, filters, cluster cards, and artifact panel need their own enumeration on a deeper walk
  • How does this surface relate to the polished /arete/patterns — that one shows hour×day heatmap + correlations + mood; this one shows a momentum-bar chart + clusters + friction. Both are pattern-spotting, but render very differently. Document V1-shipping vs internal