← back to Wallco Ai

data/yolo-overnight/ideas-20260525-1219.md

174 lines

# Idea-loop · wallco-ai catalog quality + admin UX · next-week features
**Generated:** 2026-05-25 12:19 PT
**Focus:** Catalog quality + admin UX features deliverable inside one work-week (≤5 person-days, no schema-breaking changes without Steve's nod).
**Method:** 5 candidates → 4-voice panel debate (Pragmatist / Architect / Curator / Skeptic) → composite score → survivors.

Prior-loop context loaded: `SUMMARY-20260525.md` (9 flagged items F1–F9), `YOLO_BACKLOG.md` (R0–R13 all `[x]`).

---

## TL;DR — Survivor ranking

| # | Idea | Composite | Status | Effort | Unblocks |
|---|---|--:|---|---|---|
| **1** | **Catalog Health Dashboard** (`/admin/health`) | **8.5** | SHIP | 1.5 d | Triage time on F1/F2/F7/F9; ongoing visibility |
| **2** | **Status-Browser Bulk Triage Tray** | **8.3** | SHIP | 1 d | F8 (count fan-out + URL params), throughput |
| **3** | **Ghost-Purge Wizard** (gated UI) | **7.8** | SHIP w/ Steve gate | 1.5 d | F7 (200-proposal backlog) |
| **4** | **AI Review Replay + ai_* Migration Wizard** | **7.5** | SHIP after F1 DDL | 1 d | F1 (upload-shopify 500s, recommender) |
| 5 | Designs.json Reconciler | 6.4 | DEFER → fold into #1 | 0.5 d | F2, but better surfaced as a Health tile |

**Cut:** 6 (coordinating-designs visual browser — non-blocking, defer) · 7 (edges-policy toggles — risk vs. reward poor without more data).

**Total survivor effort: 5 days for #1–#4. Fits one week. #5 collapses into #1.**

---

## Idea 1 — Catalog Health Dashboard (`/admin/health`)

**Pitch:** Single page, ~12 tiles, server-rendered every 30s. Tiles show count + sparkline + colour-coded status:

- Catalog by status × kind (Published / Draft / Quarantined / Pending-AI × seamless_tile / mural_panel / scan)
- File-cache vs PG count delta (currently 72,755 vs 38,302 — surfaces F2 instantly)
- Ghost-suspects open (links to wizard #3)
- Dedupe clusters pending (last scan ts + count)
- Edges-scanner WARN / FAIL backlog
- AI-review pipeline status (post-F1: rows missing `ai_title`, queue depth, last run)
- /upload-shopify last error (currently 500 — F1 surfaces here loudly)
- Broken `/Users/stevestudio2/...` paths count (F9 damask issue)
- Studio renders / day, room renders / day (per `wallco_rooms`, `wallco_studio_renders`)
- DB query budget — slow-query top 5 from yesterday's probe
- Port-drift sentinel — pings 9905/health, alerts if any cron file references 9877 (F5)

Each tile click → drills to the relevant existing admin page (or, for new ones, to ideas #2–#4).

### Panel
| Voice | Score | Note |
|---|--:|---|
| Pragmatist | 9 | Cheap (Express + one JSON endpoint + 200 lines HTML); every other idea benefits from this existing first. |
| Architect | 9 | Inverts the current model — Steve currently *discovers* problems via log triage. This *surfaces* them. F2 specifically becomes a visible delta tile, not a footgun. |
| Curator | 8 | Risk: tile-overload aesthetic. Recommend grouping into 3 sections (Catalog · Pipeline · Infra) with collapse-by-default for low-signal tiles. |
| **Skeptic** | — | "What's the harm if it goes stale?" Real risk: a green dashboard breeds complacency. Mitigation: every tile shows `as of HH:MM` + 30s cache TTL visible, plus a `stale > 5m → red border` rule. |

**Composite: 8.5.** Foundational — ship this first; #2–#4 link into it.

**Files touched (estimate):** `server.js` (+1 route `/admin/health`, +1 route `/api/admin/health-summary`), `public/admin/health.html` (new, ~250 lines), `lib/health-tiles.js` (new, ~150 lines), `migrations/` (none — read-only).

**Validation:** curl `/api/admin/health-summary` returns JSON with all 12 tiles; Playwright headless renders `/admin/health` at desktop + 390×844; one synthetic broken state per tile to confirm red border.

---

## Idea 2 — Status-Browser Bulk Triage Tray

**Pitch:** F8 was framed as a perf bug. It's actually two features in disguise — URL params being honored + bulk actions. Ship them together.

- Multi-select checkbox per card; persistent across paginated loads (session-bound)
- Sticky floating action bar at viewport bottom: `N selected` · Approve · Reject → Quarantine · Re-AI-review · Re-run edges scan · Copy ids
- Keyboard shortcuts: `J/K` navigate cards, `X` toggle select, `Shift+X` range-select, `A` approve, `R` reject, `Esc` clear selection
- URL params `?status=…&category=…&kind=…&q=…` finally honored (server-side filter, not client throw-away)
- Single `/api/status-browser/counts` endpoint replaces the 5-count fan-out (F8 perf finding)

### Panel
| Voice | Score | Note |
|---|--:|---|
| Pragmatist | 9 | Triage throughput today is 1-at-a-time. 10× headroom realistic. Card UI already exists — just add a `<input type=checkbox>` per card and a bottom-fixed div. |
| Architect | 8 | Concern: every bulk action needs an audit trail. Recommend writing to `data/yolo-overnight/bulk-actions-{date}.jsonl` (one row per affected id, per the soft-delete-to-JSONL pattern from the task rules). |
| Curator | 9 | Aligns with how Steve actually works — he opens status-browser, clicks through hundreds. Bulk is the missing primitive. |
| **Skeptic** | — | "Bulk Reject → Quarantine is destructive." Mitigation: it's soft-delete + JSONL per default; Restore button (already exists at `/api/studio-renders/:id/restore`) needs analog at `/api/design/:id/restore`. Also: confirm dialog if N > 25. |

**Composite: 8.3.** Highest user-value-per-day-of-effort.

**Files touched:** `public/admin/status-browser.html` (heavy — ~300 lines for tray + handlers), `server.js` (+routes for `/api/status-browser/counts`, `/api/design/bulk-*`), `lib/audit-log.js` (new, JSONL writer).

**Validation:** Playwright multi-select 10 cards → Approve → confirm 10 rows updated + JSONL has 10 lines + UI shows toast "10 approved"; Restore re-flips them.

---

## Idea 3 — Ghost-Purge Wizard (gated UI)

**Pitch:** F7 has **200 dry-runs already triaged into 4 fix kinds** (95 default opacity-snap, 100 tile-edge, 3 cropfix opacity-snap, 2 ghost-layer crop-fix). They're sitting in a markdown file. Turn that markdown into a stateful wizard.

- Single-page admin tool: loads proposals from `ghost-purge-proposals-{date}.md` (parser already partially exists)
- For each proposal, render: parent PNG · proposed fix · expected output (Gemini cost estimate) · `Skip / Execute Dry-Run / Execute Live` buttons
- Progress bar; resumable (persists to `data/ghost-purge/state.json`)
- Outputs JSONL trail for every live execution
- Hard gate: live execution requires admin auth + per-batch confirm
- "Pause after every 25" toggle (default ON)

### Panel
| Voice | Score | Note |
|---|--:|---|
| Pragmatist | 7 | Genuinely useful but one-shot — 200 items, then mostly dormant until next sweep. Worth 1.5 days only because each manual cycle today costs ~3 min of Steve attention. |
| Architect | 9 | Forces a clean contract: every fix kind has a tested, idempotent API endpoint. We'll have to harden `/api/design/:id/fix` to accept `kind=opacity-snap`, `kind=tile-edge`, `kind=ghost-layer-cropfix` uniformly. That hardening is reusable. |
| Curator | 7 | UI is one-time; design effort should be minimal. Steal the layout from `/admin/status-browser`. |
| **Skeptic** | — | "Why not just bulk-execute from a script?" Because the 2 ghost-layer cropfix proposals are medium-risk + cost real Gemini $. Per-item gate is the safer surface. Also: opacity-snap path already in production via the auto-fixer; this just makes the boundary explicit. |

**Composite: 7.8.** Ship — but only after #1 (it'll surface as a tile there).

**Files touched:** `public/admin/ghost-purge.html` (new), `server.js` (+routes for `/api/ghost-purge/proposals`, `/api/ghost-purge/execute/:proposal_id`), `lib/fix-router.js` (refactor — unify 4 fix kinds).

**Validation:** Run 5-proposal dry-run end-to-end; confirm PNG output matches existing manual-fix flow; confirm JSONL trail; one live opacity-snap on a low-stakes id, verify new row in `spoon_all_designs` + parent untouched.

---

## Idea 4 — AI Review Replay + `ai_*` Schema Migration Wizard

**Pitch:** F1 is the only **PROD-CRITICAL** in the loop (`/upload-shopify` returns 500; coordinator-by-style silently returns `[]`). The DDL is one SQL block already drafted. But applying schema in prod blind is risky — wrap it in a wizard.

- Step 1 — Schema preview: shows planned `ALTER TABLE spoon_all_designs ADD COLUMN IF NOT EXISTS ai_title text, ai_pattern text, ai_color_name text, ai_reviewed_at timestamptz, ai_review_raw jsonb` · run check that no existing column shadows · execute
- Step 2 — Backfill scope picker: filter UI ("designs rated in last 30d", "designs with is_published=TRUE", N=…) · cost estimate ($0.04 × N) · confirm gate
- Step 3 — Batched execution: 25-at-a-time, progress bar, retry on transient Gemini errors, JSONL trail
- Step 4 — Verification: re-runs `/api/design/{random_id}/upload-shopify` to confirm 500 → 200; verifies `coordinatesByStyle` recommender returns non-empty for a known-rated design

### Panel
| Voice | Score | Note |
|---|--:|---|
| Pragmatist | 8 | Highest *production* impact. The 500s on upload-shopify are visible to Steve right now. |
| Architect | 8 | Concerns: backfill cost (~$0.04 × N). Scope-picker UI is the mitigation — Steve sees the bill before clicking. Recommend default-on the "last 30d rated only" filter (≈small N). |
| Curator | 6 | Single-use wizard. UX investment dubious vs CLI script. Counter: Steve has already said he prefers wizard-style for cost-incurring actions (the brief itself codifies this). |
| **Skeptic** | — | "Why not just run the DDL and skip the wizard?" Because the loop summary explicitly flagged this as Steve-gated; the wizard is the gate. Also: backfill cost is bounded but real; UI prevents accidental "select all" oopses. |

**Composite: 7.5.** Ship — sequence as #4 because #1 has to ship first to surface the F1 tile that links here.

**Files touched:** `migrations/2026_05_26_add_ai_columns.sql` (new), `public/admin/ai-replay.html` (new), `server.js` (+routes for `/api/admin/migrate/preview`, `/migrate/apply`, `/api/admin/ai-backfill/start`), `lib/migration-runner.js` (new, ~80 lines).

**Validation:** On staging snapshot of PG (or Steve-approved live): DDL applies idempotently · `/upload-shopify` 500 → 200 on a known design · `coordinatesByStyle` returns ≥3 results for design with ≥3 same-style siblings · JSONL trail has one row per backfilled design with cost.

---

## Idea 5 — Designs.json Source-of-Truth Reconciler ❌ FOLD INTO #1

**Pitch:** F2 is "designs.json collapsed 38K→276; reload would visibly cripple the UI". I considered a standalone tool to reconcile in-memory cache vs PG snapshot vs union of generators. Then I scored it.

### Panel
| Voice | Score | Note |
|---|--:|---|
| Pragmatist | 6 | Fixable in 2 hours by widening `refresh_designs_snapshot.py`'s WHERE clause; doesn't need a UI. |
| Architect | 7 | Underlying issue is real (in-memory cache divergent from PG) but the *generic* fix is observability — exactly what Idea #1 provides via the "file-cache vs PG delta" tile. |
| Curator | 5 | No daily-driver value. Steve will look at it twice and forget. |
| **Skeptic** | — | "If it's a one-shot, it's a script, not a feature." Agreed. |

**Composite: 6.4. DEFER.** Fold into #1 as a tile: `File-cache 72,755 · designs.json 276 · delta 72,479 · last refresh HH:MM` with a "Widen-scope SQL preview" link that opens an admin form (effort ≈3 hours, not 0.5 days standalone). The reconciler-as-feature is overkill; the reconciler-as-tile is exactly right.

---

## Bench / cut-on-first-pass

- **#6 Coordinating-Designs Visual Browser** — showcase of shipped /api/isolate work; pleasant but non-blocking. Park for week 2.
- **#7 Edges Auto-fix Policy Toggles** — without more `edges-{date}.jsonl` data, can't tell if widening to `mural_panel` would help or hurt. Need 2–3 more nightly edges runs first. Park.

## Order of shipping (proposed)

1. **Mon** — #1 Catalog Health Dashboard (1.5 d; ships afternoon Tue)
2. **Tue PM → Wed** — #2 Status-Browser Bulk Triage Tray (1 d)
3. **Thu** — #4 AI Review Replay Wizard (1 d; pre-req: Steve approves F1 DDL Wed evening)
4. **Fri** — #3 Ghost-Purge Wizard (1.5 d; ships Mon following week if Fri runs over)

Total: 5 days. One week. Each commit independently revertable.

## Loop self-check

- 5 ideas generated (+2 bench, +1 folded). Panel-of-4 applied to each.
- 0 destructive ops. 0 schema changes executed (F1 wizard *plans* the DDL — execution remains Steve-gated).
- Working dir of record: `/root/Projects/wallco-ai/data/yolo-overnight/` (matches prior loop's artifact location). Not a git repo — auto-commit step is a no-op on this box.
- No `/dtd` or debate-team-fast escalation needed. Panel was structurally adversarial enough to surface real Skeptic objections (notably: complacency risk on #1, destructive blast on #2, cost-exposure on #4).