@brandry/claude-jsonl-compressor 1.0.0-rc.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/README.md ADDED
@@ -0,0 +1,593 @@
1
+ # Claude JSONL Compressor
2
+
3
+ Strict, model-assisted compression for one Claude Code session transcript, plus an independent byte-preserving compatibility repair for historical `Read.pages` records.
4
+
5
+ **Release:** [`1.0.0-rc.1`](CHANGELOG.md)<br>
6
+ **Engine:** `v10`<br>
7
+ **Model-pack schema:** `v11`<br>
8
+ **License:** GPL-3.0-only<br>
9
+ **Repository:** [brandrylabs/claude-jsonl-compressor](https://github.com/brandrylabs/claude-jsonl-compressor)
10
+
11
+ This project is not affiliated with Anthropic. Claude Code's transcript JSONL is an observed internal format, not a published stable storage API. Always keep the original file or a verified backup.
12
+
13
+ ## What It Does
14
+
15
+ - Compresses one Claude Code JSONL into one current compact-style summary pair plus a recent raw active suffix.
16
+ - Uses a model-authored semantic summary by default, with deterministic evidence selection and validation around it.
17
+ - Excludes rewound/inactive branch text from every Claude-readable output layer.
18
+ - Preserves recent conversation records for Claude rewind.
19
+ - Projects one final `last-prompt` while retaining unknown source fields.
20
+ - Validates UUIDs, parents, sessions, compact metadata and API-level tool pairing.
21
+ - Supports candidate output and transactional replacement of one live `.claude/projects` session.
22
+ - Handles repeated compression, including an explicit prior-summary verbatim mode.
23
+ - Offers an independent byte-level repair that removes unsupported historical `Read.pages` members without reserializing the JSONL.
24
+ - Runs with Python's standard library. No tokenizer or YAML dependency is required.
25
+
26
+ ## Quick Start
27
+
28
+ With this repository installed as a Codex skill, ask Codex:
29
+
30
+ ```text
31
+ Use the claude-jsonl-compressor skill on exactly one Claude Code JSONL.
32
+ Input: C:\data\session.jsonl
33
+ Output: C:\data\session.compressed.jsonl
34
+ Target: about 150k estimated Messages tokens.
35
+ Keep recent raw records for rewind, use the default model-assisted summary, and run validation.
36
+ ```
37
+
38
+ For a live `.claude/projects` file, explicitly request a numbered backup and in-place replacement, confirm that the session is closed, and provide a work directory outside `.claude`. The detailed two-pass CLI workflow appears below.
39
+
40
+ ## Why Model-Assisted By Default
41
+
42
+ Deterministic code can select topology and validate bytes, but it cannot decide which historical arguments, legal distinctions, design rationale or research conclusions matter. Python therefore freezes the active branch and builds a bounded, source-anchored evidence pack; a host model writes the summary; Python then verifies request/evidence digests, anchors, required source excerpts and the final JSONL.
43
+
44
+ The script itself never calls a model or the network. The evidence pack bridges the practical 1M-session-versus-smaller-summarizer gap by including every non-empty older active human message and assistant `text`/`thinking` message in full while excluding inactive branches, recent raw records and low-value structural repetition. U+FFFD is reported without discarding the rest of a mandatory record. If mandatory evidence exceeds either pack ceiling, generation stops instead of sampling semantic history.
45
+
46
+ ## Safety Properties
47
+
48
+ ### Strict resume authority
49
+
50
+ The physically last `type: "last-prompt"` record is authoritative in automatic mode. A malformed latest pointer is an error; the program does not search backward for an older valid pointer and accidentally revive an obsolete branch.
51
+
52
+ Strict active mode rejects:
53
+
54
+ - missing or malformed authority
55
+ - missing leaf or parent
56
+ - parent loops or malformed non-string/empty `parentUuid` values
57
+ - ordinary-message/non-attachment physical parent inversion
58
+ - recurring, pointer-mismatched or otherwise unsafe session lineage
59
+ - duplicate UUIDs anywhere in the file
60
+ - unsafe post-pointer extension
61
+
62
+ Use `--resume-leaf UUID` only for an explicit recovery decision. It is reported as `active-chain-manual-override`, distinct from default strict `active-chain`. Use `--preserve-physical-tail` only as an explicit compatibility mode; it does not provide inactive-branch isolation.
63
+
64
+ An unusual or ambiguous topology is a stop, not an automatic fallback. The CLI exits before creating a pack, candidate, report, backup or other sidecar. A hosting agent may explain one applicable explicit recovery control and ask the user to confirm it in a new instruction; it must not infer that confirmation from the original compression request. Manually spliced transcripts generally require physical-tail compatibility and therefore lose branch/rewind isolation.
65
+
66
+ Current Claude Code reconstructs a conversation from a UUID map and parent links, so physical line order is not universally chronological. This project accepts only same-session `attachment -> attachment` physical inversions on an otherwise complete acyclic chain and writes them back in logical parent order. It also accepts one-way A->B (or A->B->C) session lineage only when a session never recurs and the final leaf and pointer match the final session. All earlier-session records become summary evidence; recent raw records remain entirely in the final session. A tool pair crossing that forced cut is a hard stop.
67
+
68
+ ### Rewound branches stay out
69
+
70
+ The source indexes are partitioned into mutually exclusive sets:
71
+
72
+ | Set | Meaning | May enter summary? | May remain raw? |
73
+ | --- | --- | --- | --- |
74
+ | `summaryIndexes` | Older active-chain records | Yes | No |
75
+ | `rawKeepIndexes` | Recent active-chain records | No | Yes |
76
+ | `sideKeepIndexes` | Policy-approved checkpoint side records | No | Side records only |
77
+ | `controlProjectionIndexes` | Pointer and safe global control records | No | Projected only |
78
+ | `excludedBranchIndexes` | Inactive UUID branches | No | No |
79
+ | `excludedUnattributedIndexes` | Unattributed non-chain records | No | No |
80
+
81
+ Excluded records appear in reports only as counts and digests. Their text is not copied into the model pack, compact summary, deterministic appendix, verbatim prior-summary block or output message chain.
82
+
83
+ ### Transactional writes
84
+
85
+ - Input and candidate bytes are bound by full SHA-256; candidates are staged, flushed, validated and atomically published.
86
+ - Numbered backups use exclusive creation and byte verification. Live replacement also captures and verifies the actual old target before installing the candidate.
87
+ - Failed post-replacement validation restores the captured original. A rollback failure is raised prominently while verified recovery assets remain available.
88
+ - Concurrent target recreation preserves the external target and recovery backups, then fails without publishing the candidate.
89
+ - Parent-directory fsync is best effort and reported; this is not a cross-platform power-loss guarantee.
90
+ - If the live JSONL commits but final report publication fails, the CLI does not undo valid committed data. It prints a `committed-report-failed` receipt with hashes and backup/candidate labels and exits with code 3.
91
+
92
+ ## Requirements
93
+
94
+ - Python 3.10 or newer
95
+ - Node.js 22 or newer only when using the npm command wrappers
96
+ - Claude Code is optional; it is needed only for an explicitly requested runtime `/resume` or `/context` smoke test
97
+
98
+ No Python package installation is required.
99
+
100
+ ## Installation
101
+
102
+ ### Install As A Codex Skill
103
+
104
+ Clone the repository into the Codex skill directory:
105
+
106
+ ```bash
107
+ skill="${CODEX_HOME:-$HOME/.codex}/skills/claude-jsonl-compressor"
108
+ mkdir -p "$(dirname "$skill")"
109
+ git clone https://github.com/brandrylabs/claude-jsonl-compressor.git "$skill"
110
+ ```
111
+
112
+ Windows PowerShell:
113
+
114
+ ```powershell
115
+ $codexHome = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { Join-Path $env:USERPROFILE '.codex' }
116
+ $skill = Join-Path $codexHome 'skills\claude-jsonl-compressor'
117
+ New-Item -ItemType Directory -Force (Split-Path -Parent $skill) | Out-Null
118
+ git clone https://github.com/brandrylabs/claude-jsonl-compressor.git $skill
119
+ ```
120
+
121
+ Update or uninstall the skill:
122
+
123
+ ```bash
124
+ git -C "${CODEX_HOME:-$HOME/.codex}/skills/claude-jsonl-compressor" pull --ff-only
125
+ rm -rf "${CODEX_HOME:-$HOME/.codex}/skills/claude-jsonl-compressor"
126
+ ```
127
+
128
+ ```powershell
129
+ git -C $skill pull --ff-only
130
+ Remove-Item -LiteralPath $skill -Recurse -Force
131
+ ```
132
+
133
+ The installed directory must contain `SKILL.md`, `scripts/`, `config/`, `templates/` and `references/`.
134
+
135
+ ### Install The npm CLI
136
+
137
+ After the RC is published:
138
+
139
+ ```bash
140
+ npm install --global @brandry/claude-jsonl-compressor@rc
141
+ ```
142
+
143
+ This installs two commands:
144
+
145
+ ```text
146
+ claude-jsonl-compressor
147
+ claude-jsonl-repair-read-pages
148
+ ```
149
+
150
+ The npm package is a zero-dependency Node shim over the bundled Python implementation. It forwards arguments, stdio, exit codes and signals with `shell: false`. The tarball also contains `SKILL.md`, `agents/` and `references/`, but npm installation does not register the directory as a Codex skill; skill installation remains a separate copy/link step.
151
+
152
+ Upgrade or uninstall the global CLI:
153
+
154
+ ```bash
155
+ npm install --global @brandry/claude-jsonl-compressor@rc
156
+ npm update --global @brandry/claude-jsonl-compressor
157
+ npm uninstall --global @brandry/claude-jsonl-compressor
158
+ ```
159
+
160
+ Local development install and invocation:
161
+
162
+ ```bash
163
+ npm install --save-dev @brandry/claude-jsonl-compressor@rc
164
+ npm update @brandry/claude-jsonl-compressor
165
+ npm exec -- claude-jsonl-compressor --version
166
+ npm exec -- claude-jsonl-repair-read-pages --version
167
+ npm uninstall @brandry/claude-jsonl-compressor
168
+ ```
169
+
170
+ Run without retaining an installation:
171
+
172
+ ```bash
173
+ npx --yes --package @brandry/claude-jsonl-compressor@rc claude-jsonl-compressor --version
174
+ npx --yes --package @brandry/claude-jsonl-compressor@rc claude-jsonl-repair-read-pages --version
175
+ ```
176
+
177
+ Actual npm/npx operations use the same Python CLI options:
178
+
179
+ ```bash
180
+ npx --yes --package @brandry/claude-jsonl-compressor@rc claude-jsonl-compressor --input session.jsonl --write-model-pack run/session.model-pack.md
181
+ npx --yes --package @brandry/claude-jsonl-compressor@rc claude-jsonl-repair-read-pages --input session.jsonl --scan-only
182
+ ```
183
+
184
+ ### Use From Source Without Installing
185
+
186
+ ```bash
187
+ python scripts/compress_claude_jsonl.py --version
188
+ python scripts/repair_claude_jsonl.py --version
189
+ ```
190
+
191
+ ### Can Claude Code Install This Skill?
192
+
193
+ `SKILL.md` is a Codex skill definition, not a native Claude Code skill/plugin format. Claude Code can still run the Python or npm commands when instructed, but installing this directory into Claude's configuration does not automatically create an equivalent Claude-native skill.
194
+
195
+ ## Detailed Workflow
196
+
197
+ The examples below use PowerShell and a local skill installation:
198
+
199
+ ```powershell
200
+ $skill = "$env:USERPROFILE\.codex\skills\claude-jsonl-compressor"
201
+ ```
202
+
203
+ ### 1. Analyze The Resume Path
204
+
205
+ ```powershell
206
+ python "$skill\scripts\compress_claude_jsonl.py" `
207
+ --input "C:\data\session.jsonl" `
208
+ --analyze-resume-path
209
+ ```
210
+
211
+ This is read-only. A nonzero result must be resolved before model-pack generation.
212
+
213
+ ### 2. Generate A Model Evidence Pack
214
+
215
+ ```powershell
216
+ python "$skill\scripts\compress_claude_jsonl.py" `
217
+ --input "C:\data\session.jsonl" `
218
+ --write-model-pack "C:\work\run\session.model-pack.md" `
219
+ --target-ratio 0.30 `
220
+ --min-recent-records 120 `
221
+ --summary-char-budget 60000 `
222
+ --target-estimated-tokens 150000 `
223
+ --model-pack-char-budget 500000 `
224
+ --model-pack-estimated-token-budget 150000
225
+ ```
226
+
227
+ The evidence pack has two independent default ceilings: 500,000 characters
228
+ and a conservative 150,000-token local estimate. The token ceiling leaves
229
+ working room in a typical 200k summarizer context. Mandatory human/assistant
230
+ semantic records, prior compact summaries, handoff lines, and required coverage
231
+ groups are never sampled or clipped; generation stops if they do not fit.
232
+ Optional source/tool/system/error evidence is added by importance and chronology
233
+ until either ceiling is reached, and the pack/report state whether that optional
234
+ evidence was truncated. Do not install a tokenizer to change this workflow.
235
+
236
+ `--target-ratio` is an approximate byte-ratio planning input, not a hard release gate. For a hard local Messages estimate ceiling, use:
237
+
238
+ ```powershell
239
+ --target-estimated-tokens 150000
240
+ ```
241
+
242
+ This candidate-output estimate is separate from the model-pack reading ceiling.
243
+ It covers complete retained structured message payloads, including full thinking,
244
+ `tool_use.input`, `tool_result`, and `toolUseResult` data. It does not include
245
+ Claude's system prompt, tool schemas, MCP servers, agents, skills, memory files
246
+ or runtime-loaded context. It is not a promise about total `/context` usage.
247
+
248
+ `--summary-char-budget` has a hard minimum of 4000 characters. A smaller value or a blank compact summary is rejected instead of publishing unusable memory.
249
+
250
+ ### 3. Write The Model Summary
251
+
252
+ The model reads the pack and writes `session.model-summary.md`.
253
+
254
+ The first HTML comment must be copied exactly and contains:
255
+
256
+ ```text
257
+ source_sha256
258
+ summary_source_sha256
259
+ evidence_anchor_lines_digest
260
+ required_anchor_groups_digest
261
+ handoff_summary_digest
262
+ pack_request_digest
263
+ required_claim_sources_digest
264
+ ```
265
+
266
+ Every substantive transcript claim needs a displayed `L<number>` anchor. Every external-handoff claim needs a displayed `H<number>` anchor. The validator rejects invented or hidden anchors. It also requires at least one cited anchor from every generated coverage group and an anchored body under each of the nine exact headings printed in the pack. Only the exact leading metadata comment and exact required headings are exempt from line grounding; extra HTML comments or headings are errors. The exact whole line `Unknown from provided anchors.` is the only unanchored uncertainty placeholder; adding other text to that line removes the exemption.
267
+
268
+ Schema v11 assigns a required full-text L-anchor group to every non-empty older active human message and every older active assistant `text`/`thinking` message. It binds every selection/resource option through `pack_request_digest`. Under the exact `### Mandatory Evidence Coverage` subsection, the model must provide exactly one line per mandatory semantic/prior-summary record:
269
+
270
+ ```text
271
+ - L42 support_text_json="exact source substring" disposition=covered
272
+ ```
273
+
274
+ The JSON string must decode to a meaningful exact substring of that L record. This mechanical gate blocks anchor-only boilerplate and leaves a checkable source excerpt; it does not prove that all natural-language interpretation is correct. Schema v11 also reserves early/middle/late/latest, source/tool and prior-summary coverage. Prior compact summaries and every physical line of an explicitly supplied handoff enter the pack in full; handoff early/middle/late/latest H groups must be cited. Pack generation stops instead of truncating or sampling mandatory evidence when either the character or estimated-token ceiling is insufficient. Raise `--model-pack-char-budget` or `--model-pack-estimated-token-budget` only when the summarizing model can read the resulting pack.
275
+
276
+ The summary should preserve:
277
+
278
+ - current state
279
+ - chronology and supersessions
280
+ - user constraints and wording
281
+ - assistant/model research decisions and reasons
282
+ - evidence provenance
283
+ - rejected alternatives
284
+ - risks, unknowns and follow-ups
285
+ - recent raw boundary
286
+
287
+ Later events control current state, but earlier decisions and their reasons remain as superseded history.
288
+
289
+ ### 4. Build A Candidate
290
+
291
+ ```powershell
292
+ python "$skill\scripts\compress_claude_jsonl.py" `
293
+ --input "C:\data\session.jsonl" `
294
+ --output "C:\data\session.compressed.jsonl" `
295
+ --target-ratio 0.30 `
296
+ --min-recent-records 120 `
297
+ --summary-char-budget 60000 `
298
+ --target-estimated-tokens 150000 `
299
+ --model-pack-char-budget 500000 `
300
+ --model-pack-estimated-token-budget 150000 `
301
+ --model-summary "C:\work\run\session.model-summary.md"
302
+ ```
303
+
304
+ Pass exactly the same selection options used for the model pack. In particular,
305
+ repeat both non-default model-pack ceilings so the second pass regenerates the
306
+ same evidence contract.
307
+
308
+ The command writes:
309
+
310
+ ```text
311
+ session.compressed.jsonl
312
+ session.compressed.jsonl.validation.json
313
+ session.compressed.jsonl.report.md
314
+ ```
315
+
316
+ The input remains unchanged.
317
+
318
+ ## Live Session Replacement
319
+
320
+ Close the Claude Code process using that session before replacement. The live target must be an existing regular `.jsonl` file under `.claude/projects`.
321
+
322
+ Generate the model pack and model summary outside `.claude`, then run:
323
+
324
+ ```powershell
325
+ python "$skill\scripts\compress_claude_jsonl.py" `
326
+ --input "$env:USERPROFILE\.claude\projects\PROJECT\SESSION.jsonl" `
327
+ --replace-original `
328
+ --confirm-session-closed `
329
+ --work-dir "C:\work\claude-compression\SESSION-TIMESTAMP" `
330
+ --model-pack-estimated-token-budget 150000 `
331
+ --target-estimated-tokens 150000 `
332
+ --model-summary "C:\work\claude-compression\SESSION-TIMESTAMP\session.model-summary.md"
333
+ ```
334
+
335
+ The default backup is placed beside the live file:
336
+
337
+ ```text
338
+ SESSION.jsonl.backup
339
+ SESSION.jsonl.backup1
340
+ SESSION.jsonl.backup2
341
+ ```
342
+
343
+ To keep backups outside `.claude`:
344
+
345
+ ```powershell
346
+ --backup-dir "C:\work\claude-compression\SESSION-TIMESTAMP\backups"
347
+ ```
348
+
349
+ Candidate, report, validation, model pack and model summary files remain under the external work directory. Do not manually copy a refused candidate over a live session. Exit code 3 with `committed-report-failed` means the live JSONL was already replaced and validated but final report publication failed; inspect the printed hashes and numbered backup instead of rerunning blindly.
350
+
351
+ ## Checkpoint And Rewind Behavior
352
+
353
+ Conversation rewind and file rewind are separate mechanisms.
354
+
355
+ Default:
356
+
357
+ ```text
358
+ --checkpoint-policy active-correlated
359
+ ```
360
+
361
+ It retains only UUID-less `file-history-snapshot` records with structural identifiers that correlate to recent retained active records.
362
+
363
+ Other controls:
364
+
365
+ ```text
366
+ --checkpoint-policy none
367
+ --max-file-history-snapshots N
368
+ ```
369
+
370
+ `--checkpoint-policy preserve-recent` is rejected in strict active-chain mode. It is available only together with explicit `--preserve-physical-tail`, which is labeled compatibility mode and does not isolate rewound branches. JSONL compression alone does not guarantee complete file-state rewind.
371
+
372
+ ## Repeated Compression
373
+
374
+ The default behavior folds previous compact summaries into one new current summary. Old decisions must be checked against later supersessions; old summary text is not automatically current truth.
375
+
376
+ An older Codex compact boundary may retain a `preservedMessages` snapshot from the time it was created. If a later rewind diverges from that snapshot, source validation reports a historical-snapshot warning and follows only the current authoritative parent chain; the rewound tail stays excluded. Every newly generated candidate must rebuild this metadata to match its current chain exactly.
377
+
378
+ For an explicit exact-text request:
379
+
380
+ ```text
381
+ --preserve-prior-summaries-verbatim
382
+ ```
383
+
384
+ Use the flag in both passes. The compressor allows up to 1.5 times the configured summary character budget. If the exact block still does not fit, it reports `fallback-folded` and uses normal semantic folding. It never leaves stacked old compact pairs on the current active chain.
385
+
386
+ ## Deterministic Fallback
387
+
388
+ Model-assisted summary is the default. Use deterministic fallback only on explicit request:
389
+
390
+ ```powershell
391
+ python "$skill\scripts\compress_claude_jsonl.py" `
392
+ --input "C:\data\session.jsonl" `
393
+ --output "C:\data\session.compressed.jsonl" `
394
+ --deterministic-summary
395
+ ```
396
+
397
+ The CLI otherwise requires `--model-summary`.
398
+
399
+ ## Read.pages Compatibility Repair
400
+
401
+ Claude's native Read tool can legitimately use `pages` for long PDFs. This repair exists for a separate compatibility failure where a historical bridge cannot accept that member. Compression never runs it automatically.
402
+
403
+ ### Scan
404
+
405
+ ```powershell
406
+ python "$skill\scripts\repair_claude_jsonl.py" `
407
+ --input "C:\data\session.jsonl" `
408
+ --scan-only
409
+ ```
410
+
411
+ ### Write A Candidate
412
+
413
+ ```powershell
414
+ python "$skill\scripts\repair_claude_jsonl.py" `
415
+ --input "C:\data\session.jsonl" `
416
+ --output "C:\data\session.repaired.jsonl" `
417
+ --expect-matches 2
418
+ ```
419
+
420
+ ### Replace One Live File
421
+
422
+ ```powershell
423
+ python "$skill\scripts\repair_claude_jsonl.py" `
424
+ --input "$env:USERPROFILE\.claude\projects\PROJECT\SESSION.jsonl" `
425
+ --replace-original `
426
+ --confirm-session-closed `
427
+ --work-dir "C:\work\claude-repair\SESSION-TIMESTAMP" `
428
+ --expect-matches 2
429
+ ```
430
+
431
+ Default scope is the strict active chain. `--scope all` must be explicit.
432
+
433
+ The repair requires:
434
+
435
+ - assistant API message
436
+ - structured `tool_use`
437
+ - exact tool name `Read`
438
+ - object `input`
439
+ - present `pages` member
440
+ - non-empty `file_path`
441
+ - exactly one later matching `tool_result` in scope
442
+ - the same non-empty `sessionId` on use and result
443
+ - result `sourceToolAssistantUUID` equal to the tool-use assistant UUID
444
+
445
+ Pending calls and near matches are reported but unchanged. Duplicate JSON keys or ambiguous spans stop the run before editing. Candidate publication re-reads the actual published bytes, binds them to the expected SHA-256, validates the repair plan, requires an idempotent second scan, and runs the shared full-transcript UUID/parent/compact/tool validator. Exit code 3 with `operationState: committed-report-failed` has the same already-committed meaning as live compression.
446
+
447
+ ## CLI Reference
448
+
449
+ Important compression options:
450
+
451
+ | Option | Purpose |
452
+ | --- | --- |
453
+ | `--analyze-resume-path` | Read-only strict topology report |
454
+ | `--write-model-pack PATH` | Write bounded semantic evidence and stop |
455
+ | `--model-summary PATH` | Validate and embed model-authored summary |
456
+ | `--deterministic-summary` | Explicit model opt-out |
457
+ | `--target-ratio R` | Approximate output byte-ratio planning value; not a hard gate |
458
+ | `--target-estimated-tokens N` | Hard ceiling under the local complete-structure Messages estimate |
459
+ | `--min-recent-records N` | Raw active-suffix floor |
460
+ | `--summary-char-budget N` | Compact-summary character budget; minimum 4000 |
461
+ | `--model-pack-char-budget N` | Evidence-pack character budget |
462
+ | `--model-pack-estimated-token-budget N` | Evidence-pack local token estimate ceiling; default 150000 |
463
+ | `--resume-leaf UUID` | Explicit recovery leaf override |
464
+ | `--max-post-last-prompt-extension N` | Explicit complete tool-result-only closure limit; default 0 |
465
+ | `--checkpoint-policy POLICY` | Strict mode: `active-correlated` or `none`; `preserve-recent` only with physical-tail compatibility |
466
+ | `--preserve-prior-summaries-verbatim` | Explicit repeated-compression exact-text mode |
467
+ | `--preserve-physical-tail` | Compatibility mode without branch-isolation guarantee |
468
+ | `--replace-original` | Transactionally replace one live session |
469
+ | `--confirm-session-closed` | Required caller acknowledgement for live replacement; not process-lock detection |
470
+ | `--work-dir PATH` | External process directory for live replacement |
471
+ | `--backup-dir PATH` | Optional external backup directory |
472
+ | `--validate-only PATH` | Structural validation only |
473
+
474
+ Run `--help` for the complete list.
475
+
476
+ ## Validation Scope
477
+
478
+ The validator checks:
479
+
480
+ - JSON object per non-empty line
481
+ - UUID uniqueness
482
+ - parent existence and session consistency
483
+ - final pointer target
484
+ - active chain closure
485
+ - narrow attachment-order and one-way session-lineage compatibility, with unsafe variants rejected
486
+ - one current compact boundary and compact summary
487
+ - compact metadata consistency
488
+ - merged assistant fragments and split user tool results
489
+ - API-level `tool_use` / `tool_result` order and pairing
490
+ - non-empty, unique active tool IDs; partial multi-tool ordered subsets remain a reported branch-compatibility warning
491
+ - absence of internal scratch fields
492
+
493
+ Validation checks internal consistency under the observed-format rules; Claude Code versions may still build runtime context differently.
494
+
495
+ When runtime testing is explicitly allowed, check these separately:
496
+
497
+ 1. `/resume` lists and opens the session.
498
+ 2. `/context` shows expected Messages usage.
499
+ 3. Recent conversation rewind works.
500
+ 4. Recent file rewind works for retained checkpoints.
501
+
502
+ High total `/context` with low Messages can come from system prompt, tools, MCP, agents, skills, memory files or newly read content. Recompressing JSONL does not reduce those categories.
503
+
504
+ ## Session Locator
505
+
506
+ Locate exactly one file by filename or session ID without reading transcript bodies:
507
+
508
+ ```powershell
509
+ python "$skill\scripts\claude_session_tools.py" `
510
+ --root "$env:USERPROFILE\.claude\projects" `
511
+ --query "SESSION.jsonl"
512
+ ```
513
+
514
+ `--scan-titles` reads candidate files only when title matching is explicitly needed. Multiple matches are an error. The compressor never performs directory-wide multi-session compression.
515
+
516
+ ## Development And Verification
517
+
518
+ Run the complete standard-library suite:
519
+
520
+ ```bash
521
+ python -B -m unittest discover -s tests -v
522
+ python -B tests/test_compressor.py
523
+ python -B tests/test_repair.py
524
+ python -B tests/test_package.py
525
+ python -B tests/test_transaction_races.py
526
+ python -B tests/test_semantic_evidence_contracts.py
527
+ python -B tests/test_structural_safety_contracts.py
528
+ python -B tests/test_protocol_contracts.py
529
+ ```
530
+
531
+ Additional release checks:
532
+
533
+ ```bash
534
+ pycache="$(mktemp -d)"
535
+ if ! PYTHONPYCACHEPREFIX="$pycache" python -m compileall -q scripts tests; then
536
+ rm -rf "$pycache"
537
+ exit 1
538
+ fi
539
+ rm -rf "$pycache"
540
+ python -B -I -S scripts/compress_claude_jsonl.py --version
541
+ python -B -I -S scripts/repair_claude_jsonl.py --version
542
+ npm test
543
+ npm pack --dry-run --json
544
+ npm publish --dry-run --access public --tag rc
545
+ ```
546
+
547
+ The release suite covers active/dead branch partitioning, fixed-seed topology transformations, strict pointer failures, dual model-pack budgets, complete structured token accounting, multilingual semantic ledgers and thinking, handoffs, request/claim digests, mandatory support excerpts, tool pairs, repeated compression, checkpoint policies, transaction races and committed-report states, exact byte repair, BOM/CRLF, npm tarball allowlisting and offline tarball installation.
548
+
549
+ ### Maintainer RC Release Checklist
550
+
551
+ 1. Confirm a clean public tree and matching `1.0.0-rc.1` values in `package.json`, Python version output, docs, and tests.
552
+ 2. Run the Python, npm, isolated-Python, tarball, privacy, and offline-install gates above.
553
+ 3. Inspect `npm pack --dry-run --json`; publish only the allowlisted files.
554
+ 4. Require a clean worktree, create annotated tag `v1.0.0-rc.1`, and push the commit and tag.
555
+ 5. For the first manual RC, publish from an authenticated maintainer machine with npm 2FA:
556
+
557
+ ```bash
558
+ npm publish --access public --tag rc
559
+ ```
560
+
561
+ 6. Verify the npm version and `rc` dist-tag, then create the GitHub prerelease from the already-pushed tag.
562
+
563
+ Do not append `--provenance` to a local publish. npm provenance requires a supported cloud CI runner. For later releases, prefer npm trusted publishing from a public GitHub repository on a GitHub-hosted runner with `id-token: write`, a protected release tag, and a matching protected environment; trusted publishing generates provenance automatically.
564
+
565
+ Registry ownership, npm trusted-publisher configuration, credentials, tag push, GitHub prerelease creation, and npm publication are external maintainer actions and are not claimed by the local test suite.
566
+
567
+ ## Repository Layout
568
+
569
+ ```text
570
+ SKILL.md
571
+ CHANGELOG.md
572
+ README.md
573
+ LICENSE
574
+ package.json
575
+ bin/
576
+ config/
577
+ scripts/
578
+ templates/
579
+ references/
580
+ tests/
581
+ ```
582
+
583
+ ## Privacy
584
+
585
+ - The public project contains only anonymous synthetic fixtures.
586
+ - Model packs and candidate metadata use generic labels such as `SOURCE_JSONL`; generated reports expose basenames, never full local paths.
587
+ - npm publication uses an extension-level file allowlist.
588
+ - JSONL, backups, reports, model packs, model summaries, caches and compiled Python files are excluded from the package.
589
+ - Review generated evidence packs before sharing them; they intentionally contain selected transcript evidence.
590
+
591
+ ## License
592
+
593
+ GPL-3.0-only. You may use, study, modify and redistribute the project under the GPL terms. Distribution of modified or incorporated versions may require corresponding source and the same license; review the license when integrating it into a distributed commercial product.