diff --git a/docs/PLAN.md b/docs/PLAN.md index 7186e6b..b5b476e 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -1,6 +1,6 @@ # PLAN — Bike-Tinder -**Status:** Build phase — Phase 1 complete (2026-11-10); Phase 2 not yet started. Phases are gated: each lands, is verified, then the next begins. Glenn's standing rule applies — "pause" stops all spend immediately. +**Status:** Build phase — Phase 2 complete + phone-proven (2026-11-10); **Phase 3 built, verified, and live on the dev server (2026-11-11)**; Phase 4 next. Phases are gated: each lands, is verified, then the next begins. Glenn's standing rule applies — "pause" stops all spend immediately. ## v1 goal @@ -44,7 +44,9 @@ A single-source, single-user, tailnet-only Tinder-style PWA on the Rotarran: nig ## Phase 3 — Personalization ("Trends") -**Status: contract frozen 2026-11-10 (docs + brief); build started (Torres).** Glenn's approved design (2026-11-10): +**Status: BUILT → VERIFIED → LIVE (2026-11-11).** Contract frozen 2026-11-10; built by Torres in ~45 min ($3.80, 128 calls, 25/25 selfcheck; commits `04463ca`, `c205d31`, `b6e1851`); independently verified by Alex on DB copies — selfcheck 25/25 re-run, full section loop (compose → strikes → rounds → report → forge), strict-mode 409/200, forge-on-demand, trends, tank gauges, dossier "Why this rank". **One real defect found + fixed** (`1e4d840`): second-look returns were filtered out of the swipe buffer (`decision===null`), leaving round-2 dead in the UI — fixed and verified end to end (SECOND LOOK band, restrike writes round 2). **Live integration 2026-11-11:** backup at `~/dev/bike-tinder-p3/db-backup-pre-p3-20261111.sqlite3`; service restarted; P3 tables + 66 seeded events; section 1 composed; live calibration pass run (`deepseek/deepseek-v4.1-flash`, $0.0042; `agent_runs` #1) → taste profile v1 (`source=agent`). + +Glenn's approved design (2026-11-10): - **Sections of 25:** the deck is a finite batch; the agent always runs between sections (learning segmentation + anti-doom-scroll). Modes: forge-on-demand (default) / strict (nightly read only). Fallback to the last profile if the agent fails. - **Section lead:** on open/refresh the best suggestions lead; the 5-card live stack is unchanged. @@ -55,6 +57,8 @@ A single-source, single-user, tailnet-only Tinder-style PWA on the Rotarran: nig - **Agent pass:** nightly/on-demand read (mock + live + fallback); **no LLM in the swipe path — ever.** - **Exit criteria:** after ≥30 swipes the deck order visibly reflects taste; explainability visible (dossier breakdown + Trends); the section loop works end-to-end; the agent kill-switch test passes (app fully functional on the last profile with the pass disabled). +**Carried forward:** service-side OpenRouter key wiring at P4 — until then each forge's agent pass runs in mock mode and supersedes the live profile · wildcard pool hygiene (rare non-bike listings can surface) · early-ramp texture: dense nopes punish broad cells (year 2020+, 12k+, nb) — the Scouts read mid until the agent carves family-level exceptions · minor reload edge: an already-restruck second look can re-cycle on mid-section reload. + ## Phase 4 — Deploy + automate - Podman compose stack at `/var/mnt/DATA/podman-stacks/bike-tinder/` + systemd unit (`Delegate=yes`) + in-stack Tailscale sidecar serving `https://biketinder.tailf35a34.ts.net`; PWA install on Glenn's phone