V1 Web PWA · Journey

Journey: Metis lesson specimen, assessment integrity, and tutor handoff

A source-reconciled journey record for V1 Web PWA — shipped behavior, state boundaries, failure modes, and the automation evidence available today.

automated · 4 specs verdict: partial· 2026-05-29
9sections9 minread

On this page
Journey at a glance
ActorsReturning learnerFirst-run learnerAssessment learnerSource-conscious learner
Automation4 E2E spec(s) · verdict: partial· 2026-05-29

Journey flow#

Generated from the authored steps below — click a node to jump to that section.

flowchart TD s1["1. Enter from Home or the schoolroom"] s2["2. Inspect lessons or today's session"] s3["3. Open a course or lesson link"] s4["4. Read and answer the lesson quiz"] s5["5. Compose an assessment answer"] s6["6. Submit for integrity review"] s7["7. Follow an appealable verdict"] s8["8. Inspect the tutor specimen"] s9["9. Send a tutor question"] s10["10. Compare the separate tutor-memory seam"] s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9 --> s10 click s1 href "#1-enter-from-home-or-the-schoolroom" click s2 href "#2-inspect-lessons-or-todays-session" click s3 href "#3-open-a-course-or-lesson-link" click s4 href "#4-read-and-answer-the-lesson-quiz" click s5 href "#5-compose-an-assessment-answer" click s6 href "#6-submit-for-integrity-review" click s7 href "#7-follow-an-appealable-verdict" click s8 href "#8-inspect-the-tutor-specimen" click s9 href "#9-send-a-tutor-question" click s10 href "#10-compare-the-separate-tutor-memory-seam" s10 --> v(["verdict: partial"]) click v href "../results/metis-lesson-completion.html" style v stroke:#d6a531,color:#d6a531

The current customer flow joins navigation, not learner state. A BFF-backed schoolroom can show owned course proposals and separately recorded tutor memory; a dev/test-only backlog supplies the lessons index and today's session; all course and lesson ids then land on one authored reader. Quiz and assessment replay live in localStorage, the assessment can receive a durability-bound Themis response, and the displayed tutor queues text only in the browser. No shared authority records lesson completion or projects it into Home, the schoolroom, the library, or another device.

Personas#

  • Returning learner — enters from Home, the Metis schoolroom, the lessons index, or today's session.
  • First-run learner — needs honest no-progress and no-assessment states.
  • Assessment learner — clears the client rubric gate and sees integrity evidence with an appeal handoff when applicable.
  • Source-conscious learner — follows authored tutor citations into Nisaba.

Pre-conditions#

  • The customer web pages are opened through an authenticated shell.
  • /metis can read GET /v1/metis/room; the route combines caller-owned course proposals, a curated catalog, honest zero progress, and any separately stored tutor-memory summaries.
  • In development/test only, GET /v1/metis/lessons returns three fixed backlog rows. The production guard returns 503 not_configured; the route has no account-scoped lesson source.
  • getMetisLesson(), getMetisAssessment(), and getMetisTutor() return authored fixtures from metis-depth.ts.
  • POST /v1/metis/assessment-submissions is reachable with a Metis-scoped bearer. Its verdict, appeal, gradebook consequence, and notification intent share one required, acknowledgement-bound operation snapshot in production.

Steps#

1. Enter from Home or the schoolroom#

  • Home's Metis continuation exposes a live/fallback state and Browse courses, opening /domains/metis with origin=home and a course-path hint.
  • /metis reads /v1/metis/room. A learner without a real lesson cursor sees Begin your first lesson, zero lesson/assessment stats, and no open assessment rather than invented progress.
  • Owned course proposals are prepended to three curated catalog cards. Every card links to the shared reader with a course query.
  • The tutor nudge can quote a topic from a separately created tutor memory, but the card has no link or resume action.

2. Inspect lessons or today's session#

  • /metis/lessons groups the development/test backlog fixture by course and exposes course-level courseId links plus lesson-level id links.
  • /metis/session selects the first row whose assessmentReady flag is true, otherwise the first row, and lists the next two fixture rows. It does not read dates, mastery, enrollment, due work, or a learner cursor.
  • The lessons endpoint is shared fixture data without an auth pre-handler and fails closed in production. A failed server read is rendered as the same empty state used for an account with no lessons.
  • Schoolroom cards preserve ?course=<code>, course groups preserve ?courseId=<id>, and individual rows preserve ?id=<lessonId>.
  • The URL retains the query, but MetisLessonPage does not read it. The page always calls getMetisLessonFixture() and renders the same PHL.102 Stoic ethics section.
  • There is no per-course/per-lesson server lookup, authorization check, or mismatch response at the destination.

4. Read and answer the lesson quiz#

  • /metis/lesson renders an authored passage, five static source rows, and a four-option multi-select quiz.
  • Answers are unmarked until submit. The client reveals the score and per-option results, supports Try again, and restores { picked, phase } after reload from oshun.metis.lesson-quiz.v1.
  • The key is not scoped by tenant, account, course, lesson, assessment version, or attempt. Storage errors are ignored.
  • Previous/next section buttons have no target or handler and write no progress.

5. Compose an assessment answer#

  • /metis/assessment renders an authored prompt, fixed due copy, four fixture rubric bars, and a client editor.
  • The editor requires 180–220 words and at least one citation-like token before enabling submit. Insert citation appends a placeholder; Save draft and every change write to oshun.metis.assessment.draft.v1.<assessmentId>.
  • The request body uses the page's assessment id and hard-codes courseId: phl-102; it does not derive identity from a selected lesson.

6. Submit for integrity review#

  • A valid answer posts to POST /v1/metis/assessment-submissions with Metis scope. The BFF derives deterministic integrity signals, adjudicates them with the canonical Themis bridge, persists the operation and gradebook consequence before publication, and returns the verdict evidence.
  • The browser locks the editor and shows verdict class, severity, signal count, recommended action, source of record, and appeal availability.
  • The browser stores that reduced response in localStorage. Reloading the submitted card is browser replay, not a submission/audit/gradebook GET.
  • The browser suite forwards assessment and integrity requests with a test-authored bearer, so it proves the UI and route seams but not untouched production browser authorization.

7. Follow an appealable verdict#

  • A suspicious answer can return a violation with a canonical /integrity/:verdictId/appeal link.
  • In the browser run's same BFF process, the appeal page reads the verdict's signal count, rationale, and excerpt and exposes the appeal form.
  • Production hydrates the metis-academic-records ledger before traffic. Unit and PostgreSQL integration tests cover restart restoration, failure rollback, export, erasure fencing, and retention; this four-case browser suite does not itself restart the service.

8. Inspect the tutor specimen#

  • /metis/tutor renders six fixture messages, three authored assistant turns, two citation chips, four fixed context rows, a disclosure, and an authored end-of-session note.
  • Citation chips genuinely navigate to /nisaba?passage=<src>&from=metis-tutor&ref=<label>.
  • Transcript and End session are display-only. Report delegates to the shared Trust & Safety flag flow, covered by a separate journey.
  • “session 14,” “11 turns,” “grounded in four sources,” and “saved to library” are component/fixture copy, not reads from the tutor-memory store or library.

9. Send a tutor question#

  • The composer persists its draft under oshun.metis.tutor.draft.v1.default.
  • Submit by button or modifier+Enter appends the text and timestamp to the last 50 entries under the adjacent .queue key, clears the draft, waits 200 ms, and displays Queued · the tutor will pick this up.
  • No BFF tutor POST, SSE, WebSocket, model response, transcript append, retry worker, or library write consumes this queue.

10. Compare the separate tutor-memory seam#

  • POST /v1/metis/tutor-session-memories is a different API. It authenticates Metis scope, folds an understanding turn into mastery state, and lets the schoolroom reflect its topic and session count.
  • Production requires and hydrates tutor memory plus mastery state. The route awaits its ordered candidate snapshot before 201; export, exact-subject deletion with a recreation fence, and scheduled retention are composed.
  • Creating that record directly and reading it from /metis proves a real independent seam; it does not make the displayed fixture transcript or local composer durable.

Post-conditions#

  • The user can navigate Home or Metis into id-bearing course/lesson URLs.
  • In development/test, the lessons index and session expose a deterministic three-row backlog and responsive 390 px layout.
  • Every selected id renders the same authored lesson.
  • Quiz state and the assessment response can replay in the same browser profile.
  • A valid assessment can receive a durability-bound Themis verdict, and an appealable verdict can open its audit evidence in the running browser harness.
  • Tutor citations can open Nisaba; submitted tutor text remains only in a local queue.
  • No learner completion, server quiz attempt, browser-to-server assessment read-back, tutor transcript, library save, or Home/schoolroom progress update is produced by this chain.

Failure modes#

  • Production backlog requested/v1/metis/lessons returns 503 not_configured; index/session pages flatten that failure into empty.
  • Course or lesson id implies unique content — the destination ignores it and renders the PHL.102 fixture.
  • Quiz state leaks across ids or users in one browser profile — the single key has no account or lesson partition.
  • Browser storage rejects a write — the component swallows the error while save-oriented copy remains visible.
  • Assessment is below/above bounds or lacks a citation — submit remains disabled.
  • Integrity request fails — the answer remains editable and error copy is visible.
  • Browser reloads or changes device after a verdict — the durable server record remains, but this editor has no submission GET and replays only its local card.
  • Tutor nudge is treated as a resume action — the card has no link.
  • Tutor queued acknowledgement is treated as delivery — no runtime reads the local queue.
  • “Saved to library” is read literally — no library write or read-back occurs.
  • Footer navigation is treated as progress — the controls neither route nor persist.

E2E coverage#

Per-view files touched#

Cross-references#

  • apps/oshun/web/src/lib/lilith-data/metis-depth.ts — authored lesson, assessment, and tutor fixtures.
  • apps/oshun/bff/src/routes/domain-stubs.ts — production-guarded lesson backlog and schoolroom route.
  • apps/oshun/bff/src/routes/metis-integrity.ts — assessment, adjudication, appeal, and gradebook routes backed by the durable operation ledger.
  • apps/oshun/bff/src/routes/metis-tutor-memory.ts — separate tutor-memory route.
  • metis-byom-ingest-to-course.md — independent ingest, decision, and proposal seams.
  • themis-assessment-appeal.md — wider appeal lifecycle.

Open questions#

  • Replace the guarded backlog fixture with an authenticated enrollment and assignment read, including explicit unavailable and empty states.
  • Resolve course, courseId, and id into authorized records; reject unknown or mismatched identity.
  • Persist lesson attempts and completion by tenant, learner, lesson, version, and retry, then project them into Metis, Home, and Library.
  • Add account-scoped assessment/verdict/gradebook read-back to replace the editor's browser-local submitted replay.
  • Connect the browser tutor to the existing tutor-memory model with an generated-turn stream, transcript read-back, and real resume action; the memory commit itself is already acknowledgement-bound.
  • Replace or qualify “today,” “auto-saved,” “saved to library,” “grounded,” and queued-delivery copy until each has the corresponding authority.