Release v0.20.0: /docs/specs surface + nested flyout nav + session body-list removal

Wave 9 follow-up to roadmap item #30 (Session 0017.0 shipped #30 as v0.19.0;
v0.20.0 lands the operator-feedback follow-ups on top).

1. Specs on /docs/specs/<name> (backend docs_specs.py + frontend DocsSpec.jsx
   + DocsSpecsIndex.jsx). Configured via OHM_DOCS_SPECS; framework default
   carries OHM's two specs (rfc-app/SPEC.md + flotilla SPEC.md). Runtime
   fetch from gitea raw with 5-min TTL cache, mirroring docs_sessions.py.

2. Nested flyout nav hierarchy (DocsLayout.jsx). Sessions render as a tree
   with transcripts nested under each session row (labeled by .N ordinal).
   New Specs section between User Guide and Sessions.

3. /docs/sessions/<NNNN> body-list removed (DocsSessionIndex.jsx). Body
   becomes a session-overview card; navigation lives in the left nav.

19 new pytest cases for docs_specs (332 backend total green). Frontend
build clean. Sync frontend/package-lock.json version drift (0.15.0 → 0.20.0)
alongside the VERSION + package.json bump.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ben Stull
2026-05-28 10:48:31 -07:00
parent 69a166a6f2
commit e0d9ed7c5a
14 changed files with 1328 additions and 44 deletions
+25
View File
@@ -774,6 +774,31 @@ export async function getSessionIndex(nnnn) {
))
}
// ---------------------------------------------------------------------------
// v0.20.0 — /api/docs/specs/* surface
// ---------------------------------------------------------------------------
//
// Sibling of the docs-sessions helpers above. The framework mediates
// reads against the configured spec URLs (default: rfc-app's own
// SPEC.md + flotilla's SPEC.md on `git.wiggleverse.org`) so the
// `/docs/specs/*` route inherits the same chrome as `/docs/user-guide`
// and `/docs/sessions/*`. The manifest endpoint always returns 200 +
// {specs: [...]} — a malformed `OHM_DOCS_SPECS` env var falls back to
// the framework default at parse time on the backend.
//
// 404 from `getSpec` throws `.status === 404`; 502 throws `.status === 502`,
// matching the docs-sessions helper convention.
export async function getSpecsManifest() {
return jsonOrThrow(await fetch('/api/docs/specs/manifest'))
}
export async function getSpec(name) {
return _textOrThrow(await fetch(
`/api/docs/specs/${encodeURIComponent(name)}`
))
}
// ---------------------------------------------------------------------------
// Slice 7: admin neighborhood (§17 admin/* + user search for the §15.8 mute
// typeahead).