Last updated: 2026-09-18 · commit
5fc48d460
How to build every component of Darkbloom from a fresh clone: the Go
coordinator, the Rust prompt-contract sidecar, the Swift provider CLI (with its
source-matched mlx.metallib), and the two Next.js UIs. make build does all
of it; the per-component steps below explain what each target runs.
Registry-ID support changes Swift provider policy and Rust prompt normalization together. Build the paired coordinator/sidecar/provider candidate; the v6 prompt contract cannot reuse a v5 cache identity. The follow-up retains the merged native SDK pin and does not require new model weights. See prompt parity for the validation procedure.
Docs Lint needs Git history to validate moved source links in frozen records;
its checkout uses fetch-depth: 0 (.github/workflows/ci.yml, docs job).
Changes to native loading estimates and retirement require a rebuilt provider test product, not only a new CLI. Bind both products and the SDK/metallib to the same checkout before running the memory and lifecycle gates. See historical source references for local setup.
Native CI test isolation reuses these built test products and their staged metallib; it does not rebuild or download a model. Follow the provider test procedure to run GPU-global assertions in separate processes with the exclusive opt-in scoped to the named test.
Model publishing can pass HUGGING_FACE_ARTIFACT_JSON through
scripts/publish-model.sh to registration. See the
model publishing procedure.
Profiler wire changes require both coordinator and provider builds; the shared Go/Swift fixture and focused checks are described in test.md and prediction telemetry.
The ProviderAppAttest Swift target uses public DeviceCheck/Security APIs. Its shadow packaging and live-validation requirements are separate from a successful local compile.
The release pipeline runs optimized products and SDK qualification on separate
xcode-27-xlarge runners. Both call .github/actions/provider-release-build/action.yml;
only the optimized lane transfers an unsigned app and its file inventory to
signing. All binaries, SwiftPM resource bundles and the source-matched Metal
library travel together. Signing verifies the same-run artifact's source commit,
version, inventory and entitlements before importing its certificate.
.github/workflows/provider-release-cache.yml runs the same two lanes after
relevant master changes. Release tags can restore those default-branch caches;
they cannot reuse another tag's cache. Release-plumbing PRs run these lanes with
PR-scoped caches and no signing or publishing secrets. Changes to
BoundedSingleConsumerPipeline.swift or its tests also run both lanes to catch
shutdown lifetime regressions with the release compiler. Two concurrent SDK 27
runners are needed for the parallel wall-time benefit; a smaller runner quota
queues the jobs without changing their gates.
scripts/provider-release-cache.py (keys) separates optimized and qualification
Swift caches by selected compiler/SDK identity, machine architecture, absolute
checkout/toolchain paths, dependencies and build recipe. A source commit names an
immutable generation; restore prefixes stay inside that compatibility boundary.
The qualification lane separately caches Rust 1.88.0 dependencies and target
objects. It always cleans and recompiles the local promptsidecar package while
retaining third-party objects: independently restored Swift and Rust caches must
not combine source timestamps with a different generation of local Rust outputs.
The Metal helper retains its exact source/toolchain contract.
scripts/prepare-metal-toolchain.py requires the selected Xcode's Metal compiler
to execute successfully. A successful component download alone is insufficient:
it clears stale lookup state, waits a bounded interval for registration, and uses
Apple's explicit component export/import path if registration remains incomplete.
It never switches to an older Xcode or silently accepts an unavailable compiler.
The helper's snapshot-mtimes and restore-mtimes commands retain timestamps for
tracked files whose contents are unchanged. Changed/new files retain their fresh
timestamps and rebuild. Cached metadata never restores source contents or touches
untracked files, links, Git metadata or paths outside the checkout. These commands
make compilation incremental; every restored build still runs its build and
qualification commands. Only unsigned build directories are cached, never signing
keys or notarized bundles.
See the release cache procedure for first-run costs and rerun behavior.
-
Toolchain via
mise. Every version is pinned inmise.toml;mise installinstalls them all.Tool Pin Used by go1.25.0coordinator, e2e (matches go 1.25.0ingo.mod)rust1.88.0coordinator/promptsidecar(matchesrust-version = "1.88"incoordinator/promptsidecar/Cargo.tomland therust:1.88.0-alpinebuilder incoordinator/Dockerfile)node22console-ui,admin-uiswift6.3provider-swift(the locallibs/mlx-swiftpackage declaresswift-tools-version: 6.3;provider-swift/Package.swiftitself is6.1)python3.12scripts/*.py, benchmark wrapper testsjq,gh,awscli,gcloudlatestscripts, release and deploy tooling -
macOS on Apple Silicon for anything under
provider-swift/(MLX + Metal). The coordinator, sidecar, e2e harness, and UIs build on macOS or Linux. -
Xcode Command Line Tools +
cmake(brew install cmake) — the metallib helper compiles MLX's Metal kernels with cmake. -
Git submodules checked out:
libs/mlx-swift,libs/mlx-swift-lm,libs/mlx(git clone --recurse-submodules …orgit submodule update --init --recursive).provider-swift/Package.swiftdepends on../libs/mlx-swiftand../libs/mlx-swift-lmby local path. -
Docker only for the coordinator container image (step 9).
The Qwen 3.8 Next integration pins libs/mlx-swift-lm to the merged
SDK PR #149 commit
729fa45c67a8b1cb26b1debeacf7f1d16ef3a21e. Its complete Git tree is identical
to the approved review head ae3ecdc835a895091f8929749fdb3e14383295a9.
Use the recorded gitlink, not a floating branch or a private experiment.
Use the repository-owned conversion tools for the pinned official source. Metadata verification is distinct from full payload hashing; conversion validates each source shard and writes a new output/manifest while retaining the trained assistant and packed PLE table. Inspect the tool's storage requirements before full hashing or conversion and coordinate the model/GPU operator. Never create a missing mount path or reuse an existing output directory. These commands do not publish an artifact.
Before describing the candidate as reproducible:
- Record the selected source trees/patch digests and approved immutable core,
C, Swift, SDK and provider pins. Inspect the composed SDK's
libs/mlx-swift-lm/docs/qwen4/composition.mdfor required source selection and excluded experiments. - Resolve CMake/package revisions and nested gitlinks in a fresh recursive private checkout. A machine-specific dependency symlink, local package override or unrecorded core patch does not close this gate. After each dependency merge, record the resulting approved commit, update its consumers and repeat affected checks; a review-head pin is not a final merged pin.
- Build the provider with the source-matched metallib and required SwiftPM resources using the procedures below; record actual binary/library/resource identities. Source parsing alone is not a build or runtime test.
- Complete the candidate test matrix on that final artifact. Keep private draft staging, signing/release, model publication, catalog activation and deployment as distinct outcomes.
Current source and validation limits are in the candidate reference.
SwiftPM may mark generated resource bundles hidden on macOS. The SDK's
PagedAttentionResources.locate must still discover their readable Metal
source inside its existing search roots. Do not clear filesystem flags or
disable paged eligibility to hide a failed preflight; keep sealed-app lookup
and conflicting-resource rejection intact. Stage and verify resources for
both the test host and any separately invoked CLI child.
Private prefill experiments, including packed-read lookahead and ordered NAX, are excluded from this publication pin. Rebuild and rebind both the SDK tests and provider when its gitlink changes; an earlier executable cannot qualify the new source merely because the core metallib hash is unchanged. Record the actual compiled NAX capability and precision posture; a hardware product name does not prove which kernels or arithmetic were used.
The connected Go API matrix can reuse an independently hashed production
provider via DARKBLOOM_PROVIDER_BINARY; it does not build or substitute a
different native runtime. Record the Go coordinator/test source separately.
The connected qualification instructions
bind coordinator traffic and native metrics to one authenticated unified
provider, with the Python runner and original oracles owned by this repository.
| Path | Toolchain | Notes |
|---|---|---|
go.mod (repo root) |
Go | Single module github.com/eigeninference/d-inference; contains coordinator/... and e2e/.... There is no go.work and no nested go.mod. |
coordinator/cmd/coordinator/ |
Go | The coordinator binary (main.go). |
coordinator/promptsidecar/ |
Rust | Crate promptsidecar, edition 2024, Cargo.lock committed; built with --locked. |
provider-swift/ |
SwiftPM | Products: darkbloom (CLI), darkbloom-enclave, darkbloom-fan-helper, darkbloom-publish; libraries ProviderCore, ProviderCoreFoundation, DarkbloomFan*. Platform macOS 14+. |
console-ui/ |
Next.js 16 / React 19 | npm; tests with Vitest. |
admin-ui/ |
Next.js 16 / React 19 | npm; dev/start on port 4001. |
landing/ |
static HTML/JS | No build step; earn-calculator-core.test.js runs with node --test. |
Makefile |
— | Every target below; make help lists them. |
Provider tests are grouped by subsystem inside their existing SwiftPM targets.
See finding provider tests for the folder map;
provider-swift/Package.swift (package) retains recursive source discovery.
The inference source map locates engine,
memory, caching and request-processing code within the same ProviderCore
target; building these folders requires no separate products or commands.
mise install # installs every pin in mise.toml
git submodule update --init --recursive
git config core.hooksPath .githooks # enables pre-commit + pre-push (see "Git hooks")mise activates the pinned versions per shell; on macOS the system Xcode
swift is also acceptable for provider-swift.
make build # coordinator-build prompt-sidecar-build provider-build ui-build
make all # test + build (see test.md)Continue with the per-component steps when you need one piece or want to
understand what make runs.
The owned two-host Go fixture embeds e2e/testbed/provider_host.py; rebuild
its test binary after helper or lifecycle changes. The CPU-only
TestPrepareConnectedInputBindings check uses the actual fixture input/report
types to prepare canonical catalog entries before a physical run. The helper waits within the existing
five-minute prelaunch bound for GPU ≤42°C and load1 ≤4, under the same control
lease used after launch. See the test procedure.
CI checks formatting of tracked Go source while preserving frozen report evidence bytes; see the coordinator checks. The provider config cleanup tests run with temporary home directories and need no provider build or model.
make coordinator-build # cd coordinator && go build ./cmd/coordinator
make coordinator-build-linux # GOOS=linux GOARCH=amd64 CGO_ENABLED=0 → coordinator/coordinator-linuxThe host build writes ./coordinator/coordinator. Version identity is injected
only by the container build (-ldflags -X …api.BuildVersion/BuildCommit/BuildDate
in coordinator/Dockerfile); a local go build reports dev/unknown on
GET /health (coordinator/api/consumer.go, handleHealth).
make prompt-sidecar-format # cargo fmt --all -- --check
make prompt-sidecar-check # cargo check --locked --all-targets; cargo clippy --locked --all-targets -- -D warnings
make prompt-sidecar-build # cargo build --locked --release --bin promptsidecar
make prompt-sidecar # format + check + test + buildOutput: ./coordinator/promptsidecar/target/release/promptsidecar. The
coordinator container needs a statically linked Linux binary, built the way
coordinator/Dockerfile does it (stage prompt-sidecar-builder):
cd coordinator/promptsidecar
rustup target add x86_64-unknown-linux-musl
cargo build --locked --release --target x86_64-unknown-linux-musl --bin promptsidecar
file target/x86_64-unknown-linux-musl/release/promptsidecar # must say "statically linked" or "static-pie linked"On macOS cross-compiling to musl needs a Linux linker; use the Docker build in
step 9 instead. scripts/verify-prompt-sidecar-linux.sh <binary> runs the
production prompt vectors against a Linux sidecar binary (CI job "Prompt
Sidecar Tests").
make provider-build
# = cd provider-swift && swift build
# ./scripts/fetch-metallib.sh "$(cd provider-swift && swift build --show-bin-path)"swift build produces ./provider-swift/.build/debug/darkbloom (plus
darkbloom-enclave, darkbloom-fan-helper, darkbloom-publish). MLX loads
mlx.metallib from beside the running executable, and SwiftPM does not
compile the Metal kernels, so scripts/fetch-metallib.sh
builds them with cmake from libs/mlx-swift/Source/Cmlx/mlx (the exact source
the host side links) and copies the result next to the binary. Despite its
name it builds, it does not download.
MLX also embeds shader source in Cmlx for runtime compilation. After changing
an MLX kernel header, regenerate the affected embedded sources with
libs/mlx-swift/Tools/update-mlx.sh from a clean, isolated libs/mlx-swift
checkout and review its generated diff. For quantized.h, keep both
Source/Cmlx/mlx-generated/quantized.cpp and
Source/Cmlx/mlx-generated/metal/quantized.h synchronized with the core header.
Rebuild Cmlx and relink the provider as well as rebuilding mlx.metallib;
replacing the Metal library alone leaves the embedded QMV implementation intact.
Run the bias-accumulation regression
against the resulting runtime.
./scripts/fetch-metallib.sh # next to the latest debug build
./scripts/fetch-metallib.sh release # next to the release build
./scripts/fetch-metallib.sh /some/dir # → /some/dir/mlx.metallibKnobs: METALLIB_CACHE_DIR (default /tmp/mlx-metallib-cache; cache key
includes the MLX tree SHA, toolchain hash and deployment target) and
MLX_METALLIB_DEPLOYMENT_TARGET (default 26.2; the _nax kernels are only
compiled at SDK/deployment target ≥ 26.2). The script fails if required kernel
symbols (_nax, gemv, the affine_qmv_wide_* variants) are missing from the
produced library.
After changing doctor subprocess capture or status canonicalization, rebuild
the Swift test targets with cd provider-swift && swift build --build-tests.
Then run the focused capture and canonical-byte regressions.
Build radix-engine with its matching native dependency and RADIX_CANDIDATE
define to emit schema-3 actual-forward-width evidence. The scalar observer and
benchmark validator must come from the same reviewed source cut. See the
prefix-cache benchmark checks for
scope, completion and B2/B4 acceptance requirements.
The executable's scripts/benchmarks/radix-engine/Package.resolved is tracked
and pins the reviewed provider dependency set. Keep locked resolution enabled
and verify the resulting source graph when applying local package overrides.
The Provider Tests job removes restored metallibs and resource bundles from
all macOS build configurations in both package caches before building its debug
test product (.github/workflows/ci.yml). An inactive package's cached debug
bundle can contain older source just as a release bundle can. Each subsequent
package build recreates its own resources; compiled objects and dependency
checkouts remain cached. Runtime lookup accepts byte-identical copies and
continues to reject divergent copies.
The separate signing-validation workflow checks packaging and Apple signing without selecting a deployment environment.
Release configuration, as the release workflow builds it:
cd provider-swift && swift build -c release --product darkbloom
swift build -c release --product darkbloom-fan-helper
cd .. && ./scripts/fetch-metallib.sh releasedarkbloom --version must print the value of ProviderCore.version
(provider-swift/Sources/ProviderCore/ProviderCore.swift);
scripts/check-release-version.sh enforces this against the coordinator's
LatestProviderVersion (see ../operations/provider-release.md).
For a signed provider bundle needed by isolated tests, use the validation-only signing workflow. It retains an Actions artifact after the normal signing and final-bundle checks.
scripts/benchmarks/attention-replay
links only MLX and MLXLMCommon. It consumes validated packet bytes without loading
a model or provider. Use an isolated build directory and the reviewed dependency
pins/local MLX package binding from the replay validation manifest:
REPLAY_SOURCE_ROOT=/absolute/path/to/pinned-worktree
ATTENTION_REPLAY_SOURCE_ROOT="$REPLAY_SOURCE_ROOT" \
swift build --package-path "$REPLAY_SOURCE_ROOT/scripts/benchmarks/attention-replay" \
--scratch-path /absolute/path/to/replay-build \
-c release --product attention-replay --jobs 4 --disable-automatic-resolutionRetain the executable SHA-256, source/dependency inventory, build graph,
mlx.metallib and SwiftPM resource bundles. An executable hash alone does not
bind external Metal resources. The Python driver never builds or downloads them.
Use the offline NumPy environment for
packet validation and the independent reference. See replay validation
and the source/test milestone.
Build the native BenchSegmentedDecode target in an isolated directory with the
same pinned local MLX dependency used by the nested native tests:
swift build --package-path libs/mlx-swift-lm --scratch-path /absolute/path/to/segment-profiler-build \
-c release --product BenchSegmentedDecode --jobs 4 --disable-automatic-resolutionStage the matching mlx.metallib and SwiftPM resource bundles beside the binary,
and retain their hashes with the build's source/dependency inventory. See
profiler validation for the bounded run.
scripts/benchmarks/radix-engine
links the real provider factory and MLX packages from an explicitly selected
worktree. Keep baseline and candidate source worktrees separate, with recursive
submodules pinned. From the repository root:
RADIX_BENCH_SOURCE=/absolute/path/to/pinned-worktree
cp "$RADIX_BENCH_SOURCE/provider-swift/Package.resolved" scripts/benchmarks/radix-engine/Package.resolved
RADIX_SOURCE_ROOT="$RADIX_BENCH_SOURCE" RADIX_CANDIDATE_BUILD=0 \
swift build --package-path scripts/benchmarks/radix-engine \
--scratch-path "$RADIX_BENCH_SOURCE/provider-swift/.build" \
-c release --product radix-engine --jobs 4 --disable-automatic-resolutionUse RADIX_CANDIDATE_BUILD=1 for a source tree containing
EngineV2Factory.makeBenchmarkSession and the current cache APIs. The same
harness source compiles against the older baseline with 0. Candidate SSD mode
uses the normal slot factory after a fresh pre/post-load weight-hash check;
--cache-mode resident explicitly reproduces the earlier resident-cache arm.
The baseline conditional and resident reproduction use the direct production
engine factory (BenchmarkLoader.swift).
The paired persistent-test namespace/access-group options require a candidate
build containing SSDPersistentTestKeyNamespace; historical builds reject them.
The same RADIX_CANDIDATE_BUILD=1 define also enables the namespace test target.
Building this source does not authorize a Keychain group or establish persistent
restart. See isolated persistent namespace validation.
Archive the source manifest, compile define, binary hash, matching
mlx.metallib, and SwiftPM resource bundles before changing that source tree.
Stage the Metal library beside radix-engine, as for the provider CLI. Before
model loading, the candidate SSD harness calls bindRuntimeMetallibForMLX, the
normal startup binder, and requires a valid immutable digest; placing the file
beside the binary alone does not establish the identity used by the complete
cache (provider-swift/Sources/ProviderCore/Security/BinaryHasher.swift). The
benchmark session is exposed only through @_spi(Benchmarking); its raw events
preserve token IDs. Segmented storage uses the shared native process owner;
bridge dispatch, contiguous bridge admission and HTTP framing require the
separate provider HTTP probe. See cache validation
for replay, key-mode and process-restart requirements.
The current candidate accepts --concurrency 1|2|4 and either
--production-kv-grant or --kv-budget-gib N after its positional arguments.
Archive one binary for all compared arms. Use --production-kv-grant for the
single-model production-capacity run: the existing slot session derives its
logical grant from loaded target and assistant weights using the
production grant policy.
Archive the Python evaluator source with the binary evidence as well: the
schema-2 cache comparator requires an off-to-on pair and validates idle/shutdown
ownership. A binary whose terminal snapshots precede publication of retired
engine gauges cannot satisfy that idle gate; preserve the raw refusal and use
a harness with coherent observations for the final comparison
(scripts/benchmarks/radix_engine_evidence.py, retirement_errors).
The current candidate includes bounded observation of published idle snapshots.
Its pure BenchmarkIdleObservationTests target can be run with swift test
using the same package, pinned source environment and scratch path as the build.
Keep test and release artifacts distinct, and use the final release binary for
both compared arms. Preserve logs that name the executed Swift Testing cases;
an XCTest runner may report zero tests before Swift Testing executes its suite.
It retains the separate post-build live OS/activation headroom gate.
The mode requires the candidate SSD serving path; it cannot be combined with
resident reproduction, native-probe-only mode or an explicit grant
(provider-swift/Sources/ProviderCore/Inference/Engine/Factory/EngineV2Factory+BenchmarkGrant.swift,
benchmarkProductionGrant; BenchmarkOptions.swift).
For explicit envelope controls, use --kv-budget-gib N. Without either flag,
the existing default remains one request and a 16 GiB explicit slot grant.
Explicit mode retains its measured post-load allocator guard; that diagnostic
does not size a production grant. Candidate paged_storage metrics separately
report committed backing and the mutable logical grant. Follow the
validation steps to retain policy
inputs, live headroom and actual engine capacity with each result.
For a bounded target diagnostic, append --native-kv-probe-only with
cache-off mtp-off and concurrency one. This candidate-only mode loads the
verified model and runs the same native KV type probe used before paged backend
construction: two prefill tokens followed by one decode token. It records each
attention row's actual K/V types and shapes, with model and metallib hashes.
It creates no serving engine or SSD store.
The standalone product also includes optional bounded target-logit capture through
--logit-diagnostic-position and --logit-diagnostic-candidates. Build it with the
matching native submodule; follow the diagnostic procedure
to preserve the original request and compare observation against an uninstrumented
control. These flags belong to the standalone benchmark, not the provider CLI.
The matching native submodule also supports --attention-packet-position and
--attention-packet-layer for a bounded native-byte capture from one attention
owner. Follow the capture procedure
before passing the exported packet to the offline analyzer below.
The optional attention packet analyzer uses a separate Python environment and the pinned NumPy requirement. It needs no Swift build, model weights or GPU.
python3 -m venv /tmp/darkbloom-attention-venv
/tmp/darkbloom-attention-venv/bin/python -m pip install -r scripts/benchmarks/attention_packet/requirements.txtUse that interpreter for packet analysis and its tests.
make ui-install # cd console-ui && npm install
make ui-lint # npx eslint src/
make ui-test # npm test (vitest run)
make ui-build # npm run build (next build)
make ui # install + lint + test + buildLocal dev server: cd console-ui && npm run dev. Bundle budget check:
npm run bundle:check (console-ui/scripts/analyze-bundle.mjs). CI uses
npm ci.
No make target. From admin-ui/:
npm install
npm run lint # eslint src/
npm test # vitest run
npm run build # next build
npm run dev # next dev -p 4001Static files in landing/ (index.html, earn-calculator*.js, terms.html,
privacy.html); nothing to build. Run its one test with
node --test landing/earn-calculator-core.test.js.
The production image is built by coordinator/Dockerfile
from the repo root (it copies both coordinator/ and the sidecar crate):
docker build \
--build-arg BUILD_VERSION="$(awk -F'"' '/public static let version =/ {print $2}' provider-swift/Sources/ProviderCore/ProviderCore.swift)" \
--build-arg BUILD_COMMIT="$(git rev-parse HEAD)" \
--build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-f coordinator/Dockerfile -t coordinator:local .Stages: prompt-sidecar-builder (rust:1.88.0-alpine, musl static build) →
builder (golang:1.25-alpine, -ldflags version injection) → final image
FROM eigengajesh/d-inference-base:v1-amd64 with /usr/local/bin/coordinator
and /usr/local/bin/promptsidecar, OCI labels
org.opencontainers.image.{version,revision,created}, EXPOSE 8080, entrypoint
start.sh (coordinator/deploy/start.sh). Cloud Build wraps exactly this in
deploy/gcp/cloudbuild.yaml (dev) and deploy/gcp/cloudbuild-prod.yaml
(prod); see ../operations/coordinator-deploy.md.
The normal coordinator build also supports coordinator --migrate-only. It
requires EIGENINFERENCE_DATABASE_URL, runs store migrations, and exits without
starting the server or seeding an admin key. Container execution must override
the default MicroMDM entrypoint script; see the
deployment procedure.
The startup measurement tool requires Python 3.10+ and no third-party packages or build step. Its tests use local stub servers; its default observation mode sends only public GETs.
| Target | What it runs |
|---|---|
help |
List targets (default goal) |
coordinator-test |
cd coordinator && go test ./... |
coordinator-build |
go build ./cmd/coordinator → ./coordinator/coordinator |
coordinator-build-linux |
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o coordinator-linux ./cmd/coordinator |
coordinator |
coordinator-test + coordinator-build |
prompt-sidecar-format |
cargo fmt --all -- --check |
prompt-sidecar-check |
cargo check --locked --all-targets + cargo clippy --locked --all-targets -- -D warnings |
prompt-sidecar-test |
cargo test --locked --all-targets |
prompt-sidecar-build |
cargo build --locked --release --bin promptsidecar |
prompt-sidecar |
format + check + test + build |
provider-build |
swift build + scripts/fetch-metallib.sh <bin-path> |
provider-test |
swift build --build-tests, stage mlx.metallib into the bin dir and every *PackageTests.xctest/Contents/MacOS, then swift test --skip-build |
provider |
provider-build + provider-test |
benchmark-wrapper-test |
cd scripts && python3 -m unittest discover -s gemma_contbatch/tests -t . |
benchmark-gemma-contbatch |
python3 scripts/benchmark-gemma-contbatch.py $(GEMMA_BENCHMARK_ARGS) (needs GPU + weights) |
ui-install / ui-lint / ui-test / ui-build / ui |
npm install / npx eslint src/ / npm test / npm run build in console-ui/ |
e2e-integration |
go test ./e2e/... -run TestIntegration -v |
e2e-benchmark |
go test ./e2e/... -run TestBenchmark -v |
e2e |
e2e-integration |
docs-check |
scripts/docs-check.sh (stamps, links, cited paths, orphans) |
docs-stamp |
scripts/docs-stamp.sh $(FILES) — refresh freshness stamps |
test |
coordinator-test prompt-sidecar-test provider-test ui-test benchmark-wrapper-test docs-check |
build |
coordinator-build prompt-sidecar-build provider-build ui-build |
all |
test build |
clean |
remove ./coordinator/coordinator{,-linux}, ./coordinator/promptsidecar/target, ./provider-swift/.build, ./console-ui/.next, ./console-ui/node_modules |
Enable once with git config core.hooksPath .githooks. Both hooks only act on
components that changed.
| Hook | Trigger | Checks |
|---|---|---|
.githooks/pre-commit |
staged coordinator/**.go |
gofmt -l on the staged files (fix: gofmt -w <file>) |
staged console-ui/**.ts{,x} |
cd console-ui && npx eslint src/ (fix: npx eslint --fix src/) |
|
| Swift | skipped — no enforced formatter | |
.githooks/pre-push |
any coordinator/ change in the pushed range |
gofmt -l . over coordinator/, then go test $(go list ./... | grep -v /internal/api) from coordinator/ (the slow WebSocket integration tests run in CI only) |
any console-ui/ change |
npx eslint --quiet src/ and npm run build |
CI runs the fuller set (gofmt, golangci-lint, -race tests, Swift, Rust,
docs lint); see test.md.
make build
ls -l coordinator/coordinator coordinator/promptsidecar/target/release/promptsidecar
ls -l provider-swift/.build/debug/darkbloom provider-swift/.build/debug/mlx.metallib
./provider-swift/.build/debug/darkbloom --version # prints ProviderCore.version, e.g. 0.8.16
ls console-ui/.next| Symptom | Cause | Fix |
|---|---|---|
swift build cannot resolve ../libs/mlx-swift |
submodules not checked out | git submodule update --init --recursive |
| provider starts but MLX fails to load kernels / "metallib not found" | mlx.metallib missing beside the binary |
./scripts/fetch-metallib.sh (or make provider-build) |
fetch-metallib.sh fails on missing _nax symbols |
deployment target/SDK below 26.2 | update Xcode; or set MLX_METALLIB_DEPLOYMENT_TARGET only if you accept a kernel set that differs from release builds |
cargo build --locked fails on lockfile |
Cargo.lock out of date with Cargo.toml |
run cargo update -p <crate> deliberately and commit the lock; never drop --locked in CI |
go build picks a different Go |
mise not activated in this shell |
eval "$(mise activate bash)" (or zsh) then retry |
docker build fails at file … statically linked |
sidecar not statically linked (musl target missing) | the Dockerfile adds the target itself; check Docker platform is linux/amd64 |
Use the macOS 27 SDK for a candidate that needs Apple code-measurement extensions. The release workflow explicitly selects Command Line Tools 27.0 / Swift 6.4, then runs provider tests under that same SDK; ordinary development retains the Swift 6.3 minimum. Set SDKROOT to that SDK for both compilation and linking: a CLT 27 beta 6 Swift probe compiled with --sdk alone embedded the deployment target as its SDK; setting SDKROOT produced the correct linked SDK. Verify LC_BUILD_VERSION with xcrun vtool -show-build on the final executable. Confirm the final signed executable produces the current launch category and full CodeDirectory digest on physical macOS 27; SDK 26 builds can collect ordinary shadow proofs but cannot qualify replacement readiness. See the observed SDK and measurement contract.
Run go test ./appattest ./api ./store -run 'TestAppAttest|TestAuthorization|TestApple|TestMacCodeMeasurement'
from coordinator/, using a disposable local DATABASE_URL for the store
contracts (the test harness truncates tables). Add -race for concurrency checks.
Run swift test --filter ProviderAppAttestTests from provider-swift/.
The private admin queries have PostgreSQL coverage in
admin-ui/src/lib/queries/app-attest.test.ts.
After the optimized provider is packaged with its resources, run
Darkbloom.app/Contents/MacOS/darkbloom runtime-smoke. Require all four markers:
app-attest-callback-runtime-smoke: ok, gemma-optimizations-runtime-smoke: ok,
paged-kernel-runtime-smoke: ok, and qwen4-metal-resources-runtime-smoke: ok. Callback completion and expiry are exercised
without Apple service calls or a Keychain item. This linked-binary check catches
a release-only allocator failure that debug tests missed. Run
bash scripts/test-install-atomic.sh for installer acceptance and rollback cases.
The rollout runbook separates these checks
from real Apple receipt renewal and final signed-artifact fleet qualification.
- test.md — unit, e2e, CI.
- ../operations/provider-release.md — provider release runbook.
../operations/coordinator-deploy.md— container build and deploy on GCP.../architecture/components/mlx-swift.md— why the metallib must match the MLX source.
Candidate native prefix-cache benchmarks must build ProviderCore and
scripts/benchmarks/radix-engine from the same source revision: the benchmark
prompt SPI carries production sampling parameters into each engine request.
See native benchmark validation
for sampling scope, regression filters and diagnostic restrictions.
python3 scripts/test-qwen4-packaged-resources.py compiles the actual Qwen Metal resource accessor into a small optimized app, then runs it from a relocated app and an installer-style executable symlink. It checks all three preamble hashes, rejects missing or empty files and resource links outside the app, and proves that developer/cwd copies cannot mask a broken packaged resource. It needs Swift on macOS, but no model weights or GPU. Both SDK 27 release lanes and Provider Tests run this check. The full provider runtime-smoke exercises the same accessor before publication, installation, and update.
python3 scripts/model-token-promotion.py --help prepares a model-specific, calendar-day grant payload without making API calls. It requires Python with zoneinfo and timezone data. The promotion runbook covers review and approved application; the test guide covers calendar and settlement validation.