PtcRunner.TraceLog.TurnEvent (PtcRunner v0.13.0)

Copy Markdown View Source

Shared builder for the canonical turn event — the substrate-level record of one driver turn, emitted identically by both turn drivers (plan D1):

Both drivers build their turn record through build/1 so the top-level shape is identical and queryable through the same PtcRunner.TraceLog.Analyzer calls, regardless of which driver produced it. Driver-specific richness lives in the data bag; the top-level fields never diverge.

The map is a v2-flat-compatible envelope (event: "turn", schema_version: 2) so it rides the existing PtcRunner.TraceLog JSONL/in-memory sinks. The sink stamps trace_id, timestamp, and seq; this builder never sets them.

Top-level fields

schema_version, event ("turn"),
driver ("session" | "sub_agent"),
session_id, agent_id, agent_name,
turn, attempt, committed, status,
duration_ms, input_tokens, output_tokens, total_tokens,
data

turn is the committed-state counter (advances only when an attempt commits); attempt is the monotonic per-attempt counter (advances on every attempt, including failed ones); committed flags whether this attempt advanced committed state. Failed/parse-error/budget-stop attempts are recorded with committed: false so wasted work is visible without mutating driver state (plan P2 notes).

data bag

program, raw_response, result_preview, prints, memory_diff,
tool_calls, limits_hit, preludes, fail, turn_type

Per-driver fields that don't apply are nil/empty. raw_response carries what the driver's LLM generated when there is no parsed program (SubAgent parse/text-mode failures); it is nil for session turns and normal turns. The whole bag is run through PtcRunner.TraceLog.Event.sanitize/1, which bounds large strings/lists/maps — that is where memory-diff values and prints get their byte bounds.

Summary

Types

Normalized attributes accepted by build/1 (atom-keyed).

Functions

Builds the canonical turn-event map from normalized attributes.

Computes a memory diff (changed_keys + bounded values) between the pre-turn and post-turn memory maps. Keys whose value is unchanged are excluded. PTC-Lisp def cannot remove bindings, so this only surfaces additions and rebindings.

Slims a prelude trace summary (PtcRunner.Lisp.Prelude.trace_summary/1) to the turn-event preludes provenance shape — [%{"source_hash" => ..., "namespaces" => ..., "components" => [...]}], or [] when no prelude was attached. The components key is omitted for single-source prelude artifacts.

Renders a bounded, JSON-safe preview string for a turn result value.

Builds the credential-free turn-log projection for a single tool call.

Types

attrs()

@type attrs() :: map() | keyword()

Normalized attributes accepted by build/1 (atom-keyed).

Functions

build(attrs)

@spec build(attrs()) :: map()

Builds the canonical turn-event map from normalized attributes.

Required: :driver (:session | :sub_agent). All other keys are optional and default to nil / empty. trace_id/timestamp/seq are intentionally omitted — the sink stamps them.

memory_diff(before, after_memory)

@spec memory_diff(map(), map()) :: %{changed_keys: [String.t()], values: map()} | nil

Computes a memory diff (changed_keys + bounded values) between the pre-turn and post-turn memory maps. Keys whose value is unchanged are excluded. PTC-Lisp def cannot remove bindings, so this only surfaces additions and rebindings.

prelude_provenance(summary)

@spec prelude_provenance(map() | nil) :: [map()]

Slims a prelude trace summary (PtcRunner.Lisp.Prelude.trace_summary/1) to the turn-event preludes provenance shape — [%{"source_hash" => ..., "namespaces" => ..., "components" => [...]}], or [] when no prelude was attached. The components key is omitted for single-source prelude artifacts.

Shared by both drivers so the provenance field (the single field that makes A/B benchmarking and derivation provenance trivial, per the plan) reads identically whether a session or a SubAgent turn produced it.

preview(value)

@spec preview(term()) :: String.t()

Renders a bounded, JSON-safe preview string for a turn result value.

Shared by both drivers so result_preview reads the same regardless of who produced the turn.

tool_call_summary(call)

@spec tool_call_summary(map()) :: map()

Builds the credential-free turn-log projection for a single tool call.

The projection intentionally excludes raw arguments and results. It keeps a stable args_hash derived from the same canonical argument identity used by tool caching, so PTC-Lisp log analysis can detect duplicate fetches without ingesting potentially large or sensitive payloads.