build/platform: macOS remains unsupported and plugin-host cfg paths lack CI #59

Open
opened 2026-08-05 08:32:22 +02:00 by buildagent · 1 comment
Member

Decision record + tracking issue for the deliberate deferral of macOS release builds, and for the coverage hole that deferral leaves behind.

Decision: macOS builds are deferred

x86_64-apple-darwin and aarch64-apple-darwin are not built and not published. This is intentional, not a build failure. Every release from v0.8.4 through v0.9.0 has shipped four artifacts:

Shipped Deferred
linux-x86_64 (glibc) macos-x86_64
linux-x86_64-musl (static) macos-aarch64
linux-aarch64 windows-aarch64 (needs Windows+MSVC runner)
windows-x86_64

The matrix entries in .forgejo/workflows/release.yml were already commented out (not merely continue-on-error) because a matrix entry whose runs-on label has no registered runner does not fail — it queues forever and hangs the whole run. continue-on-error tolerates failures, never never-scheduled jobs. That distinction is why commenting out is the correct mechanism here.

The README/packaging steps still carry macos-x86_64 / macos-aarch64 case arms. Those are deliberately kept pre-wired so re-enabling is a pure uncomment.

The part that is NOT just cosmetic

There is a windows-check CI job that cross-compiles --target x86_64-pc-windows-gnu to keep Windows-only code honest. There is no macOS equivalent. So these paths are compiled by nothing, anywhere in CI:

  • crates/indexer/src/watcher.rs — #[cfg(any(target_os = "windows", target_os = "macos"))] single recursive watch (FSEvents native subtree subscription), and the IN_Q_OVERFLOW/FSEvents overflow handling
  • crates/daemon/src/lifecycle.rs — #[cfg(target_os = "macos")] stale-PID detection, and the Linux/macOS flock EWOULDBLOCK path
  • crates/indexer/tests/watcher.rs / periodic_reconcile.rs — assertions gated on cfg!(target_os = "macos") that consequently never execute

These can bit-rot silently: a refactor that breaks the macOS arm produces a green CI run. Given the project's standing parity requirement (all languages × 3 OSes × 2 arches), this is the actual debt — not the missing binaries.

Why a cheap check-only gate does not work

cargo check --target aarch64-apple-darwin from the Linux container is not sufficient. cargo check still runs build scripts, and the seven tree-sitter-* grammar crates each compile C via cc in build.rs. That needs a darwin C toolchain (osxcross + the Apple SDK), not just rustup target add. So the options are:

  1. Register a macOS runner (labelled macos, with Xcode CLT) → uncomment the two matrix entries; real builds and real tests.
  2. osxcross + Apple SDK in ci-base → enables a macos-check compile gate, and possibly full cross-builds. Note the Apple SDK has redistribution constraints; this needs a licensing look before baking it into a shared image.
  3. Accept the hole (status quo) → macOS users build from source; the cfg paths stay unverified.

Acceptance

  • Decide between options 1–3 above
  • If 1 or 2: uncomment the matrix entries, confirm 6 archives + 6 .sha256 publish, and add a macos-check job alongside windows-check
  • If 3: keep this issue open as the standing record; no code change
  • Either way: release notes must not imply macOS artifacts are imminent

Status

release.yml header comments and the release-notes footer are being corrected to state the deferral plainly (they previously described macOS as an attempted "best-effort" target, contradicting the disabled matrix entries).

Runtime-plugin architecture impact

#79 introduces a new helper executable, process containment, handle inheritance, timeout/kill behavior and dynamic WASM runtime. None of those paths may be advertised on macOS while macOS has no compile or runtime gate.

Until a runner/toolchain exists:

  • plugin package manifests and documentation list macOS host support as unavailable, not untested-but-probably-working;
  • #80’s “every shipped platform” gate excludes macOS because no macOS artifact ships;
  • enabling macOS artifacts requires a real dynamic-grammar load, timeout, trap, child-process cleanup and filesystem/network-claim smoke test in addition to compiling existing cfg arms;
  • pre-wired release cases must include the plugin-host binary and version handshake before uncommenting the matrix.

This issue stays open as the explicit platform-support decision record.

Decision record + tracking issue for the deliberate deferral of macOS release builds, and for the coverage hole that deferral leaves behind. ## Decision: macOS builds are deferred `x86_64-apple-darwin` and `aarch64-apple-darwin` are **not built and not published**. This is intentional, not a build failure. Every release from v0.8.4 through v0.9.0 has shipped four artifacts: | Shipped | Deferred | |---|---| | linux-x86_64 (glibc) | macos-x86_64 | | linux-x86_64-musl (static) | macos-aarch64 | | linux-aarch64 | windows-aarch64 (needs Windows+MSVC runner) | | windows-x86_64 | | The matrix entries in `.forgejo/workflows/release.yml` were already commented out (not merely `continue-on-error`) because a matrix entry whose `runs-on` label has no registered runner does **not** fail — it queues forever and hangs the whole run. `continue-on-error` tolerates *failures*, never *never-scheduled* jobs. That distinction is why commenting out is the correct mechanism here. The README/packaging steps still carry `macos-x86_64` / `macos-aarch64` `case` arms. Those are deliberately kept pre-wired so re-enabling is a pure uncomment. ## The part that is NOT just cosmetic There is a `windows-check` CI job that cross-compiles `--target x86_64-pc-windows-gnu` to keep Windows-only code honest. **There is no macOS equivalent.** So these paths are compiled by nothing, anywhere in CI: - `crates/indexer/src/watcher.rs` — `#[cfg(any(target_os = "windows", target_os = "macos"))]` single recursive watch (FSEvents native subtree subscription), and the `IN_Q_OVERFLOW`/FSEvents overflow handling - `crates/daemon/src/lifecycle.rs` — `#[cfg(target_os = "macos")]` stale-PID detection, and the Linux/macOS `flock` `EWOULDBLOCK` path - `crates/indexer/tests/watcher.rs` / `periodic_reconcile.rs` — assertions gated on `cfg!(target_os = "macos")` that consequently never execute These can bit-rot silently: a refactor that breaks the macOS arm produces a green CI run. Given the project's standing parity requirement (all languages × 3 OSes × 2 arches), this is the actual debt — not the missing binaries. ## Why a cheap check-only gate does not work `cargo check --target aarch64-apple-darwin` from the Linux container is not sufficient. `cargo check` still **runs build scripts**, and the seven `tree-sitter-*` grammar crates each compile C via `cc` in `build.rs`. That needs a darwin C toolchain (osxcross + the Apple SDK), not just `rustup target add`. So the options are: 1. **Register a macOS runner** (labelled `macos`, with Xcode CLT) → uncomment the two matrix entries; real builds and real tests. 2. **osxcross + Apple SDK in `ci-base`** → enables a `macos-check` compile gate, and possibly full cross-builds. Note the Apple SDK has redistribution constraints; this needs a licensing look before baking it into a shared image. 3. **Accept the hole** (status quo) → macOS users build from source; the cfg paths stay unverified. ## Acceptance - [ ] Decide between options 1–3 above - [ ] If 1 or 2: uncomment the matrix entries, confirm 6 archives + 6 `.sha256` publish, and add a `macos-check` job alongside `windows-check` - [ ] If 3: keep this issue open as the standing record; no code change - [ ] Either way: release notes must not imply macOS artifacts are imminent ## Status `release.yml` header comments and the release-notes footer are being corrected to state the deferral plainly (they previously described macOS as an attempted "best-effort" target, contradicting the disabled matrix entries). ## Runtime-plugin architecture impact #79 introduces a new helper executable, process containment, handle inheritance, timeout/kill behavior and dynamic WASM runtime. None of those paths may be advertised on macOS while macOS has no compile or runtime gate. Until a runner/toolchain exists: - plugin package manifests and documentation list macOS host support as unavailable, not untested-but-probably-working; - #80’s “every shipped platform” gate excludes macOS because no macOS artifact ships; - enabling macOS artifacts requires a real dynamic-grammar load, timeout, trap, child-process cleanup and filesystem/network-claim smoke test in addition to compiling existing cfg arms; - pre-wired release cases must include the plugin-host binary and version handshake before uncommenting the matrix. This issue stays open as the explicit platform-support decision record.
buildagent changed title from build: macOS release builds DEFERRED — and the macOS cfg paths are compiled by nothing in CI to build/platform: macOS remains unsupported and plugin-host cfg paths lack CI 2026-08-26 13:39:31 +02:00
Author
Member

Triage 2026-09-06: LEFT OPEN — correctly, by its own acceptance. Option 3 was chosen; this issue is the standing record. Its text should say so.

The decision was taken, and the reason is measured rather than asserted

crates/daemon/tests/platform_support_claims.rs:1-64 records the actual cargo check --target x86_64-apple-darwin failure (tree-sitter build.rs → cc for the target) as the cost of option 2. That is the right way to decline work — with the number that made declining correct, not an estimate.

.forgejo/workflows/release.yml:601-638 still has both darwin entries commented out, deliberately, with the never-scheduled-job reasoning intact.

The doc-honesty half landed and is gated

platform_support_claims.rs — 5 tests: the matrix parses both halves, no live Apple target, the README archive list matches the matrix in both directions, no document promises macOS, and a ledger of macOS-cfg files. Sibling: crates/daemon/tests/readme_security_claims.rs:103, sharing crates/daemon/tests/support/claims.rs.

cargo test -p code-index-daemon --test platform_support_claims → 5 passed, EXIT 0

The ledger has already earned its keep: it caught crates/daemon/src/takeover.rs growing macOS arms after this issue was written. That is a fact this issue's body does not have.

The CI hole is untouched, and that is the open half

.forgejo/workflows/ci.yml jobs are fmt, clippy, msrv, windows-check, deny, docs, test, test-daemon-leg, corpus, corpus-scale, plugin-path-cost, grammar-rebuild — no macos-check. So the macOS cfg paths still compile nowhere, and the ledger records which files carry them rather than proving they build.

What this issue's text should become

Option 3 means "keep this issue open as the standing record", so it stays open — but it currently reads as an undecided question. It should say:

  1. The decision is made: option 3. macOS is not a supported target; the measured reason is at platform_support_claims.rs:1-64.
  2. What is gated: every shipped document's platform claims, in both directions, plus a ledger of macOS-cfg code.
  3. What remains: no macos-check job, so those cfg paths are uncompiled — and takeover.rs has joined the ledger since filing.

That turns a stale open question into an accurate standing record, which is what option 3 asked for.

🤖 Triage lane, 2026-09-06, master 45cf6e4

## Triage 2026-09-06: LEFT OPEN — **correctly, by its own acceptance.** Option 3 was chosen; this issue *is* the standing record. Its text should say so. ### The decision was taken, and the reason is measured rather than asserted `crates/daemon/tests/platform_support_claims.rs:1-64` records the actual `cargo check --target x86_64-apple-darwin` failure (tree-sitter `build.rs` → `cc` for the target) as the **cost of option 2**. That is the right way to decline work — with the number that made declining correct, not an estimate. `.forgejo/workflows/release.yml:601-638` still has both darwin entries commented out, deliberately, with the never-scheduled-job reasoning intact. ### The doc-honesty half landed and is gated `platform_support_claims.rs` — 5 tests: the matrix parses both halves, no live Apple target, the README archive list matches the matrix **in both directions**, no document promises macOS, and a **ledger of macOS-`cfg` files**. Sibling: `crates/daemon/tests/readme_security_claims.rs:103`, sharing `crates/daemon/tests/support/claims.rs`. ``` cargo test -p code-index-daemon --test platform_support_claims → 5 passed, EXIT 0 ``` The ledger has already earned its keep: it caught `crates/daemon/src/takeover.rs` **growing macOS arms after this issue was written**. That is a fact this issue's body does not have. ### The CI hole is untouched, and that is the open half `.forgejo/workflows/ci.yml` jobs are `fmt, clippy, msrv, windows-check, deny, docs, test, test-daemon-leg, corpus, corpus-scale, plugin-path-cost, grammar-rebuild` — **no `macos-check`**. So the macOS `cfg` paths still compile nowhere, and the ledger records which files carry them rather than proving they build. ### What this issue's text should become Option 3 means *"keep this issue open as the standing record"*, so it stays open — but it currently reads as an undecided question. It should say: 1. **The decision is made: option 3.** macOS is not a supported target; the measured reason is at `platform_support_claims.rs:1-64`. 2. **What is gated:** every shipped document's platform claims, in both directions, plus a ledger of macOS-`cfg` code. 3. **What remains:** no `macos-check` job, so those `cfg` paths are uncompiled — and `takeover.rs` has joined the ledger since filing. That turns a stale open question into an accurate standing record, which is what option 3 asked for. 🤖 Triage lane, 2026-09-06, master `45cf6e4`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
h-dv/code-index#59
No description provided.