Backfills transcripts that existed only locally in ohm-infra: - 0019.1/.2/.3 - UX-polish wave subagent transcripts (driver 0019.0 never finalized) - 0026.1-.9 - security-audit-0026 subagent transcripts (driver abandoned/closed-out by 0068; audit drove published 0030 remediation) - 0073.0 - PPE/progressive-delivery + engineering-handbook session, originally drafted as a duplicate 0046.0; reassigned next free number (0072 taken by a concurrent session) sessions.json: add 0019/0073 titles, update 0026 title. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.0 KiB
Session 0019.3 — Transcript
Parent: SESSION-0019.0-TRANSCRIPT-… (UX-polish wave, rfc-app v0.21.0) Subagent ordinal: .3 — roadmap item #32 (session/transcript page polish) + the /docs surfaces' share of #31.
Goal
In the isolated worktree /Users/benstull/git/rfc-app-v0.21.0-docs
on branch feature/v0.21.0-docs-32:
(a) Collapse single-transcript session roots — render the transcript
inline at /docs/sessions/:nnnn instead of a dead-end placeholder;
multi-transcript sessions inline the .0 driver transcript and
list the siblings.
(b) Add a transcript metadata header (title, started/ended parsed from
the filename ISO segments, derived duration, optional tldr from
the manifest, external view-source link).
(c) Docs-surface token polish + consistent loading/empty/error states +
aria-labels on icon-only controls.
Pre-state
- Foundation commit carried
frontend/src/styles/tokens.css(the #31 design-token module). Build requiresVITE_APP_NAME(no default). /docs/sessions/:nnnn(DocsSessionIndex.jsx) rendered a.docs-session-overviewplaceholder: "N transcript(s) in this session. Select one from the navigation."- DocsSessionTranscript.jsx rendered body via MarkdownPreview with a breadcrumb but no metadata header.
- Backend
/api/docs/sessions/manifest(api.py:177-178) returnsresult["manifest"]verbatim — the fullsessions.jsonobject — so arbitrary per-entry fields already reach the frontend.
Turn-by-turn arc (honest)
- Read tokens.css, SESSION-PROTOCOL.md (§1 naming + the 0017.0 folder-layout amendment + the sessions.json shape), all seven owned docs components, api.js docs helpers, docs_sessions.py, and the api.py manifest route.
- Confirmed the manifest endpoint is a pass-through → no backend
change needed for
tldr. The decision branch in the task was resolved in favor of "already passes through". - Read the existing docs CSS block in App.css (read-only) to learn which classes a sibling owns (.docs-article, .docs-empty, .docs-error, .docs-source-link, .docs-session-overview, etc.) so Docs.css would not collide.
- Rewrote DocsSessionTranscript.jsx: exported
gitSourceUrl,transcriptOrdinal,parseTranscriptMeta, andTranscriptMetaHeader; added a manifest fetch for title+tldr; rendered the header above the body. - Rewrote DocsSessionIndex.jsx to inline-render the primary transcript
(driver
.0preferred, elsefiles[0]) and list siblings; reused the imported header + ordinal helpers. - Created Docs.css (new classes only, all token-valued).
- Brought DocsUserGuide's bare
<p className="error">onto the shared.docs-error+ retry convention. - Build failed first run (VITE_APP_NAME unset — env requirement, not
my change); re-ran with
VITE_APP_NAME="OHM Verify" npm run build→ green (974 kB index chunk; >500 kB warning expected/benign). - Staged the four files explicitly (avoided the
frontend/node_modulessymlink), committed.
Design decisions
Inline-collapse (a). URL stays stable to the session number — the
session root fetches the index, picks a primary file, fetches its body,
and renders the same TranscriptMetaHeader + philosophy-body the
standalone route uses. No <Navigate>, no 301. Primary selection:
SESSION-NNNN.0-TRANSCRIPT… if present, else files[0] (backend
returns the list pre-sorted). For multi-transcript sessions, a
.docs-session-siblings strip lists every transcript ordinal — the
primary marked "(shown below)" with aria-current, the rest linking to
/docs/sessions/:nnnn/:filename. No empty placeholder remains on any
path that has at least one transcript.
Metadata header (b). parseTranscriptMeta regexes the
-TRANSCRIPT-<start>--<end>.md ISO segment (YYYY-MM-DDTHH-MM x2,
colons-as-dashes per protocol). Times are built as local Dates and
rendered as wall-clock via toLocaleString — the filename encodes no
timezone (PST implied), and duration is a difference of two same-basis
Dates so the implied-TZ ambiguity cancels. Legacy renamed-letter
transcripts (no segment) → all derived fields null → header shows just
the title + source link (graceful degrade). Duration omitted when
start==end or unparseable.
tldr schema (b). Consumed as a string field named tldr on the
per-session entry of sessions.json, i.e. keyed by the 4-digit session
number alongside title:
{ "0019": { "title": "UX-polish wave …", "tldr": "One-line summary." } }
Read via getSessionsManifest() → payload[nnnn].tldr; rendered only
when typeof === 'string' and truthy. Absent ⇒ no TL;DR line.
Polish (c). Docs.css styles ONLY the two new element families
(.docs-transcript-meta*, .docs-session-siblings*), every value a
tokens.css custom property, to avoid racing the #31 App.css sweep for
the pre-existing docs selectors. DocsUserGuide normalized to the shared
error convention. All icon-only controls already carried aria-labels
(verified the drawer toggle ☰, scrim) — no aria gaps found in owned
files.
Cut state
- Branch:
feature/v0.21.0-docs-32 - Final commit SHA:
adb5d2571532ad5992900791d295ef214ddfba0d - Files changed (4):
frontend/src/components/DocsSessionIndex.jsx(rewrite — inline collapse)frontend/src/components/DocsSessionTranscript.jsx(rewrite — meta header + exports)frontend/src/components/DocsUserGuide.jsx(error-state normalize)frontend/src/components/Docs.css(new)
- Backend: NOT changed. docs_sessions.py untouched — manifest
pass-through already exposes
tldr. (No py_compile needed.) - Build: GREEN (
VITE_APP_NAME=… npm run build; 974 kB chunk warning benign).
What the driver needs to know
- No backend coordination required for this item — frontend renders
tldrwhen present; the field's value-backfill is the documented out-of-scope follow-up. - sessions.json
tldrschema to backfill (driver/operator task inwiggleverse/ohm-session-history): add an optional"tldr": "<one line>"string to any per-session entry next to"title". The frontend already consumes it on both the inline session-root view and the standalone transcript view. Absent ⇒ no-op. - Inline-collapse changes the
/docs/sessions/:nnnnsemantics: it is no longer nav-only. The left-nav transcript rows + sibling links still point at the standalone/docs/sessions/:nnnn/:filenameroute, which is unchanged and now also carries the metadata header. - Build needs
VITE_APP_NAMEset (env requirement, not from this item).
§19.2 candidates
parseTranscriptMeta/transcriptOrdinalare filename-shape logic that mirrors the backend_TRANSCRIPT_FILENAME_REand the nav's owntranscriptOrdinalin DocsLayout.jsx — there are now two frontend copies of the ordinal regex (DocsLayout owns one; I export one). A future consolidation could lift a singlelib/transcripts.jsand have DocsLayout import it (DocsLayout is sibling-owned, so I did not touch it). Worth flagging for a follow-up de-dup.