feat: /sessions export command for markdown/json session sharing (F4.4) #33

Open
opened 2026-04-25 07:01:48 +02:00 by root · 0 comments
Owner

Problem Statement

The terraphim-agent-session-search-spec.md (section F4.4 "Session Commands") mandates a /sessions export command for sharing and offline use of imported coding-assistant sessions:

/sessions export --format markdown --output sessions.md
/sessions export --session-id <uuid> --format json

The Phase 3 success criterion claims [x] Timeline and export, yet a repository-wide grep confirms zero Export / export symbols inside crates/terraphim_sessions/src/ or crates/terraphim_agent/src/repl/. Users currently have no first-class way to extract a single session, a filtered subset, or the full corpus -- they must hand-roll SQL or read JSONL. This blocks downstream review workflows, reproducibility audits, and the Reporting pipeline used by codebase-eval.

Acceptance Criteria

  • New REPL subcommand SessionsSubcommand::Export accepts:
    • --format markdown|json|jsonl (required, default markdown)
    • --output <path> (required when targeting multiple sessions)
    • --session-id <id> (optional; mutually exclusive with --source/--since filters)
    • --source <name> (optional filter)
    • --since <iso8601> (optional filter; reuses the parser from sessions search --after)
  • Markdown writer produces # Session: <title> headings, fenced code blocks per CodeSnippet with the language tag, and a YAML front-matter block holding session_id, source, created_at, message_count, concepts
  • JSON writer emits a single Session document; jsonl writer emits one session per line for streaming
  • Single-session export streams to stdout when --output is omitted; multi-session export requires --output and refuses to overwrite without --force
  • Robot mode returns RobotResponse<ExportSummary { sessions_written: usize, bytes_written: u64, output_path: Option<PathBuf> }> and exit code 4 (ERROR_NOT_FOUND) when no sessions match the filters
  • Unit tests cover: single session by id, filter by source, filter by --since, refusal to overwrite, format enum round-trip
  • Integration test imports two fixture Claude sessions, exports both as markdown to a tmp dir, and asserts file content matches a snapshot
  • cargo test -p terraphim_agent --features repl-full,repl-sessions passes
  • cargo clippy -p terraphim_agent --features repl-full,repl-sessions -- -D warnings passes

Proposed Approach

Affected crates:

  • crates/terraphim_sessions/ -- add pub mod export with pub fn write_markdown(session: &Session, out: &mut dyn Write) -> Result<usize>, JSON / JSONL counterparts, and a pub struct ExportRequest { format, filter, output } that the REPL handler builds.
  • crates/terraphim_agent/src/repl/commands.rs -- extend SessionsSubcommand with Export(ExportArgs) clap variant.
  • crates/terraphim_agent/src/repl/handler.rs -- new handle_sessions_export branch in handle_sessions.

Markdown layout follows the existing terraphim-session-analyzer reporter style so the two outputs remain visually consistent. No new dependencies; reuses serde_json, serde_yaml (already in the workspace via the manifest loader).

Dependencies

None. The data model (Session, Message, CodeSnippet) and the SessionService query layer are already in place.

Verification

cargo test -p terraphim_sessions export
cargo test -p terraphim_agent --features repl-full,repl-sessions sessions_export
cargo clippy -p terraphim_sessions -p terraphim_agent --features repl-full,repl-sessions -- -D warnings

Smoke test (after build):

terraphim-agent /sessions export --format markdown --output /tmp/all-sessions.md
terraphim-agent /sessions export --session-id <uuid> --format json

Scope

Single PR, approximately 350 LOC: ~120 LOC formatter (markdown), ~60 LOC JSON/JSONL writers, ~80 LOC clap variant + handler, ~90 LOC tests + fixtures. Watch-mode export, S3 sinks, and HTML/PDF formats are explicitly out of scope.

## Problem Statement The `terraphim-agent-session-search-spec.md` (section F4.4 "Session Commands") mandates a `/sessions export` command for sharing and offline use of imported coding-assistant sessions: ``` /sessions export --format markdown --output sessions.md /sessions export --session-id <uuid> --format json ``` The Phase 3 success criterion claims `[x] Timeline and export`, yet a repository-wide grep confirms zero `Export` / `export` symbols inside `crates/terraphim_sessions/src/` or `crates/terraphim_agent/src/repl/`. Users currently have no first-class way to extract a single session, a filtered subset, or the full corpus -- they must hand-roll SQL or read JSONL. This blocks downstream review workflows, reproducibility audits, and the Reporting pipeline used by `codebase-eval`. ## Acceptance Criteria - [ ] New REPL subcommand `SessionsSubcommand::Export` accepts: - `--format markdown|json|jsonl` (required, default `markdown`) - `--output <path>` (required when targeting multiple sessions) - `--session-id <id>` (optional; mutually exclusive with `--source`/`--since` filters) - `--source <name>` (optional filter) - `--since <iso8601>` (optional filter; reuses the parser from `sessions search --after`) - [ ] Markdown writer produces `# Session: <title>` headings, fenced code blocks per `CodeSnippet` with the language tag, and a YAML front-matter block holding `session_id`, `source`, `created_at`, `message_count`, `concepts` - [ ] JSON writer emits a single `Session` document; `jsonl` writer emits one session per line for streaming - [ ] Single-session export streams to stdout when `--output` is omitted; multi-session export requires `--output` and refuses to overwrite without `--force` - [ ] Robot mode returns `RobotResponse<ExportSummary { sessions_written: usize, bytes_written: u64, output_path: Option<PathBuf> }>` and exit code 4 (`ERROR_NOT_FOUND`) when no sessions match the filters - [ ] Unit tests cover: single session by id, filter by source, filter by `--since`, refusal to overwrite, format enum round-trip - [ ] Integration test imports two fixture Claude sessions, exports both as markdown to a tmp dir, and asserts file content matches a snapshot - [ ] `cargo test -p terraphim_agent --features repl-full,repl-sessions` passes - [ ] `cargo clippy -p terraphim_agent --features repl-full,repl-sessions -- -D warnings` passes ## Proposed Approach Affected crates: - `crates/terraphim_sessions/` -- add `pub mod export` with `pub fn write_markdown(session: &Session, out: &mut dyn Write) -> Result<usize>`, JSON / JSONL counterparts, and a `pub struct ExportRequest { format, filter, output }` that the REPL handler builds. - `crates/terraphim_agent/src/repl/commands.rs` -- extend `SessionsSubcommand` with `Export(ExportArgs)` clap variant. - `crates/terraphim_agent/src/repl/handler.rs` -- new `handle_sessions_export` branch in `handle_sessions`. Markdown layout follows the existing `terraphim-session-analyzer` reporter style so the two outputs remain visually consistent. No new dependencies; reuses `serde_json`, `serde_yaml` (already in the workspace via the manifest loader). ## Dependencies None. The data model (`Session`, `Message`, `CodeSnippet`) and the `SessionService` query layer are already in place. ## Verification ``` cargo test -p terraphim_sessions export cargo test -p terraphim_agent --features repl-full,repl-sessions sessions_export cargo clippy -p terraphim_sessions -p terraphim_agent --features repl-full,repl-sessions -- -D warnings ``` Smoke test (after build): ``` terraphim-agent /sessions export --format markdown --output /tmp/all-sessions.md terraphim-agent /sessions export --session-id <uuid> --format json ``` ## Scope Single PR, approximately 350 LOC: ~120 LOC formatter (markdown), ~60 LOC JSON/JSONL writers, ~80 LOC clap variant + handler, ~90 LOC tests + fixtures. Watch-mode export, S3 sinks, and HTML/PDF formats are explicitly out of scope.
Sign in to join this conversation.