V1 Web PWA · Journey

Journey: Psyche text tutor and server-side graded memory record

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

automated · 2 specs verdict: partial· 2026-05-29
9sections6 minread

On this page
Journey at a glance
ActorsText learnerServer-side tutor agentReturning learnerTeacher/operator
Automation2 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. Open the text tutor"] s2["2. Use the composer within its shipped scope"] s3["3. Follow a citation"] s4["4. Create a graded memory through the server…"] s5["5. Verify owner-scoped read-back"] s6["6. Verify the customer projection"] s7["7. Record the unshipped Psyche and review sta…"] s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 click s1 href "#1-open-the-text-tutor" click s2 href "#2-use-the-composer-within-its-shipped-scope" click s3 href "#3-follow-a-citation" click s4 href "#4-create-a-graded-memory-through-the-server-contract" click s5 href "#5-verify-owner-scoped-read-back" click s6 href "#6-verify-the-customer-projection" click s7 href "#7-record-the-unshipped-psyche-and-review-stages" s7 --> v(["verdict: partial"]) click v href "../results/psyche-tutor-live-session-to-graded-record.html" style v stroke:#d6a531,color:#d6a531

The visible /metis/tutor experience and the durable graded-memory contract are both real, but the customer UI does not connect them. The page renders a fixed Epictetus transcript, real citation links, disclosure/context cards, and a composer that appends outgoing text to localStorage. Separately, POST /v1/metis/tutor-session-memories accepts a server/agent turn assessment, folds it through the real learner-mastery engine, and durably stores the resulting owner-scoped memory, recovery, governance, Iris-link, and mastery snapshot. There is no live-voice control, browser turn emitter, library write, or tutor-session teacher-review lane today.

Personas#

  • Text learner — reads the fixture tutor transcript, follows citations, and queues a local outgoing message.
  • Server-side tutor agent — supplies assessed understanding and optional continuity/runtime/governance metadata to the memory API.
  • Returning learner — sees the latest stored topic reflected in the Metis room and activity projection.
  • Teacher/operator — can inspect the existing Metis operator dashboard, but has no wired tutor-session review queue or verdict action.

Pre-conditions#

  • Use an authenticated session with domain:metis or domain:* for the memory API. Learner identity comes from the auth context, not the request body.
  • /metis/tutor currently reads getMetisTutorFixture() from apps/oshun/web/src/lib/lilith-data/metis-depth.ts.
  • The BFF startup wires tutorSessionMemoryStore to the durable snapshot store; without that production binding, an isolated test instance uses in-memory state.
  • Keep a browser-composer action separate from an agent-runtime API action: the component does not call the memory endpoint.

Steps#

1. Open the text tutor#

Visit /metis/tutor. The header, six transcript turns, two citation chips, session context, disclosure, and end-of-session note are fixture content. The header's Transcript and End session controls are presentational and have no handler. The subtitle saved to library and note label auto · saves to library have no backing library-store write.

2. Use the composer within its shipped scope#

Type a message and activate Send or press ⌘/Ctrl+Enter. MetisTutorComposer saves a draft under oshun.metis.tutor.draft.v1.<sessionId> and appends submitted text to the associated .queue key, capped at 50 entries. After a short local delay it shows Queued · the tutor will pick this up and clears the draft.

No consumer reads that queue and no request reaches the BFF. The confirmation means browser-local intent was recorded, not that a tutor received, answered, graded, or persisted the turn.

3. Follow a citation#

Citation chips are real links to /nisaba?passage=<source>&from=metis-tutor&ref=<reference>. Navigation works, but the compact Nisaba room currently ignores those query parameters and opens its curated reading desk. The link is not proof that the requested citation was resolved or that back-stack continuity was stored.

4. Create a graded memory through the server contract#

An authorized agent/service can post a session id, topic, status, optional summary and state blocks, plus a turn assessment with understanding level, confidence, concepts, mastered concepts, gaps, and misconceptions. The route validates the envelope, derives mastery evidence, applies the real posterior update, builds TutorSessionMemory, and persists the memory together with the mastery state and recent diffs.

The route accepts assessed turn metadata, not the visible chat transcript or raw voice/audio events. A successful 201 therefore proves a graded memory record, not transcript auto-save or a live Psyche transport.

5. Verify owner-scoped read-back#

Read the record through GET /v1/metis/tutor-session-memories/:sessionId and list the learner's records newest first. A different authenticated learner cannot read that record because the route always keys by auth subject. Missing, malformed, unauthorized, and wrong-scope requests fail closed.

6. Verify the customer projection#

The Metis in-process adapter reads the same memory store. /v1/metis/room uses the latest session for its resume nudge and reports tutor activity as a session count; Activity can also include recent tutor records. Opening /metis after a server-side memory write proves this read path. It does not cause the separate fixture /metis/tutor transcript to change.

7. Record the unshipped Psyche and review stages#

There is no microphone/live-voice toggle, transport state UI, barge-in, reconnect buffer, or Psyche envelope on the customer page. /operator/metis renders fixture KPIs, a generated-lesson queue, and fixture Themis flags (with real OneRoster overlay where available); it does not list TutorSessionMemoryReviewState rows or provide uphold/dismiss/escalate actions for tutor sessions. Named live-session, Iris, mastery-verdict, library, and teacher-review telemetry in the old journey is not emitted by this path.

Post-conditions#

  • Browser draft/queue state is reported as local intent only.
  • A directly posted BFF memory is durable when the snapshot store is wired, owner scoped, and accompanied by real mastery posterior/diff state.
  • The latest server memory can influence /metis and activity read surfaces.
  • No transcript auto-save, live voice, library save, automatic Iris bridge, teacher review, or telemetry chain is claimed.
  • The fixture tutor page and server memory may legitimately show different topics and turn counts because no front-door bridge joins them.

Failure modes#

  • Local queue mistaken for delivery — the composer says queued, but no consumer or network request exists.
  • Memory API auth/scope failure — missing auth returns 401 and missing Metis scope returns 403.
  • Invalid assessment — schema violations return 400 without a graded record.
  • Unknown session — owner-scoped GET returns 404 for an absent id.
  • Cross-learner access attempt — the same session id under another auth subject does not expose the first learner's memory.
  • Snapshot backend unavailable — the runtime cannot provide restart-durable read-back; do not downgrade silently to a durability claim.
  • Fixture projection mismatch/metis/tutor keeps the Epictetus fixture even after a different server record is created.
  • Review/library overclaim — static labels and operator fixtures are treated as real writes or adjudication.

E2E coverage#

  • apps/oshun/web/e2e/metis-tutor-session.spec.ts deeply covers the visible fixture transcript, disclosure, context, citation navigation, local composer queue, negative live-voice assertion, and real /metis read-back of a seeded memory.
  • apps/oshun/web/e2e/psyche-tutor-memory-bff.spec.ts proves real HTTP validation, mastery folding, runtime/recovery/governance/Iris metadata preservation, newest-first listing, and owner isolation.
  • Coverage is deep for the two shipped seams and partial for the title's full product arc because no browser emitter, voice transport, library write, or operator review lane connects them.

Per-view files touched#

Cross-references#

  • metis-lesson-completion.md — adjacent fixture lesson and local assessment behavior.
  • nisaba-scholarly-read.md — citation-query destination boundary.
  • assistant-handoff-context-carry.md — implemented continuity record for comparison.
  • Code: apps/oshun/bff/src/routes/metis-tutor-memory.ts, apps/oshun/bff/src/metis/tutor-session-memory-store.ts, apps/oshun/web/src/components/lilith/MetisTutorComposer.tsx, and libs/metis/models/src/session-memory/tutor-session-memory.ts.

Open questions#

  • Which customer/agent runtime will send an actual tutor turn to the memory API, and how will it reconcile retries and turn ordering?
  • Should the API accept a governed transcript/checkpoint contract, or should a separate event store own raw text and voice data?
  • What Psyche transport, disclosure, interruption, and reconnect UI will ship?
  • When will End session create a summary and real Library item?
  • How will /operator/metis list, isolate, and adjudicate tutor-session review records without exposing learner data to the wrong tenant?