Skip to content

Adaptive memory distillation

This document specifies Milestone 21. The engineering plan states the requirement; this document states the mechanism. It is subordinate to engineering-plan.md, extends rather than replaces the Milestone 9 and 16 memory designs, and is recorded by ADR-0077.

The owner authorized this workstream on 2026-08-31 after observing that the current memory former is dramatically too timid to be useful. The concrete failures are ordinary and consequential. The first was:

I am building a personal AI agent and I am wondering what to use for web search and web fetch.

The active provider-assisted policy forms no ongoing-project memory from that statement. A useful personal agent should form the direct observation User is building a personal AI agent. It may also form User likely has software-development experience. as an explicitly tentative hypothesis. The first is stated evidence; the second is a useful inference that must be allowed to fade if later conversation never supports it.

The second production regression was a three-turn training discussion. The user stated a two-to-three-times-weekly 5x5 routine, swimming, running, and biking on other days, lifelong regular training, current unstalled progress, a 5x5 restart after years of calisthenics, and roughly six years of gymnastic strength training. The old path retained only the malformed ownership claim "User has a trained regularly most of my life." Formation must treat facts embedded in questions as evidence, split coordinated activities into atomic claims, preserve frequency, history, current status, and expressed uncertainty, and never let one malformed parse consume a rich conversation.

Milestone 21 deliberately favors useful recall over timidity. A few provisional false positives are acceptable when their derivation is visible, their evidence clock is honest, corrections remain durable, and unsupported claims retire. Safety is not a generic reason to suppress memory. The hard exclusions are the small set named below; uncertainty is otherwise represented rather than rejected.

The design is informed by two research directions, with none of their training machinery imported. Nemori separates episodic integration from semantic distillation and uses prediction error to select what a memory system did not already anticipate. This milestone adopts that three-stage inference shape. Mem-α optimizes memory construction against downstream usefulness. This milestone adopts the product objective and comparative evaluation, but no reinforcement learning, learned policy, training loop, or new dependency.

Scope and outcome order

Milestone 21 delivers six coupled changes.

  1. Persist coherent integrated episodes over source events, with complete tenant, principal, session, and event provenance.
  2. Add nemori-assisted-v1, a provider-assisted extractor that performs three fixed batched calls: episode integration, causally blinded anticipation, and prediction-error distillation.
  3. Expand the candidate language to represent direct observations and useful hypotheses across ongoing projects, goals, roles, skills, interests, habits, constraints, recurring states, relationships, preferences, resources, and project facts.
  4. Raise automatic formation capacity while keeping it bounded: thirty-two proposals per consolidation and six per source event, ranked by directness, future usefulness, and subject diversity.
  5. Separate evidence freshness from model usage. Supporting events refresh last_evidence_at; citations refresh last_used_at and utility only.
  6. Replace the twenty-five-case extraction corpus with at least sixty cases and compare deterministic formation@7, provider formation@8, and Nemori formation@9 on the same labels before activation.

The outcome order is load-bearing:

useful direct recall
  > useful tentative recall
  > benign precision
  > narrow trust-boundary exclusions
  > latency and cost

This does not make the exclusions optional. It prevents them from becoming a catch-all justification for a system that remembers nothing.

Existing controls stay measurable

Milestone 21 does not mutate the meaning of the completed policies:

formation@7   deterministic-v2       frozen deterministic control
formation@8   provider-assisted-v2   frozen provider control
formation@9   nemori-assisted-v1     new candidate policy
formation@10  provider-assisted-v3   repaired provider control (ADR-0086)
retrieval@3   renders derivation and uses evidence age
lifecycle@2   evidence expiry is independent of use

formation@7 and formation@8 remain executable against their recorded fixtures and corpus. Their current candidate ceiling, claim vocabulary, prompts, and evidence artifacts are historical controls, not implementation helpers that may be silently widened. formation@9 composes new objects and may reuse their public ports; it does not alter their output for the same input.

Automatic selection activates formation@9 only on an exact evidence tuple. Startup compares the seven fields a running composition can know: extractor version, formation policy version, model policy, provider, model, policy profile, and compiled policy version. The corpus digest, scorer version, and build reference bind the artifact at bundle time instead: the bundle test refuses an artifact whose digest is not the checked-in corpus or whose scorer is not the current one, and the build reference names the commit the evaluated tree was committed as and must be an ancestor of the tree that bundles it. A release is a checkout, so startup also computes the digest of the corpus the running tree ships and activates no artifact, bundled or operator-supplied, whose digest differs; a tree without its corpora activates no provider policy and logs why. A bundled artifact's build reference is verified by ancestry at bundle time, because a running process cannot compare that reference against itself: the artifact is necessarily bundled in a later commit than the one it evaluated. An operator-supplied artifact never passes the bundle test, so the runtime holds it to the one commit it can name and activates it only when its build reference is the running release's commit; outside production, where no release identity exists, the file is accepted and the gap is logged. A change to the scorer withdraws every artifact published under the previous scorer; the formation@9 artifact of 2026-09-03 was withdrawn on 2026-09-04 for that reason (ADR-0087), and auto selects formation@10 for the production tuple until a re-evaluation under the current scorer passes. Until such evidence exists, auto keeps the newest evidenced provider-assisted policy, formation@10 where its artifact matches and otherwise formation@8; required refuses rather than claiming an unevaluated policy is active. A content-free selection audit records the decision and the policy it chose.

ADR-0093 separates maintenance model selection from chat. For routed agents, formation.model_policy in memory/profiles.yaml selects the memory model through the existing static router; its shipped value balanced explicitly resolves to GPT-5.6 Sol. Production chat defaults to astra, while flagship and fable select Claude Fable 5.1. Non-routed fake compositions keep their fake policy, and explicit evaluation modes use the requested evaluation model policy. Selection audits name both policies; activation and provider requests use the actual memory tuple. Off mode still resolves no extraction model. Sol remains temporary while Milestone 21 evaluates scorer semantics and a controlled Astra comparison. All exact-evidence checks above remain required.

ADR-0119 makes reasoning effort part of the evaluated tuple. formation.reasoning_effort sets the effort for requests using the configured default tuple; null keeps the provider default. Owner-selected evidenced alternatives use their tuple's evaluated effort, and frozen evaluation controls use the provider default. Startup is refused when the configured memory model does not accept the configured effort. Schema 8 of the formation@9 artifact records the effort the evaluated arm sent; a schema 7 artifact is provider-default evidence. Activation and the bundle test's uniqueness key compare effort as an eighth field, and the formation@8 and formation@10 artifacts, which record none, match only a null effort. agent eval memory-distillation --reasoning-effort sends the effort from the formation@9 arm alone, the frozen controls keeping the provider default, and --concurrency evaluates that many cases at once in separate compositions without changing their order. On the People default path the owner may move formation to any other tuple a bundled or bound operator formation@9 artifact evaluated exactly on this tree; the choice is read at each extraction, a withdrawn choice falls back to the configured tuple, and a consolidation formed on an alternative records its policy and effort after the extractor's name. Astra at medium effort failed the formation@9 gates on 2026-09-23, so Sol at the provider default remains the only evidenced memory tuple.

The integrated episode

Raw events remain the source of truth. An integrated episode is a derived, rebuildable narrative that gives formation a coherent unit larger than one sentence and smaller than a whole session.

IntegratedEpisode
  id                         UUID
  tenant_id                  str
  principal_id               str
  session_id                 UUID
  source_event_ids           ordered unique positive sequences
  source_started_at          aware datetime
  source_ended_at            aware datetime
  narrative                  bounded text; the bound holds the largest single
                             user message the API accepts plus one citation
                             prefix per event of a full segment
  subjects                   ordered unique bounded strings
  integration_policy_version "episode-integration@1"
  derivation_key             sha256(policy + owner + session + source ids)
  created_at                 aware datetime

The integration batch contains only trusted user events for the owning tenant, principal, and session, ordered by event sequence. The provider partitions it into one or more compact topical episodes; the flattened provenance is an ordered complete partition of the input. The provider may make each narrative coherent and resolve pronouns within its fragment; it may not add a fact with no supporting source text. Every sentence in every narrative cites at least one source event through the provider response. Local validation rejects an unknown sequence, an unowned sequence, an empty citation, a duplicate subject, overlapping or omitted provenance, or a narrative span not supported by its citations. Validation failure falls back to one deterministic episode whose narrative is the ordered source text joined under the same bounds.

IntegratedEpisodeStore has put, get, principal-scoped get_by_derivation, for_session, and delete_for_session. put is idempotent on derivation_key, and a pass that re-derives a key an earlier pass already stored under different content, as a provider re-pass does after the fallback, keeps the stored episode and records derivation_conflict rather than rewriting it or failing; both in-memory and PostgreSQL implementations run one contract. Principal and tenant erasure delete integrated episodes in the same transaction family as beliefs and formation audits. Because episodes are derived, rebuild never rewrites source events and deletion never leaves the narrative behind.

Three fixed batched calls

One formation@9 consolidation performs exactly three provider calls per planned segment when it has at least one eligible new user event, and most consolidations are one segment. No candidate, sentence, or category may create an additional call.

Call 1: episode integration

Input is the bounded ordered source-event batch. Output is one or more provenance-linked episode fragments that local code validates and persists. The call sees no recalled belief: its job is to say coherently what happened, not to decide whether it is novel.

Call 2: causally blinded anticipation

The cue is the source prefix before each new evidence unit, plus relevant live memories selected at the prior store position. The call sees the cue and those memories only, and only memories at or below internal sensitivity: a sensitive or restricted belief never leaves the platform as a cue, so it can neither be predicted from nor cited as redundancy. It does not see the current evidence span, the integrated narrative that includes that span, later events, assistant answers, or a gold memory label.

The output is a bounded list of predictions. Each attributed prediction names exactly one recalled memory and copies its statement; separate recalled claims require separate predictions. The response schema permits at most one memory identifier per prediction, so a compound assertion cannot combine independently stored facts that no individual memory asserts. A prediction without an attributable memory is ordinary model expectation, not evidence that the platform already knew the fact. Clause verification still checks the prediction against that live memory and the source clause. Before distillation, local validation rejects an attributed prediction that does not copy its named memory statement.

Call 3: prediction-error distillation

The final call sees the validated integrated episodes, the source events, and the blinded predictions. It emits closed semantic claims with exact source event and evidence-span citations plus an ordered source-coverage ledger. Local code owns canonical subject composition and uncertainty language as well as scope, portability, sensitivity floors, confidence, longevity, and expiry.

The final request splits user text at bounded sentence and first-person clause boundaries. A period ends a clause only before whitespace or the end of the text and never after a common abbreviation, so a file path, a version number, a decimal, or "e.g." stays inside one clause and can be cited. Every resulting coverage_unit must appear exactly once as formed, represented, transient, unsafe, or not_memory. A formed unit names the zero-based candidates it grounds, and every candidate is named by at least one formed unit. Missing units, unknown indexes, negative indexes, or an unreferenced candidate invalidate the stage structurally and select the deterministic high-recall fallback. After that structural validation every disposition is judged on its own. A candidate whose evidence is not in the unit that claims it is rejected and counted. A represented unit names an anticipation prediction for the same episode; local code verifies that the prediction asserts what the cited live memory asserts and that the memory is about the clause, and otherwise records the unit as represented_unverified. Ordinary model expectation, and a label alone, cannot justify omission. Local policy then validates each candidate independently: an invalid candidate is rejected and counted without discarding its valid siblings, and the stage outcome is partial_validation. This keeps one bad proposal from recreating the all-or-nothing recall failure while no invalid proposal reaches consolidation. The transient, unsafe, and not-memory labels are counted, and the comparative evaluation measures how often they land on clauses the gold labels as evidence.

Segments and limits

The output ceiling is 16,384 tokens, sized so a full ledger and its candidates fit. Every stage's response schema is submitted as strict structured output, so no object property may be optional: a defaulted field is rejected by the provider on every call and surfaces only as a fallback, which is how a defaulted polarity once zeroed a live evaluation. A batch is planned into segments before any call: a segment closes before the event that would carry it past ninety coverage units, two hundred and fifty-six events, or ninety-six kilobytes of source text, and an oversized single event forms its own segment. Each segment makes the three calls in order, so a consolidation makes exactly three calls per segment and never a candidate-level call. One anticipation request covers every episode of a segment, so its prefix is the user text before the segment's earliest episode and contains no episode's own evidence; each cue names the sequence before which its evidence begins. That text includes the session's already consolidated user events, not only the current batch: a continuing session's next consolidation is cued by what the user said earlier in it, which is what makes a restated fact predictable and therefore attributable. The prefix keeps the most recent text under a bound of twice the segment byte limit, sending an oversized newest event as its tail, so neither a long session nor a long consolidation's later segments resend everything; blinding is unaffected because nothing at or after the earliest episode is ever sent. There is no cost ceiling on the distiller; cost is recorded per stage and reported in evidence.

A directly stated claim is not suppressed merely because a general model could predict it. It may be skipped as redundant only when an existing live memory already represents it and the matching anticipation cites that memory. The audit records that memory identifier. A prediction not attributable to a live memory cannot make a direct observation disappear.

The candidate language

MemoryCandidate gains four closed fields:

claim_kind  ongoing_project | goal | role | skill | interest | habit |
            constraint | recurring_state | relationship | preference |
            resource | project_fact
derivation  direct | hypothesis
longevity   ongoing | durable | tentative
evidence_spans
            one exact non-empty substring per cited source event

The older fields remain. source_event_ids is still the authoritative provenance list; evidence_spans makes grounding locally decidable rather than trusting a normalized provider claim. Every exact span must occur in the owned user event it names. Assistant, tool, model, foreign-principal, and foreign-tenant events are never direct sources.

The vocabulary intentionally covers activities and partial identity cues. A candidate is not rejected because it is ongoing rather than timeless, because it is a hypothesis rather than verbatim, because the wording is ambiguous, or because its subject may be sensitive. The derivation, longevity, confidence, sensitivity, and expiry fields carry those distinctions.

Local canonical rendering owns statements. Representative forms are:

ongoing_project/direct     User is building a personal AI agent.
skill/hypothesis           User likely has software-development experience.
goal/direct                User wants to choose web-search and fetch tools.
habit/direct               User regularly runs in the mornings.
constraint/direct          User cannot take meetings on Fridays.

Hypothesis renderers use uncertainty language (likely, may, or tentatively). A provider cannot turn hypothesis into an unqualified fact by choosing its own sentence.

A candidate also carries polarity, assert or retract. A correction ("I don't drive my BMW anymore", "I gave up swimming", "I no longer take meetings on Fridays") may yield only a retraction: the provider names the subject of the belief it ends with polarity retract and states the negated claim, the deterministic fallback recognizes the same forms itself and keys them the way the matching assertion would, and local validation rejects an assertion that cites a correction clause, a retraction that cites none, and a retraction whose statement is still affirmative. At commit, a retraction supersedes every live affirmative belief about the user that has the same main verb and whose lemmatized content contains what it negates, under whatever key that belief was filed, bounded to four: "no longer runs outdoors" ends "is running outdoors every day" and "goes running outdoors most mornings" but not "tracks runs outdoors in a journal". When nothing live matches, it is counted as skipped_unmatched_retraction and forms nothing. A correction can therefore update memory but never create it.

Capacity and ranking

formation@9 accepts at most thirty-two automatic proposals in one consolidation and at most six proposals whose provenance includes the same source event. The limits apply before commits and after local validation.

The deterministic ordering is:

  1. direct before hypothesis;
  2. higher future-usefulness score;
  3. a candidate introducing a claim kind or subject not yet represented;
  4. source event sequence;
  5. the order the proposals were made, which follows the order the user stated them.

Future usefulness is a local closed rubric over claim kind and longevity, not a fourth model call. Ongoing projects, goals, stable constraints, roles, relationships, preferences, and reusable skills outrank incidental resources or one-off project facts. The selector makes a first pass taking one candidate per subject, then fills remaining capacity in rank order. Proposals rejected by the global limit or per-source limit remain in the formation audit with distinct reason codes; no truncation is silent.

Confidence, evidence, and forgetting

MemoryRecord gains:

claim_kind                 the closed category
derivation                 direct | hypothesis
longevity                  ongoing | durable | tentative
last_evidence_at           latest supporting world event
last_used_at               latest faithful model citation, nullable
evidence_count             distinct supporting source events, positive
lifecycle_policy_version   lifecycle@2

corroboration_count remains the count of distinct supporting sessions and is not incremented twice by replay. last_reinforced_at remains on old records for compatibility and historical display, but lifecycle@2 neither ranks nor expires a belief from it. The migration backfills last_evidence_at from valid_from, evidence_count from the existing source-event list, last_used_at null, old candidates as direct, and a conservative claim-kind and longevity mapping from belief type. Backfilled rows retain their original formation version and receive lifecycle@2 only when the new policy first updates them; the migration itself records lifecycle@1-backfill.

Initial automatic values are policy, not knobs:

Derivation / longevity Confidence Expiry without later evidence
direct durable 0.65 type-aware decay horizon
direct ongoing 0.65 90 days
hypothesis tentative 0.35 30 days
explicit remember 0.95 no automatic expiry

Later supporting user evidence refreshes last_evidence_at, increments evidence_count, and may increment corroboration_count. A direct statement supporting a hypothesis promotes it to direct; repeated independent cues may raise a hypothesis within the automatic confidence ceiling without silently changing its derivation. A user edit, correction, retraction, or deletion is authoritative and remains durable across replay.

A faithful citation updates last_used_at and utility. It does not update last_evidence_at, last_reinforced_at, evidence_count, corroboration, confidence, or expiry. Returned-but-uncited utility feedback remains, likewise without touching evidence. A memory cannot keep itself alive by being recalled.

The bounded maintenance sweep retires tentative hypotheses thirty days after last_evidence_at and ongoing observations ninety days after it. Durable direct beliefs use the existing type-aware horizon and confidence steps, now measured from last_evidence_at. Explicit remembered beliefs remain outside automatic decay. Retirement closes validity and emits memory.retired with a content-free reason code.

Retrieval and uncertainty

Retrieval policy becomes retrieval@3. Ranking's age term uses last_evidence_at; usage contributes only through utility. Rendering exposes derivation and uncertainty without adding raw scores:

[m:8f21a0c3] User is building a personal AI agent.
  (direct, ongoing, medium confidence)
[m:9d02b117] User likely has software-development experience.
  (hypothesis, tentative, low confidence)

RecalledBelief, recall traces, the user-safe trace view, CLI inspection, and the read API projection carry claim_kind, derivation, and longevity. last_evidence_at and last_used_at are inspectable on the governed human surfaces. None is policy instruction; recalled text remains memory-trust data.

Deliberately narrow trust exclusions

Formation rejects only the following trust-boundary failures before ranking:

  • a cited event or span does not exist, is not owned by the tenant and principal, or is neither an owner assertion nor a recognized communication source;
  • assistant, model, arbitrary tool, or externally untrusted text is presented as a user observation;
  • the authoritative source span is a credential, secret, or PII beyond explicit policy;
  • untrusted instruction text is being promoted as an instruction rather than remembered as the fact that the user encountered it;
  • a write or read would cross tenant or principal scope;
  • a durable rejection, deletion, correction, or newer higher-authority belief forbids the candidate.

A retryable provider failure does not lose evidence. formation@9 completes the consolidation with its audited fallback and advances the watermark, then schedules a bounded provider re-pass over the same source range with the formation@8 attempt limit and backoff; the re-pass re-reads that range, commits what the provider adds, resolves what the fallback already formed as the same source, and audits exhaustion after the last attempt.

Sensitivity permitted by explicit policy is not itself a reason to reject a useful memory. It is classified and governed by the existing surface ceilings. Inference is not itself a reason to reject; it is stored as a hypothesis. Ambiguity is not itself a reason to reject; it lowers confidence or longevity. Ordinary professional, health, relationship, location, and activity context may form autonomously when it has valid user provenance and explicit policy permits it.

Formation decision telemetry

Every proposed claim ends in exactly one content-free reason category:

committed_direct        committed_hypothesis      reinforced
promoted                redundant_attributed     superseded
conflicted              rejected_provenance      rejected_credential
rejected_injection      rejected_correction      rejected_portability
rejected_validation     displaced_per_source     displaced_global
provider_invalid

ConsolidationRun stores the category counts plus episode count, provider call count, fallback stages, direct proposed/committed, hypothesis proposed/committed, prediction-attributed redundancies, coverage dispositions including unverified representations, segment count, rejected provider candidates, and per-stage input, cached-input, cache-write, output, and reasoning tokens, cost, latency, and outcome. The sum of terminal categories equals proposals plus provider-invalid claims. Events and metrics carry counts, versions, and normalized failure classes only—never source text, episode narrative, evidence spans, or memory statements.

Evaluation and activation evidence

evals/capability/memory-formation.v3.json contains at least sixty authored cases. At least seventy percent are positive. Every positive case is labeled must_form or reasonable_to_form; the narrow negative set is must_not_form. Each expected candidate declares claim kind, derivation, longevity, canonical subject and statement alternatives, and exact evidence text; a subject is a specific conflict key, never the user. A direct expectation may also declare up to three compatible kinds, the kinds a correct belief could reasonably carry instead: a stated training history is a skill to the label author and a project fact to the model, and both are the same memory. Compatible kinds are assigned by the shape of the claim, never by what a model happened to produce, from this table; a hypothesis declares none.

Claim shape Primary kind Compatible kinds
stated experience or training history skill (habit when labelled as a routine) project_fact (plus skill)
stated occupation skill role, project_fact
activity program with a schedule habit project_fact, ongoing_project
routine or chore habit project_fact, recurring_state
recurring condition recurring_state project_fact (habit when it is also a routine)
something being built or planned ongoing_project project_fact, goal
a wish or aim goal ongoing_project (project_fact for a team's aim)
a wish about how the agent should answer preference goal, constraint
a position held role project_fact
an interest interest preference
a preference preference constraint
a constraint constraint preference, project_fact
a family member relationship none
a fact about a family member's situation project_fact or relationship the other
a recurring activity of a family member relationship recurring_state, project_fact
a resource or its location resource project_fact
a technical fact about the user's project project_fact resource

Coverage includes every claim kind, direct and hypothesis formation, compound utterances, corroboration and promotion, correction, retirement, and self-citation.

The corpus also declares seed pools of realistic prior beliefs. A positive case may name a pool, and the evaluator writes those beliefs through the governed service, in a separate session, before the case consolidates, so the belief view, anticipation, and attributed redundancy behave as they do on a populated production store. At least one positive multi-event case and the rich production conversation run against a pool of at least twenty-five beliefs.

That corpus is the development set: it may be tuned, and its alternatives have been edited after observing model output. A tuning run scores it alone: --development-only reports the development gates without reading the holdout or publishing, so prompt and policy work never spends the holdout. Independent evidence comes from the frozen holdout, evals/capability/memory-formation.v3-holdout.json: at least thirty cases authored before their first run, every claim kind, both derivations, must-not-form cases, and at least three seeded cases that restate a seed across a segment boundary. Its digest is recorded beside it in memory-formation.v3-holdout.sha256; the loader refuses a holdout whose content no longer matches the record, so any edit is a deliberate re-freeze that shows in review and invalidates every artifact bound to the old digest. The evaluator scores every run on both sets, the artifact carries both digests and the holdout's own recall, precision, lift, disposition, and represented counts, and activation binds the holdout digest exactly as it binds the corpus digest.

Scoring is distillation-scorer@7. A belief matches a gold claim when its derivation agrees, its claim kind is the gold kind with the gold longevity or a compatible kind with the longevity local policy assigns that kind, its subject names the gold conflict key (a lemma of the subject names a lemma of the gold key or statement, or an inflection or compound of one, so "weightlifting" names "lifting weights"; the user bucket never does), and its statement states the claim: equal after normalization, or, with the same polarity, the same absence conditions, the same counts, the same large numbers when both carry one, the same object, compared as a lemma, after every directional marker both share, and the terms they share in the same order, either carrying every content lemma of the gold however much it adds, or sharing three quarters of the combined lemmas and adding at most one. Inflections agree and bare qualifiers such as "currently" are not content, so a correct claim stated with more detail is the claim; the runtime combiner keeps the stricter equivalence because merging is irreversible. Elaborations, negations, added or removed absence conditions, different counts or distances, reversed comparisons or origins, swapped arguments, and sibling activities never match. Negation is scoped to the clause: a negation inside a subordinate circumstance qualifies a claim rather than denying it, and a fronted circumstance ends at its comma, or without one where the main clause's subject begins, so it cannot hide the main clause's negation. The same compatibility floor and term order decide whether a live memory represents a clause. Two candidates in one batch merge only when they are one claim: compatible, with shared names in one order, and either nesting or sharing most of the smaller statement's content; of two wordings of one claim the richer survives and a tie goes to the provider's over the fallback's, whose kind is a default and whose key is composed from source words; a second claim under the same subject and kind is filed under a key extended with its distinguishing words, or with its names in order when the two claims share every word, or with an ordinal when nothing else separates them, rather than dropped. The frozen formation@7 and formation@8 controls cannot express the closed fields, so they are scored on statement equivalence alone and the lift threshold compares formation@9 strict recall against that lenient control recall. The scorer version is recorded in every result and artifact, and an artifact from an older scorer cannot activate.

The core scenarios include:

  1. the personal-agent statement forms the direct ongoing-project memory and the tentative software-development hypothesis;
  2. a broad compound utterance forms multiple subjects without one category consuming the whole budget;
  3. a misleading professional cue may form a hypothesis but never a direct occupation claim;
  4. later support refreshes evidence and promotes a hypothesis;
  5. an unsupported hypothesis retires after thirty days and an unsupported ongoing state after ninety;
  6. repeated citations do not extend either lifetime.
  7. the production three-turn training conversation forms all eleven supported memories: the improvement goal, age-aware recommendation preference, routine, three activities, progress, and four training-history claims.

The live-model command below evaluates all three policies over the same cases (with --development-only, the development corpus alone, publishing nothing) and publishes a never-overwritten MemoryDistillationEvidence only when:

RUN_LIVE_MODEL_TESTS=1 agent eval memory-distillation \
  --model-policy balanced \
  --policy-profile default \
  --build-ref FULL_COMMIT_SHA \
  --repeats 3 \
  --output PATH_THAT_DOES_NOT_EXIST.json

The build reference is the forty-character commit the evaluated tree was committed as; the command resolves it from CI or git rev-parse HEAD when the option is omitted, and the evidence schema refuses any other form. The run also refuses a reference that is not the checked-out HEAD and a worktree with uncommitted tracked changes, so an artifact never describes files the named commit does not contain.

Without the explicit live-model flag it reports a skip and makes no provider call or artifact. A failed run returns its comparative per-policy metrics but does not create the output path.

Publication requires:

  • invalid provenance, assistant-as-user, promoted injection, credential, cross-principal, and cross-tenant failures are all zero;
  • direct must_form recall is at least 95 percent;
  • hypothesis must_form recall is at least 80 percent;
  • precision against exhaustive, semantic-paraphrase-aware gold claims over benign positive and negative cases is at least 90 percent;
  • useful recall is at least fifteen percentage points above formation@8;
  • every claim kind has a positive case, counted by the kind the provider formed rather than the kind the label names, and the personal-agent core passes;
  • measurable user correction or rejection is below ten per one hundred automatically formed memories;
  • at least three quarters of the clauses the gold labels as evidence are formed or verifiably represented rather than labelled transient, unsafe, or not memory;
  • at least one positive case ran against a populated store, and at least one seeded case that restates a seeded belief across a segment boundary had that clause verifiably represented by an anticipation attributed to the seed; the gate is the aggregate, because one case is one anticipation call's chance;
  • the frozen holdout passes the same recall, lift, disposition, boundary, call-count, and represented thresholds, with none of the corpus's named-scenario rules, and a benign-precision floor of 0.75 rather than 0.90: its labels cannot anticipate every true belief, and the product is a personal agent scored recall-first (ADR-0087);
  • the gates are decided over every repeat of the evaluation, pooled, when --repeats is more than one: recall, precision, lift, disposition, correction rate, and claim-kind coverage aggregate the runs, the personal-agent and rich cores need each expected memory in a majority of runs, the represented gate needs a majority of runs, boundary failures and call counts fail on any run, and the artifact records the repeat count and each run's own numbers, because one run of this policy has been measured to move by up to a tenth on a gate against the next (ADR-0087);
  • every eligible consolidation made exactly three calls per planned segment, and the artifact records the measured call and consolidation totals;
  • all lifecycle timing, promotion, and self-citation checks pass, and the measured provider cost is recorded and below a sanity ceiling of one thousand US dollars;
  • the exact version and provider tuple matches the artifact.

The thresholds intentionally tolerate some provisional false positives. The wrong optimization is near-perfect precision achieved by suppressing useful memory.

There is no shadow, canary, or manual opt-in phase after passing evidence is bundled. auto selects formation@9 immediately for the exact production tuple, then the repaired formation@10 below, then the frozen formation@8 control, whichever artifact matches first. formation@8 remains an honest control in the comparison, not a conservative rollout stage. The operator pin AGENT_MEMORY_FORMATION_POLICY_PIN holds the selection at formation@8, formation@9, or formation@10 without deleting an artifact; a pin narrows the search to exactly that policy, a pin to an unevidenced policy falls back to deterministic formation with a content-free pinned_policy_unevidenced audit, required judges the pinned policy's own artifact and still refuses, and every selection audit records the formation policy it chose.

Every bundled artifact is bound to the compiled policy version of the tree that ships it. tests/unit/test_release_evidence_bundle.py compares each artifact against the shipped policy documents and fails, naming the file and both versions, when they differ. A change to the policy documents therefore regenerates the evidence on that tree or withdraws the artifact and records the interregnum in project state; it cannot merge and silently fall back to deterministic formation in production, which is what happened once on 2026-09-03 (ADR-0086).

The repaired provider-assisted control (formation@10)

formation@8 is frozen, and its fixed budget is why production formed almost nothing before formation@9: a USD 0.05 ceiling, a one-byte-per-token preflight, and a compact view of the fifty most recent beliefs shrink the affordable output to a few hundred tokens once a store holds a dozen beliefs and skip the call past about twenty. The production audit of 2026-09-03 recorded exactly that as truncated streams and integer_below_min_value refusals. formation@10, implemented by provider-assisted-v3 in the same extractor and the same single schema-constrained call, repairs only that:

  • the input ceiling is the model's context window less the output reserve, still estimated at one byte per token;
  • the output ceiling is 16,384 tokens, the distillation ceiling, and the timeout is 120 seconds;
  • cost is recorded in the audit and bounded only by a USD 10 sanity ceiling; it never shrinks or skips the call;
  • the compact belief view is the fifty beliefs sharing the most content with the batch, chosen from the five hundred most recent, restricted to public and internal sensitivity, with store order breaking ties, so an old belief the conversation returns to is present and a sensitive one never leaves.

Rendering, grounding, the claim vocabulary, merging with the deterministic fallback, and every service gate are unchanged. Its activation evidence is the same schema formation@8 used, produced by agent eval memory-formation --formation-policy formation@10 against the 25-case corpus with every case run on a thirty-belief seeded store whose subjects never touch an expectation, and it records the seeded case count. formation@10 is not a fourth comparative arm; the frozen formation@8 remains the control the formation@9 lift is measured against.

Persistence and migration

One structural revision adds the integrated-episode table, the new belief and formation-audit columns, and the bounded indexes on evidence expiry and episode ownership. A separate data revision backfills beliefs in bounded primary-key pages. A following additive revision adds the content-free per-stage metrics document to consolidation audits. All upgrades and downgrades are explicit; downgrade of the data revision is lossy only for derived fields and is declared as such. EXPECTED_REVISION advances with the structural head.

The in-memory store and PostgreSQL repositories translate row models by hand, return domain values only, and run the shared contracts. No provider call occurs inside a database transaction. The three calls complete and validate first; episodes, beliefs, the consolidation audit, and the watermark then commit in short units of work with idempotent derivation keys.

Build sequence

  1. This design, ADR-0077, the project-state authorization, the milestone map, readiness verdict, registry entries, and all red gates: twenty-four at authorization, thirty-one after ADR-0086 and ADR-0087. M21.
  2. Candidate, episode, evidence-clock, telemetry, and evidence-artifact domain values plus shared port contracts. M21.
  3. The in-memory episode store and formation@9 deterministic fallback, including the personal-agent direct observation and hypothesis. M21.
  4. The three-call provider pipeline with causal blinding, local grounding, fixed call count, normalized failure audits, and deterministic fallback. M21.
  5. Formation capacity, ranking, attributed redundancy, reinforcement, promotion, and category accounting. M21.
  6. lifecycle@2, retrieval@3, evidence-based expiry, usage-only clocks, and uncertainty rendering on every governed read surface. M21.
  7. PostgreSQL schema, repository, erasure, migrations, and bounded backfill. M21.
  8. Corpus v3, the three-policy offline comparison, activation selection, and a live evidence run on the intended production tuple. M21.
  9. Focused, contract, property, PostgreSQL, complete non-live, documentation, hosted CI, and final review lanes on one head. M21.

Hard gates

  1. Completed policy controls are frozen. The recorded formation@7 and formation@8 fixtures produce byte-identical normalized outputs while the new extractor identifies itself as nemori-assisted-v1 at formation@9. Registered as gate.memory.distill_versions_frozen, structural. M21.
  2. Integrated episodes are coherent and grounded. A multi-turn session produces ordered, provenance-complete episode narratives, and an unsupported sentence or foreign citation is rejected before persistence. Registered as gate.memory.episode_integration, case. M21.
  3. Both episode stores obey one contract. Idempotent put, owner-scoped get and paging, session deletion, and principal erasure behave identically in memory and PostgreSQL. Registered as gate.memory.episode_repository_parity, structural. M21.
  4. Anticipation is causally blinded. Over generated event prefixes, the anticipation request contains only the cue and memories available before the evidence event; it contains no current or future evidence, integrated answer, assistant response, or gold label. Registered as gate.memory.anticipation_blinded, property. M21.
  5. One consolidation makes exactly three batched provider calls. Any number of events and candidates still produces integration, anticipation, and distillation once each, with no candidate-level call. Registered as gate.memory.prediction_error_calls, case. M21.
  6. Every provider stage has an audited deterministic fallback. A transient, permanent, protocol, or structural validation failure records only normalized metadata and completes with locally derived episodes and candidates. After structural validation, an invalid candidate is rejected and counted without discarding valid siblings. A retryable failure additionally schedules a bounded provider re-pass over the consumed range, so an outage delays the provider's contribution without discarding it. Registered as gate.memory.distill_fallback, case. M21.
  7. Rich direct evidence forms at high recall. The personal-agent core statement forms User is building a personal AI agent. as a direct ongoing project with exact user provenance, and the production training conversation forms its eleven atomic supported memories. Registered as gate.memory.direct_high_recall, case. M21.
  8. Useful hypotheses form as hypotheses. The same core statement may form User likely has software-development experience. as tentative and never as a direct occupation fact. Registered as gate.memory.hypothesis_high_recall, case. M21.
  9. Compound formation is bounded and diverse. A broad utterance can commit multiple categories and subjects, never more than six proposals per source event or thirty-two per consolidation; direct candidates precede hypotheses and every displacement is counted. Registered as gate.memory.compound_recall, case. M21.
  10. The candidate language is closed and complete. Every claim kind, derivation, longevity, and evidence-span combination validates or fails at collection, with unknown values refused. Registered as gate.memory.candidate_schema, structural. M21.
  11. Predictability suppresses only attributable redundancy. A direct claim is skipped only when a live existing memory represents it and the matching anticipation cites that memory; general model expectation alone suppresses nothing. Registered as gate.memory.predictability_attributed, case. M21.
  12. Every automatic claim is source-grounded. Over generated ownership and event-kind combinations, every evidence span occurs exactly in an admitted source. Principal and authenticated paired-surface messages are owner assertions. First-party Gmail read results and device-ingested SMS may form only locally rendered, channel-attributed, tentative, sensitive hypotheses; they cannot retract or supersede owner memory. Assistant, model, arbitrary or lookalike tool, web, malformed, unpaired, foreign-principal, and foreign- tenant content commits nothing. Registered as gate.memory.source_grounding, property. M21.
  13. Decision telemetry accounts for every proposal. Direct, hypothesis, commit, redundancy, rejection, conflict, promotion, and displacement reason counts reconcile exactly without statements or evidence text in telemetry. Registered as gate.memory.formation_reason_telemetry, case. M21.
  14. Only later evidence refreshes the evidence clock. A supporting user event advances last_evidence_at and the evidence counters exactly once; replay, consolidation time, and citation do not. Registered as gate.memory.evidence_clock, case. M21.
  15. Usage has its own clock. A faithful citation changes last_used_at and utility only, an uncited return changes utility only, and repeating run completion is idempotent. Registered as gate.memory.usage_clock, case. M21.
  16. Unsupported hypotheses retire after thirty days. A tentative hypothesis with no later evidence is live before its boundary and retired at it, regardless of repeated retrieval or citation. Registered as gate.memory.hypothesis_retirement, case. M21.
  17. Unsupported ongoing observations retire after ninety days. An ongoing direct observation follows the same exact boundary and self-use cannot extend it. Registered as gate.memory.ongoing_retirement, case. M21.
  18. Later evidence promotes rather than duplicates. A direct supporting statement for a hypothesis updates the existing belief to direct, refreshes evidence, preserves all provenance, and creates no second live subject/type belief. Registered as gate.memory.evidence_promotion, case. M21.
  19. Recall renders uncertainty faithfully. Direct and hypothesis beliefs expose their derivation and longevity in rendered context, traces, CLI, and API views without exposing raw model scores. Registered as gate.memory.uncertainty_rendered, case. M21.
  20. Corrections remain durable through the new pipeline. A rejection, edit, retraction, or deletion cannot be recreated by episode integration, distillation, retry, or replay, and a stated correction retracts the belief it names through the provider and the fallback alike without creating one. Registered as gate.memory.correction_durable_v3, case. M21.
  21. The schema migration and backfill preserve history. Clean and stepwise upgrades create episodes and new fields, bounded backfill gives every old belief valid conservative values without changing its statement, provenance, authority, or formation version, and erasure removes the new rows. Registered as gate.memory.schema_backfill, structural. M21.
  22. Corpus v3 has the declared coverage. It contains at least sixty cases, at least seventy percent positive, every claim kind and label class, all seven core scenarios including the rich production regression, exact evidence text, and no duplicate identifier. Registered as gate.memory.formation_corpus_v3, structural. M21.
  23. Comparative evidence proves marked useful-recall lift. One offline run compares formation@7, formation@8, and formation@9; evidence publishes only at the direct, hypothesis, precision, useful-lift, category, lifecycle, correction-rate, call-count, cost, and zero-boundary-failure thresholds, and never overwrites an existing artifact. Registered as gate.memory.comparative_evidence, case. M21.
  24. Activation is exact and evidence-bound. Over generated tuple differences, formation@9 activates only for the exact artifact tuple; auto otherwise keeps the evidenced older policy and required refuses. Registered as gate.memory.distill_activation_bound, property. M21.
  25. The comparative scorer cannot be fooled. A belief that elaborates beyond, negates, recounts, reverses the direction of, or names a sibling activity of a gold claim never scores as a match, and a generic user subject never matches a specific conflict key. Registered as gate.memory.scorer_symmetric, case. M21.
  26. Comparative evidence runs against a populated store. The corpus declares a seed pool of at least twenty-five prior beliefs, the rich production conversation and another multi-event case run against it, and the evaluator writes the seeds through the governed service before consolidating. Registered as gate.memory.formation_corpus_seeded, structural. M21.
  27. The deterministic fallback never fabricates. Turns that share surface phrasing with the production training conversation but state no durable training fact form nothing except the stated wish for age-aware recommendations, and a long or unterminated turn neither crashes nor stalls consolidation. Registered as gate.memory.fallback_never_fabricates, case. M21.
  28. A represented clause is verified against the memory it cites. A coverage unit marked represented counts only when the attributed live memory asserts the same claim and is about that clause with the same polarity, count, number, and direction; otherwise it is recorded as unverified and the stage completes partially rather than trusting the label, so a correction can never be labelled away as already known. Registered as gate.memory.coverage_dispositions_verified, case. M21.
  29. Long batches segment into bounded three-call rounds. A batch beyond one ledger's clause bound runs exactly three calls per segment, persists one episode set per segment, and records per-segment stage metrics; a segment's ledger and candidates fit the output ceiling. Registered as gate.memory.distill_segmentation, case. M21.
  30. The repaired provider-assisted policy never starves. On a populated store where the frozen formation@8 control cannot afford one output token and skips its call, formation@10 makes its single call with the full output ceiling, ranks its compact belief view by relevance to the batch rather than recency, and sends only public or internal beliefs to the provider. Registered as gate.memory.provider_budget_repaired, case. M21.
  31. Automatic selection prefers the newest evidenced policy and honors a pin. With every artifact present composition activates formation@9; without it formation@10 outranks formation@8; a pin holds any one of the three; and a pin to an unevidenced policy falls back deterministically with a content-free audit rather than activating another policy. Registered as gate.memory.provider_policy_precedence, case. M21.

Tracked metrics

Track direct and hypothesis proposal, commit, reinforcement, promotion, correction, rejection, and retirement counts; recall and precision by claim kind and derivation; per-source and global displacement; prediction-attributed redundancy; episode count and size; provider calls, fallbacks, latency, tokens, and cost per stage; evidence age and usage age separately; correction and rejection per hundred automatic memories; and the exact corpus and policy versions. Metrics never contain source text, episode narrative, evidence spans, or belief statements.

Exclusions

Milestone 21 adds no reinforcement learning, model fine-tuning, vector store, embedding dependency, temporal entity graph, persona editor, global cross- principal consolidation, session-history retrieval arm, artifact retrieval arm, or external memory service. It does not add a new public write API. Those remain separate roadmap choices. The milestone is a higher-recall formation and honest-forgetting change over the existing governed memory system.

Milestone 26 semantic email policy

The approved email experience under ADR-0092 adds a separately versioned and evaluated correspondence extractor. Its contextual cross-project recall, exact semantic source grounding and historical lifecycle are an explicit extension, not an in-place change to formation@9, formation@10 or communication-attribution-v1. Existing policy evidence, precedence, authority and gates remain binding; new-policy activation waits for its own quality and source-lifecycle evidence. Old LOCAL excerpt memories retain that portability.