Monorepo migration, steps 2–4: shared harness, renames, family docs - #50
Merged
Merged
Conversation
PR #49 merged after step 1 (976f117, merge commit), so steps 2-4 continue on the branch restarted from main in a new PR. The plan says so, records that step 4's post-merge checks already hold (186 commits on main; --follow reaches RatioTap M3, a83d6d8 -> b8bad2e), and notes step 2's result; runs.md gets step 1c's run IDs and G1/G2 outcome. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
scripts/icount.py takes --engine async|bridge, which picks the workload prefix, the guest's completion marker (kept byte-identical: SRT_ICOUNT_DONE / RATIO_ICOUNT_DONE) and the default baselines file; the root plugin now prints TAP_SR_INSN_COUNT for both. bridge's copies of the toolchain files, platform startup/linker scripts, plugin and icount.py are deleted; the root ones are what CI already used since 1c. CI: one ratchet job per target measures both engines from one build (async, then bridge, each still its own gated step), and docs freshness is its own job per engine. compare.yml follows the new marker. Measured locally: counts and checksums exact against S0 and R0 on M33 and M55 (17 workloads), and +0 against both committed baselines; G1, G4, G5, G6, G7, G10 and G14 (residual/2.txt) pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
`rename.py apply --step X` makes exactly one rename class's change in a working tree (git mv, the class's text rules, clang-format on the C/C++ files it touched), so each step-3 commit is produced by the same map G14 checks it against. build/check now run the rule classes in step order regardless of their position in SUBS. The 1c book-include rules are listed after the 3.1 path rules, so through 3.1 the book's `include/srt/` includes were rewritten to `include/tap/sr/async/` before 1c could prefix `async/`, leaving 40 spurious residual hunks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
…igration step 3.1) Produced by `rename.py apply --step 3.1`, so the commit is exactly the map's class 3.1: - async/include/srt/ -> async/include/tap/sr/async/ (asrc.h -> converter.h per D15, srt.h -> async.h), with every include directive and path citation following; - bridge/include/tap/ratio/ -> bridge/include/tap/sr/bridge/; - bridge/tools/capi/ -> bridge/capi/, its standalone build now adding the engine from `..`, and ratiotap_py building from bridge/capi; - srt/detail/kaiser.h, the re-export of tap::dsp's Kaiser design, is deleted; polyphase_filter.h and test_kaiser.cpp use tap::dsp directly. Namespaces are untouched (3.2). Formatted by the pre-commit hook's clang-format. Measured locally against S0 and R0: G7 exact (host, M33, M55), G3+G5 exact for all 17 workloads on M33 and M55, G4 identical (C ABI and icount binaries), G1/G5/G6/G10 equal, G11 all seven notebooks unchanged, G14 clean against residual/3.1.txt (= step 2's). Clang -Werror 159/159, clang-tidy clean, mdBook clean. A local bridge/build_capi/ configured from the old path needs deleting once (CMake refuses a moved source). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
map_old_path tried a trailing-slash (directory) form first, which on a file path skips a file rename: from 3.1, include/srt/asrc.h mapped to async/include/tap/sr/async/asrc.h instead of .../converter.h, and G12's blame failed on the missing path. Callers that pass files now say so; G7 infers it from the suffix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
G4's normalizer now follows the plan's spec (section 5): only bytes inside an STT_FUNC's extent are compared, so the read-only data bare-metal links place in .text (string pools, typeinfo, vtables), which objdump decodes as instructions, no longer counts as code. A literal-pool word becomes the string literal it points at (mapped with its quotes, since D15's prefix rule anchors on one), the symbol it points into by nm -S extent, or the section it points into; call targets are normalized before comment stripping, so x86 PLT names (<new(...)@plt>) keep their symbol and lose their address. Step 3.2 lengthens the exception prefixes, which moves that data by 8 bytes; its code is identical, and G4 now says so (C ABI libraries and all 17 icount binaries on M33 and M55), while still failing on two different workloads. carry_residual.py carries a step's reviewed G14 allowlist forward: a hunk a later rename class touched keeps its file's reviewed reason and is printed for re-review; genuinely new residual is an error. runs.md: steps 2 (131e78b) and 3.1 (75ae156) gated green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
…n step 3.2) Produced by `rename.py apply --step 3.2`, so the commit is exactly the map's class 3.2 (formatted by the pre-commit hook's clang-format): - tap::samplerate -> tap::sr::async, tap::ratio -> tap::sr::bridge in C++ (CMake aliases move at 3.4); - D15: basic_async_sample_rate_converter -> basic_converter, async_sample_rate_converter[_q15|_q31] -> converter[_q15|_q31], and the exception prefix "async_sample_rate_converter: " -> "tap::sr::async::converter: "; - the test namespace srt_test -> async_test. Measured locally against S0 and R0: G3+G5 exact for all 17 workloads on M33 and M55; G4 identical code for the C ABI libraries and every icount binary (only the lengthened exception strings move data); G7 exact; G1, G5, G6 and G10 equal; G14 clean against residual/3.2.txt, which carries 3.1's plus the one reviewed bridge README hunk whose text the rename touched. Clang -Werror 159/159, clang-tidy clean, mdBook clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
Step 3.2 left the Hexagon leg red: 14 workloads count 47-87 instructions fewer than step 0, every one inside musl's memcpy in the final marker printf. The renamed exception-message literals change length, .rodata shifts, and the format string lands at an alignment whose memcpy path is shorter. Codegen, outputs and the Arm counts are exact. G3 now takes docs/migration/allow-g3.txt: per (target, engine, workload) one symbol and the exact delta it accounts for. The gate requires that exact delta (a delta with no row, or a row with no workload, fails) and re-proves each row with docs/migration/fncount.c, a qemu plugin that attributes every executed instruction to its symbol: as a multiset over every other symbol the counts must be identical, and the named symbol must differ by exactly the row's delta. The three kernel workloads and both Arm legs stay exact with no row. G4's normalizer learns llvm-objdump's Hexagon output: add(pc,##imm) is resolved from the packet address, the redundant immext value is dropped, bare branch targets are symbolized, and an absolute ##imm is symbolized only into writable data, since this static musl link reaches read-only data PC-relatively and a plain constant that lands in .rodata must stay raw. String literals are read from their first byte only. Measured: 0 of 919 functions differ on each of the 17 pairs; a Q15/Q31 pair still shows its 43 real differences. Measured locally on the pinned toolchains before the push: hexagon, m33 and m55 pass every gate; host passes all but G12, which needs the full history CI checks out. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
…tion step 3.3)
rename.py apply --step 3.3 over 41 files: SRT_VERSION_* and
TAP_RATIO_VERSION_* become TAP_SR_VERSION_*; the SRT_RESTRICT,
SRT_Q15_SMLALD and SRT_CHANNEL_PARALLEL forwards are deleted for their
TAP_DSP_ originals; SRT_CP_MIN_CHANNELS, TAP_RATIO_MIRRORED_DOT_ATTR,
SRT_SC_*, RATIO_SC_*, SRT_CMP_*, *_TESTS_COMPLETE, *_BARE_METAL, SRT_PICO2_*
and SRT_GD take their TAP_SR_{ASYNC,BRIDGE}_ names. Guest icount markers
are unchanged.
By hand (G14 lists each in residual/3.3.txt): TAP_SR_VERSION_* = 0.4.0
in both umbrella headers, token-identical as D13 requires and as the
bluetooth_bridge example, which includes both, needs; a D7 #error
tripwire for SRT_CP_MIN_CHANNELS; the 1c toolchain lines retired, so each
Arm toolchain file sets TAP_SR_BARE_METAL once; ratio_demo.ipynb
re-executed in the pinned environment for its version line (figures
byte-identical). STYLE.md keeps its macro example: it changes through
taphouse, and the TapHouse-synced files join APPLY_SKIP.
Gates: the two C ABI version functions return the folded constant, so
allow-g4.txt names them and G4 prints their diff (100 -> 400 decimal,
0x300 -> 0x400 bit-packed; nothing else differs). G11 executes both
trees, so a 3.3 rule maps the notebook's printed "RatioTap 0.3.0" to
0.4.0. G7 compares -D definitions as the sorted set CMake emits, since
the renamed SRT_SC_* moved past TAP_DSP_FFT_CMSIS in the Arm command
lines with no change to the set.
Measured locally before the push: G3+G5 exact on hexagon (the 14
allow-g3.txt rows proved per function), m33 and m55 for all 17
workloads; G4 17/17 per target and 2/2 C ABI libraries; G7, G11 (seven
notebooks), G14 (0 unlisted); the host gates but G12 (shallow clone);
clang -Werror 159/159 tests, clang-tidy clean, the book builds. Also
records step 3.2's runs in runs.md.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
…igration step 3.4)
rename.py apply --step 3.4 over 52 files: the options become TAP_SR_*
(D9), the warning gates TAP_SR_{ASYNC,BRIDGE}_WERROR, the internal
targets tap_sr_*, bridge's test prefix and label "bridge." / bridge
(D16), the QEMU legs' label with them, and the dev-only include target
tap_sr_async_headers.
By hand (G14 lists each in residual/3.4.txt): the root declares the D9
options once, ahead of the engines' own option() calls; project(
SampleRateTap VERSION 0.4.0) at the root and tap_sr_async / tap_sr_bridge
with no VERSION in the engines (D13); async's INTERFACE target is
tap_sr_async with one alias; the umbrella tap::sr links both engines;
cmake/retired_options.cmake is the D7 FATAL_ERROR tripwire for all 16
retired options, included by the root and by an engine configured on its
own; and the doubled -D lines the option unification left in ci.yml and
compare.yml are removed.
The 4.2 dependency rule gets its enforcement as the root tests/: per
engine, the link interface is exactly tap::dsp, every public header
compiles in its own TU with only tap::dsp and the engine's include on the
path (built by the test, so a leaked include fails the test, not the
build), the public headers name no srt/, sibling tap/sr/ or ../, and the
header count is pinned (6, 5). Each is a ctest entry under the engine's
label, so every job that runs the engine's tests runs them. D13's
family.VersionMacrosAgree, compile-only under both labels, checks that
the two umbrella headers define the same 0.4.0.
Gates: G1 counts a test in every engine bucket its labels name, and
allow.txt rows may glob the job file; notebook_text joins consecutive
stream chunks of one output, since the kernel may split a print into a
line and a bare newline.
Measured locally before the push: G3+G5 exact on hexagon (the 14
allow-g3.txt rows proved per function), m33 and m55; G4 17/17 per target
and the two allowed C ABI functions; G7, G11 (seven notebooks), G14 (0
unlisted); the host gates but G12 (shallow clone); GCC and clang -Werror
168/168 tests, clang-tidy clean, the book builds; the tripwire and each
check script fail their negative case.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
Since step 3.4 the one family option TAP_SR_BUILD_ICOUNT_BENCH builds both engines' ratchet workloads, so async/bench/icount entered the compile database the style job tidies. Those TUs were never under the gate and do not pass it (the job's own comment defers them to follow-up work); they are now excluded by path, as the bridge-only option excluded them before. Measured locally with the job's own filter: 47 TUs, the ten icount TUs all bridge's, clang-tidy clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
…ding (migration step 3.5) rename.py apply --step 3.5 over 19 files: srt_* becomes tap_sr_async_* and ratio_* tap_sr_bridge_*, with the handle types (SrtHandle -> tap_sr_async_converter, ratio_converter -> tap_sr_bridge_converter), the headers and libraries (libtap_sr_async_capi, libtap_sr_bridge_capi), the r8brain shim's exports and source file, CMake's <target>_EXPORTS defines, and the bridge binding module ratiotap_py.py -> tap_sr_bridge_py.py (D8; async's notebooks keep their inline ctypes loader, as at S0). By hand (G14 lists each in residual/3.5.txt): tap_sr_async_version returns the family's bit-packed encoding (major << 16 | minor << 8 | patch), the value tap_sr_bridge_version already returns, so both probes answer 0x000400 (D13); and CApi.VersionIsBitPacked, one per engine, links the shipped shared library and pins the encoding and 0.4.0. The test declares the probe itself, keeping the C header out of the tidy gate, and exists where TAP_SR_BUILD_CAPI builds the library (the host gate, Linux and macOS), which allow.txt lists per job file. Gates: allow-g4.txt's rows follow the renamed version functions (G4 prints their diffs: 0x64 -> 0x400 and 0x300 -> 0x400, nothing else); a lib… rule maps the shim's library name in the comparison notebook's step-0 output, as the C ABI libraries' rules do. Measured locally before the push: G3+G5 exact on hexagon (the 14 allow-g3.txt rows proved per function), m33 and m55; G4 17/17 per target and the two allowed C ABI functions; G7, G10, G11 (seven notebooks), G14 (0 unlisted); the host gates but G12 (shallow clone); GCC and clang -Werror 170/170 tests, clang-tidy clean, the book builds. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
…ep 3.6) rename.py apply --step 3.6 over 7 files: the two icount CMake targets, scripts/icount.py's engine prefixes, the comparison workloads' comments and the book's prose. Prefix only: the guest markers, the workload names and both baselines.json files are unchanged, and the ratchet keys stay the scenario names. No hand edits; residual/3.6.txt carries step 3.5's list with the two icount.py hunks re-hashed. Measured locally before the push: G3+G5 exact on hexagon (the 14 allow-g3.txt rows proved per function), m33 and m55, the binaries paired under their new prefix; G4 17/17 per target; G7, G14 (0 unlisted); the host gates but G12 (shallow clone); clang -Werror 170/170 tests with the ratchet workloads built, clang-tidy clean, the book builds. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
…step 3.7) The prose pass, by hand (G14 lists every hunk in residual/3.7.txt): bridge's README and CLAUDE.md select tests with -L '^bridge$'; the C ABI chapter describes the probe as the bit-packed family version (D13) with the tap_sr_async_* prefix and the family build path; RatioTap's links, badge and clone instructions point at the bridge engine in this repository (book Parts 0 and V, async README and COMPARISON.md, bridge README); the book's asrc.h is converter.h (D15; the chapter keeps its URL) and its "srt" namespace tap::sr::async; the @file lines the 3.1 moves left behind name the moved headers; and the example and bench paths sit under the family build tree. The mechanical renames of 3.2-3.6 had already reached the notebook markdown and the non-book docs. G9 (retired identifiers) applies from this commit. Its survey found 71 hits, 69 structural and now allowlisted in snapshot/g9.txt with reasons: the plan itself, the D7 tripwire list in cmake/retired_options.cmake, the 4.2 include grep that names srt/ on purpose, and the #ifdef half of the SRT_CP_MIN_CHANNELS tripwire. The two prose hits are fixed above. Measured locally before the push: G9 0 hits; G3+G5 exact on hexagon (the 14 allow-g3.txt rows proved per function), m33 and m55; G4 17/17 per target; G7, G14 (0 unlisted); the host gates but G12 (shallow clone); clang -Werror 170/170 tests, clang-tidy clean, the book builds. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
… time a job out The Arm toolchain is about 600 MB of .debs (libstdc++-arm-none-eabi-newlib alone is 463 MB). On 2026-09-30 a throttled Azure apt mirror served them at 100-400 kB/s to some runners, so "Install Arm toolchain and QEMU" took 17, 34 and 40 minutes on three consecutive runs of the M33 async QEMU job (1-2 minutes on every other run and on its sibling jobs), cancelling a job whose test needs 27 of its 40 minutes; the M33 ratchet and the comparison smoke jobs were cancelled the same way once each. The .debs are now kept in ~/apt-archives through actions/cache (keyed by the runner image, as the Hexagon toolchain cache is) and apt installs from that directory (-o Dir::Cache::Archives), so a cache hit turns the install into an index refresh; a stale cached package is simply not used. Applied to the four installs: the QEMU legs, the instruction-count ratchet, the Pico 2 build and compare.yml. Verified the mechanism here: a reinstall from the populated directory fetches 0 B. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
The gates' hexagon leg installs the same ~600 MB Arm toolchain; on 2026-09-30 a throttled apt mirror ran that step past the job's 90 minutes. The same actions/cache-backed apt archive directory as ci.yml's (its own key, since the package set differs) makes the install an index refresh after the first run. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
rename.py apply --step 3.8: every C/C++ and Python source outside vendored code starts with "SPDX-License-Identifier: MIT" and "Copyright 2026 Timothy Place and the SampleRateTap contributors" (68 files: the 35 existing banners rewritten, the rest added). The rule moves a banner that sat below a leading doc block (async's \file headers, the /* */ blocks of the C plugin and the startup file) to the top rather than duplicating it. bridge/tools/reference/make_reference_vectors.py emits the family holder, and tests/reference/reference_vectors.h was regenerated in the pinned notebook environment (numpy 2.4.6, scipy 1.17.1): after the pre-commit reformat its only difference is the banner line, as the plan requires. residual/3.8.txt carries step 3.7's list plus that header and its generator. Measured locally before the push: G3+G5 exact on hexagon (the 14 allow-g3.txt rows proved per function), m33 and m55; G4 17/17 per target; G7, G9 (0 hits), G11 (seven notebooks), G14 (0 unlisted); the host gates but G12 (shallow clone); clang -Werror 170/170 tests with the ratchet workloads built, clang-tidy clean, the book builds. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
…on step 4) docs/MONOREPO_PLAN.md becomes PLAN.md, the family plan. New: the family README.md (the two engines and the no-routing rule, the TAP_SR_* options, the one version, build and test, the layout, the dependency rule, provenance) and CLAUDE.md (the load-bearing family rules: never route by rate, the dependency rule and its tests, the cross-validation independence rule, the substrate discipline, one version, no aliases; build, the embedded legs and the ratchet, style, and git bisect start --first-parent across the merge); async/PLAN.md (charter, contract, status, roadmap). Reframed as engines of the family: async/README.md, bridge/README.md, bridge/PLAN.md (M0-M7 history kept; §2 and §9 updated) and bridge/CLAUDE.md, now the charter with the family rules referenced. The Doxyfile's main page is the family README. The migration's working set is retired: docs/migration/ (the step-0 snapshot, the rename map, the gates and the residual allowlists) and .github/workflows/migration-gates.yml are deleted; the gate-run record stays as docs/MIGRATION_RUNS.md. The plan's references now point at PLAN.md. Measured locally before the push: the tree configures, builds and passes 170/170 tests with the C ABI built; the book builds; doxygen runs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
tap
marked this pull request as ready for review
September 30, 2026 22:35
This was referenced Sep 30, 2026
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.
What this changes
This completes the monorepo migration of
PLAN.md(formerlydocs/MONOREPO_PLAN.md) after #49, which merged steps 0 and 1 (976f117): #49 put the async engine inasync/, imported RatioTap's history underbridge/, and made the root build compose both. This PR carries steps 2–4, one gated commit per push, each with its migration-gates run recorded indocs/MIGRATION_RUNS.md:131e78bscripts/icount.py --engine)018e912,75ae156tap/sr/async/,tap/sr/bridge/;asrc.h→converter.h; bridge's C ABI tobridge/capi/3822f71,8ce5235tap::sr::async/tap::sr::bridge; D15'sbasic_converterfamily in asyncdedf0b8TAP_SR_*; the family version 0.4.0 in both umbrella headers (D13); the D7#errortripwire9ce18f1,fa7eb17TAP_SR_*(D9), targetstap::sr::async/tap::sr::bridge/tap::sr,bridge.test prefix and label (D16), the D7FATAL_ERRORtripwires, the 4.2 dependency-rule testsfb75b6atap_sr_<engine>_*(D8): handle types, headers, libraries, the shim's exports, the bridge binding; bit-packedtap_sr_<engine>_version()pinned byCApi.VersionIsBitPackeda470648tap_sr_<engine>_icount_*(prefix only; workload names and baselines unchanged)2847630,a2b8e5e,79b609d716c7e1reference_vectors.hregenerated (banner-only diff)6404d2cREADME.md,CLAUDE.md,PLAN.md;async/PLAN.md; engine READMEs,bridge/PLAN.mdandbridge/CLAUDE.mdreframed;docs/migration/andmigration-gates.ymlretiredVerification
Every gated SHA passed the full battery (CI, style, ci-arm64, compare) and the migration gates against the step-0 tips built in the same job: instruction counts and output checksums exact (G3, G5) on M33, M55 and Hexagon; per-function codegen identical (G4) for all 17 ratchet binaries and both C ABI libraries; test multisets (G1, G2), cross-validation lines (G6), compile flags (G7), C ABI symbols (G10), history (G12), the rename-only residual (G14) and, from 3.7, zero retired identifiers (G9). Run IDs per SHA are in
docs/MIGRATION_RUNS.md; each step's plan entry records what was measured locally before its push.Two exact, printed allowances were needed, both reviewed rows in the (now retired)
docs/migration/and explained inPLAN.mdsection 7:memcpyin the final markerprintf— the renamed exception-message literals moved.rodata, so the format string landed at an alignment with a shortermemcpypath. A per-function counting plugin proved every other symbol identical on every run. The committed Hexagon baselines are therefore high by those amounts (inside the daily ±3 % gate); re-recording them is a listed follow-up.*_version()functions return the folded family version; their one changed immediate is printed by the gate on every run.Notes for the reviewer
SrtHandle→tap_sr_async_converter, mirroring bridge'stap_sr_bridge_converter; the bridge binding moduleratiotap_py.py→tap_sr_bridge_py.py(D8; async's notebooks keep their inline ctypes loader, as at S0).tap::dsp; every public header compiles in isolation; nosrt/, sibling or../includes; pinned header count), plus a compile-only check that both umbrella headers define the same version. They run in every job..debs in anactions/cachedirectory, keyed by runner image like the Hexagon toolchain cache; a hit turns the install into an index refresh.TAP_SR_BUILD_ICOUNT_BENCHpulled async'sbench/icountTUs into the style sweep for the first time; they were never under that gate and are excluded by path, as the job's comment already deferred them.git bisect start --first-parent(documented inCLAUDE.md).After merging (the maintainer's, per
PLAN.mdstep 4–5)git rev-list --count origin/main≥ count(S0) + count(R0) + N, andgit log --follow bridge/include/tap/sr/bridge/converter.hreaches RatioTap M3 (b8bad2e).89c7ebato.git-blame-ignore-revs.v0.4.0.STYLE.mdthrough taphouse.async/PLAN.md§4: re-record the Hexagon baselines (and make the marker print layout-independent), bringasync/bench/icountunder clang-tidy, MSVC/W4triage.🤖 Generated with Claude Code
https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA