Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ replaced, or truncated file fails with a retryable error.

- Claude reconstructs the active UUID ancestry selected by `last-prompt`,
validates compaction back-edges, and excludes inactive branches/meta prompts.
- Codex replays canonical legacy `response_item` history, deduplicates UI
projections, and rejects paginated/history-base lineage.
- Codex replays canonical legacy `response_item` history. For a complete root
paginated rollout it validates contiguous ordinals and takes visible turns
only from `event_msg.item_completed` TurnItems, never from contextual
provider messages. External `history_base` and subagent projections remain
fail-closed.
- Pi follows the v3 `id`/`parentId` active tree and rejects unsupported schema
versions.
- OMP follows its v3 active tree after validating the fixed 256-byte title
Expand Down
36 changes: 34 additions & 2 deletions docs/exploration-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,8 @@ in [Mistral Vibe session format](vibe-format.md).
- Repeat authenticated semantic recall when a supported target/provider version changes.
- Add native fixtures for remote-URL images, branching, and schema drift when
sanitized examples can be generated safely.
- Implement Codex paginated/history-base lineage only after ordinal, contextual
user, compaction, rollback, and inter-agent semantics are independently gated.
- Implement Codex `history_base` and paginated subagent projection only after
external-prefix, rollback, and inter-agent semantics are independently gated.
- Re-run the pinned integration suite for every supported agent version/schema
combination.

Expand Down Expand Up @@ -717,3 +717,35 @@ indexes bounded native titles/IDs without bodies, and represents selection as
validates its install bundle, for 324 ordered routes. Detailed contracts are in
[Hermes](hermes-format.md), [MastraCode](mastracode-format.md), and
[Devin](devin-format.md).

## 2026-09-11: Codex 0.153 root paginated history

PR #4 was reviewed against the official Codex `rust-v0.153.4` source rather
than its original synthetic assumption. `rollout/src/policy.rs` shows that
paginated history persists canonical `TurnItem`s as
`event_msg.item_completed`; legacy user/assistant UI events are deliberately
not persisted in that mode. `rollout/src/ordinal.rs` requires paginated
records to carry a monotonic ordinal, and `protocol/src/protocol.rs` defines
`history_base` as an external exclusive prefix and
`subagent_history_start_ordinal` as the boundary between inherited context and
the subagent's own projection.

A content-free audit then examined 172 recent native paginated rollouts without
`history_base`: nine roots and 163 subagent projections. It inspected only
record/item types, structural fields, counts, and hashed content equality; no
message, tool, media, ID, or path value was printed or committed. Across the
nine roots, 75 canonical user items matched provider user messages and all 242
provider assistant messages matched canonical assistant items. The provider
stream also contained 21 additional user-shaped messages and 53 developer
messages that had no canonical completed turn. Replaying every
`response_item.message`, as the initial PR did, would therefore turn internal
context into visible user history.

The corrected reader makes completed `UserMessage`/`AgentMessage` TurnItems the
only paginated source of conversation turns, retains non-message response items
for portable tool/reasoning data, and records ignored provider messages as
opaque losses. It accepts only self-contained roots with integer ordinals
contiguous from zero. `history_base`, subagent projections, unknown modes, and
damaged ordinal streams fail closed. The sanitized 0.153.4 fixture mirrors the
official nested item shape and includes an unmatched contextual provider
message as a regression sentinel.
39 changes: 26 additions & 13 deletions docs/format-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,24 @@ ordered `response_item` envelopes. Text messages use `type: "message"` with
`function_call_output`; call arguments are a JSON-encoded string, and both
records share `call_id`.

`response_item` is the canonical, model-visible history. `event_msg` records
drive list preview and UI display. The writer emits both for text messages so
the text is visible to the resumed model and to the interface. The reader
deduplicates UI messages against response-item messages. It uses UI events as a
legacy fallback when a rollout has no canonical messages. In a mixed partial
rollout, exact normalized duplicates are removed; unmatched UI projections are
retained as marked messages and reported in the manifest.
For legacy history, `response_item` is the canonical, model-visible history and
`event_msg` records drive list preview and UI display. The writer emits both
for text messages so the text is visible to the resumed model and to the
interface. The reader deduplicates UI messages against response-item messages.
It uses UI events as a legacy fallback when a rollout has no canonical
messages. In a mixed partial legacy rollout, exact normalized duplicates are
removed; unmatched UI projections are retained as marked messages and
reported in the manifest.

Codex 0.147+ root paginated rollouts use a different authority: completed
`UserMessage` and `AgentMessage` TurnItems inside
`event_msg.item_completed`. The reader requires an integer ordinal on every
record, contiguous from zero. It ignores provider `response_item` messages as
conversation because those records can include synthetic environment and
developer context; non-message response items still supply portable tool and
reasoning data. Direct image/audio user inputs are retained when represented
by the canonical TurnItem. Local media paths and other TurnItem blocks remain
explicit opaque losses.

Current legacy rollouts can contain `compacted.replacement_history`. Codex
installs that array as the effective history at the checkpoint and replays only
Expand All @@ -294,21 +305,22 @@ post-compaction context transfer. The paired `event_msg.context_compacted` UI
notification is deduplicated against the checkpoint.

Other observed envelopes include `compacted`, `turn_context`, `world_state`,
reasoning response items, inter-agent communication, and newer paginated or
fork-related state. Those records are not all portable conversation history.
reasoning response items, inter-agent communication, and fork-related state.
Those records are not all portable conversation history.

## Route support

Every ordered pair among the eighteen formats is implemented, for 324 routes:

- full portable adapters: Claude, Codex legacy, Pi, OMP, OpenCode, Copilot,
- full portable adapters: Claude, Codex legacy and root paginated, Pi, OMP, OpenCode, Copilot,
Antigravity, Vibe, Muse, Qwen, Kimi, Grok, Kilo, OpenHands, Hermes,
MastraCode, and Devin;
- experimental text-only adapter: Cursor.

Same-format routes are portable rewrites into new sessions, not byte copies.
Codex paginated/history-base sources remain fail-closed. Cursor is experimental,
build-pinned, and deliberately transfers only ordered user/assistant text. The
Codex `history_base` lineage and paginated subagent projections remain
fail-closed. Cursor is experimental, build-pinned, and deliberately transfers
only ordered user/assistant text. The
detailed table below explains the original Claude/Codex pair; target-specific
behavior is documented in [Additional native formats](additional-target-formats.md)
and [Muse/Qwen/Kimi](muse-qwen-kimi-formats.md). Grok, Kilo, and OpenHands
Expand Down Expand Up @@ -348,7 +360,8 @@ Legend:
| Inactive Claude branches | **Unsupported** | N/A | They become opaque events and are counted as dropped; no forks are created. |
| Claude sidechains/subagents | **Unsupported** | N/A | The catalog indexes nested sidechains as unsupported, but direct lookup/conversion does not import them; transfer the parent session. |
| Codex legacy linear history | N/A | **Supported** | Ordered response items become one linear Claude UUID graph. |
| Codex paginated history/forks | N/A | **Unsupported** | Non-legacy `history_mode` and `history_base` are rejected rather than risking an incomplete import. Replacement-history compaction uses the expanded-transcript policy above. |
| Codex root paginated history | N/A | **Supported** | Contiguous canonical completed TurnItems supply user/assistant turns; provider-context messages are not replayed. Replacement-history compaction uses the expanded-transcript policy above. |
| Codex paginated forks/subagents | N/A | **Unsupported** | `history_base` and `subagent_history_start_ordinal` require external or projected history and are rejected rather than silently truncating or duplicating a conversation. |
| Codex UI-only messages | N/A | **Lossy fallback** | Used as the conversation when no response-item messages exist. In a mixed partial file, exact normalized duplicates are removed and unmatched projections are retained with `message:ui_only_projection`; fuzzy matching is never used. |
| Turn context, policies, world state, snapshots | **Unsupported** | **Unsupported** | Codex `turn_context` is counted as context; `world_state` and `security_risk_score` become counted opaque events. Shell snapshots, approvals, external credential stores, MCP state, memories, goals, and configuration are outside transcript conversion. |
| Unknown source records/blocks | **Unsupported** | **Unsupported** | They become content-free opaque/sentinel events where recognized and are counted at write time, including unknown nested tool-result blocks. |
Expand Down
10 changes: 6 additions & 4 deletions docs/session-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,11 @@ This keeps refresh work proportional to the small inventory table, not the
total transcript corpus.

Consequently, archived sessions, duplicate UUIDs, nested sidechains/subagents,
malformed files, and absent Copilot/Cursor native stores remain discoverable. Claude
sidechains and Codex paginated/history-base sessions are listed as
`unsupported`; listing them does not make them convertible.
malformed files, and absent Copilot/Cursor native stores remain discoverable.
Complete root Codex paginated rollouts are candidates. Claude sidechains,
Codex `history_base` lineage, and paginated subagent projections are listed as
`unsupported`; listing them does not make them convertible. A paginated root
with missing or non-contiguous ordinals is `corrupt`.

## Quick start

Expand Down Expand Up @@ -320,7 +322,7 @@ registered roots.
| --- | --- |
| `candidate` | Fast structural metadata scan passed; full conversion has not been requested. OpenCode and Kilo rows remain candidates until their one-session official export is parsed. |
| `validated` | The exact stat identity was fully parsed, dry-converted, and target-validated during `refresh --validate`. |
| `unsupported` | The file is a recognized session type intentionally rejected by conversion, such as a Claude sidechain or Codex paginated/history-base rollout. |
| `unsupported` | The file is a recognized session type intentionally rejected by conversion, such as a Claude sidechain, Codex `history_base` lineage, or a Codex paginated subagent projection. |
| `corrupt` | JSONL, SQLite/protobuf, native structure, or explicit conversion validation failed. |
| `oversized` | The source exceeds the migrator's bounded input limits. |
| `busy` | The source changed while it was being scanned; retry after the native CLI finishes appending. |
Expand Down
3 changes: 2 additions & 1 deletion docs/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ creates a new independent target session; it does not move/delete the source,
clone runtime state byte-for-byte, synchronize future turns, or re-execute
historical tools.

Codex paginated/history-base lineage and Claude sidechain import remain
Complete root Codex paginated rollouts are transferable. Codex `history_base`
lineage, paginated subagent projections, and Claude sidechain import remain
non-transferable. They are discoverable in the catalog and fail closed.

## Functional requirements
Expand Down
14 changes: 8 additions & 6 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,12 +261,14 @@ separately authenticated Devin installation; session-migrate never copies
credentials. See the [Hermes](hermes-format.md),
[MastraCode](mastracode-format.md), and [Devin](devin-format.md) format notes.

## Codex paginated or history-base source

These lineage modes are recognized but unsupported. `--format codex` cannot
bypass the guard. The safe root-paginated subset still needs ordinal,
contextual-user, compaction/rollback/inter-agent, and lineage semantics before
it can be enabled.
## Codex paginated source is rejected

A complete root paginated rollout is supported when every record has an integer
ordinal contiguous from zero. Missing/gapped ordinals are treated as corrupt.
`history_base` and `subagent_history_start_ordinal` mean the file depends on an
external or projected prefix and remain unsupported; `--format codex` cannot
bypass either guard. Resume or export the root session instead of flattening
the dependent file by hand.

## Claude sidechain/subagent

Expand Down
28 changes: 25 additions & 3 deletions docs/validation-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -1292,11 +1292,33 @@ is committed. Default CI performs the frozen parser and 324 conversion cases
without network access or model spend; live gates remain explicit release
commands.

### 2026-09-11 Codex paginated-source review

The root paginated reader was checked against the official Codex 0.153.4
protocol, rollout persistence policy, and ordinal implementation. A
content-free structural audit over nine recent root rollouts found 81 canonical
user items, 244 canonical assistant items, 21 provider-only user-shaped
messages, and 53 provider developer messages. Only counts and content hashes
were compared; private values were never printed or added to fixtures.

The regression fixture now uses real `event_msg.item_completed` nesting,
canonical `UserMessage`/`AgentMessage` shapes, integer ordinals, and the current
token-usage envelope. Its provider stream deliberately contains an unmatched
context message. Tests prove that canonical text and image history matches the
legacy portable projection, the context sentinel is never replayed, damaged
ordinals fail closed, and external/history-projection metadata remains
unsupported. Catalog tests independently pin candidate, corrupt, and
unsupported classification. All nine audited native roots were parsed and
converted through each of the eighteen target byte validators: 162/162 local,
content-safe conversions passed without writing artifacts or invoking a model.

## Known boundaries

- Codex paginated history and `history_base` lineage remain fail-closed until
their effective-history and fork semantics can be reproduced and native
tested without relying on derived SQLite state.
- Complete root Codex paginated history is supported from canonical completed
TurnItems after strict ordinal validation. `history_base` lineage and
paginated subagent projections remain fail-closed until their external or
projected prefix semantics can be reproduced without relying on derived
SQLite state.
- Provider-encrypted Codex replacement-history state cannot be translated to
Claude. The migrator retains visible expanded history and reports the semantic
difference.
Expand Down
6 changes: 6 additions & 0 deletions scripts/validate-additional-target-corpus.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ def expected_source_rejection(source_format: AgentFormat, exc: SessionMigrateErr
return "codex_history_mode"
if "history_base lineage is not supported" in message:
return "codex_history_base"
if "subagent history projection is not supported" in message:
return "codex_subagent_history"
if "conflicting history modes" in message:
return "codex_history_mode_conflict"
if "paginated" in message and "ordinal" in message:
return "codex_paginated_ordinals"
return None


Expand Down
6 changes: 6 additions & 0 deletions scripts/validate-antigravity-native.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ def expected_rejection(source_format: AgentFormat, exc: SessionMigrateError) ->
return "codex_history_mode"
if "history_base lineage is not supported" in message:
return "codex_history_base"
if "subagent history projection is not supported" in message:
return "codex_subagent_history"
if "conflicting history modes" in message:
return "codex_history_mode_conflict"
if "paginated" in message and "ordinal" in message:
return "codex_paginated_ordinals"
return None


Expand Down
6 changes: 6 additions & 0 deletions scripts/validate-copilot-native.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ def _expected_rejection(source_format: AgentFormat, exc: SessionMigrateError) ->
return "codex_history_mode"
if "history_base lineage is not supported" in message:
return "codex_history_base"
if "subagent history projection is not supported" in message:
return "codex_subagent_history"
if "conflicting history modes" in message:
return "codex_history_mode_conflict"
if "paginated" in message and "ordinal" in message:
return "codex_paginated_ordinals"
return None


Expand Down
6 changes: 6 additions & 0 deletions scripts/validate-core-target-native.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ def expected_rejection(source_format: AgentFormat, exc: SessionMigrateError) ->
return "codex_history_mode"
if "history_base lineage is not supported" in message:
return "codex_history_base"
if "subagent history projection is not supported" in message:
return "codex_subagent_history"
if "conflicting history modes" in message:
return "codex_history_mode_conflict"
if "paginated" in message and "ordinal" in message:
return "codex_paginated_ordinals"
return None


Expand Down
6 changes: 6 additions & 0 deletions scripts/validate-muse-qwen-kimi-corpus.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ def expected_rejection(source_format: AgentFormat, exc: SessionMigrateError) ->
return "codex_history_mode"
if "history_base lineage is not supported" in message:
return "codex_history_base"
if "subagent history projection is not supported" in message:
return "codex_subagent_history"
if "conflicting history modes" in message:
return "codex_history_mode_conflict"
if "paginated" in message and "ordinal" in message:
return "codex_paginated_ordinals"
return None


Expand Down
Loading
Loading