- Walked: 2026-05-29 at
9455bc53ad. The retained result cited an ephemeral/tmp/claude-oshun-lt-2-walkthrough/walk.mjs, saw/nisabaand/nisaba/scholarheadings, and confirmed that scholar, lexicon, and graph routes returned200. It retained no script, trace, account, selected passage id, annotation, notebook write, plan write, cache entry, or read-back. - Reconciled: 2026-08-21 against the real universal-search route and seed, shell launch resolver, parameterized Nisaba passage workspace, authenticated compact-room route and server component, room view-model, passage actions, legacy depth fixtures, local study stores, service-worker policy, six focused unit/source suites, and both named Playwright files. The documented re-run below is a focused repository and Docs Center verification, not a production account, deployed browser, shared-device, or cross-device exercise.
- Verdict: partial / deep for the separated shipped surfaces — search can open the real Epictetus passage in the live BFF-backed workspace; the compact room renders the daily Dhammapada passage with its matching annotation count; and the legacy pages expose substantial static scholarly specimens. They are not one scholarly-read transaction. The compact room still saves under the legacy Marcus id, while the depth pages use that Marcus Aurelius composition with display-only controls.
- Current authority:
WALKTHROUGH/journeys/nisaba-scholarly-read.mdnow names the three passage identities, the real versus assisted browser seams, and the server, local, fixture, and offline-cache boundaries.
Result at a glance#
| Interaction | Proof · limit |
|---|---|
| Historical walk | Proof: the compact desk and three depth routes rendered, the desk had an h1, and language controls were later wired. Limit: route reachability did not preserve a selected passage, click a toolbar action, create a notebook item, add a plan, or establish continuity among the pages. |
| Search result | Proof: the real /v1/search response supplies the nisaba-passage-speech seed and its /library/passage/nisaba-passage-speech target. Search launch wraps that target into /domains/nisaba?...path=..., and the named browser case opens the parameterized workspace. Limit: its browser search client has no in-memory token in this harness; the spec intercepts the GET, reissues it to the real BFF with a generated dev bearer, and fulfills with that response. This proves ranking and launch against a real response, but not the unassisted browser-auth seam. |
| Live workspace | Proof: the requested-passage hook fetches /v1/nisaba/passages/nisaba-passage-speech; the browser asserts On Guarded Speech, Enchiridion XXXIII, primary text, study signals, quick actions, and twelve reading-action affordances. Limit: the named journey asserts their presence, not annotation creation, notebook capture, study-plan creation, persistence, reload read-back, or offline replay. Those behaviors belong to other Nisaba suites and authorities. |
Compact /nisaba room |
Proof: the server component forwards the oshun-access cookie as a bearer, reads /v1/nisaba/room, and renders an honest unavailable state for null or malformed data. The authorized route builds the room from the current daily passage: Mind Precedes All States, Dhammapada I.1–2, its English body, related concept, and compare targets. Limit: it is a daily-passage resolver, not the search-selected Epictetus workspace. |
| Room annotation count | Proof: the route reads the owner-scoped annotation list for the daily passage and passes that same passage into the room builder. The visible title, body, and Annotations count are now identity-aligned. Limit: Cross-references: 4 and Saved excerpts: 2 remain authored constants rather than computed totals. |
| Compact passage actions | Proof: Save writes a browser Library item; Read aloud uses speechSynthesis; flagging passes through the trust-and-safety control. Limit: all three receive the hard-coded id nisaba-on-the-ruling-part while the visible title and citation come from the daily Dhammapada passage. A save can therefore display the Buddhist title while resuming /library/passage/nisaba-on-the-ruling-part. |
| Language and sections | Proof: the room exposes only the language carried by the daily passage, so the seeded English record no longer advertises unavailable Pali or side-by-side text. Limit: the fixed footer section controls still link to #section-I and #section-III even though a dynamic passage has no authored section apparatus or persisted reading position. |
| Legacy scholar chain | Proof: scholar, lexicon, manuscript, notebook, and plan routes render a detailed Marcus Aurelius / hēgemonikon specimen; the named browser case checks apparatus, witnesses, lexicon anatomy, folio anatomy, no-index notebook metadata, the seven-week arc, and browser Back. Limit: all five read nisaba-depth.ts fixtures. Reader mode, Edition, and Cite have no handler or destination; lexicon arrows are text; the notebook is Renata K.'s display-only composition; and the plan has no completion control. |
| Legacy privacy | Proof: the fixture notebook emits noindex, nofollow and presents private to you copy. Limit: it accepts no notebook id or subject and performs no authorization check. Robots metadata governs discovery, not access. |
| Offline continuity | Proof: daily-passage and notebook-list responses have 24-hour localStorage snapshots; the service worker separately stale-while-revalidates exactly /v1/nisaba/passages/daily and /v1/nisaba/notebooks, refuses expired cache while offline, and purges member caches on the normal session-clear path. Limit: Cache API and localStorage keys are URL/status scoped, not member scoped. Correct isolation relies on the session marker and purge; requested passage detail, room, annotations, manuscript, and legacy pages are outside the API allowlist. |
| Named automation | Proof: nisaba-scholarly-read.spec.ts has 11 browser cases and nisaba-desk-deepening.spec.ts has five real-HTTP room cases. Unit coverage separately pins the room builder, SSR ready/unavailable paths, language switching, browser Library action, offline snapshots, hook hydration, and service-worker expiry policy. Limit: the 16 named browser/API cases are surface and contract evidence distributed across distinct passages; they do not execute one search → read → annotate → notebook → plan → reload chain. |
Evidence map#
Solid arrows show a real handoff within one surface. Dashed arrows mark where a label, action id, navigation, or cache crosses into another passage or authority. The three titles are deliberately visible: treating them as one record was the central error in the historical pass.
flowchart TB
J[Nisaba scholarly read] --> S[Real search response]
J --> C[Compact /nisaba]
S --> W[Live workspace<br/>Epictetus · Enchiridion XXXIII]
D[Daily passage authority<br/>Dhammapada I.1–2] --> C[Compact /nisaba room]
C -. hard-coded save and flag id .-> A[nisaba-on-the-ruling-part]
C --> L[Legacy route navigation]
L --> M[Static depth fixtures<br/>Marcus Aurelius · Meditations IV]
M --> N[Display-only Renata notebook<br/>and seven-week plan]
W -. no selected-passage handoff .-> C
Proven observations#
The historical pass proved repaired routes, not a scholarly lifecycle#
- The old result was right that
/nisaba/passage/samplewas a walker-invented path rather than a broken product link. It was also right that the desk gained a real heading and that its language chips became buttons. - Its
passverdict then promoted route render and link reachability into a journey outcome. Nothing retained from that walk connected the search result to the compact room, the room to the scholar text, the scholar text to the Renata notebook, or the notebook to the plan. - The current source provides stronger positive evidence for every independent page. It simultaneously shows why the joined claim remains partial.
Search reaches a real parameterized passage, through an assisted auth seam#
- Universal search has a concrete
nisaba-passage-speechseed with title On Guarded Speech, reference Enchiridion XXXIII, public-domain source attribution, excerpt, and target path. The generic result launcher preserves that path as the domain shell's encodedpathparameter. NisabaSurfaceresolves the path, compares it with the daily id, callsuseNisabaPassage(requestedPassageId), and uses the returned passage when the id matches. That is a real detail-resolution path rather than a client-only title substitution.- The named test's session route does not populate the search component's
in-memory API token.
forwardSearchWithAuththerefore intercepts only the main/v1/searchGET, calls the real BFF with a ten-minute dev bearer, and forwards its status and body. Assertions on the real Nisaba result and its launch are valuable, but the result must not call that an unassisted production-browser request. - After launch, the test checks the workspace anatomy and twelve action affordances. It never operates those annotation, notebook, collection, study-plan, citation, or scholar controls, so their presence is not a write.
The compact room now follows the daily passage, with one action-id seam#
bffGetnow correctly awaits Next's cookie jar and forwardsoshun-accessasAuthorization: Bearer; authenticated responses useno-store. The stale comment innisaba-desk-deepening.spec.tsthat claims cookie forwarding is infeasible predates that implementation. The current named journey plants the access cookie and can render the live room.getRoomHandlerasksgetDailyPassage(userId), lists annotations for that passage id, obtains its compare context, and passes the daily title, reference, source, language, body, concepts, and compare targets tobuildNisabaRoom. The seeded room is therefore Mind Precedes All States, Dhammapada I.1–2, and its annotation count belongs to the visible passage.- The builder derives paragraphs, a concept layout, and related compare rows
from that record. It exposes only the record's available language and omits
the curated SN 22.59 section apparatus. Cross-references
4and saved excerpts2remain authored marginalia constants. - The footer retains one identity error.
NisabaPassageActionsreceives the visible daily title and citation but a constantnisaba-on-the-ruling-partid. Its unit test proves that exact id becomes the Library resume path. The resulting row can therefore combine one passage's id with another passage's title and citation. - Read aloud gathers up to 4,000 characters from
main prather than carrying a canonical passage body and edition id. It is a convenience playback of rendered prose, not a source-pinned audio artifact.
Language and section controls are intentionally narrow#
- The builder exposes only the source record's language, so the seeded English passage has one truthful language button instead of ineffective Pali and Both choices. No language preference is written to a URL or durable store.
- Dynamic daily passages have no fabricated section list. The shared reading
footer still links to
#section-Iand#section-III, however, so those hashes are presentation affordances without matching section records. - Related rows come from the daily passage's compare targets. They do not hand a newly selected passage back into the compact room.
Legacy depth pages are authored specimens with a third text identity#
- The Scholar page moves from the Buddhist room to Marcus Aurelius,
Meditations IV.viii–xii. Its four marginal notes, four witnesses, grouped
cross-references, and five concepts are returned by a zero-argument fixture
function. The toolbar wraps ordinary buttons without
hreforonClick. - Lexicon, manuscript, notebook, and plan repeat that authored thread. The lexicon's neighboring words are masthead text, not anchors; the manuscript is a rendered facsimile specimen; and the notebook always names Renata K. and On the ruling part regardless of account or prior passage.
- The plan always reports week four and 18 of 31 readings from a seven-week fixture. There is no add-to-plan handoff from search, no completion action, no member record, and no reload read-back in the named test.
- Browser Back from Scholar to
/nisabaproves navigation history. It does not carry the Marcus apparatus into the daily room or reconcile either with the Epictetus workspace.
Offline support is deliberately narrow and depends on cleanup#
- Client hooks persist daily passage and notebook-list payloads under shared localStorage keys for at most 24 hours; recents are capped at six. Notes, drafts, collections, study plans, and density mode use other browser-local keys and do not become BFF records through that persistence module.
- The service worker caches two authenticated read URLs by request URL. Its own
comments correctly acknowledge that Cache API matching ignores authorization
and that authenticated caching can leak across sessions on a shared browser.
The mitigation is an
oshun.pwa.member-cache-presentmarker plusOSHUN_CLEAR_MEMBER_DATAon normal session clear, which deletes BFF, shell, media, and queued-action stores before re-precaching public shell assets. - This is a cleanup-dependent boundary, not intrinsic subject partitioning. The docs should not promise shared-device isolation without verifying the sign-out/session-clear path, nor claim that a cold or non-allowlisted passage is available offline.
Boundaries and gaps#
- A search result is not the compact desk. The selected Epictetus id reaches
/domains/nisaba;/nisabaindependently resolves the daily Dhammapada room. - A visible passage is not the saved passage identity. The footer stores and
flags
nisaba-on-the-ruling-partwhile displaying the daily passage. - A hash is not reading-position state. Footer hashes have no matching section records for a dynamic daily passage.
- A toolbar label is not an action. The legacy Scholar buttons render but have no handler or destination.
noindexis not authorization. The Renata notebook fixture neither accepts a member id nor checks ownership.- A warm cache is not a subject-partitioned cache. URL-keyed cached reads and browser-local snapshots rely on session cleanup rather than per-user keys.
- Sixteen cases are not one continuous scholarly read. The named automation proves search, page anatomy, routing, presentation, and room HTTP gates; it does not create and read back one annotation, notebook item, or plan for the same passage.
Re-run evidence#
python3 -m pytest tools/docs_center/tests/test_generator.py -qfinished with 70 passed. The Result 43 source assertion pins registry position 43, front matter, section order, one evidence map, the 11 + 5 named case counts, search auth forwarding, all three passage identities, the remaining action-id mismatch, static toolbar, and URL/status-scoped offline stores.- Docs generation produced 3,242 files / 2,913 reader pages; the freshness check accepted all 3,242. Integrity reported 0 structural broken links / 0 dead source paths across 3,505 entities, with 112 pre-existing imported- content warnings surfaced as nonblocking.
- The complete Docs Center reader suite ran serially on desktop and mobile:
228 passed and 22 intentionally skipped. Result 43 checks one
h1, partial status, substantive prose, every current boundary statement, Mermaid containment and pairwise node geometry, expand-control clearance, heading anchors, source-journey navigation, console/page errors, and horizontal overflow. Full-page screenshots were also reviewed at 1,440 px and Pixel 7 dimensions; no clipping or hierarchy defect was found.
Source trail#
- Search and launch:
apps/oshun/bff/src/routes/universal-search-seeds.ts,apps/oshun/web/src/components/search/SearchResultsView.tsx, andapps/oshun/web/src/components/search/search-config.ts. - Live passage selection:
apps/oshun/web/src/components/domains/NisabaSurface.tsxandapps/oshun/web/src/lib/hooks/use-bff.ts. - Compact room:
apps/oshun/web/src/app/nisaba/page.tsx,apps/oshun/web/src/lib/lilith-data/nisaba.ts,apps/oshun/web/src/lib/server/bff-fetch.ts,apps/oshun/bff/src/routes/nisaba.ts, andapps/oshun/bff/src/nisaba/room.ts. - Passage and daily identities:
apps/oshun/bff/src/nisaba/state.ts,apps/oshun/bff/src/nisaba/public-domain-corpus.ts,apps/oshun/web/src/components/lilith/NisabaDeskLanguageSwitcher.tsx, andapps/oshun/web/src/components/lilith/NisabaPassageActions.tsx. - Legacy pages:
apps/oshun/web/src/lib/lilith-data/nisaba-depth.ts,apps/oshun/web/src/components/lilith/nisaba.tsx, and the five route pages underapps/oshun/web/src/app/nisaba/{scholar,lexicon,manuscript,notebook,plan}. - Offline boundaries:
apps/oshun/web/src/lib/nisaba-offline.ts,apps/oshun/web/src/lib/pwa-service-worker.ts, andapps/oshun/web/public/sw.js. - Named browser evidence:
apps/oshun/web/e2e/nisaba-scholarly-read.spec.tsandapps/oshun/web/e2e/nisaba-desk-deepening.spec.ts.
Cross-references#
nisaba-notebook-capture-and-cite.mdseparates the durable legacy BFF and Studio notebook authorities from local notes, generated citations, and the same Renata fixture.offline-first-time-use.mdcovers the broader service-worker warm-cache and session-clear model.search-explore-deep-read-library-save.mdcovers cross-domain search and Library launch semantics.veritas-to-nisaba-deeper.mdcovers another route into the live Nisaba domain workspace.
Open questions#
- Should
/nisabaaccept a canonical passage id and render the same BFF passage selected by search, or remain a deliberately separate daily surface? - Should the room API return its canonical passage id so Save, Read aloud, and
Flag can use it rather than
nisaba-on-the-ruling-part? - Should the legacy depth pages be wired to the live workspace, retired, or visibly labelled as authored specimens?
- Which live annotation/notebook/plan mutations define the product's actual scholarly-read completion event, and what same-record read-back should gate it?
- Should offline cache and local snapshot keys include a stable subject partition so privacy does not depend solely on session-clear cleanup?