Clears the long-standing B4 block: the leeway decision was already made on the
serving path (chat/runtime.py::_surface_estimate has a real LicenseDecision +
the ReachPolicy) and then DISCARDED — never threaded to the result, and the
workbench can't import reliability_gate. This wires it through.
Producer (observational, never authorizing):
- core/cognition/leeway.py: LeewayRecord + build_leeway_record(reach_level,
license_decision) — duck-typed on the decision, zero new cross-package
coupling. Maps to: no decision -> "unknown" (STRICT, no latitude); denied
-> "blocked" (gate consulted, said no); licensed SERVE/PROPOSE widening ->
the real class / theta / "[approximate]" disclosure. "verified" is never
emitted (RESERVED state). source_digest content-addresses the decision
(deterministic, no wall-clock).
- core/cognition/result.py: additive `leeway: LeewayRecord | None = None` on
CognitiveTurnResult.
- core/cognition/pipeline.py: build it at result construction from the data
the runtime ALREADY exposes (response.reach_level +
runtime.last_turn_accrual().license). chat/runtime.py is UNTOUCHED.
- workbench/api.py: _leeway_evidence_from_result maps result.leeway ->
LeewayEvidence (pure projection; no reliability_gate import — firewall
intact). The journal already persists it; the B4a UI (Replay / Proposals /
RightInspector) already renders it — no frontend or schema change needed.
Safety (this touches the serving path, so proven, not asserted):
- trace_hash is a NAMED-field hash (core/cognition/trace.py); `leeway` is not
in it -> byte-identical serving. All provenance/trace tests pass.
- response_governance STRICT stays byte-identical (375 governance/serving/
provenance tests green, incl. the live-wiring + estimation-lane + ADR-0206
seam tests).
- core eval cognition: 13 cases, 100% intent / groundedness / versor closure.
- replay determinism holds (leeway is in CRITICAL_FIELDS; deterministic).
Tests: engine (build_leeway_record: strict/blocked/SERVE/PROPOSE, no "verified",
deterministic digest) + workbench mapping (field-for-field, honest absence,
invalid-enum clamp) + integration (a real turn now carries an honest leeway
record, not the null "No evidence recorded"). 151 workbench/leeway Python + 68
frontend (leeway/replay/proposals/schemaDrift) green; schema-snapshot unchanged.
Docs: gate cleared (b4-leeway-feasibility-gate.md), residue ledger flipped to
implemented, scope brief is b4-leeway-producer-scope-2026-06-13.md.
2.2 KiB
Wave M B3.5-c — B4 Leeway Feasibility Gate
Date: 2026-06-13
Status: GATE CLEARED (2026-06-13) — the engine-side producer now exists.
core/cognition/leeway.py::build_leeway_record turns the reach-policy +
LicenseDecision the response path already computes into an observational
LeewayRecord on CognitiveTurnResult; workbench/api.py::_leeway_evidence_from_result
maps it to LeewayEvidence (no reliability_gate import — firewall intact);
the journal persists it and the existing B4a UI (Replay / Proposals /
RightInspector) renders it. Every turn now carries an honest record (STRICT →
"no latitude"; a licensed SERVE widening → the real class/θ/[approximate]).
Scope + design: b4-leeway-producer-scope-2026-06-13.md. Original gate text
below, kept for provenance.
Finding
B4 needs a tuple that explains why approximation or leeway was granted:
class_namelicense:PROPOSE | SERVE | blocked | unknownthetaclaim_disclosure:approximate | verified | proposal_only | nonesource_digestcalibration_evidence_ref
Before this slice, that tuple was not present in ChatTurnResult,
TurnJournalEntry, ProposalDetail, or MathProposalDetail. Any UI card that
named class/license/theta would have had to infer calibration state in the
frontend.
B4a Read Model
workbench/schemas.py::LeewayEvidence is now the only lawful tuple shape for
B4 explanations. It is nullable on:
ChatTurnResultTurnJournalEntrySchemaTurnReplayComparisonProposalDetailMathProposalDetail
Frontend mirrors live in workbench-ui/src/types/api.ts. The shared
LeewayEvidenceCard renders the tuple when present and renders explicit absence
when it is null or missing.
Gate Result
B4 UI annotations may start only when a backend producer populates
LeewayEvidence from engine-owned calibration evidence or a lawful backend join.
Until then, Proposals and Replay can show "No leeway evidence recorded."; they
must not explain leeway from frontend-only class/license inference.
Follow-Up
Next PR: B4 producer wiring. Candidate sources are the turn/proposal creation
paths that already know whether a claim is approximate, plus the calibration
reader's calibration:<class_name> evidence subject.