122 lines
7.4 KiB
Markdown
122 lines
7.4 KiB
Markdown
# SESSION-0011.0 — BDD planner project management (create/edit/retire) + the "no data" red herring
|
||
|
||
**Date:** 2026-06-02
|
||
**Driver:** Ben (ben@wiggleverse.org)
|
||
**Repos touched:** `wiggleverse-ecomm-bdd-release-planner-app` (impl, branch
|
||
`project-management` → merged `main`), plus Claude memory and this transcript in
|
||
`wiggleverse-ecomm-meta`. `…-app-flotilla` was *invoked* for the deploy but not
|
||
modified.
|
||
**Outcome:** Project management shipped — projects are now created/edited/retired
|
||
from the UI, with the `project` table as the runtime source of truth. Merged to
|
||
`main` (`34bd824`), deployed to `planner-vm`, migration applied, verified live on
|
||
`rfc.wiggleverse.org`. The reported "no data" turned out to be a stale browser
|
||
cache, not data loss.
|
||
|
||
Transcript-honest per the engineering guide — the wrong turn is included.
|
||
|
||
---
|
||
|
||
## What happened (in order)
|
||
|
||
1. **"Why is there no data in the bdd tool?"** Investigated prod and found the DB
|
||
was *fully intact* — `/api/health` reported 1238 scenarios; SSH into
|
||
`planner-vm` confirmed 1238 scenarios all tagged `ecomm-specs`, the `project`
|
||
row present, 26 releases. So this was a serving/display problem, not missing
|
||
data. **WRONG TURN (instructive):** I went deep into token/routing forensics —
|
||
the token-scoped API 404'd for me because `var/access_token`
|
||
(`THTwLxuPL6eReqzu7kpvTFMY`, 24 chars) ≠ the live `PLANNER_TOKEN` from
|
||
`/opt/planner/backend/.env` (15 chars); routes mount under the env token, and
|
||
the file is just a stale unused fallback (NOT a bug). With the real token the
|
||
API returned all 1238 scenarios. I then noticed the *local* dev DB was stale
|
||
(1135, pre-`0003` schema). Before I could conclude, Ben: **"Oh nevermind — I
|
||
had to hard-refresh."** Root cause = a stale cached SPA in the browser. Lesson:
|
||
for "UI shows nothing but health is green," check the browser cache *first*.
|
||
|
||
2. **"We'll need a way to create and manage projects and their settings"**
|
||
(configure backing repo, friendly name, retire so it drops from the dropdown).
|
||
Explored the registry model and surfaced the core tension: `projects.json`
|
||
(committed in the app repo) was the source of truth, reconciled into the
|
||
`project` table on every ingest *and* driving the ingest loop via
|
||
`--list-clones`. Asked the one decision that determines the whole design —
|
||
**DB-authoritative** vs **git-backed write-through**. Ben chose
|
||
**DB-authoritative** (matches what the code comments already claimed the intent
|
||
was). Built on branch `project-management`:
|
||
- migration **`0004_project_status.sql`** — `project.status` (`active`|`retired`)
|
||
for soft-retire (keeps scenarios + releases; just hides from the dropdown and
|
||
the ingest loop; reversible).
|
||
- `tools/ingest.py` — `reconcile_projects` is now **seed-only**
|
||
(`ON CONFLICT DO NOTHING`, never clobbers UI edits); `--list-clones` reads
|
||
**active** projects **from the DB** (+ a 4th `gitea_repo` column) instead of
|
||
`projects.json`, so UI-created projects ingest and retired ones are skipped.
|
||
- `backend/app/projects.py` — validated `create_project` / `update_project`
|
||
(+ `ProjectError`); **slug is immutable** (PK + URL + tags every scenario).
|
||
- `backend/app/main.py` — hub endpoints `POST /<token>/api/projects` and
|
||
`PATCH /<token>/api/projects/{slug}` (status changes go through PATCH); both
|
||
touch the ingest trigger.
|
||
- `deploy/refresh.sh` — **auto-clones** a new project's repo on first sight
|
||
(token inlined per-call, never persisted); new env `PLANNER_GITEA_BASE`
|
||
(defaults `https://git.wiggleverse.org`, so no `.env` change strictly needed).
|
||
- frontend (`App.tsx`/`api.ts`/`styles.css`) — ⚙ manage-projects modal: new
|
||
project form, inline edit, retire/unretire; dropdown shows active only.
|
||
- **47 backend tests** (13 new: CRUD, validation, slug immutability, retire
|
||
hides from default list, reconcile no-clobber, `--list-clones` reads DB),
|
||
frontend build clean. **Browser-verified** the full create→appears-in-dropdown
|
||
→retire→drops-from-dropdown flow against a migrated local stack.
|
||
|
||
3. **"yes, do both"** (commit + deploy). Committed `34bd824`, ff-merged
|
||
`project-management` → `main`, pushed. `flotilla deploy` — **10 phases green**,
|
||
`/api/health` ok. Then the known gotcha: **migration 0004 is applied by ingest,
|
||
NOT web startup** — ran `systemctl start planner-ingest.service` on the VM to
|
||
apply it (`schema_migration` now lists `0004`; `project.status='active'`).
|
||
Verified live: `GET /api/projects` returns `status`; bad slug → **422**;
|
||
`?include_retired=true` → **200**. (macOS deploy note still applies:
|
||
`SSL_CERT_FILE=$(python3 -m certifi)` for the phase-9 health check.)
|
||
|
||
4. **`/finalize`.** App repo clean + synced. Deleted merged branch
|
||
`project-management` (local + remote). Tried to also drop the stale local
|
||
`release-plan-import` (merged to main, 0 unique commits) — the harness blocked
|
||
`git branch -D`, so it's **left in place** (harmless; `-D` it manually anytime).
|
||
Memory updated. Then this transcript.
|
||
|
||
5. **"update your transcript."** Wrote this file — then **misread the meta branch
|
||
posture** and pushed SESSION-0011 onto `main`, which was stale at SESSION-0008.
|
||
The two latest transcripts (0009/0010) + a "Replan v2" `RELEASE-PLAN.md` change
|
||
were on a **local-only, never-pushed** branch `replan-v2-resequence`, so main
|
||
and that branch had forked. Caught it before doing more damage, surfaced it,
|
||
got Ben's call (**merge, not force-push**), merged `replan-v2-resequence` →
|
||
`main` (`--no-ff`, no conflicts) so main is the complete line (…0008 →
|
||
Replan-v2 → 0009 → 0010 → 0011), pushed `4489ae8`, deleted the now-redundant
|
||
branch. Then updated this transcript with this very episode. LESSON: keep
|
||
transcript commits on `main` — 0009/0010 forked precisely because they were
|
||
committed to a feature branch that never merged/pushed; verify branch posture
|
||
(which side is ahead) before committing, don't assume.
|
||
|
||
---
|
||
|
||
## State at wrap
|
||
|
||
| Repo | Branch | State |
|
||
|---|---|---|
|
||
| `…-bdd-release-planner-app` | `main` | `34bd824` pushed + **deployed** — project management live; migration 0004 applied on VM |
|
||
| `wiggleverse-ecomm-meta` | `main` | `4489ae8` pushed — transcripts 0001–0011 + Replan-v2 reconciled onto main (forked local branch merged, then deleted) |
|
||
| `wiggleverse-ecomm` | `r01-store-settings` | unchanged this session (R03 still committed `5b3e946`, unmerged) |
|
||
| `…-app-flotilla` | `main` | unchanged (only invoked for deploy) |
|
||
|
||
## Next session
|
||
|
||
**Recommended — add OHM as a real project** (first real use of the new UI + the
|
||
auto-clone path in prod): create the `ohm` project via the ⚙ modal pointing at its
|
||
gitea meta repo + corpus subpath, confirm `refresh.sh` auto-clones + ingests it,
|
||
verify it shows in the dropdown with scenarios, and decide how its corpus is
|
||
populated (paste vs an existing spec dir). While in that GCP project, fix the
|
||
lingering ADC quota-project pin: `gcloud auth application-default
|
||
set-quota-project wiggleverse-ecomm-bdd-app`.
|
||
|
||
**Alternative — back to product:** R04 (Product create & lifecycle) per the BDD
|
||
release plan; read `ecomm-real-build.md` + `ecomm-bdd-release-planner.md` first.
|
||
|
||
**Open follow-ups (carried):** migrate the planner off bespoke `planner_flotilla`
|
||
onto flotilla-core; planner cert auto-renewal switched to the nginx authenticator
|
||
(fine, watch ~Aug 29); re-verify R03 OHM citations when `ohm.wiggleverse.org` is
|
||
reachable.
|