The build, in order

Milestones

Failed Star is built as a curriculum: M0 → M7, in order, each one a runnable artifact plus a doc that teaches it. This is the spine of the whole project — the home page tells the story, the Learnings capture the why, and this page is the where-we-are and the map to every milestone writeup.

How to read this. Status is ☑ done · ◐ now · ☐ todo. A milestone is done when it runs and its output is verified against a known-good reference. Done milestones link to their full doc; upcoming ones get theirs written as we build them.

Where we are

Build progress

2 / 8 core milestones done · currently M2 — forward pass → logits

  1. M0Tokenizer
  2. M1Load weights
  3. M2Forward pass
  4. M3Generation
  5. M4KV cache
  6. M5Metal bring-up
  7. M6Metal optimize
  8. M7Quantize?

One artifact + one doc, each

The curriculum, M0 → M7

MILESTONE M0 · ☑ DONE

Tokenizer

Text ↔ token IDs. BPE encode/decode against the model's real vocabulary — no GPU, no weights, the model's front door.

fs tokenize "hello world" → IDs, and decode back.

doc → m0-tokenizer

MILESTONE M1 · ☑ DONE

Load the weights

Parse the model file, map every tensor (names, shapes, dtypes) into memory, and prove the file matches the architecture the config implies.

fs inspect models/qwen3-0.6b → architecture + tensor table.

doc → m1-weights

MILESTONE M2 · ◐ NOW

Forward pass → logits

Embeddings → N transformer blocks (RMSNorm, RoPE, attention, SwiGLU) → final norm → logits. CPU/Rust first — correct before fast. The "it understands" milestone.

fs logits "The capital of France is" → top-k next tokens.

doc → m2-forward-pass · lands with the milestone

MILESTONE M3 · ☐ TODO

Deterministic generation, then sampling

Build the autoregressive loop and greedy oracle parity first; only then add temperature / top-k / top-p and streaming. Chat templating remains optional.

fs generate "..." reproduces a greedy continuation.

doc → lands with the milestone

MILESTONE M4 · ☐ TODO

KV cache

Cache K/V per layer so decode does one-token work instead of reprocessing the whole sequence. RAM-only first. The "I made it faster" milestone.

cached/uncached outputs agree; benchmark both as a baseline.

doc → lands with the milestone

MILESTONE M5 · ☐ TODO

Metal bring-up + end-to-end GPU

Bring up device/queue/buffers/pipelines and move the complete path to MSL through bounded raw ObjC/Metal FFI. CPU remains the correctness oracle.

End-to-end GPU generation on the local Apple Silicon Mac.

doc → lands with the milestone

MILESTONE M6 · ☐ TODO

Profile-driven Metal optimization

Profile the correct GPU path, optimize measured bottlenecks, and fuse only where reproducible before/after measurements justify it.

Local-Mac benchmarks with CPU/unfused agreement.

doc → lands with the milestone

MILESTONE M7 · ☐ TODO

Quantization go/no-go

Use the benchmark baseline to decide whether low-bit work earns its complexity. GGUF remains a separate optional interoperability choice. Earlier stretch ideas are explicitly optional post-core experiments, not promised curriculum.

A documented decision; if go, measured quality/memory/speed deltas.

doc → per goal, if we take it

Platform and checks. The accelerated engine targets modern Apple Silicon/Metal. Default CI is model-free on macOS Apple Silicon; real-model and Metal correctness/performance run on the local development Mac. Orbs are useful for host checks but are not authoritative, and standard GitHub runners are not promised to run Metal.
Filenames match the milestone. Each milestone's doc is named for it — M0 → m0-tokenizer, M1 → m1-weights, M2 → m2-forward-pass, and so on. Docs without an mN- prefix (the map, the prerequisites) are context, not milestones.

The full curriculum — verify steps, book/page cross-links, and ds4 references for each milestone — lives in PLAN.md; the running "where are we" is PROGRESS.md.