Commit graph

1 commit

Author SHA1 Message Date
chopratejas
5b38cbf8a7 fix(transforms): F2.2 c2/3 — wire toin_read_only gate + extend policy_selected log
Wires the F2.2 ``toin_read_only`` field through the only consumer where
it's load-bearing (TOIN write surface) and extends the proxy's
structured ``policy_selected`` log event with all three F2.2 fields so
the bake dashboard has per-mode observability.

Wiring (gates only TOIN writes — compression itself still runs):
- headroom/transforms/smart_crusher.py: capture
  kwargs["compression_policy"] onto self._runtime_compression_policy
  at the start of apply(). _record_to_toin returns early when the
  policy says toin_read_only=True. Direct crush() / crush_array_json()
  callers don't go through apply() and keep pre-F2.2 write-enabled
  behaviour (no auth context for non-proxy callers).
- headroom/transforms/content_router.py: same one-liner in apply(),
  same gate in _record_to_toin. Mirrors the existing
  _runtime_target_ratio / _runtime_kompress_model pattern.

Telemetry:
- crates/headroom-proxy/src/proxy.rs: extend the policy_selected
  structured log with volatile_token_threshold, max_lossy_ratio, and
  toin_read_only. F2.2 bake telemetry can now observe all five fields
  on every request — load-bearing for the F2.2-followup tune decision
  since volatile_token_threshold and max_lossy_ratio are plumbed-but-
  unconsumed today and the log is the only signal that the values are
  flowing correctly.

Plumbed-but-unconsumed (deliberate; flagged in PR body):
- volatile_token_threshold — the volatile detector in cache_aligner.py
  is shape-based, not token-count-based; wiring it forces a detector
  refactor outside F2.2 scope.
- max_lossy_ratio — distinct from the caller-driven target_ratio kwarg
  in content_router.py; gating lossy paths on a policy cap is F2.2-
  followup once telemetry decides whether to gate or just observe.

Tests (tests/test_compression_policy_toin_gate.py):
- 7 tests covering the gate. SmartCrusher tests skip when the
  headroom._core Rust wheel isn't installed (matches the existing
  test_smart_crusher_rust_parity.py pattern); the 3 ContentRouter
  tests exercise the gate without the Rust dependency. CI's
  ci-precheck-python target runs scripts/build_rust_extension.sh
  before pytest so all 7 will run in the gate.

Refs: F2.1 (#400)
2026-05-06 14:37:33 -07:00