core/core/cognition
Shay bb95dfbe67 fix(runtime): defer the turn-event sink emission to the serve boundary (R7)
Audit-ledger R7, implementing docs/handoff/curriculum-license-loop-2026-07/
E1-R7-ASSERTION-SPEC.md. `ChatRuntime.chat` seals a TurnEvent before the
surface authority is known; `CognitiveTurnPipeline` back-stamps the resolved
surface and canonical trace_hash onto `turn_log[-1]` after `chat` returns. So
the in-memory log ended up correct and the DURABLE stream carried the
pre-override record — the thing that persists was the wrong one.

Mechanism, per the spec's M1-M3:

- M1 — stage an INDEX into `turn_log`, never the TurnEvent. The flush re-reads
  the log, so every back-stamp is picked up by construction and the staged
  record cannot go stale. Capturing the event object would be the original
  defect with extra steps.
- M2 — `attach_telemetry_sink` does NOT flush a staged turn event, the
  opposite of what it correctly does for `_pending_reboot_payload`. The reboot
  payload is final when buffered; a staged turn event is mid-flight. Flushing
  on attach would silently restore the defect.
- M3 — deferral is opt-in. The pipeline wraps the runtime rather than the
  reverse, so the runtime cannot detect whether a pipeline will run. A runtime
  used directly (eval and demo paths) emits inline, byte-identically and at
  the same moment as before.

The `finally` at the serve boundary is load-bearing (I5): a pipeline that
raises after `chat` returns must still flush, or an error path silently
swallows a telemetry record — worse than the staleness being fixed.

TWO CORRECTIONS TO MY OWN SPEC, reported rather than quietly absorbed:

1. I2 bullet 3 and I3 assert on an emitted `trace_hash`. There is no such
   field — `chat/telemetry.py` never serializes `TurnEvent.trace_hash`, so the
   sink never carried a trace_hash, stale or otherwise. R7 repairs the SURFACE
   only. Pinned by `test_trace_hash_is_not_in_the_wire_format_at_all` so the
   claim cannot be re-asserted; the replay-not-recomputation ruling is kept on
   the object that does carry the hash.
2. The surface divergence is unreachable under the DEFAULT config:
   `finalize_turn_surface` is a no-op on all 36 turns probed, because the
   runtime's own surface already wins the resolver. It fires under
   `realizer_grounded_authority` — 24 divergences over 84 turns. A test on the
   default config would have passed while proving nothing, exactly as the spec
   warned, so the fixture pins that flag and asserts the pre-fix divergence
   exists before asserting it is gone.

[Verification]: in-worktree on canonical CPython 3.12.13 with `uv sync
--locked`: smoke 591 (569 + 22), deductive 291 (unchanged). All seven existing
sink test files pass UNCHANGED (80 tests). warmed_session_consistency
telemetry_consistency_rate = 1.0. Mutation-checked all three mechanisms:
staging the event instead of the index -> 3 I2 tests red; flushing on attach ->
the M2 test red; dropping the `finally` -> the I5 test red. Registered in
`smoke` and `cognition`.
2026-07-26 10:56:03 -07:00
..
__init__.py
backpressure.py feat(l10): idle backpressure telemetry — observational flywheel pressure gauge 2026-06-15 02:36:44 -07:00
explain.py feat(w013): wire explain_last_turn() into core chat /explain REPL command (#265) 2026-05-25 06:09:49 -07:00
fail_closed.py feat(cognition): fail-closed linguistic governance + trilingual constraint pipeline 2026-07-20 16:16:56 -07:00
geometric_coherence.py feat(cognition): Stage 3 geometric coherence, inductive closure, OOV pins 2026-07-20 13:54:51 -07:00
inductive_closure.py fix(stage3): gate inductive expansion on geometric admissibility 2026-07-20 15:07:12 -07:00
leeway.py feat(b4): engine-side leeway producer — populate LeewayEvidence (Wave M B4) 2026-06-13 20:22:39 -07:00
pipeline.py fix(runtime): defer the turn-event sink emission to the serve boundary (R7) 2026-07-26 10:56:03 -07:00
proof_trace.py feat(cognition): fail-closed linguistic governance + trilingual constraint pipeline 2026-07-20 16:16:56 -07:00
provenance.py chore(phase2): close W-006/W-010/W-014 — cleanup + doc amendments (#264) 2026-05-25 06:05:17 -07:00
result.py fix(cognition): expose hash_surface; point the register-matrix pin at it 2026-07-25 14:06:36 +00:00
surface_resolution.py fix(cognition): restore register axis on pipeline-served turns + Phase 0 of generalization arc 2026-07-24 12:28:32 -07:00
trace.py feat: integrate 3-core-language depth into PropositionGraph spine for bidirectional unification 2026-07-06 09:01:43 -07:00