8.0 KiB
Session 0083.0 — Transcript
App: ohm Start: 2026-06-06T01-49 (PST) End: 2026-06-06T07-59 (PST) Type: coding Mode: autonomous (yolo) Driver: Ben Stull (+ Claude Opus 4.8)
Launch prompt
Finish §22 S6 remainder: request-to-join + cross-collection inbox (§22.8), then
per-type surfaces (§22.4a items 1&3). Build by analogy to shipped §28
contribution_requests + S4 memberships.grant.
Outcome
The §22 S6 remainder is complete; the deployment→project→collection three-tier
model is now realized in both code and SPEC.md. Then two follow-up tasks at the
operator's direction: a roadmap question, and a roadmap cleanup.
- §22.8 request-to-join + the cross-collection inbox — shipped v0.46.0
(PR #24,
origin/main=1c17fec). - Per-type surfaces (§22.4a items 1 & 3) — spec pass done (PR #25,
origin/main=b7e23a0) — subsequently superseded (see §Follow-ups). - OHM roadmap Phase G refreshed (ohm-rfc PR #12,
b4a6943).
Pre-state
origin/main(rfc-app) =0140150(S6 core, v0.45.0): the SPEC merge, per-collectionenabled_models(mig 031), the type-driven entry noun.- Two S6 items deferred at v0.45.0 as "wanting a discovery/spec pass first": the per-type surfaces (§22.4a items 1 & 3) and request-to-join (§22.8).
- Clean tree on
main, fully pushed. Three concurrent ohm sessions (0079/0080/0081) in flight (unfinalized placeholders) — noted, proceeded.
The arc — §22.8 (the shipped feature)
1. Understand. Read SPEC.md §22.8 / §22.11 and the design-doc Part E S6
framing; mapped the two analogues — §28 contribution_requests
(api_contributions.py, mig 024) and S4 memberships (api_memberships.py /
memberships.py, the grant + broader-scope-supersedes prune + the
can_invite_at_{project,collection} gates). Engine seam: a join request targets
a (scope_type, scope_id) pair (the memberships vocabulary minus global),
and accept grants a scope role instead of minting an RFC invite.
2–3. Build (backend + frontend).
- Migration
032_join_requests.sql(additive; one-open-per-(scope,requester)). auth.effective_role_at_scope— scope-grain twin ofeffective_scope_role, folding global→project for a project target.notify:_scope_owner_user_ids(upward Owner enumeration = the cross-collection inbox),fan_out_join_request,notify_join_decided, 3render_summarycases.api_join_requests.py—/api/scopes/{scope_type}/{scope_id}/(join-target / request / accept / decline). The request POST is not readability-gated (that's how one joins a gated scope). Registered inapi.py.- Frontend:
api.jsverbs;JoinRequestModal;viewer.can_request_joinon the project + collection viewer blocks; "Request to join" inCollectionDirectory- the
Catalogfooter; the actionableJoinRequestRowinInbox.jsx.
- the
4. Tests + release. test_join_requests_vertical.py (11) +
test_migration_032 (5); frontend api.joinrequests.test.js (4) + two
CollectionDirectory cases. Backend 546 / frontend 36 green; build clean.
VERSION + package.json → 0.46.0; CHANGELOG 0.46.0 ("no upgrade steps"). Branch
feat/s6-join-requests → Gitea-API PR #24 → merged.
The arc — per-type surfaces (spec pass, then superseded)
The goal flagged these as wanting a discovery/spec pass first. Wrote
docs/design/2026-06-06-per-type-surfaces.md (per-type frontmatter schema via a
new entry_schema.py validator; specification Releases view; bdd
scenario/coverage views; BDD scenarios @S7a/@S7b/@S7c; a 3-slice plan).
Branch spec/s7-per-type-surfaces → PR #25 → merged.
Superseded same day. A parallel session (0079–0081) was concurrently writing
docs/design/2026-06-06-configurable-collection-metadata.md, which explicitly
supersedes the per-type-surfaces draft (its D9/D11): the schema model moves from
type-driven to collection-configured fields: + per-entry .meta.yaml
sidecars + faceted filtering. So the per-type-surfaces direction (and the
Next /goal: implement S7a I recorded) is now void; the successor's SLICE-0
will mark per-type-surfaces.md superseded + amend SPEC §22.4a.
Follow-ups (post the first finalize)
The session was finalized once at 02:17, then continued at the operator's direction:
-
Q: "what are all items on the roadmap?" Read the canonical
ben.stull/ohm-rfc/ROADMAP.md(43 numbered items, Phases A–G + a version-targets table). Reported: ~32/43 shipped; what remains is item 22 (consent copy, operator-blocked), the §22 per-type surfaces (then being reworked), and the v1-gated deploy-safety arc (37–43), plus operational cleanup (33–35). Flagged the Phase G section as stale (didn't reflect S1–S6 or §22.8 shipping). -
Roadmap cleanup (ohm-rfc PR #12, merged
b4a6943). Per the operator — "there won't be types; there will be configurable metadata per collection … do NOT add to roadmap yet, but clean up based on it being the most up-to-date plan." Four surgical Phase-G edits, no new items added, items 1–43 + version-targets table untouched: (1) a 2026-06-06 status note (series continued past v0.39.0 → three-tier, re-sliced S1–S7); (2) slice-status refresh (S1–S6 + §22.8 shipped; old M6 = invite + request-to-join; old M7 = enabled_models + SPEC merge; M4 effectively covered by ohm+ecomm + the two-project test); (3) old M5 → SUPERSEDED by configurable collection metadata (successor draft in flight, not yet roadmapped; bdd coverage = futurerefsurface); (4) cutover block fixed (0.31.5→0.39.0 cutover done, OHM pinned 0.39.0; new gap = v0.40–v0.46 undeployed). Opened for review, then merged on operator request.
Cut state
- rfc-app: my work fully landed —
origin/main=b7e23a0(v0.46.0 + the per-type-surfaces doc), branches deleted. ⚠️ At finalize the shared checkout'smainwas ahead-2 + untrackedcorpus-treespec files — that is the parallel session's WIP (the §5.4 worktree hazard); left entirely untouched (not mine to commit/push). - ohm-rfc: clean on
main=b4a6943(roadmap PR #12 merged), branch deleted. - VERSION 0.46.0. Backend 546 / frontend 36 green.
Deferred decisions / autonomous calls
- §22.8 request POST not readability-gated — deliberate (§22.8: you join a gated scope you were told of). Confident.
join_requests.scope_typeexcludesglobal— a deployment isn't "joined."- Route shape
/api/scopes/{scope_type}/{scope_id}/…— §17 is illustrative, doesn't pin these routes; no SPEC change. - Per-type surfaces delivered as a spec doc, not code — the goal said "want a spec pass first." (Now moot — superseded by configurable metadata.)
- Declined to finalize session 0081 when a finalize-on-goal hook misfired onto it — 0081 is a different (live/parallel) discovery session; finalizing it would fabricate or clobber another driver's record. Left 0079/0080/0081 alone; operator later confirmed ≥1 is the live session they're co-writing with.
- Roadmap PR opened for review (not auto-merged) then merged on operator's "Merge it" — the supersession wording was theirs to steer.
Next session
The per-type-surfaces plan is superseded; the next move is gated on the parallel session's configurable-collection-metadata spec settling.
/goal await the configurable-collection-metadata spec landing (parallel session finishing docs/design/2026-06-06-configurable-collection-metadata.md), then implement SLICE-0 — amend SPEC §22.4a so the entry schema is collection-configured .meta.yaml sidecar fields not type-driven frontmatter; defer item-3 type surfaces (record bdd coverage as a future ref surface); mark 2026-06-06-per-type-surfaces.md superseded; §20 changelog (doc-only) — then SLICE-1 (sidecar storage + dual-read parser + idempotent frontmatter→sidecar migration + malformed-metadata catalog flag). NOTE: that spec is parallel-owned and shares this checkout — use an isolated worktree (§5.4) before starting code.