Repository navigation
feat(people): remember what you deal with each person about and keep their contact details - #579
Merged
Merged
Conversation
The contact keeper now keeps, for every contact, when you last emailed, heard from and met them, their next meeting, and a short note with a few topics on what you work on together (people/contact_notes.py). The note is written only from your own sent mail to them (without the quoted mail below it, and nothing Handle it for me sent) and the titles of meetings you set up, so a contact's own mail can't write it. It is rewritten only when that mail or those meetings change, at most 5 a pass and 20 a day. The Executive reads it on your own turns in list_people and ask_about_person, so it can suggest who to ask. Before this, ask_about_person on a contact always said "not shared", since contacts never chat. The contact's page shows it as "What I remember". Archiving a contact deletes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ers too The signature read now copies every contact detail it shows (phone, mobile, website, LinkedIn, another profile, postal address) into a new person_details list, not only the role. Each is kept only when the mail writes it, a website only on the sender's own non-freemail domain and a profile only on a known site (people/contact_info.py). One of each kind is the keeper's and a newer one replaces it; typed ones are never touched. Each is a change with Undo. Team members get the same signature read (role when empty, details) and the same memory note, still the principal's alone and only from the principal's own mailbox. People and chat can type details too. Arch-Docs: n/a - the guide change is the People page text, not the user_guide section Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… turn only A teammate's mobile or address in list_people reached any turn, a stranger's inbound mail included. They now come only on the principal's own verified turn, like the notes. An address is also capped at 14 words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-p00hbu # Conflicts: # packages/core/openexecutive/architecture/prebuilt/agents.json # packages/core/openexecutive/architecture/prebuilt/api.json
A bad detail on POST or PATCH /people answered 422 after the person was already created or updated. It is now checked first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ard from A note or topic with words like "system" or "prompt" was dropped and not tried again until new mail. Only links, addresses and tags are dropped now; the note comes only from the owner's own mail. "Last heard from" was read only when a note was rewritten, so it went stale; it is now read for up to 20 people a pass whatever the note budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review summary: 🔴 2, 🟡 1, 🟣 0. |
The people routes returned Person.details (some read from a teammate's email signature in the principal's mailbox) to any signed-in caller. They now go only to the principal and to that person. A refused mailbox read (auth or rate limit) in the signature or last-heard lookups now stops those lookups for the run instead of aborting it, so the notes are still written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A note the model wrote with a link or address no longer wipes the one there was: the activity is marked read and the old note stays. A refused mailbox read in the signature or last-heard lookups still lets the notes run, then is raised so the run is recorded as failing rather than looking healthy. Adds tests for /people/by-scope details and the details filter failing closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The details loop in upsert_person reused `kind`, so the person's kind became the last detail's kind and every chat call with details failed. Adds the chat details test and the note route's 404 for the principal's own row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review summary: 🔴 1, 🟡 0, 🟣 0. The one issue is that signature details can be added next to a value the owner typed (see the inline comment). |
…omain The daily note cap counted written rows, so failed or repeated calls never used it up; contact_note_tries now counts every call. A signature website on a parent of the sender's mail domain (co.uk for corp.co.uk) no longer counts as theirs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A signature phone was added next to a phone the owner typed. The keeper now skips any kind holding a value it didn't set, as it does for role. Arch-Docs: n/a - the guide change is the People page text, not the user_guide section Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review: 🔴 0 · 🟡 2 · 🟣 0. No must-fix issues found. The two optional notes are inline. |
A failed calendar read erased every stored next meeting and meeting count until the next good pass. Those fields now stay as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A 422 from the people routes showed "Unprocessable Entity"; it now shows the server's text naming the line that isn't a phone, site or address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review summary: 🔴 1, 🟡 1, 🟣 0. I read the diff from |
Undo on a team member now acts only on role and the contact details, so a name or alias change row for a teammate can't rewrite them. The contact detail validator and people-route access tests move into their own files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review summary: 🔴 0 · 🟡 1 · 🟣 0. Privacy gating on |
johnrufusone
added a commit
that referenced
this pull request
Oct 20, 2026
🤖 I have created a release *beep* *boop* --- ## [0.6.2](v0.6.1...v0.6.2) (2026-10-20) ### Added * **briefing:** show the live brief as a Right now card on Home ([#566](#566)) ([9121b20](9121b20)) * **chat:** approve held steps with a tap instead of saying go ([#573](#573)) ([0bb0d5a](0bb0d5a)) * **chat:** let the Executive change things in the app from chat ([#541](#541)) ([f36818b](f36818b)) * **chat:** let the owner choose when outside content holds a turn ([#571](#571)) ([96c6510](96c6510)) * **delegation:** add Suggested actions On and a clearer training layout ([#560](#560)) ([0c96fd4](0c96fd4)) * **delegation:** answer meeting invites from a card, and on its own under Handle it for me ([#568](#568)) ([85f457e](85f457e)) * **delegation:** attach Drive files to drafts and let a go run held steps first ([#555](#555)) ([c887632](c887632)) * **delegation:** let the Executive rename and move the company's own Drive files, with a tap card for the rest ([#569](#569)) ([7124221](7124221)) * **delegation:** let the person choose sender only or everyone on a reply card ([#556](#556)) ([43561cf](43561cf)) * **delegation:** show reply cards closed with a one-line summary, open on tap ([#570](#570)) ([59ef8e0](59ef8e0)) * **delegation:** show What it does for you beside each Delegate tab ([#561](#561)) ([4648051](4648051)) * **integrations:** approve cards with buttons in Telegram ([#542](#542)) ([62bde0b](62bde0b)) * **integrations:** read Excel files in chat and images attached to emails ([#537](#537)) ([322659d](322659d)) * **integrations:** transcribe voice notes and add a mic to web chat ([#539](#539)) ([b3233e0](b3233e0)) * **mcp_server:** let an AI app's turn take actions when the request allows it ([#533](#533)) ([30319d9](30319d9)) * **people:** keep contacts up to date from sent mail and meetings ([#557](#557)) ([1aa8966](1aa8966)) * **people:** reach people in the chat app they last talked in ([#544](#544)) ([45ad765](45ad765)) * **people:** remember what you deal with each person about and keep their contact details ([#579](#579)) ([f719738](f719738)) * pick chat apps by name, describe watches, tap answers on replies ([#543](#543)) ([0baf9a1](0baf9a1)) * **ui:** add How it learns card and rename the screen to Learning ([#550](#550)) ([d1c50e5](d1c50e5)) * **ui:** keep the Topic view short with one-line topics and five per band ([#538](#538)) ([511e1a9](511e1a9)) * **ui:** show each chat's app logo instead of a channel pill ([#536](#536)) ([3a9e2e9](3a9e2e9)) ### Fixed * **briefing:** call people in the live header by name, not their address ([#572](#572)) ([3f697e2](3f697e2)) * **briefing:** make briefs report the reader's day, not their own messages ([#545](#545)) ([4b450ba](4b450ba)) * **briefing:** name waiting drafts and say what approved app cards did ([#558](#558)) ([80bfc74](80bfc74)) * **briefing:** treat the reader's own messages as background, not news ([#548](#548)) ([029a7ab](029a7ab)) * **chat:** start each tool round's text on a new paragraph ([#562](#562)) ([dda3fc5](dda3fc5)) * **delegation:** draft a reply when a contact proposes a time ([#559](#559)) ([0413f78](0413f78)) * **delegation:** draft a reply when an answer to a call request leaves the time open ([#554](#554)) ([479baf6](479baf6)) * **delegation:** read the person's own last email before sorting a reply ([#553](#553)) ([9b594bb](9b594bb)) * **delegation:** stop drafts writing the sender's name twice above the signature ([#535](#535)) ([c049abb](c049abb)) * **delegation:** work a typed answer into the reply draft instead of pasting it ([#567](#567)) ([a182d80](a182d80)) * **integrations:** reply to a voice note with just the answer ([#547](#547)) ([c14ff9e](c14ff9e)) * **memory:** let a name reach a lesson and keep the grader's proof to the person's words ([#551](#551)) ([528e546](528e546)) * **memory:** review chats that read mail and count misses the product recorded ([#549](#549)) ([fbcf3d2](fbcf3d2)) * **scheduler:** stand down a follow-up already handled in chat ([#540](#540)) ([4ac9af2](4ac9af2)) * **ui:** show last period's count instead of a signed change on Done for you ([#552](#552)) ([15964d9](15964d9)) ### Changed * **orchestrator:** shrink the cached chat prefix ([#546](#546)) ([50a8f1b](50a8f1b)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The contact keeper adds contacts, but the Executive knows nothing about what the owner deals with them about or when they were last in touch. Asking about a contact in chat returns "not shared", because peer memory only learns from people who chat. Only a role is read from a signature, so a contact's phone, website and address are never saved, and teammates get none of this.
Approach
people/contact_notes.py): on the same background pass, each contact and teammate gets the dates they were last emailed, heard from and met, their next meeting, and a short note with topics. The note is written only from the owner's own sent mail (no quoted text, nothing sent by Handle it for me) and meetings the owner organized. It is rewritten only on new activity, at most 5 a pass and 20 model calls a day. The Executive reads it on the owner's own turn inlist_peopleandask_about_personso it can suggest who to ask. The person's page shows it to the owner as What I remember.people/contact_info.py, tableperson_details): the signature read also copies phone, mobile, website, LinkedIn, another profile and postal address. Each is kept only if the mail writes it. A website must be on the sender's own non-freemail domain, and a profile must be on a known site. Each detail is a change with Undo, and a kind someone typed is left alone. Details can also be edited on People and set from chat.Checklist
test_contact_keeper.py,test_contact_info.py,test_people_details_access.py,contactChanges.test.mjs,contactDetails.test.mjs)ruff checkandmypypasstsc, eslint,npm test)🤖 Generated with Claude Code