13 KiB
Session 0054.0 — Transcript
Date: 2026-06-01 Goal (as launched): walk the full engineering runbook end-to-end as a test run — fake-build a throwaway app and deploy it for real, then tear it down. Discover whether the runbook actually works for a brand-new app.
Outcome: The runbook's design+build half was walked for real on a throwaway URL-shortener (
wiggle-snip): prototype → SPEC v0.0.1 → ROADMAP → standard-stack build with 14 green tests + a building Vite frontend +/api/health. The deploy half was NOT executed — at the deploy gate the operator redirected: don't deploy from this session, instead (a) hand off a reusable prompt for a future operator-driven deploy, and (b) use what we'd learned to scope a newlaunch-appskill suite that takes an engineer from "I want to build an app" to a verified pre-prod deploy. That suite was spec'd:wiggleverse/engineering/launch-app/SPEC.mdv0.0.1 + ROADMAP.md, withflotilla-coreextraction as the critical-path Slice 1. No cloud resources, Gitea repos, or deploys were created.Scope-change / publication note (transcript-honest): this session began off the record. At the deploy gate the operator explicitly chose "don't publish a transcript" — correct for a throwaway deploy test. But the session then pivoted into real org-level tooling design (the
launch-appspec), and the operator reversed the call: "the scope of this conversation changed, so let's do a proper transcript." Hence this file. The earlier off-the-record decision is recorded here precisely because it was reversed — the record shows the judgement, not a tidied version of it.Timestamp caveat: the start-gesture claim (SESSION-PROTOCOL §"session start") was NOT run at the true session start — the session opened in the
ecommworking dir as an off-the-record test and was elevated to a published transcript only at the end (the protocol's "claims its ID at publish time" path). The03-24/03-25stamps are the claim/finalize window; the actual work spanned roughly the preceding hour.
Pre-session state
- No
wiggle-snipanything existed. Working dir was~/projects/wiggleverse/ecomm(an unrelated project); this session never touched ecomm. - The runbook of record:
~/projects/wiggleverse/engineering/README.md(the canonical handbook;~/projects/wiggleverse/ENGINEERING-GUIDE.mdis the now-superseded draft). Read in full this session. scaffold-gcp-projectskill present at~/.claude/skills/scaffold-gcp-project/SKILL.md— the one existing cloud-foundation skill.ohm-rfc-app-flotillapresent — OHM's operator CLI, the template any new deployment's flotilla would fork from.
Plan
Walk the guide §1 lifecycle for a deliberately trivial app: idea →
prototype (§2) → SPEC (§3) → ROADMAP (§7) → build on the standard stack
(§4, §8) → deploy via flotilla (§8, §9) → verify /api/health → tear down.
The app is a vehicle to exercise the pipeline, so it was chosen for
minimal domain complexity and maximal stack coverage.
Turn-by-turn arc
Arc 1 — Choose the test app
Grounded in the guide first (read the engineering-pattern memory + handbook §1–§9). Proposed four candidates via AskUserQuestion (guestbook, deploy counter, link shortener, quote board), framed around which best exercises every layer (a migration + WAL write, an API, a Vite build, a health check) with least domain noise. Operator chose the link shortener — it earns a redirect route + slug generation without real complexity.
Arc 2 — Reconnaissance: is the runbook even tractable for a new app?
Before building, inspected ohm-rfc-app-flotilla. Key finding: flotilla
is OHM-specific, not generic — its README says each deployment forks its
own <deployment>-flotilla, and a generic library is a §19.2 candidate
"once a second deployment exists." Confirmed the deploy shape matches the
standard stack (plan.py/deploy.py run backend/.venv/bin/pip install +
cd frontend && npm ci && npm run build → systemctl restart → verify
/api/health), but it is OHM-coupled in two spots: the pin.py hard
rfc-app >= 0.2.3 floor and the audit.py rfc-app-lockfile target. Noted
that this test run is itself the "second deployment" the guide predicted
would justify extracting a generic flotilla.
Arc 3 — Prototype (guide §2)
Vibe-coded ~/projects/wiggleverse/wiggle-snip-prototype/prototype.py
(stdlib-only http.server + sqlite). Wrong turn: left a nonsense
expression for _ in rangeate(10) if False else range(10) in the slug
minter; caught and cleaned to range(10) before running. Ran it and
exercised every endpoint: health, shorten (201), redirect (302 + Location),
unknown slug (404), bad URL (400), bad JSON (400), hit-counter increment.
The proto's job was done the moment the contracts were describable (§2).
Arc 4 — SPEC + ROADMAP (guide §3, §7)
Matched the house style (numbered §, citable invariants, deferred-topics
section) by reading rfc-app/SPEC.md first. Wrote wiggle-snip/SPEC.md
v0.0.1 — invariants: opaque slugs (§3.1), no slug reuse (§3.3), fail-loud
collision (§3.4), validate-before-store (§4.1), unknown-slug-is-404 (§5.1),
health-reports-version (§6.1), forward-only schema (§2.1). Then
ROADMAP.md, 5 slices with a next-session brief.
Arc 5 — Build on the standard stack (guide §4, §8)
Mirrored rfc-app/backend layout. Built backend/ (FastAPI, db.py
migration runner cloned from rfc-app's shape, 001_init.sql, slug minter
with an injected randomness seam for testability, main.py routes) +
frontend/ (vanilla Vite). Wrong turns / friction:
- A
cd-in-compound Bash call and anrm -rf … &background call were both permission-denied; reworked to absolute paths + foreground. - FastAPI rejected the redirect route's
RedirectResponse | JSONResponseunion return type; fixed withresponse_model=None. 14 backend tests pass (incl. the collision-retry-then-fail-loud path and a slug-opacity check). Frontendnpm run buildproducesdist/; lockfile committed (flotilla'snpm cineeds it). Verified the full stack on one origin via curl: health reports version, homepage + assets served fromdist/, shorten → 201, redirect → 302, unknown → 404. Added.gitea/ workflows/test.yml, README,.gitignore,VERSION.
Arc 6 — The deploy gate, and the first pivot
Presented the deploy gate honestly: a real deploy creates a billable GCP
project + VM, real Gitea repos, and (per guide §6) a public transcript.
Operator had earlier chosen "full real deploy," but at the trigger
redirected: do NOT deploy from this session. Instead, produce a
self-contained prompt for a fresh operator-driven session that uses
scaffold-gcp-project + the runbook to deploy wiggle-snip and capture
skill-improvement feedback. Also chose "don't publish" a transcript
(off-the-record test). Delivered that prompt. Teardown (the planned final
step) became moot — nothing was provisioned.
Arc 7 — Skill-scope question → the second pivot
Operator asked whether scaffold-gcp-project currently covers (a) asking
about the app, (b) defining+validating topology, (c) all resource
names/locations. Read the SKILL.md and answered precisely: it asks only for
repo-name/org/billing/region/profile; it is explicitly "cloud foundation
only," stops before the VM, validates only the project-id regex, and
leaves topology + most resource names to the operator/flotilla. Identified
the gap: the middle band between "cloud foundation scaffolded" and "app
deployed" has no skill.
Arc 8 — Scope the launch-app suite, and decide its shape
Explored the full scope of a suite that takes "I want to build an app" →
deployed (≥ pre-prod), for a technical-but-not-GCP-expert engineer. Read
guide §10–§12 + the register-ohm.sh deployment record to ground the
target topology and the full resource-name set. Surfaced two genuine
forks via AskUserQuestion. Operator decided:
- Milestone = PRE-PROD ONLY (no prod, no Stage-2 blue/green/canary). This collapses the target to a single disposable pre-prod env = topologically the §8 single-VM shape, and drops all of §10.6 from v1.
- Extract
flotilla-core(not fork-per-app) — the real fix the guide's §19.2/§11 "second deployment" trigger predicts.
Arc 9 — Write the suite's SPEC + ROADMAP, and the build prompt
Wrote wiggleverse/engineering/launch-app/SPEC.md v0.0.1 (orchestrator
state machine, deployment.toml schema + fail-closed validation rules,
per-phase-skill responsibilities, the flotilla-core extraction contract
incl. its §7.3 "OHM still deploys" regression oracle, and the teaching/
safety invariants incl. the hard-secrets rule §8.3) + ROADMAP.md (5
slices, flotilla-core first, wiggle-snip as the dogfood fixture).
Delivered a paste-ready prompt to kick off the Slice-1 build session.
Updated agent memory (project notes for the suite + the fixture).
Arc 10 — Scope changed → produce this transcript
Operator: "the scope of this conversation changed, so let's do a proper
transcript." Reversed the Arc-6 off-the-record call. Read SESSION-PROTOCOL,
claimed 0054 via claim-session-id.sh, finalized + published this file.
Cut state (end of session)
~/projects/wiggleverse/wiggle-snip— built + tested, NOT deployed. backend (FastAPI/SQLite-WAL/migration0001_init//api/health), frontend (Vite→dist), 14 tests green, CI defined,SPEC.mdv0.0.1,ROADMAP.md.~/projects/wiggleverse/wiggle-snip-prototype— throwaway proto.~/projects/wiggleverse/engineering/launch-app/—SPEC.mdv0.0.1 +ROADMAP.md(NEW; local working copies, not yet committed/PR'd into thewiggleverse/engineeringrepo — that's an operator gesture).- No GCP project, VM, Gitea repos, ADC change, or deploy. Nothing to tear down.
- Two paste-ready prompts handed to the operator in-chat: (1) deploy
wiggle-snipvia scaffold-gcp-project + runbook; (2) buildlaunch-appSlice 1 (flotilla-coreextraction).
§19.2 / process candidates surfaced
flotilla-coreextraction — the headline. flotilla is OHM-coupled (pin.pyrfc-app floor,audit.pylockfile target, OHM names). This test run is the literal "second deployment" that justifies pulling the generic 9-phase engine into a reusable package + thindeployment.toml. Decided: do it (launch-app ROADMAP Slice 1). Regression oracle = OHM still deploys through the core (launch-app SPEC §7.3).- The
scaffold-gcp-project→ deploy gap — no skill owns topology definition/validation or the full resource-name set;launch-appSPEC §6.6 (define-deployment) + §6.7 (provision-vm) are the proposed fill. scaffold-gcp-projectshould confirm, not assume, the standard stack (launch-app SPEC §6.5) — it currently has no app-intake interview.
What lands on the operator's plate
- Decide whether to commit/PR the new
engineering/launch-app/SPEC+ROADMAP intowiggleverse/engineering(operator gesture). - When ready, run either handed-off prompt: deploy
wiggle-snipto validate the runbook, or start theflotilla-coreextraction (Slice 1). - Optional: fold a pointer to
launch-appinto the engineering guide's table of contents / §12 so it's discoverable.
Prompt the operator can paste into the next Claude Code session
Build the launch-app skill suite — Slice 1: extract flotilla-core.
Read first:
- Suite spec: ~/projects/wiggleverse/engineering/launch-app/SPEC.md (esp. §7 flotilla-core, §9 invariants, §10 out-of-scope)
- Suite roadmap: ~/projects/wiggleverse/engineering/launch-app/ROADMAP.md (Slice 1 is the task)
- Rulebook: ~/projects/wiggleverse/engineering/README.md (§8 stack, §8.4 cloud profile)
- Extract FROM: ~/projects/wiggleverse/ohm-rfc-app-flotilla (note pin.py, audit.py, deploy.py, registry.py)
- Dogfood fixture (built + tested): ~/projects/wiggleverse/wiggle-snip
Task: pull the generic 9-phase deploy engine out of ohm-rfc-app-flotilla into
an installable flotilla-core consuming a deployment.toml (schema = SPEC §5.1),
carrying NO app-specific defaults. De-OHM it (SPEC §7.2): remove the pin.py
rfc-app >=0.2.3 floor (pin floor → optional per-app config, default none);
generalize audit.py off rfc-app lockfiles; parameterize the OHM data-dir /
DB-filename / user-agent names.
DEFINITION OF DONE (SPEC §7.3 — do not skip): repoint OHM's flotilla to consume
flotilla-core as a thin shim and PROVE OHM STILL DEPLOYS through it unchanged.
The existing OHM deployment is the regression oracle; new tests alone are NOT done.
Scope guard (SPEC §10): pre-prod, single-environment only. NO slots / ramp /
promote / rollback / compat-gate / watcher (that's guide §10). If you start
adding any, stop.
Process: spec-driven (cite SPEC/guide § in commits; branch → PR, not straight to
main). Hard secrets rule (guide §6 / SPEC §8.3): never put a secret byte in the
session; hand the operator stdin-piped commands. At the end, hand over the
Slice-2 prompt, and note anything in the SPEC that turned out wrong/underspecified
against the real code so we can correct it before Slices 2–5.