Skip to content

feat(memory): evidence-backed claims and relationship-graph substrate (#178 s1) - #239

Merged
Ambisphaeric merged 1 commit into
mainfrom
feat/178-claims-s1
Jul 17, 2026
Merged

Ambisphaeric merged 1 commit into
mainfrom
feat/178-claims-s1

Conversation

@Ambisphaeric

Copy link
Copy Markdown
Owner

Refs #178 (slice 1 of N — substrate only).

The durable representation for learned relationships the system lacked — a person works on a repo, a repo belongs to an app, an entity relates to an earlier author. This slice lands the SUBSTRATE only: a typed append-only Claim contract, a deterministic no-model builder, store + relationship queries, and the honest user-correction path. No surface, no model-enriched semantic claims — named OUT below.

What this delivers (per the issue's acceptance criteria)

  • Claim contract (shared/contracts/src/records/claim.ts): typed, versioned, append-only Claim — subject → relation → object, grounded only in evidence refs (ClaimEvidenceRef over context-packet/moment/distillate) with minItems:1, so a claim with no evidence is unrepresentable at the schema boundary — every claim traces to source observations. Framed proposal-not-truth: source (derived/user), state (provisional/confirmed/corrected/rejected/superseded), deterministic confidence, ClaimProvenance(builder + evidenceCount = the recorded derivation behind confidence), ClaimCorrection + corrects on sovereign user rows, append-only revision/supersedes, firstObserved/lastObserved = honest valid-time from the evidence.
  • The relation-kind decision — CLOSED starter union, justified. ClaimRelation = co-occurs-with · works-on · belongs-to · authored · member-of · relates-to, not an open string: relation is a query axis (and later a UI/semantic axis), so an open string invites un-queryable drift. relates-to is the deliberate generic escape-valve; extending is a reviewed contract change + CLAIM_SCHEMA_VERSION bump + regen (the MomentKind/SummaryLevel precedent). The enum is COMPLETE now even though slice 1's builder emits only co-occurs-with — the sole relation co-occurrence can assert without a model. The semantic kinds are carried by a later judge-enrichment slice (proposals, roadmap: ambient context runtime — canonical ordered execution tracker #189) and by user corrections.
  • Deterministic builder (apps/engine/src/index/claims.ts): pure buildClaims derives co-occurrence from entities named together in one ContextPacket's candidates (reusing feat(context): converge separate senses into inspectable ContextPackets #176's converged correlation) or one moment's refs — symmetric endpoints canonically ordered by id, dangling refs never claimed, no evidence ⇒ no claim, confidence a fixed evidence-count map capped <1.0, repeated evidence strengthens only via a NEW revision (never a silent mutation). Content-derived ids ⇒ byte-stable replay (claims-replay.test.ts: same evidence into two fresh stores ⇒ byte-identical). No model this slice.
  • Wired at the session-end seam (apps/engine/src/index/produce-claims.ts + api/http.ts): materializeClaims runs AFTER packets materialize, same contained-failure discipline as packets/summaries — never throws, idempotent, batched per session, workspace-isolated.
  • Relationship queries (store/workspaces.ts): listClaims by workspace/session/entity(subject∨object)/relation/source/time, with resolveClaimHeads resolving derived-supersession AND user-sovereignty before the filters; relatedEntities = the depth-1 walk (entity → claims → counterparts, always returning the backing claim ids — feat(entity): local candidate search and typeahead person confirmation #181's typeahead substrate); threaded through moveSession. Routes: GET /claims·/claims/related, POST /claims/build·/claims/correct.
  • Honest degradation + sovereign corrections: no evidence ⇒ no claims; recordClaimCorrection mints an append-only source:'user' correction that outranks derived without deleting it (the Episode naming: derive and persist a session title from orientation output #211/fix(distill): episode-title sane defaults — judge-lane fallback + zero-model floor + no workspace-id leakage #232 titling-sovereignty pattern) — a REJECT drops the pair from the live view and survives re-derivation.

Out of scope (named — later slices)

Any UI/surface; model-enriched semantic claims (the judge-enrichment pass promoting co-occurrence into works-on/belongs-to/…); #181 entity search/typeahead (this ships the relatedEntities walk it will consume); cross-workspace / app-scoped memory grants (depends on #182 AppRuntime — no dead appId field added).

Determinism / gates

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant