From ded784c766731d4ebf8c855419952daf3c285674 Mon Sep 17 00:00:00 2001 From: Stefan Haubold Date: Fri, 20 Feb 2026 12:10:03 +0100 Subject: [PATCH 1/4] add a new requirement/checklist file any new agent integration can be validated against Entire-Checkpoint: 71e423cea43a --- CLAUDE.md | 1 + .../agent-integration-checklist.md | 111 ++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 docs/architecture/agent-integration-checklist.md diff --git a/CLAUDE.md b/CLAUDE.md index 7ffdba5c0..c9f62c500 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,6 +12,7 @@ This repo contains the CLI for Entire. - `entire/`: Main CLI entry point - `entire/cli`: CLI utilities and helpers - `entire/cli/commands`: actual command implementations +- `entire/cli/agent`: agent implementations (Claude Code, Gemini CLI, OpenCode) - see [Agent Integration Checklist](docs/architecture/agent-integration-checklist.md) - `entire/cli/strategy`: strategy implementations - see section below - `entire/cli/checkpoint`: checkpoint storage abstractions (temporary and committed) - `entire/cli/session`: session state management diff --git a/docs/architecture/agent-integration-checklist.md b/docs/architecture/agent-integration-checklist.md new file mode 100644 index 000000000..f9ede1908 --- /dev/null +++ b/docs/architecture/agent-integration-checklist.md @@ -0,0 +1,111 @@ +# Agent Integration Checklist + +This document provides requirements and a checklist for integrating new AI coding agents with Entire. Use this when implementing support for a new agent (e.g., Claude Code, Gemini CLI, OpenCode). + +## Core Principle: Full Transcript Storage + +Entire stores the **complete session transcript** at every checkpoint, not incremental diffs. This enables: + +- Simple rewind: restore the full transcript, agent resumes from that state +- No dependency on previous checkpoints being intact +- Consistent behavior across all checkpoint types (committed, uncommitted) + +**Each checkpoint must contain the full session history up to that point.** + +## Core Principle: Native Format Preservation + +Store transcripts in the **agent's native format**. Any transformation or normalization should only be done to support CLI features (rewind, resume, summarization, file extraction), not for backend or web UI consumption. + +**Why:** +- The backend/web UI should handle format differences, not the CLI +- Transforming for downstream consumers couples the CLI to their requirements +- Native formats ensure compatibility with agent's own import/export tools +- Reduces risk of data loss from lossy transformations +- Format changes that break the UI can be fixed with a backend deploy; CLI changes require a full release cycle and user adoption + +**Do:** +- Store the raw transcript as the agent produces it +- Parse the native format when CLI features need specific data (e.g., extract file paths for `entire status`) +- Let the backend normalize formats for display + +**Don't:** +- Create a "universal transcript format" in the CLI +- Transform logs to match what the web UI expects +- Strip or restructure data to simplify backend processing + +## Integration Checklist + +### Transcript Capture + +- [ ] **Full transcript on every turn**: At turn-end, capture the complete session transcript, not just events since the last checkpoint +- [ ] **Resumed session handling**: When a user resumes an existing session, the transcript must include all historical messages, not just new ones since the plugin/hook loaded +- [ ] **Use agent's canonical export**: Prefer the agent's native export command (e.g., `opencode export`, reading Claude's JSONL file) over manually reconstructing from events +- [ ] **Graceful degradation**: If the canonical source is unavailable (e.g., agent shutting down), fall back to best-effort capture with clear documentation of limitations + +### Why This Matters + +**Bug pattern to avoid:** + +```typescript +// BAD: Event-stream accumulation misses history on resumed sessions +const messageStore = new Map() // Empty on plugin load + +case "message.updated": + messageStore.set(msg.id, msg) // Only captures new messages + +case "session.idle": + writeExport(messageStore) // Missing historical messages! +``` + +**Correct approach:** + +```typescript +// GOOD: Use agent's canonical export which includes full history +case "session.idle": + await $`agent export ${sessionID} > ${exportPath}` // Full session from agent's DB +``` + +### Session Storage Abstraction + +- [ ] **`WriteSession` implementation**: Agent must implement `WriteSession(AgentSession)` to restore sessions +- [ ] **File-based agents** (Claude, Gemini): Just write `NativeData` to `SessionRef` path +- [ ] **Database-backed agents** (OpenCode): Write file AND import into native storage using `ExportData` +- [ ] **Format compatibility**: Export data format must be compatible with agent's import command + +### Hook Events + +- [ ] **turn-start**: Fire when user submits a prompt (for pre-prompt state capture) +- [ ] **turn-end**: Fire when agent finishes responding (for checkpoint creation) +- [ ] **session-start**: Fire when a new session begins +- [ ] **session-end**: Fire when session is explicitly ended (optional but recommended) + +### Rewind/Resume Support + +- [ ] **Rewind restores full state**: After rewind, agent can continue from that point with full context +- [ ] **Resume command**: `FormatResumeCommand()` returns the CLI command to resume a session +- [ ] **Session ID preservation**: Restored sessions maintain original session ID where possible + +### Testing + +- [ ] **New session**: Create session, multiple turns, verify full transcript at each checkpoint +- [ ] **Resumed session**: Resume existing session, add turns, verify checkpoint includes historical messages +- [ ] **Rewind**: Rewind to earlier checkpoint, verify agent can continue from that state +- [ ] **Agent shutdown**: Verify graceful handling if agent exits during checkpoint + +## Agent-Specific Notes + +### Claude Code +- Transcript: JSONL file on disk, always complete +- Storage: File-based, `WriteSession` just writes file +- Resume: `claude --resume ` + +### Gemini CLI +- Transcript: JSON file on disk, always complete +- Storage: File-based, `WriteSession` just writes file +- Resume: `gemini --session ` + +### OpenCode +- Transcript: SQLite database (not directly accessible) +- Storage: Database-backed, `WriteSession` must import via `opencode import` +- Export: Use `opencode export ` for canonical format +- Resume: `opencode -s ` From 54054ebbb3698f1abcae8a230973a59a26dca07f Mon Sep 17 00:00:00 2001 From: Stefan Haubold Date: Fri, 20 Feb 2026 12:28:45 +0100 Subject: [PATCH 2/4] making clearer what we want to store Entire-Checkpoint: 473fe05ee1ee --- .../agent-integration-checklist.md | 35 ++++--------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/docs/architecture/agent-integration-checklist.md b/docs/architecture/agent-integration-checklist.md index f9ede1908..dc4e61c7e 100644 --- a/docs/architecture/agent-integration-checklist.md +++ b/docs/architecture/agent-integration-checklist.md @@ -42,35 +42,12 @@ Store transcripts in the **agent's native format**. Any transformation or normal - [ ] **Use agent's canonical export**: Prefer the agent's native export command (e.g., `opencode export`, reading Claude's JSONL file) over manually reconstructing from events - [ ] **Graceful degradation**: If the canonical source is unavailable (e.g., agent shutting down), fall back to best-effort capture with clear documentation of limitations -### Why This Matters - -**Bug pattern to avoid:** - -```typescript -// BAD: Event-stream accumulation misses history on resumed sessions -const messageStore = new Map() // Empty on plugin load - -case "message.updated": - messageStore.set(msg.id, msg) // Only captures new messages - -case "session.idle": - writeExport(messageStore) // Missing historical messages! -``` - -**Correct approach:** - -```typescript -// GOOD: Use agent's canonical export which includes full history -case "session.idle": - await $`agent export ${sessionID} > ${exportPath}` // Full session from agent's DB -``` - ### Session Storage Abstraction - [ ] **`WriteSession` implementation**: Agent must implement `WriteSession(AgentSession)` to restore sessions -- [ ] **File-based agents** (Claude, Gemini): Just write `NativeData` to `SessionRef` path -- [ ] **Database-backed agents** (OpenCode): Write file AND import into native storage using `ExportData` -- [ ] **Format compatibility**: Export data format must be compatible with agent's import command +- [ ] **File-based agents** (Claude, Gemini): Write `NativeData` to `SessionRef` path +- [ ] **Database-backed agents** (OpenCode): Write `NativeData` to file, then import into native storage (the native format should be what the agent's import command expects) +- [ ] **Single format per agent**: Store only the agent's native format in `NativeData` - no separate fields for different representations of the same data ### Hook Events @@ -105,7 +82,7 @@ case "session.idle": - Resume: `gemini --session ` ### OpenCode -- Transcript: SQLite database (not directly accessible) -- Storage: Database-backed, `WriteSession` must import via `opencode import` -- Export: Use `opencode export ` for canonical format +- Transcript: `opencode export ` output (JSON) - this is the native format +- Storage: Database-backed, `WriteSession` writes file then imports via `opencode import` - Resume: `opencode -s ` +- Note: Don't build transcripts from events - use `opencode export` which reads from SQLite and includes full history From c976ea57b953db0e3db4f2f9fb6a9c9bc6ad6737 Mon Sep 17 00:00:00 2001 From: Stefan Haubold Date: Fri, 20 Feb 2026 12:33:25 +0100 Subject: [PATCH 3/4] use actual syntax Entire-Checkpoint: 7cef9eccd07f --- docs/architecture/agent-integration-checklist.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/architecture/agent-integration-checklist.md b/docs/architecture/agent-integration-checklist.md index dc4e61c7e..0d40e032a 100644 --- a/docs/architecture/agent-integration-checklist.md +++ b/docs/architecture/agent-integration-checklist.md @@ -51,10 +51,12 @@ Store transcripts in the **agent's native format**. Any transformation or normal ### Hook Events -- [ ] **turn-start**: Fire when user submits a prompt (for pre-prompt state capture) -- [ ] **turn-end**: Fire when agent finishes responding (for checkpoint creation) -- [ ] **session-start**: Fire when a new session begins -- [ ] **session-end**: Fire when session is explicitly ended (optional but recommended) +Map agent-native hooks to these `EventType` constants (see `agent/event.go`): + +- [ ] **TurnStart**: Fire when user submits a prompt (for pre-prompt state capture) +- [ ] **TurnEnd**: Fire when agent finishes responding (for checkpoint creation) +- [ ] **SessionStart**: Fire when a new session begins +- [ ] **SessionEnd**: Fire when session is explicitly ended (optional but recommended) ### Rewind/Resume Support @@ -74,12 +76,12 @@ Store transcripts in the **agent's native format**. Any transformation or normal ### Claude Code - Transcript: JSONL file on disk, always complete - Storage: File-based, `WriteSession` just writes file -- Resume: `claude --resume ` +- Resume: `claude -r ` ### Gemini CLI - Transcript: JSON file on disk, always complete - Storage: File-based, `WriteSession` just writes file -- Resume: `gemini --session ` +- Resume: `gemini --resume ` ### OpenCode - Transcript: `opencode export ` output (JSON) - this is the native format From 39156ef998b5660d628a9bd53edc40323cca87ae Mon Sep 17 00:00:00 2001 From: Stefan Haubold Date: Fri, 20 Feb 2026 12:49:42 +0100 Subject: [PATCH 4/4] more refinement Entire-Checkpoint: bbfa81785ee4 --- .../agent-integration-checklist.md | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/docs/architecture/agent-integration-checklist.md b/docs/architecture/agent-integration-checklist.md index 0d40e032a..fb11a39dc 100644 --- a/docs/architecture/agent-integration-checklist.md +++ b/docs/architecture/agent-integration-checklist.md @@ -32,6 +32,8 @@ Store transcripts in the **agent's native format**. Any transformation or normal - Create a "universal transcript format" in the CLI - Transform logs to match what the web UI expects - Strip or restructure data to simplify backend processing +- Create intermediate formats (e.g., converting JSON to JSONL for "easier parsing") +- Reconstruct transcripts from events when a canonical export exists ## Integration Checklist @@ -40,13 +42,14 @@ Store transcripts in the **agent's native format**. Any transformation or normal - [ ] **Full transcript on every turn**: At turn-end, capture the complete session transcript, not just events since the last checkpoint - [ ] **Resumed session handling**: When a user resumes an existing session, the transcript must include all historical messages, not just new ones since the plugin/hook loaded - [ ] **Use agent's canonical export**: Prefer the agent's native export command (e.g., `opencode export`, reading Claude's JSONL file) over manually reconstructing from events +- [ ] **No custom formats**: Store the agent's native format directly in `NativeData` - do not convert between formats (e.g., JSON to JSONL) or create intermediate representations - [ ] **Graceful degradation**: If the canonical source is unavailable (e.g., agent shutting down), fall back to best-effort capture with clear documentation of limitations ### Session Storage Abstraction - [ ] **`WriteSession` implementation**: Agent must implement `WriteSession(AgentSession)` to restore sessions - [ ] **File-based agents** (Claude, Gemini): Write `NativeData` to `SessionRef` path -- [ ] **Database-backed agents** (OpenCode): Write `NativeData` to file, then import into native storage (the native format should be what the agent's import command expects) +- [ ] **Database-backed agents**: Write `NativeData` to file, then import into native storage (the native format should be what the agent's import command expects) - [ ] **Single format per agent**: Store only the agent's native format in `NativeData` - no separate fields for different representations of the same data ### Hook Events @@ -70,21 +73,3 @@ Map agent-native hooks to these `EventType` constants (see `agent/event.go`): - [ ] **Resumed session**: Resume existing session, add turns, verify checkpoint includes historical messages - [ ] **Rewind**: Rewind to earlier checkpoint, verify agent can continue from that state - [ ] **Agent shutdown**: Verify graceful handling if agent exits during checkpoint - -## Agent-Specific Notes - -### Claude Code -- Transcript: JSONL file on disk, always complete -- Storage: File-based, `WriteSession` just writes file -- Resume: `claude -r ` - -### Gemini CLI -- Transcript: JSON file on disk, always complete -- Storage: File-based, `WriteSession` just writes file -- Resume: `gemini --resume ` - -### OpenCode -- Transcript: `opencode export ` output (JSON) - this is the native format -- Storage: Database-backed, `WriteSession` writes file then imports via `opencode import` -- Resume: `opencode -s ` -- Note: Don't build transcripts from events - use `opencode export` which reads from SQLite and includes full history