Pages
Conflicts And Corrections
Standalone memory service for AI tools, with durable memory, evidence, team isolation, and MCP access.
Conflicts And Corrections
Dense-Mem preserves raw evidence and resolves stale authored state with audited Relationship lifecycle transitions. It asks for a client decision when the caller-owned identity, predicate, scope, time, or current-state behavior cannot be resolved safely. A profile cannot mutate another profile's Relationship, but the bounded system Conflict reviewer may close a losing team Relationship episode after an evidence-backed case resolution. Evidence bytes, observations, support links, and author attribution remain immutable.
This page is the single source of truth for conflict and correction interaction. Relationship lifecycle is in Relationship Model And Lifecycle, identity merge/split is in Entity Identity And Resolution, and orchestration is in Memory Write Pipeline.
Same-Owner Conflict Flow
%%{init: {"sequence": {"rightAngles": true}}}%%
sequenceDiagram
actor User
participant Host as AI client
participant DM as Dense-Mem
participant PG as PostgreSQL
User->>Host: Production now deploys from release
Host->>DM: remember(new evidence)
DM->>PG: Preserve evidence, observation, verifier event, and conflict
DM-->>Host: relationship_needs_review
Host->>DM: trace_memory(related relationship_id)
DM->>PG: Load current state and append-only history
PG-->>DM: Existing/new evidence, decisions, and transitions
DM-->>Host: Trace and explicit decision choices
Host->>User: Ask the exact conflict question
User-->>Host: Decision plus evidence
Host->>DM: resolve_memory_placement(...)
DM->>PG: Append decision and recompute affected current stateAn unresolved same-owner conflicting observation is not an active edge. The owner's prior eligible Relationship stays current unless accepted evidence and deterministic predicate behavior permit supersession. A schema-valid, entailed cross-owner correction can become the caller's active edge and append a cross-reference to the other profile's record.
Why Review Is Required
| Cause | Example | Safe result |
|---|---|---|
| Entity ambiguity | context now suggests a different person named Mark | identity_needs_review; no guessed split or dependent edge |
| Unknown predicate | “Dense-Mem dogfoods PostgreSQL” maps to no registered predicate | predicate_needs_review; preserve wording; create no Relationship |
| Scope ambiguity | “uses PostgreSQL” may mean production or tests | preserve observation and request scope |
| Current-state conflict | production has competing deploys_from values | preserve both histories and ask |
| Temporal ambiguity | new evidence may describe past rather than current state | request validity context |
| Insufficient change evidence | weak evidence should not replace a supported current Relationship | retain candidate/pending_evidence without an active edge |
| Correction ambiguity | “that is wrong” identifies no Relationship | request relationship_id or a disambiguating query |
| Cross-profile disagreement | profile B supplies stronger evidence against profile A's Relationship | preserve A, create B's eligible Relationship, append a challenge/correction cross-reference, and create/update the team Conflict case |
Cross-Profile Corrections
Profiles A, B, and C may all read same-team knowledge. Each authors only the Relationships and observations created under its profile. Ordinary profile writes can change only caller-owned lifecycle state.
Assume profile A has two Relationships based on an identity that later appears to combine two people:
A: ent_mark -> works_on -> Dense-Mem
A: ent_mark -> works_on -> BillingProfile B obtains distinguishing evidence. B creates its own Entity resolutions
and Relationships through normal remember processing:
B: ent_mark_dense -> works_on -> Dense-Mem
B: ent_mark_billing -> works_on -> BillingIn the same transaction, Dense-Mem appends corrects or challenges
cross-references from B's new Relationships to A's related Relationships and
opens or updates the durable team Conflict case. A's status, tier, supports,
validity, and Entity resolutions do not change during B's placement.
%%{init: {"flowchart": {"curve": "linear"}}}%%
flowchart LR
A1["A: Mark works_on Dense-Mem"] --> Set["Team conflict set"]
A2["A: Mark works_on Billing"] --> Set
B1["B: Mark-Dense works_on Dense-Mem"] --> Set
B2["B: Mark-Billing works_on Billing"] --> Set
B1 -->|"corrects"| A1
B2 -->|"corrects"| A2
Set --> Case["Team Conflict case"]
Case --> C["Profile C recall"]
C --> Ask["Show material alternatives<br/>and ask for evidence"]
Ask --> CWrite["C remembers confirmation<br/>under profile C"]
CWrite --> Nightly["Nightly reviewer resolves,<br/>overdues, or keeps open"]Profile C sees both material positions while the case is open. C may submit new
evidence through normal remember; any confirmation C remembers belongs to C and
may confirm B or challenge A. It does not directly edit either record.
If A later accepts the correction directly, A submits or adopts exact evidence through the normal verifier. A may then supersede A's old Relationships and create A's corrected Relationships. Separately, the system Conflict reviewer may supersede A's stale episode after the team case resolves. Adoption preserves B's evidence author, provenance, and source-group identity; it does not count the same evidence twice.
The canonical ownership and cross-reference fields are defined in Relationship Model And Lifecycle. Conflict grouping and preference ranking are defined in Vector Search And Ranking.
Stale team knowledge example
Assume A recorded an accurate business rule six months ago. The business changed the rule five months ago, but Dense-Mem learned about the change only when B later submitted exact evidence:
t0 A owns Relationship A1: production deploys_from main
t1 the business changes production to release
t2 B owns Relationship B1: production deploys_from release
B1 corrects A1, with valid_from=t1 supported by B's evidenceAt t2, B's placement creates B1, the corrects cross-reference, and an open
team Conflict case. A1, A's evidence, support, tier, status, and validity remain
unchanged during placement. The AI verifier does not decide that a conflict
exists; server policy detects the incompatible single-current state after B's
submitted evidence verifies.
While the case is open, C receives both material positions plus an explicit
conflict question. C may submit new exact evidence through normal remember; any
resulting Relationship belongs to C and is grouped with the matching or new
position. A bare vote, profile count, or unsupported "B is right" assertion
changes no disposition.
The nightly Conflict reviewer owns automatic resolution. If B's side becomes the
unique winner under the deterministic policy, one PostgreSQL transaction marks
the case resolved, sets A1 status=superseded, writes A1 valid_to to the
resolved cutoff, appends Relationship and Conflict ledger events with
actor=system_conflict_reviewer, and queues rebuildable search refresh. A's
original evidence fragment and support remain traceable. Current recall at or
after the cutoff returns B-side evidence in primary results[], includes a
compact resolved conflict reference, and keeps A1 available through trace. Recall
with valid_at before the cutoff may still return A's position. Recall with
known_at before B's correction arrived reconstructs the older system view.
Durable Team Conflict Cases
An authored conflict set is still derived from Relationships, accepted cross-references, registered single-current behavior, identity history, scope, and time. When that set contains a material cross-profile Relationship disagreement, Dense-Mem also persists one team-scoped conflict case so review, deadlines, retries, and decisions survive process restarts.
ConflictCase
conflict_id
team_id
kind
status: open | overdue | resolved | dismissed
version
opened_at
review_due_at
next_review_at
claim_token
lease_expires_at
review_attempts
last_evaluated_at
resolved_at
effective_at
effective_time_basis: evidence_time | recorded_fallback
preferred_position_id
policy_version
ConflictPosition
position_id
member Relationship IDs and versions
owner profile IDs
accepted evidence and source-group handles
ConflictEvent
event_id
prior and resulting case state
actor profile when client-triggered or system worker when reviewer-triggered
reason code, policy version, time basis, and referenced versions
created_atThe case row is current materialized workflow state. Case events are
append-only. Position membership never merges authored Relationships or counts
copied evidence more than once. dismissed means fewer than two material
positions remain after an owner retraction, source revision, or other normal
lifecycle change; it is not a truth decision.
| Authored knowledge | Team conflict disposition |
|---|---|
| A1 and B1 retain immutable author attribution | the case belongs to the team, not A or B |
| each Relationship keeps its own evidence/support ledger | resolution may close losing stale episodes through audited system transitions |
| neither author receives the other's evidence as support | equivalent evidence retains its original source-group identity |
| ordinary profiles cannot rewrite cross-profile validity | effective_at is the cutoff used for current-read disposition and losing-episode closure |
| trace returns every authorized position and event | primary current recall omits resolved non-preferred support paths |
A conflict case is created or changed only from committed, schema-valid state.
Vector similarity alone cannot open one. The initial durable-case scope is a
cross-profile Relationship disagreement established by a verified
challenges/corrects reference or by incompatible, comparable
current_cardinality=one positions. Identity ambiguity and same-owner placement
review continue to use their existing review workflows.
Deterministic resolution policy
The counting unit is a current accepted independent source group. Profile count, Relationship row count, copied fragments, summaries, adoptions, and repeated source revisions are not votes.
Before review_due_at, one position qualifies only when it has at least four
independent source groups and more than 75% of counted support for the material
case. At or after review_due_at, one position qualifies when either:
- it is the unique position with an allowed authoritative source group; or
- it has at least two independent source groups and more than 50% of counted support.
In all cases, every counted support must be accepted, entailed, currently effective, and applicable to the conflict scope. A source group that currently supports incompatible positions counts toward neither side until its support is cleaned up.
Authoritative opposition normally blocks automatic replacement. A timed strong
override is allowed only when the proposed winner has at least four independent
source groups, more than 75% of counted support, and verifier-confirmed evidence
that the replacement became effective after the losing authoritative position.
recorded_fallback time cannot override authoritative opposition.
The cutoff is the evidence-supported effective time when the verifier confirms
the extracted temporal bound. If no reliable bound exists and no authority
override is needed, the reviewer may use the first contradictory placement time
as recorded_fallback. Missing or conflicting time keeps the case open when the
chosen threshold requires evidence time.
Resolution appends case events, appends Relationship transitions for losing
episodes, updates their current status/valid_to, and queues rebuildable search
refresh. It never edits raw evidence, observations, verification events, support
links, or author attribution. One fragment may support unrelated current
Relationships, so primary-result filtering operates on the relevant Relationship
support path rather than globally hiding the fragment.
Responding from another profile
Any active same-team profile with write scope may respond with new evidence.
The relevant Relationship proposal carries the recall-supplied conflict_id
and expected case version. Dense-Mem validates the version and that the verified
proposal materially belongs to the case before committing evidence or case
state. A stale version fails without changing state so the host can recall the
current alternatives and retry. The exact MCP field shape belongs in
Technical Reference.
The same transaction that places the caller-owned Relationship and validated
cross-reference opens or updates the case, membership, deadline/version, and
search refresh intent. It does not resolve the case. There is no separate
cross-profile resolve command; automatic resolution belongs to nightly review.
Nightly Conflict Review
The nightly job is the deterministic Conflict maintainer. It reviews known open or overdue cases, repairs membership, resolves qualifying cases, and closes stale Relationship episodes. It does not scan all old Relationships by age and it does not call a model.
For each case whose next_review_at is due, whether before or after
review_due_at, the job:
- claims bounded team-local work with a durable lease
- reloads current Relationship versions, effective supports, source groups, cross-references, scope, and temporal bounds from PostgreSQL
- repairs stale position membership and recomputes the policy view
- resolves only when exactly one position meets the automatic floor for the current pre-TTL or post-TTL phase
- marks the case
overdue, appends an escalation event, and schedules the next nightly check when no unique position qualifies - dismisses a case only when committed lifecycle/source changes leave no material disagreement
- when resolving, locks and updates the losing Relationship rows, appends transition events, marks the case resolved, appends the Conflict event, and queues rebuildable search/read-model refresh work in one transaction
The review deadline comes from the versioned team policy. Reaching it is not
evidence and does not force a winner; it only enables the lower automatic
threshold. Duplicate evidence from the same source group does not extend the
deadline. New independent support updates membership and may resolve on a later
nightly run, but it does not move the original deadline. A later contradictory
business change opens a new conflict episode instead of reopening a resolved
case. Database/worker failure leaves the case due and unresolved.
Multi-instance workers use durable daily run reservation plus team-local FOR UPDATE SKIP LOCKED claims, bounded retries, and lease recovery.
The job may update conflict workflow rows, losing Relationship status and
valid_to, append Relationship transition events, and enqueue rebuildable search
state. It may not edit or delete evidence, observations, verification events,
RelationshipCrossReferences, support links, Relationship ownership, author
attribution, Entity resolution, or source history. Operators inspect an overdue
case or submit new evidence; they do not repair it with direct SQL.
Defaults and bounded overrides belong in
Configuration.
Inspect Before Deciding
Use the relationship_id from recall discovery paths or from a placement
relationship_outcomes[] entry:
{
"relationship_id": "r_deploy_branch",
"include_evidence_content": true,
"include_verification": true,
"include_transitions": true,
"max_depth": 1,
"max_edges": 12
}The client presents:
- current subject, predicate, object, polarity, scope, and validity
- tier, status, current-cardinality behavior, and source count
- accepted evidence and material verification events
- the new conflicting observation and its evidence verdict
- exact identity, predicate, scope, or temporal ambiguity
- the before/after impact of each allowed decision
An opaque “accept or reject?” prompt is insufficient.
Identity Review
The client may select only a server-supplied same-team candidate:
{
"ingest_id": "ing_01J...",
"placement_item_id": "item_identity_1",
"action": "select_entity",
"decision": {
"mention_ref": "mark",
"entity_id": "ent_mark_huang"
},
"evidence": [
{
"content": "I mean Mark Huang, the Dense-Mem maintainer.",
"source_type": "manual",
"authority": "authoritative",
"source_group": "user-resolution:ing_01J..."
}
],
"idempotency_key": "identity-resolution-1"
}confirm_new_entity requires evidence that distinguishes a new identity. The
client never allocates the new ID.
A late same-name conflict may require a split. Dense-Mem first shows only the caller's observations and Relationships that may move. After confirmation, it creates the new Entity and reassigns only selected caller-owned immutable observation IDs. It never moves another profile's rows or every row based on display text.
Predicate Review
An unknown phrase remains on the observation with no predicate_key. Review
may:
- select an existing server-supplied registered predicate when meaning matches
- reject the observation mapping
- route a proposed registry change through a separately authorized, versioned vocabulary workflow
The verifier and ordinary review endpoint cannot add a predicate definition. A Hypothesis is not an unknown predicate; it is an isolated dream output using an already registered predicate. See Dreaming.
Relationship Review Actions
| Action | Meaning |
|---|---|
accept | append authoritative client evidence for the pending observation, then rerun normal policy |
reject | append the rejection and preserve observation/history |
correct | append replacement evidence and reprocess affected knowledge |
forget | retract the caller-owned selected Relationship from active reads while retaining its ledger |
acknowledge | mark review consumption; change no semantic state |
accept does not bypass verification or directly assign fact. Fact promotion
uses the authority and independent-source rules in
Relationship Model And Lifecycle.
These client actions mutate only a Relationship owned by the authenticated
profile. To address another profile's Relationship, the caller submits new
evidence through remember; deterministic post-verification identity and
conflict policy derive the appropriate cross-reference and case update. The
system Conflict reviewer is the only non-owner lifecycle writer for a
cross-profile stale-state case. There is no cross-profile client accept,
forget, supersede, merge, or split shortcut.
Correct With New Evidence
A correction appends evidence; it is not an in-place text edit.
{
"ingest_id": "ing_01J...",
"placement_item_id": "item_relationship_1",
"action": "correct",
"evidence": [
{
"content": "The user confirmed that production now deploys from release.",
"source_type": "manual",
"authority": "authoritative",
"source_group": "user-resolution:ing_01J..."
}
],
"proposal": {
"entities": [
{
"ref": "production",
"name": "production",
"entity_kind": "environment",
"identity_context": {
"system": "Dense-Mem"
}
},
{
"ref": "release",
"name": "release",
"entity_kind": "git_branch",
"identity_context": {
"repository": "Dense-Mem"
}
}
],
"relationships": [
{
"proposal_id": "production_deploys_from_release",
"subject_ref": "production",
"predicate": "deploys_from",
"object_ref": "release",
"polarity": "+",
"modality": "statement",
"evidence": [
{
"evidence_index": 0,
"start": 0,
"end": 60
}
]
}
]
},
"idempotency_key": "deployment-correction-1"
}The replacement enters the same extraction, one-call verifier, deterministic
lifecycle, and PostgreSQL transaction as every remember. Prior evidence and
transitions remain traceable.
This action corrects the caller's Relationship; it does not declare a shared
source globally obsolete. A source owner that can prove stable lineage instead
uses source_key, source_revision, and previous_source_revision, optionally
with its own supersedes_fragment_ids. Source activation occurs at intake,
makes the prior revision ineffective for every profile that adopted it, and
recomputes affected tiers from remaining effective support. The caller cannot
mix a profile-local correction with unowned source-fragment retirement.
Same-Owner Before And After
| Before decision | After an accepted correction |
|---|---|
| supported prior Relationship stays current | prior record is superseded or retracted only when registry behavior and evidence permit |
| new conflict is held and has no active edge | eligible replacement is exposed as one SemanticEdge |
| prior evidence and decisions are append-only | both old and new provenance remain traceable |
| vector search may still represent the prior version | source/full-text/adjacency reads change at commit; version-matched embedding job updates vector search |
For a cross-profile correction, the target record does not enter the right-hand column during placement. The caller creates a separately owned Relationship and cross-reference; the team Conflict case preserves both positions until the nightly reviewer resolves or escalates the case.
Forget And Retraction
forget removes a caller-owned Relationship from current graph-shaped reads
without deleting its semantic nodes or historical ledger. Same-team visibility
does not authorize forgetting another profile's record.
%%{init: {"flowchart": {"curve": "linear"}}}%%
flowchart LR
Before["Relationship status=active<br/>SemanticEdge visible"] --> Decision["Authorized forget decision"]
Decision --> Append["Append retraction event<br/>and audit"]
Append --> Current["Set current status=retracted"]
Current --> After["SemanticEdge no longer returned"]
After --> Nodes["Entity / Value nodes remain"]
After --> Trace["Evidence, verification,<br/>support and transitions remain"]Because SemanticEdge is a PostgreSQL read rule, the edge disappears from normal reads in the same transaction that records the retraction. There is no second graph copy to delete.
This is logical forgetting. A privacy-erasure request is a separate authorized workflow that may redact payload content while retaining minimal tombstones, audit proof, and referential integrity required by policy. Clients must not emulate either operation with direct SQL deletion.
Deterministic Current-State Decisions
Predicate registry fields relationship_kind and current_cardinality guide
whether accepted knowledge coexists or may supersede a prior current value owned
by the same profile. They are not model decisions and never authorize
cross-profile ordinary writes. Cross-profile stale-state closure is limited to
the nightly Conflict reviewer and the deterministic case policy above.
%%{init: {"flowchart": {"curve": "linear"}}}%%
flowchart TD
Accepted["Accepted new Relationship"] --> Kind{"state or event?"}
Kind -- event --> Coexist["Keep both occurrences"]
Kind -- state --> Cardinality{"current cardinality"}
Cardinality -- many --> Coexist
Cardinality -- one --> Scope{"Same subject, predicate,<br/>scope and comparable time?"}
Scope -- No --> Coexist
Scope -- Yes --> Evidence{"Evidence safely establishes<br/>replacement?"}
Evidence -- No --> Review["Hold conflict for review"]
Evidence -- Yes --> Supersede["Append supersession;<br/>change current state atomically"]Canonical behavior belongs in Relationship Model And Lifecycle; this page owns how the client sees and resolves uncertainty.
Risks And Mitigations
| Risk | Concrete failure mode | Mitigation |
|---|---|---|
| Wrong review target | a decision for one conflict applies to another | require ingest/item/Relationship IDs, idempotency key, and echo an impact summary |
| Accept bypasses policy | a client click writes an active fact directly | append evidence and route through strict verification and deterministic lifecycle |
| Correction erases history | old evidence is edited to match new truth | immutable fragments plus append-only observations, decisions, support, and transitions |
| Homonym split corrupts history | finance-team Mark causes all Mark edges to move | client-confirmed impact preview and caller-owned observation-ID-level reassignment |
| Unknown predicate expands vocabulary | verifier invents dogfoods as a durable key | registry allowlist and separate authorized vocabulary workflow |
| Wrong supersession | a many-valued predicate is treated as single-current | explicit current_cardinality, scope/time comparison, and before/after preview |
| Forget becomes data loss | deleting an edge also removes source and audit history | transactional retraction status; nodes and append-only ledger remain |
| Stale vector confuses review | vector search surfaces meaning from before correction | source-version checks, exact trace by ID, and explicit search freshness |
| Cross-profile correction becomes immediate mutation | B's placement marks A's Relationship superseded before review | placement can write only B's Relationship, cross-reference, and open/update case; non-owner supersession is allowed only in the nightly reviewer transaction |
| Majority becomes truth | several profiles copy one weak source and outvote stronger evidence | preserve source groups, deduplicate common origins, and rank evidence rather than author count alone |
| Correction impersonates source revision | a profile-local correct request invalidates evidence adopted by other owners | reserve team-wide invalidation for the immutable source owner and exact prior-revision contract |
| Deadline becomes truth | an unresolved case automatically chooses B after seven days | TTL only switches thresholds; require one unique temporally applicable position above the applicable evidence floor, otherwise mark overdue and escalate |
| Reviewer closes the wrong episode | B's branch change supersedes an unrelated A Relationship sharing text | lock case membership by Relationship ID/version, revalidate scope/predicate/cardinality/time, and update case plus losing Relationships in one transaction |
| Historical recall uses today's winner | a query for six months ago returns only B | evaluate both valid_at and known_at against conflict events and effective time |
| Fragment-wide suppression hides valid facts | A's fragment supports another still-current Relationship | filter only query-relevant support paths and retain the immutable fragment/search document |
| Stale C response attaches to the wrong case version | C confirms an alternative after the case was reopened or regrouped | require conflict_id plus expected version and reject stale context before commit |
Acceptance Invariants
- conflict preserves old and new evidence
- unresolved identity or predicate creates no active dependent edge
- every decision records actor, provenance, time, target IDs, and idempotency
- correction never mutates verbatim evidence
- accept, reject, correct, split, and forget write through normal PostgreSQL policy—not a graph side channel
- a late split moves only explicitly selected caller-owned observations
- prior current state changes only in the same transaction as its transition
- forget removes the SemanticEdge but retains Entity/Value nodes and all ledger history
- trace reconstructs conflict, decision, and supersession/retraction lineage
- a profile cannot accept, forget, supersede, merge, split, or change support for another profile's knowledge
- cross-profile corrections remain independently authored and link both Relationships without hiding either from authorized trace
- adopting cross-profile evidence preserves its original provenance and does not create a second independent source group
- normal correction changes only caller-owned Relationship state, while an owned source revision may invalidate its evidence team-wide through system recomputation
- a material cross-profile disagreement has one durable team case with append-only events and versioned position membership
- a resolved case removes only non-preferred current support paths from primary recall and keeps every authored Relationship available to trace
valid_atbefore the change andknown_atbefore the correction reconstruct the corresponding historical view- another writer's response creates that writer's evidence-backed Relationship and cannot act as a bare vote
- placement creates or updates Conflict cases but does not resolve them
- nightly review is the only automatic Conflict resolver and model-free
- deadline expiry without one qualifying position produces
overdue, not an invented winner - the nightly job may close losing Relationship episodes with audited
status=supersededandvalid_toupdates, but cannot mutate raw evidence, support links, ownership, author attribution, Entity resolution, or source history