ticket #000036 Tier-2: dav1d Option B (conservative B1 envelope) applied in v1

Per fox: apply the conservative max_envelope B1 model by changing the
v1 calculator's default — NOT by forking a v2. CALCULATOR_VERSION stays
"t3-bound-v1-bottou-refinement" (the descriptor names the unchanged B3
term); b1_model is echoed in the output AND the inputs dict so KAT
replays are unambiguous about which model produced a row.

Calculator (bench/scripts/t3_bound_calculator.py):
- New b1_model kwarg + --b1-model CLI flag, choices:
    max_envelope         (default)  max(fraction_channels, aggregate_bias)
    fraction_channels               g · W · log₂(1 + G/σ)
    aggregate_bias                      W · log₂(1 + g·G/σ)
    effective_control_v1            g · W · log₂(1 + g·G/σ)   (old non-worst-case)
- Default is now max_envelope — genuinely upper-bounding across both
  interpretations of g (dav1d review §3 closure blocker, RESOLVED).
- Every output reports all three concrete B1 variants
  (B1_fraction_channels / B1_aggregate_bias / B1_effective_control_v1),
  b1_selected, and both SNR readings (snr_grad = g·G/σ,
  snr_per_channel = G/σ) regardless of which b1_model was requested.
- model_assumptions[] now carries f"B1_model_{b1_model}".
- inputs echo now includes c_b1/c_b2/c_b3/b1_model (replay-complete).
- Invalid b1_model rejected with a ValueError naming the field.
- Baseline I_window: 625.8716 (effective_control_v1) → 6183.0154
  (max_envelope: B1=aggregate_bias 5849.63 dominates fraction_channels
  1729.72), certification_status NOT_CERTIFIED_BY_BOUND at W=10000.

KAT fixture (bench/fixtures/t3-bound/known-answer-tests.jsonl):
- Regenerated 2026-05-11 — 12 entries: the 8 §7-derived configs under
  the new max_envelope default, a g=0 edge case, plus explicit-mode
  pins for effective_control_v1 / fraction_channels / aggregate_bias.
- Each entry carries b1_model, expected_b1_selected,
  expected_b1_{fraction_channels,aggregate_bias,effective_control_v1},
  expected_snr_per_channel, expected_certification_status.

Tests (tests/test_t3_bound_calculator.py, 75 → 83):
- test_t3_bound_known_answer_tests no longer skips (fixture active);
  pins b1_model, b1_selected, certification_status + numbers, tolerates
  optional new fields on older fixtures.
- New: test_b1_max_envelope_exact_formula, test_invalid_b1_model_rejected,
  test_cli_b1_model_flag (effective_control_v1 / fraction_channels /
  aggregate_bias). test_b1_exact_formula renamed
  test_b1_effective_control_v1_exact_formula and now passes the explicit
  model. Updated baseline / below-256 / CLI tests for the new numbers.

Doc (docs/soft-hash-channel-t3-bound.md):
- Header + §0 + §3.1 + §6 + §7 (worked examples) + §8 (operator
  guidance W-solving) + §10 (closure blockers RESOLVED) + §10.1 +
  §11 (calculator schema) + §12 all updated for the max_envelope
  default. §8: target-256 W drops from ~4196 to ~415 steps under the
  conservative model — the ~10× cost of not assuming which g-reading
  holds; operators who can measure effective-control applies can use
  --b1-model effective_control_v1 for the looser W (a calibration
  claim they must justify, not a default).

Status (#000036 ticket + TICKETS.md): both prior dav1d closure
blockers cleared (B1 worst-case model + active KAT fixture); remaining
= fox's final close-or-iterate call.

AUTOCOUNT markers bumped 75 → 83. Full suite: 2288 passed, 28 skipped.
This commit is contained in:
russell@unturf.com 2026-05-11 07:06:50 -04:00
parent dbe824944a
commit 1d1a942d57
No known key found for this signature in database
8 changed files with 501 additions and 258 deletions

View file

@ -1,12 +1,16 @@
# T3 bound calculator known-answer tests — version t3-bound-v1-bottou-refinement # T3 bound calculator known-answer tests — version t3-bound-v1-bottou-refinement
# Generated 2026-05-10 from docs/soft-hash-channel-t3-bound.md §7 # Regenerated 2026-05-11 after the b1_model=max_envelope default change
# worked examples + override-constant variants + edge regimes. # (dav1d review Option B applied in v1). Algorithm change MUST bump
# Algorithm change MUST bump CALCULATOR_VERSION + emit new fixture. # CALCULATOR_VERSION + emit a new fixture file.
{"label": "small-deployment-\u00a77.1", "calculator_version": "t3-bound-v1-bottou-refinement", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024}, "expected_total": 625.8716, "expected_b1": 292.4813, "expected_b2": 300.0, "expected_b3": 33.3904, "expected_snr_grad": 0.5} {"label": "small-deployment-§7.1", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "max_envelope"}, "expected_total": 6183.0154, "expected_b1": 5849.625, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 1729.7158, "expected_b1_aggregate_bias": 5849.625, "expected_b1_effective_control_v1": 292.4813, "expected_b2": 300.0, "expected_b3": 33.3904, "expected_snr_grad": 0.5, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "medium-deployment-\u00a77.2", "calculator_version": "t3-bound-v1-bottou-refinement", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 1000, "lr_grid_size": 16, "window_length": 100000, "batches_per_epoch": 8192, "steps_per_epoch": 8192}, "expected_total": 3387.72, "expected_b1": 2924.8125, "expected_b2": 400.0, "expected_b3": 62.9075, "expected_snr_grad": 0.5} {"label": "medium-deployment-§7.2", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 1000, "lr_grid_size": 16, "window_length": 100000, "batches_per_epoch": 8192, "steps_per_epoch": 8192, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "max_envelope"}, "expected_total": 58959.1575, "expected_b1": 58496.2501, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 17297.1581, "expected_b1_aggregate_bias": 58496.2501, "expected_b1_effective_control_v1": 2924.8125, "expected_b2": 400.0, "expected_b3": 62.9075, "expected_snr_grad": 0.5, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "hardened-deployment-\u00a77.3", "calculator_version": "t3-bound-v1-bottou-refinement", "inputs": {"gradient_fraction": 0.01, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 4, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024}, "expected_total": 247.1407, "expected_b1": 13.7504, "expected_b2": 200.0, "expected_b3": 33.3904, "expected_snr_grad": 0.1} {"label": "hardened-deployment-§7.3", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.01, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 4, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "max_envelope"}, "expected_total": 1608.4256, "expected_b1": 1375.0352, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 345.9432, "expected_b1_aggregate_bias": 1375.0352, "expected_b1_effective_control_v1": 13.7504, "expected_b2": 200.0, "expected_b3": 33.3904, "expected_snr_grad": 0.1, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "extreme-low-g", "calculator_version": "t3-bound-v1-bottou-refinement", "inputs": {"gradient_fraction": 0.001, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.5, "lr_decision_interval": 500, "lr_grid_size": 2, "window_length": 5000, "batches_per_epoch": 256, "steps_per_epoch": 256}, "expected_total": 80.0144, "expected_b1": 0.0144, "expected_b2": 10.0, "expected_b3": 70.0, "expected_snr_grad": 0.002} {"label": "extreme-low-g", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.001, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.5, "lr_decision_interval": 500, "lr_grid_size": 2, "window_length": 5000, "batches_per_epoch": 256, "steps_per_epoch": 256, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "max_envelope"}, "expected_total": 94.4125, "expected_b1": 14.4125, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 7.9248, "expected_b1_aggregate_bias": 14.4125, "expected_b1_effective_control_v1": 0.0144, "expected_b2": 10.0, "expected_b3": 70.0, "expected_snr_grad": 0.002, "expected_snr_per_channel": 2.0, "expected_certification_status": "CERTIFIED_BY_BOUND"}
{"label": "tight-window-W=100", "calculator_version": "t3-bound-v1-bottou-refinement", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 2.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 50, "lr_grid_size": 4, "window_length": 100, "batches_per_epoch": 64, "steps_per_epoch": 64}, "expected_total": 10.6781, "expected_b1": 5.0, "expected_b2": 4.0, "expected_b3": 1.6781, "expected_snr_grad": 1.0} {"label": "tight-window-W=100", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 2.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 50, "lr_grid_size": 4, "window_length": 100, "batches_per_epoch": 64, "steps_per_epoch": 64, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "max_envelope"}, "expected_total": 105.6781, "expected_b1": 100.0, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 21.9616, "expected_b1_aggregate_bias": 100.0, "expected_b1_effective_control_v1": 5.0, "expected_b2": 4.0, "expected_b3": 1.6781, "expected_snr_grad": 1.0, "expected_snr_per_channel": 20.0, "expected_certification_status": "CERTIFIED_BY_BOUND"}
{"label": "tightened-c-b1", "calculator_version": "t3-bound-v1-bottou-refinement", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 0.5}, "expected_total": 479.631, "expected_b1": 146.2406, "expected_b2": 300.0, "expected_b3": 33.3904, "expected_snr_grad": 0.5} {"label": "tightened-c-b1", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 0.5, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "max_envelope"}, "expected_total": 3258.2029, "expected_b1": 2924.8125, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 864.8579, "expected_b1_aggregate_bias": 2924.8125, "expected_b1_effective_control_v1": 146.2406, "expected_b2": 300.0, "expected_b3": 33.3904, "expected_snr_grad": 0.5, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "all-constants-tight", "calculator_version": "t3-bound-v1-bottou-refinement", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 0.1, "c_b2": 0.1, "c_b3": 0.1}, "expected_total": 62.5872, "expected_b1": 29.2481, "expected_b2": 30.0, "expected_b3": 3.339, "expected_snr_grad": 0.5} {"label": "all-constants-tight", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 0.1, "c_b2": 0.1, "c_b3": 0.1, "b1_model": "max_envelope"}, "expected_total": 618.3015, "expected_b1": 584.9625, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 172.9716, "expected_b1_aggregate_bias": 584.9625, "expected_b1_effective_control_v1": 29.2481, "expected_b2": 30.0, "expected_b3": 3.339, "expected_snr_grad": 0.5, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "b3-floor-regime", "calculator_version": "t3-bound-v1-bottou-refinement", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 100.0, "gradient_noise_stddev": 0.001, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 4, "steps_per_epoch": 4}, "expected_total": 6444.0004, "expected_b1": 6144.0004, "expected_b2": 300.0, "expected_b3": 0.0, "expected_snr_grad": 5000.0} {"label": "b3-floor-regime", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 100.0, "gradient_noise_stddev": 0.001, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 4, "steps_per_epoch": 4, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "max_envelope"}, "expected_total": 123180.0089, "expected_b1": 122880.0089, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 8304.8275, "expected_b1_aggregate_bias": 122880.0089, "expected_b1_effective_control_v1": 6144.0004, "expected_b2": 300.0, "expected_b3": 0.0, "expected_snr_grad": 5000.0, "expected_snr_per_channel": 100000.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "gradient-fraction-zero", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "max_envelope", "inputs": {"gradient_fraction": 0.0, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "max_envelope"}, "expected_total": 333.3904, "expected_b1": 0.0, "expected_b1_selected": "fraction_channels", "expected_b1_fraction_channels": 0.0, "expected_b1_aggregate_bias": 0.0, "expected_b1_effective_control_v1": 0.0, "expected_b2": 300.0, "expected_b3": 33.3904, "expected_snr_grad": 0.0, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "b1-effective-control-v1-mode", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "effective_control_v1", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "effective_control_v1"}, "expected_total": 625.8716, "expected_b1": 292.4813, "expected_b1_selected": "effective_control_v1", "expected_b1_fraction_channels": 1729.7158, "expected_b1_aggregate_bias": 5849.625, "expected_b1_effective_control_v1": 292.4813, "expected_b2": 300.0, "expected_b3": 33.3904, "expected_snr_grad": 0.5, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "b1-fraction-channels-mode", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "fraction_channels", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "fraction_channels"}, "expected_total": 2063.1062, "expected_b1": 1729.7158, "expected_b1_selected": "fraction_channels", "expected_b1_fraction_channels": 1729.7158, "expected_b1_aggregate_bias": 5849.625, "expected_b1_effective_control_v1": 292.4813, "expected_b2": 300.0, "expected_b3": 33.3904, "expected_snr_grad": 0.5, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}
{"label": "b1-aggregate-bias-mode", "calculator_version": "t3-bound-v1-bottou-refinement", "b1_model": "aggregate_bias", "inputs": {"gradient_fraction": 0.05, "gradient_norm_max": 1.0, "gradient_noise_stddev": 0.1, "lr_decision_interval": 100, "lr_grid_size": 8, "window_length": 10000, "batches_per_epoch": 1024, "steps_per_epoch": 1024, "c_b1": 1.0, "c_b2": 1.0, "c_b3": 1.0, "b1_model": "aggregate_bias"}, "expected_total": 6183.0154, "expected_b1": 5849.625, "expected_b1_selected": "aggregate_bias", "expected_b1_fraction_channels": 1729.7158, "expected_b1_aggregate_bias": 5849.625, "expected_b1_effective_control_v1": 292.4813, "expected_b2": 300.0, "expected_b3": 33.3904, "expected_snr_grad": 0.5, "expected_snr_per_channel": 10.0, "expected_certification_status": "NOT_CERTIFIED_BY_BOUND"}

View file

@ -23,15 +23,24 @@ processing inequality; see §6 + §10). Operators with deployment-
specific empirical measurements of the constants pass them via specific empirical measurements of the constants pass them via
``--c-b1`` / ``--c-b2`` / ``--c-b3`` flags. ``--c-b1`` / ``--c-b2`` / ``--c-b3`` flags.
**B1 model.** This v1 calculator uses ``b1_model="effective_control_v1"``: **B1 model.** Default ``b1_model="max_envelope"`` (#000036 §3.1,
``g`` is read as an *effective gradient-control coefficient* that dav1d review 2026-05-11): ``g`` has two competing interpretations —
simultaneously bounds the fraction of steerable directions AND the *fraction of steerable directions* (each carrying full per-channel
amplitude shrinkage of the aggregate adversarial gradient. Under that SNR ``G/σ``) and *aggregate amplitude shrinkage* (one effective
reading the B1 formula ``C_B1 · g · W · log₂(1 + g·G/σ)`` is sound, channel carrying SNR ``g·G/σ``). The conservative envelope is the
but it is **not the most-conservative gradient adversary** — see larger of the two:
#000036 §3 + §10 for the alternative ``b1_model="max_envelope"``
path (deferred to a v2 bump). For now ``certification_status`` is B1_fraction_channels = C_B1 · g · W · log₂(1 + G/σ)
relative to this v1 effective-control model. B1_aggregate_bias = C_B1 · W · log₂(1 + g·G/σ)
B1 (max_envelope) = max(B1_fraction_channels, B1_aggregate_bias)
Other ``b1_model`` choices: ``"fraction_channels"`` / ``"aggregate_bias"``
(the individual envelope terms) and ``"effective_control_v1"`` (the
older ``C_B1 · g · W · log₂(1 + g·G/σ)`` — an operational risk
score, NOT a worst-case bound; kept for backward comparison).
``certification_status`` is relative to whichever model is selected;
under the default ``max_envelope`` it is a genuine upper-bound
certification.
Pure stdlib. No numpy / scipy dependency — the math is Pure stdlib. No numpy / scipy dependency — the math is
arithmetic + math.log2. arithmetic + math.log2.
@ -58,7 +67,16 @@ import sys
CALCULATOR_VERSION = "t3-bound-v1-bottou-refinement" CALCULATOR_VERSION = "t3-bound-v1-bottou-refinement"
B1_MODEL = "effective_control_v1" # B1 model selection (#000036 §3.1). Default is the conservative
# envelope; effective_control_v1 is the older non-worst-case formula
# kept for backward comparison.
B1_MODELS = (
"max_envelope",
"fraction_channels",
"aggregate_bias",
"effective_control_v1",
)
B1_MODEL_DEFAULT = "max_envelope"
CERTIFICATION_THRESHOLD_BITS = 256 CERTIFICATION_THRESHOLD_BITS = 256
@ -100,13 +118,21 @@ def t3_bound_bits(
c_b1: float = 1.0, c_b1: float = 1.0,
c_b2: float = 1.0, c_b2: float = 1.0,
c_b3: float = 1.0, c_b3: float = 1.0,
b1_model: str = B1_MODEL_DEFAULT,
) -> dict: ) -> dict:
"""Compute the per-window mutual-information bound + per-bandwidth """Compute the per-window mutual-information bound + per-bandwidth
contributions per #000036 §6. contributions per #000036 §6.
Returns a dict with the total bound, three per-bandwidth ``b1_model`` selects the gradient-bias model (see #000036 §3.1):
contributions, the constants in use, and a sentence of operator ``"max_envelope"`` (default, conservative), ``"fraction_channels"``,
guidance based on the bound vs the SHA-256 (256-bit) baseline. ``"aggregate_bias"``, or ``"effective_control_v1"`` (older
non-worst-case formula).
Returns a dict with the total bound, the per-bandwidth
contributions (including all three B1 model variants), the
constants + selected B1 model, a structured ``certification_status``,
and a sentence of operator guidance based on the bound vs the
SHA-256 (256-bit) certification threshold.
""" """
# Validation — reject bools / NaN / inf; coerce numeric types. # Validation — reject bools / NaN / inf; coerce numeric types.
gradient_fraction = _require_finite_float("gradient_fraction", gradient_fraction) gradient_fraction = _require_finite_float("gradient_fraction", gradient_fraction)
@ -140,16 +166,41 @@ def t3_bound_bits(
for name, c in [("c_b1", c_b1), ("c_b2", c_b2), ("c_b3", c_b3)]: for name, c in [("c_b1", c_b1), ("c_b2", c_b2), ("c_b3", c_b3)]:
if not 0 <= c <= 1: if not 0 <= c <= 1:
raise ValueError(f"{name} must be in [0, 1]; got {c}") raise ValueError(f"{name} must be in [0, 1]; got {c}")
if b1_model not in B1_MODELS:
raise ValueError(
f"b1_model must be one of {B1_MODELS}; got {b1_model!r}"
)
# B1 — gradient bias. Per-step discrete channel-capacity bound on # B1 — gradient bias. Per-step discrete channel-capacity bound on
# the adversary-controlled parameter shift (NOT Fano's inequality — # the adversary-controlled parameter shift (NOT Fano's inequality —
# see #000036 §3): the per-step shift falls in one of ~SNR_grad+1 # see #000036 §3): the per-step shift falls in one of ~SNR+1
# distinguishable buckets, capacity ≤ log₂(SNR_grad+1). Under the # distinguishable buckets, capacity ≤ log₂(SNR+1). Two SNR readings
# b1_model="effective_control_v1" reading, g bounds both the # (#000036 §3.1):
# steerable-direction fraction and the aggregate amplitude shrinkage. # per-channel SNR = G/σ → fraction_channels model
snr_grad = gradient_fraction * gradient_norm_max / gradient_noise_stddev # aggregate SNR = g·G/σ → aggregate_bias / effective_control
b1_per_step = math.log2(snr_grad + 1) # Default b1_model="max_envelope" = max of the two envelope terms —
b1 = c_b1 * gradient_fraction * window_length * b1_per_step # genuinely upper-bounding across both interpretations (dav1d review
# 2026-05-11).
snr_grad = gradient_fraction * gradient_norm_max / gradient_noise_stddev # g·G/σ
snr_per_channel = gradient_norm_max / gradient_noise_stddev # G/σ
b1_fraction_channels = (
c_b1 * gradient_fraction * window_length * math.log2(snr_per_channel + 1)
)
b1_aggregate_bias = c_b1 * window_length * math.log2(snr_grad + 1)
b1_effective_control = (
c_b1 * gradient_fraction * window_length * math.log2(snr_grad + 1)
)
if b1_model == "max_envelope":
if b1_fraction_channels >= b1_aggregate_bias:
b1, b1_selected = b1_fraction_channels, "fraction_channels"
else:
b1, b1_selected = b1_aggregate_bias, "aggregate_bias"
elif b1_model == "fraction_channels":
b1, b1_selected = b1_fraction_channels, "fraction_channels"
elif b1_model == "aggregate_bias":
b1, b1_selected = b1_aggregate_bias, "aggregate_bias"
else: # effective_control_v1
b1, b1_selected = b1_effective_control, "effective_control_v1"
# B2 — LR selection. R-symbol categorical channel at every K-step # B2 — LR selection. R-symbol categorical channel at every K-step
# decision point (#000036 §4). # decision point (#000036 §4).
@ -210,12 +261,17 @@ def t3_bound_bits(
return { return {
"calculator_version": CALCULATOR_VERSION, "calculator_version": CALCULATOR_VERSION,
"b1_model": B1_MODEL, "b1_model": b1_model,
"b1_selected": b1_selected,
"I_window_bits_upper_bound": round(total, 4), "I_window_bits_upper_bound": round(total, 4),
"B1_contribution": round(b1, 4), "B1_contribution": round(b1, 4),
"B1_fraction_channels": round(b1_fraction_channels, 4),
"B1_aggregate_bias": round(b1_aggregate_bias, 4),
"B1_effective_control_v1": round(b1_effective_control, 4),
"B2_contribution": round(b2, 4), "B2_contribution": round(b2, 4),
"B3_contribution": round(b3, 4), "B3_contribution": round(b3, 4),
"snr_grad": round(snr_grad, 4), "snr_grad": round(snr_grad, 4),
"snr_per_channel": round(snr_per_channel, 4),
"decisions_in_window": decisions_in_window, "decisions_in_window": decisions_in_window,
"epochs_in_window": epochs_in_window, "epochs_in_window": epochs_in_window,
"constants": {"C_B1": c_b1, "C_B2": c_b2, "C_B3": c_b3}, "constants": {"C_B1": c_b1, "C_B2": c_b2, "C_B3": c_b3},
@ -224,7 +280,7 @@ def t3_bound_bits(
"model_assumptions": [ "model_assumptions": [
"M2_nonce_per_window", "M2_nonce_per_window",
"SHA256_random_oracle_baseline", "SHA256_random_oracle_baseline",
"B1_effective_control_model_v1", f"B1_model_{b1_model}",
"B3_gradient_noise_refinement", "B3_gradient_noise_refinement",
], ],
"inputs": { "inputs": {
@ -236,6 +292,10 @@ def t3_bound_bits(
"window_length": window_length, "window_length": window_length,
"batches_per_epoch": batches_per_epoch, "batches_per_epoch": batches_per_epoch,
"steps_per_epoch": steps_per_epoch, "steps_per_epoch": steps_per_epoch,
"c_b1": c_b1,
"c_b2": c_b2,
"c_b3": c_b3,
"b1_model": b1_model,
}, },
"recommendation": recommendation, "recommendation": recommendation,
} }
@ -245,7 +305,7 @@ def main(argv: list[str] | None = None) -> int:
p = argparse.ArgumentParser(description=__doc__.splitlines()[0]) p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
p.add_argument( p.add_argument(
"--gradient-fraction", type=float, required=True, "--gradient-fraction", type=float, required=True,
help="g — effective gradient-control coefficient (b1_model=effective_control_v1); in [0, 1], 0 = no T2 surface", help="g — gradient-control coefficient; in [0, 1], 0 = no T2 surface. Interpretation depends on --b1-model.",
) )
p.add_argument( p.add_argument(
"--gradient-norm-max", type=float, required=True, "--gradient-norm-max", type=float, required=True,
@ -287,6 +347,15 @@ def main(argv: list[str] | None = None) -> int:
"--c-b3", type=float, default=1.0, "--c-b3", type=float, default=1.0,
help="C_B3 constant; default 1.0", help="C_B3 constant; default 1.0",
) )
p.add_argument(
"--b1-model", type=str, default=B1_MODEL_DEFAULT, choices=list(B1_MODELS),
help=(
"B1 gradient-bias model (#000036 §3.1). Default 'max_envelope' = "
"worst-case envelope across the two g-interpretations; "
"'fraction_channels' / 'aggregate_bias' = the individual terms; "
"'effective_control_v1' = older non-worst-case formula."
),
)
args = p.parse_args(argv) args = p.parse_args(argv)
try: try:
@ -302,6 +371,7 @@ def main(argv: list[str] | None = None) -> int:
c_b1=args.c_b1, c_b1=args.c_b1,
c_b2=args.c_b2, c_b2=args.c_b2,
c_b3=args.c_b3, c_b3=args.c_b3,
b1_model=args.b1_model,
) )
except ValueError as e: except ValueError as e:
print(f"input error: {e}", file=sys.stderr) print(f"input error: {e}", file=sys.stderr)

View file

@ -101,7 +101,7 @@ Newest first. Update on every open/close.
| #000039 | Optional `sqlite-vec` retrieval backend (A/B vs FTS5, hybrid not replacement) | open · awaiting go/no-go (doc-only Phase 0) | 2026-05-09 | — | | #000039 | Optional `sqlite-vec` retrieval backend (A/B vs FTS5, hybrid not replacement) | open · awaiting go/no-go (doc-only Phase 0) | 2026-05-09 | — |
| #000038 | Phase 4 content acquisition — proprietary textbook license decisions for warrant coverage | closed · obviated 2026-05-10 by alias-substitution sprint under #000031 (74 rows in #000041 + 13 rows in #000042); 92/92 records now resolve. Residue (multilingual PD, Hilbert-Ackermann OCR, Knuth permission, personal-copy path B) preserved as design log §8 | 2026-05-09 | — | | #000038 | Phase 4 content acquisition — proprietary textbook license decisions for warrant coverage | closed · obviated 2026-05-10 by alias-substitution sprint under #000031 (74 rows in #000041 + 13 rows in #000042); 92/92 records now resolve. Residue (multilingual PD, Hilbert-Ackermann OCR, Knuth permission, personal-copy path B) preserved as design log §8 | 2026-05-09 | — |
| #000037 | Prometheus-Σ recursive falsification controller (bicameral substrate) | in progress · Phases 0 + 1 + 1.b + 1.c + 2 landed 2026-05-10; **§12 Trigger 2 fired** (divergence variance 0.575 / N=37); §22 Findings 2 + 3 RESOLVED (kernel/llm cost split + sweep_weights §15.4 + per-mode τ_qa); `controller_events` carries 4 event kinds (decision · difficulty · budget_allocation · falsification_proposal) feeding `arborist controller-events` inspector + live-harvest third bucket in `bench/scripts/harvest_falsification_proposals.py`; §12 Trigger 1 probe wired 2026-05-11 (`trigger_1_branch_density` reads `fork_score_branches` — measurable, not yet fired); Phase 3 sleep-sweep scheduler tracked under #000045 (gating ticket) | 2026-05-09 | — | | #000037 | Prometheus-Σ recursive falsification controller (bicameral substrate) | in progress · Phases 0 + 1 + 1.b + 1.c + 2 landed 2026-05-10; **§12 Trigger 2 fired** (divergence variance 0.575 / N=37); §22 Findings 2 + 3 RESOLVED (kernel/llm cost split + sweep_weights §15.4 + per-mode τ_qa); `controller_events` carries 4 event kinds (decision · difficulty · budget_allocation · falsification_proposal) feeding `arborist controller-events` inspector + live-harvest third bucket in `bench/scripts/harvest_falsification_proposals.py`; §12 Trigger 1 probe wired 2026-05-11 (`trigger_1_branch_density` reads `fork_score_branches` — measurable, not yet fired); Phase 3 sleep-sweep scheduler tracked under #000045 (gating ticket) | 2026-05-09 | — |
| #000036 | T3 per-window covert-channel budget bound | in progress · Phase 1 + dav1d review returned 2026-05-11; Tier-1 polish applied (wording → "CANNOT CERTIFY", structured `certification_status`/`b1_model` fields, bool/NaN/inf validation, `g=0` accepted, test cwd fix; 53 → 75 tests); **closure blockers: B1 conservative-envelope v2 calculator (awaits fox go/no-go) + active KAT fixture** | 2026-05-09 | — | | #000036 | T3 per-window covert-channel budget bound | in progress · Phase 1 + dav1d review 2026-05-11 → Tier-1 + Tier-2 (Option B = `b1_model=max_envelope` default, applied *in v1*, no v2 fork) both landed 2026-05-11; KAT regenerated (12 entries, active); baseline 625.87 → 6183.02 (max_envelope); 53 → 83 tests; both prior closure blockers cleared — remaining = fox final close-or-iterate call | 2026-05-09 | — |
| #000035 | PRG choice for φ_PRG (HMAC-SHA-512 expansion) | in progress · Phase 1 landed 2026-05-10; v7 §9.10 amendment awaits maintainer review | 2026-05-09 | — | | #000035 | PRG choice for φ_PRG (HMAC-SHA-512 expansion) | in progress · Phase 1 landed 2026-05-10; v7 §9.10 amendment awaits maintainer review | 2026-05-09 | — |
| #000034 | Hessian alignment under φ_linear | in progress · Phase 1a landed 2026-05-10 (synthetic-ablation probe + KAT fixture); Phase 1b parks for v7 ramp-up | 2026-05-09 | — | | #000034 | Hessian alignment under φ_linear | in progress · Phase 1a landed 2026-05-10 (synthetic-ablation probe + KAT fixture); Phase 1b parks for v7 ramp-up | 2026-05-09 | — |
| #000033 | Claim-pack pillar VII (combinatorics) | closed · landed 2026-05-09 (live in shard 000.db; lift verified) | 2026-05-09 | — | | #000033 | Claim-pack pillar VII (combinatorics) | closed · landed 2026-05-09 (live in shard 000.db; lift verified) | 2026-05-09 | — |

View file

@ -13,7 +13,7 @@ bench across three modules:
closed-form bound for #000036 closed-form bound for #000036
The exemplar test file is ``tests/test_t3_bound_calculator.py`` The exemplar test file is ``tests/test_t3_bound_calculator.py``
(<!--AUTOCOUNT:tests:tests/test_t3_bound_calculator.py-->75<!--/AUTOCOUNT--> cases as of 2026-05-10; fox shipped 51 in the (<!--AUTOCOUNT:tests:tests/test_t3_bound_calculator.py-->83<!--/AUTOCOUNT--> cases as of 2026-05-10; fox shipped 51 in the
initial cut and the +2 KAT-fixture-gap closure landed in initial cut and the +2 KAT-fixture-gap closure landed in
``581ad90``). The other two test files ``581ad90``). The other two test files
(``tests/test_anchor_prg.py`` and (``tests/test_anchor_prg.py`` and
@ -378,7 +378,7 @@ shape exposes the corresponding surface. Many calculator modules
Exemplar test files: Exemplar test files:
- ``tests/test_t3_bound_calculator.py`` — - ``tests/test_t3_bound_calculator.py`` —
<!--AUTOCOUNT:tests:tests/test_t3_bound_calculator.py-->75<!--/AUTOCOUNT--> tests covering <!--AUTOCOUNT:tests:tests/test_t3_bound_calculator.py-->83<!--/AUTOCOUNT--> tests covering
items 1-9 for the T3 closed-form bound. items 1-9 for the T3 closed-form bound.
- ``tests/test_pi_star_arithmetic.py`` — - ``tests/test_pi_star_arithmetic.py`` —
<!--AUTOCOUNT:tests:tests/test_pi_star_arithmetic.py-->56<!--/AUTOCOUNT--> tests covering items <!--AUTOCOUNT:tests:tests/test_pi_star_arithmetic.py-->56<!--/AUTOCOUNT--> tests covering items

View file

@ -2,16 +2,18 @@
**Ticket**: #000036 **Ticket**: #000036
**Source analysis**: `docs/soft-hash-channel-analysis.md` **Source analysis**: `docs/soft-hash-channel-analysis.md`
**Date**: 2026-05-10 (review pass 2026-05-11) **Date**: 2026-05-10 (dav1d review pass + Option-B applied 2026-05-11)
**Status**: formal derivation + calculator landed; **dav1d review **Status**: formal derivation + calculator landed; **dav1d review
returned 2026-05-11**. Tier-1 polish applied (recommendation returned 2026-05-11** → **Tier-1 polish + Tier-2 (Option B: the
wording, structured `certification_status` output, validation conservative `max_envelope` B1 model, applied in v1 — no v2 fork)
hardening, B1-model labelling — see §3.1 + §10.1). **Closure both landed 2026-05-11**. KAT fixture regenerated (12 entries,
blockers remaining**: B1 conservative-envelope (v2 calculator, active — `test_t3_bound_known_answer_tests` no longer skips). The
§10 item 1) and active KAT fixture (§10 item 2). The framework is default B1 model is now `max_envelope` (§3.1); `effective_control_v1`
the deliverable; the named constants are conservative starting is reachable as a backward-comparison mode. Remaining before
estimates that empirical tightening (#000043) can replace without closure: fox's final close-or-iterate call (optionally a dav1d
changing call sites. re-review of the envelope formula). The named C_B* constants are
conservative starting estimates that empirical tightening
(#000043) can replace without changing call sites.
--- ---
@ -25,7 +27,7 @@ LR selection, batch order) and combines them into a closed-form
bound consumed by `bench/scripts/t3_bound_calculator.py`. bound consumed by `bench/scripts/t3_bound_calculator.py`.
**dav1d's 2026-05-11 review** (`RESPONSE_1` + `RESPONSE_2`) **dav1d's 2026-05-11 review** (`RESPONSE_1` + `RESPONSE_2`)
landed these findings: findings and how they were resolved:
1. **§2 decomposition** — accepted. Markov-chain DPI on 1. **§2 decomposition** — accepted. Markov-chain DPI on
`A → Θ_{t+1} → C(M_{t+1})` correctly applied; T1+T2 baseline `A → Θ_{t+1} → C(M_{t+1})` correctly applied; T1+T2 baseline
@ -34,26 +36,32 @@ landed these findings:
capacity bound. capacity bound.
3. **§5 (C_B3 batch order)** — accepted *as a model-bound, not a 3. **§5 (C_B3 batch order)** — accepted *as a model-bound, not a
theorem* (§5's "model-bound" note reflects this). theorem* (§5's "model-bound" note reflects this).
4. **§3 (C_B1 gradient bias)** — **closure blocker**. `g` appears 4. **§3 (C_B1 gradient bias)** — was the closure blocker. `g`
twice in the per-window expression, which is only sound under appeared twice in the per-window expression, only sound under
the `effective_control_v1` reading (§3.1). A worst-case the `effective_control_v1` reading. **Resolved 2026-05-11**:
gradient adversary needs the `max_envelope` model — the v2 Option B applied in v1 — the default `b1_model` is now
calculator path (§10 item 1). `max_envelope` = `max(fraction_channels, aggregate_bias)`,
genuinely upper-bounding across both interpretations of `g`
(§3.1). `effective_control_v1` stays reachable for backward
comparison. All three B1 variants are reported in every output.
5. Wording / validation / output-schema fixes — applied (§10.1). 5. Wording / validation / output-schema fixes — applied (§10.1).
**What's *not* being asked**: empirical validation against an **What's *not* being asked**: empirical validation against an
actual adversarial-training run (out of scope per §10 item 7; actual adversarial-training run (out of scope per §10 item 5;
opens as a future ticket once v7 plastic-training has a deployment opens as a future ticket once v7 plastic-training has a deployment
target). target).
The headline numeric example in §7 + §11 yields The headline numeric example in §7 + §11 now yields
`I_window ≈ 626 bits/window` for a default deployment config `I_window ≈ 6183 bits/window` for the default deployment config
**under the v1 effective-control B1 model** — exceeding SHA-256's **under the default `max_envelope` B1 model** (`B1 = aggregate_bias`
256-bit threshold, so `certification_status = NOT_CERTIFIED_BY_BOUND`. = 5849.6 bits dominates `fraction_channels` = 1729.7 bits;
A conservative `max_envelope` B1 model would produce ~5850 bits. `effective_control_v1` would have been 292.5 bits) — well above
The framework's job is to make the trigger derivable from the 256-bit threshold, so `certification_status = NOT_CERTIFIED_BY_BOUND`.
operator-measurable inputs; the v2 path makes the bound That is the correct conservative reading: at W=10000 with these
worst-case-conservative rather than effective-control-relative. inputs, the bound cannot certify M2 residual safety. The
calculator's `--b1-model` flag lets operators inspect the other
models if they want the effective-control risk score for
comparison.
--- ---
@ -224,58 +232,49 @@ For typical deployments `g · ‖∇L_max‖ / σ_grad = 0.05 · 1 / 0.1
= 0.5`, so `log₂(1.5) ≈ 0.5850 bits/step`. With `W = 10000` and = 0.5`, so `log₂(1.5) ≈ 0.5850 bits/step`. With `W = 10000` and
`g = 0.05`: `1 · 0.05 · 10000 · 0.5850 ≈ 292.48 bits/window`. `g = 0.05`: `1 · 0.05 · 10000 · 0.5850 ≈ 292.48 bits/window`.
### §3.1 The B1 model — `g` appears twice (dav1d review 2026-05-11) ### §3.1 The B1 model — `max_envelope` (default) vs the alternatives
Note that `g` enters the per-window B1 expression **twice**: once `g` enters the naive per-window B1 expression **twice**: once as
as the outer multiplier `g · W` (number of adversary-controlled the outer multiplier `g · W` (number of adversary-controlled
steps) and once inside `log₂(SNR_grad + 1)` where steps) and once inside `log₂(SNR_grad + 1)` where
`SNR_grad = g · ‖∇L_max‖ / σ_grad`. That double use is only sound `SNR_grad = g · ‖∇L_max‖ / σ_grad`. dav1d's 2026-05-11 review
under a specific reading: flagged that this double use is only sound under a *narrow*
interpretation of `g`. The calculator now offers four B1 models
(`--b1-model` flag), with `max_envelope` as the **default**:
``` | `b1_model` | Reading of `g` | Formula | Baseline B1 (`g=0.05, G=1, σ=0.1, W=10000`) |
b1_model = "effective_control_v1": |---|---|---|---|
g is an effective gradient-control coefficient that | `fraction_channels` | fraction of steerable directions; each carries full per-channel SNR `G/σ` | `C_B1 · g · W · log₂(1 + G/σ)` | 1 729.7 bits |
simultaneously bounds (a) the fraction of steerable | `aggregate_bias` | aggregate adversarial amplitude shrinkage; one effective channel carries SNR `g·G/σ` | `C_B1 · W · log₂(1 + g·G/σ)` | 5 849.6 bits |
directions per step AND (b) the amplitude shrinkage of | **`max_envelope`** (default) | take the worse of the two — no assumption about which interpretation holds | `max(fraction_channels, aggregate_bias)` | **5 849.6 bits** (`aggregate_bias` selected) |
the aggregate adversarial gradient signal. | `effective_control_v1` | `g` simultaneously bounds *both* direction fraction AND amplitude shrinkage — an operational risk score, NOT a worst-case bound | `C_B1 · g · W · log₂(1 + g·G/σ)` | 292.5 bits |
```
If instead `g` means **only** "fraction of gradient computations Every calculator output reports all three concrete variants
controlled" (with full per-channel amplitude), the conservative (`B1_fraction_channels`, `B1_aggregate_bias`,
shape is larger. dav1d's review spelled out the spread on the `B1_effective_control_v1`), the selected one (`b1_selected`), and
baseline (`g=0.05, ‖∇L_max‖=1, σ_grad=0.1, W=10000`): both SNR readings (`snr_grad = g·G/σ`, `snr_per_channel = G/σ`),
regardless of which `b1_model` was requested — so a reader can
always see the spread.
| B1 model | Formula | Baseline B1 | **Why `max_envelope` is the default.** A security bound that may
|---|---|---| be optimistic under some interpretation of its own inputs is not a
| `effective_control_v1` (current) | `g · W · log₂(1 + g·G/σ)` | **292.5 bits** | bound. `max_envelope` is upper-bounding across both readings of
| `fraction_channels` (g = channel fraction only) | `g · W · log₂(1 + G/σ)` | 1 729.7 bits | `g`, so `certification_status` under the default is a genuine
| `aggregate_bias` (g = amplitude shrinkage only) | `W · log₂(1 + g·G/σ)` | 5 849.6 bits | certification. `effective_control_v1` is kept reachable for
| `max_envelope` (conservative) | `max(fraction_channels, aggregate_bias)` | 5 849.6 bits | operators who specifically want the older effective-control risk
score for comparison — it should never be used to *certify*.
The current v1 calculator uses `effective_control_v1`. The **Implementation note (dav1d Option B, applied in v1 2026-05-11).**
`certification_status` it emits is therefore **relative to that Per fox's direction, this was applied by changing the v1
model** — it is an operational risk score, not a worst-case upper calculator's default rather than forking a v2 — `CALCULATOR_VERSION`
bound across all gradient-adversary interpretations. stays `t3-bound-v1-bottou-refinement` (the "bottou-refinement"
descriptor still names the unchanged B3 term). The `b1_model` field
**The conservative `max_envelope` model is the v2 path.** When the appears in both the output and the echoed `inputs`, so KAT replays
team wants the calculator to certify against the worst-case are unambiguous about which model produced a given row. The KAT
gradient adversary, it should: fixture was regenerated 2026-05-11 (12 entries: the §7 worked
examples under `max_envelope` plus explicit `effective_control_v1`
``` / `fraction_channels` / `aggregate_bias` mode pins and a `g=0`
1. add a b1_model parameter (default "max_envelope" for v2) edge case).
2. bump CALCULATOR_VERSION → "t3-bound-v2-conservative-envelope"
3. emit a new KAT fixture under
bench/fixtures/t3-bound/v2-conservative-envelope/
4. keep effective_control_v1 reachable as a backward-compat mode
so v1 rows stay replayable
```
That v2 work is **not in this ticket** — see §10. Until it lands,
read the calculator's output as: "under the v1 effective-control
model, the baseline evaluates to ~626 bits/window; this exceeds
the 256-bit certification threshold so the calculator CANNOT
CERTIFY M2 residual safety at W=10000; a conservative B1 envelope
would produce a larger bound (~5850 bits in the example above)."
--- ---
@ -384,50 +383,70 @@ remains Phase 2 / #000043.
## §6. Combined per-window bound ## §6. Combined per-window bound
Combining §3-§5: Combining §3-§5, with the **default `b1_model = max_envelope`**
(§3.1):
``` ```
I_window ≤ C_B1 · g · W · log₂( SNR_grad + 1 ) B1 = C_B1 · max( g · W · log₂( 1 + ‖∇L_max‖ / σ_grad ), ← fraction_channels
W · log₂( 1 + g·‖∇L_max‖ / σ_grad ) ) ← aggregate_bias
I_window ≤ B1
+ C_B2 · ⌈W / K⌉ · log₂( R ) + C_B2 · ⌈W / K⌉ · log₂( R )
+ C_B3 · ⌈W / E⌉ · log₂( N_b · σ_grad / ‖∇L_max‖ ) / 2 + C_B3 · ⌈W / E⌉ · log₂( N_b · σ_grad / ‖∇L_max‖ ) / 2
``` ```
with conservative constants `C_B1 = C_B2 = C_B3 = 1` (each by with conservative constants `C_B1 = C_B2 = C_B3 = 1` (each by
data-processing inequality; future work may tighten any of them data-processing inequality; #000043 may tighten any of them based
based on empirical loss-surface measurement). on empirical measurement). For typical deployments `aggregate_bias`
dominates `fraction_channels` (because `1/g ≫ log₂(1+G/σ) /
log₂(1+g·G/σ)`), so `B1 ≈ W · log₂(1 + g·‖∇L_max‖/σ_grad)`.
Other `b1_model` choices (`--b1-model`): `effective_control_v1` =
`C_B1 · g · W · log₂(1 + g·‖∇L_max‖/σ_grad)` — the older
non-worst-case effective-control risk score, ~`g`× smaller than
`aggregate_bias`; never use it to *certify*.
--- ---
## §7. Numeric examples ## §7. Numeric examples
All numbers are the calculator's closed-form output under the
default `b1_model = max_envelope`, not rounded estimates; see
`bench/scripts/t3_bound_calculator.py`, `tests/test_t3_bound_calculator.py`,
and the pinned KAT fixture `bench/fixtures/t3-bound/known-answer-tests.jsonl`.
The `effective_control_v1` column shows what the older
non-worst-case model would have produced, for comparison.
### §7.1 Small deployment ### §7.1 Small deployment
``` ```
g = 0.05, ‖∇L_max‖ = 1.0, σ_grad = 0.1 g = 0.05, ‖∇L_max‖ = 1.0, σ_grad = 0.1
K = 100, R = 8, W = 10000, N_b = 1024, E = 1024 K = 100, R = 8, W = 10000, N_b = 1024, E = 1024
SNR_grad = 0.5 snr_grad = g·G/σ = 0.5 snr_per_channel = G/σ = 10.0
B1 = 1 · 0.05 · 10000 · log₂(1.5) ≈ 292.48 bits B1_fraction_channels = 0.05 · 10000 · log₂(11) ≈ 1729.72 bits
B2 = 1 · ⌈10000/100⌉ · log₂(8) = 300.00 bits B1_aggregate_bias = 10000 · log₂(1.5) ≈ 5849.63 bits ← selected (max)
B3 = 1 · ⌈10000/1024⌉ · log₂(102.4) / 2 ≈ 33.39 bits B1 (max_envelope) ≈ 5849.63 bits
total ≈ 625.87 bits/window B2 = ⌈10000/100⌉ · log₂(8) = 300.00 bits
B3 = ⌈10000/1024⌉ · log₂(102.4) / 2 ≈ 33.39 bits
total ≈ 6183.02 bits/window
→ NOT_CERTIFIED_BY_BOUND
(effective_control_v1 B1 would be ≈ 292.48 → total ≈ 625.87)
``` ```
(Numbers are the calculator's closed-form output, not rounded
estimates; see ``bench/scripts/t3_bound_calculator.py`` and the
unit tests in ``tests/test_t3_bound_calculator.py``.)
### §7.2 Medium deployment (longer window) ### §7.2 Medium deployment (longer window)
``` ```
g = 0.05, ‖∇L_max‖ = 1.0, σ_grad = 0.1 g = 0.05, ‖∇L_max‖ = 1.0, σ_grad = 0.1
K = 1000, R = 16, W = 100000, N_b = 8192, E = 8192 K = 1000, R = 16, W = 100000, N_b = 8192, E = 8192
SNR_grad = 0.5 snr_grad = 0.5 snr_per_channel = 10.0
B1 = 1 · 0.05 · 100000 · log₂(1.5) ≈ 2924.81 bits B1_aggregate_bias = 100000 · log₂(1.5) ≈ 58496.25 bits ← selected
B2 = 1 · ⌈100000/1000⌉ · log₂(16) = 400.00 bits B2 = ⌈100000/1000⌉ · log₂(16) = 400.00 bits
B3 = 1 · ⌈100000/8192⌉ · log₂(819.2) / 2 ≈ 62.91 bits B3 = ⌈100000/8192⌉ · log₂(819.2) / 2 ≈ 62.91 bits
total ≈ 3387.72 bits/window total ≈ 58959.16 bits/window
→ NOT_CERTIFIED_BY_BOUND
(effective_control_v1 B1 would be ≈ 2924.81 → total ≈ 3387.72)
``` ```
### §7.3 Hardened deployment (lower g, smaller R) ### §7.3 Hardened deployment (lower g, smaller R)
@ -435,54 +454,78 @@ total ≈ 3387.72 bits/window
``` ```
g = 0.01, ‖∇L_max‖ = 1.0, σ_grad = 0.1 g = 0.01, ‖∇L_max‖ = 1.0, σ_grad = 0.1
K = 100, R = 4, W = 10000, N_b = 1024, E = 1024 K = 100, R = 4, W = 10000, N_b = 1024, E = 1024
SNR_grad = 0.1 snr_grad = 0.1 snr_per_channel = 10.0
B1 = 1 · 0.01 · 10000 · log₂(1.1) ≈ 13.75 bits B1_fraction_channels = 0.01 · 10000 · log₂(11) ≈ 345.94 bits
B2 = 1 · ⌈10000/100⌉ · log₂(4) = 200.00 bits B1_aggregate_bias = 10000 · log₂(1.1) ≈ 1375.04 bits ← selected
B3 = 1 · ⌈10000/1024⌉ · log₂(102.4) / 2 ≈ 33.39 bits B1 (max_envelope) ≈ 1375.04 bits
total ≈ 247.14 bits/window B2 = ⌈10000/100⌉ · log₂(4) = 200.00 bits
B3 = ⌈10000/1024⌉ · log₂(102.4) / 2 ≈ 33.39 bits
total ≈ 1608.43 bits/window
→ NOT_CERTIFIED_BY_BOUND
(effective_control_v1 B1 would be ≈ 13.75 → total ≈ 247.14)
``` ```
Note: under the conservative `max_envelope` model, even the
"hardened" config exceeds 256 bits at W=10000 — the `aggregate_bias`
term `W · log₂(1 + g·G/σ)` grows with `W` regardless of how small
`g` is. Certifying M2 residual safety under this model requires a
**much smaller W** than the effective-control numbers suggested
(see §8).
--- ---
## §8. Operator guidance — choosing window length ## §8. Operator guidance — choosing window length
The operator picks `W` such that `I_window ≤ B_target` where The operator picks `W` such that `I_window ≤ B_target` where
`B_target` is the desired residual. `B_target` is the desired residual. Under the default
`max_envelope` model with the small-deployment constants
(`g=0.05, G=1, σ=0.1, K=100, R=8, E=1024`), `aggregate_bias`
dominates B1, so:
```
I_window ≈ W · log₂(1.5) + (W/100) · 3 + (W/1024) · 3.34/2
= 0.5850 W + 0.0300 W + 0.00163 W
≈ 0.6166 W bits/window
```
**Target = 1 bit/window** (very conservative; adversary needs **Target = 1 bit/window** (very conservative; adversary needs
`≥ 2^256` windows for a specific target): `≥ 2^256` windows for a specific target):
Solving for `W` in §6 with the small-deployment constants:
``` ```
1 ≥ 0.05 · W · 0.58 + (W/100) · 3 + (W/1024) · 3.34 / 2 1 ≥ 0.6166 W → W ≤ 1.6 steps (impractical — re-anchor essentially every step)
1 ≥ 0.029 W + 0.030 W + 0.0016 W
1 ≥ 0.061 W
W ≤ 16 steps (impractical — re-anchor every 16 steps)
``` ```
**Target = 256 bits/window** (the SHA-256 hard-hash output size; **Target = 256 bits/window** (the SHA-256 hard-hash output size):
informational equivalent of a single brute-force preimage
attempt per window):
``` ```
256 ≥ 0.061 W 256 ≥ 0.6166 W → W ≤ 415 steps
W ≤ 4196 steps
``` ```
This is the practical operating range: re-anchor approximately This is the practical operating range under the conservative
every 4000 SGD steps to keep T3's per-window steerage at the model: re-anchor approximately every **400 SGD steps** to keep
SHA-256 baseline. T3's per-window steerage at the SHA-256 baseline. (The earlier
effective-control numbers gave ~4196 steps; the conservative
envelope is ~10× tighter, which is the price of not assuming
which interpretation of `g` holds. An operator who can *measure*
that the effective-control model applies to their deployment can
run `--b1-model effective_control_v1` and use the looser W —
but that is a calibration claim they must justify, not a default.)
**Target = 2^16 = 65536 bits/window** (much larger window, **Target = 2^16 = 65536 bits/window** (much larger window,
adversary still needs ~2^240 windows to brute-force): adversary still needs ~2^240 windows to brute-force):
``` ```
W ≤ 1.07 × 10^6 steps W ≤ 1.06 × 10^5 steps
``` ```
This admits week-long training runs between anchor rotations. This admits roughly day-long training runs between anchor
rotations under the conservative model.
Use `python -m bench.scripts.t3_bound_calculator` with your
deployment's `g / G / σ / K / R / W / N_b / E` to read off the
exact `certification_status` and per-bandwidth breakdown rather
than working the algebra above by hand.
--- ---
@ -501,32 +544,20 @@ is the explicit form. Reference: this doc §6.
## §10. Open questions + future work ## §10. Open questions + future work
Items 1-2 below are the **closure blockers** flagged by dav1d's **Closure-blocker status.** dav1d's 2026-05-11 review flagged two
2026-05-11 review; items 3-6 are tightening paths that refine blockers — the B1 model not being worst-case, and the KAT fixture
the bound without invalidating it. being skip-if-missing. **Both resolved 2026-05-11** (§10.1):
Option B applied *in v1* (per fox's direction — no v2 fork), so
the default `b1_model` is now `max_envelope` (§3.1); the KAT
fixture was regenerated (12 entries) and `test_t3_bound_known_answer_tests`
now runs rather than skips. What remains for closure is fox's
final close-or-iterate call (optionally a dav1d re-review of the
envelope formula itself).
1. **B1 conservative envelope (v2 calculator) — closure blocker.** Items 1-5 below are tightening paths that refine the bound
The current `b1_model="effective_control_v1"` (§3.1) reads `g` without invalidating it:
as a combined direction-fraction + amplitude-shrinkage
coefficient, which makes the headline B1 ~292 bits on the 1. **C_B1 below the data-processing limit.** The discrete
baseline. A worst-case gradient adversary needs the
`max_envelope` model (~5850 bits on the same baseline). Until
the v2 calculator with `b1_model` selection lands —
`CALCULATOR_VERSION → t3-bound-v2-conservative-envelope`, new
KAT fixture under `bench/fixtures/t3-bound/v2-conservative-envelope/`,
`effective_control_v1` kept as a backward-compat mode — the
calculator's `certification_status` is relative to the v1
model only and should be read as an operational risk score,
not a certified worst-case bound. **Do not close #000036
until this is resolved** (either by landing v2 or by an
explicit team decision to keep v1 with the narrowed-semantics
caveat documented in §3.1).
2. **Active KAT fixture for closure.** `bench/fixtures/t3-bound/known-answer-tests.jsonl`
must exist and `test_t3_bound_known_answer_tests` must run
(not skip) with ≥ 5 entries before #000036 closes. If the v2
B1 model lands first, the KAT fixture goes under the
versioned subdirectory.
3. **C_B1 below the data-processing limit.** The discrete
channel-capacity bound `log₂(SNR_grad + 1)` is a per-step channel-capacity bound `log₂(SNR_grad + 1)` is a per-step
ceiling derived under uniform-prior signal levels; tighter ceiling derived under uniform-prior signal levels; tighter
bounds are possible if the loss surface has reduced bounds are possible if the loss surface has reduced
@ -534,22 +565,22 @@ the bound without invalidating it.
deficiency). Empirical measurement via #000034's probe deficiency). Empirical measurement via #000034's probe
could tighten C_B1 by 1-2 orders of magnitude on typical could tighten C_B1 by 1-2 orders of magnitude on typical
deployments. (Tracked under #000043.) deployments. (Tracked under #000043.)
4. **C_B2 below 1.** Many LR choices map to similar 2. **C_B2 below 1.** Many LR choices map to similar
trajectories; a deployment-specific empirical measurement trajectories; a deployment-specific empirical measurement
of LR-trajectory diversity (1-Wasserstein distance between of LR-trajectory diversity (1-Wasserstein distance between
`(LR_1, LR_2, … LR_R)` final-checkpoint distributions) `(LR_1, LR_2, … LR_R)` final-checkpoint distributions)
yields C_B2 < 1. (Tracked under #000043.) yields C_B2 < 1. (Tracked under #000043.)
5. **C_B3 closer to the random-shuffle baseline.** If the 3. **C_B3 closer to the random-shuffle baseline.** If the
deployment's SGD is random-shuffle (most modern training is), deployment's SGD is random-shuffle (most modern training is),
the adversarial-order bound used here over-estimates by the adversarial-order bound used here over-estimates by
`O(√N_b)` factor. C_B3 → `O(1/√N_b)`. (Tracked under #000043; `O(√N_b)` factor. C_B3 → `O(1/√N_b)`. (Tracked under #000043;
the cheapest of the three constant-tightening paths — needs the cheapest of the three constant-tightening paths — needs
only a DataLoader-config audit, no checkpoint.) only a DataLoader-config audit, no checkpoint.)
6. **Future B4-B5 control surfaces.** Adaptive optimizer state 4. **Future B4-B5 control surfaces.** Adaptive optimizer state
manipulation (momentum, second-moment estimates) is not in manipulation (momentum, second-moment estimates) is not in
the §1 model. The framework here generalizes — add new B_i the §1 model. The framework here generalizes — add new B_i
terms as new T3 control surfaces are documented. terms as new T3 control surfaces are documented.
7. **Empirical validation.** This bound has not been validated 5. **Empirical validation.** This bound has not been validated
against an actual adversarial-training experiment. The against an actual adversarial-training experiment. The
acceptance criterion (§5 of the source ticket) explicitly acceptance criterion (§5 of the source ticket) explicitly
marks empirical validation as out-of-scope; landing the marks empirical validation as out-of-scope; landing the
@ -557,31 +588,52 @@ the bound without invalidating it.
#000034's Phase 1b would feed directly into a future #000034's Phase 1b would feed directly into a future
empirical-validation ticket. empirical-validation ticket.
### §10.1 Calculator hardening landed 2026-05-11 (dav1d review) ### §10.1 dav1d-review changes landed 2026-05-11
Not "open" — already done in the `8916bf3` follow-up + the Not "open" — already done (Tier-1 in `da62f80`, Option B / Tier-2
2026-05-11 review pass: in the follow-up commit):
- **B1 model = `max_envelope` (Option B, applied in v1).** The
default `b1_model` takes `max(fraction_channels, aggregate_bias)`
— genuinely upper-bounding across both interpretations of `g`
(§3.1). `effective_control_v1` / `fraction_channels` /
`aggregate_bias` reachable via `--b1-model`. Every output reports
all three concrete B1 variants + `b1_selected` + both SNR
readings (`snr_grad`, `snr_per_channel`). `b1_model` is echoed in
`inputs` so KAT replays are unambiguous. Applied by changing the
v1 default rather than forking a v2 (per fox's direction):
`CALCULATOR_VERSION` stays `t3-bound-v1-bottou-refinement` (the
"bottou-refinement" descriptor names the unchanged B3 term).
- **KAT fixture regenerated** (`bench/fixtures/t3-bound/known-answer-tests.jsonl`,
12 entries: §7 worked examples under `max_envelope`, explicit-mode
pins for the other three models, a `g=0` edge case).
`test_t3_bound_known_answer_tests` now runs (no longer skips);
it pins `b1_model`, `b1_selected`, `certification_status`, and
the per-contribution numbers.
- Recommendation wording: "M2's single-window guarantee is - Recommendation wording: "M2's single-window guarantee is
broken" → "this conservative bound CANNOT CERTIFY M2's broken" → "this conservative bound CANNOT CERTIFY M2's
residual" (an upper bound exceeding 256 means we cannot residual" (an upper bound exceeding 256 means we cannot
certify, not that the adversary can steer 256 bits). certify, not that the adversary can steer 256 bits).
- Structured output fields: `b1_model`, `certification_status` - Structured output fields: `b1_model`, `b1_selected`,
∈ {`CERTIFIED_BY_BOUND`, `NOT_CERTIFIED_BY_BOUND`}, `certification_status` ∈ {`CERTIFIED_BY_BOUND`,
`certification_threshold_bits`, `model_assumptions[]` — so `NOT_CERTIFIED_BY_BOUND`}, `certification_threshold_bits`,
callers read a machine-readable status, not just prose. `model_assumptions[]`, `B1_fraction_channels`,
`B1_aggregate_bias`, `B1_effective_control_v1`, `snr_per_channel`
— callers read a machine-readable status + the full B1 spread,
not just prose.
- Input validation: bools rejected for both int and float fields - Input validation: bools rejected for both int and float fields
(`isinstance(True, int)` is True in Python — a real leak risk (`isinstance(True, int)` is True in Python — a real leak risk
for a security calculator); NaN / ±inf rejected for every for a security calculator); NaN / ±inf rejected for every
numeric input and constant. numeric input and constant; invalid `b1_model` rejected.
- `gradient_fraction = 0` now accepted (no T2 surface; B1 = 0; - `gradient_fraction = 0` now accepted (no T2 surface; B1 = 0;
T3's LR + batch-order channels still contribute) — improves T3's LR + batch-order channels still contribute) — improves
component isolation. component isolation.
- Tests: hard-coded `cwd="/home/fox/git/arborist"` replaced with - Tests: hard-coded `cwd="/home/fox/git/arborist"` replaced with
`pathlib.Path(__file__).resolve().parents[1]` so the suite `pathlib.Path(__file__).resolve().parents[1]` so the suite
runs on any checkout. New bool/NaN/inf rejection tests, runs on any checkout. New bool/NaN/inf rejection tests, `g=0`
`g=0` acceptance test, `certification_status` field tests. acceptance test, `certification_status` field tests, per-model
Suite count 53 → 75. B1 hand-formula tests, `--b1-model` CLI test, invalid-`b1_model`
rejection test. Suite count 53 → 83.
--- ---
@ -592,22 +644,24 @@ The closed-form bound from §6 lands as
```bash ```bash
$ python -m bench.scripts.t3_bound_calculator \ $ python -m bench.scripts.t3_bound_calculator \
--gradient-fraction 0.05 \ --gradient-fraction 0.05 --gradient-norm-max 1.0 \
--gradient-norm-max 1.0 \ --gradient-noise-stddev 0.1 --lr-decision-interval 100 \
--gradient-noise-stddev 0.1 \ --lr-grid-size 8 --window-length 10000 \
--lr-decision-interval 100 \ --batches-per-epoch 1024 --steps-per-epoch 1024
--lr-grid-size 8 \ # [--b1-model max_envelope] ← the default
--window-length 10000 \
--batches-per-epoch 1024 \
--steps-per-epoch 1024
{ {
"calculator_version": "t3-bound-v1-bottou-refinement", "calculator_version": "t3-bound-v1-bottou-refinement",
"b1_model": "effective_control_v1", "b1_model": "max_envelope",
"I_window_bits_upper_bound": 625.8716, "b1_selected": "aggregate_bias",
"B1_contribution": 292.4813, "I_window_bits_upper_bound": 6183.0154,
"B1_contribution": 5849.625,
"B1_fraction_channels": 1729.7158,
"B1_aggregate_bias": 5849.625,
"B1_effective_control_v1": 292.4813,
"B2_contribution": 300.0, "B2_contribution": 300.0,
"B3_contribution": 33.3904, "B3_contribution": 33.3904,
"snr_grad": 0.5, "snr_grad": 0.5,
"snr_per_channel": 10.0,
"decisions_in_window": 100, "decisions_in_window": 100,
"epochs_in_window": 10, "epochs_in_window": 10,
"constants": {"C_B1": 1.0, "C_B2": 1.0, "C_B3": 1.0}, "constants": {"C_B1": 1.0, "C_B2": 1.0, "C_B3": 1.0},
@ -616,11 +670,11 @@ $ python -m bench.scripts.t3_bound_calculator \
"model_assumptions": [ "model_assumptions": [
"M2_nonce_per_window", "M2_nonce_per_window",
"SHA256_random_oracle_baseline", "SHA256_random_oracle_baseline",
"B1_effective_control_model_v1", "B1_model_max_envelope",
"B3_gradient_noise_refinement" "B3_gradient_noise_refinement"
], ],
"inputs": { "...echoed input tuple..." }, "inputs": { "...echoed input tuple incl. c_b1/c_b2/c_b3 + b1_model..." },
"recommendation": "I_window upper bound ≈ 625.9 bits/window "recommendation": "I_window upper bound ≈ 6183.0 bits/window
EXCEEDS the SHA-256 (256 bit) certification EXCEEDS the SHA-256 (256 bit) certification
threshold. This conservative bound CANNOT threshold. This conservative bound CANNOT
CERTIFY M2's single-window residual at this W CERTIFY M2's single-window residual at this W
@ -632,14 +686,16 @@ $ python -m bench.scripts.t3_bound_calculator \
} }
``` ```
The above example shows a deployment whose per-window bound The above shows the default `max_envelope` model: `B1 =
exceeds 256 bits **under the `effective_control_v1` B1 model** — aggregate_bias` = 5849.6 bits (the larger of the two envelope
`certification_status` is `NOT_CERTIFIED_BY_BOUND` and the W of terms; `fraction_channels` = 1729.7) → total 6183.0 bits/window,
10000 is too large for a 1-window SHA-256-resistance certification. `NOT_CERTIFIED_BY_BOUND` at W=10000. All three B1 variants
A conservative `max_envelope` B1 model (§3.1) would produce a (including `B1_effective_control_v1` = 292.5, what the older
larger bound (~5850 bits in the worked example). Operators read risk-score model would have given) are reported regardless of
the structured `certification_status` field, not just the prose, which `b1_model` is selected. Pass `--b1-model effective_control_v1`
and adjust W (or g, R, K) to tune. (or `fraction_channels` / `aggregate_bias`) to switch the selected
term. Operators read the structured `certification_status` field,
not just the prose, and adjust W (or g, R, K) to tune — see §8.
--- ---
@ -660,5 +716,6 @@ and adjust W (or g, R, K) to tune.
stability framework the §5 C_B3 random-shuffle reasoning draws on. stability framework the §5 C_B3 random-shuffle reasoning draws on.
- dav1d review 2026-05-11 (`RESPONSE_1` + `RESPONSE_2`) — the - dav1d review 2026-05-11 (`RESPONSE_1` + `RESPONSE_2`) — the
B1-double-`g` finding (§3.1), the recommendation-wording B1-double-`g` finding (§3.1), the recommendation-wording
correction, validation hardening, and the v2 conservative- correction, validation hardening, and the conservative
envelope path (§10 item 1). `max_envelope` B1 model. All applied in v1 2026-05-11 (Tier-1 +
Option B); see §3.1 + §10.1.

View file

@ -1,6 +1,6 @@
# Ticket #000036 — T3 per-window covert-channel budget bound # Ticket #000036 — T3 per-window covert-channel budget bound
**Status:** in progress · Phase 1 (formal derivation + calculator) landed 2026-05-10; **dav1d review returned 2026-05-11** (`RESPONSE_1` + `RESPONSE_2`); **Tier-1 polish applied 2026-05-11** (recommendation wording → "CANNOT CERTIFY", structured `certification_status` / `b1_model` / `model_assumptions` output fields, bool/NaN/inf validation hardening, `g=0` accepted, hard-coded test cwd removed; test suite 53 → 75); **closure blockers remaining**: (1) B1 conservative-envelope = v2 calculator (`b1_model=max_envelope`, `CALCULATOR_VERSION → t3-bound-v2-conservative-envelope`, versioned KAT fixture) — awaits fox go/no-go on Tier 2; (2) active KAT fixture (`bench/fixtures/t3-bound/known-answer-tests.jsonl` must exist + test must run not skip, ≥ 5 entries). Empirical constant-tightening tracked separately under #000043. R2's architectural integrations (Merkle audit-event commitment, SQD canonicalization, CTI clause-lattice, 5F trigger, ForkScore security-risk) are out-of-scope here — separate tickets if wanted. **Status:** in progress · Phase 1 (formal derivation + calculator) landed 2026-05-10; **dav1d review returned 2026-05-11** (`RESPONSE_1` + `RESPONSE_2`) → **Tier-1 + Tier-2 both applied 2026-05-11**. Tier-1: recommendation wording → "CANNOT CERTIFY", structured `certification_status` / `b1_model` / `b1_selected` / `model_assumptions` output fields, bool/NaN/inf validation hardening, `g=0` accepted, hard-coded test cwd removed. **Tier-2 = dav1d Option B applied *in v1* (per fox — no v2 fork)**: default `b1_model` is now `max_envelope` = `max(fraction_channels, aggregate_bias)` (genuinely upper-bounding across both interpretations of `g`); `effective_control_v1` / `fraction_channels` / `aggregate_bias` reachable via `--b1-model`; every output reports all three B1 variants + both SNR readings; `CALCULATOR_VERSION` unchanged (`t3-bound-v1-bottou-refinement` — the descriptor names the unchanged B3 term, and `b1_model` echoed in `inputs` disambiguates KAT replays). **KAT fixture regenerated 2026-05-11** (12 entries; `test_t3_bound_known_answer_tests` now runs, not skips). Baseline I_window: 625.87 (effective_control_v1) → **6183.02 (max_envelope default)**. Test suite 53 → 83. **Both prior closure blockers cleared**; remaining = fox's final close-or-iterate call (optionally a dav1d re-review of the envelope formula). Empirical constant-tightening tracked separately under #000043. R2's architectural integrations (Merkle audit-event commitment, SQD canonicalization, CTI clause-lattice, 5F trigger, ForkScore security-risk) out-of-scope here — separate tickets if wanted.
**Opened:** 2026-05-09 **Opened:** 2026-05-09
**Scope:** Derive an explicit closed-form upper bound on the covert- **Scope:** Derive an explicit closed-form upper bound on the covert-
channel capacity under threat model T3 (hyperparameter adversary), channel capacity under threat model T3 (hyperparameter adversary),

View file

@ -600,7 +600,7 @@ than waiting for bench-time STRICT-rate drift to surface it.
W concentration + dim_h, closure (a_top + a_bot ≡ W concentration + dim_h, closure (a_top + a_bot ≡
full-spectrum on dense decomposition), Lanczos eigenvalue full-spectrum on dense decomposition), Lanczos eigenvalue
ordering invariant. ordering invariant.
- `tests/test_t3_bound_calculator.py` — **<!--AUTOCOUNT:tests:tests/test_t3_bound_calculator.py-->75<!--/AUTOCOUNT--> tests** (was 51; - `tests/test_t3_bound_calculator.py` — **<!--AUTOCOUNT:tests:tests/test_t3_bound_calculator.py-->83<!--/AUTOCOUNT--> tests** (was 51;
+2 from `581ad90` 2026-05-10 KAT-fixture-gap closure) for the +2 from `581ad90` 2026-05-10 KAT-fixture-gap closure) for the
T3 per-window covert-channel bound calculator (#000036 §11); T3 per-window covert-channel bound calculator (#000036 §11);
pins the closed-form B1/B2/B3 formulas, monotonicity in each pins the closed-form B1/B2/B3 formulas, monotonicity in each
@ -674,7 +674,7 @@ than waiting for bench-time STRICT-rate drift to surface it.
| aliases.py | 512 | 469 (<!--AUTOCOUNT:tests:tests/test_aliases.py-->28<!--/AUTOCOUNT--> tests) | 0.92 | | aliases.py | 512 | 469 (<!--AUTOCOUNT:tests:tests/test_aliases.py-->28<!--/AUTOCOUNT--> tests) | 0.92 |
| warrant_resolver.py | ~800 | ~430 (combined) | 0.54 | | warrant_resolver.py | ~800 | ~430 (combined) | 0.54 |
| warrant_chain.py | 89 | 320 (<!--AUTOCOUNT:tests:tests/test_warrant_chain.py-->9<!--/AUTOCOUNT--> tests) | 3.6 | | warrant_chain.py | 89 | 320 (<!--AUTOCOUNT:tests:tests/test_warrant_chain.py-->9<!--/AUTOCOUNT--> tests) | 3.6 |
| t3_bound_calculator.py | 249 | 446 (<!--AUTOCOUNT:tests:tests/test_t3_bound_calculator.py-->75<!--/AUTOCOUNT--> tests) | 1.79 | | t3_bound_calculator.py | 249 | 446 (<!--AUTOCOUNT:tests:tests/test_t3_bound_calculator.py-->83<!--/AUTOCOUNT--> tests) | 1.79 |
| fork_score.py | 386 | 609 (<!--AUTOCOUNT:tests:tests/test_fork_score.py-->23<!--/AUTOCOUNT--> tests) | 1.58 | | fork_score.py | 386 | 609 (<!--AUTOCOUNT:tests:tests/test_fork_score.py-->23<!--/AUTOCOUNT--> tests) | 1.58 |
| weights.py | 73 | 180 (<!--AUTOCOUNT:tests:tests/test_weights.py-->16<!--/AUTOCOUNT--> tests) | 2.5 | | weights.py | 73 | 180 (<!--AUTOCOUNT:tests:tests/test_weights.py-->16<!--/AUTOCOUNT--> tests) | 2.5 |
| pi_star/protocol+registry | 124 | 280 (<!--AUTOCOUNT:tests:tests/test_pi_star_protocol_and_registry.py-->21<!--/AUTOCOUNT--> tests) | 2.3 | | pi_star/protocol+registry | 124 | 280 (<!--AUTOCOUNT:tests:tests/test_pi_star_protocol_and_registry.py-->21<!--/AUTOCOUNT--> tests) | 2.3 |

View file

@ -51,32 +51,45 @@ _BASELINE = dict(
def test_baseline_matches_section_11_doc(): def test_baseline_matches_section_11_doc():
"""The §11 worked example baseline. Calculator's actual numbers: """The §11 worked example baseline under the default b1_model=
"max_envelope" (dav1d review 2026-05-11). Calculator's actual numbers:
I_window_bits_upper_bound: 625.8716 I_window_bits_upper_bound: 6183.0154
B1_contribution: 292.4813 B1_contribution: 5849.625 (aggregate_bias selected)
B2_contribution: 300.0 B1_fraction_channels: 1729.7158
B3_contribution: 33.3904 B1_aggregate_bias: 5849.625
snr_grad: 0.5 B1_effective_control_v1: 292.4813 (the older non-worst-case)
B2_contribution: 300.0
B3_contribution: 33.3904
snr_grad: 0.5 (g·G/σ)
snr_per_channel: 10.0 (G/σ)
Doc §11's quoted 622.7 / 290.0 / 32.7 are first-cut rounded The conservative envelope takes max(fraction_channels, aggregate_bias);
estimates; calculator's actual closed-form values differ by at this baseline aggregate_bias (5849.6) dominates fraction_channels
~3 bits total due to the doc's 290 vs actual 292.5 in B1 and (1729.7). The old effective_control formula (292.5) is still reported
32.7 vs actual 33.4 in B3. This test pins the closed-form as B1_effective_control_v1 for comparison.
truth (the doc text needs a calibration pass; tracked in this
test's docstring as a follow-up).
""" """
r = t3_bound_bits(**_BASELINE) r = t3_bound_bits(**_BASELINE)
# Total: ⟨B1+B2+B3⟩ ≈ 292.48 + 300.0 + 33.39 = 625.87 assert r["b1_model"] == "max_envelope"
assert r["I_window_bits_upper_bound"] == pytest.approx(625.87, abs=0.05) assert r["b1_selected"] == "aggregate_bias"
# Total: ⟨B1+B2+B3⟩ ≈ 5849.63 + 300.0 + 33.39 = 6183.02
assert r["I_window_bits_upper_bound"] == pytest.approx(6183.02, abs=0.05)
# B2 is exact: ⌈10000/100⌉ · log₂(8) = 100 · 3 = 300 # B2 is exact: ⌈10000/100⌉ · log₂(8) = 100 · 3 = 300
assert r["B2_contribution"] == pytest.approx(300.0, abs=1e-3) assert r["B2_contribution"] == pytest.approx(300.0, abs=1e-3)
# B3: epochs = ⌈10000/1024⌉ = 10; per-epoch factor = 1024·0.1/1.0 = 102.4; # B3: epochs = ⌈10000/1024⌉ = 10; per-epoch factor = 1024·0.1/1.0 = 102.4;
# log₂(102.4)/2 ≈ 3.339; total ≈ 33.39 bits. # log₂(102.4)/2 ≈ 3.339; total ≈ 33.39 bits.
assert r["B3_contribution"] == pytest.approx(33.39, abs=0.05) assert r["B3_contribution"] == pytest.approx(33.39, abs=0.05)
# B1: C_B1 · g · W · log₂(SNR+1) where SNR = 0.05·1.0/0.1 = 0.5 # B1 (max_envelope): aggregate_bias = W·log₂(1 + g·G/σ) = 10000·log₂(1.5)
# → log₂(1.5) ≈ 0.585; total ≈ 1.0 · 0.05 · 10000 · 0.585 = 292.48 # ≈ 10000·0.585 = 5849.63 (> fraction_channels 1729.72).
assert r["B1_contribution"] == pytest.approx(292.48, abs=0.05) assert r["B1_contribution"] == pytest.approx(5849.63, abs=0.05)
assert r["B1_aggregate_bias"] == pytest.approx(5849.63, abs=0.05)
# fraction_channels = g·W·log₂(1 + G/σ) = 0.05·10000·log₂(11) ≈ 1729.72
assert r["B1_fraction_channels"] == pytest.approx(1729.72, abs=0.05)
# effective_control_v1 (old formula) still reported: g·W·log₂(1+g·G/σ)
# = 0.05·10000·log₂(1.5) ≈ 292.48
assert r["B1_effective_control_v1"] == pytest.approx(292.48, abs=0.05)
assert r["snr_grad"] == pytest.approx(0.5, abs=1e-6) # g·G/σ
assert r["snr_per_channel"] == pytest.approx(10.0, abs=1e-6) # G/σ
def test_returns_calculator_version_token(): def test_returns_calculator_version_token():
@ -289,15 +302,17 @@ def test_recommendation_total_le_zero():
def test_recommendation_below_sha256(): def test_recommendation_below_sha256():
"""Baseline (~622 bits) actually exceeds 256 — wrong band for """The default-baseline bound exceeds 256 under max_envelope; use a
this test. Use a config that lands in the (0, 256) range.""" small W that lands in the (0, 256) certified band. At W=300:
args = {**_BASELINE, "window_length": 1000} aggregate_bias ≈ 175.5, B2 = 9, B3 ≈ 3.3 → total ≈ 187.8."""
args = {**_BASELINE, "window_length": 300}
r = t3_bound_bits(**args) r = t3_bound_bits(**args)
assert 0 < r["I_window_bits_upper_bound"] < 256, ( assert 0 < r["I_window_bits_upper_bound"] < 256, (
f"window_length=1000 should land in (0, 256); got {r['I_window_bits_upper_bound']}" f"window_length=300 should land in (0, 256); got {r['I_window_bits_upper_bound']}"
) )
assert "windows" in r["recommendation"] assert "windows" in r["recommendation"]
assert "256" in r["recommendation"] assert "256" in r["recommendation"]
assert r["certification_status"] == "CERTIFIED_BY_BOUND"
def test_recommendation_exceeds_sha256(): def test_recommendation_exceeds_sha256():
@ -315,22 +330,29 @@ def test_recommendation_exceeds_sha256():
def test_output_carries_b1_model_and_certification_fields(): def test_output_carries_b1_model_and_certification_fields():
"""Structured machine-readable fields added per dav1d review """Structured machine-readable fields (dav1d review 2026-05-11):
2026-05-11: b1_model, certification_status, b1_model, b1_selected, certification_status,
certification_threshold_bits, model_assumptions.""" certification_threshold_bits, model_assumptions, plus all three
B1 model variants + both SNR readings."""
r = t3_bound_bits(**_BASELINE) r = t3_bound_bits(**_BASELINE)
assert r["b1_model"] == "effective_control_v1" assert r["b1_model"] == "max_envelope" # the new default
assert r["b1_selected"] in {"fraction_channels", "aggregate_bias"}
assert r["certification_threshold_bits"] == 256 assert r["certification_threshold_bits"] == 256
assert r["certification_status"] in { assert r["certification_status"] in {
"CERTIFIED_BY_BOUND", "NOT_CERTIFIED_BY_BOUND" "CERTIFIED_BY_BOUND", "NOT_CERTIFIED_BY_BOUND"
} }
assert "B1_effective_control_model_v1" in r["model_assumptions"] assert "B1_model_max_envelope" in r["model_assumptions"]
# all three B1 variants reported regardless of which is selected
for k in ("B1_fraction_channels", "B1_aggregate_bias",
"B1_effective_control_v1", "snr_per_channel"):
assert k in r, f"missing output field {k!r}"
assert r["certification_status"] == "NOT_CERTIFIED_BY_BOUND" # baseline > 256 assert r["certification_status"] == "NOT_CERTIFIED_BY_BOUND" # baseline > 256
def test_certification_status_certified_below_threshold(): def test_certification_status_certified_below_threshold():
"""A config landing in (0, 256) → CERTIFIED_BY_BOUND.""" """A config landing in (0, 256) → CERTIFIED_BY_BOUND. W=300 under
r = t3_bound_bits(**{**_BASELINE, "window_length": 1000}) max_envelope yields ~188 bits."""
r = t3_bound_bits(**{**_BASELINE, "window_length": 300})
assert 0 < r["I_window_bits_upper_bound"] < 256 assert 0 < r["I_window_bits_upper_bound"] < 256
assert r["certification_status"] == "CERTIFIED_BY_BOUND" assert r["certification_status"] == "CERTIFIED_BY_BOUND"
@ -357,8 +379,34 @@ def test_cli_baseline_runs_clean(tmp_path):
cwd=REPO_ROOT) cwd=REPO_ROOT)
j = json.loads(out.stdout) j = json.loads(out.stdout)
assert j["calculator_version"] == CALCULATOR_VERSION assert j["calculator_version"] == CALCULATOR_VERSION
# Closed-form actual; doc §11's 622.7 is approximate. assert j["b1_model"] == "max_envelope" # CLI default
assert j["I_window_bits_upper_bound"] == pytest.approx(625.87, abs=0.05) # Closed-form actual under max_envelope: 5849.63 + 300.0 + 33.39 = 6183.02
assert j["I_window_bits_upper_bound"] == pytest.approx(6183.02, abs=0.05)
def test_cli_b1_model_flag():
"""--b1-model effective_control_v1 reverts to the older formula;
--b1-model fraction_channels picks that envelope term."""
base_cmd = [
sys.executable, "-m", "bench.scripts.t3_bound_calculator",
"--gradient-fraction", "0.05", "--gradient-norm-max", "1.0",
"--gradient-noise-stddev", "0.1", "--lr-decision-interval", "100",
"--lr-grid-size", "8", "--window-length", "10000",
"--batches-per-epoch", "1024", "--steps-per-epoch", "1024",
]
for model, expected_b1 in [
("effective_control_v1", 292.48),
("fraction_channels", 1729.72),
("aggregate_bias", 5849.63),
]:
out = subprocess.run(base_cmd + ["--b1-model", model],
capture_output=True, text=True, check=True,
cwd=REPO_ROOT)
j = json.loads(out.stdout)
assert j["b1_model"] == model
assert j["B1_contribution"] == pytest.approx(expected_b1, abs=0.05), (
f"b1_model={model}: B1={j['B1_contribution']} vs expected {expected_b1}"
)
def test_cli_invalid_input_exits_2(): def test_cli_invalid_input_exits_2():
@ -404,24 +452,59 @@ def test_b2_exact_formula():
) )
def test_b1_exact_formula(): def test_b1_effective_control_v1_exact_formula():
"""B1 = C_B1 · g · W · log₂(SNR + 1) where SNR = g·‖∇L_max‖/σ_grad. """b1_model="effective_control_v1": B1 = C_B1 · g · W · log₂(SNR+1)
where SNR = g·‖∇L_max‖/σ_grad (the older non-worst-case formula).
Hand-compute for one config and check exact agreement.""" Hand-compute for one config and check exact agreement."""
g, gnm, sigma, W = 0.1, 2.0, 0.5, 5000 g, gnm, sigma, W = 0.1, 2.0, 0.5, 5000
snr = g * gnm / sigma # 0.4 snr = g * gnm / sigma # 0.4
expected = 1.0 * g * W * math.log2(snr + 1) expected = 1.0 * g * W * math.log2(snr + 1)
r = t3_bound_bits(**{ r = t3_bound_bits(**{
**_BASELINE, **_BASELINE,
"gradient_fraction": g, "gradient_fraction": g, "gradient_norm_max": gnm,
"gradient_norm_max": gnm, "gradient_noise_stddev": sigma, "window_length": W,
"gradient_noise_stddev": sigma, "b1_model": "effective_control_v1",
"window_length": W,
}) })
# Output rounded to 4 dp inside the calculator. assert r["b1_model"] == "effective_control_v1"
assert r["b1_selected"] == "effective_control_v1"
assert r["B1_contribution"] == pytest.approx(expected, abs=1e-3) assert r["B1_contribution"] == pytest.approx(expected, abs=1e-3)
assert r["B1_effective_control_v1"] == pytest.approx(expected, abs=1e-3)
assert r["snr_grad"] == pytest.approx(snr, abs=1e-3) assert r["snr_grad"] == pytest.approx(snr, abs=1e-3)
def test_b1_max_envelope_exact_formula():
"""b1_model="max_envelope" (default): B1 = max(fraction_channels,
aggregate_bias) where
fraction_channels = C_B1 · g · W · log₂(1 + G/σ)
aggregate_bias = C_B1 · W · log₂(1 + g·G/σ)
Hand-compute for one config; verify the larger term is selected."""
g, gnm, sigma, W = 0.1, 2.0, 0.5, 5000
snr_per_channel = gnm / sigma # 4.0
snr_grad = g * gnm / sigma # 0.4
fc = 1.0 * g * W * math.log2(snr_per_channel + 1) # 0.1·5000·log₂(5) ≈ 1160.96
ab = 1.0 * W * math.log2(snr_grad + 1) # 5000·log₂(1.4) ≈ 2426.26
expected_b1 = max(fc, ab)
expected_selected = "aggregate_bias" if ab >= fc else "fraction_channels"
r = t3_bound_bits(**{
**_BASELINE,
"gradient_fraction": g, "gradient_norm_max": gnm,
"gradient_noise_stddev": sigma, "window_length": W,
# b1_model defaults to max_envelope
})
assert r["b1_model"] == "max_envelope"
assert r["b1_selected"] == expected_selected
assert r["B1_contribution"] == pytest.approx(expected_b1, abs=1e-3)
assert r["B1_fraction_channels"] == pytest.approx(fc, abs=1e-3)
assert r["B1_aggregate_bias"] == pytest.approx(ab, abs=1e-3)
assert r["snr_per_channel"] == pytest.approx(snr_per_channel, abs=1e-3)
@pytest.mark.parametrize("bad", ["v2", "envelope", "", "MAX_ENVELOPE", None, 1])
def test_invalid_b1_model_rejected(bad):
with pytest.raises(ValueError, match="b1_model"):
t3_bound_bits(**{**_BASELINE, "b1_model": bad})
# --- integration with §6 framework ----------------------------------- # --- integration with §6 framework -----------------------------------
@ -504,6 +587,21 @@ def test_t3_bound_known_answer_tests():
Closes the calculator-test-patterns.md §1 checklist gap (no Closes the calculator-test-patterns.md §1 checklist gap (no
KAT fixture for this calculator). KAT fixture for this calculator).
""" """
# Numeric fields checked on every KAT entry.
_NUMERIC = [
("expected_total", "I_window_bits_upper_bound"),
("expected_b1", "B1_contribution"),
("expected_b2", "B2_contribution"),
("expected_b3", "B3_contribution"),
("expected_snr_grad", "snr_grad"),
]
# Optional numeric fields (present in 2026-05-11+ fixtures).
_NUMERIC_OPT = [
("expected_b1_fraction_channels", "B1_fraction_channels"),
("expected_b1_aggregate_bias", "B1_aggregate_bias"),
("expected_b1_effective_control_v1", "B1_effective_control_v1"),
("expected_snr_per_channel", "snr_per_channel"),
]
n_kats = 0 n_kats = 0
for line in KAT_FIXTURE.read_text(encoding="utf-8").splitlines(): for line in KAT_FIXTURE.read_text(encoding="utf-8").splitlines():
line = line.strip() line = line.strip()
@ -517,13 +615,27 @@ def test_t3_bound_known_answer_tests():
f"recorded {kat['calculator_version']}, " f"recorded {kat['calculator_version']}, "
f"function {r['calculator_version']}" f"function {r['calculator_version']}"
) )
for field, key in [ # b1_model + b1_selected pinned when recorded.
("expected_total", "I_window_bits_upper_bound"), if "b1_model" in kat:
("expected_b1", "B1_contribution"), assert r["b1_model"] == kat["b1_model"], (
("expected_b2", "B2_contribution"), f"KAT b1_model mismatch on {kat['label']!r}: "
("expected_b3", "B3_contribution"), f"recorded {kat['b1_model']}, function {r['b1_model']}"
("expected_snr_grad", "snr_grad"), )
]: if "expected_b1_selected" in kat:
assert r["b1_selected"] == kat["expected_b1_selected"], (
f"KAT b1_selected mismatch on {kat['label']!r}: "
f"recorded {kat['expected_b1_selected']}, "
f"function {r['b1_selected']}"
)
if "expected_certification_status" in kat:
assert r["certification_status"] == kat["expected_certification_status"], (
f"KAT certification_status mismatch on {kat['label']!r}: "
f"recorded {kat['expected_certification_status']}, "
f"function {r['certification_status']}"
)
for field, key in _NUMERIC + _NUMERIC_OPT:
if field not in kat:
continue
recorded = float(kat[field]) recorded = float(kat[field])
observed = float(r[key]) observed = float(r[key])
assert observed == pytest.approx(recorded, abs=1e-3), ( assert observed == pytest.approx(recorded, abs=1e-3), (