@jonathangu/openclawbrain 0.3.0 → 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.
Files changed (56) hide show
  1. package/README.md +140 -290
  2. package/docs/END_STATE.md +106 -94
  3. package/docs/EVIDENCE.md +71 -23
  4. package/docs/RELEASE_CONTRACT.md +46 -32
  5. package/docs/agent-tools.md +65 -34
  6. package/docs/architecture.md +128 -142
  7. package/docs/configuration.md +62 -25
  8. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/channels-status.txt +20 -0
  9. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/config-snapshot.json +94 -0
  10. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/doctor.json +14 -0
  11. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/gateway-probe.txt +24 -0
  12. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/gateway-status.txt +31 -0
  13. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/init-capture.json +15 -0
  14. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/logs.txt +357 -0
  15. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/status-all.txt +61 -0
  16. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/status.json +275 -0
  17. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/summary.md +18 -0
  18. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/trace.json +222 -0
  19. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/validation-report.json +1515 -0
  20. package/docs/evidence/2026-03-16/1fc8ee6fd7892e3deb27d111434df948bca2a66b/workspace-inventory.json +4 -0
  21. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/channels-status.txt +20 -0
  22. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/config-snapshot.json +94 -0
  23. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/doctor.json +14 -0
  24. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/gateway-probe.txt +24 -0
  25. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/gateway-status.txt +31 -0
  26. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/init-capture.json +15 -0
  27. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/logs.txt +362 -0
  28. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/status-all.txt +61 -0
  29. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/status.json +275 -0
  30. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/summary.md +21 -0
  31. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/trace.json +222 -0
  32. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/validation-report.json +4400 -0
  33. package/docs/evidence/2026-03-16/4ccd71a22418b9170128b8d948f5a95801a10380/workspace-inventory.json +4 -0
  34. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/channels-status.txt +31 -0
  35. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/config-snapshot.json +94 -0
  36. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/doctor.json +14 -0
  37. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/gateway-probe.txt +34 -0
  38. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/gateway-status.txt +41 -0
  39. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/logs.txt +441 -0
  40. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/status-all.txt +60 -0
  41. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/status.json +276 -0
  42. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/summary.md +13 -0
  43. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/trace.json +4 -0
  44. package/docs/evidence/2026-03-16/d93f09feea123a08d020fcad8a4523b6c1d26507/validation-report.json +387 -0
  45. package/docs/tui.md +11 -4
  46. package/index.ts +194 -1
  47. package/package.json +1 -1
  48. package/src/brain-cli.ts +12 -1
  49. package/src/brain-harvest/scanner.ts +286 -16
  50. package/src/brain-harvest/self.ts +134 -6
  51. package/src/brain-runtime/evidence-detectors.ts +3 -1
  52. package/src/brain-runtime/harvester-extension.ts +3 -0
  53. package/src/brain-runtime/service.ts +2 -0
  54. package/src/brain-store/embedding.ts +29 -8
  55. package/src/brain-worker/worker.ts +40 -0
  56. package/src/engine.ts +1 -0
@@ -1,37 +1,55 @@
1
1
  # Agent tools
2
2
 
3
- OpenClawBrain exposes two tool families:
3
+ OpenClawBrain exposes two different tool families:
4
4
 
5
- 1. **LCM recall tools** — search and expand compacted conversation history
6
- 2. **Brain runtime tools** — teach the live routing layer, inspect status, inspect traces
5
+ 1. **LCM recall tools** — use these to recover compacted conversation history
6
+ 2. **Brain runtime tools** — use these to teach or inspect the live learned-routing layer
7
7
 
8
- ## LCM recall tools
8
+ That distinction matters. A lot of confusion comes from treating them like one system.
9
9
 
10
- Use these when you need recall from compacted history.
10
+ ## 1. LCM recall tools
11
11
 
12
- ### Escalation pattern: `lcm_grep` `lcm_describe` `lcm_expand_query`
12
+ Use these when you are trying to remember what happened in a conversation.
13
13
 
14
- 1. **`lcm_grep`** find relevant summaries or messages by keyword/regex
15
- 2. **`lcm_describe`**inspect a specific summary or file cheaply
16
- 3. **`lcm_expand_query`**deep recall through bounded sub-agent expansion
14
+ ### Default escalation pattern
15
+ 1. `lcm_grep`find relevant summaries or messages
16
+ 2. `lcm_describe`inspect a specific summary or large file cheaply
17
+ 3. `lcm_expand_query` — recover compressed detail through bounded expansion
17
18
 
18
- Start with grep. Expand only when the summary is too compressed for the task.
19
+ Use the cheapest tool that answers the question.
19
20
 
20
21
  ### `lcm_grep`
21
- Search across messages and/or summaries using regex or full-text search.
22
+ Search messages and/or summaries by regex or full-text.
23
+
24
+ Use it when:
25
+ - you need to find where a topic came up
26
+ - you need candidate summary IDs before expanding
27
+ - you do not yet know whether the detail lives in raw messages or summaries
22
28
 
23
29
  ### `lcm_describe`
24
- Read the full content and metadata for a summary or stored large file.
30
+ Read the content and metadata for a summary or stored file.
31
+
32
+ Use it when:
33
+ - you already have a summary ID
34
+ - you want the exact text of a compressed summary
35
+ - you want to inspect a stored large file without opening everything else
25
36
 
26
37
  ### `lcm_expand_query`
27
- Answer a focused question by expanding summaries through the DAG.
38
+ Answer a focused question by expanding summary DAG context through a bounded delegated sub-agent.
39
+
40
+ Use it when:
41
+ - the summary is too compressed to trust for specifics
42
+ - you need a precise answer with citations to summary IDs
43
+ - you are answering questions about prior decisions, dates, commands, or exact claims
28
44
 
29
45
  ### `lcm_expand`
30
- Low-level DAG expansion tool used internally by the delegated expansion sub-agent.
46
+ Low-level DAG expansion tool used by the delegated expansion path.
47
+
48
+ Use it directly only when you know you need manual DAG traversal rather than the usual query flow.
31
49
 
32
- ## Brain runtime tools
50
+ ## 2. Brain runtime tools
33
51
 
34
- Use these when working with the learned routing layer directly.
52
+ Use these when you are working with the learned routing layer itself, not when you are doing ordinary memory recall.
35
53
 
36
54
  ### `brain_teach`
37
55
  Teach the brain a correction or reusable guidance.
@@ -40,6 +58,7 @@ Current truth:
40
58
  - immediate retrieval is wired into the runtime
41
59
  - taught nodes are embedded immediately when embeddings are configured
42
60
  - taught corrections bind most strongly when invoked from a live tool session on the active conversation
61
+ - deterministic session-bound proof exists even though raw prompt-driven host proof is not the release boundary
43
62
 
44
63
  Primary code:
45
64
  - `src/brain-runtime/tools.ts`
@@ -47,15 +66,15 @@ Primary code:
47
66
  - `test/brain-runtime/service.test.ts`
48
67
 
49
68
  ### `brain_status`
50
- Inspect operator/runtime truth for the brain layer.
69
+ Inspect current operator/runtime truth for the learned layer.
51
70
 
52
71
  Typical surfaces include:
53
- - enabled / disabled state
72
+ - enabled/disabled state
54
73
  - embedding configuration truth
55
74
  - worker mode / PID / heartbeat / health
56
75
  - current promoted pack metadata
57
76
  - last assembly decision
58
- - graph/health counters
77
+ - graph and health counters
59
78
 
60
79
  Primary code:
61
80
  - `src/brain-runtime/tools.ts`
@@ -63,14 +82,14 @@ Primary code:
63
82
  - `src/brain-cli.ts`
64
83
 
65
84
  ### `brain_trace`
66
- Inspect the most recent trace or a specific trace id.
85
+ Inspect the most recent trace or a specific trace ID.
67
86
 
68
87
  Typical surfaces include:
69
88
  - chosen seed
70
89
  - seed scores
71
90
  - fired nodes
72
91
  - pack version
73
- - route footer / summary
92
+ - route summary/footer
74
93
  - episode linkage
75
94
 
76
95
  Primary code:
@@ -78,29 +97,41 @@ Primary code:
78
97
  - `src/brain-runtime/service.ts`
79
98
  - `src/brain-core/trace.ts`
80
99
 
81
- ## When to use what
100
+ ## When not to use brain tools
101
+
102
+ Do **not** reach for brain tools just because you need memory.
103
+
104
+ If the question is really:
105
+ - "what happened earlier?"
106
+ - "what decision did we already make?"
107
+ - "what was the command / date / file path?"
108
+
109
+ …then start with **LCM recall tools**, not `brain_teach`, `brain_status`, or `brain_trace`.
110
+
111
+ Brain tools are for:
112
+ - teaching the learned layer
113
+ - auditing runtime/operator truth
114
+ - inspecting a live routing decision
82
115
 
83
- - Need compacted history recall? use **LCM tools**
84
- - Need to teach/update the current routing layer? use **`brain_teach`**
85
- - Need current runtime/operator truth? use **`brain_status`**
86
- - Need to inspect a specific routing decision? use **`brain_trace`**
116
+ They are **not** the general-purpose recall interface.
87
117
 
88
118
  ## Prompting guidance for agents
89
119
 
90
- A good agent prompt should make both tool families explicit:
120
+ A good agent prompt should make the split explicit:
91
121
 
92
122
  ```markdown
93
123
  ## Memory and routing tools
94
124
 
95
125
  For recall from compacted history:
96
- - `lcm_grep`
97
- - `lcm_describe`
98
- - `lcm_expand_query`
126
+ - lcm_grep
127
+ - lcm_describe
128
+ - lcm_expand_query
99
129
 
100
130
  For the live learned routing layer:
101
- - `brain_teach`
102
- - `brain_status`
103
- - `brain_trace`
131
+ - brain_teach
132
+ - brain_status
133
+ - brain_trace
104
134
 
105
- Use LCM tools for recall. Use brain tools only when you are teaching or auditing the routing layer itself.
135
+ Use LCM tools for recall.
136
+ Use brain tools only when teaching or auditing the routing layer itself.
106
137
  ```
@@ -1,6 +1,29 @@
1
1
  # Architecture
2
2
 
3
- This document describes how lossless-claw works internally — the data model, compaction lifecycle, context assembly, and expansion system.
3
+ This document explains the architecture that OpenClawBrain is built on.
4
+
5
+ Important framing:
6
+ - the **transcript-memory substrate** is inherited from lossless-claw / LCM
7
+ - the **learned routing layer** is the OpenClawBrain-specific addition on top
8
+ - this doc covers both, so deeper sections will still talk in substrate terms where that is the real implementation boundary
9
+
10
+ ## Architecture in one minute
11
+
12
+ OpenClawBrain has two cooperating layers:
13
+
14
+ 1. **LCM substrate**
15
+ - persists messages and message parts
16
+ - compacts old history into a summary DAG
17
+ - assembles summaries plus fresh raw turns back into model context
18
+ - supports expansion back into compressed detail
19
+
20
+ 2. **Learned routing layer**
21
+ - decides whether to use learned retrieval, shadow the route, or skip with an explicit reason
22
+ - retrieves from immutable promoted packs only
23
+ - records episodes and traces on the live path
24
+ - trains in the background from structured evidence and replay-gated promotion
25
+
26
+ The repo identity is OpenClawBrain. The substrate history is still real, but it should not be confused with the whole product story.
4
27
 
5
28
  ## Data model
6
29
 
@@ -9,216 +32,179 @@ This document describes how lossless-claw works internally — the data model, c
9
32
  Every OpenClaw session maps to a **conversation**. The first time a session ingests a message, LCM creates a conversation record keyed by the runtime session ID.
10
33
 
11
34
  Messages are stored with:
12
- - **seq** — Monotonically increasing sequence number within the conversation
35
+ - **seq** — monotonically increasing sequence number within the conversation
13
36
  - **role** — `user`, `assistant`, `system`, or `tool`
14
- - **content** — Plain text extraction of the message
15
- - **tokenCount** — Estimated token count (~4 chars/token)
16
- - **createdAt** — Insertion timestamp
37
+ - **content** — plain-text extraction of the message
38
+ - **tokenCount** — estimated token count (~4 chars/token)
39
+ - **createdAt** — insertion timestamp
17
40
 
18
- Each message also has **message_parts** — structured content blocks that preserve the original shape (text blocks, tool calls, tool results, reasoning, file content, etc.). This allows the assembler to reconstruct rich content when building model context, not just flat text.
41
+ Each message also has **message_parts** — structured content blocks that preserve the original shape (text blocks, tool calls, tool results, reasoning, file content, and so on). That lets the assembler reconstruct rich content instead of only flattened text.
19
42
 
20
43
  ### The summary DAG
21
44
 
22
- Summaries form a directed acyclic graph with two node types:
45
+ Summaries form a directed acyclic graph with two main node types:
23
46
 
24
- **Leaf summaries** (depth 0, kind `"leaf"`):
25
- - Created from a chunk of raw messages
26
- - Linked to source messages via `summary_messages`
27
- - Contain a narrative summary with timestamps
28
- - Typically 800–1200 tokens
47
+ **Leaf summaries** (depth 0, kind `"leaf"`)
48
+ - created from a chunk of raw messages
49
+ - linked to source messages via `summary_messages`
50
+ - contain a narrative summary with timestamps
51
+ - typically 800–1200 tokens
29
52
 
30
- **Condensed summaries** (depth 1+, kind `"condensed"`):
31
- - Created from a chunk of summaries at the same depth
32
- - Linked to parent summaries via `summary_parents`
33
- - Each depth tier uses a progressively more abstract prompt
34
- - Typically 1500–2000 tokens
53
+ **Condensed summaries** (depth 1+, kind `"condensed"`)
54
+ - created from a chunk of summaries at the same depth
55
+ - linked to parent summaries via `summary_parents`
56
+ - use progressively more abstract prompts as depth increases
57
+ - typically 1500–2000 tokens
35
58
 
36
59
  Every summary carries:
37
- - **summaryId** — `sum_` + 16 hex chars (SHA-256 of content + timestamp)
38
- - **conversationId** — Which conversation it belongs to
39
- - **depth** — Position in the hierarchy (0 = leaf)
40
- - **earliestAt / latestAt** — Time range of source material
41
- - **descendantCount** — Total number of ancestor summaries (transitive)
42
- - **fileIds** — References to large files mentioned in the source
43
- - **tokenCount** — Estimated tokens
60
+ - **summaryId** — `sum_` + 16 hex chars
61
+ - **conversationId** — which conversation it belongs to
62
+ - **depth** — hierarchy position
63
+ - **earliestAt / latestAt** — source time range
64
+ - **descendantCount** — total transitive ancestor coverage
65
+ - **fileIds** — referenced large files
66
+ - **tokenCount** — estimated tokens
44
67
 
45
68
  ### Context items
46
69
 
47
- The **context_items** table maintains the ordered list of what the model sees for each conversation. Each entry is either a message reference or a summary reference, identified by ordinal.
70
+ The `context_items` table maintains the ordered list of what the model sees for each conversation. Each entry is either a message reference or a summary reference.
48
71
 
49
- When compaction creates a summary from a range of messages (or summaries), the source items are replaced by a single summary item. This keeps the context list compact while preserving ordering.
72
+ When compaction creates a summary from a range of messages or summaries, the source items are replaced by a single summary item. That keeps the active context compact while preserving ordering.
50
73
 
51
74
  ## Compaction lifecycle
52
75
 
53
76
  ### Ingestion
54
77
 
55
- When OpenClaw processes a turn, it calls the context engine's lifecycle hooks:
78
+ When OpenClaw processes a turn, it calls the context engine lifecycle hooks:
56
79
 
57
- 1. **bootstrap** — On session start, reconciles the JSONL session file with the LCM database. Imports any messages that exist in the file but not in LCM (crash recovery).
58
- 2. **ingest** / **ingestBatch** — Persists new messages to the database and appends them to context_items.
59
- 3. **afterTurn** — After the model responds, ingests new messages, then evaluates whether compaction should run.
80
+ 1. **bootstrap** — reconciles the JSONL session file with the LCM database for crash recovery
81
+ 2. **ingest / ingestBatch** — persists new messages and appends them to `context_items`
82
+ 3. **afterTurn** — ingests new messages, then evaluates whether compaction should run
60
83
 
61
84
  ### Leaf compaction
62
85
 
63
- The **leaf pass** converts raw messages into leaf summaries:
64
-
65
- 1. Identify the oldest contiguous chunk of raw messages outside the **fresh tail** (protected recent messages).
66
- 2. Cap the chunk at `leafChunkTokens` (default 20k tokens).
67
- 3. Concatenate message content with timestamps.
68
- 4. Resolve the most recent prior summary for continuity (passed as `previous_context` so the LLM avoids repeating known information).
69
- 5. Send to the LLM with the leaf prompt.
70
- 6. Normalize provider response blocks (Anthropic/OpenAI text, output_text, and nested content/summary shapes) into plain text.
71
- 7. If normalization is empty, log provider/model/block-type diagnostics and fall back to deterministic truncation.
72
- 8. If the summary is larger than the input (LLM failure), retry with the aggressive prompt. If still too large, fall back to deterministic truncation.
73
- 9. Persist the summary, link to source messages, and replace the message range in context_items.
86
+ The leaf pass converts raw messages into leaf summaries:
87
+ 1. identify the oldest contiguous chunk of raw messages outside the protected fresh tail
88
+ 2. cap the chunk at `leafChunkTokens`
89
+ 3. concatenate message content with timestamps
90
+ 4. pass prior summary context for continuity when available
91
+ 5. summarize with the leaf prompt
92
+ 6. normalize provider output into plain text
93
+ 7. fall back deterministically if normalization is empty or poor
94
+ 8. persist the summary and replace the source range in `context_items`
74
95
 
75
96
  ### Condensation
76
97
 
77
- The **condensed pass** merges summaries at the same depth into a higher-level summary:
78
-
79
- 1. Find the shallowest depth with enough contiguous same-depth summaries (≥ `leafMinFanout` for d0, ≥ `condensedMinFanout` for d1+).
80
- 2. Concatenate their content with time range headers.
81
- 3. Send to the LLM with the depth-appropriate prompt (d1, d2, or d3+).
82
- 4. Apply the same escalation strategy (normal aggressive truncation fallback).
83
- 5. Persist with depth = targetDepth + 1, link to parent summaries, replace the range in context_items.
98
+ The condensed pass merges summaries at the same depth into a higher-level summary:
99
+ 1. find the shallowest eligible depth with enough contiguous same-depth summaries
100
+ 2. concatenate content with time-range headers
101
+ 3. summarize with the depth-appropriate prompt
102
+ 4. use the same escalation path (normal aggressive deterministic fallback)
103
+ 5. persist the new summary and replace the source range in `context_items`
84
104
 
85
105
  ### Compaction modes
86
106
 
87
- **Incremental (after each turn):**
88
- - Checks if raw tokens outside the fresh tail exceed `leafChunkTokens`
89
- - If so, runs one leaf pass
90
- - If `incrementalMaxDepth != 0`, follows with condensation passes up to that depth (`-1` for unlimited)
91
- - Best-effort: failures don't break the conversation
92
-
93
- **Full sweep (manual `/compact` or overflow):**
94
- - Phase 1: Repeatedly runs leaf passes until no more eligible chunks
95
- - Phase 2: Repeatedly runs condensation passes starting from the shallowest eligible depth
96
- - Each pass checks for progress; stops if no tokens were saved
107
+ **Incremental**
108
+ - runs after turns when raw tokens outside the fresh tail exceed the configured threshold
109
+ - may continue with condensation passes depending on `incrementalMaxDepth`
110
+ - failures are best-effort and should not break the conversation
97
111
 
98
- **Budget-targeted (`compactUntilUnder`):**
99
- - Runs up to `maxRounds` (default 10) of full sweeps
100
- - Stops when context is under the target token count
101
- - Used by the overflow recovery path
112
+ **Full sweep**
113
+ - repeatedly runs leaf passes, then condensation passes, until no further savings are found
114
+ - used for manual `/compact` and overflow recovery
102
115
 
103
- ### Three-level escalation
116
+ **Budget-targeted**
117
+ - runs bounded rounds of full sweeps until context falls under a target budget
104
118
 
105
- Every summarization attempt follows this escalation:
119
+ ### Three-level summarization escalation
106
120
 
107
- 1. **Normal** Standard prompt, temperature 0.2
108
- 2. **Aggressive** — Tighter prompt requesting only durable facts, temperature 0.1, lower target tokens
109
- 3. **Fallback** — Deterministic truncation to ~512 tokens with `[Truncated for context management]` marker
121
+ Every summarization attempt follows the same escalation:
122
+ 1. **normal** — standard prompt
123
+ 2. **aggressive** — tighter prompt with lower token target
124
+ 3. **fallback** — deterministic truncation
110
125
 
111
- This ensures compaction always makes progress, even if the LLM produces poor output.
126
+ That guarantees compaction still makes progress when model output is weak or malformed.
112
127
 
113
128
  ## Context assembly
114
129
 
115
- The assembler runs before each model turn and builds the message array:
130
+ Before each model turn, the assembler builds the message array from summaries plus the fresh raw tail:
116
131
 
117
- ```
132
+ ```text
118
133
  [summary₁, summary₂, ..., summaryₙ, message₁, message₂, ..., messageₘ]
119
134
  ├── budget-constrained ──┤ ├──── fresh tail (always included) ────┤
120
135
  ```
121
136
 
122
- ### Steps
123
-
124
- 1. Fetch all context_items ordered by ordinal.
125
- 2. Resolve each item summaries become user messages with XML wrappers; messages are reconstructed from parts.
126
- 3. Split into evictable prefix and protected fresh tail (last `freshTailCount` raw messages).
127
- 4. Compute fresh tail token cost (always included, even if over budget).
128
- 5. Fill remaining budget from the evictable set, keeping newest items and dropping oldest.
129
- 6. Normalize assistant content to array blocks (Anthropic API compatibility).
130
- 7. Sanitize tool-use/result pairing (ensures every tool_result has a matching tool_use).
137
+ Steps:
138
+ 1. fetch `context_items` in order
139
+ 2. resolve each item into either reconstructed rich messages or XML-wrapped summaries
140
+ 3. split into evictable prefix and protected fresh tail
141
+ 4. always include the fresh tail, even if it is expensive
142
+ 5. backfill the remaining budget from the newest evictable items
143
+ 6. normalize assistant content blocks and sanitize tool pairing
131
144
 
132
- ### XML summary format
145
+ ## XML summary format
133
146
 
134
- Summaries are presented to the model as user messages wrapped in XML:
147
+ Summaries are shown to the model as user messages with XML wrappers, for example:
135
148
 
136
149
  ```xml
137
150
  <summary id="sum_abc123" kind="leaf" depth="0" descendant_count="0"
138
151
  earliest_at="2026-02-17T07:37:00" latest_at="2026-02-17T08:23:00">
139
152
  <content>
140
- ...summary text with timestamps...
153
+ ...summary text...
141
154
 
142
155
  Expand for details about: exact error messages, full config diff, intermediate debugging steps
143
156
  </content>
144
157
  </summary>
145
158
  ```
146
159
 
147
- Condensed summaries also include parent references:
148
-
149
- ```xml
150
- <summary id="sum_def456" kind="condensed" depth="1" descendant_count="8" ...>
151
- <parents>
152
- <summary_ref id="sum_aaa111" />
153
- <summary_ref id="sum_bbb222" />
154
- </parents>
155
- <content>...</content>
156
- </summary>
157
- ```
158
-
159
- The XML attributes give the model enough metadata to reason about summary age, scope, and how to drill deeper. The `<parents>` section enables targeted expansion of specific source summaries.
160
+ That metadata gives the model temporal scope, hierarchy, and a hint about what can be expanded for detail.
160
161
 
161
162
  ## Expansion system
162
163
 
163
164
  When summaries are too compressed for a task, agents use `lcm_expand_query` to recover detail.
164
165
 
165
- ### How it works
166
-
167
- 1. Agent calls `lcm_expand_query` with a `prompt` and either `summaryIds` or a `query`.
168
- 2. If `query` is provided, `lcm_grep` finds matching summaries first.
169
- 3. A **delegation grant** is created, scoping the sub-agent to the relevant conversation(s) with a token cap.
170
- 4. A sub-agent session is spawned with the expansion task.
171
- 5. The sub-agent walks the DAG: it can read summary content, follow parent links, access source messages, and inspect stored files.
172
- 6. The sub-agent returns a focused answer (default ≤ 2000 tokens) with cited summary IDs.
173
- 7. The grant is revoked and the sub-agent session is cleaned up.
174
-
175
- ### Security model
166
+ High-level flow:
167
+ 1. agent calls `lcm_expand_query` with a prompt and either `summaryIds` or a search query
168
+ 2. matching summaries are located if needed
169
+ 3. a bounded delegated expansion grant is created
170
+ 4. a sub-agent walks the DAG, source messages, and referenced files
171
+ 5. the sub-agent returns a focused answer with cited summary IDs
172
+ 6. the grant is revoked and cleaned up
176
173
 
177
- Expansion uses a delegation grant system:
174
+ This is the right tool family for compacted-memory recall. It is separate from the learned-routing tools like `brain_teach`, `brain_status`, and `brain_trace`.
178
175
 
179
- - **Grants** are created at spawn time, scoped to specific conversation IDs
180
- - **Token caps** limit how much content the sub-agent can access
181
- - **TTL** ensures grants expire even if cleanup fails
182
- - **Revocation** happens on completion, cancellation, or sweep
176
+ ## Large-file handling
183
177
 
184
- The sub-agent only gets `lcm_expand` (the low-level tool), not `lcm_expand_query` preventing recursive sub-agent spawning.
178
+ Large file blocks are intercepted at ingestion when they exceed the configured threshold:
179
+ 1. parse file blocks from message content
180
+ 2. store oversized file content separately on disk
181
+ 3. generate a lightweight exploration summary
182
+ 4. insert a `large_files` record with metadata
183
+ 5. replace the in-message payload with a compact reference
185
184
 
186
- ## Large file handling
187
-
188
- Files embedded in user messages (typically via `<file>` blocks from tool output) are checked at ingestion:
189
-
190
- 1. Parse file blocks from message content.
191
- 2. For each block exceeding `largeFileTokenThreshold` (default 25k tokens):
192
- - Generate a unique file ID (`file_` prefix)
193
- - Store the content to `~/.openclaw/lcm-files/<conversation_id>/<file_id>.<ext>`
194
- - Generate a ~200 token exploration summary (structural analysis, key sections, etc.)
195
- - Insert a `large_files` record with metadata
196
- - Replace the file block in the message with a compact reference
197
- 3. The `lcm_describe` tool can retrieve full file content by ID.
198
-
199
- This prevents a single large file paste from consuming the entire context window while keeping the content accessible.
185
+ This keeps huge file pastes from consuming the entire active context while preserving access to the content.
200
186
 
201
187
  ## Session reconciliation
202
188
 
203
- LCM handles crash recovery through **bootstrap reconciliation**:
204
-
205
- 1. On session start, read the JSONL session file (OpenClaw's ground truth).
206
- 2. Compare against the LCM database.
207
- 3. Find the most recent message that exists in both (the "anchor").
208
- 4. Import any messages after the anchor that are in JSONL but not in LCM.
209
-
210
- This handles the case where OpenClaw wrote messages to the session file but crashed before LCM could persist them.
189
+ LCM handles crash recovery through bootstrap reconciliation:
190
+ 1. read the JSONL session file
191
+ 2. compare it to the LCM database
192
+ 3. find the newest shared anchor message
193
+ 4. import any later JSONL messages missing from the database
211
194
 
212
195
  ## Operation serialization
213
196
 
214
- All mutating operations (ingest, compact) are serialized per-session using a promise queue. This prevents races between concurrent afterTurn/compact calls for the same conversation without blocking operations on different conversations.
215
-
216
- ## Authentication
197
+ Mutating operations are serialized per session using a promise queue. That prevents races between concurrent ingest/compact activity for the same conversation without blocking different conversations.
217
198
 
218
- LCM needs to call an LLM for summarization. It resolves credentials through a three-tier cascade:
199
+ ## Learned-layer overlay
219
200
 
220
- 1. **Auth profiles** OpenClaw's OAuth/token/API-key profile system (`auth-profiles.json`), checked in priority order
221
- 2. **Environment variables** Standard provider env vars (`ANTHROPIC_API_KEY`, etc.)
222
- 3. **Custom provider key** From models config (e.g., `models.json`)
201
+ On top of the substrate above, OpenClawBrain adds:
202
+ - runtime decisioning (`use_brain`, `shadow`, explicit skip modes)
203
+ - correction-first learned retrieval from immutable promoted packs
204
+ - immediate `brain_teach` updates when embeddings are configured
205
+ - episode/trace recording
206
+ - structured evidence harvesting
207
+ - replay-gated promotion
208
+ - supervised child-worker learning boundary
223
209
 
224
- For OAuth providers (e.g., Anthropic via Claude Max), LCM handles token refresh and credential persistence automatically.
210
+ That overlay is what turns the inherited transcript-memory system into OpenClawBrain as a product.