V1 Web PWA · Surface walkthrough

Story Workspace · Veritas (fixed story)

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
9sections6 minread

On this page

Context. surface customer · domain veritas · route /domains/veritas/story · auth signed-in · source apps/oshun/web/src/app/domains/veritas/story/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md 2026-06-28 Codex addendum — expanded apps/oshun/web/e2e/veritas-story-workspace.spec.ts against real dev infra to cover canonical/direct story rendering, shell hydration, Library save toggle, Back, evidence/source/Sophia inspections, assistant pre-inspection buttons, claim/source/topic/Nisaba/Tara/Arete/Metis handoffs, unknown id fallback, standalone PWA relaunch, offline mobile interaction, and horizontal-overflow checks.

Purpose#

The Veritas Story Workspace for a fixed canonical story (storyId="story-renewables-capacity"). Functionally identical to the dynamic /domains/veritas/story/[id] route — same component, same rendering — but pinned to the renewables-capacity story for direct linking, demos, and the /d/... cross-domain handoffs that target a specific story.

Entry points#

  • Direct URL / bookmark — yes (auth required); this is the entry path for the demo story
  • /domains/veritas index — verify the internal-namespace tool grid
  • Linked from /explore — the demo story is a stable address for cards
  • Cross-domain handoff — Metis explainer flow, Nisaba source-lineage trail, Tara metabolization handoffs, and Arete next-actions all originate from this workspace and may also link back to it

Layout regions#

page.tsx is a 'use client' component:

tsx
<VeritasStoryWorkspace
  storyId="story-renewables-capacity"
  onClose={() => router.back()}
  origin="explore"
/>

VeritasStoryWorkspace renders inline (not a fixed overlay). Layout (anchored to data-veritas-story-* attributes):

  • Top toolbar: back button, Library save toggle (handleStorySaveToggle), navigation chips to claim trail / source directory / RAG assistant
  • Hero (aria-labelledby="veritas-story-title", data-veritas-story-headline=""): eyebrow "Story workspace", STORY.headline (clamp 2rem–3.6rem), STORY.dek, STORY_SIGNALS pills
  • Correction notes (data-veritas-story-correction-notes): one card per STORY_CORRECTION_NOTICES showing prior vs corrected text with audience and visibility pills
  • Retraction notices (data-veritas-story-retraction-notices): list of retraction cards with their notice text
  • Editorial frame: SectionTitle "What is settled, what is still open, and why the distinction matters" + 3 articles (Settled / Still open / Reader job)
  • Claim detail lane (data-veritas-story-claim-detail-lane): SectionTitle + two claim cards (data-veritas-story-claim-card="primary" and ="open-question") with Open claim detail links to /domains/veritas/claims/<objectId>; below, Counterclaims attached to this story list (data-veritas-story-counterclaims)
  • Source inspection (data-veritas-story-source-inspection): per STORY_SOURCES, a card with Inspect source button (opens overlay) and Open source lane link
  • Evidence trail: per PRIMARY_CLAIM.evidence[] — article cards with stance pill, source-kind/date/strength meta, and Inspect evidence button
  • Metis study continuity: link-out cards for the Metis explainer flow, lesson, mastery quiz, and study pack
  • Multi-section assistant explainers: explainer cards driven by buildVeritasStoryAssistantExplainers; each has a primary action that dispatches dispatchOshunAssistantOpen({ source, prompt })
  • Metabolize this information: Tara metabolization handoffs (buildVeritasTaraMetabolizationSuggestions) — cards with bridge label, title, summary, signals, link
  • Arete next action: buildVeritasAreteNextActions cards
  • Reading stance: closing aside with three guidance lines (Settled / Open / Assistant)
  • Right aside (EvidenceSidebar block around line 2132): evidence-side rail mirroring the trail
  • VeritasInspectionOverlay — opened by inspect buttons

States#

  • Loading — workspace renders synchronously from imports; no fetch
  • Populated — fixed story always populates fully
  • Library: saved / unsavedstorySaved toggles via useOshunWebLibraryStore
  • Has open question — when OPEN_QUESTION != null, the "Still open" panel and the open-question claim card render
  • Has correction noticesSTORY_CORRECTION_NOTICES.length > 0 gates the correction-notes section
  • Has retraction noticesSTORY_RETRACTION_NOTICES.length > 0 gates the retraction-notices section
  • Inspection openactiveInspection !== null shows the VeritasInspectionOverlay
  • Offline — workspace uses imported canonical data, no fetch
  • Standalone PWA — verify the wide multi-section grid collapses on narrow widths
  • Reduced motion — verified under the suite-wide reduced-motion Playwright fixture; no explicit story-workspace animations are present

Interactions#

Top toolbar#

  • Back — invokes onClose()router.back()
  • Library save togglehandleStorySaveToggle toggles in useOshunWebLibraryStore; fires trackLibraryItemSaved / trackLibraryItemUnsaved with domain: 'veritas', itemId: STORY.objectId, source: origin, surface: 'panel', targetPath: storyHref

Claim cards#

  • Open claim detail (Link, data-veritas-story-claim-detail-action="primary" / "open-question")
    • Function: navigates to buildDomainShellHref('veritas', '/claims/<objectId>', origin, veritasStack) — see /domains/veritas/claims/[claimId]

Source inspection#

  • Inspect source (button, data-veritas-story-inspect-source={sourceId})
    • Function: handleSourceInspection(sourceId) opens VeritasInspectionOverlay with source-specific model and fires trackVeritasInspectionOpened({ workspace: 'story', kind: 'source', itemId, source: origin })
  • Open source lane (link, data-veritas-story-source-action={sourceId})
    • Function: navigates to buildDomainShellHref('veritas', source.hrefPath, …)

Evidence trail#

  • Inspect evidence (button, data-veritas-story-inspect-evidence={evidenceId})
    • Function: handleEvidenceInspection(evidenceId) opens overlay with the evidence model

Assistant explainers#

  • Explainer action (button, data-veritas-story-assistant-explainer-action={explainerId})
    • Function: dispatchOshunAssistantOpen({ source, prompt }) opens the in-app assistant; does not navigate

Cross-domain handoff cards#

  • Tara metabolization (Link, data-veritas-story-tara-action={suggestionId})
    • Function: navigates to buildDomainShellHref('tara', …)
  • Arete next action (Link, data-veritas-story-arete-action={recommendationId})
    • Function: navigates to buildDomainShellHref('arete', …)
  • Metis explainer / lesson / mastery quiz / study pack (Links)
    • Function: navigates to buildDomainShellHref('metis', …) with the relevant relationship target path
  • Nisaba source-lineage trail (Link inside inspection-overlay actions)
    • Function: navigates to buildDomainShellHref('nisaba', …)

Current E2E Evidence#

apps/oshun/web/e2e/veritas-story-workspace.spec.ts now exercises this route through seven real-dev-infra Playwright tests:

  • renders the direct story page with evidence and source-lineage context — direct route, canonical route-state data hooks, save toggle, Back to Library, correction/retraction/open-question sections, source/evidence/Sophia inspections, and assistant pre-inspection buttons.
  • hydrates through the shell and preserves story workspace navigation — shell query hydration, assistant opening with Veritas source context, and source-directory follow-up.
  • routes the story into a Metis grounded explainer with source targets — Metis handoff URL, story/claim/source target propagation, and ref propagation.
  • uses story evidence inspection to hand off into source and Sophia evidence lanes — evidence-overlay action routing to source directory and Sophia evidence-pack route.
  • routes claim, source, topic, and cross-domain handoffs from the story — open-question claim detail, source lane, topic hub, Nisaba source-lineage, Tara, and Arete links.
  • documents the unknown-id fallback while preserving the requested story route — dynamic route fallback is explicit via requested/canonical id hooks.
  • restores standalone, remains usable offline on mobile, and avoids horizontal overflow — PWA relaunch, offline save/inspection, keyboard/touch-capable controls, and mobile overflow guard.

Data & contracts#

  • Reads (imported): STORY, STORY_SIGNALS, STORY_CORRECTION_NOTICES, STORY_RETRACTION_NOTICES, PRIMARY_CLAIM, OPEN_QUESTION, OPEN_QUESTION_CLAIM, STORY_SOURCES, STORY_COUNTERCLAIMS, EVIDENCE_STATUS, TRUST_RULE, VERITAS_STORY_SOPHIA_EVIDENCE_BUNDLES, STORY_ASSISTANT_SOURCE_INSPECTION_TARGETS, STORY_TOPIC (canonical fixtures)
  • Domain helpers: buildVeritasTaraMetabolizationSuggestions, buildVeritasAreteNextActions, buildVeritasStoryAssistantExplainers, buildVeritasStoryLibraryItem, plus the resolvers used by the claim detail workspace
  • Cross-domain stacks: buildCrossDomainStack('veritas', stack) for Nisaba / Metis / Tara / Arete handoffs
  • Library store: useOshunWebLibraryStore, toggleOshunWebLibraryItem
  • Telemetry:
    • trackLibraryItemSaved, trackLibraryItemUnsaved
    • trackVeritasInspectionOpened
    • Assistant dispatch: dispatchOshunAssistantOpen
  • Realtime: none
  • Caching: imported canonical data (static at build time)
  • Auth/role check: shell middleware (verify)
  • Page metadata: not set (client component)

Cross-references#

Open questions / known gaps#

  • storyId is hard-pinned to story-renewables-capacity; the workspace itself uses STORY (an imported canonical) regardless of the prop, because the data is static. The dynamic route now exposes requested/canonical id hooks so this static-fallback behavior is visible and covered.
  • No sr-only <h1> wrapper in page.tsx (unlike the tool overlays); the workspace's hero <h1> provides the page title and is visible in E2E assertions
  • Confirm whether V1 plans to swap the imported STORY fixture for a data fetch (otherwise this is functionally a static demo page)
  • No telemetry on Metis / Tara / Arete handoff clicks
  • Same Library/Explore nav inconsistency considered — note this workspace does not use LCustomerNav at all; it renders inline content