Use before the first memory verb — read or write — whenever the orchestrator is about to touch memory as this turn's subject: deciding what persists, searching, curating, or triaging what a session injected at start.
Pro scans all 3 files and shows the line behind each finding
Scanned 10/7/2026
npx -y skills add metraton/gaia --skill memory --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Memory?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/metraton-memory)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: memory
description: Use before the first memory verb — read or write — whenever the orchestrator is about to touch memory as this turn's subject: deciding what persists, searching, curating, or triaging what a session injected at start.
---
# Memory
Memory is the curation technique that turns selected experience into continuity:
durable knowledge kept small, live work kept visible, and raw operational
history left on the automatic event floors where it belongs.
## The three floors
| Floor | Purpose | Lifecycle |
|---|---|---|
| Events | Commands, dispatches, session events, and other operational facts | Automatic and short-lived |
| Episodes | Searchable agent-turn outcomes and anomalies | Automatic, retained for diagnosis |
| Curated memory | User-governed knowledge and work that must affect future decisions | Deliberate and long-lived |
Events and episodes are evidence, not durable truth.
## Every row answers three questions
- **Whose it is.** The user (true of him in any project, so it has no
workspace), a project (true of that codebase or initiative), or Gaia itself (a
symptom of, or a decision about, the host). A row is written where its owner's
readers look. A workspace is a container, not an owner: a row that names only
a container reaches no reader who is looking for it.
- **Which role it serves.** Durable knowledge (facts, accepted decisions,
useful dead ends, preferences, milestones), one live thread that must
reappear, or a log kept for audit and never reinjected.
- **What kind of claim it makes.** The first word of its description says so,
so a listing reads as a set of claims rather than titles, and a user's fact
is told from a user's preference without opening the body.
The enums, sentinels, thresholds and claim vocabulary are the CLI's;
`reference.md` anchors each to the symbol that reads it.
For Gaia itself, choose from how the fact was produced, not from the current
directory: Gaia observed failing or rubbing in use is `initiative=gaia_system`,
host-scoped by `gaia/store/writer.py::apply_host_scope` (a project anchor is
refused); a decision to build or change Gaia is project-scoped
`initiative=gaia`.
## Other home first
Before saving, ask: **does this already have a canonical home?** Work in flight
belongs in a brief, plan, or task; domain state in project context or the owning
system; raw execution detail in events, episodes, or the transcript.
Do not copy a fact into memory merely because it matters. A second source of
truth becomes stale; a durable reference to the canonical object is enough.
That reference is soft: the row names the brief, plan or task in its text, and
nothing links the two. No reader walks such a link, so it would cost a write
and add nothing; the name in the text is what a later search finds.
What remains for memory is placed by three questions, asked in order, because
the answer decides who will ever read it:
- **Would it still hold in a project the user has never touched?** Then it is
the user's, with no project, and it reaches every session and every agent.
- **Is it a short, fixed value an agent working one project must obey without
reading anything else** -- how that project integrates, where it releases?
Then it is a declared fact of that project, not memory: the `workflow` key of
its `project_identity` entry, which every specialist dispatched to that
project receives in its kernel. A rule an agent has to go looking for is a
rule it will not follow.
- **Is it history, reasons or something still owed about one project?** Then
it is that project's memory, read when that project is worked on.
A rule the user sets for one project splits along those lines: the habit
("follow the workflow each repository declares") is his, the value ("this one
integrates straight to main") belongs to the project. Filed as a user row, the
value follows him into every other project and contradicts the next one.
Then ask of any rule for how Gaia should behave: **would it still make sense if
Gaia worked perfectly?** If not, it is not knowledge about anyone -- it is a
defect, filed under `gaia_system` where anyone can list and fix it. Saved as a
user preference instead, the user carries the patch forever and nobody sees the
bug. What the user wants meanwhile is a preference that names the bug it covers
and retires the day that bug closes. Behaviour belongs to the harness; memory
holds what is true.
## Process
1. **Know what a session is born with, then sweep what you are about to
touch.** Every session opens with four sections: the projects, each with its
live-pending count; the environment it stands in; the user; and the user's
preferences. The last two are the user's standing rows, whole; every
dispatched subagent receives them too, minus the rows whose audience is the
orchestrator alone, so a row about how the orchestrator should report spends
no specialist's attention. Project memory — anchors, threads, their bodies —
never loads at birth and never reaches a specialist's kernel: a count is a
signal to ask, not the corpus, and what a dispatched turn needs of it travels
as a reference in its goal. It arrives when that project is worked on: before
writing into an initiative, or whenever the question is what it still owes,
read its whole live-pending set with
`gaia memory get-relevant --initiative=<key>`, uncapped and with bodies, and
its standing notes with `--sections anchor` added. A reader who only sees the
counts can add rows and never retire one. `gaia session preview` shows the birth block without
recording anything.
2. **Search before writing; do not read silence as absence.** Find the topic's
existing owner and its lineage — a duplicate divides relevance instead of
strengthening knowledge. An empty result answers "no row matches this
phrasing", never "this initiative owes nothing": a pending is worded as the
problem looked when it opened, not as what just resolved it, so step 1's
sweep is what finds it. An empty
`gaia memory get-relevant --initiative` is the complete answer for that
project: it reads every workspace by the canonical project key
(`gaia.store.reader::pending_threads_by_project`). Without `--workspace`, a
slug verb also reaches a project's row stored under another workspace
(`bin/cli/memory.py::_workspace_holding`, refusing with `ambiguous_slug`
when two other workspaces hold it); a named `--workspace` is never swapped
for another, and `delete` never makes that jump -- it refuses with
`workspace_not_named` and names the `--workspace` to sign. A search stays scoped to the
caller's workspace plus `_gaia_host` and `_gaia_user`
(`bin/cli/memory.py::_reader_workspaces`), so an empty search or a missing
row without a project is a scoping hypothesis — confirm with the right
`--workspace` before trusting it.
3. **Choose the home.** Run *Other home first*, and continue only for genuinely
curated value.
4. **Write one thing per row, in the shape a reader decides on.** The
orchestrator answers the three questions above, then writes a description
that is one sentence naming its kind of claim and a body that carries the
content, why it holds, where it came from and when -- a measured fact says
when and how it was measured, or it is an opinion. Knowledge changes by a new
row that supersedes the old one, the arrow pointing from the new row to the
old, which then leaves every injection; rewriting the old row in place
erases the change itself, so memory is append-only: there is no `edit`, an
`add` over an existing name is refused, and `add --replace` (signed) is only
for correcting an error. Only a log or a live thread grows by `append`. Graduation keeps its
lineage the same way. A row about the user stands from the moment it is
written -- every session and every dispatched agent carries it -- so the
first question of *Other home first* is what earns it that reach. The CLI
checks length, owner and the arrow and prints
the vocabulary as the row is written; it cannot judge whether the row
deserved to exist.
5. **Curate against the exception boundary, then report.** Curation is
delegated: the orchestrator adjudicates and executes directly, inside the
boundary below, and reports what changed afterward — it does not show a
proposal and wait for it to be confirmed.
| Operation | Handling |
|---|---|
| `add`/`append`/`reclassify`/`link` (creating an edge) on rows not about the user or a user decision | autonomous, brief report |
| `type=user` rows (about the user) | autonomous, flagged above the report for veto (convention — no mechanical backstop). They have no workspace: `add` from any workspace writes to the user scope, and a name already there is reported, never overwritten — a changed preference is a new row that supersedes it, which a link reaches from any workspace |
| contradicting or superseding a user `decision_*` row | ask first |
| `add --replace`/`delete`/`link --delete` | T3 approval flow; delegate to a specialist and never autoexecute. `memory_links` keeps no history, so removing an edge is as unrecoverable as a delete |
| `checkpoint` | autonomous after the milestone test; it is one atomic operation and remains all-or-nothing |
| closing an objectively verifiable brief/plan | autonomous, report; run `gaia brief verify` by hand before `set-status` — `close` (which runs verification for free, `bin/cli/brief.py::_cmd_close`) is not on the orchestrator's `gaia` CLI lane, only `set-status` is |
| promoting a TASK | never direct — dispatch `gaia-verifier` |
| approvals | read/report only |
6. **Verify the durable result.** Read back the affected rows, lifecycle, scope,
and links. Report partial batch failures per operation.
## When curated memory earns attention
- **Decision:** accepted, with no canonical home, and it binds a later choice.
- **Project milestone:** it closes a meaningful arc. A routine session close is
not one; minting a checkpoint for it turns memory into session summaries.
- **Live handoff:** one unresolved concern has no structured work object and
must resurface. One concern per thread — a single status cannot honestly
represent several.
- **Learning or dead end:** it prevents repeated investigation or error.
- **Gaia improvement:** a concrete symptom, component, evidence and reproduction
deserves visible follow-up. Persist it as a `feedback` live thread in
initiative `gaia_system`, carried forward until closed or graduated.
## When curated memory loses it
Attention is finite and a live thread spends it every session. Three exits, and
none is deletion:
- **Closed** — the concern was resolved or stopped being relevant.
`reclassify --status=closed` retires it from the worklist and keeps the row.
- **Graduated** — the work finished and left knowledge worth holding.
`reclassify --status=graduated`, or `--class=anchor` when future dispatches
should carry the knowledge; `link --kind=graduated_to` preserves the lineage
from the thread to the anchor it became.
- **Superseded** — a newer row holds the truth now; the supersedes link from it
retires this one from every injection. A workaround preference is superseded
or closed the day its bug closes.
These verbs are non-mutative, so cost is never the reason a row stays live.
Whoever observes the resolution owns the exit: a session that resolves a thread
and does not close it has moved that thread's cost onto every session after it.
## Curating inconsistencies
Curation looks for two kinds of inconsistency, and the CLI resolves neither.
- **Rows that contradict each other.** Two live rows of one owner that answer
the same question differently leave every reader to guess, and whichever it
happens to read first wins. `gaia memory conflicts` lists pairs that share
wording as candidates; only reading both says whether they disagree. What
holds is written as the newest row and supersedes the other -- the same arrow
as any change, from the new row to the old.
- **A preference that collides with a system rule.** A preference governs a
default: anything Gaia would otherwise choose on the user's behalf. It never
governs an invariant -- consent, security, the contract every agent closes --
because those are what make everything else trustworthy, and a preference
able to lift one would turn every preference into a bypass. Such a preference
is not saved as written: the collision is named to the user, and what is kept
is the part that governs a default.
## Who writes
- The **user** governs durable knowledge and every "ask first"/"veto" exception.
- The **orchestrator** reads deliberately, resolves ownership, adjudicates,
curates within the exception boundary, and reports.
- `gaia-operator` materializes already-adjudicated instructions exactly.
- Other specialists only propose (`memory_delta`, `memorialize_suggestions`);
they never write curated memory directly. They can read `gaia memory add
--help` and `gaia memory link --help`, so a proposed row arrives in the
shape it will be written in.
- The runtime enforces the writer boundary and core data invariants. The skill
supplies curation judgment; it does not duplicate enforcement details.
## Handoffs
- `session-reflection` recovers decisions, live work, learnings, Gaia
improvements and closures, then hands off the curation this skill governs.
- `gaia-compact` runs after durable persistence and carries only transient
continuity plus references to what was saved.
- The CLI is the other teaching surface: `gaia memory add --help` carries the
claim vocabulary and the three owners, and every write warns on the form and
closes with a pointer back here.
- `reference.md` contains the write path (scope rules, enums, warnings) and
retrieval; three siblings hold the rest, loaded by subject:
`reference-curation.md` (lifecycle, links, checkpoint payloads, history
coverage, graph), `reference-defect-promotion.md` (the `gaia_system` defect
shape) and `reference-access-telemetry.md` (the read counters).
- `examples.md` contains worked create, change, bug-as-rule and checkpoint cases.
## Anti-patterns
- **Digest or search as corpus:** either can miss an initiative or old wording;
only the deliberate whole-initiative sweep supports closure.
- **Wrong-scope convenience:** cwd does not decide where knowledge belongs.
- **A bug saved as a preference:** the user carries the patch forever and nobody
lists the defect.
- **The supersedes arrow pointed backwards:** the new row leaves every injection
and the stale one stays, so the corpus reads as if the change never happened.
- **A resolved thread nobody closes:** it taxes every later session.
- **Stale update metadata:** `append` changes only the body, while repeating
`add` without `--description` clears that description; verify both.
- **Curating against an old snapshot:** re-read affected rows before closure;
concurrent sessions and hooks can change the corpus.
- **Claiming perfect history:** only schema and migrations define what survives.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!