feat(export): sample trace sessions as rows are read

FE
2d ago
+137-2

Stacked on #42 (itself stacked on #40).

--sample-sessions FRACTION (with --dynamo-traces) keeps that fraction of sessions and drops other rows as they are read, before their block hashes are parsed. The exporter holds every loaded row until it writes the manifest, and for a busy model with long prompts that is more than a machine has: one hour of one production model is about 95k rows, each with a few hundred hashes, and the default link window loads a day of them. --sample cannot help there, because it thins trajectories after everything is loaded.

  • A row is kept or dropped with its agent session id, so sessions stay whole. Without one, it goes with its x_request_id, so a request's retried attempts go together, else with its request_id. Such a row can lose the request it extends and then replays as a new trajectory, as docs/export-plans.md now says.
  • The draw is a seeded hash of the key, so for one --seed a smaller fraction keeps a subset of a larger one. Manifests at several loads of the same window are then comparable.
  • Dropped rows are counted as sampled_out.

Tests: sessions are kept whole, fractions nest and differ across seeds, attempts without a session go together, and the CLI checks the fraction. 42 Python tests pass (2 need the compiled agent and skip here).

šŸ¤– Generated with Claude Code

https://claude.ai/code/session_01VDPqeFzGgF3vkuiyimwMxX