Move coding-agent tracing into the Rust daemon - #1
Merged
Conversation
Stephen Belanger (Qard)
requested review from
Abhijeet Prasad (AbhiPrasad) and
Andrew Kent (realark)
July 28, 2026 20:04
Stephen Belanger (Qard)
force-pushed
the
agent/daemon-tracing-migration
branch
from
July 28, 2026 20:04
3a52637 to
a20b7b1
Compare
Stephen Belanger (Qard)
force-pushed
the
agent/daemon-tracing-migration
branch
from
July 28, 2026 20:10
a20b7b1 to
a2879c7
Compare
Stephen Belanger (Qard)
marked this pull request as ready for review
July 28, 2026 20:10
Stephen Belanger (Qard)
force-pushed
the
agent/daemon-tracing-migration
branch
4 times, most recently
from
July 28, 2026 20:38
ac027ec to
138ac54
Compare
Port the Codex and Claude trace state machines, journal recovery, Braintrust delivery, and hook configuration into the shared bt-daemon crate. Replace the legacy TypeScript and shell implementations with fail-open launchers.\n\nAdd Unix-socket and Windows named-pipe transports, detached lifecycle management, cross-platform pipeline tests, and Linux/macOS/Windows CI. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Stephen Belanger (Qard)
force-pushed
the
agent/daemon-tracing-migration
branch
from
July 28, 2026 20:44
138ac54 to
02d316f
Compare
Andrew Kent (realark)
force-pushed
the
main
branch
8 times, most recently
from
July 29, 2026 01:46
979d26c to
5477976
Compare
Andrew Kent (realark)
approved these changes
Jul 29, 2026
Resolve the release and packaging changes against the Rust daemon architecture. Keep plugin builds content-only, retain the new distribution workflows, and exercise real Codex sessions through a daemon-capable bt CLI and mock Braintrust backend. Add one shared non-credential daemon configuration for all agent plugins. Authentication and backend resolution remain owned by bt, while trace enablement, project, flush behavior, and additional metadata use file-over-environment precedence. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
* Add deterministic agent inference test harness Add separate OpenAI Responses and Anthropic Messages mock servers with closure-driven responses, errors, request capture, and protocol-valid SSE streams. Run real Codex and Claude Code sessions through deterministic tool and provider-error scenarios, then verify the daemon delivers the resulting traces to a mock Braintrust backend. Install the latest unpinned agents in dedicated CI so upstream compatibility breaks surface immediately. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Make agent integration tests core and cross-platform Run the latest real Codex and Claude Code integrations inside the existing Linux, macOS, and Windows daemon matrix instead of a separate Linux-only job. Support both deterministic mock inference with exact scenario assertions and live inference with stable trace-invariant assertions through the same agent runner. Keep the complete programmable inference endpoints self-contained and independent of daemon orchestration so they can later be extracted as a reusable mock-inference crate. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Separate protocol routers from test hosting Have inference and ingest own only their protocol-specific Axum routers and captured state, while the upper-level tests host both through one generic server container. Expose an extensionless Windows test wrapper for hooks launched through Git Bash and make native command hooks prefer executable or command wrappers explicitly. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Add ordered ingest trace scenarios Add named row-shape expectations over the captured ingest stream, matched as an ordered subsequence independently of HTTP batching and unrelated update rows. Use the same scenario mechanism for deterministic deep trace assertions and live invariant-only assertions, with a focused router and ordering test. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Isolate coding-agent install cache in CI Keep both agents unpinned at latest while using a per-runner temporary npm cache and skipping audit/funding requests, avoiding hosted Windows global-cache stalls before the test suite. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Install CI agents into an isolated prefix Install the latest Codex and Claude Code packages into a runner-temporary npm prefix on every platform and pass their exact executable paths into the shared tests, avoiding Windows global-install state. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Scope agent executable paths to the test step Resolve runner-temporary executable paths only after the matrix runner exists, avoiding workflow validation failure while retaining exact cross-platform agent paths. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Expose Windows Codex hook diagnostics Print the real Codex process output on Windows so hook-selection failures are visible in the cross-platform integration job. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Extract reusable coding agent test adapters Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Support Codex shell command tool in tests Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Return from Windows bt hook preflight Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Decouple agent adapters from test world Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Unify live and deterministic agent scenarios Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Remove unreleased test mode alias Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Layer deterministic trace expectations over baseline checks Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Separate live assertions from mock scenarios Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> * Use direct mode checks in agent tests Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com> --------- Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Restore src exactly to main so the currently published Codex and Claude tracing implementations remain in place while the Rust daemon and bt integration land independently. The plugin cutover will follow in a stacked change after a daemon-capable bt release is available. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Keep real Codex and Claude integration coverage in the daemon PR without depending on the production plugin cutover. Generate isolated test plugins whose hooks call bt agents hook directly; the stacked plugin PR replaces these fixtures with the simplified production plugins. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Stephen Belanger (Qard)
force-pushed
the
agent/daemon-tracing-migration
branch
from
July 30, 2026 15:21
709f7bd to
3e019e4
Compare
Report JSON-RPC request receipt and completion while the daemon runs in the foreground. Event logs include only source, event, and session identifiers, with explicit accepted or rejected outcomes; payloads and credentials remain excluded. Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Signed-off-by: Stephen Belanger <stephen.belanger@braintrustdata.com>
Abhijeet Prasad (AbhiPrasad)
approved these changes
Jul 31, 2026
Abhijeet Prasad (AbhiPrasad)
left a comment
Member
There was a problem hiding this comment.
I was hoping more of an architecture where we extract out the state machine to be re-usable between the different translators
struct ClaudeTranslator {
trace: TraceMachine,
// Claude-specific parsing state
transcript_cursors: HashMap<String, TranscriptCursor>,
main_history: Vec<Value>,
pending_skills: Vec<String>,
}
struct CodexTranslator {
trace: TraceMachine,
// Codex-specific parsing state
scopes: HashMap<String, CodexScope>,
compaction_triggers: HashMap<String, String>,
spawn_turn_by_agent_id: HashMap<String, String>,
}but we can think about this in a follow up given these are all internals.
Collaborator
Author
|
I held off on that for now specifically because I don't have a clear enough intuition for what that would look like across all agent types. I didn't want to be defining that with only the common two agents covered and then find none of the others could fit. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dependency
Depends on braintrustdata/braintrust-sdk-rust#86. The daemon pins commit
d33e806bf6ab9548d37355f6a5098a971ef150aaas an exact Git dependency.Summary
This adds the shared Rust coding-agent tracing daemon that will be embedded in the
btCLI. The daemon owns event ordering, auth-redacted journaling, restart recovery, session state, span hierarchy construction, Braintrust delivery, credential isolation, experiment routing, custom parent attachment, and span-origin metadata.The journal is the daemon's recovery WAL. On restart, historical hook events rebuild the translator's in-memory correlation state before new events are processed. Rows produced during that rebuild may be resubmitted to repair interrupted delivery, but every logical span uses the same deterministic span ID and backend row ID, so those writes merge into the existing row rather than creating duplicate spans. The restart test verifies that all historical IDs recur unchanged and only a genuinely new hook event receives a new span ID.
Explicit import is a separate historical workflow.
import <source> <session-id>locates a native Codex rollout or Claude Code transcript in that agent's standard session directories, snapshots it at invocation time, synthesizes the lifecycle events recoverable from that snapshot, and passes them through the regular agent translator and sink. Hook-only facts that are not present in a native transcript are not invented. Codex imports stream the snapshot once, preserve native turn IDs, replace conversation state from native compaction records, and drain delivery in small bounded operation batches so very large sessions cannot overflow the SDK queue or backend row limits and collapse into a partial trace. Claude imports use physical record checkpoints rather than assuming file-order timestamps are monotonic, keeping every reconstructed LLM under its native turn even when Claude appends older continuation records after newer queue bookkeeping. Native Claude API-error markers populate turn and LLM errors, including the HTTP status in LLM metadata. Translator-level import tests cover multi-turn Codex and Claude sessions with LLM and tool spans.The daemon is one Rust crate with a feature-gated standalone development binary. Linux and macOS use Unix-domain sockets; Windows uses per-user byte-mode named pipes with exclusive ownership, busy-instance retry, detached spawn, status, shutdown, and version handover through the same JSON-RPC pipeline.
The daemon supports one shared coding-agent configuration file. It controls trace enablement, project, turn-end flushing, and additional metadata with file-over-environment precedence. Authentication, credentials, organization selection, and backend URLs remain owned and resolved by
bt; parent/root span attachment remains per invocation.This PR intentionally leaves
src/exactly unchanged frommain. The currently published Codex TypeScript runtime and Claude shell runtime therefore continue to build, test, and ship while the daemon and itsbtintegration land. The plugin launchers and legacy-runtime removal remain in stacked follow-up PR #3 and must not land until a daemon-capablebtrelease is available.Real-agent coverage remains in this PR without depending on that future plugin cutover. The test harness generates isolated Codex and Claude plugins whose hooks call
bt trace hookdirectly, then runs the latest unpinned agent CLIs through deterministic inference and ingest scenarios. CI builds, tests, and lints the daemon on Ubuntu, macOS, and Windows and cancels superseded runs for the same PR or branch.Validation
cargo test --manifest-path bt-daemon/Cargo.toml --all-featurescargo fmt --manifest-path bt-daemon/Cargo.toml --checkcargo check --manifest-path bt-daemon/Cargo.toml --all-featuresmake test