Skip to content

Collector: keep the Codex launch tag and call_id behind shape guards for the #381 join (U7) - #491

Merged
seathatflowsinourveins merged 7 commits into
mainfrom
claude/pra-u7-collector-join-2d-20260929
Sep 29, 2026
Merged

seathatflowsinourveins merged 7 commits into
mainfrom
claude/pra-u7-collector-join-2d-20260929

Conversation

@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes, in one or two sentences: the Collector's privacy allowlist deleted the two identities the PR-H: E2E preregistration for the token-save-practice stack (frozen tasks, metrics, gate, procedure) #381 token-practice proof needs to join a Codex launch to its Loki records, the launch tag (Codex's otel.environment, exported as the resource attribute env) and the per-call call_id; they are now kept, each behind an RE2 shape guard (^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$), with tests (one that runs the committed pipeline on the pinned otelcol 0.161.0 and Loki 3.7.8) and README limitations. It changes no host state.
  • Base commit: b1be50c8
  • Lane: lane:foundation
  • Owned paths touched: observability/collector/collector.yaml, observability/collector/README.md, tests/test_observability_run_correlation.py, tests/test_observability_tool_names.py, manifests/evidence.json (re-registered on main's copy).

SOTA sources

  • openai/codex rust-v0.157.1 (36650394): codex-rs/otel/src/provider.rs L53 and L381 (otel.environment becomes the logs resource attribute env), codex-rs/otel/src/tool_result.rs L61 and codex-rs/otel/src/events/session_telemetry.rs L1112 and L1121 (call_id on codex.tool_result and codex.tool_decision), codex-rs/core/src/tools/registry.rs L598-L634 and L667-L682 and codex-rs/core/src/tools/code_mode/mod.rs L363-L378 (which calls end without a result record, listed in the README limits).
  • open-telemetry/opentelemetry-collector-contrib v0.161.0: pkg/ottl/ottlfuncs (keep_keys, delete_key, IsMatch), transformprocessor error_mode.
  • grafana/loki v3.7.x: OTLP ingestion keeps non-index attributes as structured metadata (the native test asserts the series stay {service_name} only).
  • The requirement comes from PR-H: E2E preregistration for the token-save-practice stack (frozen tasks, metrics, gate, procedure) #381's RUNBOOK ("Loki queries and reconciliation") and the collector README's dated note that Codex env and call_id reconciliation was outstanding.

Evidence-class table

Claim Evidence class Command / receipt
The committed config keeps env (resource) and call_id (log) only when they match the guard, and drops malformed values (129 characters and spaces in the committed test; a trailing newline, unicode and a leading dash in the GPT-6 reviewer's own probes, not in the repository) local_integration (synthetic OTLP through the real pinned binaries) NativeRunCorrelationTests.test_codex_launch_tag_and_call_id_reach_loki, 18 tests, 0 skips, PyYAML interpreter
The tests fail first at the base collector local_integration commit e4552907: FAILED (failures=5); commit 02bbadb4: the SDK-receipt subtest reads 0 where 1 is expected
Removing either guard fails the tests local_integration two mutants, each FAILED (failures=2)
An SDK receipt does not export call_id (found by the cross-family review, fixed here) local_integration native test, third resource codex-sdk-receipt
otelcol-contrib validate accepts the config native_proven (upstream command) exit 0, pinned 0.161.0
A real Codex launch tagged with -c otel.environment=... reaches Loki with its tag and call ids NOT established here needs the host collector patch and the capability-phase proof (Amendment 4 of #381)
The host collector equals the repository's statements NOT established here the README gives a diff-then-patch procedure; no host was touched

Local commands run

$ /usr/bin/python3 -B -m unittest tests.test_observability_run_correlation tests.test_observability_tool_names   (PyYAML; native classes)
Ran 18 tests in 69.270s  OK   (0 skipped)
$ otelcol-contrib validate --config=observability/collector/collector.yaml   (ECOSYSTEM_OBSERVABILITY_DATA=<temp>)
exit 0
$ python3 scripts/validate.py
{"components": 69, "hashed_files": 7994, "profiles": 4, "receipts": 168, "status": "passed"}
$ git diff --check origin/main...HEAD
exit 0

Reviews: an independent Claude evidence-reviewer (4 low README findings, fixed), a Claude stack-verifier (all acceptance commands re-run), and a GPT-6 read-only cross-family review (needs_changes, one medium: SDK receipts gained call_id; fixed in b2e592da and covered by a native test). Findings about the M14 denominator wording, the amendment order and the proof procedure belong to the #381 Amendment 4 and are not in this PR.

Decision record

None new: the choices and limits are in observability/collector/README.md (limitations, host procedure). #381 Amendment 4 will cite this PR.

Host evidence

Not applicable: no file under evidence/hosts/ changes.

Checklist

  • New/changed GitHub Actions are pinned to a full commit SHA with a version comment (no floating tags). (none changed)
  • New/changed workflows declare top-level permissions: contents: read. (none changed)
  • No secrets are printed, logged or committed; no new required secret was added without a documented owner.
  • No new paid hosting, subscription or billing surface was introduced.
  • Peer-owned untracked files and worktrees were preserved (not deleted, moved or overwritten).

🤖 Generated with Claude Code

Scout and others added 7 commits September 29, 2026 00:34
Add the failing-first checks for the Codex half of the collector join.

- A static check, which needs no PyYAML, requires three things: the
  resource allowlist keeps env behind a shape guard, the log allowlist
  keeps call_id right after tool_use_id, and neither key appears in the
  metric statements.
- The tool-names check requires a delete_key shape guard for call_id.
- A native test sends codex_exec records through the committed
  processors on otelcol-contrib 0.161.0 into Loki 3.7.8 and joins them
  by env and call_id. A malformed tag, a malformed id and a 129-character
  id must be dropped, a 128-character id kept, and host.name stays
  dropped.

The commit also adds env to the dashboard ID_LABELS guard (a review
finding); that check passes at this commit.

Sources: openai/codex rust-v0.157.1 (36650394)
codex-rs/otel/src/provider.rs:53,381, codex-rs/otel/src/tool_result.rs:61,
codex-rs/otel/src/events/session_telemetry.rs:1112,1121,
codex-rs/core/src/tools/code_mode/delegate.rs:323; the
opentelemetry-collector-contrib v0.161.0 pkg/ottl/ottlfuncs/README.md.

At this commit the new checks fail: Ran 18 tests, FAILED (failures=5),
0 skipped.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Codex exports the per-launch tag (-c otel.environment=<tag>) as the logs
resource attribute env, and it pairs codex.tool_decision with
codex.tool_result by call_id. transform/privacy dropped both, so Codex
records could be joined only by conversation.id.

- transform/privacy resource context: delete env unless it matches
  ^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$, then keep it.
- transform/tool_names final group: the same shape guard for call_id.
- transform/privacy log allowlist: keep call_id right after
  tool_use_id. This leaves the SDK-receipt deny list and the allowlist
  tail unchanged.
- The metric resource allowlist is unchanged, so env and call_id stay
  off metrics.

Sources: openai/codex rust-v0.157.1 (36650394)
codex-rs/otel/src/provider.rs:53,381, codex-rs/otel/src/tool_result.rs:61,
codex-rs/otel/src/events/session_telemetry.rs:1112,1121; the
opentelemetry-collector-contrib v0.161.0 pkg/ottl/ottlfuncs/README.md
(delete_key, IsMatch, keep_keys).

otelcol-contrib 0.161.0 validate exits 0. A negative control with an
unknown OTTL function exits 1. The five collector-reading test modules
pass: Ran 127 tests, OK, 0 skipped.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This documents the collector change and corrects the host procedure in
observability/collector/README.md.

- Add a dated section, "Codex launch tag and call id — 2026-09-29". It
  names the native sources, the four touched statements, the guard
  pattern, the LogQL joins and the validation.
- The section's limits cover four points:
  - host application is still pending;
  - no real launch has been observed;
  - a call that is hook-blocked, whose hook-rewritten input fails, that
    has a nested code-mode payload error or that is cancelled before
    dispatch logs neither codex.tool_result nor codex.tool_decision, so
    Loki counts can be lower than rollout function calls;
  - env and call_id appear in the local Grafana log details.
- Replace the host note that installed the repository file verbatim.
  The new procedure diffs the host's statements, patches only the
  touched ones, validates, restarts outside measured windows and reads
  back the order. It no longer implies that the host equals the
  repository.
- Keep the dated 2026-09-27 clarification, and point its outstanding
  Codex item to the new section.

Sources: openai/codex rust-v0.157.1 (36650394)
codex-rs/core/src/tools/registry.rs:598-612,619-634,667-682,
codex-rs/core/src/tools/code_mode/mod.rs:363-379,
codex-rs/core/src/tools/code_mode/delegate.rs:323,335-337,
codex-rs/core/src/tools/orchestrator.rs:196-198,
codex-rs/otel/src/metrics/client.rs:46,345; Loki v3.7.x
send-data/otel (non-index resource attributes are stored on each entry).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The PyYAML-free test_codex_launch_tag_and_call_id_are_kept checked only
the env guard. The call_id guard was covered only by PyYAML-gated tests,
so the collector README's always-on claim overstated coverage (verifier
finding on 76c97846).

The test now requires the exact call_id guard statement in the last
transform/tool_names log group, and requires that group to have no
conditions. Transform processor conditions are ORed where clauses that
gate their whole statement group (opentelemetry-collector-contrib
v0.161.0, processor/transformprocessor/README.md:164), so a guard in a
conditioned group would leave call_id on other events unchecked. Call ids
come from openai/codex rust-v0.157.1 codex-rs/otel/src/tool_result.rs:61
and codex-rs/otel/src/events/session_telemetry.rs:1112,1121.

Scratch mutation controls with system python3 (no PyYAML): removing the
guard, conditioning its group or widening its pattern to {0,255} each
fails the extended test and passes the previous one. The README now names
both guards and where each must sit.

Review findings F1, F3, F6, F7, F9 and F10 concern the token-adoption
E2E amendment, outside this PR's files; the u7 handoff records them as
Amendment 4 inputs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The cross-family review of this branch sent an ecosystem.sdk_receipt record that
carries a call_id through the committed pipeline (native file receiver). The shared
privacy allowlist now admits call_id for Codex records, and the SDK-receipt deny
list did not remove it, so the receipt exported it. The native Loki test gains a
third resource shaped like the receipts pipeline (codex-sdk-receipt) with a
call_id; it must reach Loki and the event file without one.

At the base collector it fails for the right reason: "SDK receipts without a call
id" reads 0 where 1 is expected.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The shared privacy allowlist admits call_id for Codex records. An SDK receipt file
is ingested through the same allowlist, and its deny list (the names a receipt
cannot supply) did not include call_id, so a receipt carrying one exported it.
Found by the cross-family review of this branch by sending a receipt with a
call_id through the native file-receiver pipeline.

The deny regex gains call_id. The structural test now states the relation: the
deny list is the allowlist tail from tool_family plus the Codex call id. The
native test from the previous commit passes: the receipt reaches Loki and the event
file without a call id, the other receipt fields are unchanged, and Codex records
keep theirs. The README sentence about receipts names call_id.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Re-registers the four collector files this branch changes (collector.yaml, its
README and the two observability test modules) on top of main's manifest, as the
hot-file protocol in docs/lanes.md asks. scripts/validate.py passes.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Sep 29, 2026
@seathatflowsinourveins
seathatflowsinourveins enabled auto-merge (squash) September 29, 2026 04:38
@seathatflowsinourveins
seathatflowsinourveins merged commit f88e688 into main Sep 29, 2026
25 checks passed
@seathatflowsinourveins
seathatflowsinourveins deleted the claude/pra-u7-collector-join-2d-20260929 branch September 29, 2026 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant