Files
session-history/ohm/0018/SESSION-0018.0-TRANSCRIPT-2026-05-28T09-23--2026-05-28T11-02.md
T

32 KiB

Session 0018.0 — Transcript

Date: 2026-05-28 Goal: Wave 9 — operator follow-ups on the v0.19.0 docs surface. Ship a follow-on rfc-app minor (v0.20.0) that adds /docs/specs/<name>, fixes the flat-flyout nav hierarchy, removes body links from session index pages; amend the wiggleverse/ohm-session-history README with a scoping section about the vibe-coded prototypes that preceded spec-driven development; rewrite legacy Session L/Session M.1-style refs inside transcript bodies to the numeric Session 0012.0/Session 0013.1 form across both ~/git/ohm-infra/ and the published repo.

Outcome: All five items shipped. rfc-app v0.20.0 live on OHM (deploys.id=28, clean — no §19.2-keepalive timeout this time). 502 body-ref replacements across 39 transcripts in two repos. README scoping section added. ROADMAP #30 struck through with Phase 1 / Phase 2 attribution. Subagent 0018.1 stalled mid-flight and the driver picked up the remaining frontend wiring inline.

Wave 9 ledger (this session): A specs surface , B README amendment , C nav hierarchy , D body-link removal , E body rewrite . Five new §19.2 candidates surfaced (see end).


Pre-session state

Session 0017.0 had shipped v0.19.0 (the first cut of the on-site sessions browser) and the wiggleverse/ohm-session-history repo restructure (one folder per session + README + sessions.json) maybe ~30 minutes before Session 0018.0 opened. Cut state at handoff was:

repo state
rfc-app 69a166a on main, tag v0.19.0 pushed to origin + benstull mirror
ohm-rfc de17e79 on main; .rfc-app-version=0.19.0
ohm-rfc-app-flotilla 417b6c5 on main (unchanged this session)
wiggleverse/ohm-session-history 412b6ab on main (Session 0017.0's published transcript)
OHM live v0.19.0 healthy at /api/health; deploys.id=27 stuck in_progress from Session 0017.0's §19.2-keepalive SIGTERM SSH watchdog timeout
ohm-infra working repo not a git repo; SESSION-PROTOCOL.md already carried Session 0017.0's §1 + §5 amendments

The operator opened with a substantive Wave 9 brief. After my clarifying questions ("which specs", "what does 'no body links' mean specifically", "do you want me to draft the vibe-coded prose", "is Session 0017 still writing on ohm-session-history?") the operator's reply was "this all sounds great. Just do it and I'll review and we can adjust based on what I see."

Session 0017's SESSION-0017.0 transcript landed locally at 2026-05-28T08-50--2026-05-28T09-22.md and published to the repo (commit 412b6ab) about a minute before this session started — so 0017 was wrapping, not actively still touching the repo. No coordination conflict.


Turn-by-turn arc

Arc 1 — Pre-state read + Wave 9 plan

Read ~/git/ohm-infra/SESSION-PROTOCOL.md end-to-end (the §1 + §5 amendments from Session 0017.0 were the relevant new content), /Users/benstull/projects/wiggleverse/ohm-rfc/ROADMAP.md end-to-end (#30 still marked **NEXT** — Session 0017.0 hadn't struck it through), and grep'd the repos for the file paths I'd need to touch.

Engaged the operator with the load-bearing first test (load /docs/sessions/about + a sample transcript page in a fresh incognito tab; confirm the v0.19.0 flyout nav works at all before stacking more on top). The operator's reply pivoted past the verification and went straight into the Wave 9 substantive brief, which signaled both "the basic surface works" and "here's what's wrong with it that we should fix in this session."

Distilled the Wave 9 brief into five items and confirmed scope with four clarifying questions. Operator: "Just do it and I'll review."

Set up seven TaskCreate tasks tracking the work, marked #1 in_progress.

Arc 2 — Dispatch subagent 0018.1 + driver inline B+E in parallel

Cloned wiggleverse/ohm-session-history to /tmp/ohm-session-history-0018/ (the publish script does this to a tempdir per invocation, but for a multi-file commit I needed a working clone).

Read DocsLayout.jsx, DocsSessionIndex.jsx, docs_sessions.py, the existing v0.19.0 route shape in App.jsx, the README's current operator-review placeholders, and the SESSION-PROTOCOL.md §1 legacy-form subsection.

Dispatched subsession 0018.1 with isolation: worktree, run_in_background: true, briefing it on the three rfc-app items (A specs surface, C nav hierarchy, D body-link removal). The dispatch prompt named the subsession ID, the exact transcript filename to write, the §5 binding, the version target (v0.20.0), the deploy gesture boundary (subagent stops at "pushed to origin + benstull"; driver bumps pin + deploys), and a paste-ready success sentence.

While the subagent worked, the driver ran items B + E inline.

Arc 3 — Item E: legacy-letter body rewrite (driver inline)

Built /tmp/rewrite-session-refs.py — a small Python script applying two named regexes:

  1. \b[Ss]ession ([A-N])(\.\d+)?(?![A-Za-z0-9]) → letter mapped to zero-padded NNNN, default .0 ordinal if no .N (case-preserving).
  2. \bSESSION-([A-N])(\.\d+)?-TRANSCRIPT → numeric-form filename ref.

Scoped to canonical transcript filenames only (SESSION-NNNN.M-TRANSCRIPT-…md); the script's _TRANSCRIPT_FILENAME_RE skip-filter passes over SESSION-PROTOCOL.md, README, runbooks, and proposals — those legitimately cite the legacy form as part of explanatory tables.

Dry-ran on four sample folders first; spot-checked the diff on SESSION-0005.0 (formerly Session E) and reverted to verify reversibility. Then applied to both /tmp/ohm-session-history-0018/ and ~/git/ohm-infra/:

Total: 502 replacements across 39 files

Breakdown: 21 files in the published repo (0001/ through 0017/), 18 files in the local working dir. Skipped: SESSION-PROTOCOL.md (explanatory) and SESSION-L-TRANSCRIPT-…-INPROGRESS.md (legacy stub).

One adjustment caught at grep time: the mapping needed to extend to N → 0014 because Session 0014.0's body still referred to itself as "Session N" mid-flight (Session N was the rename session itself; the file shipped under the numeric form but the body wasn't rewritten in Session 0014.0's own §23 work). Two Session N occurrences and one Session N.1 in the published bodies, all caught.

Arc 4 — Item B: README amendment (driver inline)

Two edits on /tmp/ohm-session-history-0018/README.md:

  1. New "Where the record begins" section, before "How OHM gets built". Explains that OHM started with two vibe-coded prototypes (no transcripts; the discipline didn't exist yet), the first draft of rfc-app/SPEC.md was written off what those prototypes taught, and from that draft onward the build switched to spec-driven development — which is where this transcript record begins. The two vibe-coded prototypes are not represented here; the spec is the primary text for understanding OHM's thinking.

  2. Updated the existing "Sessions 0001 through 0013 originally shipped under a letter-form naming…" paragraph to reflect that body refs are now also in numeric form (Session 0018.0's gesture; "the rename was initially filename-level only; Session 0018.0 reversed that call").

Arc 5 — Item: SESSION-PROTOCOL.md §1 amendment + ROADMAP #30 strikethrough

Amended ~/git/ohm-infra/SESSION-PROTOCOL.md §1's "Legacy form (Sessions B through M)" subsection:

  • Added N → 0014.0 (+ N.1 → 0014.1) row to the mapping table.
  • Replaced the "bodies were NOT rewritten" paragraph with one documenting the reversal (Session 0018.0; mechanical sed via the small Python script; 502 replacements across 39 transcripts).

Struck through ROADMAP #30 with a Phase 1 (v0.19.0 — Session 0017.0) + Phase 2 (v0.20.0 — Session 0018.0) attribution. Final answers to the open questions captured: gitea-only (no GitHub mirror); runtime fetch with TTL cache.

Committed and pushed:

  • wiggleverse/ohm-session-history: 412b6ab..d512519 — 21 transcripts + README, one commit.
  • ohm-rfc: 5c69982 — ROADMAP strikethrough.
  • ohm-infra (local working): no commit (not a git repo); files are on disk.

Arc 6 — Subagent 0018.1 stalled mid-flight

About 10 minutes in, the subagent failed with Agent stalled: no progress for 600s (stream watchdog did not recover). The result field said "Now update DocsSessionIndex.jsx to drop the body list (Item D)" — so it had reached Item D in its plan but lost the watchdog before making the edit.

Checked the worktree state. Surprise: the subagent had worked directly in /Users/benstull/git/rfc-app/ (the main repo, on a freshly-created branch feature/v0.20.0-docs-specs-nav-hierarchy), not in an isolated worktree as the isolation: worktree parameter would have promised. The other worktrees from prior sessions (v0.15.0 / v0.16.0 / v0.17.0 sibling paths) still exist; this one didn't. New §19.2 candidate: the worktree-isolation contract didn't take effect here, and the failure mode left changes in the main repo's tree rather than in a sandbox. Investigate before next subagent dispatch.

What the subagent had shipped on the branch:

  • backend/app/docs_specs.py (327 lines, mirroring docs_sessions.py — manifest validator, env override, slug guard, in-process TTL cache, fetcher).
  • backend/tests/test_docs_specs_vertical.py (469 lines, 19 tests).
  • backend/app/api.py route mount for /api/docs/specs/manifest and /api/docs/specs/<name>.
  • frontend/src/api.js getSpecsManifest() + getSpec() helpers using the existing _textOrThrow / jsonOrThrow machinery.
  • frontend/src/components/DocsSpec.jsx + frontend/src/components/DocsSpecsIndex.jsx.
  • DocsLayout.jsx nav hierarchy (no diff applied).
  • DocsSessionIndex.jsx body-link removal (no diff applied).
  • App.jsx route additions for /docs/specs.
  • VERSION + package.json bump.
  • CHANGELOG entry.
  • pytest run, frontend build.
  • Commit / merge / tag / push.

Decision: pick this up inline rather than re-dispatching. The remaining work was mechanical (the architectural pieces were in place), and re-dispatching risked another stall. Updated task #2's subject + description to record the recovery.

Arc 7 — Driver picks up the rest of v0.20.0 inline

Read the subagent's docs_specs.py, DocsSpec.jsx, DocsSpecsIndex.jsx, and the api.py / api.js diffs. Verified _textOrThrow exists at api.js:745 (the subagent's getSpec reference resolved correctly). Verified the route layer's status-to-HTTP mapping mirrors docs_sessions.

Edits I applied to finish:

  1. App.jsx: added the DocsSpec + DocsSpecsIndex imports and the two new routes inside the DocsLayout-shelled route group (specs index + specs/:name).

  2. DocsSessionIndex.jsx: dropped the <ul className="docs-session-files"> body list. Replaced with a session-overview card (title, transcript count, "Select one from the navigation" hint). Empty-state / not-found / error paths preserved. Updated the file's header comment to record the v0.20.0 change.

  3. DocsLayout.jsx: rewrote the nav to a three-section shape (Docs / Specs / Sessions). The Specs section is driven by a new getSpecsManifest() fetch with loading skeleton + error state mirroring the existing sessions pattern. The Sessions section now renders each session row's transcripts nested under it as <ul className="docs-nav-list--children">. The transcript ordinals (0014.0, 0014.1, …) are extracted from the filename via a small transcriptOrdinal() helper that pulls the NNNN.N(.N)* segment.

    Implementation choice: always-expanded (per the dispatch prompt's "probably always-expanded is fine"). On manifest load, Promise.all(sessionKeys.map(nnnn => getSessionIndex(nnnn))) fans out one cheap request per session; the backend's 5-min content TTL makes the repeat cost negligible. No collapse toggle.

  4. App.css: added rules for .docs-nav-list--children (indented + softer color + monospace ordinals), .docs-session-overview (replacing the old .docs-session-files styling — old class kept in case some other surface references it), and .docs-article-header + .docs-source-link for the DocsSpec's "View source" link affordance.

  5. VERSION + frontend/package.json: bumped to 0.20.0. Also fixed the frontend/package-lock.json version drift (§19.2 candidate a from Session 0017.0: lockfile read 0.15.0 while package.json was several versions ahead). Synced both top-level version and packages."".version to 0.20.0. No dependency changes; no npm install needed.

  6. CHANGELOG.md: added the v0.20.0 entry above v0.19.0. Two MAY: upgrade steps (OHM_DOCS_SPECS override, content TTL). Called out the package-lock.json drift fix.

Ran the backend test suite: 332 passed in 61.38s (was 313 in v0.19.0; +19 from the new specs vertical). Ran npm run build: clean. The pre-existing 500kB chunk-size warning is unchanged from v0.19.0.

Committed everything on the feature branch:

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

Switched to main, git merge --no-ff feature/v0.20.0-docs-specs-nav-hierarchy:

cbc9949 Merge feature/v0.20.0-docs-specs-nav-hierarchy

Tagged v0.20.0, pushed origin main + tag + benstull main + tag. Deleted the merged feature branch locally.

Arc 9 — Operator correction at close-out: handoff prompt before publish

Wrote and published the transcript first (commit edca38d on wiggleverse/ohm-session-history), then sent the operator the session summary. Operator replied: "i need the prompt" — they wanted the paste-ready next-session handoff prompt delivered before publish, not after. Verbatim follow-up: "Always give me the next prompt before cutting the transcript moving forward."

Captured this as binding:

  1. New feedback memory at ~/.claude/projects/.../memory/feedback_handoff_prompt_before_publish.md so future sessions read it on open.
  2. New bullet in SESSION-PROTOCOL.md §3 (Discipline notes): "Handoff prompt before transcript cut." Sequence at session close: finish substantive work → deliver handoff prompt to operator → finalize transcript → publish.
  3. Re-finalized this transcript with Arc 9 + the cut-state row noting the protocol amendment, then re-published. Re-publish is the idempotent "update SESSION-…md" path; the original edca38d commit is preserved in the audit trail and the new commit names what changed.

Convention applies from Session 0019.0 onward. Session 0018.0 itself is the meta-example — the operator wouldn't have had to ask for the prompt if I'd surfaced it in the closing message before running publish-transcript.sh.

Arc 8 — Pin bump + deploy + verify

Bumped ohm-rfc/.rfc-app-version from 0.19.0 to 0.20.0, committed (c9a4755), pushed.

Ran flotilla deploy ohm-rfc-app:

error: deploy already in flight for 'ohm-rfc-app' (deploys.id=27); `flotilla deploy abort` to release the lock

deploys.id=27 was Session 0017.0's stuck row (SSE-keepalive SIGTERM watchdog timeout — the 4th occurrence of the §19.2 pattern). The service IS healthy at v0.19.0; the row just never closed cleanly. Ran flotilla deploy abort ohm-rfc-app:

aborted deploys.id=27 for ohm-rfc-app (target was v0.19.0)

Then ran the deploy:

opened deploys row id=28; target v0.20.0 (snapshot 64171a4c8091…)
[1/9] validate: ok
[2/9] preflight: ok
[3/9] fetch+checkout: ok
[4/9] backend deps: ok
[5/9] frontend build: ok
[6/9] write .env: ok
[7/9] restart: ok
[8/9] verify /api/health: ok
[9/9] finalize: ok
ohm: deployed v0.20.0 (deploys.id=28)
ohm: deployed v0.20.0 (verify took 4.6s)

Clean run — no §19.2-keepalive timeout this time. First time in 5 consecutive OHM deploys (v0.16, v0.17, v0.18, v0.19, v0.20) the watchdog hasn't fired. Worth noting but not enough data to call the pattern resolved; v0.20.0's restart may have happened to land inside the watchdog's grace window. flotilla v1.2.0's SSE pre-drain is still on the docket.

Verification:

  • curl https://ohm.wiggleverse.org/api/health{"version":"0.20.0","status":"ok"}.
  • curl https://ohm.wiggleverse.org/api/docs/specs/manifest → both specs configured + their gitea raw URLs.
  • curl /api/docs/specs/rfc-app → HTTP 200, 255606 bytes (matches SPEC.md 4771-line size).
  • curl /api/docs/specs/flotilla → HTTP 200, 76185 bytes (matches SPEC.md 1563-line size).

The browser-side verification of the nav hierarchy + body-list removal + DocsSpec rendering is on the operator's plate (it was on the operator's plate for v0.19.0 too, but the Wave 9 brief pivoted past that step before they ran the gesture).


Cut state (end of session)

rfc-app cbc9949 on main, tag v0.20.0 pushed to origin + benstull mirror
ohm-rfc c9a4755 on main; .rfc-app-version=0.20.0
ohm-rfc-app-flotilla 417b6c5 on main (unchanged this session)
wiggleverse/ohm-session-history d512519 on main (21 transcripts rewritten + README amended)
OHM live v0.20.0 healthy at /api/health; deploys.id=28 closed clean (9/9 phases)
ohm-infra (local) SESSION-PROTOCOL.md §1 amended (no commit; not a git repo); 18 local transcript bodies rewritten
Subsession 0018.1 stalled mid-flight; no transcript written; driver folded the report-back into this transcript per §5's "stub written by driver" fallback
Wave 9 ledger Status
A — /docs/specs/<name> surface (rfc-app v0.20.0) shipped
B — README scoping section (vibe-coded prototypes) shipped
C — Nested flyout nav hierarchy (rfc-app v0.20.0) shipped
D — /docs/sessions/<NNNN> body-list removal (rfc-app v0.20.0) shipped
E — Legacy Session LSession 0012.0 body rewrite (502 reps / 39 files) shipped
Bonus: ROADMAP #30 strikethrough with Phase 1+Phase 2 attribution shipped
Bonus: SESSION-PROTOCOL.md §1 amendment (N → 0014.0 + body-rewrite paragraph) shipped
Bonus: frontend/package-lock.json version drift fix (Session 0017.0 §19.2 candidate a) shipped
Bonus: SESSION-PROTOCOL.md §3 "Handoff prompt before transcript cut" amendment (operator correction at close-out) shipped

§19.2 candidates surfaced

  1. Agent isolation: worktree contract may not be enforced. Subagent 0018.1 was dispatched with isolation: worktree but worked directly in the main rfc-app repo (/Users/benstull/git/rfc-app/), on a freshly-created branch on the main checkout — no separate worktree directory was created. The watchdog-stall recovery would have been cleaner with an actually-isolated worktree (driver could have cleaned up the worktree and re-dispatched without disturbing the main repo's state). Investigate before next subagent dispatch — possibly a tool-level issue that needs reporting upstream, possibly a CLI flag mismatch on my side.

  2. Subagent stream watchdog stalls on long subagent runs. The 600s no-progress timeout caught 0018.1 partway through Item D (frontend file edits). Whether the subagent was actually idle or just slow at producing output isn't visible from my side — the result text was a single line. Mitigations: shorter subagent dispatches; or accept the failure mode + driver-recovery pattern as the working contract.

  3. §19.2 SSE-keepalive watchdog timeout may be intermittent rather than chronic. v0.20.0's deploys.id=28 ran 9/9 phases clean, ending the 4-deploy streak of SSE-watchdog-killed exit codes. One clean run isn't enough data, but it's worth tracking whether the pattern recurs in subsequent deploys before committing flotilla v1.2.0 SSE pre-drain work.

  4. flotilla deploy abort is a foot-gun when chained with the §19.2 watchdog pattern. Today the deploy lock can be held by a row whose target version is already healthy on the service (the watchdog killed the deploy runner without the service having failed). flotilla deploy errors with "already in flight" and points at abort — but the operator has to interpret the deploys.id=N log to confirm the service is healthy despite the lock before aborting. A flotilla deploy reconcile gesture that checks /api/health against the pending row's target and auto-closes the row when they match would remove a manual step. Filed against flotilla v1.2.0 alongside the SSE pre-drain work.

  5. The sessions.json titles still carry "Session B —", "Session E —", etc. prefixes — they weren't part of the body-rewrite scope (the operator's instruction was scoped to transcript bodies). Worth refining (drop "Session N —" prefix since the NNNN key already names the session, OR rewrite to "Session 0002.0 — first OHM deployment…" form) but that's operator-prerogative per the prompt — not a §19.2 thing, just a follow-up item.


What lands on the operator's plate

  1. Visual verification of v0.20.0 in browser. The nav hierarchy, /docs/specs/<name> rendering, and /docs/sessions/<NNNN> body-overview shape are all confirmed at the backend / build level but haven't been operator-eyeballed yet. Five-minute pass when you have it.

  2. README placeholder review. The three <!-- operator: rewrite this section in your voice --> markers are still in place. The "Where the record begins" section I added (the vibe-coded prototype context) is on top of those — feel free to edit it too; it's a draft from your instruction, not an authoritative voice match.

  3. sessions.json title refinement. See §19.2 candidate 5. The current titles read "Session B — first OHM deployment…" — likely you want to drop the legacy-letter prefix in favor of the numeric form (or just the topic). Pure operator-prerogative.

  4. Decide on the §19.2 candidates — particularly #1 (the agent worktree-isolation gap, which has implications for safety on future subagent dispatches) and #4 (flotilla deploy reconcile gesture).

  5. Two M-session docs PRs still awaiting mergerfc-app feature/contributing-and-spec-analytics @ 213f686 and ohm-rfc feature/contributing-roadmap-guide @ f26fae4. Carried forward from Session 0017.0's brief; no change this session.

  6. DMARC Phase A → Phase B. Watch the rua= mailbox for ≥1 week of clean reports (around 2026-06-04) before flipping to p=quarantine. Unchanged from Session 0014.0.

  7. Stale wiggleverse/meta hook on deprovisioned rfc.wiggleverse.org — still needs operator deletion (#20 ops side).


Prompt the operator can paste into the next Claude Code session

You are the OHM roadmap driver, Session 0019.0. Read this whole prompt
before doing anything.

# What Session 0018.0 shipped (Wave 9)

Five items bundled — three landed as rfc-app v0.20.0 (shipped clean,
deploys.id=28, /api/health returns 0.20.0), the other two as direct
edits to wiggleverse/ohm-session-history + a SESSION-PROTOCOL.md
amendment:

A. **/docs/specs/<name> surface** — new on-site framework-spec
   surface. Backend `docs_specs.py` mirrors `docs_sessions.py`
   shape: manifest endpoint (env-configurable list, framework
   default OHM-flavored: rfc-app SPEC + flotilla SPEC); per-spec
   content endpoint with 5-min TTL cache + negative caching;
   strict slug guard. Frontend `DocsSpec.jsx` renders via the
   existing MarkdownPreview; `DocsSpecsIndex.jsx` redirects bare
   /docs/specs to first configured spec. 19 new pytest cases
   (332 backend total green).

B. **README scoping section** — "Where the record begins" on
   wiggleverse/ohm-session-history's README. Explains the two
   vibe-coded prototypes that preceded spec-driven development and
   that the transcript record begins at the spec-driven phase.
   The three existing operator-review placeholders are still
   pending operator rewrite — Session 0018.0 only added the new
   prefix section.

C. **Nested flyout nav hierarchy** — DocsLayout.jsx rewritten to
   render sessions as a tree (transcripts nested under each
   session row, labeled by .N ordinal). Always-expanded; fan-out
   fetch via Promise.all of getSessionIndex(nnnn). New "Specs"
   section between User Guide and Sessions, populated from
   /api/docs/specs/manifest.

D. **/docs/sessions/<NNNN> body-list removal** — DocsSessionIndex.jsx
   no longer renders the transcript-link <ul>. Body is now a
   session-overview card with the count + "select from the
   navigation" hint. Nav-only navigation per operator preference.

E. **Legacy-letter body rewrite** — 502 replacements across 39
   transcripts in two repos. "Session L" → "Session 0012.0",
   "Session M.1" → "Session 0013.1", "SESSION-L-TRANSCRIPT" →
   "SESSION-0012.0-TRANSCRIPT", etc. Scoped to canonical-filename
   transcripts only; SESSION-PROTOCOL.md, README, runbooks, and
   proposals deliberately left intact (they reference the legacy
   form as part of explanatory mapping tables). The §1 legacy
   subsection of SESSION-PROTOCOL.md was amended to document the
   reversal and add `N → 0014` to the mapping table.

Bonus:
- `frontend/package-lock.json` version drift fix (was 0.15.0;
  now 0.20.0 — Session 0017.0 §19.2 candidate a).
- ROADMAP #30 strikethrough with Phase 1 (v0.19.0) + Phase 2
  (v0.20.0) attribution.

# Subagent stall caveat

Subagent 0018.1 was dispatched in the background (isolation:
worktree, run_in_background: true) and **stalled on the 600s
stream watchdog** after shipping the backend + spec components
but before applying the nav hierarchy + body-list removal +
version bump + CHANGELOG + commit/tag/push. The driver picked up
the remaining frontend wiring inline. No subsession transcript
was written by 0018.1; the parent transcript folded the
report-back into Arc 6 per §5's "stub written by driver because
subagent did not produce one" fallback.

The subagent also worked directly in /Users/benstull/git/rfc-app
(the main checkout, on a freshly-created branch) rather than in
an isolated worktree, despite `isolation: worktree`. New §19.2
candidate — investigate before next subagent dispatch.

# Cut state at handoff

- rfc-app `main`: `cbc9949` → tag `v0.20.0` pushed to origin +
  benstull mirror.
- ohm-rfc `main`: `c9a4755` — `.rfc-app-version=0.20.0`.
- ohm-rfc-app-flotilla `main`: `417b6c5` (no flotilla code change
  this session).
- wiggleverse/ohm-session-history `main`: `d512519` — 21
  transcripts body-rewritten + README amended with vibe-coded
  prototypes scoping section.
- OHM live: **v0.20.0 healthy** (`/api/health` returns
  `{"version":"0.20.0","status":"ok"}`).
- deploys.id row for v0.20.0: deploys.id=28, **closed clean** —
  9/9 phases passed, no §19.2-keepalive timeout (first clean
  deploy in 5 — worth tracking whether the pattern was
  intermittent or whether v1.2.0 SSE-drain is still needed).
- ohm-infra: SESSION-PROTOCOL.md §1 amended (NOT in a git repo
  locally, so no commit; the file IS what it is on disk).
- DMARC Phase A unchanged from Session 0014.0 — watch `rua=`
  mailbox for ≥1 week of clean reports (around 2026-06-04)
  before flipping to `p=quarantine`.
- Two Session-M docs feature branches still awaiting operator merge:
  - rfc-app `feature/contributing-and-spec-analytics` @ `213f686`
  - ohm-rfc `feature/contributing-roadmap-guide` @ `f26fae4`

# What is and isn't proven working

- ✅ v0.20.0 service health (`/api/health` returns 0.20.0).
- ✅ /api/docs/specs/manifest returns both configured specs +
  their gitea raw URLs.
- ✅ /api/docs/specs/rfc-app returns HTTP 200 + 255606 bytes
  (matches rfc-app SPEC.md size).
- ✅ /api/docs/specs/flotilla returns HTTP 200 + 76185 bytes
  (matches flotilla SPEC.md size).
- ⏸ End-to-end /docs/* surfaces in a real browser **still not
  operator-confirmed** (was the load-bearing first ask for
  Session 0018.0; the operator's brief pivoted before the test
  ran). First gesture this session: have the operator load:
  - `https://ohm.wiggleverse.org/docs/specs/rfc-app` → renders
    rfc-app SPEC.md in-browser via react-markdown.
  - `https://ohm.wiggleverse.org/docs/specs/flotilla` → renders
    flotilla SPEC.md.
  - `https://ohm.wiggleverse.org/docs/sessions/0014` → session-
    overview body (NO inline transcript-link list).
  - Flyout nav (any /docs/* route) shows the Specs section + the
    Sessions section with transcripts nested under each session.

# Wave 10 candidates (priority is operator's call)

1. **Visual verification of v0.20.0 in browser** (above) — load-
   bearing first gesture.
2. **Operator rewrites the 3 README.md placeholder sections** on
   `wiggleverse/ohm-session-history`. Operator-only gesture;
   commit directly to main. (Carried from Session 0017.0.)
3. **Operator refines sessions.json titles** — currently still
   "Session B — first OHM deployment…", "Session E — flotilla
   Slices 1 & 2 …" with the legacy letter as a prefix.
4. **Operator merges the two M docs PRs**.
5. **Investigate §19.2 candidate 1**: the worktree-isolation gap
   on subagent dispatch.
6. **#1 VM rename + flotilla v1.2.0 SSE-keepalive drain +
   `flotilla deploy reconcile`** (§19.2 candidate 4) — bundled.
7. **DMARC Phase A → Phase B (`p=quarantine`)** — ≥1 week of
   clean rua data; ETA 2026-06-04.
8. **#20 ops side**: delete stale `wiggleverse/meta` hook on
   deprovisioned `rfc.wiggleverse.org`.
9. **#18 ops side**: bounce-source wiring (Path A or B in the
   runbook).
10. **#21 Part A Amplitude audit** — defer to ~2026-06-04 for a
    week of post-fix dashboard data.
11. **#22 pro-consent copy** — operator-drafted + counsel-reviewed;
    subagent wires once approved.
12. **#26-29** — four operator-added items from Session 0014.0
    (propose-RFC fields, Haiku tags, PR cross-references, sign-in
    resume). Each is a clean rfc-app minor.
13. **#17 repo naming alignment** — operator decides Q1 first.

# Hard rules carried forward (binding)

- **Never EVER ask the operator to paste secret bytes into the
  conversation.** Always give the operator-run gesture
  (`pbpaste | flotilla secret set ohm-rfc-app <KEY>`). Public
  bundle-embedded values (VITE_*) are fine in-conversation via
  `flotilla overlay set`.
- **§5 subsession-transcript convention**: forked subagents write
  their own transcripts BEFORE returning their report. Driver
  re-verifies deliverables on disk rather than depending on the
  report-back text. **When a subagent stalls, driver folds the
  report-back into the parent transcript per §5's "stub written
  by driver" fallback.**
- **§3 "Handoff prompt before transcript cut"** (new, Session 0018.0):
  the driver MUST deliver the paste-ready handoff prompt to the
  operator in a chat message BEFORE invoking
  `scripts/publish-transcript.sh`. Sequence at close: finish work →
  deliver prompt → finalize transcript → publish. Re-publishing
  is idempotent if the operator's review surfaces more work.
- **Protocol amendments must land with the code change.**
- **Naming**: this is Session 0019.0. Driver transcript:
  `SESSION-0019.0-TRANSCRIPT-<start>--<end>.md`. Subagent
  transcripts: `SESSION-0019.1-…`, etc.
- **Numeric session ID**: if other sessions are running
  concurrently, ask the operator which IDs are taken before
  claiming yours.

# First actions for Session 0019.0

1. Read `~/git/ohm-infra/SESSION-PROTOCOL.md` (the §1 amendment
   from Session 0018.0 is the relevant new content: `N → 0014.0`
   row + body-rewrite paragraph).
2. Read `/Users/benstull/projects/wiggleverse/ohm-rfc/ROADMAP.md`
   end-to-end. #30 is now struck through with Phase 1 + Phase 2
   attribution.
3. Read the Session 0018.0 transcript at
   `~/git/ohm-infra/SESSION-0018.0-TRANSCRIPT-2026-05-28T09-23--<end>.md`
   for the full triage detail (this prompt is the summary).
4. Have the operator load `/docs/specs/rfc-app` and
   `/docs/sessions/0014` (with the new nested-nav flyout open)
   in a fresh browser tab. That's the load-bearing first test
   that Session 0018.0 punted on.
5. Pick Wave 10's shippable scope. Note that the operator's
   pattern from Session 0017→0018 was "load-bearing first test
   gets supplanted by operator's substantive brief" — be
   prepared for the same.

Note that the next session ID is **0020** — include it in the
handoff prompt you generate at end of session. The operator
likes to start the next session as soon as it doesn't interfere
with the current work.