Reproduce it
The build runs on any conformant Kubernetes cluster. No operators, no custom resources, no private registry: four public upstream images pinned by digest, and every line of homespun-specific code shipped as ConfigMap data.
Run the build, on any cluster
No GPU, no egress, no credentials. Fourteen stages, minutes, ending in a signed attestation that the last stage checks with the public key alone.
$ kubectl apply -k homespun/k8s/overlays/smoke-cpu
$ kubectl wait --for=condition=complete -n homespun-smoke-cpu \
job/homespun-verify --timeout=90m It asserts that every stage committed, that the training loss fell below a threshold so gradients actually flowed, that the exported model loads and answers, and that the attestation verifies. It asserts nothing about quality: the model it trains has under a million parameters and answers nothing.
A real run
Three things to change first. The pipeline refuses to start without
the first. scratch-1b trains the model itself;
posttrain-32b is the shortcut, and swapping the overlay
name is the only difference in what you type.
# 1. Pin the dataset revisions. An unpinned source is rejected:
# "trained on X" without a revision names a moving target.
$ $EDITOR k8s/overlays/posttrain-32b/files/datasets.jsonl
# 2. Secrets, if you need them. Both optional; absent means a
# degraded run, and preflight tells you which.
$ kubectl create secret generic homespun-signing -n homespun-posttrain-32b \
--from-literal=ed25519_seed=$(openssl rand -hex 32)
# 3. Your accelerator's peak, so utilisation is measured rather than
# invented. Leave it unset and the attestation records why it is absent.
$ bun bin/homespun.ts run --overlay k8s/overlays/posttrain-32b scratch-1b is roughly 6.6 × 1020
floating-point operations — about 460 H100-hours, two days on eight
cards. The rungs above it are 44,000 H100-hours for a 7B and 404,000
for a 32B. Plan at 30% utilisation, not 40%: the higher figure needs a
tuned configuration and is not what a first attempt gives you.
The driver is optional. Each stage writes a marker when it finishes
and waits for its inputs' markers before starting, so
kubectl apply -k on its own produces a correct run.
What the driver adds is preflight that refuses to begin a three-day
job that will fail at hour sixty for a missing secret, failure dumps,
and an append-only journal the attestation reads for wall-clock and
throughput.
Every overlay
| overlay | shape | cost | for |
|---|---|---|---|
smoke-cpu | 1 pod, no GPU | minutes | the whole graph, on any cluster, with no egress |
smoke | 1 GPU | ~32 min on an H100 | the same graph where a real accelerator exists |
scratch-1b | 8 GPUs | ~460 H100-hours | the real thing, at the size that is affordable today |
posttrain-7b | 2 GPUs | ~4 H100-hours | post-training on an existing base |
posttrain-32b | 8 GPUs | ~136 H100-hours | the same shortcut, at the size people would run |
cpt-32b | 8 GPUs | ~1,350 H100-hours | adds 10B tokens of coding data to a base |
What the artifacts run on
The export stage emits GGUF and MLX at several quantisations, so the result runs on ordinary hardware rather than only in a data centre. Every cell below is estimated from published measurements, not measured here — a cell is measured or it is marked, and today all of them are marked.
| unified memory | artifact | quantisation | weights | context |
|---|---|---|---|---|
| 16 GB | homespun-7b | 6-bit | ~6 GB | |
| 24–32 GB | homespun-7b | 8-bit | ~8 GB | |
| 48 GB | homespun-32b | 4-bit | ~19 GB | |
| 64 GB | homespun-32b | 6-bit | ~25 GB | |
| 128 GB | homespun-32b | 8-bit | ~34 GB |
Verify somebody else's artifact
Standard library only. No cluster, no network, no package to install.
$ python3 k8s/base/files/verify.py \
--attestation attestation.json \
--keys k8s/base/keys \
--art . \
--require-trust release It checks three separate things and reports them separately: that the signature verifies under a key you already held, that the document describes the bytes actually on disk, and that the trust level is the one you demanded. A development-signed artifact is a real signed artifact, and it fails the last check.