F11: demote web_ui's per-gap keyframe request (measured on air, default off) - #91
Merged
Conversation
The gap-tolerant canvas requests a keyframe on EVERY base_seq gap, including a single lost delta frame (two such on-air events in the F10 surgical window, each granted a multi-frame keyframe train; the 10 s KeyframeRequester throttle is the only damper). F10's 0x6C stale-tile path now detects and repairs exactly that damage tile-by-tile, making the per-gap keyframe largely redundant. Canvas now reports structured causes on CanvasUpdate (seq_gap, tile_error) so the policy layer never string-matches reasons; web_ui suppresses the req_keyframe publish only when the request is PURELY gap-driven and LIFETRAC_KF_ON_SEQ_GAP=0. Cold start, grid mismatch, and tile-decode errors always pass through. Suppressions log a countable "kf-on-gap suppressed (F11)" line for the bench A/B. Default stays ON per the F10 protocol: measure the A/B on air first, flip in a separate commit. 10 new tests; suite 1103/2446. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…/B pass On-air A/B (bench-evidence/F11_kf_on_gap_2026-08-02/RESULTS.md), gate off at the F10 acceptance operating point: 4 induced gaps + 2 natural single-frame air losses -> 6 suppressions, ZERO keyframe requests, and a fully healthy canvas — short-gap losses re-swept below the 30 s stale horizon, gap stragglers repaired by the 0x6C path in 1-2 report periods. The ungated cold-start request verified live mid-stream (published 3 s after a canvas-cold web_ui restart, radiated, keyframe granted). Control is the F10 surgical window: every gap requested, two keyframe trains granted. Also: the suppression counter logs at WARNING (uvicorn leaves the root logger at its default, so info was silently dropped — caught on the bench when three real suppressions produced zero log lines). LIFETRAC_KF_ON_SEQ_GAP=1 restores the old behaviour. Suite 1103/2446. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR implements F11 by adding structured keyframe-request causes to the image canvas update path and using them in web_ui to suppress pure base-seq-gap keyframe requests by default (while preserving cold-start, grid-mismatch, and tile-decode-error keyframe behavior). It also adds on-air bench evidence artifacts and new tests to lock in the gating semantics and default.
Changes:
- Add structured
seq_gap/tile_errorflags toCanvasUpdateso policy can gate without parsingreasonstrings. - In
web_ui, suppressreq_keyframepublishes for pure seq-gap requests whenLIFETRAC_KF_ON_SEQ_GAP=0(default), and emit a warning log line per suppression. - Add bench evidence artifacts and a dedicated test suite covering structured-cause semantics and gate behavior, and update the controller TODO entry to DONE/verified.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| LifeTrac-v25/DESIGN-CONTROLLER/TODO.md | Marks F11 as completed and records the on-air verification summary and evidence pointer. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/F11_kf_on_gap_2026-08-02/tap_base.log | Adds broker tap artifact showing observed tile_stale and req_keyframe activity during the A/B. |
| LifeTrac-v25/DESIGN-CONTROLLER/bench-evidence/F11_kf_on_gap_2026-08-02/RESULTS.md | Adds written on-air A/B results and decision to flip the default to OFF. |
| LifeTrac-v25/DESIGN-CONTROLLER/base_station/web_ui.py | Implements the gate and suppression logging for pure seq-gap keyframe requests. |
| LifeTrac-v25/DESIGN-CONTROLLER/base_station/tests/test_kf_on_seq_gap.py | Adds tests for structured causes, suppression/passthrough behavior, and the default setting. |
| LifeTrac-v25/DESIGN-CONTROLLER/base_station/image_pipeline/canvas.py | Adds structured cause flags to CanvasUpdate and sets them on seq gaps and tile transcode/apply errors. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+6
to
+7
| keyframe is largely redundant — but per the F10 protocol the default stays | ||
| ON until the A/B is measured on air. These tests pin the gate mechanics: |
… name The module docstring still said the default stays ON pending the A/B; it now records the measured flip. test_gate_on_default_still_requests_on_gap forces the gate on rather than exercising the default, so "default" is dropped from the name. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the F11 candidate queued by the F10 acceptance (PR #89, RESULTS §5), following the same gate → measure on air → flip protocol as F9/F10.
Why
The gap-tolerant canvas requested a keyframe on every base_seq gap — including a single lost delta frame. In the F10 surgical window (the control data for this A/B), three gap events produced three requests and two granted keyframe trains, each a multi-frame cost at the 243 B/frame budget, with the 10 s throttle as the only damper. F10's 0x6C stale-tile path now detects and repairs exactly that damage tile-by-tile, making the per-gap keyframe largely redundant.
What changed
CanvasUpdatecarries structured causes (seq_gap,tile_error) so the policy layer never string-matches reason text; a gap and a tile error can co-occur andreasononly keeps whichever fired first.req_keyframepublish only for pure-gap requests underLIFETRAC_KF_ON_SEQ_GAP=0. Cold start, grid mismatch, and tile-decode errors always pass through. Each suppression logs a countablekf-on-gap suppressed (F11)line (at WARNING — uvicorn leaves the root logger at its default level, which silently dropped the first attempt at INFO; caught on the bench when three real suppressions produced zero log lines).On-air A/B (bench-evidence/F11_kf_on_gap_2026-08-02/RESULTS.md)
Same operating point as the F10 acceptance; gate off. Six gap events — four induced (3 s rx stops) plus two natural single-frame air losses, the exact event class the control paid keyframes for — produced six suppressions and zero keyframe requests, with the canvas fully healthy: short-gap losses re-swept below the 30 s stale horizon (no repair even needed), gap stragglers repaired by 0x6C in 1–2 report periods. The ungated cold-start path was verified live: a canvas-cold web_ui restart mid-stream published "delta arrived before any keyframe" within 3 s and was granted a keyframe. Every 0x60 radiation in the session log is accounted for (2 stream-acquisition + 2 cold-start, none gap-driven).
Tests
10 new in
test_kf_on_seq_gap.py: structured-cause semantics (gap / tile-error / both / cold start), gate-off suppression, gate-on passthrough, keep-paths under gate-off, and the default pinned to OFF with the evidence pointer. Full suite: 1103 passed / 2446 subtests.🤖 Generated with Claude Code