@@ -89,90 +89,104 @@ defmodule Trinity.MixProject do
8989 # Specifies your project dependencies.
9090 #
9191 # Type `mix help deps` for examples and options.
92+ # Slice 032: EXLA is the local embedder's backend and has no Windows build (xla 0.10.0
93+ # ships archives for Linux and macOS, x86_64 and aarch64, none for Windows, and building
94+ # XLA from source needs Bazel), so a Windows host does not declare it: the tree compiles
95+ # there, `Trinity.Memory.Embedders.Bumblebee.availability/0` answers
96+ # `{:off, :no_local_backend}`, and the semantic tier is off until a Windows backend exists
97+ # (NOTES decision 3). The lock file carries exla either way; `mix deps.get` leaves an
98+ # undeclared lock entry alone.
99+ defp exla_deps do
100+ case :os . type ( ) do
101+ { :win32 , _ } -> [ ]
102+ _ -> [ { :exla , "~> 0.13.1" } ]
103+ end
104+ end
105+
92106 defp deps do
93- [
94- { :phoenix , "~> 1.8.13" } ,
95- { :phoenix_ecto , "~> 4.5 " } ,
96- { :ecto_sql , "~> 3.13 " } ,
97- { :ecto_sqlite3 , ">= 0.0.0 " } ,
98- # Slice 010: the CI-tested alternative behind TRINITY_DB=postgres (docs/adr/0002).
99- # Optional so the standalone desktop build carries no Postgres driver; the CI matrix
100- # job compiles with the variable set and proves the migrations on both.
101- { :postgrex , ">= 0.0.0" , optional: true } ,
102- # Slice 011: the provider layer behind Trinity.LLM (docs/adr/0003). What it brings into
103- # mix.lock is counted in the slice's NOTES.md, because the desktop binary carries it.
104- { :req_llm , "~> 1.22" } ,
105- # Slice 013: the chat's markdown renderer, behind TrinityWeb.Markdown. Chosen by the
106- # measurement in the slice 's NOTES.md; it brings a Rust NIF (mdex_native), precompiled.
107- { :mdex , "~> 0.13" } ,
108- # Slice 020: JSON Schema validation of tool arguments (Trinity.Tools.Schema). Already in
109- # the lock through req_llm; direct because a module of ours calls it (ADR-0009).
110- { :jsv , "~> 0.23" } ,
111- # Slice 021: RFC 8785 canonical JSON under every approval fingerprint (docs/07). Chosen
112- # by the measurement in the slice's NOTES.md; the RFC's vector is a test in the tree.
113- { :jcs , "~> 0.2" } ,
114- # Slice 022: HTML to text for web_fetch (Trinity.Tools.Web.Fetch).
115- { :floki , "~> 0.38" } ,
116- # Slice 032: local embeddings (Trinity.Memory.Embedders.Bumblebee). The 0.13 line of nx
117- # and exla is what bumblebee 0.7.1 accepts (nx 1.0.0 shipped 2026-09-10 and bumblebee has
118- # no release for it at G1); measured for bundle size and latency in the slice's NOTES.md.
119- { :nx , "~> 0.13.1" } ,
120- { :exla , "~> 0.13.1" } ,
121- { :bumblebee , "~> 0.7.1" } ,
122- # Slice 032: vectors on the Postgres job (Trinity.Memory.VectorStores.Pgvector).
123- { :pgvector , "~> 0.4.1" } ,
124- # Slice 013 (owner decision, 2026-09-20): the linux package builds mdex's NIF from
125- # source for musl (MDEX_NATIVE_BUILD=1 and TRINITY_NIF_TARGET in config/config.exs),
126- # because neither precompiled artifact loads in Burrito's musl ERTS (NOTES finding 13).
127- # rustler_precompiled needs Rustler present to run that build; build time only.
128- { :rustler , "~> 0.38" , runtime: false } ,
129- { :phoenix_html , "~> 4.1" } ,
130- { :phoenix_live_reload , "~> 1.2" , only: :dev } ,
131- { :phoenix_live_view , "~> 1.2.0" } ,
132- { :lazy_html , ">= 0.1.0" , only: :test } ,
133- { :phoenix_live_dashboard , "~> 0.8.3" } ,
134- { :esbuild , "~> 0.10" , runtime: Mix . env ( ) == :dev } ,
135- { :tailwind , "~> 0.5" , runtime: Mix . env ( ) == :dev } ,
136- { :heroicons ,
137- github: "tailwindlabs/heroicons" ,
138- tag: "v2.2.0" ,
139- sparse: "optimized" ,
140- app: false ,
141- compile: false ,
142- depth: 1 } ,
143- { :daisyui ,
144- github: "saadeghi/daisyui" ,
145- tag: "v5.5.20" ,
146- sparse: "packages/bundle" ,
147- app: false ,
148- compile: false ,
149- depth: 1 } ,
150- { :telemetry_metrics , "~> 1.0" } ,
151- { :telemetry_poller , "~> 1.0" } ,
152- { :gettext , "~> 1.0" } ,
153- { :jason , "~> 1.2" } ,
154- { :dns_cluster , "~> 0.2.0" } ,
155- { :bandit , "~> 1.5" } ,
156- # Slice 000: the gate's own tooling. Nothing else yet.
157- { :boundary , "~> 0.10" , runtime: false } ,
158- { :credo , "~> 1.7" , only: [ :dev , :test ] , runtime: false } ,
159- { :mox , "~> 1.2" , only: :test } ,
160- { :mix_audit , "~> 2.1" , only: [ :dev , :test ] , runtime: false } ,
161- { :sobelow , "~> 0.15" , only: [ :dev , :test ] , runtime: false } ,
162- { :ex_doc , "~> 0.38" , only: :dev , runtime: false } ,
163- { :nimble_options , "~> 1.1" } ,
164- # Slice 001 line 1, arm (a) recorded `only: :dev`. **Corrected at G4**, and the reason is
165- # the shell, not the tooling: `ExTauri.ShutdownManager` is the sidecar's heartbeat, the
166- # Rust window's only way to tell the BEAM it has closed, so it has to exist in the
167- # binary that ships, and a `:dev`-only dependency does not. `mix ex_tauri.install` adds
168- # that child unconditionally, which is why the generator's output could not start under
169- # MIX_ENV=test or MIX_ENV=prod. Recorded as deviation D7 in NOTES.md.
170- { :ex_tauri , "~> 0.2" } ,
171- # Slice 001 line 3. `ex_tauri` already depends on burrito, but only in :dev, and
172- # `&Burrito.wrap/1` is a release step that runs under MIX_ENV=prod. Declared directly so
173- # the module exists in the environment that calls it.
174- { :burrito , "~> 1.6" }
175- ] ++ posix_deps ( )
107+ exla_deps ( ) ++
108+ [
109+ { :phoenix , "~> 1.8.13 " } ,
110+ { :phoenix_ecto , "~> 4.5 " } ,
111+ { :ecto_sql , "~> 3.13 " } ,
112+ { :ecto_sqlite3 , ">= 0.0.0" } ,
113+ # Slice 010: the CI-tested alternative behind TRINITY_DB=postgres (docs/adr/0002).
114+ # Optional so the standalone desktop build carries no Postgres driver; the CI matrix
115+ # job compiles with the variable set and proves the migrations on both.
116+ { :postgrex , ">= 0.0.0" , optional: true } ,
117+ # Slice 011: the provider layer behind Trinity.LLM (docs/adr/0003). What it brings into
118+ # mix.lock is counted in the slice's NOTES.md, because the desktop binary carries it.
119+ { :req_llm , "~> 1.22" } ,
120+ # Slice 013: the chat 's markdown renderer, behind TrinityWeb.Markdown. Chosen by the
121+ # measurement in the slice's NOTES.md; it brings a Rust NIF (mdex_native), precompiled.
122+ { :mdex , "~> 0.13" } ,
123+ # Slice 020: JSON Schema validation of tool arguments (Trinity.Tools.Schema). Already in
124+ # the lock through req_llm; direct because a module of ours calls it (ADR-0009).
125+ { :jsv , "~> 0.23" } ,
126+ # Slice 021: RFC 8785 canonical JSON under every approval fingerprint (docs/07). Chosen
127+ # by the measurement in the slice's NOTES.md; the RFC's vector is a test in the tree.
128+ { :jcs , "~> 0.2" } ,
129+ # Slice 022: HTML to text for web_fetch (Trinity.Tools.Web.Fetch).
130+ { :floki , "~> 0.38" } ,
131+ # Slice 032: local embeddings (Trinity.Memory.Embedders.Bumblebee). The 0.13 line of nx
132+ # and exla is what bumblebee 0.7.1 accepts (nx 1.0.0 shipped 2026-09-10 and bumblebee has
133+ # no release for it at G1); measured for bundle size and latency in the slice's NOTES.md.
134+ { :nx , "~> 0.13.1" } ,
135+ { :bumblebee , "~> 0.7.1" } ,
136+ # Slice 032: vectors on the Postgres job (Trinity.Memory.VectorStores.Pgvector).
137+ { :pgvector , "~> 0.4.1" } ,
138+ # Slice 013 (owner decision, 2026-09-20): the linux package builds mdex's NIF from
139+ # source for musl (MDEX_NATIVE_BUILD=1 and TRINITY_NIF_TARGET in config/config.exs),
140+ # because neither precompiled artifact loads in Burrito's musl ERTS (NOTES finding 13).
141+ # rustler_precompiled needs Rustler present to run that build; build time only.
142+ { :rustler , "~> 0.38" , runtime: false } ,
143+ { :phoenix_html , "~> 4.1" } ,
144+ { :phoenix_live_reload , "~> 1.2" , only: :dev } ,
145+ { :phoenix_live_view , "~> 1.2.0" } ,
146+ { :lazy_html , ">= 0.1.0" , only: :test } ,
147+ { :phoenix_live_dashboard , "~> 0.8.3" } ,
148+ { :esbuild , "~> 0.10" , runtime: Mix . env ( ) == :dev } ,
149+ { :tailwind , "~> 0.5" , runtime: Mix . env ( ) == :dev } ,
150+ { :heroicons ,
151+ github: "tailwindlabs/heroicons" ,
152+ tag: "v2.2.0" ,
153+ sparse: "optimized" ,
154+ app: false ,
155+ compile: false ,
156+ depth: 1 } ,
157+ { :daisyui ,
158+ github: "saadeghi/daisyui" ,
159+ tag: "v5.5.20" ,
160+ sparse: "packages/bundle" ,
161+ app: false ,
162+ compile: false ,
163+ depth: 1 } ,
164+ { :telemetry_metrics , "~> 1.0" } ,
165+ { :telemetry_poller , "~> 1.0" } ,
166+ { :gettext , "~> 1.0" } ,
167+ { :jason , "~> 1.2" } ,
168+ { :dns_cluster , "~> 0.2.0" } ,
169+ { :bandit , "~> 1.5" } ,
170+ # Slice 000: the gate's own tooling. Nothing else yet.
171+ { :boundary , "~> 0.10" , runtime: false } ,
172+ { :credo , "~> 1.7" , only: [ :dev , :test ] , runtime: false } ,
173+ { :mox , "~> 1.2" , only: :test } ,
174+ { :mix_audit , "~> 2.1" , only: [ :dev , :test ] , runtime: false } ,
175+ { :sobelow , "~> 0.15" , only: [ :dev , :test ] , runtime: false } ,
176+ { :ex_doc , "~> 0.38" , only: :dev , runtime: false } ,
177+ { :nimble_options , "~> 1.1" } ,
178+ # Slice 001 line 1, arm (a) recorded `only: :dev`. **Corrected at G4**, and the reason is
179+ # the shell, not the tooling: `ExTauri.ShutdownManager` is the sidecar's heartbeat, the
180+ # Rust window's only way to tell the BEAM it has closed, so it has to exist in the
181+ # binary that ships, and a `:dev`-only dependency does not. `mix ex_tauri.install` adds
182+ # that child unconditionally, which is why the generator's output could not start under
183+ # MIX_ENV=test or MIX_ENV=prod. Recorded as deviation D7 in NOTES.md.
184+ { :ex_tauri , "~> 0.2" } ,
185+ # Slice 001 line 3. `ex_tauri` already depends on burrito, but only in :dev, and
186+ # `&Burrito.wrap/1` is a release step that runs under MIX_ENV=prod. Declared directly so
187+ # the module exists in the environment that calls it.
188+ { :burrito , "~> 1.6" }
189+ ] ++ posix_deps ( )
176190 end
177191
178192 # Slice 022: the shell tool's process wrapper is a C port built with elixir_make (fork,
0 commit comments