Merge pull request 'fix(pipeline): back-stamp served surface onto TurnEvent — close T13 telemetry-consistency red' (#101) from fix/telemetry-serve-boundary into main
This commit is contained in:
commit
9a428d8466
3 changed files with 84 additions and 1 deletions
|
|
@ -1195,6 +1195,53 @@ class ChatRuntime:
|
||||||
cand, source_turn_trace=trace_hash
|
cand, source_turn_trace=trace_hash
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def finalize_turn_surface(
|
||||||
|
self,
|
||||||
|
surface: str,
|
||||||
|
articulation_surface: str | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Back-stamp the pipeline's final *served* surface onto the turn.
|
||||||
|
|
||||||
|
Weekly-audit T13 (2026-07-22): ``ChatRuntime.chat`` seals a
|
||||||
|
``TurnEvent`` with the runtime-owned surface, but
|
||||||
|
``CognitiveTurnPipeline`` applies the Shadow-Coherence /
|
||||||
|
logos-morph surface authority AFTER ``chat`` returns. The
|
||||||
|
telemetry record therefore captured a surface the user never
|
||||||
|
saw — ``TurnEvent.surface != pipeline.run().surface`` — breaking
|
||||||
|
the ``warmed_session_consistency`` telemetry-consistency invariant
|
||||||
|
and audit/replay trust (Absolute Provenance).
|
||||||
|
|
||||||
|
The pipeline owns the final surface decision, so — exactly like
|
||||||
|
``finalize_turn_trace_hash`` back-stamps the pipeline-owned
|
||||||
|
``trace_hash`` — it back-stamps the resolved surface here after
|
||||||
|
``resolve_surface`` + logos-morph. Mirrors that method's
|
||||||
|
contract: operates on the most recent ``TurnEvent`` (main or
|
||||||
|
refusal-stub path), no-ops when unchanged or when no turn exists.
|
||||||
|
|
||||||
|
NOTE: the opt-in external telemetry sink (``attach_telemetry_sink``)
|
||||||
|
still receives the pre-override event, the same provisional-then-
|
||||||
|
back-stamped limitation ``finalize_turn_trace_hash`` carries today
|
||||||
|
(default sink is ``None`` → no-op). Deferring the single sink
|
||||||
|
emission to the pipeline serve boundary — which would repair both
|
||||||
|
surface and ``trace_hash`` in the durable stream — is tracked as a
|
||||||
|
follow-up (audit ledger R7), not bolted onto this red-fix.
|
||||||
|
"""
|
||||||
|
if not self.turn_log:
|
||||||
|
return
|
||||||
|
from dataclasses import replace
|
||||||
|
|
||||||
|
last_event = self.turn_log[-1]
|
||||||
|
updates: dict[str, str] = {}
|
||||||
|
if surface != last_event.surface:
|
||||||
|
updates["surface"] = surface
|
||||||
|
if (
|
||||||
|
articulation_surface is not None
|
||||||
|
and articulation_surface != last_event.articulation_surface
|
||||||
|
):
|
||||||
|
updates["articulation_surface"] = articulation_surface
|
||||||
|
if updates:
|
||||||
|
self.turn_log[-1] = replace(last_event, **updates)
|
||||||
|
|
||||||
def first_admitted_recognizer(self):
|
def first_admitted_recognizer(self):
|
||||||
if not self.config.recognition_grounded_graph:
|
if not self.config.recognition_grounded_graph:
|
||||||
return None
|
return None
|
||||||
|
|
|
||||||
|
|
@ -808,6 +808,16 @@ class CognitiveTurnPipeline:
|
||||||
# ``source_turn_trace``. See runtime.finalize_turn_trace_hash.
|
# ``source_turn_trace``. See runtime.finalize_turn_trace_hash.
|
||||||
self.runtime.finalize_turn_trace_hash(trace_hash)
|
self.runtime.finalize_turn_trace_hash(trace_hash)
|
||||||
|
|
||||||
|
# Weekly-audit T13 (2026-07-22) — back-stamp the pipeline's final
|
||||||
|
# *served* surface onto the same TurnEvent, sibling to the
|
||||||
|
# trace_hash back-stamp above. ``resolve_surface`` + the logos-morph
|
||||||
|
# authority (above) can override the runtime-owned surface AFTER
|
||||||
|
# ``runtime.chat`` sealed the TurnEvent, so without this the
|
||||||
|
# telemetry record disagrees with the served bytes
|
||||||
|
# (warmed_session_consistency telemetry_consistency_rate < 1.0;
|
||||||
|
# breaks audit/replay trust — Absolute Provenance).
|
||||||
|
self.runtime.finalize_turn_surface(surface, articulation_surface)
|
||||||
|
|
||||||
# B4 producer: capture the leeway the response path already decided —
|
# B4 producer: capture the leeway the response path already decided —
|
||||||
# observational only (reads the runtime's introspection-only accrual and
|
# observational only (reads the runtime's introspection-only accrual and
|
||||||
# the response's reach level; never alters the surface, never gates).
|
# the response's reach level; never alters the surface, never gates).
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,15 @@ fail-closed determinism). Execution status:
|
||||||
first-match pack semantics unchanged outside the morph rule.
|
first-match pack semantics unchanged outside the morph rule.
|
||||||
- [ ] **R6** — one rule type only (`he_morph_v0.plural_abstain`);
|
- [ ] **R6** — one rule type only (`he_morph_v0.plural_abstain`);
|
||||||
construct-state / prep+case / aspect deferred.
|
construct-state / prep+case / aspect deferred.
|
||||||
- [ ] **T13 (main regression, serving-provenance — needs its own fix PR):
|
- [ ] **R7** (opened by the T13 fix, 2026-07-22) — the opt-in telemetry SINK
|
||||||
|
stream (`attach_telemetry_sink`) still receives the pre-override `TurnEvent`
|
||||||
|
(pre-resolution surface + empty `trace_hash`) — the same provisional-then-
|
||||||
|
back-stamped limitation `finalize_turn_trace_hash` already carries. A single
|
||||||
|
deferred sink emission at the pipeline serve boundary would repair BOTH
|
||||||
|
surface and `trace_hash` in the durable stream. Deferred (default sink is
|
||||||
|
`None`, so no live consumer is affected today); own PR when a sink consumer
|
||||||
|
lands.
|
||||||
|
- [x] **T13 (main regression, serving-provenance — telemetry half FIXED):
|
||||||
fast lane is red on main** (was 0-red 2026-07-16):
|
fast lane is red on main** (was 0-red 2026-07-16):
|
||||||
`tests/test_warmed_session_lane.py::TestPipelineOverrideGateInvariants::test_telemetry_consistency_rate_is_one`
|
`tests/test_warmed_session_lane.py::TestPipelineOverrideGateInvariants::test_telemetry_consistency_rate_is_one`
|
||||||
fails at 0.9444 (17/18). Verified pre-existing on unmodified main (fails
|
fails at 0.9444 (17/18). Verified pre-existing on unmodified main (fails
|
||||||
|
|
@ -197,3 +205,21 @@ fail-closed determinism). Execution status:
|
||||||
the pack surface never claimed geometric certification). Note: smoke does
|
the pack surface never claimed geometric certification). Note: smoke does
|
||||||
not cover this lane, and GitHub Actions are dead signals — nothing gates
|
not cover this lane, and GitHub Actions are dead signals — nothing gates
|
||||||
fast-lane red on main right now.
|
fast-lane red on main right now.
|
||||||
|
|
||||||
|
**Resolution (2026-07-22, PR `fix/telemetry-serve-boundary`):**
|
||||||
|
- **(1) FIXED** — `ChatRuntime.finalize_turn_surface` back-stamps the
|
||||||
|
pipeline's resolved surface onto `turn_log[-1]`, a sibling to
|
||||||
|
`finalize_turn_trace_hash`, called from `pipeline.py` immediately after
|
||||||
|
the trace-hash back-stamp. Lane green: `telemetry_consistency_rate`
|
||||||
|
0.9444 → 1.0 (10/10 warmed_session tests pass). `trace_hash` byte-identity
|
||||||
|
preserved — it folds the pre-decoration surface, not the served surface.
|
||||||
|
- **(2) OPEN — needs Shay's ruling.** Orthogonal to the red (telemetry now
|
||||||
|
matches whatever is served, refusal or not). Recommend **AGAINST** a
|
||||||
|
query-type "definitional/epistemic" classifier bypass: that fails a
|
||||||
|
geometric coherence gate OPEN on a lexical cue — the fail-open / cue-table
|
||||||
|
pattern ADR-0252 retired and INV-34 / fail-closed forbid. Principled
|
||||||
|
alternative: route open-geometry-but-**pack-grounded** surfaces to the
|
||||||
|
existing hedge-injection arm (`authoritative=False`, honestly hedged),
|
||||||
|
discriminated by grounding *provenance* (structural), not question type.
|
||||||
|
Own focused PR + real-data (not synthetic) validation.
|
||||||
|
- Durable-sink residual tracked as **R7** above.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue