Task · CXO-0042

Adopt the remaining September wire additions: routing hint, passthrough metadata, models etag, compaction block

Description

Four additive shapes appear in the current capture and in none of the embedded baseline. A full-corpus scan on 2026-09-12 found 72 new findings and 0 breaking, so every item here is a gain, not a migration.

  1. Request header x-codex-routing-hint, present on 100 percent of records, value shaped model=<name>. It is the model the client asked codex-lb for at CONNECTION level, so it is fixed for the life of a websocket while response.create can name a different model per response. Four distinct values in the capture, each matching the response.create model exactly in every one of the 1,155 response.create events sampled. Its value is therefore not a new model dimension - it is the disagreement that matters, because a disagreement means codex-lb overrode the request (api_keys.enforced_model does exactly that). Emitting the hint as a per-turn attribute would duplicate an existing dimension at full cardinality and answer nothing.

  2. response.create input[].internal_chat_message_metadata_passthrough, an object on input items carrying turn_id (string, 5,146 occurrences), create_time (float unix seconds, 3,822 occurrences) and content_item_kinds (array of string, 510 occurrences). The kinds are a bounded vocabulary: 18 distinct values in the capture, including a literal unknown. They name what each injected context block IS - base instructions, memories, host skills, permissions, collaboration mode, apps, plugin usage and recommendations, multi-agent hints and role instructions, agents-md instructions, environment context, hook additional context, model-switch instructions, and user text. That is a direct measurement of prompt composition, which nothing currently reports.

  3. codex.response.metadata header x-models-etag, three distinct weak-etag values in the capture. It identifies the model-registry version the server answered from, so it dates a behaviour change to a registry roll rather than to anything local.

  4. A compaction object inside x-codex-turn-metadata, on both the record header and response.create client_metadata, with keys trigger, reason, implementation, phase, strategy - all bounded, all short. It co-occurs with request_kind=compaction, which the code already knows. Nine occurrences in the capture, so it is rare and cheap. It answers why a compaction happened, which the existing request_kind cannot.

Also stale and cheap to fix while here: internal/attr PlanType records Observed as pro and business, but prolite is now live and appears in codex.rate_limits plan_type. Observed is documentation and the corpus test expectation, not a filter, so nothing broke - but the list is now wrong.

Routing decisions for the four, and the standing policy they follow. Personal data reaching Grafana Cloud is NOT this exporters concern - the stack is the operators own and redacting on the way out buys nothing. Personal data reaching the public Git repository still is. The two guards that enforce the second boundary, TestNoArchivesAreTracked and TestSignature_CarriesNoConversationContent, and the redaction list in internal/profile/embedded.go that feeds the committed corpus.sig.json, all stay exactly as they are.

Acceptance Criteria

Definition of Done

Implementation Plan

  1. Freeze September wire Turn fields, attributes and metric names.
  2. Reduce routing, passthrough, metadata and compaction shapes.
  3. Route Identity fields to non-indexed sinks and verify bounded metrics.

Final Summary

Implemented September wire additions across reduction and sinks, including bounded routing and content metrics plus Identity-only fields. Frozen registry tests and the integrated just check gate passed.

View the source file on GitHub