Context. surface customer · domain discovery · route /library · auth signed-in · source apps/oshun/web/src/app/library/page.tsx
Last walked. 2026-06-27 automated coverage reconciliation by Codex — LibraryDashboard component states, collection-management Playwright, saved-items real-BFF sync, cross-device hydrate, share links, offline collection writes, shell-state previews, viewport fit, BFF aggregation contracts, and docs center generation cross-checked.
Purpose#
Everything the user has saved — sits, sources, passages, sky events, courses, assistant excerpts, notebooks, generated artifacts, assessment queues, tutoring threads — kept close in one memory surface, with filter-based and named collections that let one active thread stay together across the six domains.
Entry points#
- Shell nav: Library tab —
WEB_SHELL_ROUTE_PATHS.library; primary shell route - Focal-stage shortcut — Activity and other shell surfaces' "Open Library" card
- Save action from any result — Search results, Explore curated cards, and
domain rooms toggle the same
useOshunWebLibraryStorestore; library shows the same items - Library collection deep link —
/library/collection/<collectionId>lands in the same dashboard with the collection pre-selected (seelibrary-collection-collectionId.md) - Direct URL / bookmark — yes; auth required (relies on shell middleware)
- Shell state preview —
?shellState=<mode>swaps content viaresolveShellRouteSurfaceContent({ surface: 'library' })
Layout regions#
page.tsx mounts ShellLayout with active="library" and breadcrumbs
Home → Library, then renders <LibraryDashboard /> (or the shell-state
preview).
Inside LibraryDashboard:
- Pre-hydration placeholder — when
hasMounted === false, only aShellRouteAnchor("Keep what matters, then return to it deliberately") is rendered witharia-busy="true" - Focal stage —
ShellRouteAnchor(var(--l-warn)accent) +ShellLandingFocalStagewith the current "library frame title", summary metric pills, active return card, collection shortcuts, current posture, and Metis return-surfaces summary - Saved-items cap notice —
LibrarySaveCapNoticerenders the inline Pro paywall when the signed-in free member reaches the 25 real-save cap - Research-to-practice journey rail —
ResearchPracticeJourneyRaildriven byresolveResearchPracticeStageIdFromLibraryFilters - Workspace toolbar —
WorkspaceToolbarwithWorkspaceSegmentRailfilters:- Domain segment rail —
FilterRail<LibraryDomainFilter>(All / Tara / Veritas / Nyx / Arete / Nisaba / Metis) - Kind segment rail —
LIBRARY_KIND_FILTERS(all / meditation / story / claim / source / passage / notebook / collection / program / ritual / sky-event / course / generated-artifact / assessment / tutoring / assistant-excerpt)
- Domain segment rail —
- Saved queue panel —
ShellSavedQueuePanelsupports kind filters, sort modes, snooze, complete, and domain resume links - Collections lane — list of
CollectionCards for both default (LIBRARY_COLLECTIONS) and user-created collections, with editable label / description / followUp when a collection is selected - Create from filters — collection create button in the collections lane; disabled when the current filtered save set is empty
- Filtered saved items list —
LibraryItemcards withLibraryItemSignals(confidence, grounded-evidence, provenance badges), optional retraction notice, resume link, and save toggle - Stats — saved count, distinct domains, study / re-entry kind breakdown
- Support lane (
WorkspaceSupportLane) — docked on wide desktop; collapses on laptop; stacks on tablet/mobile. Contains the top 3 resumeContinuityCards, selected-collection manager, share controls, and the route relationship note.
States#
- Loading (pre-hydration) —
hasMounted === falseshows only the anchor stub witharia-busy="true"and "Loading saved continuity, collections, and the next best return point." Covered byLibraryDashboard.test.tsxvia the server render pass. - Empty saved-items store — empty
libraryItemsshowsdata-library-empty, disables "Create from current filters", renders no resume cards, and keeps default collections at0 items. Covered byLibraryDashboard.test.tsx. - Populated (filters: all/all) — saved items, metric pills, focal stage,
saved queue, collections, continue lane, and trust signals render from the
web store. Covered by
viewport-fit.spec.ts,library-save-collection-share.spec.ts, andLibraryDashboard.test.tsx. - Populated (domain filter active) — frame title and status update from
LIBRARY_DOMAIN_LABELS[domain]; saved rows narrow to that domain andClear filtersappears. Covered bylibrary-collection-management.spec.tsandLibraryDashboard.test.tsx. - Populated (kind filter active) — frame title and rows narrow from
LIBRARY_KIND_LABELS[kind]; typed saves include claim, source, passage, notebook, collection, program, ritual, sky-event, course, generated-artifact, assessment, tutoring, and assistant excerpt. Covered byLibraryDashboard.test.tsx. - Collection selected —
/library/collection/<id>passesinitialCollectionId, swaps the focal frame to collection copy, opens the support-lane manager, and marks the selected collection active. Covered bylibrary-collection-management.spec.ts. - Collection editor — selected collections populate label, description,
and follow-up fields; save writes edited details back to the collection
list. Covered by
library-collection-management.spec.tsandLibraryDashboard.test.tsx. - Stored collections missing / corrupted —
readStoredLibraryCollections()returnsnull; defaults still render and direct default collection links work. Covered bylibrary-collection-management.spec.tsandLibraryDashboard.test.tsx. - Legacy stored collections migrate — payload
version: 0normalizes to version 1, stale item ids are removed, duplicate ids collapse, and the current payload is persisted. Covered bylibrary-collection-management.spec.tsandLibraryDashboard.test.tsx. - Collection storage write — collection edits serialize to
localStorage['oshun.library.collections.v1']once collection hydration completes. Covered bylibrary-collection-management.spec.tsreload assertions andoffline-write-deepening.spec.ts. - Item save toggle —
handleLibraryItemToggleremoves the row, updates the saved-items store, and firestrackLibraryItemUnsavedfrom the library saved-items surface. Covered bylibrary-save-collection-share.spec.ts,library-save-analytics.spec.ts, andLibraryDashboard.test.tsx. - Signed-in saved-items hydrate — signed-in users reconcile from the
per-user BFF saved-items store (
GET /v1/library/saved-items); server saves from another device render on a fresh browser. Covered bylibrary-cross-device-render.spec.tsandlibrary-entitlement-and-save.spec.ts. - Saved-items cap — a free member at 25 real saves sees the inline Pro
paywall at
#library-saved-cap; showcase/demo items do not count. Covered bylibrary-entitlement-and-save.spec.tsandLibraryDashboard.test.tsx. - Reduced motion — route-owned animated trust badges use
disableAnimation; broader shell reduced-motion behavior is covered by PWA/shell animation checks, while Library has no separate motion branch. - Shell state preview —
?shellState=loading|empty|offline|...replaces the live workspace withShellSurfaceStatePreview. Covered byshell-surface-states.spec.ts.
Interactions#
Focal stage#
- Frame title / summary — non-interactive
libraryFrameTitleandlibraryFrameSummary; active filters and selected collections change the copy. Covered byLibraryDashboard.test.tsx. - Metric pills —
ShellLandingMetricPillfor saved count, domains represented, study/source count, and practice/sky/assistant returns. Covered byviewport-fit.spec.tsandLibraryDashboard.test.tsx. - Active return —
data-library-active-return-actionopensbuildLibraryResumeHref(focalReturn.domain, focalReturn.resumePath). Covered through resume-card navigation inlibrary-save-collection-share.spec.tsand component route assertions. - Collection shortcuts — focal rail opens the first collections through
navigateToCollection(collection.id). Covered byLibraryDashboard.test.tsx. - Metis return surfaces — saved course, study queue, and recent tutoring
counts stay distinct; best/queue/recent buttons route to their stored
resume targets. Covered by
LibraryDashboard.test.tsx. - Primary shortcuts — Explore more, Review activity, and Ask assistant
route/dispatch from the hero actions. Assistant launch is covered by
LibraryDashboard.test.tsx; sibling route visibility is covered by route viewport/signoff specs.
Workspace toolbar#
- Domain segment rail (
FilterRail<LibraryDomainFilter>, aria-label "Library domain focus")- Function: sets
domainFilter; updates frame title/summary - Coverage:
library-collection-management.spec.ts,viewport-fit.spec.ts, andLibraryDashboard.test.tsx.
- Function: sets
- Kind segment rail (
FilterRail<LibraryKindFilter>, aria-label "Library save type")- Function: sets
kindFilter - Coverage:
LibraryDashboard.test.tsx.
- Function: sets
- Clear filters (
data-library-filter-reset)- Function: resets
domainFilterandkindFiltertoall - Coverage:
library-collection-management.spec.tsand component tests.
- Function: resets
- Create collection from filters (
handleCreateCollectionFromFilters)- Function: clones the current
filteredItemsinto a new collection with a derived label; navigates to/library/collection/<slug> - Disabled when:
filteredItems.length === 0 - Coverage:
library-collection-management.spec.tsandLibraryDashboard.test.tsx.
- Function: clones the current
Collections lane#
- Collection card click (
CollectionCard) → navigates to/library/collection/<id>viarouter.push(buildLibraryCollectionHref) - Edit label / description / followUp — inputs update
collectionEditor;syncCollectionwrites back tocollections - Add / remove item from collection —
setCollectionItemIdsmutates the collection's item set - Archive collection —
handleArchiveCollection()removes the selected collection when more than one collection exists, deletes its item-id map, and navigates to the next remaining collection - Share controls — visibility, permission, expiry, channel, invite,
referral, private, named-user, and public-profile controls call the real
collection sharing BFF routes. Covered by
collection-share.spec.ts,library-save-collection-share.spec.ts, andlibrary-shared-web-view.spec.ts.
Coverage: collection navigation, create/edit/archive, storage hydration, legacy
migration, corrupted payload fallback, and item membership are covered by
library-collection-management.spec.ts and LibraryDashboard.test.tsx.
Saved queue#
- Queue kind filter / sort mode —
ShellSavedQueuePanelfilters bookmarks, reading list, later saves, tasks, and queue items, then sorts smart/due/resume/domain. Covered bylibrary-save-collection-share.spec.tsandShellSavedQueuePanel.test.tsx. - Snooze / complete — buttons mutate queue status and persist to
localStorage['oshun.shell.saved-queue.v1']. Covered bylibrary-save-collection-share.spec.tsandShellSavedQueuePanel.test.tsx. - Resume — queue resume pushes a hydrated domain route with
queueItemandqueueKindparams. Covered bylibrary-save-collection-share.spec.ts.
Priority resume rail#
- Top 3 resume cards (
ContinuityCard) — openbuildLibraryResumeHref(domain root +?path=...). Covered bylibrary-save-collection-share.spec.tsandLibraryDashboard.test.tsx.
Research-to-practice rail#
-
ResearchPracticeJourneyRail— stage derived from current filters (resolveResearchPracticeStageIdFromLibraryFilters); route actions open their hrefs and assistant actions dispatch the assistant entry event. Covered byResearchPracticeJourneyRail.test.tsxandLibraryDashboard.test.tsx.
Saved item row#
- Open — resume button pushes
buildLibraryResumeHref(item.domain, item.resumePath). - Ask assistant — per-row assistant button dispatches
dispatchOshunAssistantOpen({ source: "library:<item.id>" }). - Save toggle —
handleLibraryItemToggle(item)flips persistence;trackLibraryItemUnsavedanalytics on removal - Signal badges (
ConfidenceBadge,LibraryGroundingBadge,ProvenanceBadge) — non-interactive trust indicators - Retraction notice — affected saved claims show corrected-source,
remove, and appeal/correct actions. Covered by
LibraryDashboard.test.tsx.
Coverage: row removal, telemetry, trust badges, retraction actions, and notebook
card rendering are covered by library-save-analytics.spec.ts,
library-save-collection-share.spec.ts, and LibraryDashboard.test.tsx.
Metis surfaces summary#
- Best resume / queued item / recent session cards — open their stored
resume targets and keep saved courses, assessment queue, and tutoring
sessions as separate counts. Covered by
LibraryDashboard.test.tsxand BFF Metis-scoped aggregation inlibrary-route.test.ts.
Assistant entry#
- Assistant launchers within cards — call
dispatchOshunAssistantOpen(...)to surface the in-app assistant. Covered byLibraryDashboard.test.tsxand assistant save telemetry inlibrary-save-analytics.spec.ts.
Data & contracts#
- Reads:
useOshunWebLibraryStore()(client store; see@/lib/library/webLibraryStore) — returns{ items: WebLibrarySavedItem[] }GET /v1/library/saved-itemsviacreateSavedItemsClient().getSnapshot()for signed-in users; rows map throughcontractItemToWebItemDEFAULT_WEB_LIBRARY_ITEMS— guest/offline showcase bootstrap data shapelocalStorage['oshun.library.collections.v1']— persisted user collections payload (StoredLibraryCollectionsPayload)localStorage['oshun.shell.saved-queue.v1']— saved queue status, snooze, and completion state
- Writes:
toggleOshunWebLibraryItem(item)— local optimistic save/unsave; authenticated real saves callPOST/DELETE /v1/library/saved-items/:domain/:idin the backgroundPUT /v1/library/saved-items/sync— pending anonymous saves migrate after sign-inlocalStorage.setItem(LIBRARY_COLLECTION_STORAGE_KEY, …)— serialized collection statelocalStorage.setItem('oshun.shell.saved-queue.v1', …)— serialized queue statePOST/PUT/DELETE /v1/library/collections/:collectionId/share...— tokenized collection links, visibility, and revocation
- Realtime: None.
- Caching: client store + localStorage; signed-in server sync is fail-soft and retried on later hydration/profile changes
- Auth/role check: shell middleware
- Telemetry:
trackLibraryItemUnsaved; cross-surface save telemetry also recordsitem_saved/item_unsavedfrom Explore, Search, Library, and assistant-message surfaces
Automated coverage#
apps/oshun/web/src/components/library/__tests__/LibraryDashboard.test.tsx— empty/pre-hydration states, filters, collection editor, corrupted/legacy collection payloads, trust/retraction signals, Metis surfaces, assistant launcher, save-cap notice, and unsave telemetry.apps/oshun/web/e2e/library-collection-management.spec.ts— direct collection links, unknown-id fallback with query filters, stored/legacy collection hydration, create/edit/archive, and desktop/laptop support lane.apps/oshun/web/e2e/library-save-collection-share.spec.ts— continue cards, saved queue, sharing-control presence, row unsave, and anonymous-to-signed-in saved-item migration.apps/oshun/web/e2e/collection-share.spec.tsandapps/oshun/web/e2e/library-shared-web-view.spec.ts— real BFF collection share creation, visibility, revoke/private paths, and recipient rendering.apps/oshun/web/e2e/library-cross-device-render.spec.tsandapps/oshun/web/e2e/library-entitlement-and-save.spec.ts— real saved-items BFF sync, cross-device read, tombstone propagation, cap paywall, and aggregate/v1/librarycontracts.apps/oshun/web/e2e/offline-write-deepening.spec.ts— collection membership edits persist locally while offline.apps/oshun/web/e2e/viewport-fit.spec.tsandapps/oshun/web/e2e/shell-surface-states.spec.ts— Library layout fit and?shellState=preview modes.apps/oshun/bff/src/__tests__/library-route.test.ts— BFF aggregation, domain filtering, Metis-scoped items, partial failure headers, and trace metadata.
Cross-references#
- Shell:
shell/01-app-shell.md - Sibling routes:
library-collection-collectionId.md— collection-focused entryhome.md,explore.md,activity.md,search.md
- Component sources:
apps/oshun/web/src/components/library/LibraryDashboard.tsxapps/oshun/web/src/components/library/libraryModels.tsapps/oshun/web/src/components/library/librarySavedItems.tsapps/oshun/web/src/components/library/ResearchPracticeJourneyRail.tsxapps/oshun/web/src/lib/library/webLibraryStore.ts
- Feature spec:
V1/features.md - Architecture:
V1/ARCHITECTURE.md
Open questions / known gaps#
- Resolved: signed-in saved items hydrate from
/v1/library/saved-items, not only local client state. - Resolved: collection payload
version: 0migrates toLIBRARY_COLLECTION_STORAGE_VERSION(1), sanitizing stale/duplicate item ids. - Resolved: the UI affordance is Archive collection; it removes whichever collection is currently selected when more than one collection exists.
- Residual manual pass: live screen-reader/touch review for the full Library page remains useful, but automated component, Playwright, BFF, offline, viewport, and shell-state coverage is in place.