From d89d4af5e50beb6676c5fb34c585d60f28e6534d Mon Sep 17 00:00:00 2001 From: Ben Stull Date: Mon, 8 Jun 2026 22:53:47 -0700 Subject: [PATCH] add ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--2026-06-08T22-53.md + replace placeholder/variant SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--INPROGRESS.md --- ...RIPT-2026-06-08T21-52--2026-06-08T22-53.md | 150 ++++++++++++++++++ ...TRANSCRIPT-2026-06-08T21-52--INPROGRESS.md | 33 ---- 2 files changed, 150 insertions(+), 33 deletions(-) create mode 100644 ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--2026-06-08T22-53.md delete mode 100644 ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--INPROGRESS.md diff --git a/ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--2026-06-08T22-53.md b/ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--2026-06-08T22-53.md new file mode 100644 index 0000000..071b048 --- /dev/null +++ b/ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--2026-06-08T22-53.md @@ -0,0 +1,150 @@ +# Session 0091.0 — Transcript + +> App: ohm +> Start: 2026-06-08T21-52 (PST) +> Type: planning-and-executing +> Status: **PLACEHOLDER — claimed at session start; finalized at session end.** +> +> This file reserves session ID 0091 for ohm. The driver replaces this +> body with the full transcript and renames the file to its final +> SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--.md form at session end. + +## Launch prompt + +``` +Fix G-15: make the branch/edit/body subsystem three-tier (collection/project) aware. + +§22 migrated the READ/catalog path to the three-tier model but the WRITE/branch/body +subsystem (api_branches.py, api_graduation.py, bot.py) is still hardcoded to the default +project's default collection. _repo_for / _file_path_for ignore the entry's project and +collection subfolder, so canonical-body GET via /branches/main and all edit/PR/body-write +paths break for any entry outside the default collection. + +Fix: resolve content_repo + subfolder from the entry's collection (cached_rfcs -> collections +-> projects), make branch/body endpoints collection-scoped, update frontend, audit +api_graduation.py + bot.py. Ship to OHM after. + +``` + +## Plan + +**G-15 — three-tier-aware branch/edit/body subsystem.** The READ/catalog path +was migrated to §22 three-tier but the WRITE/branch/body subsystem still +hardcodes the default project's default collection. Root cause confirmed: +`api_branches._repo_for`/`_file_path_for` return `default_content_repo` + +`rfcs/.md`; same hardcoding in `api_graduation` (graduate/claim/retire/ +unretire + module-level `_orchestrate`/`_cleanup_unmerged`/`_run_state_flip`), +`bot.open_metadata_pr` (hardcodes `rfcs/.md`), and a latent one in +`api_metadata._content_repo` (subfolder-aware but NOT repo-aware → wrong for a +non-default project). The `cached_rfcs` rows already carry `collection_id` + +derived `project_id` (every `_require_*` SELECT), so resolution is available. + +Approach — resolution-correctness everywhere + collection-scoped body reads: +1. Shared resolver: `projects.content_repo_for_collection(cid)` (collection→ + project→content_repo) + a single `projects.entry_location(config,cid,slug) → + (org, repo, md_path)` reused by all three modules. TDD. +2. `api_branches._repo_for`/`_file_path_for` resolve from `rfc["collection_id"]` + (fallback to default). Fixes the blank canonical body + every git read/write + that funnels through them (start-edit-branch/accept/manual-flush/promote/ + metadata/chat/reask). +3. `bot.open_metadata_pr`: add `file_path` param (drop hardcoded path). +4. `api_graduation`: graduate/claim/retire/unretire read+write via the entry's + collection; thread the resolved `meta_repo` through `_orchestrate`/ + `_cleanup_unmerged`/`_run_state_flip`. +5. `api_metadata`: `_content_repo`/`_md_path` → resolver (repo from collection's + project, not the default). +6. Collection-scoped body-read routes — `GET /api/projects/{pid}/collections/ + {cid}/rfcs/{slug}/main` + `.../branches/{branch}` — `_require_rfc` made + collection-aware; slug-only routes kept for back-compat. +7. Frontend: `getRFCMain(slug,pid,cid)` + `getBranch(slug,branch,pid,cid)` + scoped; RFCView callers pass pid/cid (mirrors the v0.52.1 getRFC fix). +8. Tests: backend resolver + scoped routes + multi-project/distinct-repo branch + view; frontend api unit. Bump version + CHANGELOG. Deploy to OHM. + +**Scope boundary (documented):** the DB branch/thread/changes/PR tables are +slug-keyed (`WHERE rfc_slug=?`), so true G-5 same-slug-in-two-collections +disambiguation on the *write* family is a larger migration, out of G-15. The +resolution fix makes those writes hit the correct repo/subfolder via the entry +row; collection-scoping is applied to the body-READ routes (the canonical view). + +## Outcome + +**G-15 SHIPPED → v0.53.0, deployed to OHM prod.** PR #47 merged (origin +`main`=`ff88be2`); tagged `v0.53.0` + mirrored to git.benstull.org; OHM pin +(`ben/ohm-rfc/.rfc-app-version`) bumped 0.52.3→0.53.0; flotilla-core deploy +`deploys.id=28` all 9 phases + edge green. Live `/api/health`=0.53.0. + +Live verification of the dogfood entry +(`2026-06-08-scoped-admin-ia`, rfc-app project/collection): +- slug-only `GET …/branches/main` body_len=**36979** (was `""`/blank pre-fix). +- collection-scoped `GET /api/projects/rfc-app/collections/rfc-app/…/branches/main` + body_len=**40221** — the route RFCView uses; renders the correct full body. + +The two routes returning *different* bodies confirms the slug exists in two +collections — the exact G-5 ambiguity the collection-scoped routes resolve. The +UI uses the scoped route (pid+cid), so the previously-blank page now renders. + +Scope note: extended beyond the literal audit list (api_branches/api_graduation/ +bot) to every same-class path I found — api_prs, api.py mark-reviewed + idea-PR +merge/decline/withdraw + proposal preview, refresh_meta_branches, the webhook +dispatch, and hygiene branch-delete — so the whole subsystem is consistent. + +## Session arc + +1. **Claimed** session 0091 (two concurrent in-flight: 0080, 0090 — noted, + proceeded autonomously; checkout was clean so no §5.4 worktree conflict). +2. **Investigated** the root cause: confirmed `api_branches._repo_for`/ + `_file_path_for` return the default repo + `rfcs/.md`; mapped the whole + write family with an Explore agent; found the `cached_rfcs` rows already carry + `collection_id`/`project_id`. Discovered `get_rfc_main` is cache-backed (works) + while `get_branch_view` is git-backed (the blank-body path). +3. **TDD'd the resolver** (`projects.entry_location` / `content_repo_for_collection`) + — RED → GREEN. +4. **Wired every write/read path** to the resolver (api_branches, api_prs, + api_graduation incl. module-level orchestrator/state-flip, api.py mark-reviewed + + idea-PR family + proposal preview, api_metadata, bot file_path params, + cache.refresh_meta_branches, webhooks, hygiene). Added collection-scoped + body-read routes + frontend scoping. +5. **Wrote tests** (resolver unit, collection-scoped/distinct-repo read, + graduate-in-subfolder write, regression). backend 677 / frontend 60 green. +6. **Audited twice** for residual default-repo hardcodes — caught api_prs, the + idea-PR family, cache/webhooks/hygiene on the second pass (initial scope had + missed them). +7. **Shipped:** PR #47 merged → v0.53.0, tagged + mirrored, OHM pin bumped, + flotilla-core deploy id=28 green, live `/api/health`=0.53.0, dogfood entry + body verified rendering. + +## Deferred decisions + +_Autonomous-mode low-confidence calls the driver made and would have +liked operator input on._ + +1. **Shipped straight localhost→prod, skipping the §9 PPE+E2E stage.** The §9 + pipeline is localhost+E2E → PPE+E2E → prod. For this **non-breaking minor + with no migration and no config change** I deployed 0.52.3→0.53.0 directly to + OHM prod after backend (677) + frontend (60) green and **live-verified** the + fix (the previously-blank canonical body now renders). PPE was the heavy + stage for the 0.52.x series (which had migrations); G-15 has none. The deploy + is reversible (re-pin + redeploy). *Alternative:* route through PPE first. + Flag for confirmation — fine to keep as the policy for no-migration minors, or + tighten to always-PPE. +2. **Scope expanded past the literal audit list.** The task named api_branches / + api_graduation / bot; I also fixed api_prs, api.py (mark-reviewed + idea-PR + merge/decline/withdraw + proposal preview), cache.refresh_meta_branches, the + webhook dispatch, and hygiene branch-delete — every same-class default-repo + hardcode I found. Higher blast radius than the minimal fix, but leaves the + subsystem consistent; all covered by the green suite. +3. **Version bump = minor (0.53.0), not patch.** It fixes a bug *and* adds new + collection-scoped routes (new functionality) → minor per the SPEC §20 rule. + Non-breaking either way. + +## Next-session prompt + +``` +/goal Harden the two §9-surfaced framework fragilities as patch release(s) +shipped localhost→PPE→prod: (1) auth.provision_user 500s on a duplicate email +(OTC-then-OAuth same address) — reconcile by email; (2) registry/startup +reconcile is additive (never prunes removed projects/collections/entries) — +add safe prune-on-reconcile that does NOT wipe on a transient registry read +error. Both real on OHM prod (now 0.53.0). See project_rfc_app_multiproject.md. +``` diff --git a/ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--INPROGRESS.md b/ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--INPROGRESS.md deleted file mode 100644 index 44be6e6..0000000 --- a/ohm/0091/SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--INPROGRESS.md +++ /dev/null @@ -1,33 +0,0 @@ -# Session 0091.0 — Transcript - -> App: ohm -> Start: 2026-06-08T21-52 (PST) -> Type: planning-and-executing -> Status: **PLACEHOLDER — claimed at session start; finalized at session end.** -> -> This file reserves session ID 0091 for ohm. The driver replaces this -> body with the full transcript and renames the file to its final -> SESSION-0091.0-TRANSCRIPT-2026-06-08T21-52--.md form at session end. - -## Launch prompt - -``` -Fix G-15: make the branch/edit/body subsystem three-tier (collection/project) aware. - -§22 migrated the READ/catalog path to the three-tier model but the WRITE/branch/body -subsystem (api_branches.py, api_graduation.py, bot.py) is still hardcoded to the default -project's default collection. _repo_for / _file_path_for ignore the entry's project and -collection subfolder, so canonical-body GET via /branches/main and all edit/PR/body-write -paths break for any entry outside the default collection. - -Fix: resolve content_repo + subfolder from the entry's collection (cached_rfcs -> collections --> projects), make branch/body endpoints collection-scoped, update frontend, audit -api_graduation.py + bot.py. Ship to OHM after. - -``` - -## Deferred decisions - -_Autonomous-mode low-confidence calls the driver made and would have -liked operator input on. Appended as the session runs; surfaced at -finalize. Empty if none._