tara-sit-id.mdtara.mdveritas.md04-auth-session.md05-notifications.mdJourney flow#
Generated from the authored steps below — click a node to jump to that section.
User invokes the global assistant dock from any domain surface; the panel opens
with a typed context handoff (active route, current artifact, evidence state,
persona identity, memory scope); the user switches persona across a domain
boundary (e.g., Tara teacher → Veritas explainer); Iris recalls permitted prior
context; and the transcript labels it as Remembered context, with explicit
profile/notebook lines when those scopes apply. Catches broken handoff payloads,
persona switches that drop memory, and disclosure strips that de-sync from the
active grounding state without promising obsolete continuity copy.
Personas#
- Signed-in customer, mid-Tara-sit — primary; invokes from
/tara/sit/[id]then navigates to Veritas with the assistant attached - Signed-in customer, in Veritas — opens from
/veritasor/veritas/claimand asks a contemplative question that routes to a Tara persona handoff - Memory-off customer — chose
memoryScope='off'in onboarding (seeonboarding-ten-steps.md); disclosure strip must reflect "memory off" on every reply; recall must not happen - Anonymous user — no assistant dock; invocation points hidden / inert
Pre-conditions#
- Signed-in session — see
shell/04-auth-session.md memoryScopeis one ofoff | session | profile- Assistant BFF routes healthy:
POST /v1/assistant/sessions,POST /v1/assistant/sessions/:sessionId/message,GET /v1/assistant/sessions,DELETE /v1/assistant/sessions/:sessionId - Viewport ≥
ASSISTANT_DOCK_MIN_WIDTH(1360 px) for the dock; below that, the panel uses overlay presentation
Steps#
1. Open the source surface and dock#
- User on
/tara/sit/[id](or any Veritas / Nisaba / Metis surface) - Collapsed
AssistantDockvisible top-right (ASSISTANT_DOCK_COLLAPSED_WIDTH = 128) when viewport ≥ 1360 px - Verify:
customer/03-tara/tara.mdsurface mounted
2. Invoke the assistant#
- Click
data-shell-assistant-dock-expand(or global shortcut) - Dock transitions
collapsed→expanded(ASSISTANT_DOCK_EXPANDED_WIDTH = 360), 200 ms unless reduced-motion -
AssistantPanelmounts withpresentation='dock' - Shell builds
AssistantContextHandofffromlibs/oshun/shell-assistant/src/context-handoff.tscarryingactiveRoute,activeDomain,artifact,personaIdentity,evidenceState,memoryScope,disclosureState,permittedToolGrants - Handoff runs through the sanitiser: caps selection / seed length, strips
email / US phone / SSN patterns, rejects entities whose
platformShellmismatches the launch intent's shell
3. Context handoff card + disclosure strip#
-
AssistantPanelpaintsdata-assistant-context-handoffchipsArtifact: <label>,Evidence: <status>,Memory: <scope>,Persona: <displayName>,Tools: <count> -
ShellPersistentContextStripmirrors that set with secondary "Back to" and primary "Return to " (or thread label) -
AssistantDisclosureStriprenders memory / persona / grounding / voice / avatar indicators
4. Session creation + Iris recall#
- First message creates a session via
POST /v1/assistant/sessionswithuserPreferences.memoryScope,memoryConsentGranted,enabledMemoryCategories,suppressionRulesattached - If
memoryScope !== 'off', Iris recall hydrates profile (durable), session (rolling 30 d raw / 90 d summarized), and notebook-linked memory bound to the active artifact per V1/features.md § Iris Memory and Identity - If
off, no recall; disclosure strip reflects "Memory: off" on every reply
5. Reply with grounding + disclosure#
- When recall is available, the reply uses the current BFF contract:
Remembered context:followed by permitted profile/notebook facts; it does not depend on the older aspirational "I noticed you were just sitting…" sentence - Reply carries
AssistantTurnGrounding(level,supportCount,contradictionCount, optionalprimarySource+citations); "Inspect evidence" opensVeritasInspectionOverlaywith a model frombuildAssistantTurnInspectionModel - Disclosure indicators stay in sync with active grounding / memory / persona / voice state per turn
6. Cross-domain persona switch#
User on /tara/sit/[id] with persona tara-guide (teacher role) asks a
fact-grounded question; panel offers a Veritas-leaning explainer handoff.
-
personaHandoffState(frombuildAssistantPersonaSwitchingModel+buildAssistantPersonaHandoffState) surfaces options withstatus: 'active' | 'recommended' | 'available' | 'restricted' - User picks a recommended persona (e.g.,
source-lineage-guideorstoic-scholar); panel paints newactivePersona.id/role/memoryBoundary.kind -
AssistantPersonaHandoffAuditEventappended (visible viadata-assistant-persona-handoff-audit-count) - Memory boundary honoured: profile-scope memory carries across; sensitive-category memory not licensed for the new persona is suppressed per V1/features.md § Privacy-Aware Suppression
7. Navigate the domain boundary#
- User navigates from
/tara/sit/[id]to/veritas(or/veritas/claim) without dismissing the assistant - Dock stays attached; new
AssistantContextHandoffis computed; prior handoff recorded in persistent context for "return to" affordances - Context handoff card refreshes with new
Artifact/Evidence/ possibly a differentPersonarecommendation - Disclosure strip re-renders for the new domain's grounding state
- Verify:
customer/05-veritas/veritas.md
8. Continuity disclosure + dismiss#
- The first reply on the new surface may include prior context only when the
memory scope permits it; recalled facts remain visibly prefixed as
Remembered context: - If memory is off, the assistant still gets the current-screen handoff but cannot reference the prior Tara sit
- Click
data-shell-assistant-dock-dismiss(X) → dock returns tocollapsed; thread state persists in sessionStorage underASSISTANT_THREAD_STORAGE_KEY(oshun-web-assistant-thread) -
updateOshunPersistentShellContextupdates so re-invocation can offer "Return to" / "Back to "
Post-conditions#
- Live session exists with turn count recorded
- Session's
userPreferences.memoryScopematches the user's profile - Transcript + active context handoff persisted in sessionStorage
- Disclosure indicators match actual subsystem states each turn
PersonaHandoffAuditEventrecorded for any persona switch
Failure modes#
- Sanitiser drops the artifact — artifact's
platformShellmismatched launch intent; panel receivesnullartifact, shows "no current artifact" copy instead of an empty chip - Sanitiser drops a mismatched entity — a wrong-shell entity is omitted
before session creation; the handoff carries
entity: null, preserves the current artifact, and shows "Entity: removed (shell mismatch)" without exposing the dropped entity label -
POST /v1/assistant/sessionsreturns 403 (no domain access) — panel falls back toAssistantSafeFallbackStatefrombuildAssistantSafeFallbackState; user sees "Assistant unavailable on this surface" - Memory scope mismatch —
contextHandoff.memoryScopedisagrees withuserPreferences.memoryScope; panel useseffectiveMemoryScope = contextHandoff?.memoryScope ?? memoryScope(most-restrictive of the two) - Restricted persona switch — option
state === 'restricted'; UI hard-blocks; audit records the attempt withoutcome: 'fallback'; panel reverts to previous active persona - Cross-tenant entity leak — sanitiser rejects with
403 forbidden_cross_tenant_scope; INC fires in operator admin - Viewport shrinks below 1360 px mid-session — dock transitions to overlay; thread state persists; persistent-context strip changes layout
- Crisis-frame suppression activates — Lilith intercepts (see
crisis-aware-tone-policy.md); no new memory written, existing memory suppressed from recall except safety-critical; crisis surface mounts in-place
E2E coverage#
- Backed by
apps/oshun/web/e2e/assistant-continuity-journey.spec.ts,apps/oshun/web/e2e/shell-utility-dock.spec.ts,apps/oshun/web/e2e/shell-boundary.spec.ts, andapps/oshun/web/e2e/assistant-handoff-deepening.spec.ts— the continuity spec drives assistant open from library and explore CTAs and from a domain surface, asserting persona switching, voice-identity strip, disclosure strip, memory-scope chip, and thereturn-thread/return-anchorpersistent-context links; the utility-dock spec confirms the dock persists across nav and surfaces correctly at desktop and mobile viewports; the boundary spec asserts the admin-shell context handoff carriesmemory-scope=offand thestudio-operator-copilotpersona with safe-fallback state attributes; the handoff-deepening spec opens the assistant from/library, expands the persona disclosure, switches to the stoic-scholar persona, and asserts the active-persona label updates to "Stoic Research Guide" and that the handoff-state div carriesdata-assistant-persona-handoff-audit-count="1"with an audit-event row whosedata-assistant-persona-handoff-audit-outcome="applied". The handoff-deepening spec also drives the restricted-persona failure mode: an admin-only persona (allowedShells:['admin']) rendersdata-assistant-persona-state="restricted"withdata-assistant-persona-disabled="true"anddisabledin the customer shell, and force-activating it is a no-op (active-persona label unchanged, no new handoff audit row). It also opens the assistant from/profile,/library, and/domains/tara?origin=hometo prove customerpermittedToolGrantsare scoped by active domain: profile exposes onlynavigation.open, library addslibrary.save, and Tara swaps that fordomain.action.execute. The continuity spec also drives the customer memory-off branch over real BFF preferences: it patches/v1/preferencestoassistant.memory.scope='off', waits for the browser preference store to hydrate that remote value, opens the customer assistant from/library, and asserts the real/v1/assistant/sessionscreate payload, BFF continuity response, context handoff chip, disclosure indicator, transcript surface, and first turn all carrymemoryScope='off'. It also selects real browser text containing email / phone / SSN-shaped content before opening the assistant from/explore, then asserts the live session-create payload'scontextHandoff.selectioncontains[redacted-email],[redacted-phone], and[redacted-ssn]without the raw PII. It also opens the browser-visible/explorenull-artifact launch path and asserts the handoff carriesdata-assistant-context-artifact="none"plus the exact "Artifact: no current artifact" chip copy. It now also opens/searchwith a fixed wrong-shell entity preview, asserts the live session-create payload carriesentity: nullplusartifact.metadata.entitySanitization='entity-shell-mismatch', and verifies the browser panel exposesdata-assistant-context-entity="none",data-assistant-context-entity-state="shell-mismatch", and the exact "Entity: removed (shell mismatch)" chip without exposing the dropped admin entity label. It also covers the cross-domain navigation-depth branch by starting on/domains/tara?origin=explore, clicking the browser-visible Veritas domain shortcut, then opening the assistant from the Veritas context strip and asserting the live session-create payload, assistant persistent-context strip, continuity rail copy, and return-thread / return-anchor links preserveorigin=explore&stack=tara. It now also covers the browser-visible profile + notebook Iris recall continuity variant: the test grants real Iris consents, enables profile memory through/v1/preferences, writes profile and notebook memories through/v1/iris/adapter/remember, opens the assistant from a live Nisaba notebook route, verifies the session-create handoff carriesartifact.kind='domain.notebook'andartifact.metadata.notebookId, sends a live assistant message, then asserts both the realresponse.memoryRecallenvelope and the mounted transcript render "Remembered context:", "Profile memory:", "Notebook memory:", and the seeded Tara / Dhammapada recall copy withMemory: profilevisible. It now also drives a live Veritas assistant turn through the real/v1/assistant/sessions/:sessionId/messageroute, asserts the BFF returns a groundedresponse.groundingprojection sourced from Veritas article cards, then clicks the browser-visibleInspect evidenceaction and verifies the shared Veritas inspection overlay names the International Energy Agency source, support count, evidence citations, and source-directory action. Theshell-utility-dockspec now also proves the dock/thread storage boundary in the real customer shell: expanding the desktop dock writesoshun-web-assistant-dock-mode='expanded', collapsing writescollapsed, same-tab reload restores that collapsed mode and the typed transcript fromsessionStorage['oshun-web-assistant-thread'], a second tab inherits only the localStorage dock mode while seeding an independent sessionStorage-backed assistant session, and the original tab's prompt is absent from that second tab's transcript. - Backed by
apps/oshun/web/e2e/assistant-session-bff.spec.ts— step 4's post-condition over REAL HTTP: create a real session (POST /v1/assistant/sessions→ sessionId + authorizedDomains + continuity disclosure), send two messages and assert the engine'sturnCountgrows 1 → 2, and thatGET /v1/assistant/sessionsmirrors the recorded turn count (the "live session exists with the turn count recorded" post-condition the client specs could not assert). It also proves the route-level Iris bridge bootstrap + recall fold over the shared real BFF store: real/v1/preferencesenables assistant profile memory, real/v1/iris/adapter/consentsgrants the Iris side, prior/rememberprofile and notebook facts remain visible in/review,POST /v1/assistant/sessionsreturnsmemory.scope='profile', the first assistant message returns aresponse.memoryRecallenvelope containing both scoped facts, the answer text folds the remembered Tara reset and Nisaba notebook cues into the reply, and the first assistant turn is durably recorded back into the same/v1/iris/adapter/reviewfeed under the live assistant session id. It now also proves the persona recommendation BFF endpoint:GET /v1/assistant/persona-handoffs/recommendationsreturns the canonical customer candidate set for/library, blocks a requested admin-only persona with a fallback handoff, enforces customer domain scope (domain:taracannot request Veritas recommendations), and serves admin-shell candidates only to an admin-scoped bearer while preserving the admin session-only memory boundary. It also proves the mismatched-shell artifact failure mode at the BFF boundary: a valid customer Veritas handoff changes live session continuity (grounding.mode='required',sourceDomain='veritas',recentDomains=['veritas']), while the same customer launch carrying anadmin.review-packageartifact is sanitized out before continuity merge and falls back to the default assistant grounding context. Plus 401 (no bearer), 400 (empty text), 404 (unknown session), 403 (a session does not belong to another user), and DELETE → ended (no longer listed). It also drives the crisis-frame suppression branch:POST /v1/admin/safety/crisis-frame/activatepublishes a real operator frame for the member,GET /v1/safety/crisis-frames/mineconfirms the assistant projection, and a benign assistant message returnscrisis.source='operator-frame',shouldSpeak=false, no cards/actions, andturnCount=0instead of normal synthesis. - Backed by
apps/oshun/web/e2e/assistant-not-entitled-fallback.spec.ts— the downstream not-entitled degradation branch: a 403 (entitlement / authz denial) must degrade HONESTLY, never fabricate. Session-create 403 (real "No domain access" gate, driven by re-issuing to the BFF with aprofile:readbearer) flips thedownstreamsafe-fallback subsystem tofallbackwith a not-entitled reason (distinct from the generic outage copy); a message 403 (real ownership gate) surfaces an honest "isn't available on your current access" notice instead of a fabricatedgenerateSimulatedResponseanswer. This corrects the earlier "403 → safe-fallback is NOT achievable" note — thedownstreamsubsystem is session-error driven. - Coverage depth: deep — see
coverage.md. - Coverage closure notes:
- Step 4's profile-scope and notebook-linked Iris recall fold is now asserted at both the real BFF layer and the browser layer: the mounted assistant transcript now renders the exact profile + notebook "Remembered context" continuity copy after a live Nisaba notebook handoff.
- Mismatched-shell artifact rejection is now real-HTTP covered at the BFF
boundary, and the browser-visible null-artifact copy is covered from
/explore; the browser-visible entity mismatch variant is covered from/searchwith a sanitizedentity: nullpayload and safe mismatch chip; cross-domain navigation depth is covered by the Tara → Veritas browser route with assistant return links preservingorigin=explore&stack=tara. The downstreamPOST /v1/assistant/sessions403 safe-fallback branch is covered byassistant-not-entitled-fallback; operator crisis-frame suppression is covered byassistant-session-bff. - Persistent thread storage scope and dock mode lifecycle are now
browser-covered: sessionStorage restores the same-tab transcript after
reload, does not leak it into a second tab, and localStorage mirrors the
dock
expanded/collapsed/closedlifecycle. - Per-domain customer
permittedToolGrantspolicy enforcement is now covered inShellLayoutunit tests and the real browser assistant-handoff spec. - Persona handoff candidate recommendations are now real-HTTP covered at the BFF boundary for customer, admin, fallback, and authorization-scope branches.
Per-view files touched by this journey#
Assistant is global; entry can be any signed-in surface. Examples:
customer/03-tara/tara.md— Tara hubcustomer/03-tara/tara-sit-id.md— mid-sit invocationcustomer/05-veritas/veritas.md— cross-boundary destinationshell/04-auth-session.md— session + authorization scopingshell/05-notifications.md— proactive follow-ups land here
Cross-references#
- Sibling journeys:
onboarding-ten-steps.mdsetsmemoryScopeand the persona/tone preferences read here;tara-to-nisaba-handoff.mdcovers an adjacent cross-domain bridge that does not use the dock; andcrisis-aware-tone-policy.mdcovers Lilith interception inside the panel - Feature spec:
V1/features.md§ Assistant Experience; § Iris Memory and Identity (recall, scope hierarchy, suppression, conflict resolution) - Component sources:
apps/oshun/web/src/components/assistant-dock/AssistantDock.tsx;apps/oshun/web/src/components/assistant/AssistantPanel.tsx;apps/oshun/web/src/components/ShellPersistentContextStrip.tsx;libs/oshun/shell-assistant/src/context-handoff.ts;libs/oshun/shell-assistant/src/persona-handoffs.ts;libs/oshun/shell-assistant/src/safe-fallbacks.ts - BFF routes:
apps/oshun/bff/src/routes/assistant.ts;apps/oshun/bff/src/routes/assistant-metis-handoff.ts
Open questions / known gaps#
- Exact profile + notebook recall/disclosure copy variant — browser now
proves the mounted transcript renders the real
Remembered context:profile/notebook copy after a Nisaba notebook handoff. The older aspirational "I noticed you were just sitting in…" copy is not the current BFF contract. - Iris recall pipeline endpoint — recall currently runs during the live
message route through
IrisMemoryBridge.recallRelevantMemory; there is no separate browser-visible recall endpoint in the current implementation. - Persistent thread storage scope — sessionStorage under
oshun-web-assistant-thread; verify multi-tab behaviour - Dock mode lifecycle (closed/collapsed/expanded) mirror to
localStorageunderASSISTANT_DOCK_MODE_KEY -
permittedToolGrantsper customer domain —ShellLayoutnow grantsnavigation.openeverywhere, addslibrary.saveonly on save-capable domains, and addsdomain.action.executeonly on action-capable domains; unit and browser tests cover profile, library, and Tara. - Recommendation BFF endpoint for persona handoff candidates — implemented
as
GET /v1/assistant/persona-handoffs/recommendationsand covered by the real-dev-infraassistant-session-bffPlaywright API spec for customer, admin, fallback, and authz-scope branches.