Context. surface customer · domain arete · route /arete/review · auth signed-in · source apps/oshun/web/src/app/arete/review/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; content re-verified 2026-06-03 against current source; 2026-06-30 close/save telemetry re-walked in arete-review-close.spec.ts
Purpose#
"Celebrate · Notice · Choose · Invite. Four acts, twenty minutes, on a Sunday."
A guided weekly review with the four acts in order, a sidebar of KPIs, mood
thread, and one-per-evening journal lines. Renders
<AreteReview data={await getAreteReview()} />.
Entry points#
- From
/aretesub-nav "Weekly review" tab — theLSubNavitem carrieshref="/arete/review"and navigates here - Sunday reminder push — inferred from "Sunday. Look back, gently." body
- From
/arete/coaching— Lilith's letter references "the week" and may link back here (no explicit link in source) - Direct URL / bookmark — yes (signed-in)
Layout regions#
page.tsx is a thin server component: await getAreteReview() →
<AreteReview>. Component lives at
apps/oshun/web/src/components/lilith/arete.tsx line 1108 — an LWebShell with
LCustomerNav active="today".
- Header:
LCustomerNav active="today" - Masthead (
ArMast): left "Arete · sunday review", middata.weekLabel, right "four acts · twenty minutes", big "Sunday. Look back, gently.", lede about Celebrate · Notice · Choose · Invite - Main, left (1.4fr): vertical stack of four act blocks (per
data.acts). Each act renders:- Header row: "act {num} · {kicker}" eyebrow (accent if
a.accent), big italic title,LCodeduration on the right - Body: mixed text with
emphasized(accent italic) andchip(highlight bg) inline spans froma.bodyParts - Two-column grid of
a.listitems in rounded outlined cards
- Header row: "act {num} · {kicker}" eyebrow (accent if
- Aside, right (1fr):
- "The week, kept" —
data.kpi3-up: each tuple[k, v, c]renders big serif numeral colored byc('accent' / 'ink' / muted) - "Mood thread" —
aria-hiddenSVG curve across the week (mon–sun); body rendersdata.moodCaption - "What you wrote" — list of
data.days[i] = [day, txt]lines with date code + italic text
- "The week, kept" —
- Footer row (
borderTop: 1px solid L.ink):- Note: "The review is yours; Lilith never alters a sentence. She might suggest a phrase in the margin."
AreteReviewMarginSuggestionreveal button backed bydata.marginSuggestion- "Save as private letter" (ghost md) + "Close the week" (primary md)
Automation anchors#
- Root:
data-arete-review-pagewithdata-arete-review-week-label,data-arete-review-act-count,data-arete-review-kpi-count, anddata-arete-review-journal-day-count - Masthead and layout:
data-arete-review-masthead,data-arete-review-layout,data-arete-review-acts, anddata-arete-review-sidebar - Act blocks: each
data-arete-review-act={num}carries index/title/kicker/ duration/accent attributes, plusdata-arete-review-act-eyebrow,data-arete-review-act-title-text,data-arete-review-act-duration-text,data-arete-review-act-body, per body part kind,data-arete-review-act-list, and per list item index - Sidebar:
data-arete-review-kpiswith perdata-arete-review-kpi={label}value/color cells;data-arete-review-moodwithdata-arete-review-mood-chartanddata-arete-review-mood-caption; anddata-arete-review-journalwith per-row day/text cells - Footer:
data-arete-review-footer,data-arete-review-footer-note, anddata-arete-review-footer-actions
States#
- Loading — server-awaited; no
loading.tsxat this route - Populated (default fixture) — four acts, KPI tiles, mood SVG, day-by-day journal lines render
- Mid-act (partial) — N/A: the page renders all four acts at once; no "active act" progress indicator
- Empty acts / days / kpi — empty arrays render no rows (no empty-state copy)
- Error (recoverable) — relies on parent error boundary
- Offline — no explicit handling
- Gated — N/A
- Standalone PWA — renders cleanly within
LWebShell
Interactions#
Act blocks (per data.acts)#
- Act block — header, body (mixed emphasis), list items
- Function: presentational only — no inputs, no completion checks
KPI tiles (per data.kpi)#
- KPI tile — big numeral + label eyebrow
- Color: derived from third tuple entry —
accent→L.accent,ink→L.ink, elseL.muted(kpiColorhelper) - Function: presentational only
- Color: derived from third tuple entry —
Mood SVG#
- Mood thread chart —
aria-hidden="true"; smooth quadratic curve across mon–sun- Function: presentational only
- Caption renders
data.moodCaption
Journal lines (per data.days)#
- Day row — date code + italic text
- Function: presentational only — no entry-level link to journal route
Footer actions#
- Margin suggestion (button in
AreteReviewMarginSuggestion)- Function: toggles a data-backed phrase beside the footer note without mutating the review body
- Screen reader: button exposes
aria-expandedandaria-controls
- "Save as private letter" (button in
AreteReviewClose)- Function: POSTs
/v1/arete/review/closewith actionsaved-privateand rendersdata-arete-review-close-state="kept-private" - Telemetry: after the BFF closure response succeeds, emits
arete_weekly_review_closedwithaction: 'saved-private',state: 'kept-private',weekLabel,closureId, andsourcePath: '/arete/review'
- Function: POSTs
- "Close the week" (button in
AreteReviewClose)- Function: POSTs
/v1/arete/review/closewith actionclosedand rendersdata-arete-review-close-state="week-closed" - Telemetry: after the BFF closure response succeeds, emits
arete_weekly_review_closedwithaction: 'closed',state: 'week-closed',weekLabel,closureId, andsourcePath: '/arete/review'
- Function: POSTs
Data & contracts#
- Reads:
getAreteReview()from@/lib/lilith-data/arete-depth— returnsAreteReviewData({ weekLabel, acts, kpi, moodCaption, marginSuggestion, days }). BFF mapping comment:getAreteReview ← /arete/reviews/:weekId. - Writes:
AreteReviewClosePOSTs/v1/arete/review/closeforsaved-privateandclosed;/aretereads the stored closure through/v1/arete/room - Telemetry:
apps/oshun/web/src/analytics/areteReviewTelemetry.tsemitsarete_weekly_review_closedonly after the persisted close/save envelope is returned by the BFF. - Realtime: none
- Caching: server fetch, default Next.js cache
- Auth/role check: app-level middleware
Cross-references#
- Domain hub:
arete.md - Plan / Goal siblings:
arete-plan.md,arete-goal.md,arete-coaching.md - Domains-namespace alternate:
domains-arete-plan-review.md— internal plan-review workspace with reflection drafts and assistant handoff - Component source:
apps/oshun/web/src/components/lilith/arete.tsx(line 1108,AreteReview) - Data:
apps/oshun/web/src/lib/lilith-data/arete-depth.ts(getAreteReviewFixture) - Feature spec:
V1/features.md
Open questions / known gaps#
- "Save as private letter" and "Close the week" persist through
AreteReviewClose, emitarete_weekly_review_closedafter BFF success, and read back on/arete - No per-act completion state — the user can't mark Celebrate / Notice / Choose / Invite individually
- No journaling input on this page —
data.daysis read-only; the "Save as private letter" CTA implies an output that isn't wired here - Mood-thread caption is data-driven via
AreteReviewData.moodCaption - Promise text "Lilith never alters a sentence. She might suggest a phrase
in the margin." —
AreteReviewMarginSuggestionnow reveals the data-backed phrase without altering the review text