docs: handoff — in-app card intake (#7) live + device-confirmed at v0.1.0:100
#7 shipped in v100 and verified on the box; Grant device-tested on his phone — both camera capture and photo-library upload work. - matrix-intake guide: new "In-app card intake (#7)" subsection (the CRM's own twin of the Matrix M3 card flow), plus a load-bearing caveat — server.py now imports parse + spark, so those two must stay nio-free or the CRM image breaks. - AGENTS.md Current state: rewritten for v100; v99 device fixes confirmed; next steps reset to the standing mobile on-device gate.
This commit is contained in:
@@ -23,6 +23,11 @@ Spark). See *Fuzzy matching* below. Tests green (27/27 backend + the offline bot
|
||||
- A **separate process**, not part of the CRM. Its only third-party dep, `matrix-nio`, lives
|
||||
in `backend/matrix_intake/requirements.txt` and **must never** be added to the stdlib CRM
|
||||
(`backend/server.py`). Runs on the Spark (placement per `standards/guides/placement.md`).
|
||||
**Caveat (since v0.1.0:100): `parse.py` + `spark.py` are now ALSO imported by the stdlib CRM**
|
||||
— the in-app card endpoint `POST /api/intake/card` lazily imports them (they're nio-free:
|
||||
`parse`→`spark`→`ingest/llm`, no nio, no `crm_client`). So **keep `parse`/`spark` nio-free** —
|
||||
a nio-coupled helper added to either would break the CRM image, not just the bot. See the
|
||||
*In-app card intake* note under *Business-card capture* and `docs/handoffs/in-app-card-intake-plan.md`.
|
||||
- It **drafts; a human approves.** Nothing is written autonomously — every CRM write follows a
|
||||
`yes` reply in the proposal thread. This is exempt from "agents draft, humans send" the same
|
||||
way the digest is: it's internal data entry to our own CRM, not outward LP contact.
|
||||
@@ -149,6 +154,23 @@ existing flow (parse → match → disambiguate → approve → `log-communicati
|
||||
vLLM's PIL — most clients (Element iOS) transcode to JPEG on upload, but confirm on-device; ③ the
|
||||
offline tests stub the vision call (`test_spark.py`); the download + real OCR is **live-smoke only**.
|
||||
|
||||
### In-app card intake (#7 — the CRM's own twin of M3, v0.1.0:100, ships in the s9pk)
|
||||
|
||||
The same card flow, **in the app** instead of Matrix: a mobile camera button (`MobileCardCapture`
|
||||
in `frontend/index.html`, top bar left of the quick-log pencil) → take/pick a photo → `POST
|
||||
/api/intake/card`. The endpoint (`server.handle_intake_card`, authenticated **member+**, read-only)
|
||||
**lazily imports `matrix_intake/parse` + `spark`** (the nio-free core — see the *What it is* caveat),
|
||||
vision-transcribes (local VL via Spark Control), runs the **same** email/phone/LinkedIn integrity
|
||||
rule + `find_intake_match`/`find_intake_candidates`, and returns `{ok, transcription, proposal,
|
||||
match, candidates}` (soft-fails: 200 `{ok:false, reason:"unreadable"}`, 502 `vision_unavailable`).
|
||||
**Nothing is written** there — an editable mobile review sheet POSTs the approved proposal to
|
||||
`log-communication` tagged **`source="app_card"`** (vs `matrix_card`/`matrix_intake`). The client
|
||||
**downscales via `<canvas>` to JPEG** before upload, which also **normalizes iPhone HEIC→JPEG**
|
||||
(sidesteps the M3 HEIC-in-vLLM limit above). Differences from M3: **form-field edits only** (no
|
||||
NL-revise), and it **ships in the s9pk** (server + frontend), not bot-only. Tests:
|
||||
`backend/test_intake_card.py` (stubs vision+parse like `test_spark.py`); the camera/canvas/OCR path
|
||||
is on-device-only. Plan + locked decisions: `docs/handoffs/in-app-card-intake-plan.md`.
|
||||
|
||||
## Fuzzy matching (server-side, ships in the s9pk)
|
||||
|
||||
`GET /api/intake/match` returns `{match, candidates}`. `find_intake_match` is unchanged —
|
||||
|
||||
Reference in New Issue
Block a user