9.7 KiB
Session 0033.0 — Transcript
Date: 2026-05-28 Start: 2026-05-28T19-44 (PST implied) · End: 2026-05-28T20-14 Goal: Advance the OHM roadmap by one disjoint item, parallel-safe. Picked the recommended item: #28 Parts 2 + 3 — offer-to-create-an-RFC for strong-candidate terms, and offer-to-contribute-to-a-pending-RFC.
Outcome: rfc-app v0.29.0 shipped + deployed + verified live on ohm.wiggleverse.org (deploys.id=40). All three #28 parts are now live. One additive migration (024,
contribution_requests); no config / overlay / secret / nginx / systemd change. 374 backend tests green (9 new); frontend builds clean. Merged as PR #3 (8a94e26), taggedv0.29.0, pushed origin + benstull mirror; ohm-rfc pin 0.28.0 → 0.29.0; ROADMAP #28 row struck through (all three parts shipped).
Launch prompt
OHM roadmap driver session, parallel-safe. Claim ID first; read SESSION-PROTOCOL §7 + ohm-rfc/ROADMAP.md. State at hand-off (end of 0031): OHM at v0.27.0; flotilla v1.2.0 merged+tagged. Recommended item: #28 Parts 2 + 3 → target v0.28.0 (possibly split). Avoid conflicting with session 0032 (then running) and v0.27.0's fresh security surfaces. Hard rules: never ask for secret bytes; fresh worktree+venv for rfc-app builds; coordinate the serialized deploy lock + version slot; FF-merge via gitea API; finalize+publish transcript LAST, handoff prompt before publish.
Plan / TODO
- Claim session ID (→ 0033), read SESSION-PROTOCOL §7 + ROADMAP.
- Reconcile stale brief state vs reality (0032 finished; v0.28.0 shipped).
- Explore the #28 surfaces (scanner, propose flow, inbox, invite, roles, Haiku).
- Isolated rfc-app worktree + venv off main; baseline tests green.
- Part 2 — create-RFC offers (scanner candidate bucket + propose pre-fill + gating).
- Part 3 — contribute-to-pending (scanner pending bucket + request flow + inbox actions + accept→invite + decline).
- Tests (9 new), full backend suite, frontend build.
- CHANGELOG + VERSION + frontend mirror.
- Commit → PR #3 → FF-merge → tag v0.29.0 → push origin + benstull.
- ohm-rfc pin bump → deploy → verify live.
- ROADMAP #28 row struck through; worktree cleaned up.
- Finalize + publish transcript (this file).
Pre-session state vs. reality (the brief was stale)
The launch brief said OHM was live at v0.27.0 and that session 0032 was actively running; it also implied v0.28.0 was un-tagged/un-deployed. By session start the picture had moved:
- 0032 had finished (transcript
…18-52--19-13). Its work: IAP-only SSH hardening, flotilla v1.2.0 re-verify, orphaned-db cleanup, and rfc-app v0.28.0 (audit I3 HTML-email guard + I4 async Turnstile) opened as PR #2. The only--INPROGRESSplaceholders left were stale 0026 / 0027 (their security work already shipped as v0.27.0 — the brief said to ignore them). - The operator had since merged, tagged, AND deployed v0.28.0: live
/api/healthreturnedversion=0.28.0, the ohm-rfc pin was0.28.0, and tagv0.28.0existed on main. This removed the version-slot ambiguity the brief worried about — there was no un-tagged predecessor to reconcile, so this session simply took the next slot, v0.29.0.
Claimed session 0033 via claim-session-id.sh --start 2026-05-28T19-44 (push to ohm-session-history is the atomic claim).
Scope decisions (documented in code, CHANGELOG, and ROADMAP)
Two interpretive calls shaped the build; both were made to match Part 1's conservative, false-positive-averse philosophy and were written into the code docstrings so they aren't re-litigated later:
- "Pending RFC" = a super-draft (
cached_rfcs.state='super-draft'), not a pre-merge idea PR. A super-draft is incached_rfcs(so the #12rfc_invitationsFK the accept path reuses resolves), is owned (owners_json— routes the request, names the owner), and has a contribution surface to open. Pre-merge idea PRs satisfy none of those cleanly, so they're deliberately out of scope — a documented future extension. - Part 2 candidate heuristic = multi-word #27-taxonomy tags with no
defining RFC. Multi-word is the same guard Part 1 uses for titles; a
single common tag word (
identity) would turn every prose occurrence into an affordance. The roadmap sanctions "a heuristic OR the Haiku path"; the cheap deterministic tag heuristic was chosen, with capitalized-phrase mining / repeated-term detection / the #27 Haiku (ANTHROPIC_API_KEY) pathway noted as sanctioned-but-deferred extensions (mirroring how Part 1 deferred the curated canonical-terms list).
Turn-by-turn arc
Arc 1 — Claim + orient
Claimed 0033. Read SESSION-PROTOCOL §7, ROADMAP (#28 detail + operating instructions), and 0032's transcript. Confirmed live OHM = v0.28.0, pin = 0.28.0, deploy lock free, no competing active sessions.
Arc 2 — Explore (two parallel Explore agents)
Mapped the surfaces #28 Parts 2+3 touch: the role model (require_contributor
gates propose; permission_state='granted' is "has create rights"); the
RFC lifecycle (idea-PR-open → super-draft → active); the notification /
§15 inbox system (_emit_one chokepoint, render_summary, kinds, the
recipient-scoped inbox); and the #12 owner-invite flow (rfc_invitations
rfc_collaborators, accept writes the membership row). Verified migrations top out at 023 → 024 free.
Arc 3 — Backend build (isolated worktree + venv)
Took a git worktree off main on branch
feature/v0.29.0-pr-rfc-create-contribute with its own .venv; baseline
63 tests green. Then:
rfc_links.pyrewritten to a three-bucket scanner (Termnamedtuplekind∈ active/pending/candidate; precedence active > pending > candidate then longest-match-first). Kept backward-compat with the legacy(key, slug, title)3-tuple so all Part 1 unit tests pass untouched.build_indexnow also gathers super-draft terms (with resolved owner display) and candidate tags.
notify.py—fan_out_contribution_request(one actionable notification per owner) +notify_contribution_decided; three newrender_summarybranches; the inbox list item now carriesextras(recipient-scoped, so safe) for inline who/why/use-case.api_invitations.py— extracted the invite issue path into one reusableissue_invitation(...)chokepoint shared by the manual endpoint and Part 3's accept.api_contributions.py(new) — the GET target + request + accept + decline endpoints; accept firesissue_invitation(role contributor), reusing an existing pending invite if one exists.- migration 024 — additive
contribution_requeststable (partial unique index = one open request per (RFC, user)). - Registered the new router in
api.py.
Arc 4 — Frontend build
LinkedText.jsx renders the two new segment kinds as query-param-routed
affordances (no prop-threading from deep in comment lists): rfc-candidate
→ ?propose=<term> (gated on create rights), rfc-pending → ?contribute= <slug>&term=<term> (gated on signed-in). App.jsx reads the params and
opens ProposeModal (new initialTitle) / the new ContributeRequestForm
(3-field). Inbox.jsx gained a ContributionRequestRow — the first
actionable inbox kind — showing who/why/use-case with Accept/Decline.
api.js + CSS additions. viewer/canCreate threaded into the three
LinkedText call sites (PRView ×2, RFCDiscussionPanel). Frontend builds
clean.
Arc 5 — Tests
3 scanner-bucket unit tests + 6 end-to-end (PR-view segment surfacing; request→accept→invite→notify; decline; owner-cannot-self-request; active-RFC-rejected; eligibility). Full backend suite 374 passing.
Arc 6 — Release + deploy
VERSION + frontend mirror → 0.29.0; CHANGELOG entry with RFC-2119 upgrade
steps. Committed; pushed branch; opened PR #3 via gitea API; FF-merged
(8a94e26); tagged v0.29.0; pushed tag + main to origin and the
benstull mirror (the VM fetches rfc-app from the mirror — tag must be
there before deploy). Bumped ohm-rfc pin 0.28.0 → 0.29.0, pushed. Ran
flotilla deploy ohm-rfc-app — all 9 steps OK, deploys.id=40, verify
4.6s. Live checks: /api/health = 0.29.0; the new
/api/rfcs/{slug}/contribution-target route returns the handler's
{"detail":"RFC not found"} (route wired); GET /api/rfcs still 200.
Arc 7 — Record + cleanup
ROADMAP #28 row struck through (all three parts shipped, with the
deploys.id=40 + v0.29.0 link + the scope decisions); committed + pushed to
ohm-rfc. Worktree removed; shared /Users/benstull/git/rfc-app checkout
fast-forwarded to the merge.
Friction / notes
- The brief's pre-state was stale (OHM was already on 0.28.0, 0032 done). Verifying live state + tags first — rather than trusting the brief — avoided a phantom version-slot reconciliation.
- No secret bytes were needed or requested (this release adds no secret/ config). Hard rule held trivially.
issue_invitationextraction is a small §19.2-style consolidation: the manual invite endpoint and the new accept path now share one chokepoint, so the dup-guard / token / email stay identical.
Cut state (end of session)
- OHM live:
https://ohm.wiggleverse.org/api/health→version=0.29.0,status=ok. Deploy lock free. - rfc-app:
main=8a94e26(PR #3 merge); tagv0.29.0on origin + benstull. 374 backend tests green. - ohm-rfc: pin
.rfc-app-version=0.29.0; ROADMAP #28 struck through.mainpushed (62929b2). - deploys.id=40 records the v0.29.0 deploy.
Operator-plate (manual gestures, if any)
None. v0.29.0 needed no secret/config/overlay/nginx/systemd change; the additive migration 024 ran automatically during the deploy. Nothing is waiting on the operator.