1 ---
2 name: forked-dependencies
3 description: The complete inventory of forked crates and [patch.crates-io] overrides that the onde stack depends on — mistral.rs, candle, sysctl, mio, tqdm, core2. Explains what each fork is for, where it is consumed, how the git-vs-published two-tier model works, and how to update or add one. Apply whenever a build fails on a missing/incompatible crate for an Apple or Android target, when bumping the mistral.rs or candle fork, or when adding a new patched dependency.
4 allowed-tools: Read, Write, Edit, Glob, Grep, Bash
5 user-invocable: true
6 ---
7
8 # Skill: Forked Dependencies
9
10 The onde stack pulls several crates from forks instead of crates.io. They exist
11 for three reasons: **platform support** the upstream crate lacks (watchOS,
12 visionOS), **unreleased APIs** a dependency needs before upstream cuts a release
13 (candle), and **registry constraints** (`cargo publish` rejects git deps, so the
14 mistral.rs fork is republished under `onde-*` names).
15
16 This skill is the single source of truth for every fork and patch. When a build
17 breaks on a missing symbol or unsupported target, or you are bumping a fork,
18 start here.
19
20 ---
21
22 ## The two-tier consumption model (read this first)
23
24 There are two distinct ways the same dependency tree gets built, and they
25 resolve forks differently. Almost every confusing bug in this area comes from
26 mixing them up.
27
28 1. **Building the mistral.rs fork from source** (its own CI, or `onde` local dev
29 with the git override uncommented). Here the fork's `Cargo.toml` git deps and
30 `[patch.crates-io]` entries apply directly.
31
32 2. **Publishing to crates.io** (`cargo publish` of the `onde-mistralrs-*`
33 crates). **`cargo publish` strips every `git =` field and the entire
34 `[patch.crates-io]` table.** Published crates fall back to the `version = "..."`
35 registry requirement on each dep. So a git-only dep is invisible to anyone
36 installing from crates.io.
37
38 3. **onde consuming the published crates.** onde depends on the registry
39 `onde-mistralrs-*` crates, so it gets the *registry-resolved* tree — the
40 stripped-down one from step 2, not the fork's git tree. onde then re-applies
41 whatever patches it still needs in **its own** `[patch.crates-io]`. Those
42 apply to onde's from-source CI builds (Swift XCFramework, Android/Kotlin,
43 the `cargo check` matrix) but are themselves stripped when onde publishes to
44 crates.io.
45
46 **Consequence that used to bite (now fixed — kept as the canonical example):**
47 originally the `tqdm` fork bumped crossterm to 0.29 (which pulls mio 1.x, which
48 supports visionOS) but was a *git* dep of mistral.rs, so it was stripped on
49 publish. onde therefore resolved crates.io `tqdm 0.8.0` → `crossterm 0.25` →
50 `mio 0.8.11`, which does *not* support visionOS — so onde needed its own `mio`
51 visionOS patch even though the tqdm fork "already fixed" crossterm upstream of
52 it.
53
54 The fix that removed the whole problem: the crossterm-0.29 tqdm fork is now
55 **published to crates.io as `onde-tqdm`** and consumed by the mistral.rs fork as
56 a `version =` registry dep (package rename), exactly like `onde-mistralrs-*` and
57 `onde-candle-*`. A registry dep survives publish, so onde's registry-resolved
58 tree gets `onde-tqdm` → `crossterm 0.29` → `mio 1.x`, and the `mio 0.8.11`
59 line disappears entirely. This is now **done**: `onde-mistralrs-*` 0.9.3
60 (carrying the `onde-tqdm` dep) is published, onde consumes 0.9.3, and onde's
61 `[patch.crates-io] mio` entry has been **deleted**. The `mio` fork is retired.
62 See the onde-tqdm and mio entries.
63
64 ---
65
66 ## Inventory
67
68 | Crate | Fork / source | Ref | Purpose | Consumed where |
69 |-------|---------------|-----|---------|----------------|
70 | mistral.rs (12 crates) | `setoelkahfi/mistral.rs` | branch `fix/all-platform-fixes` | All-platform fixes; **published** as `onde-mistralrs-*` | onde deps (registry) |
71 | candle-core, candle-nn | `setoelkahfi/candle` | branch `onde/candle-0.11.0-27f20fea` (rev `27f20fea`) | Post-0.11.0 candle APIs; **published** as `onde-candle-{core,nn}` | mistral.rs fork deps (registry) |
72 | tqdm | `setoelkahfi/tqdm` | branch `release/onde-tqdm` (version `0.8.2`) | Bumps crossterm to 0.29 (→ mio 1.x); **published** as `onde-tqdm` | mistral.rs fork dep (registry) |
73 | sysctl | `setoelkahfi/sysctl-rs` | branch `feature/watchos` | watchOS (`target_os = "watchos"`) support | `[patch.crates-io]` in onde **and** mistral.rs fork |
74 | mio | `setoelkahfi/mio` | branch `feature/visionos` | visionOS support for the `mio 0.8.11` line | **RETIRED** — patch removed from onde once it consumed onde-mistralrs 0.9.3 (onde-tqdm → mio 1.x). Fork kept for history/upstream PR. |
75
76 > **Retired:** `core2` (`bbqsrc/core2` rev `545e84bc`) — was a `[patch.crates-io]`
77 > workaround for the yanked `core2 0.4.0`; removed from the mistral.rs fork after
78 > `bitstream-io` 4.x dropped `core2`. No longer present.
79
80 ---
81
82 ## Per-fork detail
83
84 ### mistral.rs → `onde-mistralrs-*`
85
86 - **Fork:** `setoelkahfi/mistral.rs`, branch `fix/all-platform-fixes`.
87 - **Why:** carries fixes upstream hasn't merged (iOS 32-bit memory limits,
88 watchOS/visionOS Metal compile, Android 32-bit const overflows, HF cache
89 seeding, metallib link flags, and more).
90 - **Published as:** `onde-mistralrs`, `-core`, `-quant`, `-paged-attn`,
91 `-flash-attn`, `-metal-compile`, `-code-exec`, `-sandbox`, `-macros`,
92 `-vision`, `-audio`, `-mcp`. The rename is a `package = "onde-..."` override on
93 each workspace dep entry, so Rust source still `use`s `mistralrs_*` unchanged.
94 - **Publishing + bump flow:** see [[sdk-regressions]] (the 12-crate publish
95 order, the candle Step 0, and the tqdm/core2 publish-verification snags).
96
97 ### candle → `onde-candle-{core,nn}`
98
99 - **Fork:** `setoelkahfi/candle`, branch `onde/candle-<ver>-<rev>` (currently
100 `onde/candle-0.11.0-27f20fea`).
101 - **Why:** mistral.rs pins a candle git rev past the latest release for APIs no
102 published candle has (`QTensor::indexed_gemv`, `gemv_fused_shared_lhs`,
103 `BarrierPool::execute_chunked`). Publishing the `onde-mistralrs-*` crates
104 fails verification (E0080/E0599) if their candle dep resolves to the released
105 crate, so the pinned rev is republished under `onde-candle-*`.
106 - **Only the diverged crates are renamed.** At the 0.11.0 rev only `candle-core`
107 and `candle-nn` differ from the release; `candle-metal-kernels` and
108 `candle-flash-attn-v3` are byte-identical, so the mistral.rs fork points those
109 at the official `0.11.0` crates. `candle-nn` must be republished whenever
110 `candle-core` is (even if unchanged) or the official `candle-nn` drags the
111 official `candle-core` back into the graph → two `candle-core` crates → type
112 mismatch.
113
114 ### sysctl → watchOS
115
116 - **Fork:** `setoelkahfi/sysctl-rs`, branch `feature/watchos`. Upstream PR:
117 johalun/sysctl-rs#74.
118 - **Why:** upstream sysctl has no `target_os = "watchos"` support.
119 - **Applied in:** `[patch.crates-io]` in **both** onde and the mistral.rs fork
120 (each workspace root that builds for watchOS needs its own patch entry).
121
122 ### mio → visionOS (RETIRED)
123
124 - **Status:** the onde `[patch.crates-io] mio` entry has been **removed**. onde
125 now consumes `onde-mistralrs 0.9.3`, whose `onde-tqdm` dep pulls `crossterm
126 0.29 → mio 1.x`, so `mio 0.8.11` is gone from onde's tree. The fork below is
127 kept only for history and a possible upstream PR; it is no longer wired into
128 any build.
129 - **Fork:** `setoelkahfi/mio`, branch `feature/visionos` (commit `683fca8`).
130 Based on `mio 0.8.11`. This is the **official GitHub fork** of tokio-rs/mio
131 (in tokio's fork network, so it can open upstream PRs). An earlier standalone
132 clone that carried this branch was renamed to `setoelkahfi/mio-patch` and
133 deleted; the branch now lives on the real fork.
134 - **Why:** `mio 0.8.11` hits `compile_error!("unsupported target for
135 mio::unix::pipe")` on visionOS, and its Apple cfg gates (kqueue `Filter`/
136 `Flags` type aliases, `net.rs` `sin_len`/`sin6_len`, `tcp.rs` accept path,
137 `uds/listener.rs` `accept4`/`SOCK_NONBLOCK`) omit visionos, breaking the Swift
138 XCFramework build and the visionOS CI checks. The fork adds
139 `target_os = "visionos"` to every cfg gate that already lists `tvos`/`watchos`.
140 tokio's `mio 1.x` already supports visionOS, so **only the 0.8.x line** needs it.
141 - **Where 0.8.11 came from:** `tqdm → crossterm 0.25 → mio 0.8.11`, and
142 `signal-hook-mio → crossterm`. Not from tokio (that uses `mio 1.2.2`).
143 - **Applied in:** *(historical)* was `[patch.crates-io]` in onde. The fork's
144 version (`0.8.11`) stayed semver-compatible with the `^0.8` requirement it
145 replaced; it did not touch tokio's `^1`.
146 - **How it was retired (the real fix):** the `onde-tqdm` publish (below) removed
147 the `mio 0.8.11` line from onde's registry-resolved tree entirely. Verified:
148 with onde consuming the onde-tqdm-carrying `onde-mistralrs 0.9.3` crates, onde's
149 lockfile resolves `mio 1.2.2` only — no 0.8.11 — and both visionOS targets
150 (`aarch64-apple-visionos{,-sim}`) `cargo +nightly check -Z build-std` pass with
151 the `mio` patch deleted.
152
153 ### tqdm → crossterm 0.29 → `onde-tqdm`
154
155 - **Fork:** `setoelkahfi/tqdm`. Two branches:
156 - `deps/bump-crossterm` — keeps the crate named `tqdm`, feeds the **upstream
157 PR** mrlazy1708/tqdm#28 (do not rename the package here).
158 - `release/onde-tqdm` — sets `package = "onde-tqdm"` (crate lib name stays
159 `tqdm` so downstream `use tqdm::…` and doctests are unchanged) and is
160 **published to crates.io as `onde-tqdm`** (0.8.1, 0.8.2).
161 - **Why:** bumps crossterm to 0.29 (→ mio 1.x), eliminating the whole `mio
162 0.8.11` visionOS problem at its source.
163 - **Consumed in:** the mistral.rs fork's `[workspace.dependencies]` as
164 `tqdm = { version = "0.8.2", package = "onde-tqdm" }` — a **registry** rename
165 dep, so it survives `cargo publish` and reaches onde (unlike the old git dep,
166 which was stripped). This is the same rename trick as `onde-mistralrs-*` and
167 `onde-candle-*`.
168 - **Publish order:** publish `onde-tqdm` **before** republishing the
169 `onde-mistralrs-*` crates that depend on it. Note the published
170 `onde-mistralrs-core 0.9.2` still uses plain `tqdm ^0.8.0` (pre-rename); the
171 `onde-tqdm` dep first ships in `0.9.3`.
172
173 ### core2 → removed
174
175 - **Was:** `bbqsrc/core2` rev `545e84bc`, a `[patch.crates-io]` workaround for
176 the yanked `core2 0.4.0` (pulled via `bitstream-io → rav1e → ravif → image`).
177 - **Status:** **deleted** from the mistral.rs fork. `bitstream-io` 4.x moved off
178 `core2` (to `no_std_io2`), so nothing pulls it. Removed in the same commit that
179 wired `onde-tqdm` and bumped to 0.9.3.
180
181 ---
182
183 ## Operational gotchas (hit these during the 1.2.1 release)
184
185 - **A patched fork must be pushed to GitHub before the patch works in CI.** The
186 `mio` fork existed only locally; the patch URL 404'd until it was pushed to
187 `setoelkahfi/mio`. Verify with `git ls-remote <url> <branch>` before relying
188 on a patch.
189 - **Shallow clones cannot be pushed** (`remote unpack failed: index-pack
190 failed`). If a fork was cloned shallow, `git fetch --unshallow <upstream>`
191 first, then push.
192 - **Local fork fetches need `CARGO_NET_GIT_FETCH_WITH_CLI=true`.** This machine
193 rewrites GitHub URLs to SSH aliases; cargo's built-in fetcher can't auth, so
194 export that var (or run the `cargo update` that pulls the fork with it). CI
195 fetches public https forks fine without it — same as the long-standing sysctl
196 patch.
197 - **`[patch.crates-io]` version must be semver-compatible** with the requirement
198 it replaces. A `0.8.11` fork replaces `^0.8`, not a `^1` requirement of the
199 same crate — which is how the `mio` patch touches only the crossterm line and
200 leaves tokio's `mio 1.x` alone.
201 - **Forks are public** (mio, sysctl-rs, tqdm are MIT/Apache): keep the upstream
202 `LICENSE` intact. See [[legal-and-trademarks]] for attribution obligations
203 (candle and mistral.rs especially).
204
205 ---
206
207 ## Adding a new patch
208
209 1. Fork upstream, add the fix on a descriptive branch, **push it public** to
210 `setoelkahfi/<crate>`, keep the `LICENSE`.
211 2. Add to `[patch.crates-io]` in every workspace root that builds the affected
212 target (onde, and the mistral.rs fork if it builds there too). Match the
213 fork's crate version to the requirement being replaced.
214 3. `CARGO_NET_GIT_FETCH_WITH_CLI=true cargo update -p <crate>@<ver>` to move the
215 lockfile onto the git source; verify `source = "git+..."` in `Cargo.lock`.
216 4. If it fixes a mistral.rs-fork build (not just onde), remember it is stripped
217 on publish — onde will still need its own copy of the patch unless the fix
218 also lands in a published `onde-*` crate.
219 5. `cargo check` on host, then let CI validate the target that was failing.
220
221 ---
222
223 *Update this skill whenever a fork's branch/rev changes, a patch is added or
224 removed, or a fork gets published under an `onde-*` name.*