---
path: /metis/lesson
surface: customer
domain: metis
auth: signed-in
source: apps/oshun/web/src/app/metis/lesson/page.tsx
status: walked
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'
---

# Metis · lesson (course reader)

## 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`](./metis.md)
- **Direct URL / bookmark** — yes
- **BYOM** — verify whether "Generate guide" on
  [`metis-byom.md`](./metis-byom.md) navigates 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 shared
    `TrustSafetyFlagButton` targeting
    `metis://lesson/phl-102/stoic-ethics/section-4`
- **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** — `MetisLessonQuiz` client component in
    an `LCard` with eyebrow "Check your understanding", `LCode` "1 of 3"; quiz
    prompt "Which of these would Epictetus place 'in our power'?"; option rows
    from `data.quiz`; choosing toggles `aria-pressed`, Submit transitions
    `data-metis-quiz-phase` from `choosing` to `submitted`, shows "`N` of 4
    correct", reveals kept/missed/incorrect pills, persists to
    `oshun.metis.lesson-quiz.v1`, and Try again resets.
  - **Left — Footer nav** — `← § 3 · The dichotomy` ghost button, autosave code,
    and `§ 5 · Three disciplines →` primary button. Both nav buttons are
    display-only in V1; no `href` or handler is wired.
  - **Right column — Sources rail** — static source rows plus the generated
    content disclosure card.

## States

- [x] **Loaded** — `getMetisLesson()` resolves before render; covered by
      `metis-lesson-completion.spec.ts`.
- [x] **Quiz pristine** — all options initially unselected and the quiz phase is
      `choosing`; no answer key is pre-revealed.
- [x] **Quiz partial selection** — option clicks toggle `aria-pressed`, visual
      selection, and localStorage-backed picked state.
- [x] **Quiz submitted** — Submit reveals score and per-option correctness;
      covered by choose → submit → Try again and reload-durability tests.
- [x] **Reduced motion** — composes static Lilith primitives; the page has no
      route animation to disable.
- [x] **Resume position** — `LCode` says "resumes at line 22"; no query-driven
      line scroll is implemented, so `?line=` remains documentary only.

## Interactions

### Header

- [x] **`LDisplay`** — non-interactive.
- [x] **Report** (`TrustSafetyFlagButton`) — opens the shared Trust & Safety
      category/rationale dialog; the focused `user-flag-to-review` browser 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

- [x] **Drop-cap `E`** — non-interactive decorative letter.
- [x] **Highlighted span** — visual emphasis only; no lexicon link is wired.
- [x] **Blockquote citation** — visual citation only; no Discourses I.1 link is
      wired on this reader surface.

### Check your understanding

- [x] **Option rows** (per `data.quiz`)
  - Function: multi-select; user clicks change selection state while choosing.
    `data.quiz[].ans` is used only for grading after submit, not for
    pre-marking.
- [x] **Footer eyebrow** "Pick all that apply · multi-select" — non-interactive
      guidance.
- [x] **Submit / Try again** — Submit grades the answer; Try again resets the
      quiz to choosing.

### Footer nav

- [x] **← § 3 · The dichotomy** (`LBtn kind="ghost"`) — visible display-only
      button in V1; no navigation handler is wired.
- [x] **→ § 5 · Three disciplines** — visible display-only button in V1; no
      navigation handler is wired.

### Right column (Sources rail)

- [x] **Source citation row** — static source metadata; Nisaba opening is not
      wired from this rail.
- [x] **Lilith excerpt** — static generated-content disclosure; no copy/save
      affordance exists in V1.

## Data & contracts

- **Reads**: `getMetisLesson()` from `@/lib/lilith-data/metis-depth` — returns
  `MetisLessonData` (verify shape: lesson metadata, prose blocks, blockquote,
  quiz `{ k, t, ans }[]`, sources rail entries)
- **Writes**: `TrustSafetyFlagButton` submits 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:
  - [`metis.md`](./metis.md), [`metis-assessment.md`](./metis-assessment.md),
    [`metis-byom.md`](./metis-byom.md), [`metis-tutor.md`](./metis-tutor.md)
- Cross-domain partners: Nisaba (`../07-nisaba/`) — source citations and reading
  desk; Trust & Safety moderation journey
  [`../../journeys/user-flag-to-review.md`](../../journeys/user-flag-to-review.md)
- Component sources:
  - `apps/oshun/web/src/components/lilith/metis.tsx` (`MetisLesson` line 247)
- Feature spec: [`V1/features.md#metis`](../../../V1/features.md#metis)

## Open questions / known gaps

- [x] Quiz interactivity is confirmed: `MetisLessonQuiz` is a client state
      machine with choosing/submitted phases, exact score, per-option
      correctness, Try again, and localStorage durability.
- [x] Lesson resume line contract is currently display-only: the header says
      "resumes at line 22"; the page does not consume `?line=`.
- [x] Footer section buttons are display-only in V1; no route transition,
      progress write, or section id contract is implemented here.
- [x] 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.
