---
title: Architecture drift
description: "The drift verify/ratchet/drift.json records at each commit that changed the file: layering and parity drift, and the requirements no layer traces yet."
---

## 1. What the count is

Each entry in `verify/ratchet/drift.json` is one piece of drift, and what it records depends on its category. Layering drift is work a driving adapter (the CLI or a binding) does that belongs in a lower layer; a parity gap is a capability one surface has and another lacks; an untraced requirement is one no test, model or live check is held to yet.

| Category | Kind | An entry is |
| --- | --- | --- |
| `placement` | layering | a dependency a crate has outside its allowed set in `verify/arch/placement.toml` |
| `subprocess` | layering | a `Command::new` in the source of a crate that ships |
| `port-impl` | layering | a port implemented above `microvms-edges`, where the production implementations belong |
| `adapter-logic` | layering | a control-plane operation name spelled out, or a default retyped as a number, in a driving adapter |
| `parity-gap` | parity | a capability one surface lacks until an issue closes it: an exemption in `verify/parity/capabilities.toml` that names the issue |
| `parity-drift` | parity | a case one surface can't answer offline in the shared case corpus: a `skip` in `verify/parity/cases/`. Every corpus runner refuses a `known_drift` marker, so a surface that answers wrongly fails its case |
| `untraced` | traceability | a requirement in `verify/spec/` that no group file in `verify/spec/traced/` lists, or whose entry there waives every layer, so no layer checks it. `trace:check` fails on one |

A decision in `verify/ratchet/decisions.toml` is a permanent exception with its reason, and it isn't counted. `mise run ratchet:check` collects the drift from a change's tree and from its merge base's, and fails on drift the base doesn't have, so the count can only go down.

## 2. Layering and parity drift

The total at each commit, oldest first. At `3f16a35`, dated 2026-10-01, it's 0, with 12 decisions beside it.

```mermaid
xychart-beta
  x-axis ["2026-09-30 5fc581b", "2026-09-30 e8c3fdb", "2026-09-30 5885362", "2026-09-30 b183c88", "2026-09-30 f80ef57", "2026-09-30 fee3b8a", "2026-09-30 8168420", "2026-10-01 3f16a35"]
  y-axis "Drift entries" 0 --> 93
  line [59, 59, 59, 59, 59, 59, 74, 0]
```

A category joins the count at the commit whose ratchet started collecting it, and the cells before that read "not collected": `parity-drift` from `8168420`, dated 2026-09-30, where its first count joins the total.

| Date | Commit | `placement` | `subprocess` | `port-impl` | `adapter-logic` | `parity-gap` | `parity-drift` | Total | Decisions |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 2026-09-30 | `5fc581b` | 4 | 1 | 1 | 0 | 53 | not collected | 59 | 11 |
| 2026-09-30 | `e8c3fdb` | 4 | 1 | 1 | 0 | 53 | not collected | 59 | 11 |
| 2026-09-30 | `5885362` | 4 | 1 | 1 | 0 | 53 | not collected | 59 | 11 |
| 2026-09-30 | `b183c88` | 4 | 1 | 1 | 0 | 53 | not collected | 59 | 11 |
| 2026-09-30 | `f80ef57` | 4 | 1 | 1 | 0 | 53 | not collected | 59 | 11 |
| 2026-09-30 | `fee3b8a` | 4 | 1 | 1 | 0 | 53 | not collected | 59 | 11 |
| 2026-09-30 | `8168420` | 4 | 1 | 0 | 0 | 52 | 17 | 74 | 13 |
| 2026-10-01 | `3f16a35` | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 12 |

## 3. Untraced requirements

The count at each commit, oldest first. At `3f16a35`, dated 2026-10-01, it's 0.

```mermaid
xychart-beta
  x-axis ["2026-09-30 5fc581b", "2026-09-30 e8c3fdb", "2026-09-30 5885362", "2026-09-30 b183c88", "2026-09-30 f80ef57", "2026-09-30 fee3b8a", "2026-09-30 8168420", "2026-10-01 3f16a35"]
  y-axis "Untraced requirements" 0 --> 72
  line [57, 53, 49, 43, 37, 37, 37, 0]
```

| Date | Commit | `untraced` |
| --- | --- | --- |
| 2026-09-30 | `5fc581b` | 57 |
| 2026-09-30 | `e8c3fdb` | 53 |
| 2026-09-30 | `5885362` | 49 |
| 2026-09-30 | `b183c88` | 43 |
| 2026-09-30 | `f80ef57` | 37 |
| 2026-09-30 | `fee3b8a` | 37 |
| 2026-09-30 | `8168420` | 37 |
| 2026-10-01 | `3f16a35` | 0 |

## 4. Provenance

This page is generated from the git history of `verify/ratchet/drift.json`: `tools/ratchet-history.py` reads the file at each first-parent commit that changed it, and `site/scripts/gen-reference.mjs` writes the page on every `pnpm run sync`. Until the merge-base rule the file was the hand-kept count, so each merge that moved it is a point; since then it's a snapshot that `mise run ratchet:snapshot` rewrites in a change of its own, so each rewrite is one. A working tree whose copy differs from HEAD's adds a last point marked "working tree". To change a number, fix what the entry names (move the code, give the surface the capability, or trace the requirement in its group's file in `verify/spec/traced/`); the next snapshot counts it.