Skip to content

feat(session): archive compaction-dropped messages to disk (M1.4)#5

Merged
wusijian007 merged 1 commit into
mainfrom
feat/m1.4-compaction-archive
May 14, 2026
Merged

feat(session): archive compaction-dropped messages to disk (M1.4)#5
wusijian007 merged 1 commit into
mainfrom
feat/m1.4-compaction-archive

Conversation

@wusijian007

Copy link
Copy Markdown
Owner

Compaction used to replace the dropped middle slice with an inline "[context compacted: N messages omitted]" notice and discard the originals. That made the operation lossy: there was no way to recover what got cut, and no way to audit a long-running session's compaction history.

Surface introduced:

  • CompactOptions.archiveSink?: (omitted: readonly Message[]) => void on compactMessages. Synchronously hands the caller the original (unsnipped) dropped slice. Default is no-op, so headless query-loop retries on prompt_too_long stay unchanged.

  • compactSessionRecord becomes async and accepts an optional archiver: (omitted, at) => Promise<string|undefined>. The returned path is stamped onto the resulting compact SessionEvent as archivePath. Omitting the archiver, or returning undefined, keeps archivePath unset for back-compat with older sessions.

  • myagent compact <id> and the TUI /compact wire a default archiver that writes JSON to .myagent/artifacts/<sessionId>/compactions/<at>.json. The CLI prints the archive path on success. Filename uses at with : and . replaced by - so it round-trips on Windows.

  • myagent resume <id> --show-compactions lists every compact event on the session with its archive path (or <not archived> for pre-M1.4 sessions / query-loop retries with no archiver).

Tests added in packages/core/test/security/compaction-archive.test.ts pin the new invariants (sink fires only on omission, archiver path round-trips, undefined archiver/return keeps archivePath unset). A CLI-level e2e test exercises the whole path: build a fixture session big enough to actually trigger omission, run myagent compact, read back the JSON archive, verify content is unsnipped, then run myagent resume --show-compactions and assert the archive path is listed. Catalog row added to packages/core/test/security/README.md; CLAUDE.md updated.

Compaction used to replace the dropped middle slice with an inline
"[context compacted: N messages omitted]" notice and discard the
originals. That made the operation lossy: there was no way to recover
what got cut, and no way to audit a long-running session's compaction
history.

Surface introduced:

- `CompactOptions.archiveSink?: (omitted: readonly Message[]) => void`
  on `compactMessages`. Synchronously hands the caller the *original*
  (unsnipped) dropped slice. Default is no-op, so headless query-loop
  retries on prompt_too_long stay unchanged.

- `compactSessionRecord` becomes async and accepts an optional
  `archiver: (omitted, at) => Promise<string|undefined>`. The returned
  path is stamped onto the resulting `compact` SessionEvent as
  `archivePath`. Omitting the archiver, or returning undefined,
  keeps `archivePath` unset for back-compat with older sessions.

- `myagent compact <id>` and the TUI `/compact` wire a default
  archiver that writes JSON to
  `.myagent/artifacts/<sessionId>/compactions/<at>.json`. The CLI
  prints the archive path on success. Filename uses `at` with `:` and
  `.` replaced by `-` so it round-trips on Windows.

- `myagent resume <id> --show-compactions` lists every compact event
  on the session with its archive path (or `<not archived>` for
  pre-M1.4 sessions / query-loop retries with no archiver).

Tests added in `packages/core/test/security/compaction-archive.test.ts`
pin the new invariants (sink fires only on omission, archiver path
round-trips, undefined archiver/return keeps archivePath unset). A
CLI-level e2e test exercises the whole path: build a fixture session
big enough to actually trigger omission, run `myagent compact`, read
back the JSON archive, verify content is unsnipped, then run
`myagent resume --show-compactions` and assert the archive path is
listed. Catalog row added to `packages/core/test/security/README.md`;
CLAUDE.md updated.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@wusijian007 wusijian007 merged commit 2740bb3 into main May 14, 2026
3 checks passed
@wusijian007 wusijian007 deleted the feat/m1.4-compaction-archive branch May 14, 2026 07:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant