@martian-engineering/lossless-claw 0.7.0 → 0.8.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 (54) hide show
  1. package/README.md +19 -3
  2. package/dist/index.js +19240 -0
  3. package/docs/agent-tools.md +9 -4
  4. package/docs/configuration.md +24 -5
  5. package/openclaw.plugin.json +27 -3
  6. package/package.json +7 -6
  7. package/skills/lossless-claw/SKILL.md +3 -2
  8. package/skills/lossless-claw/references/architecture.md +12 -0
  9. package/skills/lossless-claw/references/config.md +37 -0
  10. package/skills/lossless-claw/references/diagnostics.md +13 -0
  11. package/index.ts +0 -2
  12. package/src/assembler.ts +0 -1188
  13. package/src/compaction.ts +0 -1756
  14. package/src/db/config.ts +0 -345
  15. package/src/db/connection.ts +0 -141
  16. package/src/db/features.ts +0 -42
  17. package/src/db/migration.ts +0 -746
  18. package/src/engine.ts +0 -4306
  19. package/src/expansion-auth.ts +0 -365
  20. package/src/expansion-policy.ts +0 -303
  21. package/src/expansion.ts +0 -383
  22. package/src/integrity.ts +0 -600
  23. package/src/large-files.ts +0 -546
  24. package/src/lcm-log.ts +0 -37
  25. package/src/openclaw-bridge.ts +0 -22
  26. package/src/plugin/index.ts +0 -1960
  27. package/src/plugin/lcm-command.ts +0 -765
  28. package/src/plugin/lcm-doctor-apply.ts +0 -542
  29. package/src/plugin/lcm-doctor-shared.ts +0 -210
  30. package/src/plugin/shared-init.ts +0 -59
  31. package/src/prune.ts +0 -391
  32. package/src/retrieval.ts +0 -363
  33. package/src/session-patterns.ts +0 -23
  34. package/src/startup-banner-log.ts +0 -49
  35. package/src/store/compaction-telemetry-store.ts +0 -156
  36. package/src/store/conversation-store.ts +0 -929
  37. package/src/store/fts5-sanitize.ts +0 -50
  38. package/src/store/full-text-fallback.ts +0 -83
  39. package/src/store/full-text-sort.ts +0 -21
  40. package/src/store/index.ts +0 -39
  41. package/src/store/parse-utc-timestamp.ts +0 -25
  42. package/src/store/summary-store.ts +0 -1519
  43. package/src/summarize.ts +0 -1511
  44. package/src/tools/common.ts +0 -53
  45. package/src/tools/lcm-conversation-scope.ts +0 -127
  46. package/src/tools/lcm-describe-tool.ts +0 -245
  47. package/src/tools/lcm-expand-query-tool.ts +0 -831
  48. package/src/tools/lcm-expand-tool.delegation.ts +0 -580
  49. package/src/tools/lcm-expand-tool.ts +0 -453
  50. package/src/tools/lcm-expansion-recursion-guard.ts +0 -373
  51. package/src/tools/lcm-grep-tool.ts +0 -228
  52. package/src/transaction-mutex.ts +0 -136
  53. package/src/transcript-repair.ts +0 -301
  54. package/src/types.ts +0 -165
@@ -24,7 +24,7 @@ Summaries are lossy by design. The "Expand for details about:" footer at the end
24
24
  - Tool call sequences and their outputs
25
25
  - Verbatim quotes or specific data points
26
26
 
27
- `lcm_expand_query` is bounded (~120s, scoped sub-agent) and relatively cheap. Don't ration it.
27
+ `lcm_expand_query` is bounded (~120s, scoped sub-agent) and relatively cheap. Don't ration it, but use `lcm_grep` first when you need broad discovery across many sessions.
28
28
 
29
29
  ## Tool reference
30
30
 
@@ -114,6 +114,8 @@ lcm_describe(id: "file_789abc012345")
114
114
 
115
115
  Answer a focused question by expanding summaries through the DAG. Spawns a bounded sub-agent that walks parent links down to source material and returns a compact answer.
116
116
 
117
+ When `allConversations: true` is set, `lcm_expand_query` can now synthesize one answer across multiple conversations. That cross-conversation mode is bounded, not exhaustive: it ranks conversation buckets, expands only the top few, and marks the result truncated when lower-ranked buckets are skipped or fail.
118
+
117
119
  **Parameters:**
118
120
 
119
121
  | Param | Type | Required | Default | Description |
@@ -130,9 +132,11 @@ Answer a focused question by expanding summaries through the DAG. Spawns a bound
130
132
  **Returns:**
131
133
  - `answer` — The focused answer text
132
134
  - `citedIds` — Summary IDs that contributed to the answer
135
+ - `sourceConversationIds` — Conversations that were successfully expanded
133
136
  - `expandedSummaryCount` — How many summaries were expanded
134
137
  - `totalSourceTokens` — Total tokens read from the DAG
135
138
  - `truncated` — Whether the answer was truncated to fit maxTokens
139
+ - `conversationBreakdown` — Optional per-conversation success/failure diagnostics for bounded multi-conversation runs
136
140
 
137
141
  **Examples:**
138
142
 
@@ -149,7 +153,7 @@ lcm_expand_query(
149
153
  prompt: "What were the exact file changes?"
150
154
  )
151
155
 
152
- # Cross-conversation search
156
+ # Cross-conversation synthesis
153
157
  lcm_expand_query(
154
158
  query: "deployment procedure",
155
159
  prompt: "What's the current deployment process?",
@@ -175,7 +179,7 @@ Add instructions to your agent's system prompt so it knows when to use LCM tools
175
179
  Use LCM tools for recall:
176
180
  1. `lcm_grep` — Search all conversations by keyword/regex. Prefer `mode: "full_text"` for topic recall, quote exact phrases, use `sort: "relevance"` for older-topic lookups, and `sort: "hybrid"` when recency should still matter.
177
181
  2. `lcm_describe` — Inspect a specific summary (cheap, no sub-agent)
178
- 3. `lcm_expand_query` — Deep recall with sub-agent expansion
182
+ 3. `lcm_expand_query` — Deep recall with bounded sub-agent expansion
179
183
 
180
184
  When summaries in context have an "Expand for details about:" footer
181
185
  listing something you need, use `lcm_expand_query` to get the full detail.
@@ -183,7 +187,7 @@ listing something you need, use `lcm_expand_query` to get the full detail.
183
187
 
184
188
  ### Conversation scoping
185
189
 
186
- By default, tools operate on the current conversation. Use `allConversations: true` to search across all of them (all agents, all sessions). Use `conversationId` to target a specific conversation you already know about (from previous grep results).
190
+ By default, tools operate on the current conversation. Use `lcm_grep(..., allConversations: true)` when you need broad global discovery. Use `lcm_expand_query(..., allConversations: true)` when you want bounded synthesis across sessions. Use `conversationId` when you already know the exact conversation to inspect or expand.
187
191
 
188
192
  ### Performance considerations
189
193
 
@@ -191,3 +195,4 @@ By default, tools operate on the current conversation. Use `allConversations: tr
191
195
  - `lcm_expand_query` spawns a sub-agent and takes ~30–120 seconds
192
196
  - The sub-agent has a 120-second timeout with cleanup guarantees
193
197
  - Token caps (`LCM_MAX_EXPAND_TOKENS`) prevent runaway expansion
198
+ - Cross-conversation `lcm_expand_query` expands only a bounded set of top-ranked conversations
@@ -16,11 +16,13 @@ Most installations only need to override a handful of keys. If you want a comple
16
16
  {
17
17
  "enabled": true,
18
18
  "databasePath": "/Users/alice/.openclaw/lcm.db",
19
+ "largeFilesDir": "/Users/alice/.openclaw/lcm-files",
19
20
  "ignoreSessionPatterns": [],
20
21
  "statelessSessionPatterns": [],
21
22
  "skipStatelessSessions": true,
22
23
  "contextThreshold": 0.75,
23
24
  "freshTailCount": 64,
25
+ "freshTailMaxTokens": 24000,
24
26
  "newSessionRetainDepth": 2,
25
27
  "leafMinFanout": 8,
26
28
  "condensedMinFanout": 4,
@@ -42,6 +44,7 @@ Most installations only need to override a handful of keys. If you want a comple
42
44
  "summaryTimeoutMs": 60000,
43
45
  "timezone": "America/Los_Angeles",
44
46
  "pruneHeartbeatOk": false,
47
+ "transcriptGcEnabled": false,
45
48
  "maxAssemblyTokenBudget": 30000,
46
49
  "summaryMaxOverageFactor": 3,
47
50
  "customInstructions": "",
@@ -65,6 +68,7 @@ Notes on the example:
65
68
 
66
69
  - Values shown are the runtime defaults when a fixed default exists.
67
70
  - `databasePath` shows the expanded default path shape. Use an absolute path in config rather than `~`.
71
+ - `largeFilesDir` shows the expanded default path shape. Both `databasePath` and `largeFilesDir` default to paths under `OPENCLAW_STATE_DIR` (which in turn falls back to `~/.openclaw`).
68
72
  - `timezone` has no fixed hardcoded default; at runtime it resolves from `TZ` first, then the system timezone. The example uses `America/Los_Angeles`.
69
73
  - `maxAssemblyTokenBudget` has no default. The example uses `30000` as a realistic cap for a 32k-class model.
70
74
  - `databasePath` is the preferred key. `dbPath` is an accepted alias.
@@ -97,14 +101,18 @@ openclaw plugins install --link /path/to/lossless-claw
97
101
  | Key | Type | Default | Env override | Purpose |
98
102
  | --- | --- | --- | --- | --- |
99
103
  | `enabled` | `boolean` | `true` | `LCM_ENABLED` | Enables or disables lossless-claw without uninstalling it. |
100
- | `databasePath` | `string` | `${HOME}/.openclaw/lcm.db` | `LCM_DATABASE_PATH` | Preferred path for the SQLite database. |
104
+ | `databasePath` | `string` | `${OPENCLAW_STATE_DIR}/lcm.db` | `LCM_DATABASE_PATH` | Preferred path for the SQLite database. |
101
105
  | `dbPath` | `string` | alias of `databasePath` | `LCM_DATABASE_PATH` | Legacy alias for `databasePath`. Prefer `databasePath` in new config. |
106
+ | `largeFilesDir` | `string` | `${OPENCLAW_STATE_DIR}/lcm-files` | `LCM_LARGE_FILES_DIR` | Directory where large-file text payloads are persisted. Automatically follows the active state directory. |
102
107
  | `ignoreSessionPatterns` | `string[]` | `[]` | `LCM_IGNORE_SESSION_PATTERNS` | Session-key glob patterns that skip LCM entirely. |
103
108
  | `statelessSessionPatterns` | `string[]` | `[]` | `LCM_STATELESS_SESSION_PATTERNS` | Session-key glob patterns that may read from LCM but never write to it. |
104
109
  | `skipStatelessSessions` | `boolean` | `true` | `LCM_SKIP_STATELESS_SESSIONS` | Enforces `statelessSessionPatterns` when enabled. |
105
110
  | `newSessionRetainDepth` | `integer` | `2` | `LCM_NEW_SESSION_RETAIN_DEPTH` | Controls what survives `/new`. `-1` keeps all context, `0` keeps summaries only, higher values keep only deeper summaries. |
106
111
  | `timezone` | `string` | `TZ` or system timezone | `TZ` | IANA timezone used for timestamp rendering in summaries. |
107
112
  | `pruneHeartbeatOk` | `boolean` | `false` | `LCM_PRUNE_HEARTBEAT_OK` | Retroactively removes `HEARTBEAT_OK` turn cycles from persisted storage. |
113
+ | `transcriptGcEnabled` | `boolean` | `false` | `LCM_TRANSCRIPT_GC_ENABLED` | Enables transcript rewrite GC during `maintain()`; disabled by default so transcript rewrites stay opt-in. |
114
+
115
+ > **Multi-profile note:** `OPENCLAW_STATE_DIR` (set by the host OpenClaw gateway) controls where state is stored. When two gateways run on the same host (e.g. separate bot personas), each gateway sets its own `OPENCLAW_STATE_DIR` and lossless-claw automatically uses that directory for the database, large-file payloads, auth-profile lookups, and legacy secrets — no per-profile plugin config is needed.
108
116
 
109
117
  ### Compaction thresholds and summary sizing
110
118
 
@@ -112,6 +120,7 @@ openclaw plugins install --link /path/to/lossless-claw
112
120
  | --- | --- | --- | --- | --- |
113
121
  | `contextThreshold` | `number` | `0.75` | `LCM_CONTEXT_THRESHOLD` | Fraction of the active model context window that triggers compaction. |
114
122
  | `freshTailCount` | `integer` | `64` | `LCM_FRESH_TAIL_COUNT` | Number of newest messages always kept raw. |
123
+ | `freshTailMaxTokens` | `integer` | unset | `LCM_FRESH_TAIL_MAX_TOKENS` | Optional token cap for the protected fresh tail. The newest message is always preserved even if it exceeds the cap. |
115
124
  | `leafMinFanout` | `integer` | `8` | `LCM_LEAF_MIN_FANOUT` | Minimum number of raw messages required before a leaf pass runs. |
116
125
  | `condensedMinFanout` | `integer` | `4` | `LCM_CONDENSED_MIN_FANOUT` | Number of same-depth summaries needed before condensation is attempted. |
117
126
  | `condensedMinFanoutHard` | `integer` | `2` | `LCM_CONDENSED_MIN_FANOUT_HARD` | Hard floor for condensation grouping during maintenance and repair flows. |
@@ -191,6 +200,15 @@ Compaction summarization resolves candidates in this order:
191
200
 
192
201
  If `summaryModel` already contains a provider prefix such as `anthropic/claude-sonnet-4-20250514`, `summaryProvider` is ignored for that candidate.
193
202
 
203
+ Runtime-managed OAuth providers are supported here too. In particular, `openai-codex` and `github-copilot` auth profiles can be used for summary and expansion calls without a separate API key.
204
+
205
+ A practical starting point for cost-sensitive setups is:
206
+
207
+ ```env
208
+ LCM_SUMMARY_MODEL=openai/gpt-5.4-mini
209
+ LCM_EXPANSION_MODEL=openai/gpt-5.4-mini
210
+ ```
211
+
194
212
  ### Session pattern matching
195
213
 
196
214
  `ignoreSessionPatterns` and `statelessSessionPatterns` use full session keys.
@@ -228,16 +246,17 @@ These settings are not part of `plugins.entries.lossless-claw.config`, but they
228
246
 
229
247
  | Env var | Default | Purpose |
230
248
  | --- | --- | --- |
249
+ | `OPENCLAW_STATE_DIR` | `~/.openclaw` | Active state directory for the OpenClaw gateway. When set, all path defaults (database, large files, auth profiles, secrets) resolve relative to this directory instead of `~/.openclaw`. Set automatically by OpenClaw for non-default profiles. |
231
250
  | `LCM_TUI_CONVERSATION_WINDOW_SIZE` | `200` | Number of messages `lcm-tui` loads per keyset-paged conversation window. |
232
251
 
233
252
  ## Database operations
234
253
 
235
- The SQLite database lives at `databasePath` or `LCM_DATABASE_PATH`. The default path is `${HOME}/.openclaw/lcm.db`.
254
+ The SQLite database lives at `databasePath` or `LCM_DATABASE_PATH`. The default path is `${OPENCLAW_STATE_DIR}/lcm.db` (resolves to `~/.openclaw/lcm.db` when `OPENCLAW_STATE_DIR` is not set).
236
255
 
237
256
  Inspect it with:
238
257
 
239
258
  ```bash
240
- sqlite3 ~/.openclaw/lcm.db
259
+ sqlite3 "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db"
241
260
 
242
261
  SELECT COUNT(*) FROM conversations;
243
262
  SELECT * FROM context_items WHERE conversation_id = 1 ORDER BY ordinal;
@@ -248,8 +267,8 @@ SELECT summary_id, depth, token_count FROM summaries ORDER BY token_count DESC L
248
267
  Back it up with:
249
268
 
250
269
  ```bash
251
- cp ~/.openclaw/lcm.db ~/.openclaw/lcm.db.backup
252
- sqlite3 ~/.openclaw/lcm.db ".backup ~/.openclaw/lcm.db.backup"
270
+ cp "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db" "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db.backup"
271
+ sqlite3 "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db" ".backup ${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db.backup"
253
272
  ```
254
273
 
255
274
  ## Disabling lossless-claw
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "id": "lossless-claw",
3
+ "kind": "context-engine",
3
4
  "skills": [
4
5
  "skills/lossless-claw"
5
6
  ],
@@ -20,6 +21,10 @@
20
21
  "label": "Fresh Tail Count",
21
22
  "help": "Number of recent messages protected from compaction"
22
23
  },
24
+ "freshTailMaxTokens": {
25
+ "label": "Fresh Tail Max Tokens",
26
+ "help": "Optional token cap for the protected fresh tail; the newest message is always preserved"
27
+ },
23
28
  "leafChunkTokens": {
24
29
  "label": "Leaf Chunk Tokens",
25
30
  "help": "Maximum source tokens per leaf compaction chunk before summarization"
@@ -58,11 +63,15 @@
58
63
  },
59
64
  "dbPath": {
60
65
  "label": "Database Path",
61
- "help": "Path to LCM SQLite database (default: ~/.openclaw/lcm.db)"
66
+ "help": "Path to LCM SQLite database (default: <OPENCLAW_STATE_DIR>/lcm.db; falls back to ~/.openclaw/lcm.db)"
62
67
  },
63
68
  "databasePath": {
64
69
  "label": "Database Path",
65
- "help": "Path to LCM SQLite database (preferred key; alias of dbPath)"
70
+ "help": "Path to LCM SQLite database (preferred key; alias of dbPath, default: <OPENCLAW_STATE_DIR>/lcm.db)"
71
+ },
72
+ "largeFilesDir": {
73
+ "label": "Large Files Directory",
74
+ "help": "Directory for persisting large-file text payloads (default: <stateDir>/lcm-files). Uses OPENCLAW_STATE_DIR when set."
66
75
  },
67
76
  "ignoreSessionPatterns": {
68
77
  "label": "Ignored Sessions",
@@ -168,6 +177,10 @@
168
177
  "label": "Prune HEARTBEAT_OK",
169
178
  "help": "Retroactively delete HEARTBEAT_OK turn cycles from LCM storage"
170
179
  },
180
+ "transcriptGcEnabled": {
181
+ "label": "Transcript GC",
182
+ "help": "Enable transcript rewrite GC during maintain(); disabled by default"
183
+ },
171
184
  "fallbackProviders": {
172
185
  "label": "Fallback Providers",
173
186
  "help": "Explicit fallback provider/model pairs for compaction summarization (e.g., [{\"provider\": \"anthropic\", \"model\": \"claude-haiku-4-5\"}])"
@@ -193,6 +206,10 @@
193
206
  "type": "integer",
194
207
  "minimum": 1
195
208
  },
209
+ "freshTailMaxTokens": {
210
+ "type": "integer",
211
+ "minimum": 0
212
+ },
196
213
  "leafChunkTokens": {
197
214
  "type": "integer",
198
215
  "minimum": 1
@@ -341,8 +358,15 @@
341
358
  "pruneHeartbeatOk": {
342
359
  "type": "boolean"
343
360
  },
361
+ "transcriptGcEnabled": {
362
+ "type": "boolean"
363
+ },
344
364
  "databasePath": {
345
- "description": "Path to LCM SQLite database (alias for dbPath)",
365
+ "description": "Path to LCM SQLite database (preferred key; alias of dbPath, default: <OPENCLAW_STATE_DIR>/lcm.db)",
366
+ "type": "string"
367
+ },
368
+ "largeFilesDir": {
369
+ "description": "Directory for persisting large-file text payloads (default: <OPENCLAW_STATE_DIR>/lcm-files)",
346
370
  "type": "string"
347
371
  },
348
372
  "fallbackProviders": {
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@martian-engineering/lossless-claw",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "Lossless Context Management plugin for OpenClaw — DAG-based conversation summarization with incremental compaction",
5
5
  "type": "module",
6
- "main": "index.ts",
6
+ "main": "dist/index.js",
7
7
  "license": "MIT",
8
8
  "author": "Josh Lehman <josh@martian.engineering>",
9
9
  "keywords": [
@@ -16,14 +16,14 @@
16
16
  "dag"
17
17
  ],
18
18
  "scripts": {
19
+ "build": "esbuild index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --external:openclaw --external:\"@mariozechner/*\"",
19
20
  "changeset": "changeset",
20
- "release:verify": "npm test && npm pack --dry-run",
21
+ "release:verify": "npm run build && npm test && npm pack --dry-run",
21
22
  "test": "vitest run --dir test",
22
23
  "version-packages": "changeset version"
23
24
  },
24
25
  "files": [
25
- "index.ts",
26
- "src/**/*.ts",
26
+ "dist/",
27
27
  "skills/",
28
28
  "openclaw.plugin.json",
29
29
  "docs/",
@@ -38,6 +38,7 @@
38
38
  "devDependencies": {
39
39
  "@changesets/changelog-github": "^0.6.0",
40
40
  "@changesets/cli": "^2.30.0",
41
+ "esbuild": "^0.28.0",
41
42
  "typescript": "^5.7.0",
42
43
  "vitest": "^3.0.0"
43
44
  },
@@ -49,7 +50,7 @@
49
50
  },
50
51
  "openclaw": {
51
52
  "extensions": [
52
- "./index.ts"
53
+ "./dist/index.js"
53
54
  ]
54
55
  },
55
56
  "repository": {
@@ -12,8 +12,9 @@ Start here:
12
12
  1. Confirm whether the user needs configuration help, diagnostics, recall-tool guidance, or session-lifecycle guidance.
13
13
  2. If they need a quick health check, tell them to run `/lossless` (`/lcm` is the shorter alias).
14
14
  3. If they suspect summary corruption or truncation, use `/lossless doctor`.
15
- 4. If they ask how `/new` or `/reset` interacts with LCM, read the session-lifecycle reference before answering.
16
- 5. Load the relevant reference file instead of improvising details from memory.
15
+ 4. If they want high-confidence junk/session cleanup guidance, use `/lossless doctor clean` before recommending any deletes.
16
+ 5. If they ask how `/new` or `/reset` interacts with LCM, read the session-lifecycle reference before answering.
17
+ 6. Load the relevant reference file instead of improvising details from memory.
17
18
 
18
19
  Reference map:
19
20
 
@@ -50,3 +50,15 @@ It looks for known summary-health markers that indicate:
50
50
  - truncated summary artifacts near the end of stored content
51
51
 
52
52
  This gives users one place to answer the question “is my summary graph healthy?” without introducing a broader mutation surface.
53
+
54
+ ## What `/lcm doctor clean` tells you
55
+
56
+ The cleaners flow is also diagnostic first.
57
+
58
+ It reports high-confidence junk patterns that are structurally safe to review as standalone cleanup candidates, including:
59
+
60
+ - archived subagent sessions
61
+ - cron sessions
62
+ - NULL-key orphaned subagent context conversations
63
+
64
+ This keeps cleanup discovery separate from summary-health diagnostics while still using the same native command surface.
@@ -43,6 +43,20 @@ Good starting range:
43
43
 
44
44
  - `32` to `64`
45
45
 
46
+ ### `freshTailMaxTokens`
47
+
48
+ Optional token cap for the protected fresh tail.
49
+
50
+ Why it matters:
51
+
52
+ - Prevents a few huge tool results from making the "fresh" suffix effectively uncompactable.
53
+ - Still preserves the newest message even if that single message exceeds the cap.
54
+
55
+ Good starting range:
56
+
57
+ - Leave unset unless large tool outputs are forcing avoidable cost or overflow.
58
+ - Start around `12000` to `32000` when you want a softer, size-aware fresh tail.
59
+
46
60
  ### `leafChunkTokens`
47
61
 
48
62
  Caps how much raw material gets summarized into one leaf summary.
@@ -154,6 +168,7 @@ Why it matters:
154
168
 
155
169
  - useful for custom deployments, testing, or isolating environments
156
170
  - wrong path selection is a common reason operators think LCM is empty or not growing
171
+ - the default resolves to `${OPENCLAW_STATE_DIR}/lcm.db` (falls back to `~/.openclaw/lcm.db`)
157
172
 
158
173
  ### `databasePath`
159
174
 
@@ -164,6 +179,15 @@ Why it matters:
164
179
  - this is the documented key new config should use
165
180
  - `dbPath` is still accepted for compatibility
166
181
 
182
+ ### `largeFilesDir`
183
+
184
+ Directory for persisting large-file text payloads externalised from the transcript.
185
+
186
+ Why it matters:
187
+
188
+ - defaults to `${OPENCLAW_STATE_DIR}/lcm-files`; on multi-profile hosts each profile stores files in its own state directory automatically
189
+ - override with `LCM_LARGE_FILES_DIR` or set `largeFilesDir` in plugin config when you want an explicit path
190
+
167
191
  ### `largeFileThresholdTokens`
168
192
 
169
193
  Threshold for externalizing oversized tool/file payloads out of the main transcript into large-file storage.
@@ -173,6 +197,15 @@ Why it matters:
173
197
  - lower values externalize more aggressively
174
198
  - higher values keep more payload inline but can bloat storage and compaction inputs
175
199
 
200
+ ### `transcriptGcEnabled`
201
+
202
+ Controls whether `maintain()` rewrites transcript entries for already-externalized tool results.
203
+
204
+ Why it matters:
205
+
206
+ - keep this off unless you want transcript GC to mutate the live session file during maintenance
207
+ - the default is `false`
208
+
176
209
  ## Compaction timing and shape
177
210
 
178
211
  ### `contextThreshold`
@@ -183,6 +216,10 @@ See high-impact settings above.
183
216
 
184
217
  See high-impact settings above.
185
218
 
219
+ ### `freshTailMaxTokens`
220
+
221
+ See high-impact settings above.
222
+
186
223
  ### `leafChunkTokens`
187
224
 
188
225
  See high-impact settings above.
@@ -29,6 +29,19 @@ What it should help confirm:
29
29
  - whether truncation markers exist
30
30
  - which conversations are affected most
31
31
 
32
+ ### `/lossless doctor clean`
33
+
34
+ Use this when the user wants read-only diagnostics for high-confidence junk patterns before any cleanup.
35
+
36
+ It should help confirm:
37
+
38
+ - whether archived subagent sessions are present
39
+ - whether cron sessions are accumulating unexpectedly
40
+ - whether NULL-key orphaned subagent conversations are present
41
+ - which high-confidence filters match the most conversations and messages
42
+
43
+ This command is read-only. Use it to identify likely cleanup candidates before taking any separate cleanup action.
44
+
32
45
  ## Interpreting common states
33
46
 
34
47
  ### `/lossless` tokens vs `/status` context
package/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export { default } from "./src/plugin/index.js";
2
- export { buildCompleteSimpleOptions, shouldOmitTemperatureForApi } from "./src/plugin/index.js";