Scope note: consumers choose
third_party/rgo/v0_60_0/baseor a versioned base tree. Maintainer-only local regression fixtures live intools/tests/rules_go_variant_regressions.
This document explains the Go instrumentation path as it exists today in this repository.
It focuses on the current steady-state design:
- how
dd_topt_go_testis exposed to users - how bootstrap wires a workspace for Orchestrion
- how the vendored
rules_gofork invokes Orchestrion under Bazel - how stdlib weaving, synthetic
testmain, and final link stay consistent - which invariants matter if you need to maintain or extend this path
If you need the current optimization status, the experiments that were kept or reverted, or the latest measured bottlenecks, start with go_orchestrion_maintainer_state.md and then return here for the lower-level architectural detail.
This is a maintainer document. It intentionally describes the current system, not the debugging history that produced it.
The Go integration is split across bootstrap, Starlark, vendored rules_go,
and patched Orchestrion source. This section states upfront that the document is
meant to unify those pieces into one operational model.
The Go integration spans four layers:
- User-facing macro and analysis-time selection
- Bootstrap and workspace wiring
- Vendored
rules_gofork with Orchestrion support - Datadog Orchestrion itself, built from patched source
Primary implementation entry points follow the default upstream path
third_party/rgo/v0_60_0/base. For another supported upstream, resolve the
tree with:
python3 tools/dev/materialize_rules_go_fork.py resolve --upstream <upstream> --variant baseThen use the same relative files under that tree.
- modules/go/topt_go_test.bzl
- modules/go/topt_go_orchestrion.bzl
- modules/go/tools/dd_topt_go_bootstrap/main.go
- third_party/rgo/v0_60_0/base/go/private/orchestrion/extensions.bzl
- third_party/rgo/v0_60_0/base/go/private/actions/archive.bzl
- third_party/rgo/v0_60_0/base/go/private/actions/compilepkg.bzl
- third_party/rgo/v0_60_0/base/go/private/actions/link.bzl
- third_party/rgo/v0_60_0/base/go/tools/builders/compilepkg.go
- third_party/rgo/v0_60_0/base/go/tools/builders/importcfg.go
- third_party/rgo/v0_60_0/base/go/tools/builders/link.go
- third_party/rgo/v0_60_0/base/go/tools/builders/orchestrion.go
The repository is broader than the Go integration path. This section narrows the document to the files that actually determine how Orchestrion-backed Go tests work.
The system is easiest to understand as three concentric layers:
- Bazel remains the outer build and test system.
rules_goremains the Go rule implementation, but we vendor a fork that knows how to invoke Orchestrion coherently.- Orchestrion remains the inner compile-time instrumentation engine.
The user still writes a Bazel-native target:
dd_topt_go_test(
name = "pkg_test",
srcs = ["*_test.go"],
orchestrion_mode = "test_optimization",
topt_data = topt_data,
)When Test Optimization is enabled, the raw go_test is built under a
transition that enables the requested Orchestrion mode in the vendored
toolchain. When the selected sync export is disabled, the macro instead creates
only the caller's public raw go_test.
The most common architectural mistake is to think of Orchestrion as an external
post-processing step. This section sets the correct model: Bazel, vendored
rules_go, and Orchestrion are one compile pipeline.
flowchart TD
A[MODULE.bazel] --> B[Go companion extension]
A --> C[dd_topt_go_bootstrap]
C --> D[Bzlmod MODULE.bazel patching or WORKSPACE local scaffolding]
C --> E[orchestrion pin files]
D --> F[vendored rules_go fork]
D --> W[Bazel-managed Go SDK]
F --> G[rules_go Orchestrion extension]
G --> U{Test Optimization enabled?}
U -->|no| V[stable empty repository\n no host Go or source fetch]
U -->|yes| H[patched Orchestrion binary]
W --> H
I[BUILD: dd_topt_go_test] --> R{Sync export enabled?}
R -->|no| S[public raw go_test\n no Test Optimization targets]
R -->|yes| J[hidden raw go_test]
R -->|yes| K[public orch_go_test wrapper]
K --> L[function transition]
L --> J
J --> M[compilepkg / stdlib / link actions]
M --> N[Orchestrion toolexec path]
N --> O[woven stdlib + package compile + synthetic testmain]
O --> P[final Bazel test binary]
P --> Q[CI Visibility runtime + payloads]
The rest of the document is easier to follow if the major boundaries are visible first. This diagram is the system map the later sections zoom into.
The public API is intentionally simpler than the internal implementation. This section explains the supported user-facing contract before moving into toolchain mechanics.
The consumer adds:
- the core module
- the Go companion module
rules_go- the Go companion extension repo
In the guided Go path, bootstrap writes test_optimization_go_extension, which
materializes the metadata repo used by dd_topt_go_test.
- In guided single-service setup, bootstrap writes the managed
test_optimization_go_extensionblock anduse_repo(...)call. - In manual single-service or multi-service setup, the Go macro only requires a
compatible exported
topt_datashape. That can come from the Go extension or from the core sync and multi-sync extensions. - In a consumer-managed Go/Python monorepo, the separate manifest-sync
aggregate exports
topt_data_by_target; the central Go wrapper passes the matching entry to the same macro. Target discovery and service naming happen before repository resolution in the consumer command, not in Orchestrion orrules_go.
The generated metadata repo then provides the per-service and per-module
payload labels consumed by dd_topt_go_test.
Analysis-time payload selection depends on repository-level metadata. Module setup creates the repos and exports the macro needs later.
The bootstrap binary is the one-time workspace mutation step.
Implementation:
In guided Bzlmod mode, bootstrap does six things that matter for the current architecture:
- Ensures
MODULE.bazelcontainsbazel_dep(name = "rules_go", version = "0.60.0") - Writes a managed
git_overrideforrules_gopointing back to this repo withstrip_prefix = "third_party/rgo/v0_60_0/base" - Declares a Bazel-managed Go SDK from
--runtime-version - Enables the
@rules_go//go:extensions.bzlOrchestrion extension, passes the SDK root and exact version, and importsuse_repo(orchestrion, "rules_go_orchestrion_tool") - Sets the workspace-wide tracer selection with either
orchestrion.from_source(..., dd_trace_go_version = "...")ororchestrion.from_source(..., dd_trace_go_versions = {...}) - Runs
orchestrion pinin the Go module and ensures:go.modgo.sumorchestrion.tool.goorchestrion.yml
The important point is that bootstrap does not merely install an external tool. It aligns:
- Bazel module wiring
- the vendored
rules_gofork - the Bazel-managed Go SDK used to build Orchestrion
- the selected
dd-trace-goversion used by Bazel injection - the pinned Go module files that Orchestrion expects
In WORKSPACE mode, bootstrap deliberately does not edit WORKSPACE. It prints
repository wiring for review and can write only repository-local scaffolding:
the managed .bazelrc block, root doctor/uploader targets, Orchestrion pin
files, wrapper template, and validation script. Large WORKSPACE monorepos keep
their repository placement and local wrapper policy under owner review while
still using the same Orchestrion-enabled rules_go variants.
If no tracer setting is present, the default is still
v2.9.1. Bootstrap keeps the local Go module
on the same effective versions, and the Bazel build now fails fast if the
workspace setting and the local Go module pins drift apart.
The downloaded Orchestrion tool source is still patched before Bazel builds the
binary, but Bazel now builds that tool from Orchestrion's upstream module graph
instead of rewriting the tool repo's own go.mod. The selected tracer version
is enforced later against the target module through the emitted
dd_trace_go_versions.json file and the builder-side validation path.
Manual consumer wiring normally replaces bootstrap's explicit tracer selection
with dd_trace_go_pin_files = ["@//:go.mod", "@//:go.sum"]. The repository rule
uses the Bazel-managed Go SDK to resolve every supported direct or transitive
module with -mod=readonly, emits the same canonical
dd_trace_go_versions.json, and keys the bootstrap cache by that resolved map.
Explicit shared and per-module selections remain compatibility escape hatches.
Bootstrap centralizes the one-time mutations needed to make Bazel and Orchestrion agree on the workspace shape. Without that central step, each test target would need to carry fragile setup knowledge.
dd_topt_go_test is the public macro surface.
Implementation:
With an enabled sync export, the macro does three distinct jobs:
- Select Datadog payload data
- Prepare runtime env/data wiring for Test Optimization
- Route the public test through the Orchestrion wrapper transition
The enabled macro expands into:
- a hidden raw
go_test - a public
orch_go_testwrapper
With a disabled export, the macro validates its macro-only inputs and selected
service, then creates only the caller's public raw go_test. It does not create
the hidden test, payload selector, target metadata, Orchestrion pin, or wrapper
targets. The public label is therefore stable across modes, but the rule class
is not: it is go_test while disabled and orch_go_test while enabled.
The wrapper forwards orchestrion_mode into the vendored rules_go fork. The
default mode is general, which preserves broad generic Orchestrion behavior.
For standard Go testing, use orchestrion_mode = "test_optimization". That
mode keeps stdlib testing, synthetic testmain, helper packagefile, importcfg,
and link support coherent while ordinary customer packages and external _test
packages compile on the plain rules_go path. Nested packages still need
package-local pin files or explicit orchestrion_pin_files, and callers can
disable the test-binary linker flag optimization with
enable_test_binary_linker_optimization = False.
When present in the current Bazel package, the raw go_test stages the local
Orchestrion pin files as hidden data:
go.modgo.sumorchestrion.tool.goorchestrion.yml
The macro discovers them with a package-local glob, so this is automatic for packages that contain those files, but it is not a cross-workspace guarantee for arbitrary subpackages.
That keeps typical module-root packages simple without implying that every Go test target in every package automatically receives those files.
The macro is the policy boundary. It keeps user BUILD files simple while combining payload selection, runtime wiring, and Orchestrion-enabled compilation in one place.
Implementation:
In the enabled path, the wrapper rule applies a function transition that sets only:
"@rules_go//go/private/orchestrion:mode": "general" or "test_optimization"The transition deliberately preserves the existing
@rules_go//go/private/orchestrion:enabled setting. The user-facing
--config=test-optimization config enables that setting during analysis;
omitting the config leaves it at the rules_go default of False.
The wrapper then symlinks the executable produced by the raw target and returns the same runfiles.
This preserves normal Bazel test ergonomics while moving the actual build onto an Orchestrion-enabled configuration.
The transition wrapper lets the raw test build under a different configuration
without changing the public target label that users and CI invoke. Callers that
filter tests by rule language must account for the mode-dependent rule class:
go for the disabled raw target and orch_go for the enabled wrapper.
Orchestrion is fundamentally a toolexec-style integration. In a plain Go
workflow, the intended shape is conceptually:
go test -toolexec="orchestrion toolexec"
rules_go does not expose a single public seam that means "attach this
toolexec everywhere and preserve normal Go behavior". Under Bazel, the Go
pipeline is decomposed into builder actions:
- stdlib list and stdlib build
- package compilation
- synthetic
testmaingeneration and compile - final link
For Orchestrion to behave correctly, all of those steps must agree on:
- module context
- GOROOT and SDK layout
- importcfg contents
- Datadog helper packagefiles
- stdlib export family
- synthetic test binary link inputs
That is why the repository vendors a rules_go fork instead of trying to bolt
Orchestrion on as an external wrapper.
The vendored fork is the key architectural decision. If a maintainer does not understand why it exists, they will naturally try to simplify the wrong layer.
flowchart LR
A[dd_topt_go_test] --> B[raw go_test]
B --> C[vendored rules_go actions]
C --> D[patched Orchestrion binary]
D --> E[go compile]
D --> F[go link]
C --> G[importcfg rewriting]
C --> H[stdlib cache/export handling]
C --> I[synthetic testmain manifest]
I --> F
This is the toolchain-only view of the system. It highlights where state is carried between compile and link, which is the part most maintainers need to reason about when something breaks.
The vendored fork owns the Orchestrion integration at the action and builder layer.
The fork is not just a copy of upstream rules_go; it is the layer that makes
the Bazel pipeline and Orchestrion pipeline behave coherently.
Responsibilities:
- declare the outputs needed by Orchestrion-aware compile and link steps
- pass the Orchestrion binary into builders
- pass the synthetic
testmainmanifest sidecar through analysis and execution
Starlark is where Bazel decides which files and arguments are real. If the manifest sidecar or Orchestrion tool are not declared here, the builders cannot use them later.
Responsibilities:
- prepare a safe Go module environment for Orchestrion
- normalize GOROOT and SDK behavior in Bazel sandboxes
- rewrite importcfg so woven stdlib and Datadog helper packages are resolvable
- persist synthetic
testmainhelper selections across compile and link - ensure final link reuses the same helper export family chosen during compile
Execution-time coherence cannot be solved in analysis alone. The builder layer is where the environment, importcfg, and archive family are made consistent.
The vendored rules_go fork does not use upstream Orchestrion unchanged.
Implementation:
The Orchestrion repository rule downloads Orchestrion source and patches it before building the binary. The patches fall into a few categories:
Orchestrion sometimes shells out to go list while resolving injectors and
package files. Under Bazel, that has to work in a synthetic module layout and
inside sandboxes.
The patches make dependency resolution less recursive and more Bazel-friendly, and they create compatibility symlinks in temporary work directories where needed.
Upstream Orchestrion expects a more conventional Go execution environment than Bazel provides. These patches adapt resolver behavior to Bazel sandboxes and synthetic work directories.
The compile proxy is patched so it can correctly understand linker-object
outputs and cooperate with the synthetic testmain flow.
The synthetic testmain path needs metadata to survive across Bazel's separate
compile and link stages. The compile proxy has to preserve that information.
The oncompile, oncompile-main, and onlink hooks are patched so dependency
lookups run with the Bazel-specific import-path context they actually need, not
only with upstream assumptions about a normal Go tool invocation.
Under Bazel, package identity can differ from what upstream Orchestrion would
infer from a normal go command. These patches keep lookup context aligned with
the package Bazel is actually compiling.
Some patches keep Orchestrion from dropping required aspects too early or failing to discover stdlib archives when Bazel's importcfg layout differs from what upstream Orchestrion normally sees.
If Orchestrion rejects a package too early or cannot locate stdlib archives, later steps cannot recover. These patches keep the instrumentation path open.
The result is still "Orchestrion from source", but it is a Bazel-adapted build of Orchestrion, not a stock upstream binary.
The Orchestrion binary is part of the supported integration surface. This
section explains why the current design depends on a Bazel-adapted Orchestrion
build, not just on the vendored rules_go changes.
Compile is where the system first moves from "configured for instrumentation" to "producing instrumented artifacts". This section explains that boundary.
The compile entry point is:
At compile time, the builder:
- Parses the normal
rules_gocompile arguments - Creates a work directory
- Prepares a Go module/cache environment for Orchestrion
- Filters sources and applies cgo/coverage/nogo handling as usual
- Invokes the Go compiler through Orchestrion when enabled
In test_optimization mode, package compile is deliberately narrower:
customer packages and external _test packages do not receive Orchestrion
toolexec. The synthetic testmain compile still receives Orchestrion context
so it can produce the Datadog helper packagefile manifest consumed by final
link.
The key Orchestrion-specific compile responsibilities are:
- module/cache preparation
- importcfg rewriting
- synthetic
testmainhelper capture
Package compile is the first place where wrong module context, wrong importcfg, or wrong stdlib selection can poison everything downstream.
rules_go synthesizes a testmain.go package for Go tests. That synthetic
package is special because it is the point where Datadog CI Visibility hooks
around testing become visible in the final test binary.
For synthetic testmain, compilepkg generates a sidecar manifest:
- logical manifest name inside the workdir:
orchestrion.pack - declared Bazel sidecar output:
<archive>.a.orchestrion.pack
Implementation details:
The sidecar records the compile-time packagefile directives for the Datadog
helper packages that synthetic testmain was rooted against. That is the
contract between compile and final link.
testing instrumentation enters through synthetic testmain. The sidecar
exists so final link can reuse the exact helper package family chosen during
compile instead of reconstructing a different one.
The importcfg layer is where the Bazel/Orchestrion integration becomes most concrete.
Implementation:
This file owns several distinct jobs:
Importcfg is the explicit statement of what the toolchain can import. This section explains how the integration shapes that package universe.
Orchestrion may need the woven stdlib archive family, not just the default one. The builder can source stdlib packagefiles from:
- normal Bazel stdlib archives
- seeded stdlib cache exports
- persisted stdlib export manifests
Orchestrion can weave stdlib packages, so compile and link need to resolve the woven stdlib archive family rather than silently falling back to the default unwoven one.
The Datadog helper packages used for CI Visibility and tracing must exist as
real packagefile entries in the importcfg seen by compile and link.
Injected CI Visibility hooks become ordinary package dependencies after weaving. If their exports are missing from importcfg, the final binary cannot preserve the instrumentation path.
The builder rewrites existing packagefile directives and appends missing ones
so the toolchain sees a coherent package universe.
Bazel's default importcfg contents do not fully describe the instrumented build graph. Rewriting is how the builders present the package set Orchestrion actually needs.
The final link must not invent a different Datadog helper export family than
the one synthetic testmain compile already used. The importcfg layer is where
that reuse is made explicit.
Compile and link are separate actions. Helper-root reuse is the mechanism that keeps them inside the same Datadog package universe.
The link entry point is:
The link builder has two broad paths:
- normal Orchestrion-enabled link
- synthetic test binary link
In test_optimization mode, the final synthetic test binary link does not run
with -orchestrion. It consumes the synthetic testmain manifest and helper
packagefiles produced earlier, then keeps the link action free of unused
Orchestrion proxy and pin-file inputs. Generic mode can still use the broader
Orchestrion link behavior.
Link is the last place where separate compile outputs can either converge into a coherent binary or drift apart. This section explains how the current design forces convergence.
When linking a normal main package, link can run through Orchestrion directly and can append the broader Datadog helper closure it needs for the final binary.
Normal link establishes the baseline behavior: link may complete the helper closure, but it must still stay inside one consistent export family.
When linking the Bazel synthetic test binary, the path is more constrained.
link.go detects a synthetic test link from the main archive name:
~testmain.a
For synthetic test links it:
- Reads the synthetic
testmainsidecar manifest - Applies those
packagefiledirectives into the link importcfg - Reuses the compile-time Datadog helper root
- Completes the broader Datadog closure from that same root when link itself is still Orchestrion-enabled
In test_optimization mode, customer package compiles remain plain and the
helper closure is reduced around the standard Go testing path. The mode still
lets the woven stdlib cover standard packages such as net/http and log/slog,
but Datadog contrib HTTP/slog helpers and profiler roots stay out of the
synthetic testmain helper/link closure. Automatic testify/suite support is
outside this mode.
That is the core consistency rule of the current implementation:
synthetic
testmaincompile and final link must operate on the same Datadog helper export family
Without that, compile may instrument testing, but the final linked test binary
may not preserve those hooks coherently.
This is the highest-risk link path because Bazel's synthetic test wrapper and
Datadog's testing instrumentation meet here. The sidecar manifest exists to
make that join deterministic.
Implementation:
This file centralizes the environment preparation Orchestrion needs under Bazel.
Important responsibilities:
The builders do not run in a normal developer shell. This section explains the supporting environment that must exist before Orchestrion can do useful work.
The builder ensures writable:
GOPATHGOMODCACHEGOCACHE
That matters because Orchestrion shells out to Go tooling while resolving injectors and package files.
Without writable caches and module storage, Orchestrion's internal go calls
fail inside Bazel sandboxes even when the outer action is otherwise correct.
Bootstrap and sandboxed builder steps share the
datadog-orchestrion-go-cache namespace, but not always the exact same root
path.
- the builder and extension prefer a persistent host cache root
- the guided bootstrap CLI uses a temp-rooted cache location for its own local workflow unless you override the environment
This still lets Orchestrion reuse fetched modules instead of redownloading them for each sandboxed step.
The shared cache is not just a performance optimization. It keeps bootstrap-time pinning and sandboxed builder steps working against the same downloaded module set.
Some Bazel sandboxes expose an SDK layout that differs from what Orchestrion's subprocesses assume. The builder normalizes that by:
- resolving absolute SDK/GOROOT paths
- creating compatibility symlinks when
GOROOT/srcis missing
Orchestrion and the Go toolchain expect a usable GOROOT layout. Bazel's SDK presentation can differ enough that the builders need to repair that view.
Orchestrion expects a real Go module context. The builder prepares a synthetic module environment when the Bazel workdir does not already match that shape.
Orchestrion resolves injectors and pinned module files through Go module semantics. Synthetic module preparation gives it a workspace shape compatible with those expectations.
The builder can probe or warm the dependencies Orchestrion commonly weaves.
In generic mode this includes the broader tracing/profiling and contrib helper
set. In test_optimization mode the synthetic module and helper closure are
reduced to the standard Go testing Test Optimization path and exclude profiler
and Datadog contrib HTTP/slog helper roots.
Some required woven dependencies are first touched inside sandboxed steps. Warming them reduces failures caused by lazy first access in those contexts.
The disabled path stops at the macro: it creates the public raw go_test and
does not enter the wrapper, vendored Orchestrion, or payload path below.
sequenceDiagram
participant User
participant Macro as dd_topt_go_test
participant Wrapper as orch_go_test
participant RG as vendored rules_go
participant Orch as patched Orchestrion
participant Bin as final test binary
User->>Macro: declare Go test
Macro->>Macro: select payload data + add pin files
Macro->>Wrapper: public test target
Wrapper->>RG: build raw go_test with mode transition; preserve enabled flag
RG->>RG: compile customer packages
RG->>Orch: compile woven stdlib as needed
RG->>Orch: prepare synthetic testmain helper packagefiles
RG->>RG: persist synthetic helper manifest sidecar
RG->>RG: link final binary using same helper family
RG->>Bin: produce instrumented test executable
Bin->>Bin: emit tracer / CI Visibility runtime
The system crosses many boundaries. This sequence compresses them into one path so a maintainer can reason from the declared test target to the observed runtime behavior.
At runtime, a correctly wired binary shows evidence that the compile-time path worked:
- Datadog tracer debug logs can appear when enabled
- CI Visibility hooks around Go
testingare preserved in the final test binary
Those runtime markers are not produced by the macro alone. They depend on the
compile, synthetic testmain, and final link steps all agreeing on the same
instrumented package universe.
Separate from runtime behavior, the builders also use archive-content heuristics
such as instrumentTestingTFunc and instrumentTestingM while scanning helper
exports during compile/link consistency checks. Those names are useful
build-time indicators, but they are not themselves user-visible runtime
signals.
The global goal is not just "a successful build". It is a final test binary whose runtime behavior proves that CI Visibility instrumentation survived the full Bazel compile and link pipeline.
If you change this system, keep these invariants intact.
This section marks the boundaries of safe refactoring. It separates incidental implementation details from the properties that actually make the design work.
Users should keep writing dd_topt_go_test, not a custom shell rule or an
alternate test runner.
The integration is meant to feel like normal Bazel usage to consumers. If the public entry point changes shape, the maintenance burden moves into every consumer workspace.
The bootstrap tool is the place that mutates:
MODULE.bazelorchestrion.tool.goorchestrion.yml- pinned Go module files
Do not push that complexity onto each test target.
Workspace mutation has to happen in one place or the setup becomes fragile and non-idempotent. Bootstrap is that one place.
The sidecar manifest and helper-root reuse are structural, not optional.
This is the specific invariant that keeps testing instrumentation alive in the
final binary. Losing it produces apparently successful builds with incomplete
runtime behavior.
If compile or link needs a packagefile and it is not in importcfg, that is an importcfg problem first.
Putting package-universe fixes in multiple places makes the pipeline impossible to reason about. Importcfg must remain the primary source of truth.
Builder-side synthetic module and cache preparation are not cosmetic. They are required because Orchestrion shells out to Go tooling internally.
If Orchestrion cannot see a usable Go module environment, it stops behaving like the tool this design expects and starts failing in ways that look unrelated to the actual instrumentation logic.
The source patches in extensions.bzl are part of the supported design. Treat
them as first-class integration code, not as temporary local hacks.
The vendored rules_go changes alone are not enough. The built Orchestrion
binary carries Bazel-specific behavior that the rest of the design relies on.
When something breaks, this is the fastest place to look.
The implementation surface is large. This section shortens the feedback loop by mapping likely failure classes to the files that actually control them.
Look here if:
MODULE.bazelwiring is wrongrules_go_orchestrion_toolis missingorchestrion.tool.gowas not pinned
Many failures that look like compile bugs are really workspace-shape bugs. This section makes that distinction explicit.
Look here if:
- the wrapper target is not enabling Orchestrion
- runfiles or executable naming are wrong
- payload data selection is wrong
This is the place to debug analysis-time mistakes before looking at builder internals. If the wrong target graph is produced, the toolchain never gets a chance to do the right thing.
Look here if:
- the Orchestrion tool fails during resolver or injector setup
- dependency resolution differs from local
gobehavior - patched upstream assumptions drift
Some failures originate inside the generated Orchestrion binary, not inside Starlark or the builders. This section points directly at that integration seam.
Look here if:
- stdlib weaving appears missing
- Datadog helper packages are unresolved
- synthetic test binaries lose instrumentation at final link
Most correctness bugs eventually reduce to compile/link inconsistency. This is the fastest entry point for the class of bugs that most directly threaten the global goal.
The current architecture is:
- a Bazel-native public Go test macro
- a bootstrap step that wires the workspace once
- a vendored
rules_gofork that integrates Orchestrion at the builder layer - a patched Orchestrion binary built from source
- a synthetic
testmainmanifest contract that keeps compile and final link in the same Datadog helper package universe
That combination is what makes the current Go CI Visibility path work under
Bazel while still behaving like a normal go_test target from the user's point
of view.
The final summary compresses the design down to the few moving pieces that are actually carrying the integration. If a future simplification preserves these properties, it is likely safe.