Person memory keeps useful statements that do not fit the typed fact ledger, with archive quotes, support healing, owner decisions and separate consent for each new model program. It sits beside the existing fact ledger and uses the same evidence rules. The design takes ideas from Honcho; the code and prompts are written fresh for msgvault.
https://github.com/user-attachments/assets/a6718bc1-6646-482b-9d97-29ebd17b55b8
Current delivery
21 PRs are open; none have merged as of 2026-10-24 UTC. The published work covers the two sweep fixes and most of the foundations. The complete person-memory feature has not shipped.
The current work is review fixes, CI cleanup and integrating the prerequisite stacks. Opening a PR does not mark a phase complete. This issue stays open across the roadmap; each partial PR should use Refs #1450.
Published PRs
Immediate parents and stack dependencies are documented in each PR.
| Area | PRs |
|---|---|
| Phase 0: context trim and evidence retractions | #1480 context priority; #1465 retractions before the provider packet |
| Observation contracts, schema and locked writes | #1462 contracts; #1469 schema/readers; #1470 per-person writes |
| Observation healing and owner operations | #1471 support/categories; #1472 merge/split; #1473 CLI/API decisions |
| Stability and automatic-extraction boundaries | #1475 attribute stability; #1476 resolver policy; #1478 stale facts; #1479 inference eligibility |
| Standing instructions | #1468 ledger; #1474 merge/split; #1477 CLI/API |
| Novelty building blocks | #1461 vector batch reads; #1464 selection kernel; #1481 known-evidence anchors; #1467 selection records |
| Sweep memory foundations | #1463 accounting; #1466 derivation due rule |
Still to publish or build
- Finish phase 1: definition stability in the observation clamp; memory state and note tables; identity resets; scheduling and touch integration. These remaining slices do not yet have public PRs.
- Phase 2: observation/instruction proposals from the sweep, their own provider profile and consent, context citations, and real novelty-selection wiring with preview and offline evaluation.
- Phase 3: run-to-run memory, deduction and induction, evidence-based tendencies, rechecks and shadow notes, plus owner review and enrollment.
- Phase 4: MCP and person-card readers, TUI/Web surfaces, observation embeddings and semantic merge, notes activation, and evaluation-gated defaults.
Phases land in order. Independent slices within a phase may proceed in parallel. New provider work stays off by default until its own consent and delivery gates are met.
Dependencies and related work
- #1330 person cards and #1300 who-knows supply reader and vector foundations.
- #1344–#1353 signal tiers supply tier-scaled intervals; until then tracked people retain manual eligibility.
- #1361 cold rooms, #1394/#1398 drafts and unsent messages, and #1431 hidden text define evidence exclusions as they land.
- #1224 supplies scoped person-edit permissions.
- #534 is the broader People roadmap; #1166 owns delivery policies; #1305 owns one-off open-loop requests.
Full phase scope, evidence rules and review questions
The phases land in order. PRs inside a phase can run in parallel unless one depends on another.
Phase 0: two sweep fixes
Both are independent of the rest and can go upstream now.
- The context trim drops by priority (retrieval order, round-robin across targets) instead of popping the tail of the sorted list. The wire order stays the same.
- The extraction packet stops showing profile values whose evidence the same run is retracting. A failing test comes first, and the fix ships only if that test fails on
main.
Phase 1: foundations, with no model calls
Unlocks: owner-written memory, review and healing, proven before any model writes to it.
- Observations. Atomic free-text statements about one person, stored beside the fact ledger and never written into profile fields. Each machine-written one cites a verbatim quote inside an existing evidence row. Levels are explicit, deductive, inductive and contradiction.
- Healing. When a cited message is deleted, edited, unlinked or reassigned, the ledger's existing evidence status events recompute support in the same transaction. No support left means
unsupported; support back meansactiveagain. Derived rows follow their premises through the whole graph. - Merges and splits. A person merge carries owner observations, decisions and rejections to the survivor, and an exact split restores them.
- Owner surface. Add your own observations, then confirm, pin, mark unsure or reject any row from the CLI and API. A rejection suppresses by content hash, so the same text doesn't come back.
- Stability rule. Attributes and observations get a stability class:
fixed,durable,volatileorepisodic. It tunes the resolver's freshness and staleness per class. It doesn't change the apply threshold, and pins still win. - Standing instructions. A ledger for rules a person stated about how they want to be addressed or contacted, like "call me Vee", stored with the quote. An instruction can only narrow behavior. It never authorizes a send, a recipient or an address. Owner-only in this phase.
- Novelty building blocks. Batch vector reads, the scoring kernel, anchors and selection records.
- One combined migration, plus per-person memory state and the rule that decides when a person is due.
personalityandcontact_frequencyleave automatic extraction. Self-descriptions become explicit observations, andpersonalityis written by the owner or promoted from an accepted tendency. This changes shipped behavior.
Phase 2: observations from the sweep
Unlocks: the sweep keeps what typed fields miss.
- A new observation pass proposes explicit observations and instruction candidates from what the person wrote, each with its quote. It runs on its own claim after extraction. The extraction program and its fingerprint don't change, so existing consent stays valid.
- It gets its own provider profile and consent, off by default.
- Context citations: a third-party report, or an owner proposal the person agreed to, is stored as context and never counted as the person's own words.
- Novelty-ranked evidence selection, behind the current
recencydefault. When there's more evidence than budget, keep the newest first, then spend the rest on messages least like what the ledger already cites for that person. It scores exact cosine in Go over the message vectors that already exist on this machine, so there's no new egress. When vectors are missing, partial or stale, it falls back to today's recency order exactly. Ships with a preview command and an offline eval.
Phase 3: sweep memory and behavioral tendencies
Unlocks: conclusions that span many messages, held to evidence the owner can check.
- Sweep memory. Per-person state carried between runs: a code-written cursor over what a run was shown, pending rechecks, and open hypotheses that didn't have enough evidence yet. Notes start in shadow mode.
- Deduction, then induction. Two bounded, single-shot programs per pass, with no tool loop. Deduction finds knowledge updates, implications and contradictions. Induction finds tendencies.
- Tendencies read as evidence, not labels: "In your archive, alice tends to reply with one or two lines." Code renders the sentence from a fixed frame (tends to, often, usually, has repeatedly, seems to prefer) and rejects absolute words, clinical or personality-type labels, guesses about motive, and moral judgments.
- Code decides trust. Support is counted from messages the person wrote, across independent conversations and calendar months. The lowest band needs at least 3 contexts over 2 months and 30 days. Below that, the result is an open hypothesis, not a conclusion.
- Never inferred from special categories. Behavior never leads to a conclusion about health, sexuality, religion, politics or the other special categories, whatever the owner opts into. The only path near them is deduction from what the person said about themselves, behind a separate per-category opt-in that's off by default, with a per-person deny list.
- Owner-reviewed, owner-only, never auto-applied. Every tendency starts as a proposal. Only the owner can accept one, so MCP clients and delegated tokens can't. Tendencies never reach CardDAV, and reading them needs its own permission.
- Its own consent purpose,
person_trait_inference, with per-person enrollment. Off by default. - CLI and API, then TUI and Web, each with a drill-down from a tendency to its premises and quotes.
Phase 4: readers and polish
- Rebuild requests for briefs and instructions after their support goes away.
- MCP reads:
list_person_observations, confirmed instructions, andget_person_traits. - Person card blocks for stable markers, instructions and tendencies.
- Observation-text embeddings under their own purpose, off by default, and semantic merge.
- Sweep notes on.
- Novelty becomes the default, only after it meets its eval bar.
- A live eval harness for tendencies.
What stays the same
- Evidence first. Every machine-written statement cites a verbatim archive quote, and loses support when its source goes away. Derived rows cite the observations they come from.
- Consent-gated. Each new model program has its own consent, off by default. Typed extraction and briefs keep today's
people_inferenceconsent and fingerprint. Novelty selection reads only local vectors. - Owner-only where it matters. Owner decisions and pins win. Automatic paths never change a confirmed or pinned row; they flag it. Instructions reach MCP clients only once the owner confirms them, as attributed data, never inside a system prompt.
- Exclusions apply everywhere. Drafts and unsent messages, hidden-text messages, list mail, automated senders, owner identities, cold rooms and quarantined messages never count as evidence.
- SQLite and PostgreSQL behave the same. No query scans
message_bodies. Fixtures use synthetic people.
Questions for review
- When a recheck never gets a model answer, should a confirmed row go to an owner queue while a proposed row is downgraded?
- Is 365 days the right default history window for the first observation pass when a profile sets none?
- How much of the budget should novelty selection keep for the newest messages before it picks the rest?
Activity
0No activity yet.