---
path: /library
surface: customer
domain: discovery
auth: signed-in
source: apps/oshun/web/src/app/library/page.tsx
status: walked
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.'
---

# Library

## 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 `useOshunWebLibraryStore` store; library shows
  the same items
- **Library collection deep link** — `/library/collection/<collectionId>` lands
  in the same dashboard with the collection pre-selected (see
  [`library-collection-collectionId.md`](./library-collection-collectionId.md))
- **Direct URL / bookmark** — yes; auth required (relies on shell middleware)
- **Shell state preview** — `?shellState=<mode>` swaps content via
  `resolveShellRouteSurfaceContent({ 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 a
  `ShellRouteAnchor` ("Keep what matters, then return to it deliberately") is
  rendered with `aria-busy="true"`
- **Focal stage** — `ShellRouteAnchor` (`var(--l-warn)` accent) +
  `ShellLandingFocalStage` with the current "library frame title", summary
  metric pills, active return card, collection shortcuts, current posture, and
  Metis return-surfaces summary
- **Saved-items cap notice** — `LibrarySaveCapNotice` renders the inline Pro
  paywall when the signed-in free member reaches the 25 real-save cap
- **Research-to-practice journey rail** — `ResearchPracticeJourneyRail` driven
  by `resolveResearchPracticeStageIdFromLibraryFilters`
- **Workspace toolbar** — `WorkspaceToolbar` with `WorkspaceSegmentRail`
  filters:
  - **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)
- **Saved queue panel** — `ShellSavedQueuePanel` supports kind filters, sort
  modes, snooze, complete, and domain resume links
- **Collections lane** — list of `CollectionCard`s 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** — `LibraryItem` cards with `LibraryItemSignals`
  (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 resume
  `ContinuityCard`s, selected-collection manager, share controls, and the route
  relationship note.

## States

- [x] **Loading (pre-hydration)** — `hasMounted === false` shows only the anchor
      stub with `aria-busy="true"` and "Loading saved continuity, collections,
      and the next best return point." Covered by `LibraryDashboard.test.tsx`
      via the server render pass.
- [x] **Empty saved-items store** — empty `libraryItems` shows
      `data-library-empty`, disables "Create from current filters", renders no
      resume cards, and keeps default collections at `0 items`. Covered by
      `LibraryDashboard.test.tsx`.
- [x] **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`, and `LibraryDashboard.test.tsx`.
- [x] **Populated (domain filter active)** — frame title and status update from
      `LIBRARY_DOMAIN_LABELS[domain]`; saved rows narrow to that domain and
      `Clear filters` appears. Covered by
      `library-collection-management.spec.ts` and `LibraryDashboard.test.tsx`.
- [x] **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
      by `LibraryDashboard.test.tsx`.
- [x] **Collection selected** — `/library/collection/<id>` passes
      `initialCollectionId`, swaps the focal frame to collection copy, opens the
      support-lane manager, and marks the selected collection active. Covered by
      `library-collection-management.spec.ts`.
- [x] **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.ts` and
      `LibraryDashboard.test.tsx`.
- [x] **Stored collections missing / corrupted** —
      `readStoredLibraryCollections()` returns `null`; defaults still render and
      direct default collection links work. Covered by
      `library-collection-management.spec.ts` and `LibraryDashboard.test.tsx`.
- [x] **Legacy stored collections migrate** — payload `version: 0` normalizes to
      version 1, stale item ids are removed, duplicate ids collapse, and the
      current payload is persisted. Covered by
      `library-collection-management.spec.ts` and `LibraryDashboard.test.tsx`.
- [x] **Collection storage write** — collection edits serialize to
      `localStorage['oshun.library.collections.v1']` once collection hydration
      completes. Covered by `library-collection-management.spec.ts` reload
      assertions and `offline-write-deepening.spec.ts`.
- [x] **Item save toggle** — `handleLibraryItemToggle` removes the row, updates
      the saved-items store, and fires `trackLibraryItemUnsaved` from the
      library saved-items surface. Covered by
      `library-save-collection-share.spec.ts`, `library-save-analytics.spec.ts`,
      and `LibraryDashboard.test.tsx`.
- [x] **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 by
      `library-cross-device-render.spec.ts` and
      `library-entitlement-and-save.spec.ts`.
- [x] **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
      by `library-entitlement-and-save.spec.ts` and `LibraryDashboard.test.tsx`.
- [x] **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.
- [x] **Shell state preview** — `?shellState=loading|empty|offline|...` replaces
      the live workspace with `ShellSurfaceStatePreview`. Covered by
      `shell-surface-states.spec.ts`.

## Interactions

### Focal stage

- [x] **Frame title / summary** — non-interactive `libraryFrameTitle` and
      `libraryFrameSummary`; active filters and selected collections change the
      copy. Covered by `LibraryDashboard.test.tsx`.
- [x] **Metric pills** — `ShellLandingMetricPill` for saved count, domains
      represented, study/source count, and practice/sky/assistant returns.
      Covered by `viewport-fit.spec.ts` and `LibraryDashboard.test.tsx`.
- [x] **Active return** — `data-library-active-return-action` opens
      `buildLibraryResumeHref(focalReturn.domain, focalReturn.resumePath)`.
      Covered through resume-card navigation in
      `library-save-collection-share.spec.ts` and component route assertions.
- [x] **Collection shortcuts** — focal rail opens the first collections through
      `navigateToCollection(collection.id)`. Covered by
      `LibraryDashboard.test.tsx`.
- [x] **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`.
- [x] **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

- [x] **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`,
    and `LibraryDashboard.test.tsx`.
- [x] **Kind segment rail** (`FilterRail<LibraryKindFilter>`, aria-label
      "Library save type")
  - Function: sets `kindFilter`
  - Coverage: `LibraryDashboard.test.tsx`.
- [x] **Clear filters** (`data-library-filter-reset`)
  - Function: resets `domainFilter` and `kindFilter` to `all`
  - Coverage: `library-collection-management.spec.ts` and component tests.
- [x] **Create collection from filters** (`handleCreateCollectionFromFilters`)
  - Function: clones the current `filteredItems` into a new collection with a
    derived label; navigates to `/library/collection/<slug>`
  - Disabled when: `filteredItems.length === 0`
  - Coverage: `library-collection-management.spec.ts` and
    `LibraryDashboard.test.tsx`.

### Collections lane

- [x] **Collection card click** (`CollectionCard`) → navigates to
      `/library/collection/<id>` via `router.push(buildLibraryCollectionHref)`
- [x] **Edit label / description / followUp** — inputs update
      `collectionEditor`; `syncCollection` writes back to `collections`
- [x] **Add / remove item from collection** — `setCollectionItemIds` mutates the
      collection's item set
- [x] **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
- [x] **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`, and
      `library-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

- [x] **Queue kind filter / sort mode** — `ShellSavedQueuePanel` filters
      bookmarks, reading list, later saves, tasks, and queue items, then sorts
      smart/due/resume/domain. Covered by
      `library-save-collection-share.spec.ts` and
      `ShellSavedQueuePanel.test.tsx`.
- [x] **Snooze / complete** — buttons mutate queue status and persist to
      `localStorage['oshun.shell.saved-queue.v1']`. Covered by
      `library-save-collection-share.spec.ts` and
      `ShellSavedQueuePanel.test.tsx`.
- [x] **Resume** — queue resume pushes a hydrated domain route with `queueItem`
      and `queueKind` params. Covered by
      `library-save-collection-share.spec.ts`.

### Priority resume rail

- [x] **Top 3 resume cards** (`ContinuityCard`) — open `buildLibraryResumeHref`
      (domain root + `?path=...`). Covered by
      `library-save-collection-share.spec.ts` and `LibraryDashboard.test.tsx`.

### Research-to-practice rail

- [x] **`ResearchPracticeJourneyRail`** — stage derived from current filters
      (`resolveResearchPracticeStageIdFromLibraryFilters`); route actions open
      their hrefs and assistant actions dispatch the assistant entry event.
      Covered by `ResearchPracticeJourneyRail.test.tsx` and
      `LibraryDashboard.test.tsx`.

### Saved item row

- [x] **Open** — resume button pushes
      `buildLibraryResumeHref(item.domain, item.resumePath)`.
- [x] **Ask assistant** — per-row assistant button dispatches
      `dispatchOshunAssistantOpen({ source: "library:<item.id>" })`.
- [x] **Save toggle** — `handleLibraryItemToggle(item)` flips persistence;
      `trackLibraryItemUnsaved` analytics on removal
- [x] **Signal badges** (`ConfidenceBadge`, `LibraryGroundingBadge`,
      `ProvenanceBadge`) — non-interactive trust indicators
- [x] **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

- [x] **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.tsx` and
      BFF Metis-scoped aggregation in `library-route.test.ts`.

### Assistant entry

- [x] **Assistant launchers** within cards — call
      `dispatchOshunAssistantOpen(...)` to surface the in-app assistant. Covered
      by `LibraryDashboard.test.tsx` and assistant save telemetry in
      `library-save-analytics.spec.ts`.

## Data & contracts

- **Reads**:
  - `useOshunWebLibraryStore()` (client store; see
    `@/lib/library/webLibraryStore`) — returns
    `{ items: WebLibrarySavedItem[] }`
  - `GET /v1/library/saved-items` via `createSavedItemsClient().getSnapshot()`
    for signed-in users; rows map through `contractItemToWebItem`
  - `DEFAULT_WEB_LIBRARY_ITEMS` — guest/offline showcase bootstrap data shape
  - `localStorage['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 call
    `POST/DELETE /v1/library/saved-items/:domain/:id` in the background
  - `PUT /v1/library/saved-items/sync` — pending anonymous saves migrate after
    sign-in
  - `localStorage.setItem(LIBRARY_COLLECTION_STORAGE_KEY, …)` — serialized
    collection state
  - `localStorage.setItem('oshun.shell.saved-queue.v1', …)` — serialized queue
    state
  - `POST/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
  records `item_saved` / `item_unsaved` from 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.ts` and
  `apps/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.ts` and
  `apps/oshun/web/e2e/library-entitlement-and-save.spec.ts` — real saved-items
  BFF sync, cross-device read, tombstone propagation, cap paywall, and aggregate
  `/v1/library` contracts.
- `apps/oshun/web/e2e/offline-write-deepening.spec.ts` — collection membership
  edits persist locally while offline.
- `apps/oshun/web/e2e/viewport-fit.spec.ts` and
  `apps/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`](../../shell/01-app-shell.md)
- Sibling routes:
  - [`library-collection-collectionId.md`](./library-collection-collectionId.md)
    — collection-focused entry
  - [`home.md`](./home.md), [`explore.md`](./explore.md),
    [`activity.md`](./activity.md), [`search.md`](./search.md)
- Component sources:
  - `apps/oshun/web/src/components/library/LibraryDashboard.tsx`
  - `apps/oshun/web/src/components/library/libraryModels.ts`
  - `apps/oshun/web/src/components/library/librarySavedItems.ts`
  - `apps/oshun/web/src/components/library/ResearchPracticeJourneyRail.tsx`
  - `apps/oshun/web/src/lib/library/webLibraryStore.ts`
- Feature spec: [`V1/features.md`](../../../V1/features.md)
- Architecture: [`V1/ARCHITECTURE.md`](../../../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: 0` migrates to
  `LIBRARY_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.
