Entity identity and conservative merges
A memory owner is the account storing a message. A message role identifies its source, and an entity identifies the subject of a claim. These are separate: a user can paste a colleague’s email without adopting the colleague’s preferences.
Extracted English personal references such as I, we and they remain local
to their source event. They carry identity_status="unresolved_reference" and
reference_event_id metadata. Repeating preparation for that same event may
reuse its reference; another event, absent provenance, or an older globally
merged pronoun node cannot establish the same referent. Explicit non-personal
meanings such as US/country and IT/technology retain named-entity behavior.
This is a conservative English guard, not general coreference resolution. It
does not disambiguate several quoted speakers inside one event or equal names
belonging to different people.
enable_speaker_references (on by default since 2026-10-06) provides a named
exception. When a turn names its speaker (ingest(speaker=...)), a
first-person singular reference in its claims (I, me, my, mine,
myself) binds to an entity with that speaker’s name and type person, the
same node that other mentions of the name use. The claim keeps the literal
pronoun as its subject or object, and its speaker_reference metadata names
the speaker and which of the two it bound. A speaker’s claims then connect
across messages, so a repeated claim can merge (#209) and a named update can
supersede the value it replaces. Turns without a speaker or an explicit owner declaration, and plural,
second-person and third-person references, stay local to their message. It
became a default together with enable_claim_sentence_text and
packing.fold_repeated_text, after the three passed the default-change rule
on the DeepSeek answer track over ingest() packs (BENCHMARKS.md, “Default
change: claim sentences, speaker references and folding”). Only the caller
knows that the named speaker, and not someone the turn quotes, is who says
I, so set PRME_ENABLE_SPEAKER_REFERENCES=false when a speaker’s turns
quote others in the first person.
ingest(first_person_owner=True) provides a separate per-message declaration
for user/human sources with no named speaker. Under fresh v14 plans, singular
first-person references bind to one deterministic owner_reference entity per
owner and scope. Its content remains I; it binds no display name. Claims keep
their literal references and record owner_reference with the owner and bound
fields. The reserved source metadata key is prme_first_person_owner_v1.
This is caller-declared authorship, not automatic coreference. Leave it false
for pasted first-person letters; split mixed authorship into separate messages.
Old unresolved identities and named speaker entities are not merged into this
identity. See the correction API.
enable_speaker_grounding (default false) makes the same assumption during
grounding. Grounding requires a claim’s subject and object to occur in its
quoted sentences, and an extractor writes the speaker into a claim as their
name (“Dana, lives in, Denver” for “I live in Denver”) or as I (“Rachel, is
sister of, I” for “my sister Rachel”), so grounding discards a name absent from its evidence. Fresh extraction also
accepts an unnamed first-person singular subject (I, me, my, mine,
myself) when any of those forms occurs in its cited sentence. For example,
I / name / Sam is supported by “My name is Sam”, and a preference
I / wants_to_be_called / Sam by “Call me Sam”. This binds no personal name
and keeps the reference event-local. It does not infer a missing first-person
subject in “keep answers short”, bind plural references, or establish that
pasted first-person text belongs to the memory owner. With the
option, in a turn that names its speaker, the speaker’s own first-person
singular reference (I, me, my, mine, myself) counts as a mention of
a claim value that is the speaker’s name or one of those references. That
applies in the provider’s check, the pipeline’s second check and the sentence
choice of enable_claim_sentence_text. The model is asked the same question either way.
A first-person attempt or intention (“I’m trying to set up ESLint”) still
needs a predicate that keeps it when the claim names the speaker, and a claim
naming the speaker covers the speaker’s I clause, so recovery adds no
duplicate for it. Plural references are unchanged.
Built-in extraction keeps only claims whose named references resolve within the same response, apart from those event-local personal references. A missing or ambiguous reference discards its claim while preserving grounded, closed siblings; it never creates or selects an identity to repair model output.
Fresh extractions and plans record speech_act_v14. V14 preserves v13
unnamed singular-form matching and earlier qualifier, quantity, speech-act and
source-effective validity rules, and adds explicit owner references and bounded
correction matching. Saved v13 records still prepare v13 plans. Saved v11 and v12 extractions keep their
v12 plan behavior; saved v12 plans retain literal-only unnamed matching.
Saved v10 through v6 records also prepare v12, v5 records prepare v11, v4 prepare v10, v3
prepare v9, and v2 prepare v8. A v12 extraction record also prepares v12.
Legacy source_passage_v1 extraction records prepare missing plans under
temporal_validity_v7, so recovery never claims validation that did not run.
Prepared plans using speech_act_v11, speech_act_v10, speech_act_v9, speech_act_v8, temporal_validity_v7, grounded_quantities_v6, claim_qualifiers_v5,
event_local_references_v4, and earlier policies remain valid immutable replay
inputs.
Previously saved plans preserve their policy, node IDs and checksums and replay
unchanged. The default for an omitted historical policy remains the previous
value. Existing incorrectly merged identities are not automatically split; doing
so requires an explicit provenance-based correction.
Organizer duplicate and alias candidates must agree on owner, scope, memory type, source type, epistemic classification, session, event time, validity end, retention settings, pinning and metadata. This includes entity types and claim subject/predicate metadata. Unresolved personal references cannot become canonical identities through organizer merging or alias links.
For non-entity duplicate copies, automatic merging additionally requires exactly equal content and validity start. Two separately admitted observations remain distinct even when their text matches. Case changes in ordinary claim text are not assumed equivalent. Named entities retain stripped, case-insensitive name matching within the compatible metadata/provenance boundary. This policy favors retaining an uncertain duplicate over erasing an episode or qualifier.
Vector similarity still proposes candidates; it does not authorize replacing
different text with a canonical claim. organize(jobs=["deduplicate"]) reports
both candidates and actual merges, plus unapplied pairs and its merge-policy
version. A candidate count greater than zero with no merged nodes can be correct.
Compatible exact copies can still merge and combine their evidence references.
Organizer duplicate and alias merges now publish canonical evidence, copied relationships, retirement and one supersedence edge in a single backend transaction. They revalidate both nodes after entering that transaction. PostgreSQL locks shared nodes in UUID order before reading evidence, so overlapping merges cannot overwrite each other’s evidence union. A conflicting DuckDB transaction can fail safely and be retried against current state.
Copied relationships retain validity, provenance, confidence, metadata and
assertion time. Their deterministic IDs also recognize exact partial copies left
by older versions. A conflicting existing copy aborts the new transaction.
Each committed merge records complete before/after node values, original and
published relationships, and a checksum-protected ORGANIZER_MERGED operation.
The operation identity is stable for the unordered node pair and merge kind.
Non-finite numeric metadata is rejected before commit rather than silently
changed to JSON null in the journal. Existing compact JSON records retain their
original bytes, checksums and retry identities.
Retries return the committed identity without reactivating later-retired nodes.
External index eviction runs after graph commit and remains repairable by compaction. Retired graph state governs candidate admission if eviction fails. Cancellation or a lost acknowledgment may follow a committed transaction; callers must not interpret cancellation as proof of rollback. This adds complete records for new organizer merges, not replay of every historical manual or organizer mutation.
Alias application rechecks the actual names. A compatible known abbreviation,
case variant or exact normalized name can merge at the configured confidence
threshold. A high semantic score by itself only creates a RELATES_TO proposal
marked identity_verified=False, preserving both entities. Caller-supplied
candidate labels do not bypass these checks. A proposed alias is not a verified
same-person relationship.
New proposals publish their relationship and a checksum-protected
ALIAS_PROPOSED record in one backend transaction. Their operation and edge IDs
are stable for the unordered pair, so repeated or concurrent organizer passes
do not create duplicate links. The record retains both complete node inputs and
the exact edge. Version-2 records can additionally retain a complete external
assessment bound to exact node checksums. Repeated matching requests return the
first committed assessment; older proposals are never relabeled with evidence
they did not originally contain. Existing random-ID proposal edges are
recognized and reused but not backfilled with invented creation history.
Unverified proposals remain queryable as edges but are excluded from ordinary
neighborhood and shortest-path traversal unless a caller explicitly opts in.
An owner can list these records through the alias-proposal inbox and make one explicit accepted or rejected decision. The decision transaction retains the complete original proposal payload and reviewer input in a checksummed record. Acceptance rechecks the exact proposed node snapshots and publishes a separate verified alias edge; it leaves both nodes active and does not perform an organizer merge. Rejection publishes no traversable edge. Matching retries reuse the deterministic review record, while conflicting decisions fail. This turns a model or similarity signal into a reviewable identity link without treating it as permission to delete or supersede either entity.
These guards protect source identity and merge behavior. They do not establish that extraction predicates are entailed, that a source is truthful, or that a reader correctly attributes every quotation. The PersonaMem reader diagnostic still exposes attribution failures on raw histories; it is not an evaluation of these new ingestion/organizer guards.
Source: docs/ENTITY-IDENTITY.md in PRME at 58caddb1.