Capture city + LinkedIn on card intake; sharpen the transcription prompt

The card transcription prompt now reads emails/URLs/phones character-by-character,
explicitly forbids autocompleting toward a plausible domain (the mara.com ->
marac.com failure), and emits labeled lines (which also feeds the field extractor
cleaner input).

The extractor gains city + linkedin_url. city is a plain field (low-harm if wrong;
the human sees it on the card). linkedin_url follows the email-integrity rule: kept
only if it literally appears in the source / a revise instruction, never minted -- a
wrong profile URL points at the wrong person. Both flow to the contact via the
existing log-communication upsert (city also syncs to the grid contact pill).

Phone is intentionally NOT included yet: the bot's write path can't store it until a
small server-side change lands (next s9pk). See the matrix-intake guide.
This commit is contained in:
Keysat
2026-06-20 11:07:17 -05:00
parent 5e115a3409
commit 8b2eb01a65
8 changed files with 120 additions and 13 deletions
+6 -1
View File
@@ -18,6 +18,8 @@ _EDIT_ALIASES = {
"contact": "contact_name", "person": "contact_name",
"email": "contact_email",
"title": "contact_title", "role": "contact_title",
"city": "city", "location": "city",
"linkedin": "linkedin_url", "linkedin_url": "linkedin_url", "li": "linkedin_url",
"note": "note",
}
@@ -26,7 +28,8 @@ _NO = {"no", "n", "cancel", "discard", "reject", "stop", "👎", "❌"}
# "create a new investor anyway" replies to a disambiguation shortlist
_NEW = {"new", "none", "new investor", "none of these", "create", "create new", "add new", "neither"}
_CONTENT_FIELDS = ("intent", "investor_name", "contact_name", "contact_email", "contact_title", "note")
_CONTENT_FIELDS = ("intent", "investor_name", "contact_name", "contact_email", "contact_title",
"city", "linkedin_url", "note")
class ProposalStore:
@@ -174,6 +177,8 @@ def render(proposal):
("Contact", proposal.get("contact_name")),
("Email", proposal.get("contact_email")),
("Title", proposal.get("contact_title")),
("City", proposal.get("city")),
("LinkedIn", proposal.get("linkedin_url")),
("Note", proposal.get("note")),
]
for label, val in fields: