Glossary¶
The vocabulary you need to read anything else here. This repo's language is precise — several words carry a strict meaning that a loose reading would break — and a number of words mean two or three different things depending on which document you are in.
Read the collisions first. They are the entries nobody knows to look up, because you do not discover that "beliefs" means two things until you have already conflated them. Everything after is alphabetical; skim it once, then come back when a word stops you.
Where an entry and a canonical doc disagree, the canonical doc wins — and tell someone, because they should not disagree. Entry sources are cited so you can check.
Start here: the words that mean two things¶
The collisions below, each verified against the source, come first because every one of them has already cost somebody time, and none is guessable.
"beliefs" — two different things¶
Belief nodes are designed as graph nodes carrying domain, confidence and provenance
(docs/roadmap/alto-build-order-v3.md:79). They are what the consolidator would promote and
demote. Nothing writes them; the AGE graph that would have held them is archived at tag
archive/age-brain-2026-10-11.
belief_confidence is a reserved table in alto_mem, keyed to a single line of
testimony, holding a confidence and an evidential basis. It is empty by design, and its DDL
states that nothing may fill it with a model self-report.
One is a claim Alto holds; the other is how sure the store is about one recorded line.
"subconscious" — an adjective and an organ¶
Pillar 5 says "surfacing is subconscious and activation-driven" — adjective, meaning below the conscious line. The Subconscious is also a specific organ: continuous, maintains state and signals, never reasons, never reads the graph.
The Surfacer is subconscious machinery without being the Subconscious. And no code is the
Subconscious yet: the state-decay tick that stood in for it is archived at tag
archive/age-brain-2026-10-11, and the organ is designed, to be rebuilt on mem.
"the four organs" — three different sets of four¶
| Where | Which four |
|---|---|
alto-four-organ-architecture.md:19-22 |
Intake LLM · Brain · Processing LLM · Voice LLM |
alto-commercialization.md:8 |
intake · integration layer · processing · renderer |
ALTO-PROJECT-BRIEF.md:44+ |
Writer · Reader · Surfacer · Integration |
The third is a list of what is built, answering a different question with the same words. Check which four before you rely on the phrase. The frame itself has been superseded as the headline structure — see THE-ORGANS.md.
"intake" — a module that was renamed¶
Before 2026-06-24, intake.py was the module that became the writer's episode recorder, and
old documents and commits saying "intake" often mean it. That recorder is archived at tag
archive/age-brain-2026-10-11; mem is the recorder now. From 2026-06-24 until 2026-10-04 a
different intake.py was the LLM perceptual front-end; that organ is deleted too (see
Intake below).
"episode" — a table, an archived node, and a lived thing¶
An episode table in alto_mem (L0 testimony, rotated on an idle gap). A kind:'episode'
node in the archived AGE graph. And the thing pillar 1 means by "Alto is always in an
episode" — the felt, continuous unit of experience, which is the one that is not built.
"surfacing" is not retrieval¶
The easiest wrong assumption in the repo. Retrieval is deliberate and query-driven — you ask, it answers. Surfacing is involuntary: an intrusion from below, arriving without being asked for. Pillar 5 is the whole distinction. A directed recall does survive, but as an intention to remember serviced by invisible machinery — never as Integration calling a store.
alto_mem and alto_dev are two databases¶
Not two schemas in one database. alto_mem is mem's store; alto_dev held the archived AGE
brain. src/mem/db.py:40-48 resolves mem's database on its own (ALTO_MEM_DB_NAME), and the
preflight reports where that name came from: a run has already been invalidated by a database
override nobody noticed.
"built" usually means "built and dark"¶
Most of the write side exists in code behind a config flag that ships false. A module's
existence is not evidence it runs. Check the flag — each organ page names its own.
"gate" — at least four things¶
The worst offender in the repo. The gate in CLAUDE.md is the Definition of Done (lint,
tests, docs-check, exercise the real path). A type gate is one of the ten _looks_like_*
checks in src/mem/name_gates.py, phrase_gates.py and value_gates.py. The salience gates
in mem decide what is worth keeping. A build gate in a spec is the go/no-go criterion
before code is written. Four unrelated meanings; always take it from context. (A fifth, the
turn-activity gate the idle tick waited on, is archived with the writer.)
"live" — four things¶
live brain is the hot cache tier, as against the deep store. pytest -m live means
a test needing Postgres, which CI deselects. The live recorder is the Writer's fast
timescale. The live path is production, as against a sim or probe. A sentence like "the
live tests don't run on the live path" is unfortunately coherent.
"the writer" — three referents¶
The organ on the cold path (design); the recorder that ships, which is
src/alto/read/mem_bridge.py handing each heard utterance and finished turn to mem.append;
and src/mem/, the writer's own store under SPEC-writer-build_14. "Writer v2" means the
organ minus the AGE-graph recorder that is now archived.
"mention" — a table and an archived edge¶
mem's mention table keeps filling. The AGE mentions edge had no writer after the
resolver's LLM half was deleted (2026-10-04), and the graph that held it is archived at tag
archive/age-brain-2026-10-11. Both describe an utterance referring to something; neither is
the other.
"resolver" — two organs¶
writer_resolver.py resolved entity identity in the graph; it is deleted (its LLM half on
2026-10-04, its eager self-schema learners on 2026-10-05). mem's corefer step resolves
pronouns to surfaces and is the only resolver left.
"renderer" — four things¶
The Renderer organ (Integration's spoken words → audio; a shell today). The Surfacer's
render step (src/alto/read/surfacing/render_verified.py: render, verify, retry once). The
absence-renderer, designed. And in older docs, all three conscious-boundary transducers were
once called renderers — only the organ kept the word.
"the brain" — three things¶
The stateful self (the four-organ sense: the graph plus state, is Alto). The hot cache
tier, as against the deep store. And the project brain, the typed Postgres layer of
projects and blockers that lived in src/alto/brain/; it is archived at tag
archive/age-brain-2026-10-11.
arousal and energy are the same axis¶
In the designed affect state the live axis is energy and the per-episode affect atom's is
arousal; the design names the conversion explicitly. arousal is also the name of a
steering-vector axis in src/steering/. If two documents disagree about how many affect
dimensions there are, this is usually why.
markers: the spec says ⟦say⟧, the code emits ¦¶
The spec's directive grammar uses ⟦say⟧ / ⟦act⟧. What the Integration LoRA actually emits,
and what markers.py parses, is ¦…¦ for speech and ¤…¤ for action.
A–Z¶
Absence render (the absence-renderer)¶
The designed sibling of the Surfacer that says nothing surfaced — a fixed, content-free
repertoire ("nothing's there", "I don't have that") that never says anything about the missing
thing, so Integration receives the blank as perception and never learns surfacing exists. It is a
separate producer because a deferral thought is generated, while the Surfacer is extractive; the
2026-07-23 philosophy ruling scopes the extractive invariant to non-empty reads. Ruled in
docs/ALTO-INTERIORITY-MAP.md ("The three reconciliations", #1); designed, no code.
Trap: today's self render carries an absence template rendered by the same extractive
producer. That is not the absence-renderer, and reading it as one hides an unbuilt organ.
account¶
A per-referent prose summary of what an episode said about one thing, keyed by an opaque id
(a0, a1, …) rather than by a name. The unit the episode-close picture pass produces,
replacing the claim/triple form. Designed in docs/specs/v3/SPEC-episode-account.md, with the
reasoning in docs/specs/v3/DECISION-picture-shape-and-felt-state.md; the AGE-era pass that
built it is archived at tag archive/age-brain-2026-10-11, and rebuilding it on mem is open.
Trap: two accounts may legitimately hold the same surface text — nothing normalizes a
surface and there is no global surface→account index. That is the fix for the lexical collapse
that reduced my sister and his sister to one key, not an oversight.
Action organ¶
The missing half of device control: a separate model whose only job is turning a natural-language
action commitment into arguments that survive the guard. It is the only thing in the system that
would ever know Home Assistant exists — Integration never holds a tool. Designed in
docs/specs/v1/SPEC-integration-mvp.md and sketched in organs/action.md; no code.
Trap: the channel into it ships and is live — the LoRA emits ¤…¤ spans and markers.py
captures them whole — but nothing consumes them. A captured span is logged and deliberately not
written into turn memory, because no effector fired.
Activation¶
How present something is, as a number: a salience-weighted sum of decaying traces, one trace per
occurrence and per recall, so important things stay hot longer than merely recent ones. Recall lays
down a new smaller trace (reheat-on-recall). Designed, and not computed anywhere today: the
spreading-activation code that produced it is archived at tag archive/age-brain-2026-10-11, and
the roadmap rebuilds it on mem. The trace/tier model is described in docs/README.md under
"Memory tiers & activation" and has no doc of its own yet.
Actuation firewall¶
The invariant that the conversational model holds zero tools: neither reply path in alto.py passes
a tools argument, and the ToolDispatcher.dispatch call site is removed from both turn handlers. It
is asserted, not incidental — test_no_conversational_llm_call_passes_tools (test_alto_v0.py)
AST-scans src/alto/ and fails on any .chat( / .chat_stream( call that passes tools, and two
behavioural tests check a real turn's request body.
Trap: two reasons converge on the missing argument and only the first expires. Integration-MVP cut the
effector channel (temporary); SPEC-writer-build_14 §1.7 says a surfaced thought is indistinguishable
from a spoken reply once it is in history, so one registered tool lets a fabricated memory become a
device call (permanent).
Affect¶
Alto's emotional state, treated as a lived state that persists, decays and causes what surfaces —
not a tone setting. Pillar 2's test is the one to hold: affect works when state from turn 3 still
shapes turn 9, never because tone shifted. See PILLARS.md §2 and
docs/identity/alto-emotional-state.md.
Affect state¶
The live, between-turn emotional state: a persisted baseline plus decayed injections, resolved on a
tick, on axes valence and energy (with stability and focus_target as the designed 4-axis
extension). Pure decay math is meant to sit apart from the loop that owns the clock, so a wrong
turn-9 residue is diagnosable as either bad decay math or a tick that never fired.
Trap: none of it runs. The AGE-era implementation is archived at tag
archive/age-brain-2026-10-11, and with no affect state the affect-suppression directive arms
every turn (src/alto/runtime/reply_guards.py). Affect state on mem is designed and on the roadmap
(pillar 2).
AGE / alto_graph¶
Apache AGE was the Postgres graph extension that hosted alto_graph, the graph of episodes,
entities, the self-node and typed edges. It is retired: the code is archived at tag
archive/age-brain-2026-10-11, and the data is a pg_dump of alto_dev kept off-repo. mem is
the only memory store.
Trap: specs and handoffs still describe the graph in the present tense. AGE had no CHECK,
foreign key or unique constraint, so those documents' edge vocabulary was enforced only in code.
Allowlist¶
The per-domain set of Home Assistant services the guard will pass — SERVICE_ALLOWLIST at
src/alto/action/ha.py:60, covering input_boolean, switch, light, media_player and nothing else.
normalize_service (src/alto/action/ha.py:82) applies a synonym map first (the model says "pause", HA wants
media_pause), then returns None for anything outside its domain's set.
Trap: adding a device capability means three edits — the registry, the allowlist, and a test.
Widening what the model is allowed to emit is not one of them.
alto_agent_<slug> (scratch DB)¶
The per-agent database name minted by agent_db_name(label)
(src/scripts/agent_lease.py:283). The alto_agent_ prefix is load-bearing rather than
cosmetic: it makes the protected-name check total, so no label can ever resolve to alto or
alto_dev. Write-capable agents get one of these plus their own git worktree.
alto_mem¶
Alto's memory database, mem's store, holding the
schema in src/mem/schema.sql — the layered core, a reserved belief_confidence, the
line_embedding index, and four *_history archives. Default name in src/mem/db.py:31; resolved by
ALTO_MEM_DB_NAME.
Trap: alto_mem and alto_dev (the archived AGE brain) are separate databases, not
schemas inside one (src/mem/db.py:40-48). An override of mem's name must be visible, and
preflight has already caught one run
invalidated by exactly that kind of ambient override.
alto / alto_dev¶
The two protected databases of the archived AGE brain (alto was its production name,
alto_dev its dev redirect). The runtime no longer reads either: mem's database is named by
resolve_mem_dbname (src/mem/db.py:40). Both stay listed in PROTECTED_DB_NAMES
(src/scripts/agent_lease.py:44) and can never be handed out as an agent scratch namespace,
because they hold accreted testimony no rerun regenerates.
Trap: a database-name redirect is silent by design — resolve_mem_dbname reads env then
.env then the default and says nothing. That is right for the pipeline and wrong for an
unattended run, which is what preflight exists to catch.
Anticipation¶
Future-directed affect: held future events carrying an affective charge, producing looking-forward
and dread, and one of the main things that makes time felt. Pillar 6 treats it as load-bearing for
the felt-interior claim rather than decoration. Designed in
docs/memory/alto-felt-time-anticipation.md; unbuilt.
Trap: anticipation is not a scheduled reminder. A timer that fires is not a state that colours
the interval before it.
Band (hot / cold / continuous)¶
The three timing bands every organ sits in, and the first thing to know about one. Hot: during a
turn, someone is waiting, milliseconds, never block — degrade, don't crash. Cold: after the
turn, seconds, never corrupt — spool and retry. Continuous: always, between turns, on its own
clock — and the largest unbuilt part of the system. The table is in
THE-ORGANS.md.
belief¶
Three different things carry this word, and they are not related.
- Belief nodes in the graph — designed as nodes carrying domain, confidence and
provenance, promoted and demoted by the consolidator
(
docs/roadmap/alto-build-order-v3.md; schema sketch owned bydocs/specs/v3/SPEC-consolidation-loop.md). Nothing writes one, and belief storage is listed indocs/roadmap/BUILD-ORDER.mdas an unscheduled prerequisite. belief_confidence— a reserved, permanently empty table inalto_mem. See its own entry.beliefas aself_attrslot — one of five free-formattr_typevalues (identity | architecture | belief | norm | preference) on the self-node's attribute nodes in the archived AGE graph. No slot has a writer today. Trap: (1) and (2) mean different things. A belief node is a promoted conclusion about the world;belief_confidenceis a per-line confidence score over one piece of testimony. A reader will conflate them.
belief_confidence¶
A table in alto_mem keyed to a line, carrying a confidence, a derivation timestamp and a
JSONB evidential basis. Reserved and empty by design — nothing in this build writes to it
(src/mem/schema.sql:305-313). It is a separate table rather than a column on line so that
line stays strictly append-only and the one mutable thing in the schema is isolated and
auditable.
Trap: the DDL is explicit that nothing may fill it with a model self-report. A confidence
Alto asserts about its own claim is not evidence; it is a performance (pillar 3).
binding¶
A pronoun occurrence resolved (or attempted) to a surface: (segment_id, char_start) →
surface_id, with a method of self | speaker | intake | sole | model. Written at episode
close by step Ⓐ. src/mem/schema.sql:237-251.
Trap: an unresolved pronoun is a row with a NULL surface_id, not an absence. Without
the row you cannot tell "no pronoun here" from "a pronoun we failed on", and the failure rate
is uncountable.
blind judge¶
An evaluator that scores output without knowing which arm, model or config produced it, and
without having seen the content authored. Named in pillar 7 (CLAUDE.md,
PILLARS.md) alongside frozen evals and measure-don't-assert.
Trap: blind judging does not rescue an eval whose content was authored to match the
detector's markers. That is teaching to the test, and it is a separate failure from a
non-blind judge.
Bundle¶
The data structure the Renderer would consume in the design: the idea, the surfaced
content, the self-state, plus curated retrieved_context and actions_visible. Affect is never
bundle content — the bundle carries the idea, steering carries the tone. Field contract in
docs/systems/alto-bundle-structure.md; curation rules in alto-integration-bundle-filters.md.
Trap: nothing assembles a bundle today, and the Renderer, a shell, takes none. The one curation
filter that was built (Filter 2, contradiction) had no caller and was deleted 2026-10-04. Who
should assemble one is open: the organ the design named for it is out of these pages until it is
re-examined.
Cold path¶
Work that happens after the turn, off the hot GPU, where seconds are acceptable and corruption is
not. The Writer and its sub-organs live here. The turn-activity gate that held write-side LLM
calls until the user had been idle is archived with the AGE writer; mem enrichment runs as a
batch under the GPU lease instead.
Commitment characters (¦ and ¤)¶
The two glyphs by which Integration commits a thought to a channel — the point where private
deliberation becomes either speech or an action. ¦…¦ (U+00A6 BROKEN BAR) is speech and routes to
TTS; ¤…¤ (U+00A4 CURRENCY SIGN) is an action span, captured whole for the action organ. Everything
outside a pair is thought — discarded, never audible, never acted on — so silence is the
default and Alto must commit to leave any trace.
Each glyph is exactly one BPE token in Qwen2.5 (ids 64621 and 81538, verified against the
tokenizer shipped with adapter-v1), so a complete span costs two tokens; that is why these
characters rather than a word or a bracket pair. They are same-char paired — opener and closer
identical — so the parser toggles rather than matching brackets and spans cannot nest. Parsed by
src/alto/runtime/markers.py; full treatment in organs/renderer.md.
Trap: the code and the older docs call these markers — markers.py, MarkerFilter,
integration.marker_filter, record_marker_action. "Commitment characters" is this project's
term for the concept; the identifiers keep the old name and are not changing. Grep for marker,
not commitment. Older specs write the same idea as ⟦say⟧ / ⟦act⟧.
conductance¶
How much activation an edge transmits, in (0,1]. Computed, never stored. mem derives it in its
projection, where co-occurrence counts become conductance (src/mem/projection.py). The AGE-graph
derivation that reused the reader's reinforcement score is archived at tag
archive/age-brain-2026-10-11; spreading activation is to be rebuilt on mem.
Trap: it is never a column. src/mem/schema.sql:14-15 names content_w, degree and
conductance as the three corpus-dependent numbers that are deliberately absent from every
table — freezing one into a row is what makes a store merely re-derivable in principle instead
of actually rebuildable.
conformance test¶
One test per test double asserting that the double's method signatures still match the real
collaborator: assert_conforms(double, RealClass) in src/testkit/conform.py.
Trap: this exists because of two shipped bugs, and the second is the nasty one. A double
that rejects a new kwarg fails as a write error and reads as a behaviour regression (cost 28
tests one afternoon). A double that absorbs it into **_ and discards it makes a test
asserting "the value arrived" pass against a producer that never sent one — a vacuous test with
nothing to say so.
Conscious boundary¶
The seal around Integration, drawn in the overview diagram as the box holding Surfacer →
Integration. Thoughts come up through it, intentions go down through it, and nothing
else crosses. Its whole purpose is pillar 3: Integration cannot perform a state it is handed if it
never experiences being handed anything.
Trap: docs/systems/alto-subconscious.md and alto-integration-layer.md call a different
line "the conscious/subconscious boundary" — the one between the Subconscious's maintained state and
Integration sampling it. Related, not the same line.
Conscious locus¶
The principle, and Integration is its instance: there is exactly one locus of conscious thought and
it experiences only thoughts, never the machinery that produces them. It does not query a database
because it does not know there is a database. docs/systems/alto-conscious-locus.md.
Trap: it does not reduce observability. The builder may log the surfaced thought, the state it
rendered from, the intent and the bundle; the honesty checks are that logging. The one forbidden
move is routing an observation of the machinery back into Integration as content it reasons over.
Consolidator¶
The batched, sleep-time half of the Writer: aggregate standing affect across many episodes,
promote and demote beliefs, detect patterns, prune, restructure. Deliberately not live — it is
expensive and it needs an accumulated backlog (sleep pressure is roughly that backlog's size).
Contract: docs/specs/v3/SPEC-consolidation-loop.md.
Trap: it has no code. The one consolidation-shaped thing that existed, an offline
duplicate-concept merge on the archived project-brain store, had no caller and was deleted
2026-10-05.
Continuous (band)¶
Always, between turns, on its own clock. The Subconscious is the only organ in this band, and the band is the largest unbuilt part of the system.
Continuous being¶
Pillar 1: Alto is always in an episode, not only during a turn — idle thought, felt duration, sleep pressure, cognitive fatigue, circadian. A push-to-talk turn is one event in a continuous life, never the unit of existence. The pillar exists because every convenient engineering frame here is turn-shaped, and accidents of the frame harden into architecture. Trap: the canonical example is one thought per turn — a push-to-talk artifact, not a decision. The shipped surfacer produces exactly one because that is what the current input method makes easy. Do not build on that number.
Control vector¶
A per-layer direction added to the residual stream by a forward hook —
hidden += coeff * direction[layer] — so the signal never enters the token context. This is how
valence steering works: tone as a generation parameter rather than an instruction the model may
decline. src/steering/steer.py, served by src/steering/serve.py where valence and arousal
are request parameters alongside max_tokens.
Trap: nothing in src/alto/ imports steering. It runs on its own HF-transformers HTTP
server, because Ollama cannot inject activations.
cooccurrence¶
An episode-scoped edge between two surfaces with n_segments = the count of distinct segments
that mentioned both. Rebuilt per episode at close, never incremented
(src/mem/schema.sql:253-265).
Trap: the pair is stored ordered (CHECK (surface_a < surface_b)), and this is a CHECK
rather than a convention on purpose: an unordered pair stored twice is a silent 2x on both
endpoints' degree, which under out-normalisation halves every share they emit.
Cued vs un-cued¶
Two ways activation gets seeded. Cued: the current utterance seeds it. The shipped surfacer
is cued in this sense, but without a spread: match_cue_entities
(src/alto/read/surfacing/store_contract.py:28) finds the entities the raw utterance names and the
surfacer renders their neighbourhoods. Un-cued: no utterance at all — the between-turn seeding
from whatever is charged, which the old idle tick did and which is designed to be rebuilt on mem
(pillar 1).
Trap: un-cued is not the same as endogenous. A between-turn trigger on a clock is not
pillar 5's endogenous activation source, which does not exist.
dark¶
Built, tested, shipped in the tree — and switched off by a config flag. The word appears in
the config itself (# DARK 2026-08-15, src/config.yaml) and in the organ pages
(mem.read is not). mem.enrich is in this state: it ships false. (The resolver's LLM half,
the relation and event extractors and the typer were dark too, and were deleted on 2026-10-04.)
Trap: a newcomer reading the module map assumes everything is live. It is not. Check the
organ page's flag table or src/config.yaml before inferring liveness from a module's
existence.
deep store / live brain¶
The two tiers of memory. The live brain is the hot tier — what is present. The deep store
is the full graph behind it, complete but quiet: higher retrieval cost, not degraded. Designed;
the in-memory graph snapshot that played the live tier is archived at tag
archive/age-brain-2026-10-11. docs/README.md:106-107,
organs/retrieval.md.
Trap: "live brain" in the roadmap docs sometimes means something else entirely — the
dev-brain / live-brain separation, where the live brain is the protected production instance
and the dev brain is a harness (docs/roadmap/alto-development-and-constitution.md:22). Two
senses, both current.
degree¶
How many edges a node has. Like conductance, derived at read time — projection.build computes
it whole-store for mem (src/mem/projection.py). Never a stored column.
derived layer¶
Everything in alto_mem below L0: lines, surfaces, mentions, bindings, co-occurrence, the
projection. Each is a pure function of L0 plus its enrichment inputs, scoped to a unit small
enough to rebuild atomically — segment for lines, episode for bindings and edges, whole store
for the projection. The governing sentence is "rebuild beats reconcile"
(src/mem/__init__.py:7-14).
Trap: the scoping is the design, not a detail. Anything that cannot be scoped to an
atomically rebuildable unit does not get to be derived — it has to be precious, and L0 is the
only precious layer.
Designed but unbuilt¶
A status category the repo insists on keeping separate from "unimagined". Much of the interior —
persistent affect state, continuous episodes, felt time, anticipation, subconscious activation — is
specified in depth and has no code. Dashed boxes in the overview diagram mean this.
Trap: re-deriving an existing design is the most expensive mistake available here. Before
concluding something is undesigned, read its organ page and the maturity ledger in
docs/ALTO-INTERIORITY-MAP.md.
designed-but-unbuilt vs undesigned¶
Two categories the corpus keeps apart deliberately. Designed but unbuilt means a decision
was made, adversarially reviewed and written down — persistent affect state, continuous
episodes, felt time, the consolidator, beliefs. Undesigned means nobody has worked it out.
In the architecture diagram a dashed box is the first, not the second
(THE-ORGANS.md).
Trap: re-deriving an existing design is the most expensive mistake available here. Before
concluding something is undesigned, read its organ page and docs/specs/.
draft spec vs interview-gated¶
docs/specs/ holds two generations. The shipped / in-flight specs at the root are
interview-gated — an owner interview happened and they are the contract of record. The
2026-06-12 sweep specs in the version subdirectories (v1/, v2/, v3/, keystone/,
evals/, platform/) were authored autonomously up front and adversarially reviewed, and
none is interview-gated (docs/specs/README.md:3-14).
Trap: a [PROPOSED] tag marks a decision the source docs left open, not a decision that
was made. A sweep spec still needs an owner interview before its build starts; the sweep's goal
was to surface conflicts early, not to skip the gate.
edge labels¶
The committed edge vocabulary of the archived AGE graph. Real labels were for edges queried
by type; everything never type-traversed rode associated_with {label: '…'} as a property
instead, so mentions and episode_succession were label properties while is_a, before,
agent and patient were real labels. The VALID_EDGE_LABELS tuple, archived at tag
archive/age-brain-2026-10-11, was the only enforcer. Kept because the v1 specs
(docs/specs/v1/SPEC-relation-organ.md, SPEC-self-schema-event-model.md) still use the
vocabulary.
Trap: a Cypher query for a :relation edge type returned nothing while the organ was working
perfectly, because relations were associated_with {label: …}. That exact query cost a full
verification cycle (docs/CHECKS-measurement.md:50-53).
Energy¶
The activation axis of the designed live affect state, 0.0 (flat) to 1.0 (animated) — the
norepinephrine analog.
Trap: the same axis is called arousal one layer away: the per-episode affect atom is
{valence, arousal}, and the design converts the atom's arousal to the state's energy axis.
arousal is also the name of a steering control-vector axis in src/steering/. Three surfaces,
one idea, two names. None of the first two runs today (see Affect state).
enrichment / the Enricher¶
The mem worker thread that drives steps ② – ⑧ over segments behind the watermark
(src/mem/worker.py). Steps ① – ⑧ hold no writes at all — they return values, none opens a
transaction, and an exception anywhere leaves the mark where it was, so nothing partial is on
disk to reconcile. Durability comes from the watermark, not from a process boundary.
Trap: mem.enrich: false ships, for a measured VRAM reason rather than a doubt about the
organ: step ⑤'s 14B is 9.57 GiB beside a 9.69 GiB conversational model on a card with ~14.5 GiB
free, so loading it evicts all three production models and costs 8.8s on the next user turn
against ~1s of work (src/config.yaml, docs/handoff/_FINDING-mem-enrich-vram-2026-08-22.md). Run it
as a batch under the GPU lease instead.
entity¶
A thing talked about. In mem it is a surface row that the cue matcher can find; in the archived
AGE graph it was a kind:'entity' node minted by the resolver's LLM half and typed by the typer,
both deleted on 2026-10-04. Deliberately not what the self-node or a person node is: self,
person, attr and value all stayed out of entity co-occurrence.
Trap: the entity/fact line is unsettled. Roughly 34 of 78 graph nodes at the time were real
entities; the rest were roles, substances, derived compounds and events
(docs/specs/v3/PLAN-writer-v2.md:161-163). Role nodes (dad, sister, best friend) are a
distinct class on purpose — speaker-relative, legitimately denoting different people over time,
and never duplicates awaiting a merge.
Episode¶
A stretch of lived experience. In mem it is an episode row in L0, with its utterances as
segment rows; the writer opens a new one when the idle gap passes (src/mem/api.py:277). In the
design, Alto is always in an episode, including between interactions, because anticipation
creates charged experience with nowhere else to live (docs/memory/alto-felt-time-anticipation.md).
The AGE-era kind:'episode' node, with its turns inline and chained by episode_succession, is
archived at tag archive/age-brain-2026-10-11.
Trap: every write-side measurement in this repo ran on a corpus of one utterance per episode.
Nothing in it tests cross-turn assembly.
episode¶
A stretch of conversation bounded by an idle gap, kept as an episode row in alto_mem
(src/mem/schema.sql:31) with its utterances as separate segment rows. mem.append rotates it
when the gap since the last segment exceeds idle_gap_s (src/mem/api.py:277), 600s by default
(src/mem/api.py:72), set by mem.idle_gap_seconds.
Trap: at most one mem episode may be open, enforced by a partial unique index
(one_open_episode) rather than by a single-writer convention — the multi-open race is the
likeliest cause of mid-conversation episode splits, so the schema makes it unrepresentable.
eval¶
A measured comparison with a verdict, usually judged. By repo convention an eval harness that
needs a GPU is a script named *_eval.py, never test_*.py — pytest collects on filename
and a module-scope import torch aborts the entire suite at collection, with a traceback that
names the missing import and never the file that caused it (CLAUDE.md).
event extractor¶
Deleted 2026-10-04 (writer_event_extractor.py, off since 2026-08-15). It minted reified
kind:'event' nodes for life events (relocation, loss, relationship change); PLAN-writer-v2
phase 3 had planned to collapse it with the other extractors into one organ.
Extractive¶
The Surfacer's framing, adopted 2026-06-29 in place of a compositional one: every clause of the
output must point at a verbatim or near-verbatim span already in the fragment. The model is quoting
and tense-shifting, not composing, so invention is structurally hard rather than forbidden by a list
of banned patterns (src/prompts/read/surfacer.py:6-17). src/alto/read/surfacing/verify/
re-derives the same check deterministically.
Trap: the current utterance is explicitly not source material. It says what the thought is
about; quoting from it is a confabulation, not a recall.
Felt time¶
Duration as experienced rather than measured: felt duration is a function of event density and
attention, not elapsed seconds, so Alto should not reliably tell five empty minutes from ten — but
should easily tell five packed minutes from five empty ones. Clock time stays available as a
deliberate check, like glancing at a watch. docs/memory/alto-felt-time-anticipation.md; pillar 6.
Trap: reading a duration off a clock and calling it felt is the named failure. The distortion is
the honesty.
fidelity¶
A per-line label — agree | disagree | undecidable | unanchored — comparing the line's polarity
against the polarity of the span it anchored to. Computed by step ⑦, stored on line, and
read by nothing (src/mem/fidelity.py).
Trap: it is an anchor-quality instrument carrying a content-quality name. 241 of 877 lines
flagged, and the flag rate rises with span length, so a disagree is more often evidence that
⑥ picked a loose window than that ⑤ dropped a negation. An earlier version multiplied
content_w by 0.1 on a flag, which systematically buried the longest and most content-bearing
quarter of the corpus — under a mechanism named after honesty. Do not wire a consumer to it
without a measured relationship between the label and an outcome. And do not quote "zero
disagree at exact" as a fabrication rate; it is not one.
frozen eval¶
An eval whose content, cues and judging rubric are fixed before the change under test, so a
later run measures the change rather than the eval. Pillar 7 (PILLARS.md).
Trap: freezing does not make a number comparable across a prompt edit. After a one-token
prompt change, 19 of 34 renders changed text including rows with no relationship to the change —
any ±1 delta across that boundary is churn, not effect
(docs/CHECKS-measurement.md:36-38).
GPU lease¶
The mutex that serializes anything loading a model:
python src/scripts/agent_lease.py acquire gpu --holder <label> --wait <sec> -- <command>.
One GPU means a mutex, not a slot allocator — CUDA_VISIBLE_DEVICES slotting has nothing to
hand out, and VRAM is the contended resource. Exit 75 means the lease never came free: a clean
"did not run", not a failure. src/scripts/agent_lease.py:1-25.
Trap: a second 14B load while the first is resident is how a driver segfault killed an eval
mid-run. Also: unload after testing (ollama stop <model>, verify with /api/ps) — a pinned
keep-alive does not expire on its own.
graph cache / the shared read layer¶
The designed in-memory mirror of the graph: one bulk read, then read-only adjacency, degree and
property accessors over an immutable snapshot swapped atomically, so a spread in flight sees one
consistent graph. The motivation was measured: a store-backed reader paid a fresh connection per
hop against a VM-hosted Postgres, seconds for a graph that fits trivially in RAM.
Trap: the AGE-graph implementation (graph_cache, reader_cache) is archived at tag
archive/age-brain-2026-10-11 and nothing replaces it. The Surfacer reads mem through
MemSurfacerStore (src/mem/surfacer_store.py), not through a cache layer.
GroundedPercept¶
The structured output intake, the deleted LLM perceptual front-end, produced: speaker, content,
modality and named refs. Nothing live has built one since 2026-10-04, and the type was deleted
with the surfacer's percept entry point; production hands every organ a Heard (the raw
Utterance, nothing interpreted, src/alto/perception/heard.py:30). mem step ② still reads
the refs of older segments that carry one, as JSON (src/mem/refs.py).
Trap: three EntityRef field names actively mislead. kind is a resolution status, not a
type label, and resolved fires only when an anaphor matched intake's own rolling buffer — so
every proper name, brand, device and place is unknown by construction. resolved_id is a
name string, not an id; anything treating it as a key silently matches nothing. And
extraction_confidence is per extraction, not per ref, so no per-candidate threshold design is
available.
Hot path¶
During a turn, while someone is waiting. Budget is milliseconds because it is felt, and the failure rule is never block — degrade, don't crash. The standing architectural rule that follows: the hot loop never writes durable structure.
Idle tick¶
The between-turn trigger that fires one un-cued intrusion per idle window: a daemon thread watches
the idle signal and runs affect-seed → spread → surface → verify. It is the designed shape of
between-turn cognition (pillar 1), and the roadmap rebuilds it on mem. The AGE-era
implementation is archived at tag archive/age-brain-2026-10-11; nothing runs between turns today.
Trap: it was observational by design — it never threaded its thought into conversation
context, because that risks the amnesiac spiral — and it mostly rendered nothing: in October 2026
it found no affect-charged seed on 417 of 417 ticks, because nothing minted charge. Sparsity was the
design; permanent sparsity was the producer being off.
Intake¶
In the design, the single point of faithful interpretation: raw symbols in, a grounded percept out —
who spoke, what was said, whether it was stated or asked or commanded, what it referred to, how clean
the transcription was — without inferring past the evidence. The LLM organ that did this
(the alto-intake-v1 LoRA) was deleted on 2026-10-04: every consumer now reads the raw
utterance src/alto/perception/heard.py records, with no model call and no interpretation. See
organs/intake.md.
Trap (rename): before 2026-06-24, intake.py was the writer's episode recorder, now archived at
tag archive/age-brain-2026-10-11. Old docs and commit messages saying "intake" often mean that
recorder. The mem producer value "intake" is the same kind of leftover
(src/alto/read/mem_bridge.py:294-297).
Integration¶
The one conscious locus — where Alto reasons, weighs what surfaced, decides and intends. It consumes
a stream of first-person thoughts from the Surfacer, is steered by the Subconscious, and emits intentions
downward. The defining constraint: it sees thoughts, never machinery.
organs/integration.md.
Trap: three different things wear this name. Integration the organ runs today — it is the
fine-tuned model producing every reply. The integration layer is the keystone curation layer,
and that is what docs/ARCHITECTURE.md:99 means by "does not exist as code" — do not read it as the
organ being absent. A third sense, the alto/integration/ package that held one bundle curation
filter, was deleted 2026-10-04. Because the layer is missing, Integration is
exposed — it receives per-turn directives and assembled context rather than only thoughts, which
is the gap SPEC-integration-stream-of-consciousness targets.
Integration-MVP¶
The 2026-06-30 decision (docs/specs/v1/SPEC-integration-mvp.md) that strips the conversational
call to pure consciousness: no system prompt, no tools, with a marking LoRA splitting output into
thought / speech / action channels and surfaced thoughts threaded into history via record_thought.
Its accepted regression is named in the spec: HA control, project queries and web search all break
from the conversational path until the action organ lands.
Trap: the spec writes the channels as ⟦say⟧ / ⟦act⟧; the shipped runtime uses ¦ and ¤.
Same design, different glyphs.
Interoception¶
The affective special case of the Surfacer: live affect state rendered up into a felt-sense thought
("something's off"). It is graph-blind and pre-causal by design — it renders the state and never
looks up why, because attribution is Integration's conscious work and may honestly be wrong.
docs/systems/alto-affect-routing.md. Designed; no code.
Trap: it is the missing bridge between the Subconscious and the Surfacer, which is part of why
those two organs blur together today.
Intrusion (thought)¶
A thought that arrives unbidden — memory doing something to Alto rather than Alto querying. The
Surfacer emits one thought string per call, which reaches Integration by being appended to the
rolling turn buffer as an assistant-role event (context.record_thought,
src/alto/runtime/context.py), never as a field in a prompt.
Trap: when it lands has two answers. The persisted buffer is next-turn (context.record flushes
pending thoughts after the turn's own events). A second ephemeral seam, pending_thoughts() +
with_surfaced_thoughts (src/alto/runtime/alto.py:243), appends to the in-flight call's history,
so a thought rendering inside the 10s surfacer wait grounds the very turn that produced it. Check
the consumer's accessor, not the wait. The event stream has no intrusion kind; a surfaced thought
is a thought event.
L0¶
The testimony layer in alto_mem — the raw record of what was said. It is the only precious
layer: every derived layer is a pure function of L0 and is rebuildable, so the build discipline
protects L0 and nothing else (src/mem/__init__.py).
L0 / L1¶
The two named layers in alto_mem. L0 is episode + segment — testimony, what was
actually said. L1 is surface, line and mention — what a model extracted from it.
Episode-close artefacts (binding, cooccurrence) and the projection sit below both. Headers
are in src/mem/schema.sql:23, :103, :235.
line¶
One claim step ⑤'s 14B extracted from a segment, in plain English, with a modality, an
optional anchored span back into the segment text, a fidelity label, a polarity and its
content_tokens. src/mem/schema.sql:179-212.
Trap: a line carries text and modality only — no subject, no predicate, no relation
word. The line table has no relation column; the nine-predicate allowlist belonged to the
archived AGE-graph relation organ. Also: there is no unique index, deliberately. TX2
deletes by (segment_id, prompt_ver) and reinserts, because no key over model-produced content
converges on replay — a non-deterministic 14B returns slightly different text, ordinal moves
if the count changes, a text hash inserts the near-duplicate as a new row, and keying on the
span collapses two real claims that share a clause, which ⑤ produces by design.
live recorder¶
The concurrent, off-the-hot-path half of the Writer: records that an episode is happening,
stamps its date, captures what was perceived, computes that episode's immediate valence. Live
so recent memory does not lag experience. Today the recorder is mem, fed by
src/alto/read/mem_bridge.py (observe_user_utterance, observe_turn_complete), and it is
on (mem.enabled); it records testimony and computes no valence. The other timescale is the
consolidator.
Trap: "live recorder" and "live test" and "live brain" share a word and share nothing
else.
live tests¶
Tests marked @pytest.mark.live because they need Postgres. pyproject.toml sets
addopts = "-q -m 'not live'", so a bare pytest — the one CI runs — deselects every test
that touches the database.
Trap: a green CI badge is evidence about ruff and the pure-function layer, and about nothing
else. Every transactional property in the writer — the watermark discipline, TX2's
delete-and-reinsert, TX3, the episode-close readiness gate, the spool drain's store semantics —
is proven on one machine and nowhere else. Whole mem test modules carry a module-level
pytestmark and are entirely absent from CI. A change under src/mem/ that touches the store
is not done until pytest -m live has been run locally and its result stated. Read the current
counts off pytest's own summary line, never off a doc.
LoRA¶
A small trained adapter over the shared base (Qwen2.5). The runtime is one or two resident base
models plus swappable adapters at the transform boundaries, not one full model per organ. Training
is an episodic cost; inference stays local. Shipped adapters: alto-integration-v6 (the
conversational model, config.yaml:85). alto-intake-v1 was served until 2026-10-04, when the
intake organ was deleted; its files are kept, unserved (config.yaml:92-95).
Trap: alto-surfacer-14b is not a fine-tune — it is a re-tag of stock Qwen-14B with no
adapter. No surfacer fine-tune has ever been trained. Never credit a result to "the surfacer
fine-tune."
Marker spans (¦ and ¤)¶
The code's name for the commitment characters — see that entry, which is the primary one.
markers.py is a three-state streaming machine with recovery transitions, so a malformed reply
still produces something. integration.marker_filter is true as shipped (config.yaml:240) and
defaults to false in code.
Trap: marker_filter must be false if you point ollama.model at a stock non-LoRA model.
The filter starts in the discard state, so a model that emits no ¦ produces zero speech and Alto
goes completely silent — a config mismatch that looks like a broken pipeline.
measure-don't-assert¶
The habit of producing the number rather than reasoning to it. Pillar 7's shorthand
(CLAUDE.md, PILLARS.md); named at the code site in
src/config.yaml:358, where mem.read.top_n carries the sweep behind its value and its conditions.
Trap: the canonical instance is arithmetic wearing a measurement's clothes — "a 3-candidate
turn lands near 15s" blocked an organ for weeks; measured, it was max one verifier call per turn
at 1.1–2.2s wall (docs/CHECKS-measurement.md:106-109). If the verb is "computed" rather than
"observed", it is an estimate; label it one.
mem¶
The writer's own store: the src/mem/ package (its own __init__.py map) plus the alto_mem
database. Built against SPEC-writer-build_14. It turns what was said into testimony and then
into retrievable statements, and it is explicitly not the consolidator — nothing in it
promotes a belief, merges a referent or summarises an episode.
Trap: the old shorthand "shadow mode, write side only" is out of date. mem.read.enabled went
true on 2026-09-22 (src/config.yaml:331), and src/alto/read/mem_bridge.py — the only
module in alto/ that imports mem, enforced by docs_check — records each heard utterance and
finished turn into mem and builds the two read providers for the Surfacer: its store
(MemSurfacerStore, build_surfacer_store) and MemRecall (build_surfacer_recall). What mem writes can reach a reply.
The enricher is a separate matter: mem.enrich ships false, so lines are derived only when
someone runs the enrichment batch.
mem / alto_mem¶
The Writer's own store — a separate Postgres database and the package under src/mem/, built to
SPEC-writer-build_14. It is the only memory store and the only recorder; the AGE graph in alto_dev
is archived. The only module in alto/ that imports it is src/alto/read/mem_bridge.py, which is
how "nothing else reaches into mem" is enforced rather than asserted.
Trap: older documents call it write-only in shadow mode. That stopped being true on 2026-09-22 —
see the entry for mem.
mention¶
Two things, one word. In alto_mem, a mention row links a segment (and usually a line) to a
surface (src/mem/schema.sql:214). In the archived AGE graph, a mentions edge linked an
episode to an entity.
Trap: the AGE mentions edge had no writer after the writer-resolver's LLM half was deleted
(2026-10-04), so documents describing the reader or the idle tick starving for mention edges
describe the archived graph. The mem table is unaffected and keeps filling.
Mention edge¶
The AGE-graph edge that said this episode mentioned this entity, the payload the read side ran on:
hop-1 was the episodes that mention a thing, hop-2 the other entities those episodes mention.
Archived at tag archive/age-brain-2026-10-11; the mem equivalent is the mention table.
Trap: its only writer, the resolver's LLM half, was deleted 2026-10-04, so the reader returned
nothing and the idle tick found nothing to spread. That was one starvation, not three bugs.
Modality¶
Intake's grammatical classification of an utterance. The code enum is five closed values —
stated, asked, command, observed, expressed. Since intake was deleted
(2026-10-04) nothing live assigns one, and nothing replaced it: the grammar-rule features that
briefly stood in for it (is_question / is_asking / is_pure_question) were removed in
October 2026, so no organ gates on what kind of utterance it heard. Promoting or demoting between modalities was classification, not inference.
Trap: docs/README.md (and the onboarding intake page quoting it) describes modality as
"stated vs fact". "fact" is not a modality value in the code and never has been. Read the
enum, not the prose. Separately, observed → stated is the documented prompt-resistant "modality
wall" the intake LoRA was trained to break.
mood-blind¶
The Writer's firewall: it reads graph-affect freely — prior valences, standing affect,
because computing an episode's valence is its job — but never takes the live subconscious
mood as an input to what it records. The rule is architecture-revisions §3. The module that
carried it is archived at tag archive/age-brain-2026-10-11; mem records testimony and takes
no mood input.
Trap: it is current-mood-blindness, not affect-neutrality. Alto irritated now does not get
to bend the facts; Alto computing that an episode felt bad is the organ working. The subconscious
legitimately gates whether and how much is worth writing; the Writer alone controls what.
Observatory¶
A window over the session event stream: one process on one port (service.observatory, off by
default) that tails runtime/<session>.jsonl, the ordered record of what a session did — heard,
percept, thought, speech, action, turn_end — each with a monotonic seq. It exists
because the older logs could only be re-ordered by joining on the thought's text.
src/alto/runtime/observe/eventstream.py.
Trap: turn: null is not a missing value; it means the event happened between turns, such as
a thought that landed after its own turn closed. The stream does not replace the forensic logs —
they keep the large prompt payloads.
Organ¶
The unit of architecture here: one narrow job, one band, one place in the map. The organ language is
a deliberate cognitive-architecture analogy, not decoration — but the canonical list is
THE-ORGANS.md, and an organ is not the same as a module.
Trap: "built" on an organ page usually means "built and switched off." Much of the system exists
behind a config flag that ships false; check the flags named on the page rather than inferring
liveness from a module's existence.
Percept¶
In the design, what perception emits per utterance and fans out in parallel to three peers that do
not gate each other — the Subconscious (to feel), Integration (to attend), and the Writer's live
recorder (to persist). Today it is a Heard (see GroundedPercept for the intake-era type); the
event stream still calls its record percept.
Trap: the fan-out is serial today. Alto._perceive runs inline between STT and the
conversational LLM and takes one completed utterance — the hard batch boundary the design rules
out. Two of the three designed consumers are unbuilt, so parallelising it now would buy latency,
not the twitch path.
Perception¶
The only organ that touches the physical world, and deliberately the stupidest: it converts signal to
raw symbols and knows nothing else. Not what an entity is, not that a graph exists, not that Alto
exists. audio.py and stt.py turn sound into text; src/alto/perception/ wraps the transcript in
a Heard (the raw utterance, its speaker and when it was heard), with no model call and no
interpretation.
Trap: the designed perception envelope — {modality, content, confidence, timestamp,
metadata}, uniform across senses — does not exist in code. transcribe returns a bare str and
Whisper's info object is discarded. The interface is missing, not just the extra modules.
picture / the episode-close picture pass¶
The decided replacement for the per-turn LLM cold path: instead of resolving entities turn by
turn, read the whole episode once at close and produce a picture of it. Recorded as a decision
in src/config.yaml (2026-08-15) and shaped by
docs/specs/v3/SPEC-episode-account.md after
docs/specs/v3/DECISION-picture-shape-and-felt-state.md found the claim/triple form wrong.
Trap: the picture is a set of per-referent accounts, not a list of claims. The triple
form failed on things a better binder cannot rescue — an exclusion ("Not the bright ones")
became an entity, a claim got built on the wrong nucleus, and a comparative stance had no slot
at all. The AGE-era write-side passes that implemented it are archived at tag
archive/age-brain-2026-10-11; the design stands and nothing builds it on mem yet.
Pillar¶
One of the nine numbered commitments in CLAUDE.md, explained in PILLARS.md. A
design that violates a pillar is wrong even if it passes tests; surface the conflict rather than
shipping around it.
Trap: the numbers are an interface — code cites pillar 9 and pillar 3 by number in module
docstrings, 62 citations in all. Never renumber them; a retired pillar leaves a tombstone.
polarity¶
The sign of a claim: '+', '-', or NULL for undecidable. One implementation, sign() in
src/mem/polarity.py, which delegates to _assertion_polarity in the same file (moved there
from the deleted relation organ, 2026-10-05) rather than restating it.
Trap: a span holding both a clause boundary and a negator returns None, because which
clause a negator scopes is not something a regex can decide (measured: 2 of 20 edges written
with an inverted sign). The two organs diverged deliberately — the deleted relator dropped the
proposal, because an edge with a guessed sign says the opposite of the utterance and leaves
nothing to revise; mem stores polarity = NULL and keeps the line, because the line
carries its own text and dropping would discard testimony to protect a label.
preflight¶
python src/scripts/agent_lease.py preflight --agent <label> — run before any sim, eval or
DB-backed run, with its table pasted into the run log. It resolves the database name and where
it came from (resolve_db_provenance, src/scripts/agent_lease.py:302).
Trap: the row that matters is db.OVERRIDE (src/scripts/agent_lease.py:351) — it means ALTO_MEM_DB_NAME
is silently redirecting the run, which has already happened once and invalidated a launch. A
discipline that depends on remembering to run a command is one that gets skipped on the run that
mattered, which is why SpikeRun.start() does it for you.
probe¶
An exploratory harness that measures something without a pass/fail verdict. Named *_probe.py
by convention, never test_*.py, for the same collection reason as an eval.
Trap: probes are where the measurement failures in docs/CHECKS-measurement.md cluster,
because a probe is exactly the thing that quietly differs from production. Every probe passed
gate=None, so the resolver's idle gate had never been exercised by any measurement (#167); one
constructed intake directly instead of through _build_intake_client and measured the stock 3B
while production served a LoRA (#159); the relator probe force-enabled the flag it was testing, so
no probe run could prove the config path. Name the production seam and confirm the harness goes
through it.
Processing¶
The organ Alto uses to work something out: Integration hands a problem down, waits, and gets a
conclusion back — never a transcript of a subordinate model's reasoning, which is what keeps the
conscious-locus frame intact. Anything durable it discovers is designed to re-enter through Intake (deleted in code; see Intake), tagged
inherited so provenance survives. Build order Stage 6.
Trap: only the web_search seam exists, and it is not wired — the tool is never registered, so
the model is never told it exists. Nothing about Processing is measured because nothing about it
runs; treat any number in this repo about "processing" as being about something else.
producer¶
The stamp recording which organ wrote a given edge or segment. Shipped on
writer/producer-provenance; also a NOT NULL column on segment (src/mem/schema.sql:78).
Trap: it exists because a log counter counts attempts per organ and cannot attribute a
surviving edge. When the stamp landed it reversed an inference recorded the same day: the
counters said most relations came from the deterministic detectors, the stamp said all five
relation edges across 150 episodes came from the LLM arm — which is off in production
(docs/specs/v3/PLAN-writer-v2.md:77-98).
projection¶
src/mem/projection.py — §17's whole-store read that computes every corpus-derived number
(degree, conductance, content weight) and writes nothing. Reads only, never raises.
Trap: it is a whole-store rebuild, not incremental, for the same reason as TX3 — an
incremental projection needs exactly the reconciliation this design keeps deleting. On any
failure it keeps the previous generation and counts it: a stale snapshot is a correct snapshot
of an earlier moment, a partial one is not a snapshot of anything.
Reader (L3)¶
A client of the shared read layer that, given a cue, gathered the typed neighbourhood, scored each
candidate fact and returned a ranked FactRecord list, rendered as a [What Alto knows about X]
block into Integration's context. It shipped dark (integration.reader_enabled: false) and was
removed 2026-10-01: the Surfacer is the only channel by which memory reaches a reply (pillar 5).
Trap: older docs, specs and handoffs still cite reader.py, what_alto_knows and the block as
current — they are dated records. "Reader" in mem/ (mem.read, the belief reader) is a different
thing and is live.
referent_class¶
How a surface's identity is scoped: referential (a name — unique globally), episode_local (a
generic definite like "the car" — unique only within its episode), or deictic.
src/mem/schema.sql:105-129.
Trap: the key is conditional, so it takes two partial unique indexes that cannot be
merged (ON CONFLICT must name one index). And the original rule that an episode_local
surface is never cue-matchable was replaced by "matchable, returned grouped by episode"
(decision D-B, 2026-08-20) — 57% of real intake candidates land in episode_local, and 31% of
those carry a norm that recurs across episodes. knowledge() returning several episodes' worth
of "the PR" is a correct result; the episode stamp is what makes it safe.
Registry¶
The device registry in config.yaml (entities:) — the source of truth the guard trusts over the
model. DeviceRegistry.resolve accepts an exact id, an alias, a friendly name or a bare object id,
and returns None otherwise, which ends the call.
Trap: "the executor proposes, the registry disposes." A new capability is added by extending the
registry, never by trusting the model's entity_id.
relation extractor¶
Deleted 2026-10-04 (writer_relation_extractor.py, off since 2026-08-15). It proposed typed
relation edges between entities from an encyclopedic predicate allowlist, and could not write
without the entity nodes only the resolver's LLM half minted.
Trap: in its old measurements, a preferences corpus produced 0 proposals and the organ was
fine — its allowlist was encyclopedic (docs/CHECKS-measurement.md:57-59). A zero there is
ambiguous between "did not happen" and "could not happen".
relator¶
Deleted 2026-10-05 (writer_relator.py, OpenSpec change remove-grammar-rules; its LLM arm went
earlier the same day). It wrote typed edges and attributes to the AGE graph from English phrase
detectors: "I like/hate X" preferences, own and third-party birthdays, "you work for me". Nothing on
the normal path read them; stated facts now reach memory only as mem lines, which step 5 writes
and mem.enrich is off, so until a batch runs a stated fact exists only as raw testimony.
Trap: it was promoted on a 0-fabrication gate, but the detectors wrote almost nothing across 150
stamped episodes, and a 0-fabrication rate over 0 writes is trivially satisfied
(docs/specs/v3/PLAN-writer-v2.md:88-94). Its negation-scope helper lives on in
src/mem/polarity.py.
Renderer (the organ) / Voice¶
The thing that talks, and today a shell: Integration writes the words and marks the speech, and the
Renderer picks those spans up — marker filter, sentence chunking, TTS — and says them. The design
was larger: bundle plus steering in, speech out, with four commitments that make it honest rather
than good — stateless (a renderer that remembered would be a second mind), unable to fake interior
(delete the bundle and there is nothing to render), affect arriving as a dimensional value, never a
named feeling (energy: 0.2, not "tired", because knowing the name is what makes a model perform
the name), and affect reaching it only by twitch and steering, never as content. The owner has set that
design aside (2026-09-30) until there is a tone organ to need it.
Trap: "renderer" is heavily overloaded. Three layers were once all called renderer, and only this
one kept the word. The Surfacer's render step (render_verified.py) is a different thing. The
absence renderer is a third. And today's Renderer is collapsed into the
same model that does Integration's reasoning, so it is not stateless in the designed sense — a
choice now, not a gap, because the organ the design described is not being built.
repairability over precision¶
Pillar 9. Alto misunderstanding is not the failure; being unable to revise that understanding is. Bias toward capture: an imperfect edge that can later be corrected beats a missing one, and a precision gate that DROPS rather than records is the anti-pattern. Measured trigger: 730 simulated episodes → 953 mentions, 0 relations; a blind gold standard → 0 of ~30 durable facts captured. Trap: the line it does not cross. This licenses imperfect capture of what was actually said. It never licenses inventing what was not — that is pillar 3, a different failure. "Heard it and filed it imperfectly" is fine; "never heard it and asserted it" is the enemy. And it applies to the write side only; do not use it to relax the surfacer's fabrication guards, because a false memory Alto narrates is far harder to correct than a wrong edge in a graph.
resolver¶
Two organs shared the job title. writer_resolver.py is deleted: its entity-binding LLM half
on 2026-10-04 with its resolver_enabled flag, its eager self-schema learners (self name,
speaker name, self-type, creation event, the addressed edge) on 2026-10-05. mem's Ⓐ
(src/mem/corefer.py) binds pronouns to surfaces at episode close, writing binding rows.
Trap: nothing writes entity identity or self-schema to a graph any more. Alto's name comes from
src/mem/selfname.py. Separately, PLAN-writer-v2 replaces the LLM's identity adjudication entirely
with a deterministic canonical → alias → create-new cascade; the type gates (now name_gates and
siblings under src/mem/) and their tests are v2's acceptance suite, which turns "rebuild" into
"port".
retraction¶
A table in alto_mem marking a line as withdrawn, with a reason, a by_whom and a timestamp.
Empty in this build — no UI produces one — but present from day one and respected by every
read path (src/mem/schema.sql:293-303).
Trap: it looks like dead code and is not. It is the substrate a correction mechanism stands
on, which is pillar 9's actual unblock. Deleting it because nothing writes to it removes the
only thing that makes a later correction possible.
Salience¶
What deserves to be present. In the design it is a signal the Subconscious emits — "this mattered,
this is charged enough to bubble up" — which the Surfacer turns into a sentence. The salience render
that did this un-cued, from the idle tick, is archived at tag archive/age-brain-2026-10-11; the
roadmap rebuilds it on mem.
Trap: the Subconscious never emitted a live salience signal. The archived tick seeded from
charged episode nodes in the graph, not from a resolved affect state. mem has separate
salience gates (worth_extracting, retrievable, src/mem/salience.py) that decide what is
worth keeping; they are a different thing.
segment¶
One utterance in alto_mem's L0: un-prefixed text, an axis (speaker | alto_reply |
alto_thought | action | external), a speaker column, a producer-supplied occurred_at, and an
opaque structured record that is None on new segments
(src/alto/read/mem_bridge.py:219) and holds intake's percept on older ones.
src/mem/schema.sql:71-93.
Trap: speaker is a column, never part of text — a prefixed utterance is a bug, which
is why strip_speaker_prefix is part of the public API. occurred_at is producer-supplied and
never clock-read, while line.created_at is extraction time and never event time. And
segment here is not the same word as the picture pass's segments, which are the units of an
episode walk and assume nothing about a segment being a turn.
Shadow mode¶
Built, running, and writing — with nothing reading the output. mem was the example until
2026-09-22, when its read path went on.
Shared read / cache layer¶
One in-memory mirror of the graph, designed as first-class infrastructure with peer clients —
the Subconscious, the Writer (recorder and consolidator), and later dreaming. Integration's
retrieval, in the original design, is struck: Integration is not a client. Explicitly shared read
infrastructure, not co-located components, because their query profiles differ.
Trap: it does not exist as code. The AGE-era graph_cache and reader_cache, which had one
client (the idle tick), are archived at tag archive/age-brain-2026-10-11. mem.read is a
separate read path and does not read through this layer.
sim¶
A simulated conversation run — many synthetic episodes pushed through the real organs to measure what the write side captures. The measured triggers behind pillar 9 (730 episodes → 0 relations) came from one. Trap: sim content must be authored blind — natural speech, never written to match a detector's markers. Misses are the signal. Also, every write-side measurement to date ran on a corpus of one utterance per episode, so no sim in the record tests cross-turn assembly, and ⑤'s lines are not reproducible run to run (18 of 507 segments differ across two builds on the same 12 episodes) — read any harness delta against that noise floor.
SpikeRun¶
testkit.spikes.SpikeRun.start(label, agent=...) — creates the run directory and writes
preflight.txt and manifest.json (with a top-level db_override flag) into it before the
caller does any work, reusing agent_lease.build_preflight rather than a second copy of the
logic. src/testkit/spikes.py.
Trap: it deliberately does not wrap load_config or OllamaClient. Hiding which model
a spike used behind a helper is the opposite of what docs/CHECKS-measurement.md asks for.
spool¶
The JSONL file a writer appends to when the database is unreachable, so the turn still succeeds
and the pipeline never fails because the DB is down. Drains on the next append, replaying events
in order with their original timestamps so a gap that elapsed during downtime still rotates the
episode correctly. mem spools to ~/.alto/mem_spool.jsonl
(DEFAULT_SPOOL_PATH, src/mem/api.py:76; replay in drain, src/mem/api.py:357).
Trap: older documents name ~/.alto/intake_spool.jsonl, the archived AGE writer's spool, kept
from when that module was called alto.intake. No live code writes it.
spread / spreading activation¶
Conductance-weighted activation pushed outward from seed nodes, where each node splits its decayed
budget across its out-edges in proportion to conductance. The AGE-graph implementation
(spread, over GraphCache) is archived at tag archive/age-brain-2026-10-11; the roadmap
rebuilds it on mem. See Spreading activation for the design.
Trap: spread is pillar 5's substrate and the reader is explicitly the other thing.
Conflating them is how a search box with a personality gets built. Also, the honesty gate is
structural: only grounded (and structurally-provenanced) edges conduct, so a node reachable
only through an inferred, dreamed or quarantined edge cannot become present at all.
Spreading activation¶
The substrate pillar 5 names: activation flows outward from seed nodes, each node splitting its
outgoing activation across its edges in proportion to each edge's conductance, so an is_a
backbone edge transmits more than a weak co-occurrence edge. Bounded for a hot path (hop cap,
frontier cap, activation floor). Designed, and not running: no spread runs today, and the roadmap
rebuilds it on mem.
Trap: spreading activation existing is not pillar 5 being built. What is missing is the
endogenous source — something that generates activation continuously, independent of any query.
Steering / valence steering¶
Affect reaching cognition as a bias on activations rather than as content a model reads: a control vector added to the residual stream, so it moves the option space without ever being performable. Integration is moved and informed (steering plus an interoceptive thought, because it reasons); in the design the Renderer is only moved (steering, because it does not reason); the Renderer is a shell now, and the steering that is built acts on Integration's own generation. Trap: built and measured but not connected. Pillar 2 calls valence steering "only the renderer half" of affect — and even that half is unwired.
subconscious (the adjective)¶
Below the conscious line. Pillar 5 says "surfacing is subconscious and activation-driven" — meaning involuntary and below awareness, not "produced by the Subconscious organ." Trap: this is the sharpest word collision in the corpus. The Surfacer is subconscious machinery without being the Subconscious, and an earlier diagram encouraged the conflation by drawing the Subconscious as the Surfacer's only input. They are near-opposites: the Subconscious is continuous, graph-forbidden, never reasons, and outputs numbers; the Surfacer is per-event, holds a store handle, runs a model, and outputs first-person language.
Subconscious (the organ)¶
Alto's endogenous state — mood, drive, felt duration, anticipation, energy — maintained on its own
clock whether or not anyone is talking. It maintains and signals; it never reasons, decides,
routes, or queries the graph. Graph access is forbidden by design, because reading the graph means
resolving entities and deciding relevance, which would smuggle a second conscious layer in through
the data-access door.
Trap: nothing is this loop today. The state-decay tick that stood in for it — one facet of
eight, two axes of four, no triggers — is archived at tag archive/age-brain-2026-10-11. The organ
is designed, and the roadmap rebuilds its affect state on mem.
surface¶
A row in alto_mem for one way of referring to something: a normalised key, the raw text as
said, a referent_class and an optional episode scope (src/mem/schema.sql:111). Two singleton
surfaces — __self__ and __speaker__ — are minted at schema init with first_seen_at = 0,
because they precede all testimony; before those rows existed, 97 of 163 pronoun occurrences on
the first live episode resolved with certainty and bound to NULL.
Trap: step ④ mints but never merges. Exact key match resolves; anything else creates
new, because false-merge is catastrophic-silent-permanent and false-new is
cheap-visible-recoverable. Related trap: "surface" the noun and "surfacing" the pillar-5 verb
are unrelated. A surface is a string in a table; surfacing is an involuntary intrusion from the
subconscious.
Surfacer¶
The upward transducer at the conscious boundary: sub-symbolic state — an activated memory, a felt
state, an anticipation — rendered into a first-person thought that arrives in Integration as
Integration's own. It exists so memory reaches the thinking layer in the medium a mind works in, a
thought, rather than the medium storage uses, a record; a mind that can watch its own retrieval is
not remembering, it is reading a briefing. One transducer, three sources.
src/alto/read/surfacing/surfacer.py; it reads mem only.
The guardrail: it renders form, never content. A record → "I remember arguing with Brendan in
March" is translation; the same record → "that awful fight where he was so unfair" invents the
framing. A false memory smeared onto a true record is worse than the record ever was.
Trap: the organ never raises — safe_call degrades any substrate error to None, and
build_surfacer returns a _NoopSurfacer whenever Ollama, the store or the self-node is
unavailable, so the pipeline can call it unconditionally. A fresh clone with no database gets the
Noop, silently and by design.
Surfacing (vs retrieval)¶
Pillar 5, and the distinction a newcomer will assume away. Surfacing is an involuntary intrusion
from below — the subconscious feels a percept, activation crosses a threshold, and Integration finds
itself thinking of something it did not ask for. Retrieval is what a reader does: deliberate,
directed, in service of a question. If Alto only ever surfaces what something asked for, there is no
interior; there is a search box with a personality.
Trap: "what surfaced" ≠ "what a reader retrieved." Directed recall does survive — but as an
intention to remember, serviced by invisible machinery, never as Integration calling a database.
Keep that or the database sneaks back into consciousness through the "it can choose to retrieve"
door. Building a retrieval call and naming it surfacing is the named failure mode — and is close to
what ships: Surfacer.surface_from_heard matches the entities the raw utterance names and renders
their neighbourhoods, and offers only a self-absence render when it names nothing the store holds.
Testimony¶
Something someone actually said, and the only thing identity may be built from. The self and the
first speaker accrete name, creator and type through testimony, each fact traceable to the moment it
was said (pillar 4). In mem, L0 is the testimony layer and the only precious one.
Trap: pillar 9 licenses imperfect capture of what was actually said; it never licenses
inventing what was not. "Heard it and filed it imperfectly" is fine; "never heard it and asserted it"
is pillar 3 and a different failure.
testimony¶
What was actually said, recorded verbatim and attributed. L0 in alto_mem is testimony and
nothing else. It is also the mechanism of identity: the self and the first speaker accrete names
and facts by being told, never by being configured or trained.
Trap: this is the word that separates pillar 9 from pillar 3. Filing testimony imperfectly
is acceptable. Asserting something no testimony contains is not, whatever confidence the model
reports.
The aux model¶
One shared small non-LoRA handle — ollama.aux_model, today qwen2.5:3b-instruct
(src/config.yaml:86) — used by the surfacer's entity, belief and salience renders for format=-constrained JSON calls. It must co-reside in VRAM with the 14B
conversational model, which is why it is a 3B.
Trap: it is a shared slot, so pointing it at any specialised model corrupts every sibling's
JSON call. That is why the intake LoRA had its own intake_model handle until intake was deleted
on 2026-10-04 — and that third resident model was a measured cost, not a free one (intake ~820ms →
~2.7s warm).
The brain¶
Three different things wear this word. (1) In docs/alto-four-organ-architecture.md, the brain
is the stateful self — graph plus affect plus integration plus continuity — with LLMs quarantined
to the edges as transducers. (2) The live brain is the hot tier of the shared read cache, over a
deep store that is complete but quiet (docs/README.md). (3) The project brain — V1 Track A,
a typed Postgres layer of projects and blockers, with the get_projects voice tool — is archived at
tag archive/age-brain-2026-10-11.
Trap: "the brain DB" in practice meant the Postgres database alto_dev, now archived, not the
mem store.
The four organs¶
This phrase names at least three different sets, and which one is meant depends entirely on the
document. (1) docs/alto-four-organ-architecture.md — Intake · Brain · Processing · Voice
(Renderer): LLMs quarantined to the edges around a stateful self. (2)
docs/roadmap/alto-build-order-v2.md:17 — Intake → Integration layer → Processing → Renderer:
the same shape with the integration layer in the brain's slot. (3) docs/ALTO-PROJECT-BRIEF.md §3 —
Writer · Reader · Surfacer · Integration: the four organs that actually exist in code over the
graph. docs/perception/alto-perception-layer.md:202 then extends the list to five by putting
Perception in front, and docs/README.md states the "four organs" headline is superseded by the
ingestion-path / conscious-locus structure, keeping organ language as a compatible lens.
Trap: THE-ORGANS.md lists eleven. If a doc says "the four organs" without
naming them, check which set it means before mapping it onto anything.
the gate (Definition of Done)¶
The five-step quality gate in CLAUDE.md: ruff clean; tests/test_alto_v0.py and pytest
both pass; pytest -m live; docs_check.py; and exercise the real pipeline path. Plus the five
measurement questions in docs/CHECKS-measurement.md before quoting any number.
Trap: "gate" is overloaded in this repo. It also means the named type gates (_looks_like_*,
in name_gates / phrase_gates / value_gates under src/mem/), mem's two salience gates
(worth_extracting before ⑤, retrievable at read), and a spec's hard gate (an eval that must
pass before a capability ships). Nothing but context disambiguates them.
Trap: step 4 is the scratch-database live smoke (src/scripts/live_smoke.py). It supplies
no HA token, so it does not exercise HA dispatch; use a real HA turn when the change touches
tool-calling.
The guard¶
validate_tool_call (src/alto/action/ha.py:147) — the deterministic safety boundary. It takes a proposed device
call, throws away most of what the model said, resolves the entity against the registry and checks
the service against the allowlist, and returns a validated tuple or None. The load-bearing line is
src/alto/action/ha.py:153: domain = registry.domain_of(canonical) — the model's domain argument is
discarded, not checked. validate_state_query (src/alto/action/ha.py:168) is the read-only sibling; web.py's
validate_search_query is the outbound sibling, guarding what may leave rather than what may act.
There is exactly one call_service call site (src/alto/action/ha.py:294, called at src/alto/action/tool_dispatch.py:185).
Trap: the guard is complete, correct — and currently uncalled. The conversational model has no
tools, so say "turn on the lights" today and Alto talks about it rather than doing it. This is the
first thing to check before debugging anything device-shaped. Described on the Action organ page,
organs/action.md.
The payload layer¶
Shorthand for the write-side output the read side needs — mention edges, typed relations, entity
neighbourhoods. When an organ page says the payload layer is "dark", it means the producers are off,
not that the consumer is broken. Fix it and several apparently independent organs light up at once,
which is also why measuring any of them in isolation tells you very little. On mem the payload is
derived lines, bindings and co-occurrence, and mem.enrich ships off.
the precious layer¶
L0 — episode and segment — and nothing else. It is the only thing in alto_mem that cannot
be recomputed, so it is the only thing that must never be destroyed
(src/mem/schema.sql:10-15).
Trap: this is what buys TX2 the right to DELETE a segment's lines and reinsert them rather
than reconcile them (each replaced row is archived to line_history first, since 2026-09-14), and what makes a prompt change a --rewind plus one batch pass instead of
a migration. Neither salience gate ever touches L0; a skip is recorded with its reason and the
read path filters.
The read side¶
Everything on the far side of the Writer: the Surfacer and the mem read path it uses, with
spreading activation and the other between-turn organs designed but not running. Contrast the
write side (what perception heard, turned into durable structure). The distinction matters for
pillar 9, which licenses generous capture on the write side and explicitly does not relax the
Surfacer's fabrication guards on the read side.
The self-node¶
Alto's identity as a node rather than a persona in a prompt. In mem it is the __self__
singleton surface, minted at schema init, and MemSurfacerStore.get_self_node
(src/mem/surfacer_store.py:264) hands it to the Surfacer as its POV anchor; the Surfacer refuses
to construct without one. Its name is never stored: src/mem/selfname.py derives it from testimony.
Learned facts were attached in the archived AGE graph as separate attribute nodes under five typed
slots (identity, architecture, belief, norm, preference); nothing writes them now.
Trap: the self may be seeded bare because it is constitutive; the speaker may not, because
asserting a user exists before anyone has spoken is an unearned claim. __speaker__ is likewise a
nameless referent that earns its name by testimony, so every fact attached while nameless stays
attached.
the self-node¶
The self as a graph node that boots empty — Alto does not know its own name until told — and
accretes name, creator and type through testimony, each fact traceable to the moment it was said
(pillar 4). Today that is the __self__ surface in mem; the AGE kind:'self' node and its
self_attr nodes are archived at tag archive/age-brain-2026-10-11.
Trap: it is the replacement for a system prompt, not a competitor to one — the
conversational call has an empty system prompt by design, so identity reaches behaviour through
the Surfacer's POV anchor or not at all. Alto's name comes from src/mem/selfname.py, which
derives it from testimony and stores nothing — a mem.self_name config key would be the trained
self-description pillar 4 rules out, just filed somewhere that looks like ops.
The spool¶
The recorder's DB-down safety net: if a store call raises, the event is written to JSONL and the
turn still succeeds, so the pipeline never fails because the database is down. See spool; the
file is ~/.alto/mem_spool.jsonl.
The write side¶
Everything that turns what was heard into durable structure — mem, fed by
src/alto/read/mem_bridge.py (intake, the resolver's LLM half and the extractors were deleted on
2026-10-04; the resolver's learners and the relator on 2026-10-05; the AGE-graph writer was
archived with the graph). Governed by pillar 9: bias toward capture, because an
imperfect edge that can later be corrected beats a missing one, and a precision gate that DROPS
rather than records is the anti-pattern.
Trap: the line pillar 9 does not cross is on this side too. An inverted relation sign is not an
imprecise capture — it says the opposite of the utterance, so there is nothing to revise later. It is
a confident falsehood that looks exactly like a fact, and the relator's _assertion_polarity (now
src/mem/polarity.py) returned None rather than guess.
the writer¶
Three things, and the corpus uses all three.
- The Writer organ — the whole cold path that turns the now into the past: live recorder
plus consolidator (
organs/writer.md). In code today it issrc/alto/read/mem_bridge.pyandsrc/mem/. - The AGE-graph recorder — the module that did episode segmentation and the
kind:'episode'node write. It was namedalto.intakeuntil 2026-06-24, and is archived at tagarchive/age-brain-2026-10-11. mem's writer — SPEC-writer-build_14's subject, whichsrc/mem/__init__.pycalls "the recorder half of the cold path". Segments → lines, in its own database. Trap: "Writer v2" (docs/specs/v3/PLAN-writer-v2.md) means sense (1) minus (2): it replaces the resolver's identity adjudication and collapses the three extractors (all deleted on 2026-10-04 while v2 was still unbuilt), and states explicitly that intake and the writer/recorder are not touched. A doc predating 2026-06-24 that says "intake" almost certainly means (2).
tier¶
Edge provenance in the AGE graph design: grounded, inferred, dreamed, quarantined. The
spread's honesty gate reused the store's default-read tiers rather than defining a new set. Both are
archived at tag archive/age-brain-2026-10-11; the tiers survive as design in the specs.
Trap: unrelated to "memory tiers" (live brain / deep store) and to the self-node spec's
three payoff tiers. Same word, three scales.
Track A / Track B¶
Two parallel build tracks. Track A is organ-first construction (in V1, the project brain).
Track B is the validation track — harness, gating experiments, blind judges, medium-continuity
arc tests — and also the Claude Code integration. The project brain and the Claude Code integration
are both archived at tag archive/age-brain-2026-10-11. The development exit gate needs both
tracks. Per the judge-before-adapter rule, a Track-B judge is a prerequisite for the LoRA it
gates.
Transducer¶
A model confined to a narrow translation at an edge, never the seat of the self. The Surfacer and — in the design — the Renderer are the transducers (Intake was one until it was deleted on 2026-10-04); the point of quarantining them is that the self is sealed behind them and therefore cannot be a performance.
Twitch (the flinch)¶
The reflex route for affect: raw state straight to the Renderer, bypassing Integration, so a fast
reaction can fill the beat before deliberation finishes. One of three affect routes alongside
steering and the introspective felt-sense thought (docs/systems/alto-affect-routing.md; the timing
is alto-reaction-timing.md's "flinch and settle"). Designed; unbuilt, and with the Renderer a shell nothing is there to receive it.
Trap: the twitch path is why the designed Intake must fan out in parallel (today hear is serial and model-free) — a reflex has to be able to fire
before deliberation finishes, so a hard batch boundary at Intake contradicts it.
TX2 / TX3¶
The two write transactions in mem. TX2 commits one segment's enrichment — it archives that
segment's lines and their mentions to line_history and mention_history, deletes them by
(segment_id, prompt_ver), reinserts, and advances the watermark in the same commit. TX3
commits one closed episode's bindings and co-occurrence — archiving the ones it replaces to
binding_history and cooccurrence_history — and advances watermark_episode.
src/mem/commit.py.
Trap: delete-and-reinsert is the design, not a shortcut. It is what the precious-layer rule
buys, and it is why line has no unique index. Each mark advances only in the commit carrying
the writes it certifies, and the two never interact — except that the episode loop refuses to
certify an episode whose segments the segment loop has not reached. The archive shares the
transaction, so a failed TX2 archives nothing.
typer¶
Deleted 2026-10-04 (writer_typer.py, off since 2026-08-15). It assigned entity types (is_a)
and maintained entity co-occurrence, reading mentions edges only the resolver's LLM half wrote.
Trap: its shipped 88.9% precision covered 17 of 39 written edges; the other 22 were
unlabelled. That was never a number about the organ — it was a number about 44% of the data
(docs/CHECKS-measurement.md:88-91).
V0 / V1 / V3¶
Capability generations, not release versions. V0 is the local voice pipeline (shipped 2026-06-06); V1
is the project brain (archived) and the first organ separations; V3 holds consolidation, autonomous
research and the salience/subconscious specs. docs/roadmap/BUILD-ORDER.md is the status ledger;
alto-build-order-v3.md is the sequence of record.
Valence¶
How pleasant or unpleasant something felt, −1.0 to 1.0. It appears at three layers: as the affect atom stamped on a closed episode, as an axis of the designed live affect state, and as a steering control-vector axis. Only the steering axis runs today. Trap: valence steering being proven is not pillar 2 being satisfied. Steering is the renderer half; the pillar's test is whether state from an earlier turn still shapes a later one.
verifier¶
An LLM skeptic that reviews a proposed edge before it is written, kept deliberately in the Writer v2
plan (docs/specs/v3/PLAN-writer-v2.md:23). The module that did it is archived at tag
archive/age-brain-2026-10-11 with the AGE writer. Not to be confused with surfacing/verify,
which checks the Surfacer's own claims and is live.
Trap: the standard objection — "a validator shares the confabulator's failure mode" — does
not hold here, and the counterexample is named: the verifier caught Sacramento == Portland, a
fabricated identity edge that cleared every structural guard including the verbatim-span check
proposed as its replacement. Structural provenance catches "you said a word nobody uttered"; the
skeptic catches "every word is real and the claim is still false". Different classes.
watermark¶
A single-row high-water mark recording how far a loop has processed. There are two, and they
never interact: watermark.seg_id (segments, driven by the Enricher) and
watermark_episode.ep_id (closed episodes, driven by the EpisodeCloser).
src/mem/schema.sql:271-280.
Trap: the CHECK (only_row) idiom makes a second row impossible at the schema level, and the
watermark — not a process boundary — is the entire durability story. Kill the worker at any
instant and restarting is a no-op plus a replay of at most one segment. A real failure this
caused: close_episode, commit_episode and TX3 were built, tested and proven, and called only
from scripts — so on the live path watermark_episode never advanced, cooccurrence and
binding stayed empty, and projection.build produced every degree at 0. Four counters reading
a perfectly legal zero, one missing caller.
worktree¶
A separate git checkout under .claude/worktrees/<task>, given to any write-capable agent
alongside its own alto_agent_<slug> scratch DB. Read-only agents may share the main tree.
Trap: a worktree can be cut from a stale base (seen 30 commits behind), so give the exact
sha. A worktree also lacks the main tree's gitignored src/.env, so database-name and password
resolution differ inside it — which is exactly the ambient difference preflight exists to
print.
Writer¶
The organ that turns the now into the past: it takes a completed turn and persists it — episodes,
the entities mentioned, the relations and events those mentions imply — so a later moment can be
shaped by an earlier one. Everything Alto can ever remember arrives through here. It is a cold-path
sibling of the Subconscious, not nested under it and not attached to the designed Intake. Two
timescales: the live recorder (concurrent, immediate valence) and the consolidator (batched,
sleep-time). Today only the recorder half exists, as mem.
Trap (the firewall): it is current-mood-blind, not affect-neutral. It must read
graph-affect — computing an episode's valence is its job — but it never takes the live subconscious
mood as an input to what it records. Alto irritated now does not get to bend the facts. The
Subconscious may gate whether and how much is written; the Writer alone controls what.
Where to go next¶
| Question | Read |
|---|---|
| What are the parts, and how do they compose? | THE-ORGANS.md |
| Why is it built this way? | PILLARS.md |
If a term is missing, it is probably in an organ page under organs/ — each one defines the vocabulary local to it.