# an.timing.contract

The timing kernel’s cross-language contract: five JSON files, generated from the registries.

The contract lives in `an/data/timing/` (shipped in the wheel) and is what any
other implementation of the kernel — the TypeScript one, a package that copies
`an`’s track format — copies and asserts:

| `easing.json`          | every registered easing (name, version, family,<br/>solver) with sample values, plus parametrised examples   |
|------------------------|--------------------------------------------------------------------------------------------------------------|
| `kinds.json`           | every field kind with sample interpolations, and the<br/>seeded property spaces                              |
| `timeline.schema.json` | the authored flat timeline `(start, end, address, change)`                                                   |
| `compiled.schema.json` | tracks, placed clips, loop modes, channels — the<br/>compiled form `runtime.js` consumes                     |
| `timing_vectors.json`  | compiled documents and the state at listed times                                                             |

**Numbers agree within** `1e-9 * max(1, |x|, |y|)`; strings, booleans,
`null`, list lengths and object keys agree exactly. A state is SPARSE: an
address no clip has started writing is absent (at rest).

The files are regenerated by `python -m an.timing.contract write` and checked
by `python -m an.timing.contract check` (a test runs the check). Regenerating
is a deliberate act: a change to a committed sample is a change of the contract.

```pycon
>>> doc = {"timeline": {"duration": 1.0, "tracks": [{"clips": [
...     {"animation_id": "m", "start_time": 0.0}]}]},
...     "animations": {"m": {"duration": 1.0, "channels": [{"target": "cam",
...     "property": "yaw", "keyframes": [{"time": 0.0, "value": 350.0},
...     {"time": 1.0, "value": 10.0}]}]}}}
>>> space = {"fields": [{"pattern": "yaw", "spec": {"kind": "angle"}}]}
>>> state_at(doc, 0.5, space=space)
{'cam:yaw': 360.0}
```

### Module Attributes

| [`CONTRACT_DIR`](#an.timing.contract.CONTRACT_DIR)           | Where the committed contract files live (inside the package, so they ship).                                                                                                                                                                                          |
|-------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [`REL_TOL`](#an.timing.contract.REL_TOL)                | ```<br/>|x - y|<br/>```<br/><br/> <= REL_TOL \* max(1, <br/><br/>```<br/>|x|<br/>```<br/><br/>, <br/><br/>```<br/>|y|<br/>```<br/><br/>).                                                                                                                            |
| [`VALUE_TYPED_CASE_SPACE`](#an.timing.contract.VALUE_TYPED_CASE_SPACE) | The cases whose space is the value-typed rule's write-group space are ALSO evaluated with `space=VALUE_TYPED` — the rule `runtime.js` implements — so both rules are held to the same numbers (the default, `space=None`, is the declared rule since an#239 item 2). |
| [`SOLVER_PROBE_U`](#an.timing.contract.SOLVER_PROBE_U)         | a uniform grid, plus points that reach the solvers' fallbacks (near the ends, and around the middle of a curve whose slope vanishes there, e.g. cubic-bezier(1, 0, 0, 1)).                                                                                           |
| [`PARAMETRIC_EXAMPLES`](#an.timing.contract.PARAMETRIC_EXAMPLES)    | Parametrised specs the easing file samples, beside the named entries.                                                                                                                                                                                                |
| [`CSS_IMPORT_ALIASES`](#an.timing.contract.CSS_IMPORT_ALIASES)     | How a CSS-named document's names map onto this registry where the name means something else here.                                                                                                                                                                    |
| [`ADDRESS_PATTERN`](#an.timing.contract.ADDRESS_PATTERN)        | The address grammar as a regular expression (the parser is `an.timing.address`).                                                                                                                                                                                     |

### Functions

| `build_compiled_schema`()                                                                      |                                                                                                                |
|------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|
| [`build_contract`](#an.timing.contract.build_contract)()                              | Every contract file's content, by file name, generated from the registries.                                    |
| `build_easing`()                                                                               |                                                                                                                |
| `build_kinds`()                                                                                |                                                                                                                |
| `build_timeline_schema`()                                                                      |                                                                                                                |
| `build_vectors`()                                                                              |                                                                                                                |
| [`check_vectors`](#an.timing.contract.check_vectors)([vectors])                      | Every sample of `vectors` (default: the committed file) that `an.timing` does not reproduce, as one line each. |
| [`contract_drift`](#an.timing.contract.contract_drift)([directory])                   | How the committed files differ from what the registries generate today.                                        |
| [`dumps`](#an.timing.contract.dumps)(obj)                                    | The committed text of a contract file (stable, diffable).                                                      |
| `load_contract_file`(name, \*[, directory])                                                    |                                                                                                                |
| [`main`](#an.timing.contract.main)([argv])                                  | `python -m an.timing.contract [write|check]`.                                                                  |
| [`resolve_space`](#an.timing.contract.resolve_space)(space)                          | A vector case's `space`: a registered space's name, or its JSON form.                                          |
| [`state_at`](#an.timing.contract.state_at)(doc, t, \*, space)                   | The sparse state of compiled document `doc` at `t`, keyed by address.                                          |
| [`values_close`](#an.timing.contract.values_close)(expected, actual, \*[, rel_tol]) | The contract's comparison (see the module docstring).                                                          |
| [`write_contract`](#an.timing.contract.write_contract)([directory])                   | Regenerate every contract file under `directory`.                                                              |

### an.timing.contract.ADDRESS_PATTERN *: [str](https://docs.python.org/3/builtins/stdtypes.html#str)* *= '^[^:/@\\\\s](?:[^:/@]\*[^:/@\\\\s])?(?:/[^:/@\\\\s](?:[^:/@]\*[^:/@\\\\s])?)\*:[^:/@.\\\\s](?:[^:/@.]\*[^:/@.\\\\s])?(?:\\\\.[^:/@.\\\\s](?:[^:/@.]\*[^:/@.\\\\s])?)\*(?:@[^:/@\\\\s](?:[^:/@]\*[^:/@\\\\s])?)?$'*

The address grammar as a regular expression (the parser is `an.timing.address`).

### an.timing.contract.CONTRACT_DIR *: [Path](https://docs.python.org/3/library/pathlib.html#pathlib.Path)* *= PosixPath('/home/runner/work/an/an/an/data/timing')*

Where the committed contract files live (inside the package, so they ship).

### an.timing.contract.CSS_IMPORT_ALIASES *: [dict](https://docs.python.org/3/builtins/stdtypes.html#dict)[[str](https://docs.python.org/3/builtins/stdtypes.html#str), [str](https://docs.python.org/3/builtins/stdtypes.html#str)]* *= {'ease': 'cubic-bezier(0.25, 0.1, 0.25, 1)'}*

How a CSS-named document’s names map onto this registry where the name means
something else here. `ease` is `an`’s quadratic (ADR 0001 decision 10,
amended 2026-10-01); a CSS document’s `ease` is this spec.

### an.timing.contract.PARAMETRIC_EXAMPLES *: [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[Any](https://docs.python.org/3/library/typing.html#typing.Any), ...]* *= ('cubic-bezier(0.25, 0.1, 0.25, 1)', 'cubic-bezier(0.5, -0.8, 0.5, 1.8)', 'cubic-bezier(0.3, 1.8, 0.7, -0.8)', 'steps(4)', 'steps(4, jump-start)', 'steps(3, jump-none)', 'steps(2, jump-both)', 'steps(2, start)', 'cubic-bezier(1, 0, 0, 1)', [0.42, 0.0, 0.58, 1.0], [0.5, 2.0, 0.5, 2.0], [0.3, 3.0, 0.7, 0.0], [1.0, 0.0, 0.0, 1.0], [0.42, 0.0, 1.0, 1.0], [0.0, 0.0, 0.58, 1.0])*

Parametrised specs the easing file samples, beside the named entries.

### an.timing.contract.REL_TOL *: [float](https://docs.python.org/3/builtins/functions.html#float)* *= 1e-09*

```
|x - y|
```

 <= REL_TOL \* max(1, 

```
|x|
```

, 

```
|y|
```

).

* **Type:**
  The contract’s tolerance

### an.timing.contract.SOLVER_PROBE_U *: [tuple](https://docs.python.org/3/builtins/stdtypes.html#tuple)[[float](https://docs.python.org/3/builtins/functions.html#float), ...]* *= (1e-06, 0.4, 0.501, 0.999999)*

a uniform grid, plus points that reach the
solvers’ fallbacks (near the ends, and around the middle of a curve whose
slope vanishes there, e.g. cubic-bezier(1, 0, 0, 1)).

* **Type:**
  Where every easing is sampled

### an.timing.contract.VALUE_TYPED_CASE_SPACE *: [str](https://docs.python.org/3/builtins/stdtypes.html#str)* *= 'stage.node'*

The cases whose space is the value-typed rule’s write-group space are ALSO
evaluated with `space=VALUE_TYPED` — the rule `runtime.js` implements —
so both rules are held to the same numbers (the default, `space=None`, is
the declared rule since an#239 item 2).

### an.timing.contract.build_contract()

Every contract file’s content, by file name, generated from the registries.

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]

### an.timing.contract.check_vectors(vectors=None)

Every sample of `vectors` (default: the committed file) that `an.timing`
does not reproduce, as one line each. Empty means the kernel meets the contract.

Both evaluation rules are held: every case under its declared space, and every
`stage.node` case also under the value-typed rule (`space=VALUE_TYPED`).

* **Return type:**
  [`list`](https://docs.python.org/3/builtins/stdtypes.html#list)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]

### an.timing.contract.contract_drift(directory=PosixPath('/home/runner/work/an/an/an/data/timing'))

How the committed files differ from what the registries generate today.

Numbers compare with the contract’s tolerance, because a transcendental
function (`exp`, `sin`, `pow`) may differ in its last bit across
platforms’ maths libraries; anything else must match exactly.

* **Return type:**
  [`list`](https://docs.python.org/3/builtins/stdtypes.html#list)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str)]

### an.timing.contract.dumps(obj)

The committed text of a contract file (stable, diffable).

* **Return type:**
  [`str`](https://docs.python.org/3/builtins/stdtypes.html#str)

### an.timing.contract.main(argv=None)

`python -m an.timing.contract [write|check]`.

* **Return type:**
  [`int`](https://docs.python.org/3/builtins/functions.html#int)

### an.timing.contract.resolve_space(space)

A vector case’s `space`: a registered space’s name, or its JSON form.

* **Return type:**
  [`PropertySpace`](an.timing.spaces.html.md#an.timing.spaces.PropertySpace)

### an.timing.contract.state_at(doc, t, , space)

The sparse state of compiled document `doc` at `t`, keyed by address.

* **Return type:**
  [`dict`](https://docs.python.org/3/builtins/stdtypes.html#dict)[[`str`](https://docs.python.org/3/builtins/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)]

### an.timing.contract.values_close(expected, actual, , rel_tol=1e-09)

The contract’s comparison (see the module docstring).

* **Return type:**
  [`bool`](https://docs.python.org/3/builtins/functions.html#bool)

```pycon
>>> values_close(1e9, 1e9 + 0.5), values_close([1, "a"], [1.0, "a"]), values_close(True, 1)
(True, True, False)
```

### an.timing.contract.write_contract(directory=PosixPath('/home/runner/work/an/an/an/data/timing'))

Regenerate every contract file under `directory`.

* **Return type:**
  [`list`](https://docs.python.org/3/builtins/stdtypes.html#list)[[`Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path)]
