Files
james.maesandClaude Opus 4.7 bcc55c68be fix(ci): pin Xcode 26.x, drop phantom VoiceLog, harden Batcher timing (#167)
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>
2026-05-13 08:37:47 -05:00
..

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. Both BusOutbound and BusInbound declare Codable in extensions with explicit init(from:) / encode(to:). Swift's synthesized Codable would 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.swift carries the version; webview/packages/bus/src/version.ts carries the TS mirror. scripts/check-bus-protocol-version.sh requires both to match.
  • Harness parity. scripts/check-bus-harness-parity.sh requires the TS bus fixtures to round-trip through the Swift decoder.
  • No evaluateJavaScript outside WebviewBridge. Grep-gated by scripts/check-no-evaluate-javascript.sh.
  • Single writer to HudState. scripts/check-single-writer-hudstate.sh enforces.

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 Codable
  • Sources/Bus/BusInbound.swift — JS→Swift event union + hand-written Codable
  • Sources/Bus/OutboundBatcher.swift — token-coalescing actor
  • Sources/Bus/WebviewBridge.swift — WKScriptMessageHandler boundary
  • Sources/Bus/Protocol.swift — version constant