Introduce a typed compaction.ended observation and project it through the existing analytics compaction fact so the legacy reducer remains the only analytics emission path.
Add a side-by-side reducer test covering the subagent thread metadata join and verifying the observation path produces the same codex_compaction_event payload as the legacy fact.
Introduce a typed turn.steer observation for same-turn steering outcomes, including accepted and rejected requests with stable rejection reasons.
Project the observation through the existing analytics reducer state so the current codex_turn_steer_event payload and steer-count side effect remain matched. Add side-by-side conformance coverage against the legacy request/response and error-response sources.
Add FieldUse metadata so fields declare the exact projections intended to consume them. Detail level and data class remain guardrails enforced by FieldPolicy, while uses drives selection and prevents broad policies from accidentally collecting every safe-looking field.
Support struct-level default uses in the Observation derive, with field-level uses overriding the default for mixed events. AppUsed now declares analytics once at the event level instead of repeating it on every field.
Keep analytics conformance focused on final TrackEventRequest equality and move marker/policy filtering coverage into codex-observability tests. Update the design doc to describe the intent-versus-guardrail split.
Introduce FieldPolicy as the small shared primitive that decides whether a sink may inspect a field before serialization. The policy combines the field detail limit with the allowed data classes, keeping destination-specific rules outside the event definitions.
Add tests for the basic remote-safe shape and for the important safety invariant: denied content and secret-risk fields are filtered before serialization, proven with fields that panic if a visitor tries to serialize them.
Introduce a small codex-observability crate with typed observations, field-level policy metadata, and a derive macro that requires each exported field to declare detail level and data class. The derive crate stays narrow: it only generates visitor calls and leaves filtering, serialization, and destination-specific mapping to sinks and reducers.
Add the first canonical app.used observation and a private analytics observation reducer that projects it through the existing AnalyticsReducer. This gives us a side-by-side conformance test where the legacy analytics fact path and the observation path must emit identical TrackEventRequest JSON.
Document the target architecture and staged verification plan so later work can expand the taxonomy, field policy, E2E shadowing, rollout trace, and OTEL projection without widening this first checkpoint.