fix(ci): Harness SQLite struct conflict + Voice cold-start timing budgets #168

Merged
KofTwentyTwo merged 3 commits from fix/ci-env-harness-sqlite-voice-warmup into develop 2026-05-13 13:52:37 +00:00
3 Commits
Author SHA1 Message Date
james.maesandClaude Opus 4.7 a69de3ed30 test(voice): widen CI-jitter budgets in TTSInterruptTests + VoiceControllerTests
Two timing-sensitive Voice tests intermittently failed on the macos-15
GitHub Actions runner (CI run 25801448991) under cold-start scheduling
load. Both failures masked nothing — the semantics under test still hold;
the budgets were just tighter than CI variance.

TTSInterruptTests.testI3_completionTimeoutRespected
  - Stall widened 100ms → 400ms, budget widened 80ms → 250ms.
  - The semantic ("InterruptSequence's 20 ms completion timeout fires
    before the sink stall would have completed on its own", proved by
    `elapsed < stallDuration`) is preserved: 400 ms - 250 ms = 150 ms of
    headroom over the 20 ms timeout. CI observed 108 ms — already past
    the previous 100 ms stall, making the assertion self-defeating.

VoiceControllerTests.testV4_audioLevelEmitter_emits_correct_rms_at_30hz
  - Sleep widened 250ms → 500ms; minimum emission count unchanged at 4.
  - At 30 Hz, 500 ms ≈ 15 expected emissions, so the 4-floor still
    asserts the rate semantics with comfortable margin. CI observed only
    2 emissions in the 250 ms window when the emitter task's first tick
    was delayed by cold-start Task scheduling.

Neither change masks a regression — both still fail on real wall-clock
budget breaches that would affect users.

Closes CI failure 25801448991/SPM-Voice testI3 + testV4.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 08:49:41 -05:00
james.maesandClaude Opus 4.7 6a84e96eb4 test(voice): warm up AVSpeechSynthesizer in setUp to absorb cold-start cost
CI run 25801448991 SPM-Voice failed `testA1_speakResolvesWithinTwoSeconds`
at 4.07 s. The 2 s assertion is a real regression budget for warm-path
synthesis; bumping it would mask actual perf regressions. The root cause
is a one-time per-process cost on the very first `AVSpeechSynthesizer
.speak()` call: the speech subsystem loads the default voice and
initializes the audio path. On Apple Silicon dev machines this is under
200 ms; on the macos-15 GitHub Actions hosted runner (cold, multi-tenant)
it routinely exceeds 2 s.

Fix: drive one full `speak(" ")` in `setUp()` before each test runs.
After the first warm-up the macOS process-wide speech subsystem stays
primed, so subsequent setUp() warm-ups are cheap (~tens of ms). The 2 s
budget on testA1 now measures only the steady-state cost users actually
experience after the first utterance of a session — which is what the
test was always meant to assert.

Implemented via `override func setUp() async throws` (the modern async
XCTest entry point) rather than a guarded `static var warmedUp` flag
because Swift 6 strict concurrency rejects unsynchronized mutable
static state and the per-test warm-up cost is negligible after the
first one.

Closes CI failure 25801448991/SPM-Voice testA1.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 08:49:27 -05:00
james.maesandClaude Opus 4.7 56958c6b71 fix(harness): import CSQLiteVec instead of SQLite3 to avoid struct conflict
`import SQLite3` resolves to the macOS SDK's overlay (SQLite3.tbd /
sqlite3ext.h). On the Xcode 26.x / macOS 26 SDKs, that header declares
`set_errmsg` (3.51+) and `db_status64` (3.46+) as members of
`sqlite3_api_routines`. The bundled jkrukowski/SQLiteVec build that
`Replay.SQLiteConnection` `@_exported import`s ships its own
`sqlite3ext.h` without those members. Importing both modules in the same
Swift file produces conflicting `struct sqlite3_api_routines` definitions
and the compile fails ("'sqlite3_api_routines::db_status64' from module
'CSQLiteVec' is not present in definition of 'struct sqlite3_api_routines'
in module 'SQLite3.Ext'").

Replay closed this with D-5/D-6 on 2026-05-11 by switching its single
SQLite consumer to `@_exported import CSQLiteVec`. Harness wasn't
migrated, and remained green on older SDKs that didn't have the newer
struct members. Xcode 26.3 (CI macos-15 runner) and Xcode 26.5 (local
dev) both surface the conflict.

`sqlite3_*` call sites are unchanged — CSQLiteVec is a drop-in for
SQLite3 in source, with `core_vec_init()` bundling vec0 as an
auto-extension on top.

Closes CI failure 25801448991/SPM-Harness + likely 25801448991/App-target
(xcodebuild was building Harness as part of package resolution because
`project.yml` declares it as a workspace package, and the same compile
failure cascaded to "Found unhandled resource at Corpora" during artifact
packaging).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-13 08:49:13 -05:00