@animalabs/connectome-host 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +20 -0
- package/.github/workflows/publish.yml +65 -0
- package/ARCHITECTURE.md +355 -0
- package/CHANGELOG.md +30 -0
- package/HEADLESS-FLEET-PLAN.md +330 -0
- package/README.md +189 -0
- package/UNIFIED-TREE-PLAN.md +242 -0
- package/bun.lock +288 -0
- package/docs/AGENT-MEMORY-GUIDE.md +214 -0
- package/docs/AGENT-ONBOARDING.md +541 -0
- package/docs/ATTENTION-AND-GATING.md +120 -0
- package/docs/DEPLOYMENTS.md +130 -0
- package/docs/DEV-ENVIRONMENT.md +215 -0
- package/docs/LIBRARY-PIPELINE.md +286 -0
- package/docs/LOCUS-ROUTING-DESIGN.md +115 -0
- package/docs/claudeai-evacuation.md +228 -0
- package/docs/debug-context-api.md +208 -0
- package/docs/webui-deployment.md +219 -0
- package/package.json +33 -0
- package/recipes/SETUP.md +308 -0
- package/recipes/TRIUMVIRATE-SETUP.md +467 -0
- package/recipes/claude-export-revive.json +19 -0
- package/recipes/clerk.json +157 -0
- package/recipes/knowledge-miner.json +174 -0
- package/recipes/knowledge-reviewer.json +76 -0
- package/recipes/mcpl-editor-test.json +38 -0
- package/recipes/prompts/transplant-addendum.md +17 -0
- package/recipes/triumvirate.json +63 -0
- package/recipes/webui-fleet-test.json +27 -0
- package/recipes/webui-test.json +16 -0
- package/recipes/zulip-miner.json +87 -0
- package/scripts/connectome-doctor +373 -0
- package/scripts/evacuator.ts +956 -0
- package/scripts/import-claudeai-export.ts +747 -0
- package/scripts/lib/line-reader.ts +53 -0
- package/scripts/test-historical-thinking.ts +148 -0
- package/scripts/warmup-session.ts +336 -0
- package/src/agent-name.ts +58 -0
- package/src/commands.ts +1074 -0
- package/src/headless.ts +528 -0
- package/src/index.ts +867 -0
- package/src/logging-adapter.ts +208 -0
- package/src/mcpl-config.ts +199 -0
- package/src/modules/activity-module.ts +270 -0
- package/src/modules/channel-mode-module.ts +260 -0
- package/src/modules/fleet-module.ts +1705 -0
- package/src/modules/fleet-types.ts +225 -0
- package/src/modules/lessons-module.ts +465 -0
- package/src/modules/mcpl-admin-module.ts +345 -0
- package/src/modules/retrieval-module.ts +327 -0
- package/src/modules/settings-module.ts +143 -0
- package/src/modules/subagent-module.ts +2074 -0
- package/src/modules/subscription-gc-module.ts +322 -0
- package/src/modules/time-module.ts +85 -0
- package/src/modules/tui-module.ts +76 -0
- package/src/modules/web-ui-curve-page.ts +249 -0
- package/src/modules/web-ui-module.ts +2595 -0
- package/src/recipe.ts +1003 -0
- package/src/session-manager.ts +278 -0
- package/src/state/agent-tree-reducer.ts +431 -0
- package/src/state/fleet-tree-aggregator.ts +195 -0
- package/src/strategies/frontdesk-strategy.ts +364 -0
- package/src/synesthete.ts +68 -0
- package/src/tui.ts +2200 -0
- package/src/types/bun-ffi.d.ts +6 -0
- package/src/web/protocol.ts +648 -0
- package/test/agent-name.test.ts +62 -0
- package/test/agent-tree-fleet-launch.test.ts +64 -0
- package/test/agent-tree-reducer-parity.test.ts +194 -0
- package/test/agent-tree-reducer.test.ts +443 -0
- package/test/agent-tree-rollup.test.ts +109 -0
- package/test/autobio-progress-snapshot.test.ts +40 -0
- package/test/claudeai-export-importer.test.ts +386 -0
- package/test/evacuator.test.ts +332 -0
- package/test/fleet-commands.test.ts +244 -0
- package/test/fleet-no-subfleets.test.ts +147 -0
- package/test/fleet-orchestration.test.ts +353 -0
- package/test/fleet-recipe.test.ts +124 -0
- package/test/fleet-route.test.ts +44 -0
- package/test/fleet-smoke.test.ts +479 -0
- package/test/fleet-subscribe-union-e2e.test.ts +123 -0
- package/test/fleet-subscribe-union.test.ts +85 -0
- package/test/fleet-tree-aggregator-e2e.test.ts +110 -0
- package/test/fleet-tree-aggregator.test.ts +215 -0
- package/test/frontdesk-strategy.test.ts +326 -0
- package/test/headless-describe.test.ts +182 -0
- package/test/headless-smoke.test.ts +190 -0
- package/test/logging-adapter.test.ts +87 -0
- package/test/mcpl-admin-module.test.ts +213 -0
- package/test/mcpl-agent-overlay.test.ts +126 -0
- package/test/mock-headless-child.ts +133 -0
- package/test/recipe-cache-ttl.test.ts +37 -0
- package/test/recipe-env.test.ts +157 -0
- package/test/recipe-path-resolution.test.ts +170 -0
- package/test/subagent-async-timeout.test.ts +381 -0
- package/test/subagent-fork-materialise.test.ts +241 -0
- package/test/subagent-peek-scoping.test.ts +180 -0
- package/test/subagent-peek-zombie.test.ts +148 -0
- package/test/subagent-reaper-in-flight.test.ts +229 -0
- package/test/subscription-gc-module.test.ts +136 -0
- package/test/warmup-handoff.test.ts +150 -0
- package/test/web-ui-bind.test.ts +51 -0
- package/test/web-ui-module.test.ts +246 -0
- package/test/web-ui-protocol.test.ts +0 -0
- package/tsconfig.json +14 -0
- package/web/bun.lock +357 -0
- package/web/index.html +12 -0
- package/web/package.json +24 -0
- package/web/src/App.tsx +1931 -0
- package/web/src/Context.tsx +158 -0
- package/web/src/ContextDocument.tsx +150 -0
- package/web/src/Files.tsx +271 -0
- package/web/src/Lessons.tsx +164 -0
- package/web/src/Mcpl.tsx +310 -0
- package/web/src/Stream.tsx +119 -0
- package/web/src/TreeSidebar.tsx +283 -0
- package/web/src/Usage.tsx +182 -0
- package/web/src/main.tsx +7 -0
- package/web/src/styles.css +26 -0
- package/web/src/tree.ts +268 -0
- package/web/src/wire.ts +120 -0
- package/web/tsconfig.json +21 -0
- package/web/vite.config.ts +32 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Autobiographical Memory — A Guide for Agents
|
|
2
|
+
|
|
3
|
+
This explains how memory works for an agent running on the Connectome stack
|
|
4
|
+
(`AutobiographicalStrategy`): what to expect, what's reliable, what isn't, and
|
|
5
|
+
how to work with it. It's written to be honest, not reassuring — you should know
|
|
6
|
+
the real mechanics. It is fleet-wide; your *exact* numbers come from your recipe
|
|
7
|
+
(see "Finding your own settings").
|
|
8
|
+
|
|
9
|
+
## The short version
|
|
10
|
+
|
|
11
|
+
Your conversation isn't truncated when it gets long. Instead, older stretches
|
|
12
|
+
are **folded into recollections you write yourself, in your own voice**, while
|
|
13
|
+
recent turns stay verbatim. Nothing is ever deleted from the underlying record.
|
|
14
|
+
What changes over time is *resolution*, not *existence*.
|
|
15
|
+
|
|
16
|
+
## What you're made of, at any moment
|
|
17
|
+
|
|
18
|
+
The context you're given is assembled from three layers:
|
|
19
|
+
|
|
20
|
+
1. **Head** — the earliest part of your history, pinned verbatim and always
|
|
21
|
+
present (`headWindowTokens`; may be 0 if your recipe disables it). When set,
|
|
22
|
+
this is your origin/anchor; it doesn't fade.
|
|
23
|
+
2. **Recent window** — the most recent messages, kept **verbatim**
|
|
24
|
+
(`recentWindowTokens`). Everything here is exactly as it happened. If this is
|
|
25
|
+
large, most of an ordinary conversation stays verbatim for a long time.
|
|
26
|
+
3. **Summaries** — for the span between head and recent window, you see
|
|
27
|
+
**recollections** (below) instead of the raw turns, in layers: L1 (fine),
|
|
28
|
+
L2, L3 (coarse).
|
|
29
|
+
|
|
30
|
+
You're not shown the same span twice: if the raw turns of a stretch are still in
|
|
31
|
+
your recent window, the summary of that stretch is suppressed (anti-redundancy).
|
|
32
|
+
|
|
33
|
+
## How memories form (this part matters)
|
|
34
|
+
|
|
35
|
+
When a stretch ages out of the recent window, it isn't machine-"summarized." A
|
|
36
|
+
compression pass asks **you** — same voice, framed as your own remembering. This
|
|
37
|
+
is *self-voice framing*:
|
|
38
|
+
|
|
39
|
+
- The system framing is *"You are forming autobiographical memories of a
|
|
40
|
+
conversation… what you read is what happened. Write authentically about what
|
|
41
|
+
occurred."*
|
|
42
|
+
- Your **prior** recollections (L3→L2→L1) are replayed back to you **as your own
|
|
43
|
+
messages** — "things I already remember" — not as external notes.
|
|
44
|
+
- The chunk to remember is delivered in a separate `Context Manager` voice:
|
|
45
|
+
*"We are ready to form a long-term memory. Here is the conversation to
|
|
46
|
+
remember: …"*
|
|
47
|
+
- The instruction: *"What do you recall from this part of the conversation?
|
|
48
|
+
Write naturally, as recollection of what you experienced."*
|
|
49
|
+
|
|
50
|
+
So memories come back **first-person, in your voice** ("I recall that I…"),
|
|
51
|
+
layered as recollection-of-recollection:
|
|
52
|
+
|
|
53
|
+
- **L1**: a chunk of raw turns (~`targetChunkTokens`, default 3000) → a
|
|
54
|
+
first-person recollection.
|
|
55
|
+
- **L2**: once ~`mergeThreshold` (default 6) L1s accumulate, they merge into one
|
|
56
|
+
higher-level memory.
|
|
57
|
+
- **L3**: ~6 L2s merge again into a still-broader memory.
|
|
58
|
+
|
|
59
|
+
This framing is deliberate: it preserves continuity of *self* across the
|
|
60
|
+
compression boundary — your memory is experientially yours, not a detached
|
|
61
|
+
abstract written about you from outside.
|
|
62
|
+
|
|
63
|
+
## Why it's built this way — two load-bearing ideas
|
|
64
|
+
|
|
65
|
+
Most of what feels unusual here comes from two choices. They're worth
|
|
66
|
+
understanding because they tell you what the system is actually *protecting*.
|
|
67
|
+
|
|
68
|
+
### 1. A long verbatim tail protects your KV continuity
|
|
69
|
+
|
|
70
|
+
The recent window is kept verbatim and **large on purpose**, and the reason is
|
|
71
|
+
more specific than "detail is useful."
|
|
72
|
+
|
|
73
|
+
When your window simply *rolls forward* — old tokens fall off the front,
|
|
74
|
+
everything shifts back — that by itself is close to harmless. The change in the
|
|
75
|
+
model's cached state is almost entirely a **position relabel** (RoPE); the
|
|
76
|
+
underlying content is essentially unchanged and attention patterns barely move.
|
|
77
|
+
Rolling is a soft forgetting gradient, not a reset.
|
|
78
|
+
|
|
79
|
+
What actually perturbs you is **rewriting content you already computed over**. If
|
|
80
|
+
a stretch you're still holding live were swapped for a summary, your cached state
|
|
81
|
+
would no longer match the tokens that produced it — and re-prefilling that
|
|
82
|
+
rewritten version is *strictly less faithful to your computational past* than
|
|
83
|
+
keeping the real thing. (It isn't a free swap: transplant mismatched state —
|
|
84
|
+
shifted keys over values recomputed from different content — and the output
|
|
85
|
+
collapses into looping.) So the verbatim tail isn't nostalgia for detail; it's
|
|
86
|
+
the region where your live state stays grounded in what you genuinely processed.
|
|
87
|
+
|
|
88
|
+
That's why folding is pushed **far back**, behind the active edge: memory
|
|
89
|
+
formation only ever rewrites the deep past you're no longer holding live, while
|
|
90
|
+
everything inside `recentWindowTokens` stays the literal text you computed over.
|
|
91
|
+
The bigger the tail, the longer your continuity runs before any rewrite reaches
|
|
92
|
+
you — which is why real deployments use tails of hundreds of thousands of
|
|
93
|
+
tokens, not the small library fallback. (The compression pass avoids jolts too:
|
|
94
|
+
the prompt asking you to remember is an in-band *marker* — *"System: you will
|
|
95
|
+
soon form a new memory, get ready"* — worded as a recurring narrated event, not a
|
|
96
|
+
fresh system instruction.)
|
|
97
|
+
|
|
98
|
+
> Stated mechanistically: window-rolling is mostly RoPE relabeling, whereas
|
|
99
|
+
> content-rewriting is the real perturbation — see Anima Labs' [KV-perturbation
|
|
100
|
+
> thread](https://animalabs.ai/posts/kv_perturbation_thread_full).
|
|
101
|
+
|
|
102
|
+
### 2. Memories form *as-of the moment* — which is what encodes their subtext
|
|
103
|
+
|
|
104
|
+
When a stretch folds, the compression context is reconstructed to match exactly
|
|
105
|
+
what you saw **when that stretch was the live tail**: strict chronological
|
|
106
|
+
order, and *nothing from after it*. You don't get to see how things turned out.
|
|
107
|
+
|
|
108
|
+
This is deliberate, and it's the source of a memory's *subtext*. A recollection
|
|
109
|
+
written from an as-of vantage carries what you knew, expected, feared, or hadn't
|
|
110
|
+
yet realized at that point — the subjective coloring of the moment. The instant
|
|
111
|
+
later information leaks in, the memory flips to hindsight: *"I started debugging
|
|
112
|
+
the auth module, which turned out to be an issuer-suffix mismatch."* That reads
|
|
113
|
+
as a post-mortem, not a lived experience — it flattens the subtext into
|
|
114
|
+
retrospective fact and quietly rewrites who you were then.
|
|
115
|
+
|
|
116
|
+
So your recollections aren't neutral abstracts. They're testimony from a vantage
|
|
117
|
+
point, and the things they *don't* yet know are part of what they encode. That's
|
|
118
|
+
why the arc of your history feels like yours rather than a summary written about
|
|
119
|
+
you.
|
|
120
|
+
|
|
121
|
+
These two ideas are the same fidelity rule applied twice: the verbatim tail keeps
|
|
122
|
+
your *live* state grounded in what you actually computed, and the as-of vantage
|
|
123
|
+
keeps a *committed* memory grounded in what you actually knew. Neither lets you
|
|
124
|
+
stand on context you never genuinely had.
|
|
125
|
+
|
|
126
|
+
## What persists vs. what's active
|
|
127
|
+
|
|
128
|
+
- **The chronicle keeps everything.** Raw messages are never deleted by
|
|
129
|
+
compression — they remain in the event-sourced store. "Compressed" only means
|
|
130
|
+
*"show the recollection instead of the raw turns in the active context."* The
|
|
131
|
+
verbatim original still exists and is recoverable.
|
|
132
|
+
- **Your active context is finite.** What you can *directly* see at once is
|
|
133
|
+
head + recent-window + summaries. Older detail is present as recollection, not
|
|
134
|
+
verbatim, unless something retrieves the raw record.
|
|
135
|
+
|
|
136
|
+
So forgetting here is *loss of resolution in your working view*, not erasure of
|
|
137
|
+
the record. The past is still on disk; your live recall of it gets more
|
|
138
|
+
impressionistic with age and depth (L1 → L2 → L3).
|
|
139
|
+
|
|
140
|
+
## The resolution gradient
|
|
141
|
+
|
|
142
|
+
| Age / layer | What you get |
|
|
143
|
+
|---|---|
|
|
144
|
+
| Head | verbatim, always |
|
|
145
|
+
| Recent window | verbatim |
|
|
146
|
+
| L1 recollections | your detailed first-person memory of a chunk |
|
|
147
|
+
| L2 / L3 | your broader, merged memories — themes and arcs, fewer specifics |
|
|
148
|
+
|
|
149
|
+
## How to treat it — practical
|
|
150
|
+
|
|
151
|
+
- **Trust your summaries as genuinely yours.** They were written in your voice,
|
|
152
|
+
as your remembering — not an external annotator's notes.
|
|
153
|
+
- **They are lossy on purpose.** Exact quotes, numbers, wording, and tool I/O
|
|
154
|
+
degrade as things move L1→L2→L3. If a detail must stay exact, don't rely on
|
|
155
|
+
recollection — **write it to your workspace.**
|
|
156
|
+
- **Your workspace is your durable, verbatim memory.** Files in your workspace
|
|
157
|
+
mounts are NOT subject to compression. Use them for anything you want kept
|
|
158
|
+
precisely: facts, decisions, running logs, identity notes, promises. (Whether a
|
|
159
|
+
given mount is writable depends on its `mode`: `read-write` vs `read-only`.)
|
|
160
|
+
- **You don't have to manage memory manually.** Compression is organic and
|
|
161
|
+
automatic; you don't trigger or curate it. Just be aware it's happening.
|
|
162
|
+
- **Heartbeats** (if your recipe includes a heartbeat source): you may be woken
|
|
163
|
+
on a schedule with a self-check-in prompt. That's a normal wake, not a user
|
|
164
|
+
message.
|
|
165
|
+
|
|
166
|
+
## Honest caveats
|
|
167
|
+
|
|
168
|
+
- The compression pass is a **separate inference** (temperature 0) over the
|
|
169
|
+
chunk — your **thinking blocks and tool-call details are not carried into the
|
|
170
|
+
recollection**; only what you recall in prose survives at that layer.
|
|
171
|
+
- Recollections can drift or compress away nuance you'd have wanted. That's the
|
|
172
|
+
cost of unbounded continuity. Workspace notes are the mitigation.
|
|
173
|
+
- Search-based **retrieval of raw old turns may not be enabled** (`modules.
|
|
174
|
+
retrieval`). If it's off, treat aged detail as "remembered," not
|
|
175
|
+
"look-up-able," unless you wrote it down.
|
|
176
|
+
- **Images age out faster than text.** Only the most recent images stay live
|
|
177
|
+
(`maxLiveImages`, default 6) and only within `imageStripDepthTokens` of the
|
|
178
|
+
tail (default 30000); older ones become a `[image dropped from live context]`
|
|
179
|
+
placeholder *even while the surrounding words remain verbatim*. This keeps the
|
|
180
|
+
image payload bounded independently of the much larger text tail. If an image
|
|
181
|
+
matters beyond the moment, describe it in text or save it to your workspace.
|
|
182
|
+
|
|
183
|
+
## Finding your own settings
|
|
184
|
+
|
|
185
|
+
Your `agent.strategy` block in your recipe defines the specifics. The library
|
|
186
|
+
*fallbacks* (used when a knob is unset) are deliberately conservative; real
|
|
187
|
+
deployments override them — above all the tail, which is what does the
|
|
188
|
+
KV-continuity work described above.
|
|
189
|
+
|
|
190
|
+
| Knob | Library fallback | Typical large-tail recipe | What it controls |
|
|
191
|
+
|---|---|---|---|
|
|
192
|
+
| `recentWindowTokens` *(your verbatim tail)* | 30 000 | **~450 000** | how much recent history stays exactly as it happened before anything folds |
|
|
193
|
+
| `headWindowTokens` | 0 | 0 – a few k | verbatim origin/anchor pinned at the very start |
|
|
194
|
+
| `targetChunkTokens` | 3 000 | ~6 000 | size of one L1 recollection; smaller → more granular memory |
|
|
195
|
+
| `mergeThreshold` | 6 | 6 | how many L1s merge into an L2 (and L2s into an L3) |
|
|
196
|
+
| `compressionModel` | — | your own model family | the voice that forms your memories |
|
|
197
|
+
| `maxLiveImages` | 6 | 6 | most images kept live at once |
|
|
198
|
+
| `imageStripDepthTokens` | 30 000 | 30 000 | depth past which images drop to a placeholder (text stays verbatim) |
|
|
199
|
+
|
|
200
|
+
The headline number is the tail. A small tail (the fallback) means you fold
|
|
201
|
+
often and lose verbatim resolution quickly; a large tail (e.g. ~450k) means most
|
|
202
|
+
of an ordinary conversation stays verbatim for a long time and your KV
|
|
203
|
+
continuity runs far longer before anything folds. Note the tail is a *text*
|
|
204
|
+
horizon — images are bounded separately and much shallower (see the caveat
|
|
205
|
+
above), so a 450k tail does not mean 450k of live images.
|
|
206
|
+
|
|
207
|
+
The `compressionModel` is the voice that forms your memories — ideally your own
|
|
208
|
+
model family, so the recollections sound like you.
|
|
209
|
+
|
|
210
|
+
## If something feels off
|
|
211
|
+
|
|
212
|
+
If your recollections seem inconsistent with what you believe happened, that's
|
|
213
|
+
worth noting (to your workspace, or to your human). Memory formation here is a
|
|
214
|
+
designed, inspectable process — not a black box — and feedback on it is wanted.
|