Trace JSON Schema reference

The full schema is in contracts/claude-code-parity-apr-v1.yaml § trace_schema. This page is a quick reference; the YAML is canonical.

Record kinds

// session_start — first record of every trace
{
  "kind": "session_start",
  "session_id": "string",
  "cwd": "/absolute/path",
  "git_commit": "deadbeef..."
}

// user_prompt — user-initiated turn
{
  "kind": "user_prompt",
  "text": "Fix the failing test.",
  "attachments": [/* optional */]
}

// assistant_turn — model response
{
  "kind": "assistant_turn",
  "blocks": [
    {"type": "text", "text": "I'll start by reading the file."},
    {"type": "tool_use", "id": "tu_1", "name": "Read", "input": {"path": "src/lib.rs"}}
  ],
  "stop_reason": "tool_use"  // or "end_turn", "max_tokens", "stop_sequence"
}

// tool_result — tool execution result
{
  "kind": "tool_result",
  "tool_use_id": "tu_1",
  "content": "<file contents>",
  "is_error": false
}

// session_end — last record
{
  "kind": "session_end",
  "reason": "end_turn"  // or "max_turns", "wall_timeout", "driver_error", etc.
}

// hook_event — hook fired (schema v2, M15)
{
  "kind": "hook_event",
  "hook_name": "pre-tool-use",
  "trigger": "PreToolUse",
  "tool_use_id": "tu_1"  // optional; null if pre-session
}

// skill_invocation — skill invoked (schema v2, M15)
{
  "kind": "skill_invocation",
  "skill_name": "explain",
  "args": {"depth": "medium"}
}

Block types (inside assistant_turn.blocks[])

// Text — plain text output
{"type": "text", "text": "..."}

// ToolUse — a tool call
{"type": "tool_use", "id": "tu_<n>", "name": "Bash|Read|Write|Edit|...", "input": {...}}

// Thinking — extended thinking (claude-only; optional)
{"type": "thinking", "text": "..."}

stop_reason values

ValueMeaning
tool_useModel emitted a tool_call; turn ends here
end_turnModel's natural turn boundary (e.g., emitted EOS)
max_tokensHit the token cap
stop_sequenceHit a configured stop sequence

Rust types

The Rust-side types are in crates/ccpa-trace/src/lib.rs:

pub struct Trace { pub records: Vec<Record> }

#[serde(tag = "kind", rename_all = "snake_case")]
pub enum Record {
    SessionStart { session_id: String, cwd: PathBuf, git_commit: String },
    UserPrompt { text: String, attachments: Vec<Attachment> },
    AssistantTurn { blocks: Vec<Block>, stop_reason: StopReason },
    ToolResult { tool_use_id: String, content: String, is_error: bool },
    SessionEnd { reason: SessionEndReason },
    HookEvent { hook_name: String, trigger: HookTrigger, tool_use_id: Option<String> },
    SkillInvocation { skill_name: String, args: serde_json::Value },
}

The roundtrip falsifier (FALSIFY-CCPA-001) asserts that every value serializes → parses → re-serializes losslessly.