294 lines
15 KiB
Markdown
294 lines
15 KiB
Markdown
# Session 0046.0 — Transcript
|
||
|
||
> Date: 2026-05-30
|
||
> Goal: Fold the operator's two-tier-testing refinement into the
|
||
> published docs — engineering handbook §10.3 + ohm-rfc ROADMAP #38
|
||
> (note on #40) — then, if time, author the rfc-app Tier-1 local-Docker
|
||
> e2e scaffold as #37/#38 groundwork (no VM work).
|
||
>
|
||
> Outcome: **Done. Handbook §10.3 rewritten to the two-tier model
|
||
> (engineering PR #1, merged). ohm-rfc ROADMAP now carries the full
|
||
> two-tier treatment — #38 table row + detailed narrative, #40 narrative
|
||
> + table row (PR #4 core + PR #5 coherence, both merged). rfc-app
|
||
> `e2e/` Tier-1 scaffold authored (PR #4, left OPEN for review). No
|
||
> deploys, no tags, no pin bumps — docs + groundwork only.**
|
||
>
|
||
> Late addendum (post-first-publish): the operator settled four design
|
||
> decisions, recorded (not built — all v1-gated): **#42 auto-rollback =
|
||
> always-on VM-side watcher**; **#37 PPE = completely separate infra**
|
||
> (own micro VM + separate gcloud stack + own Gitea at
|
||
> `ppe.git.wiggleverse.org`, not colocated on prod); **#37 OAuth caveat
|
||
> resolved** (e2e via OTC); **#38 Tier-1 Gitea = stub inner loop, real
|
||
> Gitea for the gate**. Landed in handbook §10.1/§10.5 (eng PR #2) +
|
||
> ROADMAP #37/#42 (ohm-rfc PR #7) + the rfc-app scaffold README.
|
||
>
|
||
> Texture note: this session ran amid the harness-corruption /
|
||
> parallel-execution conditions flagged at launch (the prior advisory
|
||
> "0046" hit Bash/Read garbling). Concretely: ROADMAP commits appeared
|
||
> on `main` authored at this session's start time, and my coherence
|
||
> commit (`30326e3`) reached `main` via a PR I did not open (#5,
|
||
> `roadmap/38-body-two-tier`) while my own PR (#6, same commit) sat
|
||
> open and un-mergeable. Plus a wedged Gitea merge-queue window. Every
|
||
> claim below was re-verified against committed blobs, not large dumps.
|
||
|
||
---
|
||
|
||
## Pre-session state
|
||
|
||
- Claimed session **0046** via `claim-session-id.sh` (max+1; the prior
|
||
advisory "0046" never pushed a claim). Active `--INPROGRESS` at start:
|
||
0026, 0027 (stale), **0045** (a genuinely in-flight parallel session).
|
||
- **engineering** (`wiggleverse/engineering`): one commit (`4ae1d03`
|
||
seed). §10.3 was PPE-gate-only — no two-tier / local-Docker content.
|
||
The repo now exists (the memory's "repo not yet created" was stale);
|
||
`README.md` is canonical, `~/projects/wiggleverse/ENGINEERING-GUIDE.md`
|
||
is the now-superseded original draft.
|
||
- **ohm-rfc** (`ben.stull/ohm-rfc`): Phase F / Track Δ (#37–#42) present
|
||
(PR #3). At session start a commit `2e403dd` ("ROADMAP #38/#40:
|
||
two-tier") was already on `main` via PR #4, authored 06:29 — i.e. the
|
||
prior corrupted turn's captured work had in fact landed, contradicting
|
||
the launch brief's "did NOT yet write into the published docs." It
|
||
updated the **#38 table row** + **#40 narrative bullet** only.
|
||
- **rfc-app** (`ben.stull/rfc-app`): v0.31.0 (meta-only topology). No
|
||
checked-in e2e suite; `scripts/seed_*` only. Backend = FastAPI/uvicorn
|
||
`app.main:app` :8000, env-driven (`config.py` requires Gitea + OAuth +
|
||
SECRET_KEY + webhook secret); frontend = Vite; email via SMTP env.
|
||
|
||
---
|
||
|
||
## Plan
|
||
|
||
- [x] Claim session id (first gesture).
|
||
- [x] Read SESSION-PROTOCOL.md + ROADMAP Phase F / Track Δ.
|
||
- [x] Handbook §10.3 → two-tier model (branch → PR → merge).
|
||
- [x] ohm-rfc ROADMAP #38 + note on #40 (verify done / complete coherence
|
||
via PR with Keychain PAT).
|
||
- [x] rfc-app Tier-1 local-Docker + e2e skeleton scaffold (if time).
|
||
- [x] Surface open decisions (#42, #37 OAuth, v1 timing) — not default.
|
||
- [x] Update memory.
|
||
- [x] Finalize + publish transcript LAST.
|
||
|
||
---
|
||
|
||
## Turn-by-turn arc
|
||
|
||
### Arc 1 — Orient + claim, detect the corruption
|
||
|
||
Read the protocol + ROADMAP. Claimed 0046. Early on, two reads of the
|
||
same `git log` disagreed (one showed `2e403dd` as HEAD, the next showed
|
||
the PR-#4 merge `ff4ff67`) — the flagged corruption, live. Adopted a
|
||
discipline for the rest of the session: verify against `git show <sha>` /
|
||
`git show origin/main:<path>` (committed blobs), never trust a large or
|
||
first-time dump.
|
||
|
||
### Arc 2 — Handbook §10.3 (engineering)
|
||
|
||
Rewrote §10.3 from "The PPE gate tests the combination a normal deploy
|
||
skips" → **"Two-tier testing: one suite, local Docker then PPE."** The
|
||
suite is environment-agnostic (one `BASE_URL` + a mail-sink API URL);
|
||
Tier 1 = local `docker compose` (backend + built frontend + fresh SQLite
|
||
+ Mailpit) in the dev loop + CI on every PR (needs no VM → not blocked on
|
||
PPE); Tier 2 = the same suite vs PPE on the VM as the deploy gate. The
|
||
N−1/N compat-gate steps were preserved and re-homed: they run **first in
|
||
Tier-1 Docker** (boot N−1 image → migrate → test → swap N image → test),
|
||
PPE as prod-like confirmation. Also nudged §10.6 (machinery list +
|
||
build-order). **Kept §10.4/§10.5/§10.6 numbering stable** because ROADMAP
|
||
references handbook sections by number (#38→§10.3, #40→§10.2–§10.3,
|
||
#41→§10.4, #42→§10.5). Branch → PR #1 → merged (`1f3c8e7`, merge
|
||
`4bab7a0`).
|
||
|
||
### Arc 3 — ohm-rfc ROADMAP coherence (#38 / #40)
|
||
|
||
Verified PR #4 (`2e403dd`) had already landed the core (#38 table row +
|
||
#40 narrative bullet), leaving two gaps: the **#38 detailed narrative**
|
||
(### 38 block, still PPE-only) and the **#40 table row**. Filled both on
|
||
branch `session-0046/two-tier-narrative-coherence` (commit `30326e3`):
|
||
#38 narrative now has the environment-agnostic contract + Tier 1/Tier 2 +
|
||
"Tier 1 depends on nothing; Tier 2 depends on #37"; #40 row notes the
|
||
compat gate runs first in Tier-1 Docker. Opened **PR #6**.
|
||
|
||
The Keychain PAT API path needed care: `ben/ohm-rfc` 307-redirects;
|
||
canonical is `ben.stull/ohm-rfc`. A POST hung once (killed it; it had in
|
||
fact created the PR — 409 on retry). Then **PR #6 would not merge**:
|
||
persistent `HTTP 405 "Please try again later"` for >2 min across retries
|
||
and a close/reopen, despite `mergeable: true` and no branch protection —
|
||
Gitea's conflict-check queue wedged server-side (a lingering lock, likely
|
||
aggravated by the hung request + concurrent-session load).
|
||
|
||
**Resolution discovered at finalize:** `main` later already contained my
|
||
exact commit `30326e3` — merged via **PR #5** (`roadmap/38-body-two-tier`,
|
||
merge `5760b5d`), a PR I did not open. A parallel actor (session 0045, or
|
||
a corrupted parallel execution of this one) re-merged my commit. PR #6
|
||
was thus redundant (empty diff vs base — the real reason for the 405);
|
||
**closed it as superseded by #5.** Net: `main` (5760b5d) carries the
|
||
complete two-tier ROADMAP treatment, coherent.
|
||
|
||
### Arc 4 — rfc-app Tier-1 e2e scaffold (#37/#38 groundwork)
|
||
|
||
Read the real runtime shape (`config.py`, systemd unit, `vite.config.js`
|
||
proxy, `email.py` SMTP env, OTC endpoints `POST /auth/otc/request` +
|
||
`/auth/otc/verify`). **Key finding:** Tier 1 cannot be a trivial
|
||
two-container compose — the backend has a hard **Gitea dependency** (reads
|
||
`META_REPO` content via the Gitea API, bot writes, `config.py` requires
|
||
Gitea + OAuth env). So a hermetic Tier 1 needs a disposable Gitea (real
|
||
container + bootstrap) or a stubbed gitea client — a genuine #38 design
|
||
decision, surfaced not defaulted. Also: auth in tests uses **OTC, not
|
||
OAuth** (the #37 caveat dissolves because #5/OTC shipped in v0.7.0).
|
||
|
||
Authored `e2e/` (9 files, additive, no existing code touched): `README.md`
|
||
(the design + the Gitea-dependency decision + the #40 compat-gate
|
||
mapping), `docker-compose.yml` (backend + built-frontend + fresh-SQLite
|
||
tmpfs + Mailpit + disposable Gitea + a bootstrap init, all `down -v`
|
||
disposable; Dockerfiles marked TODO(#38)), `.env.example` (OTC auth,
|
||
SMTP→Mailpit, `RFC_APP_INSECURE_WEBHOOKS=1`), `playwright.config.js`
|
||
(env-agnostic, reads `BASE_URL`), `tests/helpers/mailpit.js` (poll sink
|
||
API → extract OTC code / link; catch-all addressing → no provisioned
|
||
mailboxes), and two spec stubs (`smoke`, `otc-login`, `test.fixme`).
|
||
**Not a release** — no VERSION/CHANGELOG/pin/deploy. Pushed via SSH;
|
||
opened **PR #4 (rfc-app), left OPEN for review** (correct end state for a
|
||
framework-repo scaffold; should not auto-merge).
|
||
|
||
### Arc 5 — surface decisions, memory, finalize
|
||
|
||
Updated `project_engineering_handbook.md` memory (repo exists/canonical;
|
||
§10.3 = two-tier; open items refreshed). Surfaced the open decisions
|
||
(below). Wrote + published this transcript.
|
||
|
||
### Arc 6 — operator design decisions (post-first-publish)
|
||
|
||
After the first finalize, the operator engaged the surfaced open
|
||
decisions and settled them. Recorded across the docs (not built — all
|
||
gated on flotilla v1):
|
||
|
||
1. **#42 auto-rollback → always-on VM-side watcher** (chose option (a)
|
||
over my (b)-leaning recommendation). A systemd daemon arms on cutover,
|
||
disarms on promote, trips ONLY the DB-free rollback. Framed as a
|
||
bounded carve-out from flotilla's laptop-only model. (handbook §10.5 +
|
||
ROADMAP #42)
|
||
2. **#37 PPE → completely separate infra.** A real architecture pivot off
|
||
the original "three instances on one VM": PPE gets its own GCP micro
|
||
instance, its own separate gcloud stack (project + config), and its
|
||
own Gitea at `ppe.git.wiggleverse.org` colocated on the PPE VM. Only
|
||
flotilla's code-deploy gesture crosses over. flotilla
|
||
multi-deployment becomes "2nd record at a different host+project," not
|
||
a 2nd install dir. (handbook §10.1 reframed + ROADMAP #37 rewritten)
|
||
3. **#37 OAuth caveat → resolved** (e2e logs in via OTC; #5 shipped).
|
||
4. **#38 Tier-1 Gitea → stub for the inner loop, real Gitea for the
|
||
gate** (Tier 2 = PPE's own real Gitea). (rfc-app scaffold README)
|
||
5. **Open follow-on captured:** self-host prod Gitea on the prod VM too
|
||
("we can do that for prod, too") — flagged as its own decision, not
|
||
committed.
|
||
|
||
Merges: eng PR #2 (`4259df3`), ohm-rfc PR #7 (`f2a661f`), rfc-app PR #4
|
||
updated (`a3f48ba`). The Gitea merge-queue had recovered by this arc
|
||
(all three merged HTTP 200 cleanly). Memory updated. Operator reviewed
|
||
the decisions + the next-session prompt in chat and called the wrap;
|
||
session closed here.
|
||
|
||
---
|
||
|
||
## Cut state (end of session)
|
||
|
||
| repo | state |
|
||
| --- | --- |
|
||
| engineering | `main` @ `4259df3` (PR #1 two-tier §10.3; PR #2 §10.1 PPE-separate-infra + §10.5 always-on watcher) |
|
||
| ohm-rfc | `main` @ `f2a661f` (PR #4+#5 two-tier #38/#40; PR #7 #37 separate-infra + #42 watcher). PR #6 closed (superseded). |
|
||
| rfc-app | branch `session-0046/e2e-tier1-scaffold` @ `a3f48ba`, **PR #4 OPEN** — `e2e/` Tier-1 scaffold + Gitea decision. No release. |
|
||
| OHM live | **untouched** — no deploy this session (docs + groundwork). |
|
||
| ohm-rfc pin | **unchanged** (`.rfc-app-version` not bumped). |
|
||
| memory | `project_engineering_handbook.md` updated. |
|
||
|
||
| Track Δ ledger | Status |
|
||
| --- | --- |
|
||
| Two-tier refinement → handbook §10.3 | ✅ shipped (eng PR #1) |
|
||
| Two-tier refinement → ROADMAP #38/#40 | ✅ shipped (ohm-rfc PR #4 + #5) |
|
||
| #37 PPE | ⏸ gated on v1 (no VM work done) |
|
||
| #38 e2e suite | 🟡 Tier-1 scaffold opened (rfc-app PR #4, for review) |
|
||
| #39–#42 | ⏸ not started (chained, post-v1) |
|
||
|
||
---
|
||
|
||
## §19.2 / process candidates surfaced
|
||
|
||
1. **Gitea merge-queue wedge.** Persistent `405 "Please try again later"`
|
||
for >2 min, surviving close/reopen, with `mergeable:true`. The
|
||
conflict-check worker appears to stick after a killed/hung API request
|
||
under concurrent-session load. May affect ANY merge instance-wide
|
||
during such a window — operator may need to restart Gitea / its queue.
|
||
A client-side `--max-time` on every `curl` is now mandatory discipline
|
||
(one hung request poisoned the queue and held a server lock).
|
||
2. **PR identity under parallelism.** Two PRs (#5, #6) carried the *same*
|
||
commit sha into the same base; one merged, one became an empty-diff
|
||
orphan. Sessions should check `git branch -r --contains <their commit>`
|
||
before assuming their own PR is the merge path — content-addressing
|
||
means another actor can land "your" commit under a different branch.
|
||
3. **`config.py` Gitea-hardness vs. hermetic Tier-1.** The required
|
||
Gitea + OAuth env is the structural obstacle to a cheap local e2e.
|
||
Worth a framework note on a test-mode seam (the (A) real-Gitea vs (B)
|
||
stub decision) so #38 doesn't rediscover it cold.
|
||
|
||
---
|
||
|
||
## What lands on the operator's plate
|
||
|
||
1. **#42 watcher — DECIDED (always-on VM-side), build is v1-gated.** The
|
||
systemd watcher itself is built when #42 lands (post-v1, after #41).
|
||
2. **#37 PPE — DECIDED (separate infra), live stand-up is v1-gated.** The
|
||
real work waiting: provision the micro VM in its own gcloud project,
|
||
stand up its Gitea at `ppe.git.wiggleverse.org`, DNS for `ppe.*` +
|
||
`ppe.git.*`, flotilla 2nd deployment record at the new host/project.
|
||
None done — all v1-gated.
|
||
3. **v1 timing — the gating question.** Confirm flotilla v1 timing before
|
||
ANY PPE VM stand-up. I stood up nothing (local scaffold only).
|
||
4. **rfc-app PR #4 (e2e scaffold)** — review / merge when ready. The
|
||
Tier-1 Gitea decision is now recorded in its README; #38 still builds
|
||
both seams (stub + real-Gitea bootstrap).
|
||
5. **Open follow-on:** self-host prod Gitea on the prod VM too — captured
|
||
in §10.1 + ROADMAP #37, needs its own decision before any move.
|
||
6. **Gitea merge-queue wedge** (§19.2 #1) happened mid-session and
|
||
recovered; if it recurs, a queue/Gitea restart is the fix — may affect
|
||
parallel sessions (0045 was in flight).
|
||
|
||
---
|
||
|
||
## Prompt the operator can paste into the next Claude Code session
|
||
|
||
```
|
||
OHM driver session. Read ~/git/ohm-infra/SESSION-PROTOCOL.md and
|
||
~/projects/wiggleverse/ohm-rfc/ROADMAP.md (Phase F / Track Δ, #37–#42)
|
||
first. Claim your session id via claim-session-id.sh --start <now>.
|
||
|
||
Session 0046 recorded the operator's Track-Δ design decisions into the
|
||
docs (engineering handbook §10 + ohm-rfc ROADMAP). Nothing was built —
|
||
all of Track Δ is GATED ON flotilla v1. The decided shape:
|
||
|
||
- Two-tier testing (handbook §10.3 / ROADMAP #38, #40): env-agnostic
|
||
suite (one BASE_URL + mail-sink API URL). Tier 1 = local Docker per-PR
|
||
(no VM); Tier 2 = PPE as the deploy gate. The #40 N−1/N compat gate
|
||
runs first in Tier-1 Docker, PPE as prod-like confirmation.
|
||
- #37 PPE = COMPLETELY SEPARATE infra (handbook §10.1 / ROADMAP #37):
|
||
own GCP micro instance + separate gcloud stack (own project/config) +
|
||
own Gitea at ppe.git.wiggleverse.org colocated on the PPE VM. NOT
|
||
colocated on prod; only flotilla's code-deploy gesture crosses over.
|
||
Auth in tests = OTC (OAuth caveat resolved, #5 shipped).
|
||
- #38 Tier-1 Gitea = stub for the fast inner loop, real Gitea for the
|
||
gate (Tier 2 uses PPE's own Gitea). Scaffold OPEN at rfc-app PR #4
|
||
(branch session-0046/e2e-tier1-scaffold, e2e/ dir, NOT a release).
|
||
- #42 auto-rollback = always-on VM-side watcher (systemd daemon, DB-free
|
||
rollback only; bounded carve-out from flotilla laptop-only).
|
||
- Open follow-on (not decided): self-host PROD Gitea on the prod VM too.
|
||
|
||
CONFIRM flotilla v1 timing with the operator before standing up ANYTHING
|
||
on a VM (PPE micro instance, the PPE/prod Gitea, DNS). Work that does NOT
|
||
need the VM and can proceed now: flesh out rfc-app PR #4 toward a passing
|
||
Tier-1 suite (Dockerfiles + the (B) gitea stub + the (A) gitea bootstrap
|
||
+ real selectors) — that's #38.
|
||
|
||
Heads-up: 0046 hit a wedged Gitea merge-queue (persistent 405 "please
|
||
try again later"; recovered later) and harness Bash/Read corruption —
|
||
verify git state against committed blobs (git show origin/main:<path>),
|
||
put --max-time on every curl, and check `git branch -r --contains <your
|
||
commit>` before assuming your own PR is the merge path. Session 0045 was
|
||
also in flight.
|
||
```
|