Commit Graph

3 Commits

Author SHA1 Message Date
b4766d2f24 feat(apple): VoiceCatCore Swift package + XCFramework build for macOS/iOS clients
Lays the groundwork for the macOS (AppKit) and iOS (SwiftUI) clients with a shared
Swift core wrapping the C ABI, mirroring the proven Windows VoiceCat.Interop layer.

Architecture decision: macOS UI = AppKit (not SwiftUI) for the most mature VoiceOver
accessibility story — same rationale as the Windows client's WinForms-over-WinUI-3
decision. iOS stays SwiftUI. Recorded in docs/roadmap.md §2.

Build infrastructure (Phase 0):
- clients/apple/scripts/build-xcframework.sh: runs cmake --preset apple-dev, merges
  libvoicecat.a + 107 vcpkg static deps into a single ~30 MB fat static library
  (libvoicecat-fat.a) via libtool -static (SPM binary targets link one .a per slice),
  stages voicecat.h + a generated module.modulemap (module VoiceCatC) into the headers,
  runs xcodebuild -create-xcframework -> clients/apple/VoiceCatCore.xcframework.

VoiceCatCore Swift Package (Phase 1):
- Package.swift: binary target (VoiceCatCoreXCF) + library (VoiceCatCore) + test target.
- Sources/VoiceCatCore/: 7 files mirroring the C# VoiceCat.Interop patterns adapted to
  Swift native C interop — Enums (9 Swift mirrors of C enums, UInt32-backed), Config,
  Event (copies ev.text to String inside the callback — the #1 lifetime rule), Models
  (10 Swift value types), Marshaling (C arrays -> Swift + immediate vc_free_*),
  Callbacks (@convention(c) + Unmanaged.passUnretained, the Swift analog of C#'s
  [UnmanagedCallersOnly] + GCHandle), VoiceCatClient (owns vc_client* as OpaquePointer,
  all 38 C ABI functions, deinit -> vc_client_destroy then frees config CStrings, event
  delivery on main queue via coalesced DispatchQueue.main drain).

Tests — 6/6 green (swift test against a real voicecat-server):
- testConnectTofuAuthListChannelsRoundTrips, testAdminChannelCrudAccountCrudRoundTrips,
  testScreenAudioStreamStartsAndStops, testPerStreamRecvControlsRoundTrip, plus two
  static smoke tests. Catches Swift-specific interop bugs (@convention(c) callback
  lifetime, Unmanaged pointer resolution, CString memory management, enum raw-value
  bridging, struct layout) that C++ ctest cannot. C++ suite still 21/21 green.

Docs updated (house rule): tech-stack.md §2, architecture.md §4, roadmap.md M4 + §2,
clients/apple/README.md (full rewrite), PROGRESS.md, .gitignore.
2026-06-18 14:20:38 +02:00
1dfe3c95ed chore: gitignore voicecat_tofu_pins.txt test artifact
The TOFU pin store is written by vc_client during headless tests (the
relative fallback path in core/src/core/client.cpp when tofu_store_path
is unset). Ignore it so it doesn't show up as untracked after test runs.
2026-06-18 01:22:11 +02:00
b332b0972b scaffold: M0 skeleton + agent onboarding (build, architecture, progress)
Turn the design into a buildable, dependency-free M0 skeleton plus the
onboarding layer so a new agent can pick up instantly.

Build system:
- CMake + CMakePresets (dev = no deps; server-release = vcpkg) + vcpkg.json
- Skeleton builds with just a C++20 compiler; deps stay off until needed
- .gitattributes (LF), .gitignore, .clang-format

Core (libvoicecat):
- core/include/voicecat.h: full C ABI (the client/server contract), stubbed
- core/proto/voicecat.proto: control-plane wire format, matches docs/protocol.md
- src/{net,crypto,codec,protocol,session,audio,core}: subsystem stubs that
  return VC_ERR_NOT_IMPLEMENTED, each pointing to its design doc
- server/ (voicecat-server) and tools/vccli/ link the core
- tests/: CTest smoke test asserting the C ABI contract (behavior, not just build)
- clients/{apple,windows}: M4 placeholders

Onboarding for agents:
- CLAUDE.md: hub — build/test commands, architecture at a glance, doc map, rules
- AGENTS.md: working method (behavior-driven; clean compile is the floor not the goal)
- PROGRESS.md: living tracker — M0 done, M1 task checklist, "where we left off"

Verified: cmake --preset dev && cmake --build --preset dev && ctest --preset dev → green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 21:09:09 +02:00