Repository navigation
Land howl_guard (#78) on main - #81
Merged
Merged
Conversation
…off (phase 2 item 6b, PR B) The safety layer's gain policy over the canceller's verdict (D and A') and a howl_detector on each residual: ARMING / OPEN / OPEN_CAPPED / DUCKED / RELEASING / LATCHED, every transition in the header; TRIP = the level catch always or growth while the verdict is not ok; LOST = an ok -> not-ok edge held trip_hold_s, disarmed after a timer re-arm until ok is seen; strikes, back-off and latch; dB-linear ramps that land exactly; per-mic attribution with a duck-all fallback; a post-reverb bus stage. Real-time contract as fd_kalman.h. afc_chain::set_guard(): runs the guard per mic on e_k after forwarding A' and D, before the bus sum; static_asserts the canceller's statistics and refuses (returns false) a canceller without the shadow or a guard of the wrong shape; reset() re-arms an attached guard. Without a guard the chain is unchanged (the plain bus sum is the old code; fingerprints identical). Tests: the float/double state-machine suite (both emulated selections run the float half), the live loop on afc_chain (tests/support/guard_loop.h, guard_runs.h) with guard-independent oracles, 13 gated host rows and the MUTAP_SLOW sweep. docs/howl-guard.md has every table; HANDOFF item 12. Measured (macOS 15.7 x86_64, AppleClang 17, Release, double): 0 howl blocks in 108 gated and 620 sweep cold starts; at the canceller's limit + 6, 0 guarded against 575 / 1203 unguarded; 0 ducks off a loop-born burst in 180 audible-cost runs; cost 0.60 / 0.88 % of a canceller per mic. Open: F -> 2F still cycles duck / open (47 LOST-ducks after a re-arm in 20 of 30 sweep runs, 0 howl); no declaration without a backing track (the cap opens those runs); A' plateaus near -15 dB in silence, so restart_a_db (a new field, -1 dB) fires only on a canceller reset. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDhgJqxUsdmWPKh6pKrV5A
…unts with margin
guard_runs.h: the [from, to) helpers over run_trace (blocks_in, howl_blocks,
entries, longest_howl_s) walk iterators clamped to their own vector instead
of an index loop against min(to, size()). GCC 13's
-Waggressive-loop-optimizations bounded size() only by the pointer
difference and failed the Linux build ("iteration 4611686018427387903
invokes undefined behavior" in howl_blocks via cold_stats::add_unguarded).
HowlGuardHost.TwoMicsAttributeASingleMicHowl: the wrong-mic-alone count was
gated at 0 on 8 chaotic runs; macOS arm64 CI (run 36828198214) read 1 of 8.
Now gated at <= 2 of 8 (the sweep's rate is 1 of 20), plus what the claim is
about: howl blocks <= 24 over the 8 runs and no howl run of 0.1 s. Measured:
Intel 0 of 8 wrong, 1 howl block, longest 0.0013 s; arm64 1 of 8, 3 blocks,
longest one block. Header, doc and HANDOFF quote both hosts.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DDhgJqxUsdmWPKh6pKrV5A
tap
added a commit
that referenced
this pull request
Oct 2, 2026
…nstead of apt gcc-arm-none-eabi Ubuntu's gcc-arm-none-eabi pulls the 463 MB libstdc++-arm-none-eabi-newlib package from the runner's Azure mirror. That fetch stalled past the 15-minute step limit three times on 2026-10-01 (#81 twice, #80 once) after eating two 45-minute legs on #67. Both Cortex legs now restore Arm's arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi from the Actions cache, or download it (179 MB from Arm's CDN, curl with retries, verified against Arm's published sha256) on a miss, and put its bin on PATH; only qemu-system-arm still comes from apt. It is the same upstream release Ubuntu noble packages (15:13.2.rel1-2), so the fingerprint and icount gates on this PR's own run are the check that the numerics did not move. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DDhgJqxUsdmWPKh6pKrV5A
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.
Lands #78 (
tap::mu::howl_guard, PR B of the safety layer) onmain.#78 was stacked on #77's branch
feat/howl-detector, and when it was merged GitHub merged it into that branch rather than intomain(#77 had already landed onmainby rebase). Somainhas the detector but not the guard. This PR ismain+ #78's two commits, cherry-picked unchanged (b805626→7b53fac,9d088ea→92dff1e): the guard header, theafc_chainhook, the tests and sweeps,docs/howl-guard.md, HANDOFF item 12. Everything measured and claimed is in #78's description and its CI run (green: 35 passed, 1 skip); nothing here is new.The chain is bit-identical with no guard attached (
test_afc_chain.cppoutput and the 14mutap_fingerprintlines unchanged, as #78 verified). Locally on this branch (macOS x86_64, AppleClang, Release): the build is clean on main's DspTap pin and the guard's state-machine suite passes; CI runs the host rows.PR C (#80, the re-arm hold, soundcheck calibration and cap rule) is re-stacked on this branch and retargets
mainonce this merges.🤖 Generated with Claude Code
https://claude.ai/code/session_01DDhgJqxUsdmWPKh6pKrV5A