Skip to content

Trajectory interop spec: importer and exporter design - #19

Open
adewale wants to merge 2 commits into
mainfrom
claude/letta-trajectory-blog-80byr3
Open

Trajectory interop spec: importer and exporter design#19
adewale wants to merge 2 commits into
mainfrom
claude/letta-trajectory-blog-80byr3

Conversation

@adewale

@adewale adewale commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

Add comprehensive specification for trajectory-v1 interchange format support, defining the contract for importing agent session data from external sources and exporting aha sessions to the trajectory format for consumption by other tools.

Key changes

  • Specification document (docs/trajectory-interop-spec.md): Complete design for trajectory-v1 importer and exporter, including:
    • Data model mappings between trajectory-v1 and aha's internal ParsedEntry representation
    • Six load-bearing properties of the format that drive architectural decisions
    • Correctness-by-construction patterns for the implementation (sum types, builders, opaque timestamps, redaction boundaries)
    • Nine named laws (L1–L9) that define the contract and are testable
    • Comprehensive test strategy across 11 layers (schema, conformance, golden, property, fuzz, exhaustive, Type B, differential, CLI journey, static guards, mutation)
    • Phased rollout plan (4 phases) with red-green-refactor discipline
    • Loss table documenting exactly which fields survive round-trip and which are dropped
    • Non-goals clarifying what trajectory-v1 is not (not our internal model, not canonical-v1, no replay, no network behavior)

Notable design decisions

  • Importer as a source adapter: Reuses existing SourceAdapter interface, gaining redaction, content-addressed blobs, read-only guarantee, and conformance harnesses for free
  • Exporter as a library + workspace operation: Pure projection function with no I/O, surfaced via aha workspace export command (not a top-level export command, which was explicitly frozen in v0.2)
  • Redaction boundary enforcement: Exporter cannot import internal/depot, internal/archive, or internal/cas; constructed only from redacted corpus rows
  • Sum type for assistant records: Prose and tool calls are mutually exclusive per schema; modeled as a sum type to make invalid states unrepresentable
  • Entry identity ladder: Replaces boolean HasStableEntryIDs with closed variant (native, location, content, synthetic, unknown) to distinguish materially different identity strategies
  • Two independent validators: Every document validated through both JSON Schema and hand-written Go validator; disagreements are test failures
  • Deterministic export: No map iteration, no ambient time, stable key order; two exports of the same session are byte-identical
  • Sidecar for metadata: Everything the schema forbids (via additionalProperties: false) goes in a companion .aha.json file

Test strategy highlights

  • Tier-1 minimal fixtures, tier-2 adversarial fixtures (must reject), tier-3 vendored real sessions
  • Property tests over generated documents for laws L2, L3, L4, L6, L7, L9
  • Fuzz targets for parse robustness and round-trip fixed point
  • Opt-in differential test against reference implementation (@letta-ai/trajectory)
  • Golden documents with version-field exclusion to avoid noise on release bumps
  • CLI journey test proving full loop: init → upload → download → export → re-import → search
  • Static guards for import bans, schema vendoring integrity, naming rules
  • Mutation testing for critical paths (pairing, redaction boundary, destination check, timestamp validation)

Definition of done

Specification is complete and ready for implementation phases. All nine laws are defined and testable. Type A/Type B inventory covers every invariant. Phased rollout plan provides clear sequencing from gates (Phase 0) through importer (Phase 1), exporter library (Phase 2), surfaces (Phase 3), and closing the loop (Phase 4).

https://claude.ai/code/session_019bXCp1iJB7dU2cAxSzWKmY

claude added 2 commits July 25, 2026 08:59
Specify two-way interop with Letta's trajectory-v1 interchange format,
read off the authoritative schema rather than the announcement post.

The importer is a source adapter, so it inherits redaction, content
addressing, manifests, and the read-only guarantee with no new command.
The exporter is a projection package plus one Workspace transition, and
may only read redacted corpus rows -- never Archive blobs.

Six schema properties drive the design: a trajectory is a JSON array
rather than JSONL; additionalProperties is false everywhere, so aha
metadata goes in a sidecar; the assistant record is a closed two-way
variant modelled as a sum type; tool results carry no error signal, so
exit codes are lost on export and never inferred on import; timestamps
are pattern-constrained, so untimestamped entries are dropped loudly;
and meta is flat, with no tree or subagent structure.

Nine named laws carry the verification, each with a Type A and a Type B
test: schema closure, no invention, loss-table honesty, import
idempotence as an exact byte-level fixed point, link integrity, order
preservation, redaction fixed point, truncation honesty, read-only
boundaries, and determinism. Schema conformance is gated with the
jsonschema-go module already present indirectly, so no new direct
dependency is required.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019bXCp1iJB7dU2cAxSzWKmY
Fold three mechanisms from the reference implementation's ecosystem into
the interop spec.

Validate every document through two independently written validators --
the vendored JSON Schema and a hand-written Go validator -- and assert
they agree. A schema passes things that are semantically wrong (args
decoding to an array satisfies "type": "string"), and a hand-written
validator drifts the moment upstream revises the schema; each catches the
other's blind spot. Cross-record properties no schema can express, such
as tool-call resolution, live in the hand-written half. Disagreements
outside a committed exception list are themselves failures.

Exclude version constants from golden comparison and assert them by
separate rule instead, so a release bump cannot rewrite every golden and
drown the diffs a reviewer is meant to read.

Replace AdapterCapabilities.HasStableEntryIDs with a closed
EntryIdentityKind ladder, promoted from an open question to scoped work.
The importer is the forcing function: it is the first adapter whose
message identity is content-derived and whose session header is
synthetic, and one boolean puts it in the same bucket as Pi. The boolean
becomes a derived method so it cannot disagree with the kind; manifest
marshalling stays additive per the compatibility policy; and legacy
manifests read back as unknown rather than as an invented level.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019bXCp1iJB7dU2cAxSzWKmY
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.

2 participants