Add mobile-first design contract and redesign brief
Scaffold design/ for the frontend's first design contract, extracted as-built from index.html (document-as-is): - DESIGN.md: 9-section brand brief (dark venture-CRM look, IBM Plex, single #3b82c4 accent) + tokens.tokens.json (DTCG, from :root + an inline-style census). - BRIEF.md: the mobile-first redesign packet. Mobile = 4 surfaces (Grid, Pipeline, Reminders, Contacts) in a bottom tab bar; the rest desktop-only. Grid view-switching first-class; narrow on-the-go edit set (name, contacts, notes/comms/outreach log, stage, reminders) + create-investor, all via the canonical grid path (Contacts stays read-only). Includes a backend-reality callout: no field-level write (whole-grid versioned PUT vs the targeted log-communication path), stage is a separate two-call opportunities flow, pill removal has no undo, dedup typeahead is client-side. - brand/ assets, inspiration/ provenance. Wire the AGENTS.md Design line so any agent reads the contract before UI work.
This commit is contained in:
@@ -75,6 +75,7 @@ Subsystem rules live in `docs/guides/` and lazy-load in Claude Code via `.claude
|
||||
- **Env:** secrets in `.env` (gitignored); names in `.env.example`. Verified names: `ANTHROPIC_API_KEY`, `SPARK_CONTROL_URL`, `SPARK_CONTROL_VERIFY_TLS`, `QDRANT_URL`, `X_API_KEY`, `CRM_DB_PATH`, `CRM_DEV_DB_PATH`. Also used: `CRM_SECRET_KEY` (beta/prod), `CRM_HOST`/`CRM_PORT`, `CRM_DATA_DIR`; digest mailer: `CRM_DIGEST_SENDER` (DWD impersonation sender) + `SMTP_HOST`/`SMTP_PORT`/`SMTP_SECURITY`/`SMTP_FROM`/`SMTP_USERNAME`/`SMTP_PASSWORD` (SMTP fallback); daily digest (Phase B): `CRM_DIGEST_ENABLED` + `CRM_DIGEST_SEND_HOUR` **only seed the first-boot default** — the live control is the DB policy (`app_settings.digest_policy`, set in Settings → Admin).
|
||||
- **Config placement:** operational/feature toggles live in the **admin panel**, DB-backed via `app_settings` (read-merge through a `load_*_policy(conn)` helper shared by the API + any scheduler; precedence DB-row → env-seed → default), so they're discoverable and take effect live. Reserve StartOS actions / env for **secrets and deploy-time config** (SMTP creds, API keys, DWD sender). Precedent: `digest_policy` (`GET/PATCH /api/admin/digest/policy`), `fundraising_backup_policy`.
|
||||
- **Agent/bot API access — three roles now (`admin`/`member`/`bot`).** `require_admin` is the only hard gate; everything else is "authenticated" (member, admin, *and* bot all pass). The **`bot` role** (added v0.1.0:89) is authenticated-but-never-admin: `require_bot_or_admin` gates agent-facing endpoints (e.g. `/api/intake/email-proposals*`) so a bot credential reaches *only* what it needs, never user-management/settings/security. Provision it via Settings → Admin edit-user dropdown (kept out of the teammate-invite form). **Two axes to keep separate as more agent capability lands:** the role controls *reach* (which endpoints); the per-feature human draft→approve gate controls *autonomy* (acting unattended). Money/merge/delete mutations stay behind the approval gate regardless of role. Don't build a finer capability/scope system until real NL-mutation endpoints exist to scope against.
|
||||
- **Design:** before building or changing any user-facing UI, read `design/DESIGN.md` and `design/tokens.tokens.json` and conform to them. A **mobile-first redesign** is in flight — read `design/BRIEF.md` before any responsive/layout work. (Note: inline `style={{}}` objects can't respond to media queries; responsive layout belongs in the CSS `<style>` block.)
|
||||
- **Commit style:** imperative subject, concise body explaining the *why*; put the package version in the subject (`… (v0.1.0:NN)`) for shippable changes. **No AI co-author / attribution trailers** — commits are authored by the user.
|
||||
|
||||
## Always
|
||||
@@ -106,13 +107,13 @@ Subsystem rules live in `docs/guides/` and lazy-load in Claude Code via `.claude
|
||||
|
||||
## Current state
|
||||
|
||||
_Phase 0 + Phase 1 built; **box live at v0.1.0:94; repo at v0.1.0:94** (reminders W1 + NL-query W2 deployed 2026-06-18; v94 = NL-query matched-only fix). **The fundraising grid + email capture is the canonical system of record.** Active thread: **W2 natural-language query** (backend + Matrix Q&A live; web "Ask" box next). Deploy/feature history: git log + `start9/0.4/startos/versions/`; longer-term backlog/debt: `ROADMAP.md` / `EVALUATION.md`._
|
||||
_Phase 0 + Phase 1 built; **box + repo live at v0.1.0:94** (reminders W1 + NL-query W2 deployed 2026-06-18; v94 = NL-query matched-only fix). **The fundraising grid + email capture is the canonical system of record.** Active thread: **W2 natural-language query** — backend + Matrix Q&A live; web "Ask" box is the last piece. Feature/deploy history: git log + `start9/0.4/startos/versions/`; longer-term backlog/debt: `ROADMAP.md` / `EVALUATION.md`._
|
||||
|
||||
- **W2 — natural-language query (read-only): BACKEND + MATRIX Q&A LIVE (deployed v0.1.0:93, 2026-06-18); web "Ask" box next.** `backend/nl_query/` — 12 curated parameterized queries + a slot validator (the trust boundary; no generic SQL) + a **local-Qwen** translator (question→{intent,slots} via Spark Control; nothing leaves the box, **no Claude, no redaction** — the simplification Grant chose). `POST /api/query/nl` (also accepts direct `{intent,slots}`) + `GET /api/query/catalog`, `require_bot_or_admin`, audited (`entity_type='nl_query'`) — **live on the box** (verified 400/200 post-install). Soft-delete-correct per table (gotcha: `fundraising_*` has **no `deleted_at`** — `graveyard` is the axis; emails via a live `eam` sighting). Guide: `docs/guides/nl-query.md`. **Step 5 (Matrix Q&A) DONE + DEPLOYED** — thin client in `backend/matrix_intake/query.py` (trigger grammar + answer rendering) + `crm_client.nl_query` + `bot.py` wiring, read-only (no approval gate), tested in `test_query.py`. **Two entry points (room-per-purpose model):** a **dedicated Q&A room** (`MATRIX_QUERY_ROOM=!RGlJEObVaIUtUVcHtx:matrix.gilliam.ai`) where every message is a question, **and** the `?`/`@bot` trigger in the intake room as a cross-room convenience. Bot rebuilt + running on the Spark (logs: `answering questions in room …`). **End-to-end verified from inside the bot container** (3 questions → correct intents, live box, no errors; `investors_cold` hits the 500-row cap so Matrix shows 30 + a refine note). **Remaining: the actual in-room Matrix smoke (a human typing a question) — not yet done.** **Matched-only fix (v0.1.0:94, LIVE 2026-06-18):** `comms_by_user` + `email_counts_by_user` were counting/listing the user's *entire* captured sent corpus, not just investor-linked email (missing the `EXISTS email_investor_links` gate that `recent_emails`/`query_email_activity` use) — fixed + regression-tested, deployed to the box in v94. **Next: step 4 web "Ask" box (Communications tab)** — the last thin client.
|
||||
- **W2 — NL query (read-only): LIVE on the box** (backend + Matrix Q&A shipped v93; matched-only fix v94). Curated parameterized catalog + slot validator (trust boundary; no generic SQL) + **local-Qwen** translator (`backend/nl_query/`; nothing leaves the box, no Claude/redaction). `POST /api/query/nl` + `GET /api/query/catalog` (`require_bot_or_admin`, audited). **Matrix Q&A client deployed** (`backend/matrix_intake/query.py` + `crm_client.nl_query`, read-only, no approval gate): **dedicated Q&A room** `!RGlJEObVaIUtUVcHtx:matrix.gilliam.ai` (every message is a question) **+** the `?`/`@bot` trigger in the intake room (cross-room convenience). Email/comms intents are **matched-only** (investor-linked email only — v94 fixed `comms_by_user`/`email_counts_by_user` which had counted the whole sent corpus). Guides: `docs/guides/nl-query.md` + matrix-intake. **Remaining: (a) the actual in-room Matrix smoke — a human typing a question (not yet done); (b) step 4 web "Ask" box (Communications tab), the last thin client.**
|
||||
|
||||
- **W1 — reminders & follow-ups: LIVE (deployed v0.1.0:93, 2026-06-18).** First-class tickler tied to the grid (migration `0006` — applied cleanly on the box per logs; CRUD `GET/POST/PATCH/DELETE /api/reminders`; derived `reminder_status` grid column; Reminders page + dashboard card + digest section; the `last_activity_at` recency rollup that W2 reuses). `0006` was verified up/down against a copy of `crm.db` before install. Deferred **W1b** = nurture-gap auto-suggested reminders.
|
||||
- **W1 — reminders & follow-ups: LIVE (shipped v93).** First-class tickler tied to the grid (migration `0006`; CRUD `/api/reminders`; derived `reminder_status` grid column; Reminders page + dashboard card + digest section; the `last_activity_at` recency rollup W2 reuses). Deferred **W1b** = nurture-gap auto-suggested reminders.
|
||||
|
||||
- **Done & live (detail in git log / ROADMAP):** email-proposal Matrix review + `bot` role (box v91); grid-driven Pipeline (v88); Matrix intake bot (Spark `matrix-intake` container); Gmail capture (DWD) + propose→approve + daily digest; Thesis Workshop + Architect (Claude, dual-approval); outreach drafts + radar. All draft-only.
|
||||
- **Tests:** **35/35 backend green** (`python3 backend/run_tests.py`; +`nl_query/` + matrix `test_query.py` suites), `py_compile` clean; render-smoke gates `make`.
|
||||
- **Tests:** **35/35 backend green** (`python3 backend/run_tests.py`), `py_compile` clean; render-smoke gates `make`.
|
||||
- **Next (priority order):** 1) **in-room Matrix smoke** of the Q&A room (type a real question; confirm the answer renders well on mobile — broad questions like "cold investors" hit the 500-row cap → 30 shown + refine note) + the intake `?`/`@bot` trigger; 2) **W2 step 4** web Ask box (last NL-query client); 3) **W3** bot grid-mutations behind the Matrix approval gate (local-Qwen parse); 4) **W1b** nurture-gap reminders; 5) Grant + Jonathan freeze v2.0 canonical; 6) in-room smoke of the intake disambiguation numbered-pick grammar; then P2 debt (reports comms-aggregate soft-delete sweep, `?limit=abc` crash, auth regression test, oversized StartOS icon).
|
||||
- **Open / risks:** W2 translation only **happy-path-validated** (typos/ambiguous/no-match phrasings shake out in live use); **Claude/Architect path still unverified live on the box**; v2.0 reserve-asset spine is the *working approved* spine but **not canonical** (needs dual sign-off); doc drift — `crm-overview.md` + `EVALUATION.md` still call `lp_profiles` live.
|
||||
|
||||
Reference in New Issue
Block a user