Pipeline funnel v2: 4-stage enum + migration 0007 + derived grid signals

Collapse the inherited 6-stage opportunity funnel to the locked 4-stage
per-investor funnel (lead -> engaged -> diligence -> commitment), terminal at
commitment. Migration 0007 remaps existing stage values (outreach/meeting ->
engaged, due_diligence -> diligence, committed/funded -> commitment) and
archives the stray 'lost' value (the grid row is left intact). Inject read-only
existing_investor (total_invested>0), last_activity_at, and staleness
(''/'aging'>=30d/'stale'>=60d) into the grid GET, stripped on write. Frontend:
4-stage chip tints + Pipeline board / opp-form / mock on the new enum.

The visible desktop existing-investor star + staleness recency column + the
Stale saved view are deferred to mobile Phase 3 (data is injected + test-locked
now, so that phase stays pure-frontend). Longshot was already retired by prior
cleanup -- no-op.

Tests: test_pipeline_stages_v2.py (migration remap + derivation boundaries) +
updated grid-pipeline-link / soft-delete / nl_query; 36/36 green, render-smoke
green, fresh-DB migrate clean.
This commit is contained in:
Keysat
2026-06-19 12:54:12 -05:00
parent fe62df1a14
commit e46dd36517
12 changed files with 420 additions and 95 deletions
+5 -4
View File
@@ -107,13 +107,14 @@ Subsystem rules live in `docs/guides/` and lazy-load in Claude Code via `.claude
## Current state
_Phase 0 + Phase 1 built; **box + repo live at v0.1.0:94** (`main` ahead by docs/design-only commits since). **The fundraising grid + email capture is the canonical system of record.** Active threads: **mobile-first redesign** (design DONE → implementation planning next) and **W2 NL query** (live; web "Ask" box outstanding). History: git log + `start9/0.4/startos/versions/`; backlog/debt: `ROADMAP.md` / `EVALUATION.md`._
_Phase 0 + Phase 1 built; **box + repo live at v0.1.0:94** (`main` ahead by docs/design-only commits since). **The fundraising grid + email capture is the canonical system of record.** Active threads: **mobile-first redesign** (design DONE → scoped + **Phase 0 data layer BUILT 2026-06-19**, deploy pending; mobile foundation next) and **W2 NL query** (live; web "Ask" box outstanding). History: git log + `start9/0.4/startos/versions/`; backlog/debt: `ROADMAP.md` / `EVALUATION.md`._
- **Mobile-first redesign — design phase COMPLETE; implementation not started.** This session ran the `/design` round-trip Phase C/D: distilled the Claude Design cloud output ("Venture-CRM mobile redesign") into the contract — `DESIGN.md` §8 (responsive) + §4 (mobile component states) + §3 (15px scale), tokens `mobile` group + `color.light`, provenance + per-surface interaction reference in `design/_imports/2026-06-19/`. **Light theme adopted as a planned, toggle-gated feature** (dark default). Comps are Claude Design **runtime prototypes** — re-author each surface in React against the real API, not drop-in. Process learnings pushed to `standards/guides/design.md`.
- **Mobile implementation — SCOPED 2026-06-19 (plan in `ROADMAP.md` "Mobile-first implementation").** Key finding: the inline-style→CSS "blocker" is **~114 inline styles across the 4 surfaces + shell** (Grid 70 / Reminders 18 / Contacts 17 / Pipeline 7 / shell 2), **not ~1,300** — the app is already majority class-based (1,861-line `<style>`, 1,088 `className`s, 4 media queries). So it's **divisible per-surface, no upfront sweep**, and splits into two axes: *responsive* (layout→classes, gates mobile) vs *theming* (inline-hex→`var()`, 183 literals, gates light theme). Sequence: **Phase 0** pipeline-stages/flags data layer (standalone) → **Phase 1** shared foundation (tokens/`:root` + shell + bottom-tabs + sheet primitive) → **Phase 2** Contacts (validator) → **Phase 3** Grid (crux) → **Phase 4** Pipeline → **Phase 5** Reminders → **Phase 6** light theme. **Phase 0 is BUILT + tested (2026-06-19, deploy pending)** — enum→4 stages + migration `0007` + `existing_investor`/`staleness` injection; the *visible* existing-investor star + staleness recency column + Stale view deferred to Phase 3 (data injected + test-locked now). See ROADMAP for the change set.
- **Built, deploy pending:** **drag-reorder grid views** (frontend-only; `moveViewBefore` in `index.html`; persists via autosave → `views_json`; render-smoke green, browser-interaction untested).
- **W2 — NL query (read-only): LIVE** (v93; matched-only fix v94). Local-Qwen translate → curated intents + slot validator (no generic SQL), `POST /api/query/nl`, audited; Matrix Q&A + intake `?`/`@bot` live. Remaining: **in-room human smoke** + **step-4 web "Ask" box**. Guides: `docs/guides/nl-query.md` + matrix-intake.
- **W1 — reminders: LIVE (v93).** Grid-tied tickler (migration `0006`, `/api/reminders`, derived `reminder_status`, `last_activity_at` rollup). Deferred **W1b** = nurture-gap auto-suggested reminders (staleness nudge → Engaged/Diligence).
- **Done & live:** email-proposal Matrix review + `bot` role (v91); grid-driven Pipeline (v88); Matrix intake bot; Gmail capture (DWD) + propose→approve + daily digest; Thesis Workshop + Architect (Claude, dual-approval); outreach drafts. All draft-only.
- **Tests:** **35/35 backend green** (`python3 backend/run_tests.py`), `py_compile` clean; render-smoke gates `make`. (Docs/design only this session — no code touched.)
- **Next (priority order):** 1) **mobile implementation plan** — scope the **inline-style→CSS migration** first (responsive can't live in ~1300 inline styles, still unscoped); 2) land the **locked pipeline-stages/flags** data layer (enum + migration + Existing-Investor derive + staleness); 3) build the 4 mobile surfaces (Grid first; writes via one-row `log-communication` + pipeline link→stage, never whole-grid PUT; light theme co-lands with the CSS migration); 4) **deploy** view-reorder (next s9pk build); 5) **W2 step-4** web Ask box + in-room smoke; 6) **W3** bot grid-mutations behind Matrix gate; 7) **W1b** nurture-gap reminders; then P2 debt (reports comms-aggregate soft-delete sweep, `?limit=abc` crash, auth regression test, oversized icon).
- **Open / risks:** mobile implementation **blocked on the unscoped inline-style→CSS migration**; W2 translation only **happy-path-validated**; **Claude/Architect path still unverified live on the box**; v2.0 reserve-asset spine approved but **not canonical** (needs dual sign-off); doc drift — `crm-overview.md` + `EVALUATION.md` still call `lp_profiles` live.
- **Tests:** **36/36 backend green** (`python3 backend/run_tests.py`; +`test_pipeline_stages_v2.py`), `py_compile` clean, render-smoke green, fresh-DB migrate clean. (Phase 0 code shipped this session.)
- **Next (priority order):** 1) **deploy Phase 0** (s9pk build + install — pipeline-stages/flags data layer; bundle view-reorder, which is also deploy-pending; **authorize first**); 2) **Phase 1 — mobile foundation** (tokens/`:root` + viewport-gated shell + 4-tab bottom bar + bottom-sheet primitive); 3) mobile surfaces **Contacts → Grid → Pipeline → Reminders** (writes via one-row `log-communication` + pipeline link→stage, never whole-grid PUT; the deferred existing-investor star + staleness recency column + Stale view co-land here); 4) **Phase 6 light theme** (inline-hex→`var()` + `[data-theme]` toggle); 5) **W2 step-4** web Ask box + in-room smoke; 6) **W3** bot grid-mutations behind Matrix gate; 7) **W1b** nurture-gap reminders (target Engaged/Diligence); then P2 debt (reports comms-aggregate soft-delete sweep, `?limit=abc` crash, auth regression test, oversized icon).
- **Open / risks:** **Phase 0 built but not yet deployed** — the `0007` enum migration is a no-op on the live DB (0 opps today, so near-zero remap risk), and the derived `existing_investor`/`staleness` signals are injected + test-locked but not yet *rendered* on desktop (that lands in Phase 3); the mobile UI itself is still unbuilt (Grid is the heavy surface at ~70 inline styles + the two-call stage write path); W2 translation only **happy-path-validated**; **Claude/Architect path still unverified live on the box**; v2.0 reserve-asset spine approved but **not canonical** (needs dual sign-off); doc drift — `crm-overview.md` + `EVALUATION.md` still call `lp_profiles` live.