Context. surface customer · domain metis · route /metis/lesson · auth signed-in · source apps/oshun/web/src/app/metis/lesson/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; Trust & Safety report affordance target metadata + dialog verified on 2026-06-26; interactive quiz, durable grade result, footer nav, and course-card query entry re-verified on 2026-06-27 by metis-lesson-completion.spec.ts
Purpose#
Course reader for one lesson — passages, sources rail, and a check-your-understanding quiz. Fixture: PHL.102, Stoic ethics, § 4 of 11 — "What is in our power, and what is not." (14 minutes; resumes at line 22).
Entry points#
- Metis schoolroom — "Continue lesson →" primary button on
metis.md - Direct URL / bookmark — yes
- BYOM — verify whether "Generate guide" on
metis-byom.mdnavigates here with a generated lesson
Layout regions#
page.tsx is a thin server component: await getMetisLesson() →
<MetisLesson data={data} />.
Inside MetisLesson (metis.tsx, line 247):
- Web shell top —
LCustomerNav active="library" - Header row (
gridTemplateColumns: '1fr auto'):- Left — eyebrow "PHL · 102 · Stoic ethics · § 4 of 11",
LDisplay"What is in our power, and what is not." - Right —
LCode"14 minutes · resumes at line 22" and the sharedTrustSafetyFlagButtontargetingmetis://lesson/phl-102/stoic-ethics/section-4
- Left — eyebrow "PHL · 102 · Stoic ethics · § 4 of 11",
- Two-column body (
gridTemplateColumns: '1.6fr 320px'):- Left — Reading column — long-form serif body with a 86 px accent
drop-cap (
E), three paragraphs and one blockquote that highlights "In our power are opinion, movement towards a thing, desire, aversion" (line 319); citation row "— Discourses · I.1 · trans. Long" - Left — Check your understanding —
MetisLessonQuizclient component in anLCardwith eyebrow "Check your understanding",LCode"1 of 3"; quiz prompt "Which of these would Epictetus place 'in our power'?"; option rows fromdata.quiz; choosing togglesaria-pressed, Submit transitionsdata-metis-quiz-phasefromchoosingtosubmitted, shows "Nof 4 correct", reveals kept/missed/incorrect pills, persists tooshun.metis.lesson-quiz.v1, and Try again resets. - Left — Footer nav —
← § 3 · The dichotomyghost button, autosave code, and§ 5 · Three disciplines →primary button. Both nav buttons are display-only in V1; nohrefor handler is wired. - Right column — Sources rail — static source rows plus the generated content disclosure card.
- Left — Reading column — long-form serif body with a 86 px accent
drop-cap (
States#
- Loaded —
getMetisLesson()resolves before render; covered bymetis-lesson-completion.spec.ts. - Quiz pristine — all options initially unselected and the quiz phase is
choosing; no answer key is pre-revealed. - Quiz partial selection — option clicks toggle
aria-pressed, visual selection, and localStorage-backed picked state. - Quiz submitted — Submit reveals score and per-option correctness; covered by choose → submit → Try again and reload-durability tests.
- Reduced motion — composes static Lilith primitives; the page has no route animation to disable.
- Resume position —
LCodesays "resumes at line 22"; no query-driven line scroll is implemented, so?line=remains documentary only.
Interactions#
Header#
-
LDisplay— non-interactive. - Report (
TrustSafetyFlagButton) — opens the shared Trust & Safety category/rationale dialog; the focuseduser-flag-to-reviewbrowser spec verifies this button's stable Metis lesson target kind/id/label metadata and dialog controls. The shared live submit → admin moderation read-back path is covered through the Nisaba flag in the same spec.
Reading column#
- Drop-cap
E— non-interactive decorative letter. - Highlighted span — visual emphasis only; no lexicon link is wired.
- Blockquote citation — visual citation only; no Discourses I.1 link is wired on this reader surface.
Check your understanding#
- Option rows (per
data.quiz)- Function: multi-select; user clicks change selection state while choosing.
data.quiz[].ansis used only for grading after submit, not for pre-marking.
- Function: multi-select; user clicks change selection state while choosing.
- Footer eyebrow "Pick all that apply · multi-select" — non-interactive guidance.
- Submit / Try again — Submit grades the answer; Try again resets the quiz to choosing.
Footer nav#
- ← § 3 · The dichotomy (
LBtn kind="ghost") — visible display-only button in V1; no navigation handler is wired. - → § 5 · Three disciplines — visible display-only button in V1; no navigation handler is wired.
Right column (Sources rail)#
- Source citation row — static source metadata; Nisaba opening is not wired from this rail.
- Lilith excerpt — static generated-content disclosure; no copy/save affordance exists in V1.
Data & contracts#
- Reads:
getMetisLesson()from@/lib/lilith-data/metis-depth— returnsMetisLessonData(verify shape: lesson metadata, prose blocks, blockquote, quiz{ k, t, ans }[], sources rail entries) - Writes:
TrustSafetyFlagButtonsubmits customer reports through/api/trust-safety/flags→POST /v1/user-reports; verify quiz submission + progress-save endpoints - Realtime: None.
- Caching: server fetch
- Auth/role check: shell middleware
Cross-references#
- Sibling Metis routes:
- Cross-domain partners: Nisaba (
../07-nisaba/) — source citations and reading desk; Trust & Safety moderation journey../../journeys/user-flag-to-review.md - Component sources:
apps/oshun/web/src/components/lilith/metis.tsx(MetisLessonline 247)
- Feature spec:
V1/features.md#metis
Open questions / known gaps#
- Quiz interactivity is confirmed:
MetisLessonQuizis a client state machine with choosing/submitted phases, exact score, per-option correctness, Try again, and localStorage durability. - Lesson resume line contract is currently display-only: the header says
"resumes at line 22"; the page does not consume
?line=. - Footer section buttons are display-only in V1; no route transition, progress write, or section id contract is implemented here.
- Sources rail save-to-library / save-to-Nisaba is not implemented on the lesson reader; source follow-through is covered on the tutor citation chips instead.