From a5b9b9051ecf7d0d86df9390e7db1841f8cbc9e3 Mon Sep 17 00:00:00 2001 From: Hofni Gartner Date: Wed, 22 Jul 2026 11:47:45 +0300 Subject: [PATCH 1/8] docs(adr): propose ADR 0071 harness snapshot for agent traces Record Level-1 harness-snapshot.json and root-span forge pointers as the run-time join contract; implementation follows in a separate issue. Signed-off-by: Hofni Gartner Co-authored-by: Cursor --- ...ge-pointer-correlation-for-agent-traces.md | 96 +++++++++++++++++++ .../infrastructure/distributed-tracing.md | 6 ++ 2 files changed, 102 insertions(+) create mode 100644 docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md diff --git a/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md b/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md new file mode 100644 index 0000000000..84b44399d8 --- /dev/null +++ b/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md @@ -0,0 +1,96 @@ +--- +title: "71. Harness snapshot and forge pointer correlation for agent traces" +status: Proposed +relates_to: + - operational-observability +topics: + - observability + - telemetry + - opentelemetry + - forge +--- + +# 71. Harness snapshot and forge pointer correlation for agent traces + +Date: 2026-07-22 + +## Status + +Proposed + +## Context + +[ADR 0050](0050-distributed-tracing-instrumentation.md) defines how fullsend +generates traces (OTel Go SDK; Level 1 = `run-telemetry.jsonl`; Level 2 = +OTLP). [Operational observability](../problems/operational-observability.md) +requires forge **pointers** (repo + SHA, change id, pipeline run) rather than +duplicating diffs, and a stable answer to: “what harness/config produced this +run?” + +After the OTel SDK migration, `run-summary.json` was removed; the sole Level 1 +telemetry file is `run-telemetry.jsonl`. Eval wrappers that `export` ambient CI +variables are the wrong layer: harness identity is a **run-time** concern of +`fullsend run`, and downstream tools must not scrape CI env as the source of +truth. + +Cross-project join field semantics (Provenance / MLflow tag names) live in the +shared join contract maintained with the certification report schema; this ADR +decides only what **fullsend** writes. + +## Decision + +### 1. Harness snapshot artifact (Level 1) + +Every `fullsend run` writes **`harness-snapshot.json`** into the run output +directory (next to `run-telemetry.jsonl`) at run start, after the root span +exists. + +Contents are pointers and a config fingerprint only (no diffs, prompts, or +skill bodies), including at least: + +- Harness identity: agent, role, slug, model, skills, harness path +- `harness_content_sha` (content hash of the resolved harness file) +- Forge/CI pointers when known: `forge_platform`, `repository_url`, + `ref_revision`, `ref_name`, `change_id`, `pipeline_run_id`, + `pipeline_run_url` +- Trace join: `trace_id`, `traceparent` + +Forge/CI fields are filled by fullsend when writing the snapshot (`FULLSEND_*` +overrides first, then standard CI env). Downstream consumers **read the JSON +file** (and/or later stores that ingest it), not ambient CI env. + +`OTEL_SDK_DISABLED=true` suppresses span export (`run-telemetry.jsonl` / OTLP) +but **does not** suppress `harness-snapshot.json` — it is the run-start config +contract, not span export. + +### 2. Root span attributes (Level 1 + Level 2) + +The same join keys are set on the root `run` span (`vcs.*`, `cicd.*`, +harness content SHA, forge platform) so OTLP backends receive them without +parsing the JSON. Local JSON remains the forensic / handoff contract. + +### 3. What we do not do + +- Do **not** treat eval scripts’ CI env exports as the harness-snapshot path. +- Do **not** embed PR diffs or prompt content in the snapshot. +- Do **not** redefine cross-project report field ownership in this ADR; link + the shared join contract from Related. + +## Consequences + +**Easier:** One decided artifact per run; operators and eval loggers can join +runs to forge/CI and to `run-telemetry.jsonl` via `trace_id`. + +**Harder:** Dispatched child runs must inherit forge context via env so the +child snapshot is complete; GitLab/Bitbucket coverage depends on CI vars or +`FULLSEND_*` overrides. Implementation is a follow-up issue after this ADR is +accepted. + +## Related + +- [ADR 0050](0050-distributed-tracing-instrumentation.md) +- [ADR 0005](0005-forge-abstraction-layer.md) +- Shared join contract: [provenance_forge_pointers.md](https://github.com/RHEcosystemAppEng/ABEvalFlow/blob/main/Docs/provenance_forge_pointers.md) + (land on ABEvalFlow `main` via the join-contract doc PR) +- [#2368](https://github.com/fullsend-ai/fullsend/issues/2368) +- [#294](https://github.com/fullsend-ai/fullsend/issues/294) diff --git a/docs/guides/infrastructure/distributed-tracing.md b/docs/guides/infrastructure/distributed-tracing.md index b299341039..2281211f3e 100644 --- a/docs/guides/infrastructure/distributed-tracing.md +++ b/docs/guides/infrastructure/distributed-tracing.md @@ -19,6 +19,12 @@ Level 3 adds prompt/completion content to spans. ## Environment variables +> **Planned:** `harness-snapshot.json` (run-start harness fingerprint and +> forge/CI pointers, mirrored on the root span) is decided in +> [ADR 0075](../../ADRs/0075-forge-pointer-correlation-for-agent-traces.md). +> Implementation follows ADR acceptance; until then only `run-telemetry.jsonl` +> is guaranteed on disk. + ### Endpoint configuration | Variable | Purpose | Notes | From 239482090fe3d8d3a3188722153647734bff361d Mon Sep 17 00:00:00 2001 From: Hofni Gartner Date: Thu, 23 Jul 2026 10:48:22 +0300 Subject: [PATCH 2/8] docs(adr): address ADR 0071 review feedback Accept status, add Options, single Decision, bullet Consequences, and Planned callout for harness-snapshot in the tracing guide (#5449). Signed-off-by: Hofni Gartner Co-authored-by: Cursor --- ...ge-pointer-correlation-for-agent-traces.md | 91 +++++++++---------- 1 file changed, 41 insertions(+), 50 deletions(-) diff --git a/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md b/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md index 84b44399d8..f451a2bc1b 100644 --- a/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md +++ b/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md @@ -1,6 +1,6 @@ --- title: "71. Harness snapshot and forge pointer correlation for agent traces" -status: Proposed +status: Accepted relates_to: - operational-observability topics: @@ -16,7 +16,7 @@ Date: 2026-07-22 ## Status -Proposed +Accepted ## Context @@ -28,69 +28,60 @@ duplicating diffs, and a stable answer to: “what harness/config produced this run?” After the OTel SDK migration, `run-summary.json` was removed; the sole Level 1 -telemetry file is `run-telemetry.jsonl`. Eval wrappers that `export` ambient CI -variables are the wrong layer: harness identity is a **run-time** concern of -`fullsend run`, and downstream tools must not scrape CI env as the source of -truth. +telemetry file today is `run-telemetry.jsonl`. Eval wrappers that `export` +ambient CI variables are the wrong layer: harness identity is a **run-time** +concern of `fullsend run`, and downstream tools must not scrape CI env as the +source of truth. Cross-project join field names live in a shared join contract; +this ADR decides only what **fullsend** writes. -Cross-project join field semantics (Provenance / MLflow tag names) live in the -shared join contract maintained with the certification report schema; this ADR -decides only what **fullsend** writes. +## Options -## Decision - -### 1. Harness snapshot artifact (Level 1) - -Every `fullsend run` writes **`harness-snapshot.json`** into the run output -directory (next to `run-telemetry.jsonl`) at run start, after the root span -exists. - -Contents are pointers and a config fingerprint only (no diffs, prompts, or -skill bodies), including at least: +**A. Root-span attributes only (no snapshot file).** Join keys exist in OTLP +backends, but offline/forensic consumers must parse spans, and keys disappear +when span export is disabled. -- Harness identity: agent, role, slug, model, skills, harness path -- `harness_content_sha` (content hash of the resolved harness file) -- Forge/CI pointers when known: `forge_platform`, `repository_url`, - `ref_revision`, `ref_name`, `change_id`, `pipeline_run_id`, - `pipeline_run_url` -- Trace join: `trace_id`, `traceparent` +**B. Embed a snapshot event in `run-telemetry.jsonl`.** One Level 1 file, but +couples the harness/config contract to telemetry format and exporter semantics. -Forge/CI fields are filled by fullsend when writing the snapshot (`FULLSEND_*` -overrides first, then standard CI env). Downstream consumers **read the JSON -file** (and/or later stores that ingest it), not ambient CI env. +**C. Eval-script / ambient CI env exports.** Easy to prototype; unstable across +local runs, child dispatches, and forges; encourages scraping rather than an +explicit artifact. -`OTEL_SDK_DISABLED=true` suppresses span export (`run-telemetry.jsonl` / OTLP) -but **does not** suppress `harness-snapshot.json` — it is the run-start config -contract, not span export. +**D. Dedicated `harness-snapshot.json` plus mirrored root-span attributes +(chosen).** Stable local run-start contract for offline consumers, plus +backend-friendly correlation for OTLP. -### 2. Root span attributes (Level 1 + Level 2) - -The same join keys are set on the root `run` span (`vcs.*`, `cicd.*`, -harness content SHA, forge platform) so OTLP backends receive them without -parsing the JSON. Local JSON remains the forensic / handoff contract. - -### 3. What we do not do +## Decision -- Do **not** treat eval scripts’ CI env exports as the harness-snapshot path. -- Do **not** embed PR diffs or prompt content in the snapshot. -- Do **not** redefine cross-project report field ownership in this ADR; link - the shared join contract from Related. +Every `fullsend run` records run-start join keys by writing +**`harness-snapshot.json`** next to `run-telemetry.jsonl` (after the root span +exists) **and** setting the same keys on the root `run` span (`vcs.*`, +`cicd.*`, harness content SHA, forge platform). The file holds pointers and a +config fingerprint only (harness identity, content hash, forge/CI pointers when +known, `trace_id` / `traceparent`) — no diffs, prompts, or skill bodies. +Forge/CI fields are filled at write time (`FULLSEND_*` overrides first, then +standard CI env). Consumers read the JSON (or stores that ingest it), not +ambient CI env. `OTEL_SDK_DISABLED=true` suppresses span export but does **not** +suppress the snapshot file. ## Consequences -**Easier:** One decided artifact per run; operators and eval loggers can join -runs to forge/CI and to `run-telemetry.jsonl` via `trace_id`. - -**Harder:** Dispatched child runs must inherit forge context via env so the -child snapshot is complete; GitLab/Bitbucket coverage depends on CI vars or -`FULLSEND_*` overrides. Implementation is a follow-up issue after this ADR is -accepted. +- Operators and downstream loggers can join a run to forge/CI and to + `run-telemetry.jsonl` via a single decided artifact and `trace_id`. +- OTLP backends receive join keys without parsing the JSON; local JSON remains + the forensic / handoff contract. +- Dispatched child runs must inherit forge context via env so child snapshots + are complete. +- GitLab/Bitbucket coverage depends on CI vars or `FULLSEND_*` overrides. +- Implementation is tracked separately ([#5449](https://github.com/fullsend-ai/fullsend/issues/5449)); + detailed field lists for cross-project consumers stay in the shared join + contract, not duplicated here. ## Related - [ADR 0050](0050-distributed-tracing-instrumentation.md) - [ADR 0005](0005-forge-abstraction-layer.md) - Shared join contract: [provenance_forge_pointers.md](https://github.com/RHEcosystemAppEng/ABEvalFlow/blob/main/Docs/provenance_forge_pointers.md) - (land on ABEvalFlow `main` via the join-contract doc PR) +- Implementation: [#5449](https://github.com/fullsend-ai/fullsend/issues/5449) - [#2368](https://github.com/fullsend-ai/fullsend/issues/2368) - [#294](https://github.com/fullsend-ai/fullsend/issues/294) From c39de5841a4ee561b0a0ef1c1a29c33c10bbcbdf Mon Sep 17 00:00:00 2001 From: Hofni Gartner Date: Thu, 23 Jul 2026 11:02:59 +0300 Subject: [PATCH 3/8] docs(adr): clarify ADR 0071 disabled-mode traces and architecture sync Cross-ref ADR 0005 in Context, omit trace_id when OTEL_SDK_DISABLED, and add the decided entry to docs/architecture.md Observability. Signed-off-by: Hofni Gartner Co-authored-by: Cursor --- ...ge-pointer-correlation-for-agent-traces.md | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md b/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md index f451a2bc1b..451b48dbab 100644 --- a/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md +++ b/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md @@ -25,7 +25,9 @@ generates traces (OTel Go SDK; Level 1 = `run-telemetry.jsonl`; Level 2 = OTLP). [Operational observability](../problems/operational-observability.md) requires forge **pointers** (repo + SHA, change id, pipeline run) rather than duplicating diffs, and a stable answer to: “what harness/config produced this -run?” +run?” Forge-neutral hosting concepts remain those in +[ADR 0005](0005-forge-abstraction-layer.md); this ADR only decides how join +pointers are recorded on a run. After the OTel SDK migration, `run-summary.json` was removed; the sole Level 1 telemetry file today is `run-telemetry.jsonl`. Eval wrappers that `export` @@ -54,22 +56,26 @@ backend-friendly correlation for OTLP. ## Decision Every `fullsend run` records run-start join keys by writing -**`harness-snapshot.json`** next to `run-telemetry.jsonl` (after the root span -exists) **and** setting the same keys on the root `run` span (`vcs.*`, -`cicd.*`, harness content SHA, forge platform). The file holds pointers and a -config fingerprint only (harness identity, content hash, forge/CI pointers when -known, `trace_id` / `traceparent`) — no diffs, prompts, or skill bodies. -Forge/CI fields are filled at write time (`FULLSEND_*` overrides first, then -standard CI env). Consumers read the JSON (or stores that ingest it), not -ambient CI env. `OTEL_SDK_DISABLED=true` suppresses span export but does **not** -suppress the snapshot file. +**`harness-snapshot.json`** next to `run-telemetry.jsonl` **and**, when tracing +is enabled, setting the same keys on the root `run` span (`vcs.*`, `cicd.*`, +harness content SHA, forge platform). The file holds pointers and a config +fingerprint only (harness identity, content hash, forge/CI pointers when known) +— no diffs, prompts, or skill bodies. Forge/CI fields are filled at write time +(`FULLSEND_*` overrides first, then standard CI env). Consumers read the JSON +(or stores that ingest it), not ambient CI env. + +When tracing is enabled, write the snapshot after the root span exists and +include `trace_id` / `traceparent` so the file joins to `run-telemetry.jsonl` +and OTLP. When `OTEL_SDK_DISABLED=true`, still write the snapshot (config/forge +contract, not span export) but **omit** `trace_id` / `traceparent` and skip +root-span attribute mirroring — there is no usable trace context. ## Consequences -- Operators and downstream loggers can join a run to forge/CI and to - `run-telemetry.jsonl` via a single decided artifact and `trace_id`. -- OTLP backends receive join keys without parsing the JSON; local JSON remains - the forensic / handoff contract. +- Operators and downstream loggers can join a run to forge/CI via a single + decided artifact; when tracing is on, `trace_id` joins to `run-telemetry.jsonl`. +- OTLP backends receive join keys without parsing the JSON when tracing is on; + local JSON remains the forensic / handoff contract. - Dispatched child runs must inherit forge context via env so child snapshots are complete. - GitLab/Bitbucket coverage depends on CI vars or `FULLSEND_*` overrides. From ccaace100aa5a2a2bdfee848051932a4eb977057 Mon Sep 17 00:00:00 2001 From: Hofni Gartner Date: Thu, 23 Jul 2026 11:03:16 +0300 Subject: [PATCH 4/8] docs(architecture): record ADR 0071 harness snapshot decision Keep Observability decided list in sync with the accepted ADR. Signed-off-by: Hofni Gartner Co-authored-by: Cursor --- docs/architecture.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/architecture.md b/docs/architecture.md index 3cc582c809..355ee26c0f 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -303,6 +303,7 @@ Observability is a cross-cutting concern that touches every other component. Eac - JSONL reasoning trace exposure: raw JSONL conversation transcripts are extracted from sandboxes and stored with owner-scoped access. Credential scanning acts as an invariant check on [ADR 0017](ADRs/0017-credential-isolation-for-sandboxed-agents.md)'s isolation model. Agents handling data from protected sources beyond the target repo can opt in to JSONL suppression via configuration ([ADR 0021](ADRs/0021-jsonl-reasoning-trace-exposure.md)). - Event-driven stage dispatch remains traceable end-to-end in the GitHub Actions UI by using synchronous `workflow_call` dispatch (see [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)). - Distributed tracing: framework-native OpenTelemetry instrumentation with zero-configuration baseline. Every run produces `run-telemetry.jsonl` locally; optional live OTLP export to any compatible backend. W3C trace context propagation links multi-agent pipelines into unified traces. OTEL GenAI semantic conventions enable LLM-aware backends ([ADR 0050](ADRs/0050-distributed-tracing-instrumentation.md)). +- Harness snapshot join keys: every run writes `harness-snapshot.json` (harness fingerprint + forge/CI pointers) and, when tracing is enabled, mirrors those keys on the root span so offline and OTLP consumers can correlate without scraping CI env ([ADR 0071](ADRs/0071-forge-pointer-correlation-for-agent-traces.md)). **Open questions:** From 5cad99a9a8b443d2de387656fce605127e1934fa Mon Sep 17 00:00:00 2001 From: Hofni Gartner Date: Thu, 23 Jul 2026 14:56:08 +0300 Subject: [PATCH 5/8] docs(architecture): mark ADR 0071 snapshot as pending implementation Align architecture.md with the Planned callout in the tracing guide so operators do not treat harness-snapshot.json as already shipped. Signed-off-by: Hofni Gartner Co-authored-by: Cursor --- docs/architecture.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture.md b/docs/architecture.md index 355ee26c0f..12f2a5d590 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -303,7 +303,7 @@ Observability is a cross-cutting concern that touches every other component. Eac - JSONL reasoning trace exposure: raw JSONL conversation transcripts are extracted from sandboxes and stored with owner-scoped access. Credential scanning acts as an invariant check on [ADR 0017](ADRs/0017-credential-isolation-for-sandboxed-agents.md)'s isolation model. Agents handling data from protected sources beyond the target repo can opt in to JSONL suppression via configuration ([ADR 0021](ADRs/0021-jsonl-reasoning-trace-exposure.md)). - Event-driven stage dispatch remains traceable end-to-end in the GitHub Actions UI by using synchronous `workflow_call` dispatch (see [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)). - Distributed tracing: framework-native OpenTelemetry instrumentation with zero-configuration baseline. Every run produces `run-telemetry.jsonl` locally; optional live OTLP export to any compatible backend. W3C trace context propagation links multi-agent pipelines into unified traces. OTEL GenAI semantic conventions enable LLM-aware backends ([ADR 0050](ADRs/0050-distributed-tracing-instrumentation.md)). -- Harness snapshot join keys: every run writes `harness-snapshot.json` (harness fingerprint + forge/CI pointers) and, when tracing is enabled, mirrors those keys on the root span so offline and OTLP consumers can correlate without scraping CI env ([ADR 0071](ADRs/0071-forge-pointer-correlation-for-agent-traces.md)). +- Decided (pending [#5449](https://github.com/fullsend-ai/fullsend/issues/5449)): harness snapshot join keys — every run will write `harness-snapshot.json` (harness fingerprint + forge/CI pointers) and, when tracing is enabled, mirror those keys on the root span so offline and OTLP consumers can correlate without scraping CI env ([ADR 0071](ADRs/0071-forge-pointer-correlation-for-agent-traces.md)). **Open questions:** From 696622812e2dd179d57666edd354d09243b568d9 Mon Sep 17 00:00:00 2001 From: Hofni Gartner Date: Wed, 29 Jul 2026 12:38:26 +0300 Subject: [PATCH 6/8] docs(adr): renumber harness snapshot ADR to 0077 Avoid collision with open ADR 0071 (auto-merge #2791). Drop closed shared join contract; scope forge coverage to GitHub/GitLab today; link the contract via ABEvalFlow #57 only. Signed-off-by: Hofni Gartner Co-authored-by: Cursor --- ...e-pointer-correlation-for-agent-traces.md} | 195 +++++++++--------- docs/architecture.md | 2 +- .../infrastructure/distributed-tracing.md | 4 +- 3 files changed, 105 insertions(+), 96 deletions(-) rename docs/ADRs/{0071-forge-pointer-correlation-for-agent-traces.md => 0075-forge-pointer-correlation-for-agent-traces.md} (64%) diff --git a/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md b/docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md similarity index 64% rename from docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md rename to docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md index 451b48dbab..2918e0d032 100644 --- a/docs/ADRs/0071-forge-pointer-correlation-for-agent-traces.md +++ b/docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md @@ -1,93 +1,102 @@ ---- -title: "71. Harness snapshot and forge pointer correlation for agent traces" -status: Accepted -relates_to: - - operational-observability -topics: - - observability - - telemetry - - opentelemetry - - forge ---- - -# 71. Harness snapshot and forge pointer correlation for agent traces - -Date: 2026-07-22 - -## Status - -Accepted - -## Context - -[ADR 0050](0050-distributed-tracing-instrumentation.md) defines how fullsend -generates traces (OTel Go SDK; Level 1 = `run-telemetry.jsonl`; Level 2 = -OTLP). [Operational observability](../problems/operational-observability.md) -requires forge **pointers** (repo + SHA, change id, pipeline run) rather than -duplicating diffs, and a stable answer to: “what harness/config produced this -run?” Forge-neutral hosting concepts remain those in -[ADR 0005](0005-forge-abstraction-layer.md); this ADR only decides how join -pointers are recorded on a run. - -After the OTel SDK migration, `run-summary.json` was removed; the sole Level 1 -telemetry file today is `run-telemetry.jsonl`. Eval wrappers that `export` -ambient CI variables are the wrong layer: harness identity is a **run-time** -concern of `fullsend run`, and downstream tools must not scrape CI env as the -source of truth. Cross-project join field names live in a shared join contract; -this ADR decides only what **fullsend** writes. - -## Options - -**A. Root-span attributes only (no snapshot file).** Join keys exist in OTLP -backends, but offline/forensic consumers must parse spans, and keys disappear -when span export is disabled. - -**B. Embed a snapshot event in `run-telemetry.jsonl`.** One Level 1 file, but -couples the harness/config contract to telemetry format and exporter semantics. - -**C. Eval-script / ambient CI env exports.** Easy to prototype; unstable across -local runs, child dispatches, and forges; encourages scraping rather than an -explicit artifact. - -**D. Dedicated `harness-snapshot.json` plus mirrored root-span attributes -(chosen).** Stable local run-start contract for offline consumers, plus -backend-friendly correlation for OTLP. - -## Decision - -Every `fullsend run` records run-start join keys by writing -**`harness-snapshot.json`** next to `run-telemetry.jsonl` **and**, when tracing -is enabled, setting the same keys on the root `run` span (`vcs.*`, `cicd.*`, -harness content SHA, forge platform). The file holds pointers and a config -fingerprint only (harness identity, content hash, forge/CI pointers when known) -— no diffs, prompts, or skill bodies. Forge/CI fields are filled at write time -(`FULLSEND_*` overrides first, then standard CI env). Consumers read the JSON -(or stores that ingest it), not ambient CI env. - -When tracing is enabled, write the snapshot after the root span exists and -include `trace_id` / `traceparent` so the file joins to `run-telemetry.jsonl` -and OTLP. When `OTEL_SDK_DISABLED=true`, still write the snapshot (config/forge -contract, not span export) but **omit** `trace_id` / `traceparent` and skip -root-span attribute mirroring — there is no usable trace context. - -## Consequences - -- Operators and downstream loggers can join a run to forge/CI via a single - decided artifact; when tracing is on, `trace_id` joins to `run-telemetry.jsonl`. -- OTLP backends receive join keys without parsing the JSON when tracing is on; - local JSON remains the forensic / handoff contract. -- Dispatched child runs must inherit forge context via env so child snapshots - are complete. -- GitLab/Bitbucket coverage depends on CI vars or `FULLSEND_*` overrides. -- Implementation is tracked separately ([#5449](https://github.com/fullsend-ai/fullsend/issues/5449)); - detailed field lists for cross-project consumers stay in the shared join - contract, not duplicated here. - -## Related - -- [ADR 0050](0050-distributed-tracing-instrumentation.md) -- [ADR 0005](0005-forge-abstraction-layer.md) -- Shared join contract: [provenance_forge_pointers.md](https://github.com/RHEcosystemAppEng/ABEvalFlow/blob/main/Docs/provenance_forge_pointers.md) -- Implementation: [#5449](https://github.com/fullsend-ai/fullsend/issues/5449) -- [#2368](https://github.com/fullsend-ai/fullsend/issues/2368) -- [#294](https://github.com/fullsend-ai/fullsend/issues/294) +--- +title: "75. Harness snapshot and forge pointer correlation for agent traces" +status: Accepted +relates_to: + - operational-observability +topics: + - observability + - telemetry + - opentelemetry + - forge +--- + +# 75. Harness snapshot and forge pointer correlation for agent traces + +Date: 2026-07-22 + +## Status + +Accepted + +## Context + +[ADR 0050](0050-distributed-tracing-instrumentation.md) defines how fullsend +generates traces (OTel Go SDK; Level 1 = `run-telemetry.jsonl`; Level 2 = +OTLP). [Operational observability](../problems/operational-observability.md) +requires forge **pointers** (repo + SHA, change id, pipeline run) rather than +duplicating diffs, and a stable answer to: “what harness/config produced this +run?” Forge-neutral hosting concepts remain those in +[ADR 0005](0005-forge-abstraction-layer.md); this ADR only decides how join +pointers are recorded on a run. + +After the OTel SDK migration, `run-summary.json` was removed; the sole Level 1 +telemetry file today is `run-telemetry.jsonl`. Eval wrappers that `export` +ambient CI variables are the wrong layer: harness identity is a **run-time** +concern of `fullsend run`, and downstream tools must not scrape CI env as the +source of truth. Cross-project join field names live in a shared join contract; +this ADR decides only what **fullsend** writes. Literal OTel attribute names +below are **illustrative** pending that contract +([ABEvalFlow #57](https://github.com/RHEcosystemAppEng/ABEvalFlow/pull/57)); +the follow-up implementation issue freezes the final strings. + +## Options + +**A. Root-span attributes only (no snapshot file).** Join keys exist in OTLP +backends, but offline/forensic consumers must parse spans, and keys disappear +when span export is disabled. + +**B. Embed a snapshot event in `run-telemetry.jsonl`.** One Level 1 file, but +couples the harness/config contract to telemetry format and exporter semantics. + +**C. Eval-script / ambient CI env exports.** Easy to prototype; unstable across +local runs, child dispatches, and forges; encourages scraping rather than an +explicit artifact. + +**D. Dedicated `harness-snapshot.json` plus mirrored root-span attributes +(chosen).** Stable local run-start contract for offline consumers, plus +backend-friendly correlation for OTLP. + +## Decision + +Every `fullsend run` records run-start join keys by writing +**`harness-snapshot.json`** next to `run-telemetry.jsonl` **and**, when tracing +is enabled, mirroring those keys on the root `run` span (illustrative OTel +namespaces today: `vcs.*`, `cicd.*`, plus harness content SHA and forge +platform — finalize literal names with the shared join contract / follow-up +issue). The file holds pointers and a config fingerprint only (harness +identity, content hash, forge/CI pointers when known) — no diffs, prompts, or +skill bodies. Forge/CI fields are filled at write time (`FULLSEND_*` overrides +first, then standard CI env). Consumers read the JSON (or stores that ingest +it), not ambient CI env. + +When tracing is enabled, write the snapshot after the root span exists and +include `trace_id` / `traceparent` so the file joins to `run-telemetry.jsonl` +and OTLP. When `OTEL_SDK_DISABLED=true`, still write the snapshot (config/forge +contract, not span export) but **omit** `trace_id` / `traceparent` and skip +root-span attribute mirroring — there is no usable trace context. + +## Consequences + +- Operators and downstream loggers can join a run to forge/CI via a single + decided artifact; when tracing is on, `trace_id` joins to `run-telemetry.jsonl`. +- OTLP backends receive join keys without parsing the JSON when tracing is on; + local JSON remains the forensic / handoff contract. +- Dispatched child runs must inherit forge context via env so child snapshots + are complete. +- GitHub/GitLab coverage depends on CI vars or `FULLSEND_*` overrides (forges + with clients today). Forgejo is a planned target per + [ADR 0005](0005-forge-abstraction-layer.md) and needs a forge client before + this join-key behavior applies there. +- Implementation will be tracked in a follow-up issue filed after this ADR + merges (per repo convention; premature tracker [#5449](https://github.com/fullsend-ai/fullsend/issues/5449) + was closed as not planned). Detailed field lists for cross-project consumers + stay in the shared join contract, not duplicated here. + +## Related + +- [ADR 0050](0050-distributed-tracing-instrumentation.md) +- [ADR 0005](0005-forge-abstraction-layer.md) +- Shared join contract (pending merge; not yet on `main`): + [ABEvalFlow #57](https://github.com/RHEcosystemAppEng/ABEvalFlow/pull/57) +- [#2368](https://github.com/fullsend-ai/fullsend/issues/2368) +- [#294](https://github.com/fullsend-ai/fullsend/issues/294) diff --git a/docs/architecture.md b/docs/architecture.md index 12f2a5d590..b7f3b800a8 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -303,7 +303,7 @@ Observability is a cross-cutting concern that touches every other component. Eac - JSONL reasoning trace exposure: raw JSONL conversation transcripts are extracted from sandboxes and stored with owner-scoped access. Credential scanning acts as an invariant check on [ADR 0017](ADRs/0017-credential-isolation-for-sandboxed-agents.md)'s isolation model. Agents handling data from protected sources beyond the target repo can opt in to JSONL suppression via configuration ([ADR 0021](ADRs/0021-jsonl-reasoning-trace-exposure.md)). - Event-driven stage dispatch remains traceable end-to-end in the GitHub Actions UI by using synchronous `workflow_call` dispatch (see [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)). - Distributed tracing: framework-native OpenTelemetry instrumentation with zero-configuration baseline. Every run produces `run-telemetry.jsonl` locally; optional live OTLP export to any compatible backend. W3C trace context propagation links multi-agent pipelines into unified traces. OTEL GenAI semantic conventions enable LLM-aware backends ([ADR 0050](ADRs/0050-distributed-tracing-instrumentation.md)). -- Decided (pending [#5449](https://github.com/fullsend-ai/fullsend/issues/5449)): harness snapshot join keys — every run will write `harness-snapshot.json` (harness fingerprint + forge/CI pointers) and, when tracing is enabled, mirror those keys on the root span so offline and OTLP consumers can correlate without scraping CI env ([ADR 0071](ADRs/0071-forge-pointer-correlation-for-agent-traces.md)). +- Decided (implementation follow-up after merge): harness snapshot join keys — every run will write `harness-snapshot.json` (harness fingerprint + forge/CI pointers) and, when tracing is enabled, mirror those keys on the root span so offline and OTLP consumers can correlate without scraping CI env ([ADR 0075](ADRs/0075-forge-pointer-correlation-for-agent-traces.md)). **Open questions:** diff --git a/docs/guides/infrastructure/distributed-tracing.md b/docs/guides/infrastructure/distributed-tracing.md index 2281211f3e..a41a58c2ce 100644 --- a/docs/guides/infrastructure/distributed-tracing.md +++ b/docs/guides/infrastructure/distributed-tracing.md @@ -22,8 +22,8 @@ Level 3 adds prompt/completion content to spans. > **Planned:** `harness-snapshot.json` (run-start harness fingerprint and > forge/CI pointers, mirrored on the root span) is decided in > [ADR 0075](../../ADRs/0075-forge-pointer-correlation-for-agent-traces.md). -> Implementation follows ADR acceptance; until then only `run-telemetry.jsonl` -> is guaranteed on disk. +> Implementation will be tracked in a follow-up issue after that ADR merges. +> Until that ships, only `run-telemetry.jsonl` is guaranteed on disk. ### Endpoint configuration From 36788ed4001c075472caebc9f49328d2d5ffc9dd Mon Sep 17 00:00:00 2001 From: Hofni Gartner Date: Sun, 2 Aug 2026 12:24:30 +0300 Subject: [PATCH 7/8] docs(adr): clear remaining #5524 review nits; renumber to ADR 0075 Drop closed #5449 as a live tracker cite, and ground the GitHub/GitLab vs Forgejo readiness wording in the in-tree clients instead of over-reading ADR 0005. Renumber to 0075 because 0077 is taken on main by mint-repos-scope-hardening. Signed-off-by: Hofni Gartner Co-authored-by: Cursor Signed-off-by: Hofni Gartner --- ...ge-pointer-correlation-for-agent-traces.md | 206 +++++++++--------- 1 file changed, 104 insertions(+), 102 deletions(-) diff --git a/docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md b/docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md index 2918e0d032..c757638722 100644 --- a/docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md +++ b/docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md @@ -1,102 +1,104 @@ ---- -title: "75. Harness snapshot and forge pointer correlation for agent traces" -status: Accepted -relates_to: - - operational-observability -topics: - - observability - - telemetry - - opentelemetry - - forge ---- - -# 75. Harness snapshot and forge pointer correlation for agent traces - -Date: 2026-07-22 - -## Status - -Accepted - -## Context - -[ADR 0050](0050-distributed-tracing-instrumentation.md) defines how fullsend -generates traces (OTel Go SDK; Level 1 = `run-telemetry.jsonl`; Level 2 = -OTLP). [Operational observability](../problems/operational-observability.md) -requires forge **pointers** (repo + SHA, change id, pipeline run) rather than -duplicating diffs, and a stable answer to: “what harness/config produced this -run?” Forge-neutral hosting concepts remain those in -[ADR 0005](0005-forge-abstraction-layer.md); this ADR only decides how join -pointers are recorded on a run. - -After the OTel SDK migration, `run-summary.json` was removed; the sole Level 1 -telemetry file today is `run-telemetry.jsonl`. Eval wrappers that `export` -ambient CI variables are the wrong layer: harness identity is a **run-time** -concern of `fullsend run`, and downstream tools must not scrape CI env as the -source of truth. Cross-project join field names live in a shared join contract; -this ADR decides only what **fullsend** writes. Literal OTel attribute names -below are **illustrative** pending that contract -([ABEvalFlow #57](https://github.com/RHEcosystemAppEng/ABEvalFlow/pull/57)); -the follow-up implementation issue freezes the final strings. - -## Options - -**A. Root-span attributes only (no snapshot file).** Join keys exist in OTLP -backends, but offline/forensic consumers must parse spans, and keys disappear -when span export is disabled. - -**B. Embed a snapshot event in `run-telemetry.jsonl`.** One Level 1 file, but -couples the harness/config contract to telemetry format and exporter semantics. - -**C. Eval-script / ambient CI env exports.** Easy to prototype; unstable across -local runs, child dispatches, and forges; encourages scraping rather than an -explicit artifact. - -**D. Dedicated `harness-snapshot.json` plus mirrored root-span attributes -(chosen).** Stable local run-start contract for offline consumers, plus -backend-friendly correlation for OTLP. - -## Decision - -Every `fullsend run` records run-start join keys by writing -**`harness-snapshot.json`** next to `run-telemetry.jsonl` **and**, when tracing -is enabled, mirroring those keys on the root `run` span (illustrative OTel -namespaces today: `vcs.*`, `cicd.*`, plus harness content SHA and forge -platform — finalize literal names with the shared join contract / follow-up -issue). The file holds pointers and a config fingerprint only (harness -identity, content hash, forge/CI pointers when known) — no diffs, prompts, or -skill bodies. Forge/CI fields are filled at write time (`FULLSEND_*` overrides -first, then standard CI env). Consumers read the JSON (or stores that ingest -it), not ambient CI env. - -When tracing is enabled, write the snapshot after the root span exists and -include `trace_id` / `traceparent` so the file joins to `run-telemetry.jsonl` -and OTLP. When `OTEL_SDK_DISABLED=true`, still write the snapshot (config/forge -contract, not span export) but **omit** `trace_id` / `traceparent` and skip -root-span attribute mirroring — there is no usable trace context. - -## Consequences - -- Operators and downstream loggers can join a run to forge/CI via a single - decided artifact; when tracing is on, `trace_id` joins to `run-telemetry.jsonl`. -- OTLP backends receive join keys without parsing the JSON when tracing is on; - local JSON remains the forensic / handoff contract. -- Dispatched child runs must inherit forge context via env so child snapshots - are complete. -- GitHub/GitLab coverage depends on CI vars or `FULLSEND_*` overrides (forges - with clients today). Forgejo is a planned target per - [ADR 0005](0005-forge-abstraction-layer.md) and needs a forge client before - this join-key behavior applies there. -- Implementation will be tracked in a follow-up issue filed after this ADR - merges (per repo convention; premature tracker [#5449](https://github.com/fullsend-ai/fullsend/issues/5449) - was closed as not planned). Detailed field lists for cross-project consumers - stay in the shared join contract, not duplicated here. - -## Related - -- [ADR 0050](0050-distributed-tracing-instrumentation.md) -- [ADR 0005](0005-forge-abstraction-layer.md) -- Shared join contract (pending merge; not yet on `main`): - [ABEvalFlow #57](https://github.com/RHEcosystemAppEng/ABEvalFlow/pull/57) -- [#2368](https://github.com/fullsend-ai/fullsend/issues/2368) -- [#294](https://github.com/fullsend-ai/fullsend/issues/294) +--- +title: "75. Harness snapshot and forge pointer correlation for agent traces" +status: Accepted +relates_to: + - operational-observability +topics: + - observability + - telemetry + - opentelemetry + - forge +--- + +# 75. Harness snapshot and forge pointer correlation for agent traces + +Date: 2026-07-22 + +## Status + +Accepted + +## Context + +[ADR 0050](0050-distributed-tracing-instrumentation.md) defines how fullsend +generates traces (OTel Go SDK; Level 1 = `run-telemetry.jsonl`; Level 2 = +OTLP). [Operational observability](../problems/operational-observability.md) +requires forge **pointers** (repo + SHA, change id, pipeline run) rather than +duplicating diffs, and a stable answer to: “what harness/config produced this +run?” Forge-neutral hosting concepts remain those in +[ADR 0005](0005-forge-abstraction-layer.md); this ADR only decides how join +pointers are recorded on a run. + +After the OTel SDK migration, `run-summary.json` was removed; the sole Level 1 +telemetry file today is `run-telemetry.jsonl`. Eval wrappers that `export` +ambient CI variables are the wrong layer: harness identity is a **run-time** +concern of `fullsend run`, and downstream tools must not scrape CI env as the +source of truth. Cross-project join field names live in a shared join contract; +this ADR decides only what **fullsend** writes. Literal OTel attribute names +below are **illustrative** pending that contract +([ABEvalFlow #57](https://github.com/RHEcosystemAppEng/ABEvalFlow/pull/57)); +the follow-up implementation issue freezes the final strings. + +## Options + +**A. Root-span attributes only (no snapshot file).** Join keys exist in OTLP +backends, but offline/forensic consumers must parse spans, and keys disappear +when span export is disabled. + +**B. Embed a snapshot event in `run-telemetry.jsonl`.** One Level 1 file, but +couples the harness/config contract to telemetry format and exporter semantics. + +**C. Eval-script / ambient CI env exports.** Easy to prototype; unstable across +local runs, child dispatches, and forges; encourages scraping rather than an +explicit artifact. + +**D. Dedicated `harness-snapshot.json` plus mirrored root-span attributes +(chosen).** Stable local run-start contract for offline consumers, plus +backend-friendly correlation for OTLP. + +## Decision + +Every `fullsend run` records run-start join keys by writing +**`harness-snapshot.json`** next to `run-telemetry.jsonl` **and**, when tracing +is enabled, mirroring those keys on the root `run` span (illustrative OTel +namespaces today: `vcs.*`, `cicd.*`, plus harness content SHA and forge +platform — finalize literal names with the shared join contract / follow-up +issue). The file holds pointers and a config fingerprint only (harness +identity, content hash, forge/CI pointers when known) — no diffs, prompts, or +skill bodies. Forge/CI fields are filled at write time (`FULLSEND_*` overrides +first, then standard CI env). Consumers read the JSON (or stores that ingest +it), not ambient CI env. + +When tracing is enabled, write the snapshot after the root span exists and +include `trace_id` / `traceparent` so the file joins to `run-telemetry.jsonl` +and OTLP. When `OTEL_SDK_DISABLED=true`, still write the snapshot (config/forge +contract, not span export) but **omit** `trace_id` / `traceparent` and skip +root-span attribute mirroring — there is no usable trace context. + +## Consequences + +- Operators and downstream loggers can join a run to forge/CI via a single + decided artifact; when tracing is on, `trace_id` joins to `run-telemetry.jsonl`. +- OTLP backends receive join keys without parsing the JSON when tracing is on; + local JSON remains the forensic / handoff contract. +- Dispatched child runs must inherit forge context via env so child snapshots + are complete. +- GitHub/GitLab coverage depends on CI vars or `FULLSEND_*` overrides — both + have in-tree `forge.Client` implementations today (`internal/forge/github`, + `internal/forge/gitlab`). Forgejo remains a planned target under + [ADR 0005](0005-forge-abstraction-layer.md) and needs a forge client before + this join-key behavior applies there (ADR 0005 still groups GitLab with + Forgejo as future work; the GitLab client landed later). +- Implementation will be tracked in a **new** follow-up issue filed after this + ADR merges (per repo convention). Do not cite closed #5449. Detailed field + lists for cross-project consumers stay in the shared join contract, not + duplicated here. + +## Related + +- [ADR 0050](0050-distributed-tracing-instrumentation.md) +- [ADR 0005](0005-forge-abstraction-layer.md) +- Shared join contract (pending merge; not yet on `main`): + [ABEvalFlow #57](https://github.com/RHEcosystemAppEng/ABEvalFlow/pull/57) +- [#2368](https://github.com/fullsend-ai/fullsend/issues/2368) +- [#294](https://github.com/fullsend-ai/fullsend/issues/294) From e9e6ca5fc6ea9ff7e6b38823b2aef8b2dbe5081a Mon Sep 17 00:00:00 2001 From: Hofni Gartner Date: Wed, 19 Aug 2026 16:20:02 +0300 Subject: [PATCH 8/8] fix(adr): renumber to ADR 0090, fix ADR 0005 citation - 0075 is taken by local-path-profiles-providers on main; renumber our harness snapshot ADR to 0090. - Update distributed-tracing.md and architecture.md cross-links. - Clarify ADR 0005 citation: it defines forge targets but predates the GitLab client landing. In-tree code (internal/forge/gitlab/) is the authoritative source for current support status. Signed-off-by: Hofni Gartner Co-authored-by: Cursor --- ...-forge-pointer-correlation-for-agent-traces.md} | 14 ++++++++------ docs/architecture.md | 2 +- docs/guides/infrastructure/distributed-tracing.md | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) rename docs/ADRs/{0075-forge-pointer-correlation-for-agent-traces.md => 0090-forge-pointer-correlation-for-agent-traces.md} (86%) diff --git a/docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md b/docs/ADRs/0090-forge-pointer-correlation-for-agent-traces.md similarity index 86% rename from docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md rename to docs/ADRs/0090-forge-pointer-correlation-for-agent-traces.md index c757638722..11c26bdbb9 100644 --- a/docs/ADRs/0075-forge-pointer-correlation-for-agent-traces.md +++ b/docs/ADRs/0090-forge-pointer-correlation-for-agent-traces.md @@ -1,5 +1,5 @@ --- -title: "75. Harness snapshot and forge pointer correlation for agent traces" +title: "90. Harness snapshot and forge pointer correlation for agent traces" status: Accepted relates_to: - operational-observability @@ -84,11 +84,13 @@ root-span attribute mirroring — there is no usable trace context. - Dispatched child runs must inherit forge context via env so child snapshots are complete. - GitHub/GitLab coverage depends on CI vars or `FULLSEND_*` overrides — both - have in-tree `forge.Client` implementations today (`internal/forge/github`, - `internal/forge/gitlab`). Forgejo remains a planned target under - [ADR 0005](0005-forge-abstraction-layer.md) and needs a forge client before - this join-key behavior applies there (ADR 0005 still groups GitLab with - Forgejo as future work; the GitLab client landed later). + have in-tree `forge.Client` implementations today (see `internal/forge/github/` + and `internal/forge/gitlab/`). Forgejo is defined as a future forge target in + [ADR 0005](0005-forge-abstraction-layer.md) and needs a `forge.Client` + implementation before this join-key behavior applies there. + (Note: ADR 0005 predates the GitLab client landing and still groups GitLab + with Forgejo as unimplemented; the in-tree code is the authoritative source + for current forge support status.) - Implementation will be tracked in a **new** follow-up issue filed after this ADR merges (per repo convention). Do not cite closed #5449. Detailed field lists for cross-project consumers stay in the shared join contract, not diff --git a/docs/architecture.md b/docs/architecture.md index b7f3b800a8..29398d7d1c 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -303,7 +303,7 @@ Observability is a cross-cutting concern that touches every other component. Eac - JSONL reasoning trace exposure: raw JSONL conversation transcripts are extracted from sandboxes and stored with owner-scoped access. Credential scanning acts as an invariant check on [ADR 0017](ADRs/0017-credential-isolation-for-sandboxed-agents.md)'s isolation model. Agents handling data from protected sources beyond the target repo can opt in to JSONL suppression via configuration ([ADR 0021](ADRs/0021-jsonl-reasoning-trace-exposure.md)). - Event-driven stage dispatch remains traceable end-to-end in the GitHub Actions UI by using synchronous `workflow_call` dispatch (see [ADR 0041](ADRs/0041-synchronous-workflow-call-event-dispatch.md)). - Distributed tracing: framework-native OpenTelemetry instrumentation with zero-configuration baseline. Every run produces `run-telemetry.jsonl` locally; optional live OTLP export to any compatible backend. W3C trace context propagation links multi-agent pipelines into unified traces. OTEL GenAI semantic conventions enable LLM-aware backends ([ADR 0050](ADRs/0050-distributed-tracing-instrumentation.md)). -- Decided (implementation follow-up after merge): harness snapshot join keys — every run will write `harness-snapshot.json` (harness fingerprint + forge/CI pointers) and, when tracing is enabled, mirror those keys on the root span so offline and OTLP consumers can correlate without scraping CI env ([ADR 0075](ADRs/0075-forge-pointer-correlation-for-agent-traces.md)). +- Decided (implementation follow-up after merge): harness snapshot join keys — every run will write `harness-snapshot.json` (harness fingerprint + forge/CI pointers) and, when tracing is enabled, mirror those keys on the root span so offline and OTLP consumers can correlate without scraping CI env ([ADR 0090](ADRs/0090-forge-pointer-correlation-for-agent-traces.md)). **Open questions:** diff --git a/docs/guides/infrastructure/distributed-tracing.md b/docs/guides/infrastructure/distributed-tracing.md index a41a58c2ce..dd35d09862 100644 --- a/docs/guides/infrastructure/distributed-tracing.md +++ b/docs/guides/infrastructure/distributed-tracing.md @@ -21,7 +21,7 @@ Level 3 adds prompt/completion content to spans. > **Planned:** `harness-snapshot.json` (run-start harness fingerprint and > forge/CI pointers, mirrored on the root span) is decided in -> [ADR 0075](../../ADRs/0075-forge-pointer-correlation-for-agent-traces.md). +> [ADR 0090](../../ADRs/0090-forge-pointer-correlation-for-agent-traces.md). > Implementation will be tracked in a follow-up issue after that ADR merges. > Until that ships, only `run-telemetry.jsonl` is guaranteed on disk.