V1 Web PWA · Surface walkthrough

Metis · assessment

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 metis · route /metis/assessment · auth signed-in · source apps/oshun/web/src/app/metis/assessment/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; submit→Themis verdict re-verified 2026-06-26 by metis-assessment-submit.spec.ts

Purpose#

Short-answer assessment with rubric preview and a Themis academic-integrity notice. Fixture: PHL.102 · A2, "Apatheia, in your own words." — 200-word short answer with citation requirements.

Entry points#

  • Metis schoolroom — "Begin" primary button on metis.md sidebar — LBtn href="/metis/assessment"
  • Direct URL / bookmark — yes (auth required via shell middleware)

Layout regions#

page.tsx is a thin server component: await getMetisAssessment()<MetisAssessment data={data} />.

Inside MetisAssessment (metis.tsx, line 439):

  • Web shell topLCustomerNav active="library"
  • Header row (gridTemplateColumns: '1fr auto'):
    • Left — title — eyebrow "PHL.102 · A2 · short answer", LDisplay headline "Apatheia, in your own words."
    • Right — metaLStatusPill status="ok" "Auto-saved 14:22", LCode "due Sun · 11 May"
  • Two-column body (gridTemplateColumns: '1.6fr 1fr'):
    • Left — prompt + answer editor:
      • Prompt card (LCard) — italic "In 200 words, explain what the Stoics meant by apatheia, …"; meta row "min · 180 w / max · 220 w / citations · 1+ / rubric · 4 dims"
      • Answer panel — ruled-paper styled (repeating-linear-gradient every 27/28 px) with a real <textarea aria-label="Assessment answer">, eyebrow "Your answer · / 220", live citation count, Save draft, Submit, and Reopen draft controls
      • Themis result — after a successful submit, the answer locks read-only and a compact data-metis-assessment-themis-result panel shows verdict class, severity, signal count, source of record, recommended action, and an appeal link when appealAllowed=true
    • Right column — rubric preview (4 dimensions) + Themis academic-integrity notice + draft history / actions

States#

  • LoadedgetMetisAssessment() resolves before render; route covered by metis-assessment-submit.spec.ts.
  • Draft saved locally — editor writes the draft to oshun.metis.assessment.draft.v1.<assessmentId> and updates the local "auto-saved" time
  • Word count progress — eyebrow "Your answer · / 220"
  • Under min words — below 180 words shows "below minimum" and keeps Submit rubric-gated
  • Over max words — over 220 words shows "over maximum" and keeps Submit rubric-gated
  • No citation yet — citation count below the requirement keeps Submit in "Submit · check rubric"
  • Themis integrity notice present — right rail copy renders: "This is your work. Quoting is allowed; cite the source. Tutor (✻) may help you understand, but may not write the answer for you." No policy link is wired in this card.
  • Submitted state — successful BFF submit locks the editor read-only, persists the Themis result locally, and exposes verdict / appeal metadata
  • Submit failure — failed Themis submit leaves the textarea editable and renders the returned error
  • Reduced motion — composes static Lilith primitives; the former decorative blinking cursor span is gone because the editor is a real textarea/read-only record.

Interactions#

  • LDisplay — non-interactive.

Auto-save chip#

  • LStatusPill — non-interactive route-level fixture chip; the editor's own autosave timestamp updates from local draft persistence.

Prompt card#

  • Prompt — non-interactive.
  • Meta row — non-interactive (min / max / citations / rubric).

Answer panel#

  • Answer textMetisAssessmentEditor mounts a real <textarea aria-label="Assessment answer"> while editable and a read-only serif record after successful submit
  • Draft auto-save — localStorage draft persistence is implemented; no BFF draft auto-save endpoint is wired yet
  • Citation insertion — Insert citation appends a citation placeholder and updates the citation count

Right column#

  • Rubric preview (4 dimensions) — static dimension rows with percentage bars; no expansion controls are wired in V1.
  • Themis integrity notice — exact visible copy is documented above; no integrity-policy link is wired.
  • Submit — posts to POST /v1/metis/assessment-submissions; read-back includes detection signals and a canonical Themis adjudication
  • Save draft / discard — Save draft persists the current textarea value to localStorage; no discard control is present.

Data & contracts#

  • Reads: getMetisAssessment() from @/lib/lilith-data/metis-depth — returns MetisAssessmentData (verify shape: prompt, meta, current draft, word count, rubric, integrity notice)
  • Writes: draft save is localStorage; submit uses POST /v1/metis/assessment-submissions with { assessmentId, courseId, answer, submittedAt } and returns { submission, detection, adjudication }
  • Realtime: None observed in this view.
  • Caching: server fetch
  • Auth/role check: shell middleware

Cross-references#

Open questions / known gaps#

  • Confirm whether the answer panel is a live editor in V1 or remains a display specimen with a blinking-cursor element — it is a real textarea while editable
  • BFF draft auto-save is not wired by design in this V1 page; draft persistence is localStorage-only until product requires a server draft record.
  • Document the submit endpoint — POST /v1/metis/assessment-submissions
  • Rubric preview is static labels + bars; no expandable dimension details.
  • Themis academic-integrity notice exact copy is documented; it carries no link.