# Native macOS CI on the existing Ubuntu runner `tools/ci/MacOsNativeDiagnostic.cs` is a .NET 10 file-based application that owns one temporary macOS VM inside Docker. The PR/push workflow runs it after the existing Ubuntu and Wine jobs. It uses the existing Intel runner, Docker daemon and `/dev/kvm`, with no additional runner label, service, secret or host configuration. The pipeline and its application/test prerequisites are consolidated on `codex/macos-support`, the source branch of PR 39. The older CI branches retain experimental history. The current production configuration uses the Full KVM/NoAVX/RAW controller and its latest bounded resource collector; no separate diagnostic workflow or experimental branch filter is needed. The configuration has not passed remote installation, build or tests. Run [4219](https://gitea.schweigert.cloud/Daniel/meeting-assistant/actions/runs/4219) proved native macOS 13.6/x86_64 but failed eight bounded disk-readiness attempts. Run [4221](https://gitea.schweigert.cloud/Daniel/meeting-assistant/actions/runs/4221) failed both bounded `sw_vers` attempts. Run [4245](https://gitea.schweigert.cloud/Daniel/meeting-assistant/actions/runs/4245) subsequently passed Recovery readiness and entered installation; it was stopped at the user's request before a native build/test result. Local validation checks preparation and ownership contracts, not native CI success. These results do not establish that PR 39 is ready to merge. ## Entrypoints Run from a clean checkout of the commit to test: ```sh dotnet run --file tools/ci/MacOsNativeDiagnostic.cs -- --run --full --recovery-format raw --output artifacts/native-macos-full dotnet run --file tools/ci/MacOsNativeDiagnostic.cs -- --cleanup --output artifacts/native-macos-full ``` The output directory binds the run identity and must be fresh. `git archive HEAD` supplies the exact source to the guest; uncommitted application changes are not included. Cleanup uses the same output directory and removes only the saved container, image and anonymous storage volume with matching ownership labels and IDs. Retained artifacts stay outside that volume. Shared Docker caches are not pruned. For a read-only Recovery check, omit `--full`. That mode does not install an OS or execute application tests. Offline checks use a pristine checkout of the pinned Dockur source and the two pinned compatibility archives: ```sh dotnet run --file tools/ci/MacOsNativeDiagnostic.cs -- --validate --full --recovery-format raw --source /path/to/dockur --cryptex-archive /path/to/CryptexFixup.zip --noavx-archive /path/to/NoAVX.zip --output /path/to/fresh-validation dotnet run --file tools/ci/MacOsNativeGuest.cs -- --validate ``` ## Guest and dependencies The controller pins Dockur source `16a5b470cdd601bae8b05b02d748d7edfb36c12e`, QEMU image digests, OpenCore bytes, CryptexFixup 1.0.5, Lilu 1.7.1 and the OCLP 2.5.1 NoAVX AVXpel 12.6 archive. Hashes and staging/configuration checks live beside their use in the controller. The NoAVX and Cryptex fixes accommodate the existing host CPU without AVX/AVX2; native readiness must still pass. Downloads use existing outbound networking to upstream sources, Apple, Microsoft and NuGet. The guest uses macOS 13, KVM with the real host CPU, two CPUs, 4 GiB RAM and a fresh 64-GiB disk. The container has a 6-GiB memory/swap limit, two CPUs and 512 MiB shared memory. Its sole mapped host device is `/dev/kvm`; no privileged mode, bind mount, host network or published port is used. Full runs check existing free memory and 32 GiB of Docker storage before proceeding. RAW mode converts the patched Recovery DMG with QEMU, verifies sector equality and unchanged source SHA256, and retains both images plus their receipt. QEMU attaches the same read-only virtio device with `format=raw`. Before RAM admission, existing GNU `dd` requests eviction of only the two verified files' caches; it does not clear host caches or raise resource limits. The default CLI format remains DMG; the automatic workflow explicitly selects RAW. After staging, the controller records the immutable Recovery hash once and retains the successful receipt. It does not reread the large DMG on every progress poll. Missing-image or failed captures can retry; they cannot create a successful receipt. The collector also retains CPU, memory and I/O counters from its owned container at most once per minute. Each snapshot has a ten-second deadline and 16-KiB output budget; collection failure cannot qualify or fail a native gate. The optional failure-time `kmutil` probe records loaded Recovery extensions when available. These observations do not alter VM settings or prove a performance cause. The guest receives Microsoft SDK 10.0.401 with its pinned official SHA512 and installs Apple Command Line Tools through headless `softwareupdate`. A compiled framework smoke check verifies the selected CLT/SDK. macOS 13 is outside Microsoft's current .NET 10 OS support: a successful runtime test establishes this tested configuration, not vendor support. The product's Swift helpers already target macOS 13. ## Required proof and side effects Recovery must prove macOS 13+/x86_64, root identity, live native service domains and exactly one writable 64-GiB disk. Before the guest's only erase operation, both host and guest verify the run-owned disk and its emulated serial. A token/commit/disk permit and persistent markers prevent an unqualified or duplicate installation. The erase is confined to that fresh guest disk. The installed guest must map its APFS root back to the same owned disk, validate the source payload, restore/build `net10.0`, compile all four Swift helpers, verify fresh Mach-O/x86_64 output and the audio/desktop app signatures, and discover/run the full test suite. Acceptance requires matching fresh discovery and TRX for the current source, zero failures, all five named native macOS tests explicitly passed, and only the two named Windows-only tests skipped with their platform reasons. The desktop helper lives in `Native/MeetingAssistantDesktopControls.app/Contents/MacOS/macos-desktop-controls`. Real microphone capture, system audio and user privacy consent remain separate operational checks. The workflow limit is 180 minutes, with a 172-minute controller deadline and phase budgets of Recovery 40, installation 80, CLT 30 and build/tests 25 minutes. These phase budgets do not extend the overall deadline. A bounded heartbeat reports the phase and captured guest progress. Failures retain logs and receipts; `finally` and `always()` perform the same owned-resource cleanup. CI artifacts contain source/SDK and boot-asset hashes, container/resource identity, Recovery proof, installation/firstboot/CLT logs, disk/APFS identity, native helper/signature evidence, guest result and binary-preserved TRX. A green Recovery check alone is insufficient; only an exact-source Full result and matching native TRX prove macOS build/test execution. CI does not deploy or restart the workstation application. ## Branch inventory — 2026-10-06 Thirteen distinct macOS branch names were found: ten on the Daniel remote and three only locally. `codex/macos-support` is the delivery branch for application, Windows/portable pipeline, current native controller and their test prerequisites. Its automatic workflow checks the source revision of PR 39. The other names retain prior experiments and are no longer separate delivery targets. | Branch | Location at inventory | Purpose before consolidation | | --- | --- | --- | | `codex/macos-support` | Remote/local | Current delivery branch | | `codex/macos-native-full-kvm-noavx-raw` | Remote/local | Latest VM/resource-observation source, `b15670c` | | `codex/macos-ci-pr39` | Local | Prepared PR integration, `1b9ec14` | | `codex/macos-native-full-kvm-noavx` | Local | Earlier full KVM/NoAVX candidate | | `codex/macos-ci-native` | Local | Earlier integrated native candidate | | `codex/macos-ci-bootstrap-diagnostic` | Remote/local | Bootstrap diagnostic | | `codex/macos-ci-diagnostic` | Remote/local | Recovery diagnostic | | `codex/macos-ci-kvm-compatibility` | Remote/local | Earlier KVM compatibility experiment | | `codex/macos-ci-kvm-diagnostic` | Remote/local | Separate KVM diagnostic | | `codex/macos-ci-tcg-supported` | Remote/local | TCG diagnostic alternative | | `codex/macos-kvm-noavx-recovery` | Remote/local | Earlier NoAVX Recovery experiment | | `codex/macos-native-full-tcg` | Remote/local | Full TCG alternative | | `codex/macos-native-raw-recovery` | Remote/local | Earlier RAW/cache experiment | Local consolidation verification: 655 portable cases discovered on macOS, 653 passed, exactly two named Windows-only skips and zero failures; all five required native cases passed. Both test TFMs built normally, with four existing NAudio deprecation warnings in the Windows cross-build. The platform verifier and native evidence parser accepted the actual discovery/TRX. Both native controller offline contract suites, strict validation of the three affected OpenSpec changes, workflow YAML/dependencies and embedded shell syntax passed. This is local preparation evidence; native Ubuntu/macOS CI qualification remains open.