37 KiB
Session 0017.0 — Transcript
Date: 2026-05-28 Start: 2026-05-28T08-50 PST End: 2026-05-28T09-22 PST Goal: drive Wave 8 — pick a shippable scope from the post-Wave-7 candidate list now that the OTC sign-in gate is open; the operator marked roadmap #30 (docs nav + on-site sessions browser + session-history repo restructure) as NEXT in ROADMAP.md, so that became the target.
Outcome: Wave 8 = roadmap #30 shipped end-to-end. rfc-app v0.19.0 tagged + pushed (canonical + benstull mirror); ohm-rfc pin bumped to 0.19.0; OHM live at v0.19.0 healthy.
wiggleverse/ohm-session-historyrestructured into one folder per session +README.md(operator-review draft) +sessions.jsontitle manifest (15 entries, all titled).publish-transcript.shextended for the folder convention + sessions.json upsert. SESSION-PROTOCOL.md §1 + §5 amended. Three subagents (0017.1 rfc-app code, 0017.2 session-history restructure, plus the driver-inline publish-script + protocol edits) all delivered.Highlights:
- The OTC sign-in end-to-end gate (Wave 7 carry-forward) was operator-confirmed working at session start — first-time-since-launch.
- Two other sessions were running concurrently (0015.0 troubleshooting an OTC-config edge case; 0016.0 completed). Driver took ID 0017.0 per operator confirmation.
- Settled at session time: gitea-only (no GitHub mirror); runtime fetch with cache for
/docs/sessions; fullSESSION-NNNN.M-TRANSCRIPT-…mdfilename retained inside each folder (overrode roadmap example's trimmed form).- SSE-keepalive SSH-watchdog timeout fired again at deploy time (4th occurrence; flotilla v1.2.0 §19.2 candidate). Service came up at v0.19.0 healthy regardless.
Pre-session state
- rfc-app
main@ac3513a("Merge: CONTRIBUTING.md + SPEC.md §21 analytics chapter (Session 0013.1)");v0.18.0was the latest tag; clean working tree. - ohm-rfc
main@74a3e12("ROADMAP: +#24..#29"); pin.rfc-app-version=0.18.0. (Between session start and the post-deploy pin push, the operator landed at least one more commit on ohm-rfc —9c47792— adding roadmap item #30 with its NEXT marker; my pin-bump committed onto the updated9c47792cleanly.) - ohm-rfc-app-flotilla
main@417b6c5(v1.1.0, Wave 7 deploy with VITE_* overlay propagation). Local working tree had one modified file:CLAUDE.md. - OHM live: v0.18.0 healthy (
/api/health200,{"version":"0.18.0","status":"ok"}). - ohm-infra (
~/git/ohm-infra/, not a git repo locally):publish-transcript.shat the post-#23 form (accepting numeric + legacy letter regex);SESSION-PROTOCOL.mdat the post-Session-0014.0 amendment shape. StaleSESSION-0012.0-TRANSCRIPT-…INPROGRESS.mdstill on disk (handoff said leave as-is). - Session 0014.0's main driver transcript NOT yet on disk at session start (it appeared at 08:43 mid-session — the parallel-running driver was finalizing). 0014.1 subagent transcript was on disk from 07:42. 0016.0 transcript not seen on disk this session.
The operator's handoff prompt (pasted at session start) was the load-bearing summary of what Wave 7 shipped + the Wave 8 candidate list. Two clarifying gates the operator surfaced at the top:
- OTC sign-in end-to-end was unverified. Wave 7's full triage stopped before the operator retested.
- Two other sessions were running. Session ID for this driver had to be calculated from what the other sessions had claimed.
Turn-by-turn arc
Arc 1 — Orient + clear the two gates
Read SESSION-PROTOCOL.md, ohm-rfc/ROADMAP.md (which surfaced a NEW item #30 marked NEXT by the operator — newer than the handoff prompt and effectively re-shaping the Wave 8 priority order), the on-disk transcript listing (showed 0001–0013.3 + 0014.1 in numeric form), and the publish-transcript.sh + flotilla state. Health-probed OHM (v0.18.0 ok). Confirmed flotilla deploy ohm-rfc-app venv at .venv/bin/ohm-rfc-app-flotilla.
Asked the operator two questions in one tool call:
- Session ID — other sessions claimed 0015.0 + 0016.0; driver took 0017.0.
- OTC sign-in test in a fresh incognito window — "Code arrived, sign-in worked" — first-time-since-launch confirmation of the Wave 7 v0.18.0 chain working end-to-end. The Wave 7 load-bearing gate is closed.
Asked a follow-up: what are 0015.0 and 0016.0 doing, so Wave 8 doesn't collide? 0016.0 is complete (transcript pending publish — at this point not yet on disk locally, but operator confirmed it's done); 0015.0 is troubleshooting an OTC-not-being-sent edge case described as a config issue, no code changes, and the operator was going to context-switch to 0015.0 directly. That cleared the way for #30 since neither competing session was touching the rfc-app or session-history surfaces.
Arc 2 — Propose Wave 8 scope + settle the open #30 decisions
Recommended Wave 8 = #30 since the operator had marked it NEXT and nothing else was more pressing. Proposed shape: three parallel subagents touching three different repos (session-history restructure + rfc-app v0.19.0 + ohm-infra publish-script + protocol updates).
Asked the operator's two open session-time questions from the roadmap text:
- Repo host: gitea-only / gitea+GitHub mirror / GitHub canonical. Operator chose gitea-only.
- Fetch mode: runtime fetch with cache (recommended) / build-time bundle. Operator chose runtime fetch with cache.
Then asked two coordination questions: 3. Is restructuring the session-history repo safe to start now? (The handoff's "don't do transcript renames yet — another session is running" caveat might still apply.) Operator chose "Wait — I'll signal when clear" for the restructure subagent specifically; authorized the other two subagents to proceed. 4. Session titles + README prose drafting: subagent drafts / operator hand-writes / hybrid. Operator chose subagent drafts both, operator reviews.
Renumbered the subagent labels by dispatch order per protocol §5: subagent dispatched first = .1, second = .2. So:
- 0017.1 = rfc-app v0.19.0 code subagent (dispatched first)
- 0017.2 = session-history restructure subagent (held until operator signal)
Driver does the ohm-infra publish-script + protocol updates inline (small enough; not a forked subagent — captured in this transcript).
Arc 3 — Driver-inline edits: publish-script + SESSION-PROTOCOL.md
Read the existing scripts/publish-transcript.sh. Rewrote the body to:
- Parse out
NNNNfromSESSION-NNNN.M-TRANSCRIPT-…mdvia bash regex^SESSION-([0-9]{4})\.[0-9]+(\.[0-9]+)*-TRANSCRIPT. - For numeric form: place transcript in
NNNN/subfolder (mkdir -p); for legacy letter form: place at repo root (backward compat). - Upsert
sessions.jsonvia inlinepython3heredoc (pure stdlib, no jq): ifNNNNkey is missing, add{"NNNN": {"title": ""}}, sort keys numerically, write 2-space-indented JSON with trailing newline. Ifsessions.jsonis malformed JSON, fail cleanly with exit 2. - Compute commit message based on what's in the diff (
add NNNN/SESSION-… + sessions.json: add entry for NNNN, or just one of those). - Use
git status --porcelainafter staging to detect any change; no-op exit 0 if nothing changed. - Keep dry-run behavior; expand its logging to name both the transcript-action and the manifest-action.
Smoke-tested the regex locally (numeric forms parse, legacy letters reject) and the Python upsert in isolation (first-add returns 1, re-add returns 0, malformed JSON exits 2, sort order works).
Edited SESSION-PROTOCOL.md:
- §1 gained a "Published repo layout (Session 0017.0 amendment, 2026-05-28)" subsection describing the
NNNN/folder shape, thesessions.jsonschema, and the "local files stay flat — folders are publish-time" rule. Documents the decision to retain the fullSESSION-NNNN.M-TRANSCRIPT-…mdfilename inside folders (no trim of theSESSION-prefix; overrides the roadmap example). - §5 gained a short "Published-repo placement" note saying subagent transcripts inherit their parent's
NNNN/folder (publish-script handles this by parsing the leadingNNNN).
Documented that the local working files at ~/git/ohm-infra/SESSION-… keep the flat shape — folders are a publish-time gesture only.
Arc 4 — Dispatch subsession 0017.1 (rfc-app v0.19.0)
Dispatched a forked general-purpose subagent in the background with a self-contained prompt:
- Pre-assigned subsession ID
0017.1. - Repo
/Users/benstull/git/rfc-app, branchfeature/v0.19.0-docs-sessions-browseroffmain@ac3513a. - Settled decisions: gitea-only, runtime fetch + cache.
- Concrete scope (backend endpoints + TTL cache + frontend route tree + flyout nav + CHANGELOG + version bumps).
- Hard rules: do NOT tag, do NOT bump ohm-rfc pin, do NOT push to benstull mirror, do NOT deploy. Driver handles all of those after 0017.2 also returns.
- Transcript expectations per §5 (write
SESSION-0017.1-TRANSCRIPT-…mdBEFORE returning report). - Pasted roadmap item #30 verbatim for self-containment.
Subagent ran ~15 minutes and reported back:
- Branch
feature/v0.19.0-docs-sessions-browser@477f496, pushed to origin only. - 313 backend pytest passing (18 new in
test_docs_sessions_vertical.py); frontendnpm run buildgreen; no frontend test framework (per dispatch); dev-server smoke not run (sandboxed agent, no browser — flagged for driver). - Settled in-session: per-session listing source = separate
/api/docs/sessions/<NNNN>/indexendpoint (not extending the manifest, keeps it cheap); negative-cache 404s (rationale: at ship time the repo restructure is racing the rfc-app deploy; empty-state path may be hot for hours); the dispatch'spyproject.tomlwas a non-op (repo usesbackend/requirements.txtonly — canonical version sources areVERSION+frontend/package.json#version, both bumped). - 5 §19.2 candidates surfaced (
package-lock.jsonversion drift, missingpyproject.toml, validator-leak, CHANGELOG style drift, cache-invalidation seam). - Transcript at
SESSION-0017.1-TRANSCRIPT-2026-05-28T08-52--2026-05-28T09-07.md. - Notable in-flight snag (full detail in its transcript): the shared
app_with_fake_giteafixture monkeypatcheshttpx.AsyncClientglobally on the module — the first-attempt test fixture captured areal_client_cls = httpx.AsyncClientthat was already the gitea-patched wrapper; subagent fixed by importing the truly-unpatchedAsyncClientfromhttpx._clientdirectly._UpstreamHandlergained a host-marker filter so reconciler-side gitea calls don't inflate cache-hit assertions.
Driver verified deliverables on disk (don't depend on report-back text per §5 amendment):
feature/v0.19.0-docs-sessions-browserexists locally at477f496, matches origin.VERSION=0.19.0;frontend/package.jsonversion =0.19.0;mainuntouched atac3513a.- Transcript exists at the named path, 350 lines, header matches expected shape.
- CHANGELOG diff: 12 lines added; full v0.19.0 entry with
Upgrade steps:block. - Backend diff: 855 LOC across
api.py+docs_sessions.py+ tests. - Frontend diff: 864 LOC across
App.css/App.jsx/api.js/ 5 new components /analytics.js(+Docs.jsxdeletion).
Noticed one quick fix the subagent flagged as §19.2 (## v0.19.0 vs ## 0.18.0 style mismatch — every prior CHANGELOG header drops the v prefix; the new entry having v was MY dispatch-prompt typo, not architectural). Made a small driver-inline commit on the feature branch normalizing the header — bb5137f CHANGELOG: normalize 0.19.0 header (drop 'v' prefix to match surrounding style), pushed to origin. The other §19.2 candidates are genuinely architectural and stay deferred.
(One operator-config note: git emitted the "your name and email were configured automatically based on hostname" warning for the commit — benstull@mac.lan rather than ben@wiggleverse.org. Per the "no git config edits" hard rule I left it; same identity shape as the subagent's commits and as 0017.2's later commit. Operator can normalize globally if desired.)
Arc 5 — Operator clears the restructure gate; dispatch 0017.2
Operator said "we're good to go. Go for it" — clearing 0017.2's hold.
Dispatched the second forked general-purpose subagent in the background:
- Pre-assigned subsession ID
0017.2. - Mission: restructure
wiggleverse/ohm-session-history(gitea SSH remote atssh://git@git.wiggleverse.org:2222/wiggleverse/ohm-session-history.git); one atomic commit onmain. - Settled decisions baked into the prompt (keep
SESSION-prefix in folder filenames; gitea-only). - README ingredients (per roadmap #30): how OHM is built, why transcripts are public, the verbatim "Oh and Jan, your joke is in there somewhere." line, link to canonical repo. Subagent drafts; operator reviews via embedded
<!-- operator: rewrite this section in your voice -->markers. - Title-drafting heuristic: read each transcript's
> Goal:/> Outcome:header block. Driver supplied starter sketches for 0001 + 0009–0014; subagent filled in 0002–0008 + 0015 from the actual transcripts.
Subagent ran ~5 minutes and reported back:
- Public repo
main@ad01c08(fast-forward push fromb6a7b7d); 19 transcriptsgit mv'd into 15NNNN/folders, rename detection 100%; zero legacy letter-form at root (Session 0014.0's #23 rename had already cleared them). sessions.json: 15 entries, every session titled, no placeholders. Did NOT include 0016/0017 (unpublished in the public repo as of 0017.2's run).- README.md drafted with 3 operator-review markers on key sections (~520 words, includes canonical-link callout + publish-script how-to + license pointer).
- Transcript at
SESSION-0017.2-TRANSCRIPT-2026-05-28T09-10--2026-05-28T09-15.md. - 3 §19.2 candidates (publish-script placeholder-on-first-publish contract; README ↔ /docs/sessions/about render contract; local-vs-published shape asymmetry).
- Cosmetic note: committer identity
Ben Stull <benstull@mac.lan>(same as 0017.1's and the driver inline commit).
Driver verified:
- Transcript exists at named path, 13.5 KB.
- Gitea raw probe:
sessions.jsonreturns 200;README.mdreturns 200;0014/SESSION-0014.0-TRANSCRIPT-2026-05-28T07-01--2026-05-28T08-25.mdreturns 200. sessions.jsoncontent sane (15 entries; titles read like decent first drafts; 0013 is a semicolon-list — likely worth compression; 0014 uses subagent's phrasing rather than §1-example verbatim form — operator's call).
Arc 6 — Merge, tag, push, pin, deploy, verify
With both subagents returned and verified, executed the coordinated landing:
git checkout mainon rfc-app,git merge --no-ff feature/v0.19.0-docs-sessions-browser -m "Merge feature/v0.19.0-docs-sessions-browser"→ merge commit69a166a(16 files changed, 1732+/57-).git tag v0.19.0on the merge commit.git push origin main v0.19.0→ success.git push benstull main v0.19.0→ success.cd ohm-rfc && echo "0.19.0" > .rfc-app-version && git commit -m "Pin rfc-app 0.19.0 — Wave 8 deploy: /docs nav + on-site sessions browser (#30)"→ commitde17e79. (Local main was at9c47792, not74a3e12as seen at session start — operator landed at least one more ohm-rfc commit in between; commit graph stayed clean.)git push→ success..venv/bin/ohm-rfc-app-flotilla deploy ohm-rfc-app→ hit the §19.2 SSE-keepalive SSH-watchdog timeout at phase 7 (SshError: ssh to ohm-app timed out after 60.0s running: 'sudo sh -c ... systemctl restart ohm-app.service ...'). 4th occurrence of this pattern (Session 0009.0 §19.2 / Session 0014.0 carry-forward).- Verification via
/api/health(not the flotilla exit code, per Session 0014.0's lesson): first probe right after the timeout returned 502 from nginx (service was mid-restart); second probe 15s later also 502; but then.venv/bin/ohm-rfc-app-flotilla deploy status ohm-rfc-appreturnedHTTP 200 version=0.19.0 status=ok. Re-probed the public URL — 5 consecutive 200s, all{"version":"0.19.0","status":"ok"}, ~190 ms each. So: deploy succeeded; the 502 window was transient (a few seconds while the service was finishing restart); SSH watchdog falling off doesn't reflect actual deploy outcome.
(Side observation: an ssh ohm-app attempt to read journalctl failed "Could not resolve hostname ohm-app" — my local SSH config doesn't have the alias the flotilla CLI uses internally. flotilla deploy status was the canonical path anyway. Not blocking.)
deploys.id row for this deploy will read aborted-on-SSH-timeout despite the service running healthy at v0.19.0 — same dichotomy as deploys.id 23/24/25 from Session 0014.0.
Arc 7 — Operator asks for the next-session prompt mid-arc; transcript wraps after
Operator asked for the closing-handoff prompt at the moment the deploy verification finished. Driver drafted it inline in the conversation (full prompt included below in "Prompt the operator can paste into the next Claude Code session"). Browser-side verification of /docs/sessions/about + a per-transcript view is the next session's first gesture, not 0017.0's — the deploy is up; the on-site rendering is the operator's eyeball confirmation.
Then this transcript got written (you are reading it).
Cut state (end of session)
| rfc-app | main @ 69a166a (merge commit); tag v0.19.0; pushed to origin + benstull mirror |
| ohm-rfc | main @ de17e79 — .rfc-app-version=0.19.0 |
| ohm-rfc-app-flotilla | main @ 417b6c5 — no flotilla code change this session (CLAUDE.md modified file from session start was carried through unchanged) |
wiggleverse/ohm-session-history |
main @ ad01c08 — restructured into 15 NNNN/ folders + README.md (with 3 operator-rewrite markers) + sessions.json (15 entries, all titled) |
| OHM live | v0.19.0 healthy (/api/health 200, {"version":"0.19.0","status":"ok"}); deploys.id row = aborted-on-SSH-timeout per §19.2 (h) below |
| ohm-infra | scripts/publish-transcript.sh extended for NNNN/ folders + sessions.json upsert; SESSION-PROTOCOL.md §1 + §5 amended. (Not a git repo locally; on-disk changes are the artifact.) |
| Session 0017 transcripts on disk | SESSION-0017.0-TRANSCRIPT-2026-05-28T08-50--2026-05-28T09-22.md (this file), SESSION-0017.1-TRANSCRIPT-2026-05-28T08-52--2026-05-28T09-07.md, SESSION-0017.2-TRANSCRIPT-2026-05-28T09-10--2026-05-28T09-15.md. All three publish via publish-transcript.sh at session close. |
| Wave 8 ledger | Status |
|---|---|
| #30 docs nav + on-site sessions browser + session-history restructure (rfc-app v0.19.0 + ohm-session-history reshape) | ✅ shipped |
§19.2 candidates surfaced
a. frontend/package-lock.json version drift (0017.1). Lockfile top-level "version" reads 0.15.0 while frontend/package.json#version is 0.19.0. Cosmetic but ugly; symptom of no automated lockfile-discipline check. Repo doesn't run npm install as part of the version bump, so the lockfile drifts on every minor.
b. rfc-app backend has no pyproject.toml (0017.1). Dispatch named one as a version source; the repo uses backend/requirements.txt only. Canonical version sources are VERSION + frontend/package.json#version. If a backend pyproject.toml is desired (for editable installs, build-tool integration, etc.), it earns its own small release.
c. docs_sessions.py private validators leak into the route layer (0017.1). _is_valid_session_dir / _is_valid_transcript_filename are referenced from route handlers; consolidating into a public validate_path() would tighten the seam.
d. docs_sessions cache has no external invalidation (0017.1). In-process TTL only; no reset_cache() admin endpoint or test seam. Operationally fine (TTL is short); developer-experience worth improving.
e. publish-transcript.sh should auto-populate sessions.json placeholder entries on first-publish (0017.2). Already partially shipped in the driver-inline edit (publish-script upserts {"NNNN": {"title": ""}} if the key is missing). Worth confirming the contract end-to-end against a real fresh-session publish; surfaced as a §19.2 mostly to track the testing follow-up.
f. Contract between README and rfc-app /docs/sessions/about renderer (0017.2). Operator-review HTML comments (<!-- ... -->) should render as nothing on-site (markdown stripping). Worth confirming in the next session's first browser-verification gesture; if they show up as raw text the renderer needs a small fix.
g. Local-vs-published shape asymmetry (0017.2). Local working dir ~/git/ohm-infra/ stays flat; published repo is nested in NNNN/ folders. Already documented in SESSION-PROTOCOL.md §1, but worth a one-line callout if future drivers get confused.
h. SSE-keepalive SSH-watchdog timeout — 4th occurrence (driver). Hit at phase 7 of every recent deploy: SIGTERM doesn't drain SSE connections in under 60 s, the SSH watchdog falls off, flotilla reports aborted, the service actually restarts and comes up healthy. flotilla v1.2.0 candidate: pre-drain SSE connections (or raise the watchdog to e.g. 180 s) before systemctl restart. Driver verification now leans entirely on /api/health + flotilla deploy status post-deploy rather than the flotilla exit code.
i. Driver-inline commit identity drift (driver). Three commits this session (one driver-inline CHANGELOG fix + two subagent merges + the pin bump) carried Ben Stull <benstull@mac.lan> as the committer rather than the operator's preferred identity. Per the hard rule, no git config edit; operator can rewrite if desired. Worth surfacing as an operator-tooling §19.2: a one-line "ensure git identity is set on this machine" gesture would prevent it.
j. publish-transcript.sh sessions.json formatting churn (driver, noticed at publish-time after 0017.2's restructure had already shipped). The script's inline-Python upsert uses json.dump's default indent=2 (expands every entry to multi-line) AND default ensure_ascii=True (escapes em-dashes / § / en-dashes as — / § / –). 0017.2's subagent had hand-written sessions.json with compact one-line entries per session + raw UTF-8. The first publish-time upsert (0017.0's transcript publish, which added the 0017 placeholder) rewrote the file in the expanded ASCII-escaped form, so the operator's next edit starts from that shape rather than the subagent's. Fix is one-line in publish-transcript.sh: json.dump(out, f, indent=2, ensure_ascii=False) plus a small custom emitter to keep each session's { "title": "…" } on one line. Cosmetic; no functional impact.
What lands on the operator's plate
- Browser-verify
/docs/*surfaces (next-session first gesture). Concrete URLs in the next-session prompt below. ~5 minutes. - Rewrite the 3 README.md placeholder sections on
wiggleverse/ohm-session-history(sections marked with<!-- operator: rewrite this section in your voice -->). Direct commit to main; no PR ceremony needed. - Refine
sessions.jsontitles if desired. 0013's title is a semicolon-list of three subagent workstreams (may want compression); 0014's title is the subagent's phrasing rather than the §1-example verbatim form. Add a title for 0017 (currently absent from the manifest — it'll be added as{"title": ""}when this transcript publishes; operator fills in something like"Wave 8 driver — docs nav + on-site sessions browser (#30)"). - Merge the two Session-M docs PRs still awaiting operator merge:
- rfc-app
feature/contributing-and-spec-analytics@213f686 - ohm-rfc
feature/contributing-roadmap-guide@f26fae4
- rfc-app
- DMARC Phase A → Phase B: ≥1 week of clean
ruareports atben.stull@wiggleverse.orgsince Session 0014.0; ETA 2026-06-04 to flipp=quarantine. - #1 VM rename + flotilla v1.2.0 SSE-keepalive drain (combined session) — the watchdog pattern is now 4× confirmed; worth fixing alongside the rename when the maintenance window opens.
- Update ohm-rfc/ROADMAP.md: strikethrough #30 row in the version-target table; link to v0.19.0 + the deploys.id row (when one materializes — currently aborted-on-timeout).
Prompt the operator can paste into the next Claude Code session
You are the OHM roadmap driver, Session 0018.0. Read this whole prompt
before doing anything.
# What Session 0017.0 shipped
Wave 8 was roadmap item #30 — the docs nav + on-site sessions browser
+ session-history repo restructure — picked because the operator
marked #30 **NEXT** in ROADMAP.md and the load-bearing OTC sign-in
gate (the Wave 7 / v0.18.0 carry-forward) was confirmed working
end-to-end at session start. Three parallel subagents:
1. **flotilla / ohm-infra** (driver inline) — `publish-transcript.sh`
extended to place new transcripts into their `NNNN/` subfolder and
upsert `sessions.json` (a top-level title manifest, keyed by
4-digit `NNNN`, value `{"title": ""}`). Backward-compat: legacy
letter-form transcripts still land at repo root. JSON upsert is
pure stdlib via inline `python3` heredoc, no jq dep.
SESSION-PROTOCOL.md §1 gained a "Published repo layout" amendment
documenting the new folder shape, the `sessions.json` schema, and
the "local files stay flat — folders are publish-time" rule. §5
gained a short "Published-repo placement" note saying subsession
transcripts inherit their parent's `NNNN/`.
2. **subsession 0017.1 — rfc-app v0.19.0** (merged + tagged + pushed).
Backend: `/api/docs/sessions/{manifest,about,<NNNN>/index,<NNNN>/<file>}`
with in-process TTL cache (60s manifest, 5min content; both
env-tunable via `OHM_DOCS_SESSIONS_MANIFEST_TTL_SEC` /
`OHM_DOCS_SESSIONS_CONTENT_TTL_SEC`). Negative caching for 404s
(rationale: at ship time the repo restructure is racing the rfc-app
deploy; empty-state path may be hot for hours). Gitea raw base
configurable via `OHM_SESSION_HISTORY_RAW_BASE`. 18 new pytest
cases (`test_docs_sessions_vertical.py`, 313 backend total green).
Frontend: `/docs` → redirect to `/docs/user-guide`; `/docs/sessions`
→ redirect to `/docs/sessions/about`; `/docs/sessions/<NNNN>` and
`/docs/sessions/<NNNN>/<filename>` for index + transcript view;
`DocsLayout.jsx` with left-side flyout nav driven by the manifest;
reuses the v0.14.0 react-markdown renderer; Amplitude `Doc Viewed`
events + `data-amp-track-*` decoration. Branch
`feature/v0.19.0-docs-sessions-browser` merged to main at `69a166a`,
tag v0.19.0, pushed to origin + benstull mirror.
3. **subsession 0017.2 — wiggleverse/ohm-session-history restructure**
(one atomic commit `ad01c08` on `main`, fast-forward push). 19
transcripts `git mv`'d into 15 `NNNN/` folders (rename detection
100%); `0013/` holds 4 transcripts (driver + 3 subagents from
Session 0013.0); `0014/` holds 2 (driver + 1 subagent). Top-level
`README.md` rewritten with 3 `<!-- operator: rewrite this section
in your voice -->` markers (sections: "How OHM gets built", "Why
transcripts are public" — which includes the verbatim
"Oh and Jan, your joke is in there somewhere." line — and
"What's in the repo"). Top-level `sessions.json` drafted with 15
entries, every session titled (no placeholders); titles read off
each transcript's `Goal:`/`Outcome:` header block. Operator-review
notes: 0013's title is a semicolon-list of three subagent
workstreams (may want compression); 0014's title is the
subagent's phrasing rather than the §1-example verbatim form.
Filename convention inside each folder: full
`SESSION-NNNN.M-TRANSCRIPT-…md` form retained (no trim of the
`SESSION-` prefix). The roadmap example showed trimmed form;
Session 0017.0 settled on retained-prefix for file-self-
identification. Document in SPEC.md if operator wants to flip.
# Cut state at handoff
- rfc-app `main`: `69a166a` (merge) → tag `v0.19.0` published; pushed
to origin + benstull mirror.
- ohm-rfc `main`: `de17e79` — `.rfc-app-version=0.19.0`.
- ohm-rfc-app-flotilla `main`: `417b6c5` (no flotilla code change
this session).
- wiggleverse/ohm-session-history `main`: `ad01c08` — restructured
into `NNNN/` folders + README.md + sessions.json at root.
- OHM live: **v0.19.0 healthy** (`/api/health` returns
`{"version":"0.19.0","status":"ok"}`).
- deploys.id row for v0.19.0: aborted-due-to-SSH-timeout (the
§19.2 SSE-keepalive pattern fired again; service IS healthy at
v0.19.0; the aborted row reflects the SSH watchdog falling off,
not the deploy itself — 4th occurrence; flotilla v1.2.0
candidate).
- ohm-infra: `scripts/publish-transcript.sh` extended;
`SESSION-PROTOCOL.md` §1 + §5 amended (NOT in a git repo locally,
so no commit; the files ARE what they are on disk).
- DMARC Phase A unchanged from Session 0014.0 (`p=none`, `pct=100`,
TTL=3600s, `rua=mailto:ben.stull@wiggleverse.org`). 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
- ✅ OTC sign-in end-to-end (Session 0017.0 operator-confirmed at
session start — the Wave 7 / v0.18.0 carry-forward gate).
- ✅ v0.19.0 service health (`/api/health` returns 0.19.0).
- ✅ wiggleverse/ohm-session-history restructure (gitea raw probes
on `sessions.json`, `README.md`, and a sample 0014/ transcript
all return 200).
- ⏸ End-to-end `/docs/*` surfaces in a real browser **not yet
operator-confirmed**. Session 0017.0 ended before the operator
loaded the site. First gesture this session: have the operator
load these URLs in a fresh browser tab:
- `https://ohm.wiggleverse.org/docs` → should redirect to
`/docs/user-guide` (existing v0.14.0 content, no behavior change
beyond the URL move).
- `https://ohm.wiggleverse.org/docs/sessions/about` → renders the
README.md from `wiggleverse/ohm-session-history`. Expect the
3 operator-review HTML comments to render as nothing on-site
(one of the §19.2 candidates is to verify this; if they're
visible as raw text, that's a markdown-renderer bug to fix).
- `https://ohm.wiggleverse.org/docs/sessions/0009` → session index
page for Session 0009.0 (the multi-wave driver). Should show
"Session 0009.0 — multi-wave driver (rfc-app v0.4–v0.13, skipping
vacants)" as the title from sessions.json.
- `https://ohm.wiggleverse.org/docs/sessions/0013` → should show
4 transcripts (driver + 3 subagents) and resolve the right list
via the per-session `/index` endpoint.
- `https://ohm.wiggleverse.org/docs/sessions/0014/SESSION-0014.0-TRANSCRIPT-2026-05-28T07-01--2026-05-28T08-25.md`
→ renders Wave 7 driver transcript in-browser.
- Flyout nav: open from any /docs/* route; on mobile, confirm the
drawer toggles.
- ⏸ Operator hasn't reviewed the README draft prose or sessions.json
titles — they're shipped as drafted; refinement is a follow-up.
# Wave 9 candidates (priority is operator's call)
1. **Verify /docs/* surfaces in browser** (above). Five minutes if
they work; longer if not.
2. **Operator rewrites the 3 README.md placeholder sections** on
`wiggleverse/ohm-session-history`. Operator-only gesture; commit
directly to main.
3. **Operator refines sessions.json titles** if desired (0013's
semicolon-list, 0014's phrasing, or anywhere else); also fills in
the empty title for 0017 (added as `{"title": ""}` when 0017.0's
transcript published).
4. **Operator merges the two M docs PRs**.
5. **#1 VM rename + flotilla v1.2.0 SSE-keepalive drain** — the
§19.2 SSE-keepalive timeout pattern was hit a 4th time this
session; worth fixing alongside the rename. flotilla v1.2.0
would pre-drain SSE connections before `systemctl restart` to
close the watchdog gap.
6. **DMARC Phase A → Phase B (`p=quarantine`)** — ≥1 week of clean
rua data; ETA 2026-06-04.
7. **#20 ops side**: delete stale `wiggleverse/meta` hook on
deprovisioned `rfc.wiggleverse.org`.
8. **#18 ops side**: bounce-source wiring (Path A or B in the
runbook).
9. **#21 Part A Amplitude audit** — defer to ~2026-06-04 for a week
of post-fix dashboard data (Amplitude + OTC both now confirmed
working).
10. **#22 pro-consent copy** — operator-drafted + counsel-reviewed;
subagent wires once approved.
11. **#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.
12. **#17 repo naming alignment** — operator decides Q1 first.
# §19.2 candidates surfaced in Session 0017.0
From subsession 0017.1 (rfc-app v0.19.0):
a. `frontend/package-lock.json` top-level "version" field drifted
(lockfile reads `0.15.0` while `package.json` is `0.19.0`).
Cosmetic but ugly. Symptom of no automated lockfile-discipline
check.
b. rfc-app backend has no `pyproject.toml` — the dispatch assumed
one. Repo uses `backend/requirements.txt` only. Canonical version
sources are `VERSION` + `frontend/package.json#version`.
c. `docs_sessions.py`'s private validators (`_is_valid_session_dir`,
`_is_valid_transcript_filename`) leak into the route layer —
consider consolidating into a public `validate_path()`.
d. `docs_sessions` in-process cache cannot be invalidated externally
without a process restart or a `reset_cache()` test seam.
Operationally fine (TTL is short); developer-experience worth
improving.
From subsession 0017.2 (session-history restructure):
e. publish-transcript.sh should auto-add `sessions.json` placeholder
entries on first-publish for a new NNNN. **Already partially
shipped** in 0017.0's publish-script extension (the upsert logic
adds `{"NNNN": {"title": ""}}` if the key is missing). Worth
confirming the contract end-to-end.
f. Contract between README and rfc-app `/docs/sessions/about`
renderer — operator-review HTML comments (`<!-- ... -->`) should
render as nothing on-site. Worth confirming in the first-test
gesture.
g. Local-vs-published shape asymmetry (local flat in
`~/git/ohm-infra/`, published nested in `NNNN/` folders) is
already documented in SESSION-PROTOCOL.md §1; worth surfacing as a
one-line callout if it confuses future drivers.
From driver:
h. The §19.2 SSE-keepalive SIGTERM holding past the 60s SSH watchdog
— hit AGAIN this session (4th occurrence). flotilla v1.2.0 should
pre-drain SSE connections before `systemctl restart`. Driver
verification now leans entirely on `/api/health` post-deploy
rather than the flotilla exit code.
i. Driver-inline commit identity drift (`benstull@mac.lan` rather
than `ben@wiggleverse.org`). Per hard rule no `git config` edit
this session; surfaced for operator tooling.
j. `publish-transcript.sh` `sessions.json` formatting churn. The
script's inline-Python upsert uses `json.dump`'s default
`indent=2` (every entry expands to multi-line) and default
`ensure_ascii=True` (em-dashes / `§` / en-dashes escape to
`\uXXXX`). 0017.2's subagent had hand-written compact one-line
entries with raw UTF-8; the first publish-time upsert (0017.0's
publish, adding the `0017` placeholder) rewrote the file in the
expanded ASCII-escaped form. Operator's next edit starts from
that shape. One-line fix: `json.dump(out, f, indent=2,
ensure_ascii=False)` + a small custom emitter to keep each
session on one line. Cosmetic only; no functional impact.
# 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** (binding from Session
0013.0 onward): forked subagents write their own transcripts
BEFORE returning their report. Driver re-verifies deliverables on
disk rather than depending on the report-back text.
- **Protocol amendments must land with the code change.**
- **Naming**: this is Session 0018.0. Driver transcript:
`SESSION-0018.0-TRANSCRIPT-<start>--<end>.md`. Subagent transcripts:
`SESSION-0018.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 0018.0
1. Read `~/git/ohm-infra/SESSION-PROTOCOL.md` (the §1 + §5
amendments from Session 0017.0 are the relevant new content).
2. Read `/Users/benstull/projects/wiggleverse/ohm-rfc/ROADMAP.md`
end-to-end. #30 is the most recent item shipped (strikethrough
pending — operator may or may not have updated the version-target
table; if not, do it on the next ohm-rfc edit you make).
3. Read the Session 0017.0 transcript at
`~/git/ohm-infra/SESSION-0017.0-TRANSCRIPT-2026-05-28T08-50--2026-05-28T09-22.md`
for the full triage detail (this prompt is the summary).
4. Have the operator load `/docs/sessions/about` and at least one
`/docs/sessions/<NNNN>/<filename>` in a fresh browser tab. That's
the load-bearing first test.
5. Pick Wave 9's shippable scope. The roadmap doesn't have an
explicit **NEXT** marker after #30 ships, so the picking is the
operator's call.