guide · memory promotion
Memory promotion — episodic notes into semantic knowledge
Agent sessions produce raw notes worth keeping for a while and a few facts worth keeping
forever. Taguru already has the destination (the association graph) and the vehicle
(taguru extract, POST /import); this page fixes the
conventions and the procedure that make the lifecycle work with no new server
machinery: scratch is an ordinary context, promotion is ordinary writes, and
forgetting is always an explicit operation (issue #423; ADR 0011, ADR 0012).
Scratch conventions
- Scratch is an ordinary
context—scratch-{agent}, orscratch-{agent}-{topic}when sessions must not mix. There is no TTL and none is planned: nothing in this store expires silently. - Source ids name the session, globally uniquely:
session:{agent}:{id}(the id a UUID or an equally unique token) for the running note, with/{doc}appended when one session produces several documents. Uniqueness is load-bearing: import is retract-then-apply per source id, so two agents sharing a baresession:{id}in one permanentcontextwould silently replace each other's assertions. The id survives promotion, so a promoted fact's citation still names the session that produced it — provenance rides the existing source/citation machinery. - Always declare
datewhen storing passages.date ?? stored_atis the assertion time every windowed graph read (since/until, ADR 0011) and the staleness audit run on. An associations-only source stores no metadata and is invisible to every window — store at least the session note as a passage. - Tag scratch sources with the session's topics; passage search's
tagsfilter is how a later session finds its own trail.
The promotion procedure
- Review the scratch
context:recall/query, ortaguru communities --context IDfor a themed overview once the scratch has grown (--into IDaims the artifact at a chosen context id — by default its id derives from the scratch's own, namedNAME::communities;--group NAMEsummarizes a wholegroupinstead;--dry-run/--jsonpreview and machine output). - Graph path — one call when the structure is already right (ADR 0018):
when the keepers are the scratch's own structured associations (written by the
session itself, nothing left to extract), the
promoteMCP tool (POST /contexts/{scratch id}/promote, body{into, sources, audit?}—intois the destination's id (theidcolumn ofGET /contexts), not its name —?dry_run=trueto preview) bundles steps 4–5: each named source moves whole — passage,date, tags, and only its own share of every edge's weight — with no LLM anywhere in the path. Source ids survive, so promoted citations still name the session; per-source retract-then-apply makes re-promotion idempotent; the destination must already exist and its own schema judges the incoming sources;sourcesshares the API's list ceiling (1,000 ids per call —over_limitpast it; split a bigger promotion); the landing-zone audit rides back in the response (audit: falseopts out), and a dry run previews the sources to transfer only, with nothing written and no audit. What stays yours is exactly the judgment: which sources (step 1's review), the audit's candidates (step 5's rubric), and retirement (step 6). Steps 3–4 below are the text path, needed only when the keepers exist as prose that still wants extraction. - Extract the keepers with
taguru extractover the session passages (or hand-write the source file), targeting the permanentcontext(--contexttakes its id) — keeping thesession:{agent}:{id}source ids and thedates:--source-id,--date, and--tagbake all three conventions into the emitted source file directly (ADR 0017), so no hand-editing of the generated file remains. Resolve spellings against the permanentcontextrather than forking its vocabulary: export it (taguru export --out DIR) and hand the export to--vocabulary(ADR 0015), which steers the extraction toward thecontext's existing spellings and admits them through validation — the manualresolve/resolve_labelpass remains for hand-written source files.--coverage(ADR 0016) reports what the extraction left behind, sentence by sentence — the mechanical floor under the review this step owes. - Import via
POST /import/taguru import— retract-then-apply per source makes re-promoting the same session idempotent. - Audit the landing zone:
taguru consolidation --context ID(or theaudit_consolidationMCP tool) —--checks LISTnarrows the sections (comma-separatedmerge,contradiction,staleness; default all three),--into IDaims the judgmentcontextat a chosen id (default: derived from the auditedcontext's id, namedNAME::consolidation),--dry-runpreviews. Promotion is exactly when merge twins and contradictions appear; judgments are proposals keyed by evidence fingerprint (re-runs over an unchanged graph cost zero LLM calls), and applying an accepted one is always an ordinary write — an alias, a retraction, a negative-weight assertion, or a re-import. - Retire the promoted scratch:
retract_sourcethe promoted session sources (or delete the scratchcontextonce everything promoted). Unpromoted scratch stays until someone decides otherwise — that is the posture, not a gap.
What not to do
- Don't promote into a fresh spelling universe — the resolve-first rule in step 3 (and, on the graph path, the landing-zone audit's merge candidates) is what keeps one referent one spelling.
- Don't invent an end date for a superseded fact: assert the new fact with its own
date; as-of queries (
until) and the audit's dated rows sort the regimes out (ADR 0011 §6). - Don't auto-expire scratch, and don't skip the audit on a large promotion — an unchanged graph re-audits for free.
An agent-facing version of this runbook ships as a skill template in
examples/skills/memory-promotion/.
Taguru