CI run 25799596445 failed on 6 SPM packages + the App target. Root cause was a toolchain skew between local dev (Swift 6.3.2 / Xcode 26) and CI (Swift 6.0 / Xcode 16): - mlx-audio-swift v0.1.2 ships swift-tools-version:6.2 which Swift 6.0 cannot parse, breaking Voice + Harness + the App target with "Dependencies could not be resolved because 'mlx-audio-swift' contains incompatible tools version (6.2.0)". - MCP swift-sdk 0.12.0 uses the new `withThrowingTaskGroup` overload (no `of:` parameter) that only exists in Swift 6.2+. - AgentCore tests use `@MainActor` XCTestCase with `await super.setUp()`, a pattern Swift 6.0 rejects but Swift 6.1+ accepts. The macos-15 runner already ships Xcode 26.3 / 26.2 / 26.1 / 26.0 alongside 16.x, so the fix is to switch the Xcode select. Fallback to Xcode_26.app preserves robustness against patch-level shuffles. Also: - Drop `VoiceLog` from the SPM matrix. No `packages/VoiceLog` directory exists; the job failed with `chdir error: No such file or directory`. Voice-log work is parked under v1.1. - Bump BatcherTests `waitForDrain` from 80ms to 250ms. The batcher window is 33ms; 80ms was tight enough that macos-15 dropped test_tokenDeltaConcat with sendCount=0 because the scheduled drain hadn't completed its actor + main-actor hop before the test resumed. 250ms (~7.5× the window) survives CI jitter; verified locally — all five Batcher tests pass in 1.27s. Refs: CI run 25799596445. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Bus
Typed Swift↔JS message protocol over WKScriptMessageHandler. The webview is a pure rendering layer; this package is the only legitimate way Swift talks to the HUD and back.
Key public types
| Type | Purpose |
|---|---|
BusOutbound (enum) |
Messages Swift→JS — hello, hudState, tokenDelta, audioLevel, toolCallStart/End, turnStarted/Ended, sessionHistory |
BusInbound (enum) |
Messages JS→Swift — helloAck, uiReady, frameAttachRequested, chatSubmit, chatCancelAndSubmit |
OutboundBatcher (actor) |
Coalesces tokenDelta on a 32 ms tick; forwards everything else immediately |
WebviewBridge |
The WKScriptMessageHandler boundary (the only place that calls evaluateJavaScript) |
Handshake |
Version-negotiation flow on first uiReady |
BusReply / BusError |
Reply + error types for request/response patterns |
Depends on
Logging. External: swift-log.
Used by
App/AppDelegate, every subsystem that emits to the HUD, the webview-side TS package webview/packages/bus.
Key invariants / contracts
- Hand-written
Codable. BothBusOutboundandBusInbounddeclareCodablein extensions with explicitinit(from:)/encode(to:). Swift's synthesizedCodablewould produce{"hudState": {"_0": "idle"}}instead of{"type":"hudState","state":"idle"}. Adding a case without updating both methods is a compile error — schema-drift preventer at the language level. - Schema version sync.
Protocol.swiftcarries the version;webview/packages/bus/src/version.tscarries the TS mirror.scripts/check-bus-protocol-version.shrequires both to match. - Harness parity.
scripts/check-bus-harness-parity.shrequires the TS bus fixtures to round-trip through the Swift decoder. - No
evaluateJavaScriptoutsideWebviewBridge. Grep-gated byscripts/check-no-evaluate-javascript.sh. - Single writer to
HudState.scripts/check-single-writer-hudstate.shenforces.
Tests
58 XCTest. Round-trip encoding tests, version-negotiation tests, batcher coalescing tests, content-world isolation tests (WebviewBridgeOutboundTests asserts WKContentWorld.page).
Notable files
Sources/Bus/BusOutbound.swift— Swift→JS event union + hand-written CodableSources/Bus/BusInbound.swift— JS→Swift event union + hand-written CodableSources/Bus/OutboundBatcher.swift— token-coalescing actorSources/Bus/WebviewBridge.swift— WKScriptMessageHandler boundarySources/Bus/Protocol.swift— version constant