@martian-engineering/lossless-claw 0.13.0 → 0.13.2

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.
@@ -84,6 +84,7 @@ Most installations only need to override a handful of keys. If you want a comple
84
84
  "enableSummaryThinking": true,
85
85
  "maxAssemblyTokenBudget": 30000,
86
86
  "summaryMaxOverageFactor": 3,
87
+ "fallbackMaxTokens": 512,
87
88
  "customInstructions": "",
88
89
  "circuitBreakerThreshold": 5,
89
90
  "circuitBreakerCooldownMs": 1800000,
@@ -141,13 +142,19 @@ Notes on the example:
141
142
  Install with OpenClaw's plugin installer:
142
143
 
143
144
  ```bash
144
- openclaw plugins install @martian-engineering/lossless-claw
145
+ openclaw plugins install @martian-engineering/lossless-claw@latest
145
146
  ```
146
147
 
147
148
  If you are running from a local OpenClaw checkout:
148
149
 
149
150
  ```bash
150
- pnpm openclaw plugins install @martian-engineering/lossless-claw
151
+ pnpm openclaw plugins install @martian-engineering/lossless-claw@latest
152
+ ```
153
+
154
+ Use exact versions only for rollback or reproducible canary testing. OpenClaw treats an exact install spec such as `@martian-engineering/lossless-claw@0.12.0` as pinned, so plugin update sync will not follow newer LCM releases until you return to the moving track:
155
+
156
+ ```bash
157
+ openclaw plugins update @martian-engineering/lossless-claw@latest
151
158
  ```
152
159
 
153
160
  For local plugin development, link a working copy:
@@ -176,17 +183,17 @@ openclaw plugins install --link /path/to/lossless-claw
176
183
  | `enableSummaryThinking` | `boolean` | `true` | `LCM_ENABLE_SUMMARY_THINKING` | When true, requests low reasoning budget from the model during summarization calls. Set to false to disable reasoning and keep summarization output concise. |
177
184
  | `proactiveThresholdCompactionMode` | `"deferred" \| "inline"` | `"deferred"` | `LCM_PROACTIVE_THRESHOLD_COMPACTION_MODE` | Controls whether proactive threshold compaction is deferred into maintenance debt by default or run inline for legacy behavior. |
178
185
  | `autoRotateSessionFiles.enabled` | `boolean` | `true` | `LCM_AUTO_ROTATE_SESSION_FILES_ENABLED` | Enables automatic rotation for oversized LCM-managed session JSONL files. |
179
- | `autoRotateSessionFiles.createBackups` | `boolean` | `false` | `LCM_AUTO_ROTATE_SESSION_FILES_CREATE_BACKUPS` | Creates or replaces the rolling `rotate-latest` SQLite backup before automatic session-file rotation. Manual `/lcm rotate` backups are always created. |
186
+ | `autoRotateSessionFiles.createBackups` | `boolean` | `false` | `LCM_AUTO_ROTATE_SESSION_FILES_CREATE_BACKUPS` | Creates or replaces the rolling `rotate-latest` SQLite backup before automatic session-file rotation. Manual `/lossless rotate` backups are always created. |
180
187
  | `autoRotateSessionFiles.sizeBytes` | `integer` | `2097152` | `LCM_AUTO_ROTATE_SESSION_FILES_SIZE_BYTES` | Byte threshold that triggers automatic session-file rotation. |
181
188
  | `autoRotateSessionFiles.startup` | `"rotate" \| "warn" \| "off"` | `"rotate"` | `LCM_AUTO_ROTATE_SESSION_FILES_STARTUP` | Startup behavior for oversized indexed OpenClaw session transcripts that also have active LCM bootstrap state. |
182
- | `autoRotateSessionFiles.runtime` | `"rotate" \| "warn" \| "off"` | `"rotate"` | `LCM_AUTO_ROTATE_SESSION_FILES_RUNTIME` | Runtime behavior after post-turn checks. Runtime `rotate` logs deferral for active session JSONL rewrites and leaves direct rotation to startup or manual `/lcm rotate`. |
189
+ | `autoRotateSessionFiles.runtime` | `"rotate" \| "warn" \| "off"` | `"rotate"` | `LCM_AUTO_ROTATE_SESSION_FILES_RUNTIME` | Runtime behavior after post-turn checks. Runtime `rotate` logs deferral for active session JSONL rewrites and leaves direct rotation to startup or manual `/lossless rotate`. |
183
190
  | `independentLogFile.enabled` | `boolean` | `true` | `LCM_LOG_FILE_ENABLED` | Writes lossless-claw JSONL logs to an independent plugin-owned file in addition to OpenClaw's runtime logger. |
184
191
  | `independentLogFile.file` | `string` | `/tmp/openclaw/lossless-claw-YYYY-MM-DD.log` | `LCM_LOG_FILE` | Optional log path. A dated `lossless-claw-YYYY-MM-DD.log` path rolls over daily. |
185
192
  | `independentLogFile.maxFileBytes` | `integer` | `104857600` | `LCM_LOG_MAX_FILE_BYTES` | Size threshold for rotating the active lossless-claw log file to `.1.log` through `.5.log`. |
186
193
 
187
194
  > **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.
188
195
 
189
- Automatic session-file rotation rewrites only the live session transcript, keeps the active LCM conversation and durable history intact, and refreshes the bootstrap checkpoint. Before manual or startup rewrites, rotation forces leaf-only compaction for raw context outside the preserved tail so trimmed transcript messages are covered by LCM summaries without running unrelated summary-condensation passes. Startup rotation first scans OpenClaw's current indexed session stores for configured agents, then intersects those candidates with active LCM conversations and matching bootstrap file mappings. Runtime rotation checks from `afterTurn()` and `maintain()` intentionally do not directly rewrite active session JSONL because embedded prompt-lock fences can still be open while tool-call loops and host background maintenance overlap; runtime `rotate` logs a deferral until startup, manual `/lcm rotate`, or a future host-owned full-transcript rewrite primitive is available. Automatic rotation does not create a SQLite backup by default; set `autoRotateSessionFiles.createBackups` to `true` to make startup rotation create one pre-rotation LCM database backup for the batch before any transcript is rewritten. Manual `/lcm rotate` always keeps its backup-backed behavior regardless of this flag. Rotation never runs for ignored sessions, stateless sessions, or sessions without active LCM state. The preserved JSONL tail follows the existing rotate behavior, which is controlled by `freshTailCount`. Transcript GC uses the host-provided `rewriteTranscriptEntries` primitive and defers until host-approved background maintenance when `transcriptGcEnabled` is enabled.
196
+ Automatic session-file rotation rewrites only the live session transcript, keeps the active LCM conversation and durable history intact, and refreshes the bootstrap checkpoint. Before manual or startup rewrites, rotation forces leaf-only compaction for raw context outside the preserved tail so trimmed transcript messages are covered by LCM summaries without running unrelated summary-condensation passes. Startup rotation first scans OpenClaw's current indexed session stores for configured agents, then intersects those candidates with active LCM conversations and matching bootstrap file mappings. Runtime rotation checks from `afterTurn()` and `maintain()` intentionally do not directly rewrite active session JSONL because embedded prompt-lock fences can still be open while tool-call loops and host background maintenance overlap; runtime `rotate` logs a deferral until startup, manual `/lossless rotate`, or a future host-owned full-transcript rewrite primitive is available. Automatic rotation does not create a SQLite backup by default; set `autoRotateSessionFiles.createBackups` to `true` to make startup rotation create one pre-rotation LCM database backup for the batch before any transcript is rewritten. Manual `/lossless rotate` always keeps its backup-backed behavior regardless of this flag. Rotation never runs for ignored sessions, stateless sessions, or sessions without active LCM state. The preserved JSONL tail follows the existing rotate behavior, which is controlled by `freshTailCount`. Transcript GC uses the host-provided `rewriteTranscriptEntries` primitive and defers until host-approved background maintenance when `transcriptGcEnabled` is enabled.
190
197
 
191
198
  Lossless-claw writes routine operational JSONL logs by default at `/tmp/openclaw/lossless-claw-YYYY-MM-DD.log`, beside OpenClaw's `/tmp/openclaw/openclaw-YYYY-MM-DD.log`. Routine info and debug lines go to the independent file instead of the shared OpenClaw log. Startup banners and warning/error lines still go through OpenClaw's runtime logger so gateway-level startup and failure diagnostics remain visible. The independent file follows the same practical rotation model as OpenClaw: a dated filename rolls over when the local date changes, stale dated files are pruned after 3 days, and an oversized active file is rotated through `.1.log` to `.5.log`.
192
199
 
@@ -216,6 +223,7 @@ Every automatic decision emits grep-able log lines prefixed with `[lcm] auto-rot
216
223
  | `leafTargetTokens` | `integer` | `2400` | `LCM_LEAF_TARGET_TOKENS` | Prompt target for leaf summary size. |
217
224
  | `condensedTargetTokens` | `integer` | `2000` | `LCM_CONDENSED_TARGET_TOKENS` | Prompt target for condensed summary size. |
218
225
  | `summaryMaxOverageFactor` | `number` | `3` | `LCM_SUMMARY_MAX_OVERAGE_FACTOR` | Hard ceiling multiplier before oversized summaries are deterministically truncated. |
226
+ | `fallbackMaxTokens` | `integer` | `512` | `LCM_FALLBACK_MAX_TOKENS` | Maximum token budget for deterministic fallback summaries when the LLM summarizer is unavailable. Values below 64 are ignored. |
219
227
  | `largeFileThresholdTokens` | `integer` | `25000` | `LCM_LARGE_FILE_TOKEN_THRESHOLD` | Preferred key for the token threshold that routes text attachments into large-file summarization. |
220
228
  | `largeFileTokenThreshold` | `integer` | alias of `largeFileThresholdTokens` | `LCM_LARGE_FILE_TOKEN_THRESHOLD` | Legacy alias accepted by the runtime. Prefer `largeFileThresholdTokens` in new config. |
221
229
  | `maxAssemblyTokenBudget` | `integer` | unset | `LCM_MAX_ASSEMBLY_TOKEN_BUDGET` | Optional hard cap for assembly and threshold evaluation, useful with smaller-context models. |
@@ -380,19 +388,19 @@ Lossless-claw now defaults `proactiveThresholdCompactionMode` to `deferred`.
380
388
  - `assemble()` leaves pending threshold debt for after-turn background drain or host-approved `maintain()` while the live prompt is still within budget
381
389
  - `assemble()` only consumes pending threshold debt synchronously as an emergency safeguard when the live prompt estimate is already over the active token budget
382
390
  - old non-threshold debt from earlier builds is revalidated; if the conversation is no longer over threshold, it is cleared as a no-op
383
- - `/lcm status` / `/lossless status` shows the current maintenance state, including pending/running/last-failure details
391
+ - `/lossless status` (`/lcm status` alias) shows the current maintenance state, including pending/running/last-failure details
384
392
  - status output also surfaces the latest API/cache telemetry as diagnostics, not as a deferral gate
385
393
  - set `proactiveThresholdCompactionMode` to `inline` only if you need the legacy inline proactive compaction behavior for compatibility
386
394
 
387
- ### `/lcm rotate`
395
+ ### `/lossless rotate`
388
396
 
389
- `/lcm rotate` exists for a different use case than `/new` or `/reset`:
397
+ `/lossless rotate` exists for a different use case than `/new` or `/reset`:
390
398
 
391
399
  - `/new` keeps the same active LCM conversation row and only prunes context.
392
400
  - `/reset` changes OpenClaw session flow, which is sometimes more disruptive than users want.
393
- - `/lcm rotate` keeps the live OpenClaw session identity and the same active LCM conversation row, but rewrites the backing transcript into a compact preserved-tail form.
401
+ - `/lossless rotate` keeps the live OpenClaw session identity and the same active LCM conversation row, but rewrites the backing transcript into a compact preserved-tail form.
394
402
 
395
- Before rotating, Lossless-claw replaces one rolling `rotate-latest` SQLite backup. It then rewrites the current session transcript and checkpoints the same conversation at the new transcript frontier so bootstrap does not replay the dropped transcript history. Existing summaries, context items, and conversation identity stay in place. If you want additional timestamped snapshots, run `/lcm backup` explicitly before `/lcm rotate`.
403
+ Before rotating, Lossless-claw replaces one rolling `rotate-latest` SQLite backup. It then rewrites the current session transcript and checkpoints the same conversation at the new transcript frontier so bootstrap does not replay the dropped transcript history. Existing summaries, context items, and conversation identity stay in place. If you want additional timestamped snapshots, run `/lossless backup` explicitly before `/lossless rotate`.
396
404
 
397
405
  ## Environment-only knobs outside plugin config
398
406
 
@@ -428,7 +436,7 @@ sqlite3 "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/lcm.db" ".backup ${OPENCLAW_STAT
428
436
  Or from a supported OpenClaw chat/native command surface:
429
437
 
430
438
  ```text
431
- /lcm backup
439
+ /lossless backup
432
440
  ```
433
441
 
434
442
  ## Disabling lossless-claw
@@ -5,6 +5,16 @@
5
5
  "activation": {
6
6
  "onStartup": true
7
7
  },
8
+ "commandAliases": [
9
+ {
10
+ "name": "lossless",
11
+ "kind": "runtime-slash"
12
+ },
13
+ {
14
+ "name": "lcm",
15
+ "kind": "runtime-slash"
16
+ }
17
+ ],
8
18
  "skills": [
9
19
  "skills/lossless-claw"
10
20
  ],
@@ -193,6 +203,10 @@
193
203
  "label": "Summary Max Overage Factor",
194
204
  "help": "Maximum allowed overage factor for summaries relative to target tokens (default 3). Summaries exceeding this are deterministically truncated."
195
205
  },
206
+ "fallbackMaxTokens": {
207
+ "label": "Fallback Max Tokens",
208
+ "help": "Maximum token budget for deterministic fallback summaries when the LLM summarizer fails (default 512, minimum 64)"
209
+ },
196
210
  "customInstructions": {
197
211
  "label": "Custom Instructions",
198
212
  "help": "Natural language instructions injected into all summarization prompts (e.g., formatting rules, tone control)"
@@ -515,6 +529,10 @@
515
529
  "type": "number",
516
530
  "minimum": 1
517
531
  },
532
+ "fallbackMaxTokens": {
533
+ "type": "integer",
534
+ "minimum": 64
535
+ },
518
536
  "customInstructions": {
519
537
  "type": "string"
520
538
  },
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "@martian-engineering/lossless-claw",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "description": "Lossless Context Management plugin for OpenClaw — DAG-based conversation summarization with threshold compaction",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
+ "bin": {
8
+ "lossless-claw-migrate-sessions": "dist/migrate-sessions.js"
9
+ },
7
10
  "license": "MIT",
8
11
  "author": "Josh Lehman <josh@martian.engineering>",
9
12
  "keywords": [
@@ -16,7 +19,7 @@
16
19
  "dag"
17
20
  ],
18
21
  "scripts": {
19
- "build": "esbuild index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --external:openclaw --external:\"@earendil-works/*\" --minify-whitespace",
22
+ "build": "esbuild index.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/index.js --external:openclaw --external:\"@earendil-works/*\" --minify-whitespace && esbuild src/cli/migrate-sessions.ts --bundle --platform=node --target=node22 --format=esm --outfile=dist/migrate-sessions.js --external:openclaw --external:\"@earendil-works/*\" --minify-whitespace",
20
23
  "changeset": "changeset",
21
24
  "plugin-inspector:ci": "npm exec --yes --package @openclaw/plugin-inspector@0.3.11 -- plugin-inspector ci --plugin-root . --out plugin-inspector-reports",
22
25
  "release:verify": "npm run typecheck && npm run build && npm test && npm pack --dry-run",
@@ -39,13 +42,13 @@
39
42
  },
40
43
  "devDependencies": {
41
44
  "@changesets/changelog-github": "^0.6.0",
42
- "@changesets/cli": "^2.30.0",
43
- "@earendil-works/pi-agent-core": "^0.79.0",
44
- "@earendil-works/pi-ai": "^0.79.0",
45
- "@earendil-works/pi-coding-agent": "^0.79.0",
46
- "esbuild": "^0.28.0",
45
+ "@changesets/cli": "^2.31.0",
46
+ "@earendil-works/pi-agent-core": "^0.79.8",
47
+ "@earendil-works/pi-ai": "^0.79.8",
48
+ "@earendil-works/pi-coding-agent": "^0.79.8",
49
+ "esbuild": "^0.28.1",
47
50
  "typescript": "^5.7.0",
48
- "vitest": "^3.0.0"
51
+ "vitest": "^4.1.9"
49
52
  },
50
53
  "peerDependencies": {
51
54
  "openclaw": ">=2026.5.28"
@@ -15,7 +15,8 @@ Start here:
15
15
  4. If they suspect summary corruption or truncation, use `/lossless doctor`.
16
16
  5. If they want high-confidence junk/session cleanup guidance, use `/lossless doctor clean` before recommending any deletes.
17
17
  6. If they ask how `/new`, `/reset`, or `/lossless rotate` interacts with LCM, read the session-lifecycle reference before answering.
18
- 7. Load the relevant reference file instead of improvising details from memory.
18
+ 7. If they ask how to import old or past OpenClaw conversation data into Lossless, read the session-lifecycle reference before answering.
19
+ 8. Load the relevant reference file instead of improvising details from memory.
19
20
 
20
21
  Reference map:
21
22
 
@@ -23,13 +24,13 @@ Reference map:
23
24
  - Internal model and data flow: `references/architecture.md`
24
25
  - Diagnostics and summary-health workflow: `references/diagnostics.md`
25
26
  - Recall tools and when to use them: `references/recall-tools.md`
26
- - `/new`, `/reset`, and `/lossless rotate` behavior with current lossless-claw session mapping: `references/session-lifecycle.md`
27
+ - `/new`, `/reset`, `/lossless rotate`, and past-session import behavior with current lossless-claw session mapping: `references/session-lifecycle.md`
27
28
 
28
29
  Working rules:
29
30
 
30
31
  - Prioritize explaining why a setting matters, not just what it does.
31
32
  - Prefer the native plugin command surface for MVP workflows (`/lossless`, with `/lcm` as alias).
32
33
  - Do not assume the Go TUI is installed.
33
- - Do not recommend advanced rewrite/backfill/transplant/dissolve flows unless the user explicitly asks for non-MVP internals.
34
+ - Do not recommend advanced rewrite/backfill/transplant/dissolve flows unless the user explicitly asks for non-MVP internals. If the user specifically asks to import old or past OpenClaw conversation data into Lossless, recommend the packaged session migration CLI instead of TUI backfill/surgery flows.
34
35
  - For exact evidence retrieval from compacted history, guide the user toward recall tools instead of guessing from summaries.
35
36
  - When users compare `/lossless` to `/status`, explain that they report different layers: `/lossless` shows LCM-side frontier/summary metrics, while `/status` shows the last assembled runtime prompt snapshot.
@@ -29,7 +29,7 @@ Bad summaries do not stay local:
29
29
 
30
30
  That is why configuration choices around compaction thresholds and summary model quality matter operationally.
31
31
 
32
- ## What `/lcm` tells you
32
+ ## What `/lossless` tells you
33
33
 
34
34
  The MVP command surface focuses on operational facts:
35
35
 
@@ -40,7 +40,7 @@ The MVP command surface focuses on operational facts:
40
40
  - total summarized source-token coverage when available
41
41
  - broken or truncated summary presence
42
42
 
43
- ## What `/lcm doctor` tells you
43
+ ## What `/lossless doctor` tells you
44
44
 
45
45
  The MVP doctor flow is diagnostic only.
46
46
 
@@ -51,7 +51,7 @@ It looks for known summary-health markers that indicate:
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
53
 
54
- ## What `/lcm doctor clean` tells you
54
+ ## What `/lossless doctor clean` tells you
55
55
 
56
56
  The cleaners flow is also diagnostic first.
57
57
 
@@ -347,7 +347,7 @@ Why it matters:
347
347
  - `deferred` is the default and avoids foreground turn stalls by recording one coalesced maintenance row per conversation
348
348
  - `deferred` also stores provider/model/cache telemetry so Anthropic-family sessions can avoid rewriting a still-hot prompt cache
349
349
  - `inline` preserves the legacy foreground compaction path for hosts that do not yet support deferred execution
350
- - `/lossless status` and `/lcm status` surface pending/running/last-failure maintenance state so operators can see when compaction is queued
350
+ - `/lossless status` (`/lcm status` alias) surfaces pending/running/last-failure maintenance state so operators can see when compaction is queued
351
351
  - after-turn background drain and host-approved `maintain()` consume routine threshold debt; `assemble()` only drains pending threshold debt synchronously as an emergency safeguard when the live prompt estimate is already over budget
352
352
 
353
353
  ### `autoRotateSessionFiles`
@@ -365,7 +365,7 @@ Defaults:
365
365
  Why it matters:
366
366
 
367
367
  - prevents very large OpenClaw session JSONL files from choking fallback/gateway startup while LCM owns the durable context
368
- - runtime rotation only creates or replaces the rolling `rotate-latest` DB backup when `createBackups` is `true`; manual `/lossless rotate` / `/lcm rotate` always keeps its backup-backed behavior
368
+ - runtime rotation only creates or replaces the rolling `rotate-latest` DB backup when `createBackups` is `true`; manual `/lossless rotate` always keeps its backup-backed behavior
369
369
  - runtime JSONL rewrites run from `afterTurn()` after the host turn completes; `maintain()` skips rotation and leaves it to `afterTurn()` or startup because background maintenance can overlap an embedded model call
370
370
  - startup scans OpenClaw's current indexed session stores for configured agents, intersects those candidates with active LCM bootstrap state, and creates one pre-rotation DB backup for the startup batch only when `createBackups` is `true`
371
371
  - only runs for active, writable LCM conversations; ignored sessions, stateless sessions, sessions outside the indexed startup candidate set, and sessions without active LCM state are skipped
@@ -721,6 +721,25 @@ Why it matters:
721
721
  - guards against runaway summaries that are much larger than their target budget
722
722
  - useful when summary models are verbose or unstable
723
723
 
724
+ ### `fallbackMaxTokens`
725
+
726
+ | | |
727
+ | --- | --- |
728
+ | Type | `integer` |
729
+ | Default | `512` |
730
+ | Minimum | `64` |
731
+ | Env | `LCM_FALLBACK_MAX_TOKENS` |
732
+
733
+ Maximum token budget for deterministic fallback summaries when the LLM summarizer is unavailable.
734
+
735
+ Why it matters:
736
+
737
+ - when the LLM summarizer fails (auth errors, timeout, empty output), Lossless falls back to a purely local truncation-based summary
738
+ - this fallback is bounded by `fallbackMaxTokens` so it cannot balloon the context
739
+ - values below `64` are ignored so the required fallback marker can fit inside the configured budget
740
+ - lower values produce more aggressive truncation; higher values preserve more source text at the cost of larger fallback summaries
741
+ - the default `512` is conservative; raise it if you prefer richer fallback summaries over more aggressive truncation
742
+
724
743
  ### `summaryMaxCallsPerWindow`, `summaryCallWindowMs`, and `summarySpendBackoffMs`
725
744
 
726
745
  Bounds model-backed compaction and large-file summarization calls per session.
@@ -788,7 +807,7 @@ Design note: stripping happens at compaction time, not at message ingestion. Th
788
807
 
789
808
  Useful interpretation notes:
790
809
 
791
- - `tokens in context` is the current LCM frontier token count in the live LCM state.
810
+ - `LCM frontier tokens` is the current LCM frontier token count in the live LCM state.
792
811
  - `compression ratio` is shown as a rounded `1:N`, which is easier to read than a tiny percentage for heavily compacted conversations.
793
812
  - `/status` may still show a different context number because it reflects the runtime prompt that was actually assembled and sent on the last turn.
794
813
 
@@ -73,6 +73,40 @@ When answering users:
73
73
  - explain that cron scheduler session keys are isolated per runtime run while preserving archived prior runs
74
74
  - if they need a truly separate LCM history, use a different session key context (for example a different chat/thread/binding) or explicit non-MVP migration/surgery tools
75
75
 
76
+ ## Importing past conversation data
77
+
78
+ If a user explicitly asks how to import old or past OpenClaw conversation data into Lossless, recommend the packaged session migration CLI:
79
+
80
+ ```bash
81
+ npx --package @martian-engineering/lossless-claw@latest lossless-claw-migrate-sessions --state-dir ~/.openclaw
82
+ ```
83
+
84
+ That command name, `lossless-claw-migrate-sessions`, is the npm package executable declared by lossless-claw. It backfills OpenClaw JSONL session files into `lcm.db`.
85
+
86
+ Use it when:
87
+
88
+ - lossless-claw was installed after useful OpenClaw sessions already existed
89
+ - lossless-claw was disabled or missing for a period
90
+ - the user wants historical JSONL sessions imported into Lossless storage
91
+
92
+ Do not present it as:
93
+
94
+ - a background replay loop
95
+ - a summarization or embedding migration
96
+ - a replacement for normal startup bootstrap/crash recovery
97
+ - a general rewrite/transplant/surgery tool
98
+
99
+ Safe recommendation pattern:
100
+
101
+ 1. Run the dry-run command first and inspect the output.
102
+ 2. Apply only after the user confirms the target state directory and import set:
103
+
104
+ ```bash
105
+ npx --package @martian-engineering/lossless-claw@latest lossless-claw-migrate-sessions --state-dir ~/.openclaw --apply
106
+ ```
107
+
108
+ The CLI defaults to `${OPENCLAW_STATE_DIR:-~/.openclaw}` and `${OPENCLAW_STATE_DIR:-~/.openclaw}/lcm.db`. On `--apply`, it creates a timestamped SQLite backup before writing when the database already exists. For narrow imports, suggest `--file <path>`, repeatable `--sessions-dir <path>`, `--since <iso-date>`, or `--limit <n>`.
109
+
76
110
  ## Relation to `/status`
77
111
 
78
112
  This session behavior is separate from `/status` metrics.