# How it works

A `.sx` file states one experiment: the data it reads, the model, the
objective, the optimizer and the run configuration. `sexpgpu` reads that
file with a compile-time Lisp evaluator. Tensor operations evaluated during
that pass compute nothing; they append nodes to a graph. What comes out is
one IR document (parameters, graphs, loaders, optimizer updates, the run
configuration), which is validated, differentiated, rewritten for the
precision policy and then executed by one fixed training loop on a device.

```text
file.sx ──read──▶ Lisp evaluator ──trace──▶ graphs ──lower──▶ IR document
                  (compile time)                              │ validate
                                                              │ autodiff
                                                              │ precision
                                                              ▼
                                      fixed training loop on cpu | cuda
```

The file never sees the loop, the device or a kernel.

## Two kinds of value

| kind | examples | when it exists |
|---|---|---|
| ordinary | numbers, strings, keywords, symbols, lists, vectors, functions, models, optimizers | at compile time, while the file is evaluated |
| tensor | the result of `matmul`, `field`, `zeros`, a parameter | symbolically, as a node with a static shape and dtype, inside a graph being traced |

Ordinary values drive construction: `(repeat layers ...)` builds a stack,
`(if (> (dim x 0) (dim x 1)) ...)` picks a code path from a shape. Tensor
values cannot be branched on, because both branches must exist in a static
graph: that is `E-FLOW-001`, and the fix is `where`. See
[truth and staging](https://sexpgpu.041.io/docs/control.md#truth-and-staging).

## Where graphs come from

Tensors exist only inside a function the compiler traces:

| traced function | graph |
|---|---|
| `prepare`, the model, `objective` | the training graph, differentiated with respect to the objective |
| `eval-prepare`, the model, `evaluate` | one graph per evaluation pass |
| an optimizer body | one update graph per parameter |
| a `defparam` initializer | one closed graph per parameter |
| `curriculum` | one graph run after each evaluation |

A tensor operation outside these is `E-FLOW-003`; a tensor carried from one
graph into another is `E-FLOW-002`.

## What the compiler owns

The training loop, autodiff, gradient accumulation over microbatches, the
evaluation cadence, checkpoints and resume, the precision policy, fusion
and kernel selection, metrics, the status file and data parallelism. None
of it is in the file, so none of it can be subtly wrong in the file.

## What is recorded

Every compilation has a manifest: every source file with its SHA-256, the
selected variant and every knob with its source. It travels in the IR, the
checkpoint and the metrics `open` event, so any number can be traced back
to the exact text that produced it. The status file carries only the entry
file and the selection. See [events](https://sexpgpu.041.io/docs/events.md#the-open-metadata).

Related: [the run file](https://sexpgpu.041.io/docs/run-file.md), [It is Common Lisp](https://sexpgpu.041.io/docs/lisp.md),
[tensor operations](https://sexpgpu.041.io/docs/tensors.md).

---

SexpGPU documentation. Every page: https://sexpgpu.041.io/llms.txt
