The graft namespaced pyxis's BLE/HDLC sources to <microReticulum/Bytes.h> etc.,
but the standalone native unit-test build only had flat shims in tests/native/,
so test_ble_* and test_hdlc failed to compile ("'microReticulum/Bytes.h' file
not found"). Add forwarding shims under tests/native/microReticulum/ that
include the existing flat shims. Production code is unchanged; this only fixes
the test harness for the relocated layout.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UWZuYkHBRqNb6BZHV8sTG5
VoiceFilterChain::applyHighPass collapsed to a constant-gain
multiplier instead of a real high-pass response. The inner loop
read `samples[prevIdx]` as "previous input" — but that slot held
y[n-1] (output) since the previous iteration had overwritten it.
Substituting that into the formula
y[n] = α(y[n-1] + x[n] - x[n-1])
with x[n-1] := y[n-1] gave
y[n] = α(y[n-1] + x[n] - y[n-1]) = α · x[n]
i.e. just a fixed gain ≈ 0.81 at 300Hz cutoff / 8kHz. DC offsets
sailed through; the chain only kept signal levels reasonable
because the AGC stage downstream pulled the residual toward target.
The same bug exists in upstream LXST-kt's
native_audio_filters.cpp (filed as LXST-kt#13).
Fix: walk per-channel with explicit `xPrev` / `yPrev` variables so
input history isn't clobbered by the output write. Per-chunk save
of `lastInputs[ch]` now stores the actual last input, not the last
output, so the first sample of each new chunk uses the correct
x[n-1].
Test `dc_offset_attenuated_by_hpf` updated to assert tail RMS
< 0.01 (was < 0.5 — accommodating the broken behavior). Pass.
End-to-end acoustic test (Mac speaker → T-Deck mic): pyxis_rms
went up from 4378 → 5835, bot_rms from 1194 → 1517 — DC offset
removal lets clean signal through better.
Pyxis-side fix only. LXST-kt should pick up the same fix
upstream — see project_lxst_hpf_filter_bug.md in the vault.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile review feedback on PR #21:
ACCEPT:
- test_patch_nimble.py:151 (P1) — replace dead `if False else True`
ternary with a real assertion that "already applied" is absent on
the first run.
- test_patch_nimble.py:247 (P1) — invoke the shim subprocess via
`sys.executable` instead of hardcoded `/usr/bin/python3` so CI's
setup-python interpreter is used consistently.
- workflows/test.yml:50 (P2) — include hash of
deps/microReticulum/platformio.ini in PlatformIO cache key so the
cache invalidates when dependencies change.
MODIFY (narrowed):
- test_ring_buffers.cpp:209 (P2) — keep both `write(data, 0)` and
`write(data, -1)` assertions, but add a comment clarifying that
EncodedRingBuffer::write() takes signed `int length` (not size_t),
so -1 hits the `length <= 0` branch — same as 0. Greptile's
premise (size_t wrap to SIZE_MAX) does not apply to this codebase.
The two assertions lock the contract in case the param is ever
migrated to size_t.
REJECT (silently — no public reply per agent policy):
- test_audio_filters.cpp:237 (P1) — VoiceFilterChain::process()
takes `numSamples = frames * channels` per the documented
contract in audio_filters.h:33-40, and the implementation does
`numFrames = numSamples / channels_` (audio_filters.cpp:63). The
multichannel test correctly passes `(int)samples.size() = 8000`
(4000 frames * 2 channels). No out-of-bounds read occurs.
Standalone C++ tests of pyxis-unique code (BLE fragmenter/reassembler,
peer manager, GATT op queue, LXST ring buffers, audio filters, HDLC
framing) plus Python tests of the patch_nimble.py build script.
Each C++ test is compiled directly by clang++/g++ with shims in
tests/native/ (Bytes.h, Log.h, Utilities/OS.h) so pyxis sources can build
without microReticulum's full Arduino/MsgPack dep tree. A pytest wrapper
per test compiles, runs, and parses the summary line — the whole suite
is one command: `pytest tests/build_scripts tests/native -v`.
Total: 13 pytest tests, ~72 underlying C++ assertions, 3.4s.
Surfaced an HPF-formula bug in lxst_audio (mirrored upstream in
LXST-kt/native_audio_filters.cpp) — filed as LXST-kt#13 and tracked
in the corresponding test with a TODO link.
CI workflow runs the pyxis pytest suite plus the clean-passing
microReticulum native17 unit tests (94/114 of the existing fork
test/* suites) on push and PR.