# Quality you can watch

Every rule this codebase lives by is a test, and fifteen numbers about its shape may only get better. This page shows both, read from the build that serves it, including the two weeks the numbers got worse.

## In plain words

I built this site with AI while most of my attention was elsewhere, and the risk in that is quality slipping while nobody is looking. So the decisions are written down as records, the records that a machine can check are tests, and a scanner counts fifteen things about the code on every version. A version that breaks a rule or makes any of them worse does not ship.

Every count and measurement on this page is read, when you open it, from files the build writes: the quality history (81 versions measured so far), the gate's own test results, the rules table and CodeRabbit's log. A test fails if any of them cannot be read from the data, or if the prose types a count of its own.

What that is worth to a team: quality that is measured on every change and can only ratchet one way, with the evidence public and the slip left in.

## In one table

| Number | 15 October | Worst | Now | Limit now |
| --- | ---: | ---: | ---: | ---: |
| Async methods with no CancellationToken | 51 | 109 at 1.0.3.186 | 1 | 1 |
| Declarations with no summary | 240 | 549 at 1.0.4.105 | 399 | 399 |
| Clock reads outside a composition root | 46 | 57 at 1.0.4.85 | 35 | 35 |
| Comments carrying a date or a name | 1 | 27 at 1.0.4.110 | 0 | 0 |
| Service classes with six or more dependencies | 1 | 12 at 1.0.4.105 | 8 | 8 |
| Test lines per production line (may only rise) | 0.82 | 0.74 at 1.0.4.65 | 0.81 | 0.81 |
| xUnit facts and data rows (may only rise) | 950 | 950 at 1.0.3.139 | 3,473 | 3,473 |

The worst is the version or day each number was at its worst, measured the same way as now.

## The slip, and the turn

In the two weeks to 29 October the code grew faster than it ever had, every yes-or-no rule held, and everything nobody was counting got worse. Async methods with no way to cancel them went from 51 on 15 October to 109 at 1.0.3.186. Declarations with no summary peaked at 549 at 1.0.4.105. On 29 October, at 1.0.4.115, the ratchet went in ([ADR-122](https://theyard.stevenstout.biz/?doc=adr-the-numbers-that-may-only-fall)): fourteen numbers in one file, fifteen since 1.0.5.1, read by the gate on every version, each allowed to move only the good way.

Today the async count is 1 and the undocumented count is 399. The gold mark on each chart is the version that number joined the ratchet. Every point is the same scanner, today's, read over that version's own tree: before the ratchet, the last version of each day from 15 October; from it on, every version.

## The numbers over time

One line per number, the whole history.

```quality-trend
Async methods with no CancellationToken | may only fall | 1.0.4.115
2026-10-15 | 1.0.3.139 | 51 | quality.py
2026-10-16 | 1.0.3.150 | 53 | quality.py
2026-10-17 | 1.0.3.161 | 53 | quality.py
2026-10-18 | 1.0.3.179 | 97 | quality.py
2026-10-19 | 1.0.3.186 | 109 | quality.py
2026-10-20 | 1.0.4.9 | 103 | quality.py
2026-10-21 | 1.0.4.24 | 103 | quality.py
2026-10-22 | 1.0.4.34 | 103 | quality.py
2026-10-23 | 1.0.4.48 | 106 | quality.py
2026-10-24 | 1.0.4.65 | 107 | quality.py
2026-10-25 | 1.0.4.85 | 107 | quality.py
2026-10-26 | 1.0.4.105 | 107 | quality.py
2026-10-27 | 1.0.4.110 | 107 | quality.py
2026-10-29 | 1.0.4.114 | 107 | quality.py
2026-10-29 | 1.0.4.115 | 107 | quality.py
2026-10-29 | 1.0.4.116 | 25 | quality.py
2026-10-29 | 1.0.4.117 | 1 | quality.py
2026-10-29 | 1.0.4.118 | 1 | quality.py
2026-10-29 | 1.0.4.119 | 1 | quality.py
2026-10-30 | 1.0.4.120 | 1 | quality.py
2026-10-30 | 1.0.4.121 | 1 | quality.py
2026-10-30 | 1.0.4.122 | 1 | quality.py
2026-10-30 | 1.0.4.123 | 1 | quality.py
2026-10-30 | 1.0.4.124 | 1 | quality.py
2026-10-30 | 1.0.4.125 | 1 | quality.py
2026-10-30 | 1.0.4.126 | 1 | quality.py
2026-10-30 | 1.0.4.127 | 1 | quality.py
2026-11-03 | 1.0.4.128 | 1 | quality.py
2026-11-04 | 1.0.4.129 | 1 | quality.py
2026-11-04 | 1.0.4.130 | 1 | quality.py
2026-11-04 | 1.0.4.131 | 1 | quality.py
2026-11-04 | 1.0.4.132 | 1 | quality.py
2026-11-04 | 1.0.4.133 | 1 | quality.py
2026-11-04 | 1.0.4.134 | 1 | quality.py
2026-11-04 | 1.0.4.135 | 1 | quality.py
2026-11-04 | 1.0.4.136 | 1 | quality.py
2026-11-05 | 1.0.4.137 | 1 | quality.py
2026-11-05 | 1.0.4.138 | 1 | quality.py
2026-11-05 | 1.0.4.139 | 1 | quality.py
2026-11-05 | 1.0.4.140 | 1 | quality.py
2026-11-05 | 1.0.4.141 | 1 | quality.py
2026-11-05 | 1.0.4.142 | 1 | quality.py
2026-11-05 | 1.0.4.143 | 1 | quality.py
2026-11-05 | 1.0.4.144 | 1 | quality.py
2026-11-05 | 1.0.4.145 | 1 | quality.py
2026-11-06 | 1.0.4.146 | 1 | quality.py
2026-11-07 | 1.0.4.147 | 1 | quality.py
2026-11-07 | 1.0.4.148 | 1 | quality.py
2026-11-07 | 1.0.4.149 | 1 | quality.py
2026-11-07 | 1.0.4.150 | 1 | quality.py
2026-11-07 | 1.0.4.151 | 1 | quality.py
2026-11-07 | 1.0.4.152 | 1 | quality.py
2026-11-07 | 1.0.4.153 | 1 | quality.py
2026-11-07 | 1.0.4.154 | 1 | quality.py
2026-11-07 | 1.0.4.155 | 1 | quality.py
2026-11-07 | 1.0.4.156 | 1 | quality.py
2026-11-08 | 1.0.4.157 | 1 | quality.py
2026-11-08 | 1.0.4.158 | 1 | quality.py
2026-11-08 | 1.0.4.159 | 1 | quality.py
2026-11-08 | 1.0.4.160 | 1 | quality.py
2026-11-08 | 1.0.4.161 | 1 | quality.py
2026-11-08 | 1.0.4.162 | 1 | quality.py
2026-11-09 | 1.0.4.163 | 1 | quality.py
2026-11-09 | 1.0.4.164 | 1 | quality.py
2026-11-09 | 1.0.4.165 | 1 | quality.py
2026-11-09 | 1.0.4.166 | 1 | quality.py
2026-11-09 | 1.0.4.167 | 1 | quality.py
2026-11-09 | 1.0.4.168 | 1 | quality.py
2026-11-09 | 1.0.4.169 | 1 | quality.py
2026-11-09 | 1.0.4.170 | 1 | quality.py
2026-11-09 | 1.0.4.171 | 1 | quality.py
2026-11-09 | 1.0.4.172 | 1 | quality.py
2026-11-09 | 1.0.4.173 | 1 | quality.py
2026-11-09 | 1.0.4.174 | 1 | quality.py
2026-11-10 | 1.0.4.175 | 1 | quality.py
2026-11-10 | 1.0.4.176 | 1 | quality.py
2026-11-10 | 1.0.4.177 | 1 | quality.py
2026-11-10 | 1.0.4.178 | 1 | quality.py
2026-11-10 | 1.0.5.0 | 1 | quality.py
2026-11-10 | 1.0.5.1 | 1 | quality.py
2026-11-10 | 1.0.5.2 | 1 | quality.py
```

```quality-trend
Declarations with no summary | may only fall | 1.0.4.115
2026-10-15 | 1.0.3.139 | 240 | quality.py
2026-10-16 | 1.0.3.150 | 241 | quality.py
2026-10-17 | 1.0.3.161 | 241 | quality.py
2026-10-18 | 1.0.3.179 | 325 | quality.py
2026-10-19 | 1.0.3.186 | 325 | quality.py
2026-10-20 | 1.0.4.9 | 348 | quality.py
2026-10-21 | 1.0.4.24 | 348 | quality.py
2026-10-22 | 1.0.4.34 | 447 | quality.py
2026-10-23 | 1.0.4.48 | 448 | quality.py
2026-10-24 | 1.0.4.65 | 542 | quality.py
2026-10-25 | 1.0.4.85 | 547 | quality.py
2026-10-26 | 1.0.4.105 | 549 | quality.py
2026-10-27 | 1.0.4.110 | 549 | quality.py
2026-10-29 | 1.0.4.114 | 549 | quality.py
2026-10-29 | 1.0.4.115 | 549 | quality.py
2026-10-29 | 1.0.4.116 | 545 | quality.py
2026-10-29 | 1.0.4.117 | 543 | quality.py
2026-10-29 | 1.0.4.118 | 543 | quality.py
2026-10-29 | 1.0.4.119 | 543 | quality.py
2026-10-30 | 1.0.4.120 | 543 | quality.py
2026-10-30 | 1.0.4.121 | 543 | quality.py
2026-10-30 | 1.0.4.122 | 543 | quality.py
2026-10-30 | 1.0.4.123 | 543 | quality.py
2026-10-30 | 1.0.4.124 | 401 | quality.py
2026-10-30 | 1.0.4.125 | 401 | quality.py
2026-10-30 | 1.0.4.126 | 401 | quality.py
2026-10-30 | 1.0.4.127 | 401 | quality.py
2026-11-03 | 1.0.4.128 | 401 | quality.py
2026-11-04 | 1.0.4.129 | 401 | quality.py
2026-11-04 | 1.0.4.130 | 401 | quality.py
2026-11-04 | 1.0.4.131 | 401 | quality.py
2026-11-04 | 1.0.4.132 | 401 | quality.py
2026-11-04 | 1.0.4.133 | 401 | quality.py
2026-11-04 | 1.0.4.134 | 401 | quality.py
2026-11-04 | 1.0.4.135 | 401 | quality.py
2026-11-04 | 1.0.4.136 | 401 | quality.py
2026-11-05 | 1.0.4.137 | 401 | quality.py
2026-11-05 | 1.0.4.138 | 401 | quality.py
2026-11-05 | 1.0.4.139 | 401 | quality.py
2026-11-05 | 1.0.4.140 | 401 | quality.py
2026-11-05 | 1.0.4.141 | 401 | quality.py
2026-11-05 | 1.0.4.142 | 401 | quality.py
2026-11-05 | 1.0.4.143 | 400 | quality.py
2026-11-05 | 1.0.4.144 | 400 | quality.py
2026-11-05 | 1.0.4.145 | 400 | quality.py
2026-11-06 | 1.0.4.146 | 400 | quality.py
2026-11-07 | 1.0.4.147 | 400 | quality.py
2026-11-07 | 1.0.4.148 | 400 | quality.py
2026-11-07 | 1.0.4.149 | 400 | quality.py
2026-11-07 | 1.0.4.150 | 400 | quality.py
2026-11-07 | 1.0.4.151 | 400 | quality.py
2026-11-07 | 1.0.4.152 | 400 | quality.py
2026-11-07 | 1.0.4.153 | 400 | quality.py
2026-11-07 | 1.0.4.154 | 400 | quality.py
2026-11-07 | 1.0.4.155 | 400 | quality.py
2026-11-07 | 1.0.4.156 | 400 | quality.py
2026-11-08 | 1.0.4.157 | 400 | quality.py
2026-11-08 | 1.0.4.158 | 400 | quality.py
2026-11-08 | 1.0.4.159 | 400 | quality.py
2026-11-08 | 1.0.4.160 | 400 | quality.py
2026-11-08 | 1.0.4.161 | 400 | quality.py
2026-11-08 | 1.0.4.162 | 400 | quality.py
2026-11-09 | 1.0.4.163 | 400 | quality.py
2026-11-09 | 1.0.4.164 | 399 | quality.py
2026-11-09 | 1.0.4.165 | 399 | quality.py
2026-11-09 | 1.0.4.166 | 399 | quality.py
2026-11-09 | 1.0.4.167 | 399 | quality.py
2026-11-09 | 1.0.4.168 | 399 | quality.py
2026-11-09 | 1.0.4.169 | 399 | quality.py
2026-11-09 | 1.0.4.170 | 399 | quality.py
2026-11-09 | 1.0.4.171 | 399 | quality.py
2026-11-09 | 1.0.4.172 | 399 | quality.py
2026-11-09 | 1.0.4.173 | 399 | quality.py
2026-11-09 | 1.0.4.174 | 399 | quality.py
2026-11-10 | 1.0.4.175 | 399 | quality.py
2026-11-10 | 1.0.4.176 | 399 | quality.py
2026-11-10 | 1.0.4.177 | 399 | quality.py
2026-11-10 | 1.0.4.178 | 399 | quality.py
2026-11-10 | 1.0.5.0 | 399 | quality.py
2026-11-10 | 1.0.5.1 | 399 | quality.py
2026-11-10 | 1.0.5.2 | 399 | quality.py
```

```quality-trend
Clock reads outside a composition root | may only fall | 1.0.4.115
2026-10-15 | 1.0.3.139 | 46 | quality.py
2026-10-16 | 1.0.3.150 | 46 | quality.py
2026-10-17 | 1.0.3.161 | 46 | quality.py
2026-10-18 | 1.0.3.179 | 51 | quality.py
2026-10-19 | 1.0.3.186 | 54 | quality.py
2026-10-20 | 1.0.4.9 | 53 | quality.py
2026-10-21 | 1.0.4.24 | 53 | quality.py
2026-10-22 | 1.0.4.34 | 54 | quality.py
2026-10-23 | 1.0.4.48 | 53 | quality.py
2026-10-24 | 1.0.4.65 | 56 | quality.py
2026-10-25 | 1.0.4.85 | 57 | quality.py
2026-10-26 | 1.0.4.105 | 57 | quality.py
2026-10-27 | 1.0.4.110 | 57 | quality.py
2026-10-29 | 1.0.4.114 | 57 | quality.py
2026-10-29 | 1.0.4.115 | 57 | quality.py
2026-10-29 | 1.0.4.116 | 57 | quality.py
2026-10-29 | 1.0.4.117 | 57 | quality.py
2026-10-29 | 1.0.4.118 | 45 | quality.py
2026-10-29 | 1.0.4.119 | 45 | quality.py
2026-10-30 | 1.0.4.120 | 45 | quality.py
2026-10-30 | 1.0.4.121 | 35 | quality.py
2026-10-30 | 1.0.4.122 | 35 | quality.py
2026-10-30 | 1.0.4.123 | 35 | quality.py
2026-10-30 | 1.0.4.124 | 35 | quality.py
2026-10-30 | 1.0.4.125 | 35 | quality.py
2026-10-30 | 1.0.4.126 | 35 | quality.py
2026-10-30 | 1.0.4.127 | 35 | quality.py
2026-11-03 | 1.0.4.128 | 35 | quality.py
2026-11-04 | 1.0.4.129 | 35 | quality.py
2026-11-04 | 1.0.4.130 | 35 | quality.py
2026-11-04 | 1.0.4.131 | 35 | quality.py
2026-11-04 | 1.0.4.132 | 35 | quality.py
2026-11-04 | 1.0.4.133 | 35 | quality.py
2026-11-04 | 1.0.4.134 | 35 | quality.py
2026-11-04 | 1.0.4.135 | 35 | quality.py
2026-11-04 | 1.0.4.136 | 35 | quality.py
2026-11-05 | 1.0.4.137 | 35 | quality.py
2026-11-05 | 1.0.4.138 | 35 | quality.py
2026-11-05 | 1.0.4.139 | 35 | quality.py
2026-11-05 | 1.0.4.140 | 35 | quality.py
2026-11-05 | 1.0.4.141 | 35 | quality.py
2026-11-05 | 1.0.4.142 | 35 | quality.py
2026-11-05 | 1.0.4.143 | 35 | quality.py
2026-11-05 | 1.0.4.144 | 35 | quality.py
2026-11-05 | 1.0.4.145 | 35 | quality.py
2026-11-06 | 1.0.4.146 | 35 | quality.py
2026-11-07 | 1.0.4.147 | 35 | quality.py
2026-11-07 | 1.0.4.148 | 35 | quality.py
2026-11-07 | 1.0.4.149 | 35 | quality.py
2026-11-07 | 1.0.4.150 | 35 | quality.py
2026-11-07 | 1.0.4.151 | 35 | quality.py
2026-11-07 | 1.0.4.152 | 35 | quality.py
2026-11-07 | 1.0.4.153 | 35 | quality.py
2026-11-07 | 1.0.4.154 | 35 | quality.py
2026-11-07 | 1.0.4.155 | 35 | quality.py
2026-11-07 | 1.0.4.156 | 35 | quality.py
2026-11-08 | 1.0.4.157 | 35 | quality.py
2026-11-08 | 1.0.4.158 | 35 | quality.py
2026-11-08 | 1.0.4.159 | 35 | quality.py
2026-11-08 | 1.0.4.160 | 35 | quality.py
2026-11-08 | 1.0.4.161 | 35 | quality.py
2026-11-08 | 1.0.4.162 | 35 | quality.py
2026-11-09 | 1.0.4.163 | 35 | quality.py
2026-11-09 | 1.0.4.164 | 35 | quality.py
2026-11-09 | 1.0.4.165 | 35 | quality.py
2026-11-09 | 1.0.4.166 | 35 | quality.py
2026-11-09 | 1.0.4.167 | 35 | quality.py
2026-11-09 | 1.0.4.168 | 35 | quality.py
2026-11-09 | 1.0.4.169 | 35 | quality.py
2026-11-09 | 1.0.4.170 | 35 | quality.py
2026-11-09 | 1.0.4.171 | 35 | quality.py
2026-11-09 | 1.0.4.172 | 35 | quality.py
2026-11-09 | 1.0.4.173 | 35 | quality.py
2026-11-09 | 1.0.4.174 | 35 | quality.py
2026-11-10 | 1.0.4.175 | 35 | quality.py
2026-11-10 | 1.0.4.176 | 35 | quality.py
2026-11-10 | 1.0.4.177 | 35 | quality.py
2026-11-10 | 1.0.4.178 | 35 | quality.py
2026-11-10 | 1.0.5.0 | 35 | quality.py
2026-11-10 | 1.0.5.1 | 35 | quality.py
2026-11-10 | 1.0.5.2 | 35 | quality.py
```

```quality-trend
Comments carrying a date or a name | may only fall | 1.0.4.115
2026-10-15 | 1.0.3.139 | 1 | quality.py
2026-10-16 | 1.0.3.150 | 2 | quality.py
2026-10-17 | 1.0.3.161 | 1 | quality.py
2026-10-18 | 1.0.3.179 | 2 | quality.py
2026-10-19 | 1.0.3.186 | 12 | quality.py
2026-10-20 | 1.0.4.9 | 15 | quality.py
2026-10-21 | 1.0.4.24 | 4 | quality.py
2026-10-22 | 1.0.4.34 | 7 | quality.py
2026-10-23 | 1.0.4.48 | 11 | quality.py
2026-10-24 | 1.0.4.65 | 24 | quality.py
2026-10-25 | 1.0.4.85 | 24 | quality.py
2026-10-26 | 1.0.4.105 | 24 | quality.py
2026-10-27 | 1.0.4.110 | 27 | quality.py
2026-10-29 | 1.0.4.114 | 27 | quality.py
2026-10-29 | 1.0.4.115 | 27 | quality.py
2026-10-29 | 1.0.4.116 | 27 | quality.py
2026-10-29 | 1.0.4.117 | 27 | quality.py
2026-10-29 | 1.0.4.118 | 27 | quality.py
2026-10-29 | 1.0.4.119 | 27 | quality.py
2026-10-30 | 1.0.4.120 | 27 | quality.py
2026-10-30 | 1.0.4.121 | 27 | quality.py
2026-10-30 | 1.0.4.122 | 27 | quality.py
2026-10-30 | 1.0.4.123 | 27 | quality.py
2026-10-30 | 1.0.4.124 | 27 | quality.py
2026-10-30 | 1.0.4.125 | 0 | quality.py
2026-10-30 | 1.0.4.126 | 0 | quality.py
2026-10-30 | 1.0.4.127 | 0 | quality.py
2026-11-03 | 1.0.4.128 | 0 | quality.py
2026-11-04 | 1.0.4.129 | 0 | quality.py
2026-11-04 | 1.0.4.130 | 0 | quality.py
2026-11-04 | 1.0.4.131 | 0 | quality.py
2026-11-04 | 1.0.4.132 | 0 | quality.py
2026-11-04 | 1.0.4.133 | 0 | quality.py
2026-11-04 | 1.0.4.134 | 0 | quality.py
2026-11-04 | 1.0.4.135 | 0 | quality.py
2026-11-04 | 1.0.4.136 | 0 | quality.py
2026-11-05 | 1.0.4.137 | 0 | quality.py
2026-11-05 | 1.0.4.138 | 0 | quality.py
2026-11-05 | 1.0.4.139 | 0 | quality.py
2026-11-05 | 1.0.4.140 | 0 | quality.py
2026-11-05 | 1.0.4.141 | 0 | quality.py
2026-11-05 | 1.0.4.142 | 0 | quality.py
2026-11-05 | 1.0.4.143 | 0 | quality.py
2026-11-05 | 1.0.4.144 | 0 | quality.py
2026-11-05 | 1.0.4.145 | 0 | quality.py
2026-11-06 | 1.0.4.146 | 0 | quality.py
2026-11-07 | 1.0.4.147 | 0 | quality.py
2026-11-07 | 1.0.4.148 | 0 | quality.py
2026-11-07 | 1.0.4.149 | 0 | quality.py
2026-11-07 | 1.0.4.150 | 0 | quality.py
2026-11-07 | 1.0.4.151 | 0 | quality.py
2026-11-07 | 1.0.4.152 | 0 | quality.py
2026-11-07 | 1.0.4.153 | 0 | quality.py
2026-11-07 | 1.0.4.154 | 0 | quality.py
2026-11-07 | 1.0.4.155 | 0 | quality.py
2026-11-07 | 1.0.4.156 | 0 | quality.py
2026-11-08 | 1.0.4.157 | 0 | quality.py
2026-11-08 | 1.0.4.158 | 0 | quality.py
2026-11-08 | 1.0.4.159 | 0 | quality.py
2026-11-08 | 1.0.4.160 | 0 | quality.py
2026-11-08 | 1.0.4.161 | 0 | quality.py
2026-11-08 | 1.0.4.162 | 0 | quality.py
2026-11-09 | 1.0.4.163 | 0 | quality.py
2026-11-09 | 1.0.4.164 | 0 | quality.py
2026-11-09 | 1.0.4.165 | 0 | quality.py
2026-11-09 | 1.0.4.166 | 0 | quality.py
2026-11-09 | 1.0.4.167 | 0 | quality.py
2026-11-09 | 1.0.4.168 | 0 | quality.py
2026-11-09 | 1.0.4.169 | 0 | quality.py
2026-11-09 | 1.0.4.170 | 0 | quality.py
2026-11-09 | 1.0.4.171 | 0 | quality.py
2026-11-09 | 1.0.4.172 | 0 | quality.py
2026-11-09 | 1.0.4.173 | 0 | quality.py
2026-11-09 | 1.0.4.174 | 0 | quality.py
2026-11-10 | 1.0.4.175 | 0 | quality.py
2026-11-10 | 1.0.4.176 | 0 | quality.py
2026-11-10 | 1.0.4.177 | 0 | quality.py
2026-11-10 | 1.0.4.178 | 0 | quality.py
2026-11-10 | 1.0.5.0 | 0 | quality.py
2026-11-10 | 1.0.5.1 | 0 | quality.py
2026-11-10 | 1.0.5.2 | 0 | quality.py
```

```quality-trend
Service classes with six or more dependencies | may only fall | 1.0.4.115
2026-10-15 | 1.0.3.139 | 1 | quality.py
2026-10-16 | 1.0.3.150 | 1 | quality.py
2026-10-17 | 1.0.3.161 | 2 | quality.py
2026-10-18 | 1.0.3.179 | 3 | quality.py
2026-10-19 | 1.0.3.186 | 3 | quality.py
2026-10-20 | 1.0.4.9 | 6 | quality.py
2026-10-21 | 1.0.4.24 | 6 | quality.py
2026-10-22 | 1.0.4.34 | 6 | quality.py
2026-10-23 | 1.0.4.48 | 8 | quality.py
2026-10-24 | 1.0.4.65 | 11 | quality.py
2026-10-25 | 1.0.4.85 | 11 | quality.py
2026-10-26 | 1.0.4.105 | 12 | quality.py
2026-10-27 | 1.0.4.110 | 12 | quality.py
2026-10-29 | 1.0.4.114 | 12 | quality.py
2026-10-29 | 1.0.4.115 | 12 | quality.py
2026-10-29 | 1.0.4.116 | 12 | quality.py
2026-10-29 | 1.0.4.117 | 12 | quality.py
2026-10-29 | 1.0.4.118 | 12 | quality.py
2026-10-29 | 1.0.4.119 | 12 | quality.py
2026-10-30 | 1.0.4.120 | 8 | quality.py
2026-10-30 | 1.0.4.121 | 8 | quality.py
2026-10-30 | 1.0.4.122 | 8 | quality.py
2026-10-30 | 1.0.4.123 | 8 | quality.py
2026-10-30 | 1.0.4.124 | 8 | quality.py
2026-10-30 | 1.0.4.125 | 8 | quality.py
2026-10-30 | 1.0.4.126 | 8 | quality.py
2026-10-30 | 1.0.4.127 | 8 | quality.py
2026-11-03 | 1.0.4.128 | 8 | quality.py
2026-11-04 | 1.0.4.129 | 8 | quality.py
2026-11-04 | 1.0.4.130 | 8 | quality.py
2026-11-04 | 1.0.4.131 | 8 | quality.py
2026-11-04 | 1.0.4.132 | 8 | quality.py
2026-11-04 | 1.0.4.133 | 8 | quality.py
2026-11-04 | 1.0.4.134 | 8 | quality.py
2026-11-04 | 1.0.4.135 | 8 | quality.py
2026-11-04 | 1.0.4.136 | 8 | quality.py
2026-11-05 | 1.0.4.137 | 8 | quality.py
2026-11-05 | 1.0.4.138 | 8 | quality.py
2026-11-05 | 1.0.4.139 | 8 | quality.py
2026-11-05 | 1.0.4.140 | 8 | quality.py
2026-11-05 | 1.0.4.141 | 8 | quality.py
2026-11-05 | 1.0.4.142 | 8 | quality.py
2026-11-05 | 1.0.4.143 | 8 | quality.py
2026-11-05 | 1.0.4.144 | 8 | quality.py
2026-11-05 | 1.0.4.145 | 8 | quality.py
2026-11-06 | 1.0.4.146 | 8 | quality.py
2026-11-07 | 1.0.4.147 | 8 | quality.py
2026-11-07 | 1.0.4.148 | 8 | quality.py
2026-11-07 | 1.0.4.149 | 8 | quality.py
2026-11-07 | 1.0.4.150 | 8 | quality.py
2026-11-07 | 1.0.4.151 | 8 | quality.py
2026-11-07 | 1.0.4.152 | 8 | quality.py
2026-11-07 | 1.0.4.153 | 8 | quality.py
2026-11-07 | 1.0.4.154 | 8 | quality.py
2026-11-07 | 1.0.4.155 | 8 | quality.py
2026-11-07 | 1.0.4.156 | 8 | quality.py
2026-11-08 | 1.0.4.157 | 8 | quality.py
2026-11-08 | 1.0.4.158 | 8 | quality.py
2026-11-08 | 1.0.4.159 | 8 | quality.py
2026-11-08 | 1.0.4.160 | 8 | quality.py
2026-11-08 | 1.0.4.161 | 8 | quality.py
2026-11-08 | 1.0.4.162 | 8 | quality.py
2026-11-09 | 1.0.4.163 | 8 | quality.py
2026-11-09 | 1.0.4.164 | 8 | quality.py
2026-11-09 | 1.0.4.165 | 8 | quality.py
2026-11-09 | 1.0.4.166 | 8 | quality.py
2026-11-09 | 1.0.4.167 | 8 | quality.py
2026-11-09 | 1.0.4.168 | 8 | quality.py
2026-11-09 | 1.0.4.169 | 8 | quality.py
2026-11-09 | 1.0.4.170 | 8 | quality.py
2026-11-09 | 1.0.4.171 | 8 | quality.py
2026-11-09 | 1.0.4.172 | 8 | quality.py
2026-11-09 | 1.0.4.173 | 8 | quality.py
2026-11-09 | 1.0.4.174 | 8 | quality.py
2026-11-10 | 1.0.4.175 | 8 | quality.py
2026-11-10 | 1.0.4.176 | 8 | quality.py
2026-11-10 | 1.0.4.177 | 8 | quality.py
2026-11-10 | 1.0.4.178 | 8 | quality.py
2026-11-10 | 1.0.5.0 | 8 | quality.py
2026-11-10 | 1.0.5.1 | 8 | quality.py
2026-11-10 | 1.0.5.2 | 8 | quality.py
```

```quality-trend
Files within ten lines of the 300-line cap | may only fall | 1.0.4.115
2026-10-15 | 1.0.3.139 | 3 | quality.py
2026-10-16 | 1.0.3.150 | 4 | quality.py
2026-10-17 | 1.0.3.161 | 3 | quality.py
2026-10-18 | 1.0.3.179 | 4 | quality.py
2026-10-19 | 1.0.3.186 | 5 | quality.py
2026-10-20 | 1.0.4.9 | 6 | quality.py
2026-10-21 | 1.0.4.24 | 6 | quality.py
2026-10-22 | 1.0.4.34 | 7 | quality.py
2026-10-23 | 1.0.4.48 | 6 | quality.py
2026-10-24 | 1.0.4.65 | 6 | quality.py
2026-10-25 | 1.0.4.85 | 6 | quality.py
2026-10-26 | 1.0.4.105 | 7 | quality.py
2026-10-27 | 1.0.4.110 | 7 | quality.py
2026-10-29 | 1.0.4.114 | 7 | quality.py
2026-10-29 | 1.0.4.115 | 7 | quality.py
2026-10-29 | 1.0.4.116 | 7 | quality.py
2026-10-29 | 1.0.4.117 | 6 | quality.py
2026-10-29 | 1.0.4.118 | 6 | quality.py
2026-10-29 | 1.0.4.119 | 6 | quality.py
2026-10-30 | 1.0.4.120 | 6 | quality.py
2026-10-30 | 1.0.4.121 | 6 | quality.py
2026-10-30 | 1.0.4.122 | 2 | quality.py
2026-10-30 | 1.0.4.123 | 2 | quality.py
2026-10-30 | 1.0.4.124 | 2 | quality.py
2026-10-30 | 1.0.4.125 | 2 | quality.py
2026-10-30 | 1.0.4.126 | 2 | quality.py
2026-10-30 | 1.0.4.127 | 2 | quality.py
2026-11-03 | 1.0.4.128 | 2 | quality.py
2026-11-04 | 1.0.4.129 | 2 | quality.py
2026-11-04 | 1.0.4.130 | 2 | quality.py
2026-11-04 | 1.0.4.131 | 2 | quality.py
2026-11-04 | 1.0.4.132 | 2 | quality.py
2026-11-04 | 1.0.4.133 | 2 | quality.py
2026-11-04 | 1.0.4.134 | 2 | quality.py
2026-11-04 | 1.0.4.135 | 2 | quality.py
2026-11-04 | 1.0.4.136 | 2 | quality.py
2026-11-05 | 1.0.4.137 | 2 | quality.py
2026-11-05 | 1.0.4.138 | 2 | quality.py
2026-11-05 | 1.0.4.139 | 2 | quality.py
2026-11-05 | 1.0.4.140 | 2 | quality.py
2026-11-05 | 1.0.4.141 | 2 | quality.py
2026-11-05 | 1.0.4.142 | 2 | quality.py
2026-11-05 | 1.0.4.143 | 2 | quality.py
2026-11-05 | 1.0.4.144 | 2 | quality.py
2026-11-05 | 1.0.4.145 | 2 | quality.py
2026-11-06 | 1.0.4.146 | 2 | quality.py
2026-11-07 | 1.0.4.147 | 2 | quality.py
2026-11-07 | 1.0.4.148 | 2 | quality.py
2026-11-07 | 1.0.4.149 | 2 | quality.py
2026-11-07 | 1.0.4.150 | 2 | quality.py
2026-11-07 | 1.0.4.151 | 2 | quality.py
2026-11-07 | 1.0.4.152 | 2 | quality.py
2026-11-07 | 1.0.4.153 | 2 | quality.py
2026-11-07 | 1.0.4.154 | 2 | quality.py
2026-11-07 | 1.0.4.155 | 2 | quality.py
2026-11-07 | 1.0.4.156 | 2 | quality.py
2026-11-08 | 1.0.4.157 | 2 | quality.py
2026-11-08 | 1.0.4.158 | 2 | quality.py
2026-11-08 | 1.0.4.159 | 2 | quality.py
2026-11-08 | 1.0.4.160 | 2 | quality.py
2026-11-08 | 1.0.4.161 | 2 | quality.py
2026-11-08 | 1.0.4.162 | 2 | quality.py
2026-11-09 | 1.0.4.163 | 2 | quality.py
2026-11-09 | 1.0.4.164 | 2 | quality.py
2026-11-09 | 1.0.4.165 | 2 | quality.py
2026-11-09 | 1.0.4.166 | 2 | quality.py
2026-11-09 | 1.0.4.167 | 2 | quality.py
2026-11-09 | 1.0.4.168 | 2 | quality.py
2026-11-09 | 1.0.4.169 | 2 | quality.py
2026-11-09 | 1.0.4.170 | 2 | quality.py
2026-11-09 | 1.0.4.171 | 2 | quality.py
2026-11-09 | 1.0.4.172 | 2 | quality.py
2026-11-09 | 1.0.4.173 | 2 | quality.py
2026-11-09 | 1.0.4.174 | 2 | quality.py
2026-11-10 | 1.0.4.175 | 2 | quality.py
2026-11-10 | 1.0.4.176 | 2 | quality.py
2026-11-10 | 1.0.4.177 | 2 | quality.py
2026-11-10 | 1.0.4.178 | 2 | quality.py
2026-11-10 | 1.0.5.0 | 2 | quality.py
2026-11-10 | 1.0.5.1 | 2 | quality.py
2026-11-10 | 1.0.5.2 | 2 | quality.py
```

```quality-trend
Behaviour types no test names | may only fall | 1.0.4.115
2026-10-15 | 1.0.3.139 | 7 | quality.py
2026-10-16 | 1.0.3.150 | 7 | quality.py
2026-10-17 | 1.0.3.161 | 7 | quality.py
2026-10-18 | 1.0.3.179 | 6 | quality.py
2026-10-19 | 1.0.3.186 | 6 | quality.py
2026-10-20 | 1.0.4.9 | 8 | quality.py
2026-10-21 | 1.0.4.24 | 8 | quality.py
2026-10-22 | 1.0.4.34 | 9 | quality.py
2026-10-23 | 1.0.4.48 | 9 | quality.py
2026-10-24 | 1.0.4.65 | 9 | quality.py
2026-10-25 | 1.0.4.85 | 9 | quality.py
2026-10-26 | 1.0.4.105 | 9 | quality.py
2026-10-27 | 1.0.4.110 | 9 | quality.py
2026-10-29 | 1.0.4.114 | 9 | quality.py
2026-10-29 | 1.0.4.115 | 9 | quality.py
2026-10-29 | 1.0.4.116 | 9 | quality.py
2026-10-29 | 1.0.4.117 | 9 | quality.py
2026-10-29 | 1.0.4.118 | 9 | quality.py
2026-10-29 | 1.0.4.119 | 9 | quality.py
2026-10-30 | 1.0.4.120 | 9 | quality.py
2026-10-30 | 1.0.4.121 | 9 | quality.py
2026-10-30 | 1.0.4.122 | 9 | quality.py
2026-10-30 | 1.0.4.123 | 9 | quality.py
2026-10-30 | 1.0.4.124 | 9 | quality.py
2026-10-30 | 1.0.4.125 | 9 | quality.py
2026-10-30 | 1.0.4.126 | 0 | quality.py
2026-10-30 | 1.0.4.127 | 0 | quality.py
2026-11-03 | 1.0.4.128 | 0 | quality.py
2026-11-04 | 1.0.4.129 | 0 | quality.py
2026-11-04 | 1.0.4.130 | 0 | quality.py
2026-11-04 | 1.0.4.131 | 0 | quality.py
2026-11-04 | 1.0.4.132 | 0 | quality.py
2026-11-04 | 1.0.4.133 | 0 | quality.py
2026-11-04 | 1.0.4.134 | 0 | quality.py
2026-11-04 | 1.0.4.135 | 0 | quality.py
2026-11-04 | 1.0.4.136 | 0 | quality.py
2026-11-05 | 1.0.4.137 | 0 | quality.py
2026-11-05 | 1.0.4.138 | 0 | quality.py
2026-11-05 | 1.0.4.139 | 0 | quality.py
2026-11-05 | 1.0.4.140 | 0 | quality.py
2026-11-05 | 1.0.4.141 | 0 | quality.py
2026-11-05 | 1.0.4.142 | 0 | quality.py
2026-11-05 | 1.0.4.143 | 0 | quality.py
2026-11-05 | 1.0.4.144 | 0 | quality.py
2026-11-05 | 1.0.4.145 | 0 | quality.py
2026-11-06 | 1.0.4.146 | 0 | quality.py
2026-11-07 | 1.0.4.147 | 0 | quality.py
2026-11-07 | 1.0.4.148 | 0 | quality.py
2026-11-07 | 1.0.4.149 | 0 | quality.py
2026-11-07 | 1.0.4.150 | 0 | quality.py
2026-11-07 | 1.0.4.151 | 0 | quality.py
2026-11-07 | 1.0.4.152 | 0 | quality.py
2026-11-07 | 1.0.4.153 | 0 | quality.py
2026-11-07 | 1.0.4.154 | 0 | quality.py
2026-11-07 | 1.0.4.155 | 0 | quality.py
2026-11-07 | 1.0.4.156 | 0 | quality.py
2026-11-08 | 1.0.4.157 | 0 | quality.py
2026-11-08 | 1.0.4.158 | 0 | quality.py
2026-11-08 | 1.0.4.159 | 0 | quality.py
2026-11-08 | 1.0.4.160 | 0 | quality.py
2026-11-08 | 1.0.4.161 | 0 | quality.py
2026-11-08 | 1.0.4.162 | 0 | quality.py
2026-11-09 | 1.0.4.163 | 0 | quality.py
2026-11-09 | 1.0.4.164 | 0 | quality.py
2026-11-09 | 1.0.4.165 | 0 | quality.py
2026-11-09 | 1.0.4.166 | 0 | quality.py
2026-11-09 | 1.0.4.167 | 0 | quality.py
2026-11-09 | 1.0.4.168 | 0 | quality.py
2026-11-09 | 1.0.4.169 | 0 | quality.py
2026-11-09 | 1.0.4.170 | 0 | quality.py
2026-11-09 | 1.0.4.171 | 0 | quality.py
2026-11-09 | 1.0.4.172 | 0 | quality.py
2026-11-09 | 1.0.4.173 | 0 | quality.py
2026-11-09 | 1.0.4.174 | 0 | quality.py
2026-11-10 | 1.0.4.175 | 0 | quality.py
2026-11-10 | 1.0.4.176 | 0 | quality.py
2026-11-10 | 1.0.4.177 | 0 | quality.py
2026-11-10 | 1.0.4.178 | 0 | quality.py
2026-11-10 | 1.0.5.0 | 0 | quality.py
2026-11-10 | 1.0.5.1 | 0 | quality.py
2026-11-10 | 1.0.5.2 | 0 | quality.py
```

```quality-trend
React files with no header saying what they do | may only fall | 1.0.5.1
2026-10-15 | 1.0.3.139 | 273 | quality.py
2026-10-16 | 1.0.3.150 | 273 | quality.py
2026-10-17 | 1.0.3.161 | 277 | quality.py
2026-10-18 | 1.0.3.179 | 293 | quality.py
2026-10-19 | 1.0.3.186 | 293 | quality.py
2026-10-20 | 1.0.4.9 | 297 | quality.py
2026-10-21 | 1.0.4.24 | 302 | quality.py
2026-10-22 | 1.0.4.34 | 312 | quality.py
2026-10-23 | 1.0.4.48 | 315 | quality.py
2026-10-24 | 1.0.4.65 | 320 | quality.py
2026-10-25 | 1.0.4.85 | 326 | quality.py
2026-10-26 | 1.0.4.105 | 323 | quality.py
2026-10-27 | 1.0.4.110 | 323 | quality.py
2026-10-29 | 1.0.4.114 | 323 | quality.py
2026-10-29 | 1.0.4.115 | 323 | quality.py
2026-10-29 | 1.0.4.116 | 323 | quality.py
2026-10-29 | 1.0.4.117 | 323 | quality.py
2026-10-29 | 1.0.4.118 | 323 | quality.py
2026-10-29 | 1.0.4.119 | 323 | quality.py
2026-10-30 | 1.0.4.120 | 323 | quality.py
2026-10-30 | 1.0.4.121 | 323 | quality.py
2026-10-30 | 1.0.4.122 | 323 | quality.py
2026-10-30 | 1.0.4.123 | 323 | quality.py
2026-10-30 | 1.0.4.124 | 323 | quality.py
2026-10-30 | 1.0.4.125 | 323 | quality.py
2026-10-30 | 1.0.4.126 | 323 | quality.py
2026-10-30 | 1.0.4.127 | 323 | quality.py
2026-11-03 | 1.0.4.128 | 323 | quality.py
2026-11-04 | 1.0.4.129 | 323 | quality.py
2026-11-04 | 1.0.4.130 | 332 | quality.py
2026-11-04 | 1.0.4.131 | 336 | quality.py
2026-11-04 | 1.0.4.132 | 336 | quality.py
2026-11-04 | 1.0.4.133 | 336 | quality.py
2026-11-04 | 1.0.4.134 | 336 | quality.py
2026-11-04 | 1.0.4.135 | 336 | quality.py
2026-11-04 | 1.0.4.136 | 336 | quality.py
2026-11-05 | 1.0.4.137 | 336 | quality.py
2026-11-05 | 1.0.4.138 | 336 | quality.py
2026-11-05 | 1.0.4.139 | 336 | quality.py
2026-11-05 | 1.0.4.140 | 336 | quality.py
2026-11-05 | 1.0.4.141 | 336 | quality.py
2026-11-05 | 1.0.4.142 | 336 | quality.py
2026-11-05 | 1.0.4.143 | 336 | quality.py
2026-11-05 | 1.0.4.144 | 336 | quality.py
2026-11-05 | 1.0.4.145 | 336 | quality.py
2026-11-06 | 1.0.4.146 | 336 | quality.py
2026-11-07 | 1.0.4.147 | 336 | quality.py
2026-11-07 | 1.0.4.148 | 336 | quality.py
2026-11-07 | 1.0.4.149 | 336 | quality.py
2026-11-07 | 1.0.4.150 | 336 | quality.py
2026-11-07 | 1.0.4.151 | 336 | quality.py
2026-11-07 | 1.0.4.152 | 336 | quality.py
2026-11-07 | 1.0.4.153 | 338 | quality.py
2026-11-07 | 1.0.4.154 | 340 | quality.py
2026-11-07 | 1.0.4.155 | 343 | quality.py
2026-11-07 | 1.0.4.156 | 343 | quality.py
2026-11-08 | 1.0.4.157 | 347 | quality.py
2026-11-08 | 1.0.4.158 | 347 | quality.py
2026-11-08 | 1.0.4.159 | 350 | quality.py
2026-11-08 | 1.0.4.160 | 350 | quality.py
2026-11-08 | 1.0.4.161 | 350 | quality.py
2026-11-08 | 1.0.4.162 | 350 | quality.py
2026-11-09 | 1.0.4.163 | 350 | quality.py
2026-11-09 | 1.0.4.164 | 350 | quality.py
2026-11-09 | 1.0.4.165 | 350 | quality.py
2026-11-09 | 1.0.4.166 | 350 | quality.py
2026-11-09 | 1.0.4.167 | 350 | quality.py
2026-11-09 | 1.0.4.168 | 350 | quality.py
2026-11-09 | 1.0.4.169 | 350 | quality.py
2026-11-09 | 1.0.4.170 | 353 | quality.py
2026-11-09 | 1.0.4.171 | 353 | quality.py
2026-11-09 | 1.0.4.172 | 353 | quality.py
2026-11-09 | 1.0.4.173 | 353 | quality.py
2026-11-09 | 1.0.4.174 | 353 | quality.py
2026-11-10 | 1.0.4.175 | 353 | quality.py
2026-11-10 | 1.0.4.176 | 353 | quality.py
2026-11-10 | 1.0.4.177 | 353 | quality.py
2026-11-10 | 1.0.4.178 | 353 | quality.py
2026-11-10 | 1.0.5.0 | 356 | quality.py
2026-11-10 | 1.0.5.1 | 241 | quality.py
2026-11-10 | 1.0.5.2 | 241 | quality.py
```

```quality-trend
Test lines per production line | may only rise | 1.0.4.115
2026-10-15 | 1.0.3.139 | 0.82 | quality.py
2026-10-16 | 1.0.3.150 | 0.85 | quality.py
2026-10-17 | 1.0.3.161 | 0.85 | quality.py
2026-10-18 | 1.0.3.179 | 0.76 | quality.py
2026-10-19 | 1.0.3.186 | 0.75 | quality.py
2026-10-20 | 1.0.4.9 | 0.76 | quality.py
2026-10-21 | 1.0.4.24 | 0.78 | quality.py
2026-10-22 | 1.0.4.34 | 0.76 | quality.py
2026-10-23 | 1.0.4.48 | 0.75 | quality.py
2026-10-24 | 1.0.4.65 | 0.74 | quality.py
2026-10-25 | 1.0.4.85 | 0.74 | quality.py
2026-10-26 | 1.0.4.105 | 0.75 | quality.py
2026-10-27 | 1.0.4.110 | 0.75 | quality.py
2026-10-29 | 1.0.4.114 | 0.76 | quality.py
2026-10-29 | 1.0.4.115 | 0.76 | quality.py
2026-10-29 | 1.0.4.116 | 0.76 | quality.py
2026-10-29 | 1.0.4.117 | 0.77 | quality.py
2026-10-29 | 1.0.4.118 | 0.77 | quality.py
2026-10-29 | 1.0.4.119 | 0.77 | quality.py
2026-10-30 | 1.0.4.120 | 0.78 | quality.py
2026-10-30 | 1.0.4.121 | 0.78 | quality.py
2026-10-30 | 1.0.4.122 | 0.78 | quality.py
2026-10-30 | 1.0.4.123 | 0.78 | quality.py
2026-10-30 | 1.0.4.124 | 0.78 | quality.py
2026-10-30 | 1.0.4.125 | 0.78 | quality.py
2026-10-30 | 1.0.4.126 | 0.79 | quality.py
2026-10-30 | 1.0.4.127 | 0.79 | quality.py
2026-11-03 | 1.0.4.128 | 0.79 | quality.py
2026-11-04 | 1.0.4.129 | 0.79 | quality.py
2026-11-04 | 1.0.4.130 | 0.79 | quality.py
2026-11-04 | 1.0.4.131 | 0.79 | quality.py
2026-11-04 | 1.0.4.132 | 0.79 | quality.py
2026-11-04 | 1.0.4.133 | 0.79 | quality.py
2026-11-04 | 1.0.4.134 | 0.79 | quality.py
2026-11-04 | 1.0.4.135 | 0.79 | quality.py
2026-11-04 | 1.0.4.136 | 0.79 | quality.py
2026-11-05 | 1.0.4.137 | 0.79 | quality.py
2026-11-05 | 1.0.4.138 | 0.79 | quality.py
2026-11-05 | 1.0.4.139 | 0.79 | quality.py
2026-11-05 | 1.0.4.140 | 0.8 | quality.py
2026-11-05 | 1.0.4.141 | 0.8 | quality.py
2026-11-05 | 1.0.4.142 | 0.8 | quality.py
2026-11-05 | 1.0.4.143 | 0.8 | quality.py
2026-11-05 | 1.0.4.144 | 0.8 | quality.py
2026-11-05 | 1.0.4.145 | 0.8 | quality.py
2026-11-06 | 1.0.4.146 | 0.8 | quality.py
2026-11-07 | 1.0.4.147 | 0.8 | quality.py
2026-11-07 | 1.0.4.148 | 0.8 | quality.py
2026-11-07 | 1.0.4.149 | 0.8 | quality.py
2026-11-07 | 1.0.4.150 | 0.8 | quality.py
2026-11-07 | 1.0.4.151 | 0.8 | quality.py
2026-11-07 | 1.0.4.152 | 0.8 | quality.py
2026-11-07 | 1.0.4.153 | 0.8 | quality.py
2026-11-07 | 1.0.4.154 | 0.8 | quality.py
2026-11-07 | 1.0.4.155 | 0.8 | quality.py
2026-11-07 | 1.0.4.156 | 0.8 | quality.py
2026-11-08 | 1.0.4.157 | 0.8 | quality.py
2026-11-08 | 1.0.4.158 | 0.8 | quality.py
2026-11-08 | 1.0.4.159 | 0.8 | quality.py
2026-11-08 | 1.0.4.160 | 0.8 | quality.py
2026-11-08 | 1.0.4.161 | 0.8 | quality.py
2026-11-08 | 1.0.4.162 | 0.8 | quality.py
2026-11-09 | 1.0.4.163 | 0.8 | quality.py
2026-11-09 | 1.0.4.164 | 0.8 | quality.py
2026-11-09 | 1.0.4.165 | 0.8 | quality.py
2026-11-09 | 1.0.4.166 | 0.81 | quality.py
2026-11-09 | 1.0.4.167 | 0.81 | quality.py
2026-11-09 | 1.0.4.168 | 0.81 | quality.py
2026-11-09 | 1.0.4.169 | 0.81 | quality.py
2026-11-09 | 1.0.4.170 | 0.81 | quality.py
2026-11-09 | 1.0.4.171 | 0.81 | quality.py
2026-11-09 | 1.0.4.172 | 0.81 | quality.py
2026-11-09 | 1.0.4.173 | 0.81 | quality.py
2026-11-09 | 1.0.4.174 | 0.81 | quality.py
2026-11-10 | 1.0.4.175 | 0.81 | quality.py
2026-11-10 | 1.0.4.176 | 0.81 | quality.py
2026-11-10 | 1.0.4.177 | 0.81 | quality.py
2026-11-10 | 1.0.4.178 | 0.81 | quality.py
2026-11-10 | 1.0.5.0 | 0.81 | quality.py
2026-11-10 | 1.0.5.1 | 0.81 | quality.py
2026-11-10 | 1.0.5.2 | 0.81 | quality.py
```

```quality-trend
xUnit facts and data rows | may only rise | 1.0.4.115
2026-10-15 | 1.0.3.139 | 950 | quality.py
2026-10-16 | 1.0.3.150 | 1110 | quality.py
2026-10-17 | 1.0.3.161 | 1122 | quality.py
2026-10-18 | 1.0.3.179 | 1238 | quality.py
2026-10-19 | 1.0.3.186 | 1256 | quality.py
2026-10-20 | 1.0.4.9 | 1420 | quality.py
2026-10-21 | 1.0.4.24 | 1514 | quality.py
2026-10-22 | 1.0.4.34 | 1704 | quality.py
2026-10-23 | 1.0.4.48 | 1777 | quality.py
2026-10-24 | 1.0.4.65 | 2056 | quality.py
2026-10-25 | 1.0.4.85 | 2116 | quality.py
2026-10-26 | 1.0.4.105 | 2194 | quality.py
2026-10-27 | 1.0.4.110 | 2220 | quality.py
2026-10-29 | 1.0.4.114 | 2249 | quality.py
2026-10-29 | 1.0.4.115 | 2255 | quality.py
2026-10-29 | 1.0.4.116 | 2263 | quality.py
2026-10-29 | 1.0.4.117 | 2270 | quality.py
2026-10-29 | 1.0.4.118 | 2274 | quality.py
2026-10-29 | 1.0.4.119 | 2288 | quality.py
2026-10-30 | 1.0.4.120 | 2310 | quality.py
2026-10-30 | 1.0.4.121 | 2320 | quality.py
2026-10-30 | 1.0.4.122 | 2321 | quality.py
2026-10-30 | 1.0.4.123 | 2321 | quality.py
2026-10-30 | 1.0.4.124 | 2324 | quality.py
2026-10-30 | 1.0.4.125 | 2338 | quality.py
2026-10-30 | 1.0.4.126 | 2358 | quality.py
2026-10-30 | 1.0.4.127 | 2361 | quality.py
2026-11-03 | 1.0.4.128 | 2361 | quality.py
2026-11-04 | 1.0.4.129 | 2361 | quality.py
2026-11-04 | 1.0.4.130 | 2368 | quality.py
2026-11-04 | 1.0.4.131 | 2391 | quality.py
2026-11-04 | 1.0.4.132 | 2480 | quality.py
2026-11-04 | 1.0.4.133 | 2511 | quality.py
2026-11-04 | 1.0.4.134 | 2526 | quality.py
2026-11-04 | 1.0.4.135 | 2532 | quality.py
2026-11-04 | 1.0.4.136 | 2538 | quality.py
2026-11-05 | 1.0.4.137 | 2565 | quality.py
2026-11-05 | 1.0.4.138 | 2567 | quality.py
2026-11-05 | 1.0.4.139 | 2568 | quality.py
2026-11-05 | 1.0.4.140 | 2614 | quality.py
2026-11-05 | 1.0.4.141 | 2628 | quality.py
2026-11-05 | 1.0.4.142 | 2663 | quality.py
2026-11-05 | 1.0.4.143 | 2722 | quality.py
2026-11-05 | 1.0.4.144 | 2723 | quality.py
2026-11-05 | 1.0.4.145 | 2730 | quality.py
2026-11-06 | 1.0.4.146 | 2730 | quality.py
2026-11-07 | 1.0.4.147 | 2730 | quality.py
2026-11-07 | 1.0.4.148 | 2747 | quality.py
2026-11-07 | 1.0.4.149 | 2747 | quality.py
2026-11-07 | 1.0.4.150 | 2748 | quality.py
2026-11-07 | 1.0.4.151 | 2753 | quality.py
2026-11-07 | 1.0.4.152 | 2772 | quality.py
2026-11-07 | 1.0.4.153 | 2773 | quality.py
2026-11-07 | 1.0.4.154 | 2778 | quality.py
2026-11-07 | 1.0.4.155 | 2785 | quality.py
2026-11-07 | 1.0.4.156 | 2822 | quality.py
2026-11-08 | 1.0.4.157 | 2830 | quality.py
2026-11-08 | 1.0.4.158 | 2851 | quality.py
2026-11-08 | 1.0.4.159 | 2874 | quality.py
2026-11-08 | 1.0.4.160 | 2877 | quality.py
2026-11-08 | 1.0.4.161 | 2883 | quality.py
2026-11-08 | 1.0.4.162 | 2885 | quality.py
2026-11-09 | 1.0.4.163 | 2888 | quality.py
2026-11-09 | 1.0.4.164 | 2892 | quality.py
2026-11-09 | 1.0.4.165 | 2892 | quality.py
2026-11-09 | 1.0.4.166 | 3350 | quality.py
2026-11-09 | 1.0.4.167 | 3352 | quality.py
2026-11-09 | 1.0.4.168 | 3359 | quality.py
2026-11-09 | 1.0.4.169 | 3360 | quality.py
2026-11-09 | 1.0.4.170 | 3373 | quality.py
2026-11-09 | 1.0.4.171 | 3400 | quality.py
2026-11-09 | 1.0.4.172 | 3400 | quality.py
2026-11-09 | 1.0.4.173 | 3408 | quality.py
2026-11-09 | 1.0.4.174 | 3430 | quality.py
2026-11-10 | 1.0.4.175 | 3452 | quality.py
2026-11-10 | 1.0.4.176 | 3465 | quality.py
2026-11-10 | 1.0.4.177 | 3466 | quality.py
2026-11-10 | 1.0.4.178 | 3467 | quality.py
2026-11-10 | 1.0.5.0 | 3472 | quality.py
2026-11-10 | 1.0.5.1 | 3472 | quality.py
2026-11-10 | 1.0.5.2 | 3473 | quality.py
```

Held at zero on every version since the ratchet went in, so there is no line to draw: project references pointing outward (0), inner rings reaching the disk or the network (0), one slice naming another (0), blocking waits (0) and files over the cap (0).

## Coverage

Line and branch coverage from CI on main for each version, against a floor of 90 per cent of lines and 75 per cent of branches that no change may lower ([ADR: Counting what the tests cover](https://theyard.stevenstout.biz/?doc=adr-coverage)). Today: 93.6 per cent of lines, 83.1 per cent of branches.

```quality-trend
Line coverage, per cent | floor 90 |
2026-10-15 | 1.0.3.139 | 91.8 | ci
2026-10-16 | 1.0.3.150 | 91.9 | ci
2026-10-17 | 1.0.3.161 | 91.7 | ci
2026-10-20 | 1.0.4.9 | 93 | ci
2026-10-21 | 1.0.4.24 | 93.4 | ci
2026-10-22 | 1.0.4.34 | 93.6 | ci
2026-10-23 | 1.0.4.48 | 93.5 | ci
2026-10-24 | 1.0.4.65 | 92.7 | ci
2026-10-25 | 1.0.4.85 | 92.7 | ci
2026-10-26 | 1.0.4.105 | 92.7 | ci
2026-10-27 | 1.0.4.110 | 92.7 | ci
2026-10-29 | 1.0.4.114 | 93.6 | ci
2026-10-29 | 1.0.4.115 | 93.6 | ci
2026-10-29 | 1.0.4.116 | 93.6 | ci
2026-10-29 | 1.0.4.117 | 93.6 | ci
2026-10-29 | 1.0.4.118 | 93.6 | ci
2026-10-29 | 1.0.4.119 | 93.6 | ci
2026-10-30 | 1.0.4.120 | 93.6 | ci
2026-10-30 | 1.0.4.121 | 93.8 | ci
2026-10-30 | 1.0.4.123 | 93.8 | ci
2026-10-30 | 1.0.4.124 | 93.8 | ci
2026-10-30 | 1.0.4.125 | 93.8 | ci
2026-10-30 | 1.0.4.126 | 93.8 | ci
2026-10-30 | 1.0.4.127 | 93.8 | ci
2026-11-03 | 1.0.4.128 | 93.8 | ci
2026-11-04 | 1.0.4.129 | 93.8 | ci
2026-11-04 | 1.0.4.130 | 93.8 | ci
2026-11-04 | 1.0.4.131 | 93.8 | ci
2026-11-04 | 1.0.4.133 | 93.8 | ci
2026-11-04 | 1.0.4.134 | 93.8 | ci
2026-11-04 | 1.0.4.135 | 93.8 | ci
2026-11-04 | 1.0.4.136 | 93.7 | ci
2026-11-05 | 1.0.4.138 | 93.7 | ci
2026-11-05 | 1.0.4.139 | 93.8 | ci
2026-11-05 | 1.0.4.140 | 93.8 | ci
2026-11-05 | 1.0.4.141 | 93.7 | ci
2026-11-05 | 1.0.4.142 | 93.8 | ci
2026-11-05 | 1.0.4.143 | 93.7 | ci
2026-11-05 | 1.0.4.144 | 93.7 | ci
2026-11-05 | 1.0.4.145 | 93.8 | ci
2026-11-06 | 1.0.4.146 | 93.7 | ci
2026-11-07 | 1.0.4.147 | 93.8 | ci
2026-11-07 | 1.0.4.149 | 93.8 | ci
2026-11-07 | 1.0.4.150 | 93.8 | ci
2026-11-07 | 1.0.4.151 | 93.8 | ci
2026-11-07 | 1.0.4.152 | 93.8 | ci
2026-11-07 | 1.0.4.153 | 93.7 | ci
2026-11-07 | 1.0.4.154 | 93.8 | ci
2026-11-07 | 1.0.4.155 | 93.6 | ci
2026-11-07 | 1.0.4.156 | 93.7 | ci
2026-11-08 | 1.0.4.157 | 93.7 | ci
2026-11-08 | 1.0.4.158 | 93.7 | ci
2026-11-08 | 1.0.4.159 | 93.7 | ci
2026-11-08 | 1.0.4.160 | 93.8 | ci
2026-11-08 | 1.0.4.161 | 93.7 | ci
2026-11-08 | 1.0.4.162 | 93.7 | ci
2026-11-09 | 1.0.4.163 | 93.8 | ci
2026-11-09 | 1.0.4.164 | 93.7 | ci
2026-11-09 | 1.0.4.165 | 93.7 | ci
2026-11-09 | 1.0.4.166 | 93.7 | ci
2026-11-09 | 1.0.4.167 | 93.7 | ci
2026-11-09 | 1.0.4.168 | 93.7 | ci
2026-11-09 | 1.0.4.169 | 93.7 | ci
2026-11-09 | 1.0.4.170 | 93.7 | ci
2026-11-09 | 1.0.4.171 | 93.7 | ci
2026-11-09 | 1.0.4.172 | 93.7 | ci
2026-11-09 | 1.0.4.173 | 93.7 | ci
2026-11-09 | 1.0.4.174 | 93.6 | ci
2026-11-10 | 1.0.4.175 | 93.7 | ci
2026-11-10 | 1.0.4.176 | 93.7 | ci
2026-11-10 | 1.0.4.177 | 93.6 | ci
2026-11-10 | 1.0.4.178 | 93.7 | ci
2026-11-10 | 1.0.5.0 | 93.7 | ci
2026-11-10 | 1.0.5.1 | 93.6 | ci
```

```quality-trend
Branch coverage, per cent | floor 75 |
2026-10-15 | 1.0.3.139 | 77.5 | ci
2026-10-16 | 1.0.3.150 | 77.5 | ci
2026-10-17 | 1.0.3.161 | 77 | ci
2026-10-20 | 1.0.4.9 | 80.5 | ci
2026-10-21 | 1.0.4.24 | 82.2 | ci
2026-10-22 | 1.0.4.34 | 82 | ci
2026-10-23 | 1.0.4.48 | 82 | ci
2026-10-24 | 1.0.4.65 | 80.7 | ci
2026-10-25 | 1.0.4.85 | 80.8 | ci
2026-10-26 | 1.0.4.105 | 81 | ci
2026-10-27 | 1.0.4.110 | 81 | ci
2026-10-29 | 1.0.4.114 | 82.4 | ci
2026-10-29 | 1.0.4.115 | 82.4 | ci
2026-10-29 | 1.0.4.116 | 82.4 | ci
2026-10-29 | 1.0.4.117 | 82.3 | ci
2026-10-29 | 1.0.4.118 | 82.4 | ci
2026-10-29 | 1.0.4.119 | 82.4 | ci
2026-10-30 | 1.0.4.120 | 82.4 | ci
2026-10-30 | 1.0.4.121 | 82.6 | ci
2026-10-30 | 1.0.4.123 | 82.6 | ci
2026-10-30 | 1.0.4.124 | 82.6 | ci
2026-10-30 | 1.0.4.125 | 82.6 | ci
2026-10-30 | 1.0.4.126 | 82.7 | ci
2026-10-30 | 1.0.4.127 | 82.7 | ci
2026-11-03 | 1.0.4.128 | 82.7 | ci
2026-11-04 | 1.0.4.129 | 82.7 | ci
2026-11-04 | 1.0.4.130 | 82.6 | ci
2026-11-04 | 1.0.4.131 | 82.7 | ci
2026-11-04 | 1.0.4.133 | 82.6 | ci
2026-11-04 | 1.0.4.134 | 82.6 | ci
2026-11-04 | 1.0.4.135 | 82.6 | ci
2026-11-04 | 1.0.4.136 | 82.5 | ci
2026-11-05 | 1.0.4.138 | 82.5 | ci
2026-11-05 | 1.0.4.139 | 82.6 | ci
2026-11-05 | 1.0.4.140 | 82.7 | ci
2026-11-05 | 1.0.4.141 | 82.7 | ci
2026-11-05 | 1.0.4.142 | 82.7 | ci
2026-11-05 | 1.0.4.143 | 82.7 | ci
2026-11-05 | 1.0.4.144 | 82.8 | ci
2026-11-05 | 1.0.4.145 | 82.8 | ci
2026-11-06 | 1.0.4.146 | 82.7 | ci
2026-11-07 | 1.0.4.147 | 82.8 | ci
2026-11-07 | 1.0.4.149 | 82.8 | ci
2026-11-07 | 1.0.4.150 | 82.8 | ci
2026-11-07 | 1.0.4.151 | 82.8 | ci
2026-11-07 | 1.0.4.152 | 82.8 | ci
2026-11-07 | 1.0.4.153 | 82.7 | ci
2026-11-07 | 1.0.4.154 | 82.9 | ci
2026-11-07 | 1.0.4.155 | 82.6 | ci
2026-11-07 | 1.0.4.156 | 82.8 | ci
2026-11-08 | 1.0.4.157 | 82.9 | ci
2026-11-08 | 1.0.4.158 | 83 | ci
2026-11-08 | 1.0.4.159 | 83 | ci
2026-11-08 | 1.0.4.160 | 83.1 | ci
2026-11-08 | 1.0.4.161 | 83 | ci
2026-11-08 | 1.0.4.162 | 83 | ci
2026-11-09 | 1.0.4.163 | 83.1 | ci
2026-11-09 | 1.0.4.164 | 83.1 | ci
2026-11-09 | 1.0.4.165 | 83.1 | ci
2026-11-09 | 1.0.4.166 | 83.1 | ci
2026-11-09 | 1.0.4.167 | 83.1 | ci
2026-11-09 | 1.0.4.168 | 83.1 | ci
2026-11-09 | 1.0.4.169 | 83.1 | ci
2026-11-09 | 1.0.4.170 | 83.1 | ci
2026-11-09 | 1.0.4.171 | 83.1 | ci
2026-11-09 | 1.0.4.172 | 83.1 | ci
2026-11-09 | 1.0.4.173 | 83.1 | ci
2026-11-09 | 1.0.4.174 | 83.1 | ci
2026-11-10 | 1.0.4.175 | 83.1 | ci
2026-11-10 | 1.0.4.176 | 83.1 | ci
2026-11-10 | 1.0.4.177 | 83.1 | ci
2026-11-10 | 1.0.4.178 | 83.1 | ci
2026-11-10 | 1.0.5.0 | 83.1 | ci
2026-11-10 | 1.0.5.1 | 83.1 | ci
```

## CodeRabbit, the last reviewer

An AI review bot reads every version's pull request inside the gate. It is at level 0 of four, where it comments and no finding holds a release; each step up is my decision, on this log ([ADR-129](https://theyard.stevenstout.biz/?doc=adr-coderabbit-one-rung-at-a-time)).

| Version | Pull request | Reviewed | Findings | Review minutes |
| --- | --- | --- | --- | ---: |
| 1.0.4.176 | [#5](https://github.com/SteveStout/TheYard/pull/5) | full | 1 minor | 13.0 |
| 1.0.4.177 | [#6](https://github.com/SteveStout/TheYard/pull/6) | full | 1 minor | 7.0 |
| 1.0.4.178 | [#7](https://github.com/SteveStout/TheYard/pull/7) | full | 3 minor | 11.7 |
| 1.0.5.0 | [#8](https://github.com/SteveStout/TheYard/pull/8) | full | 1 minor | 11.3 |
| 1.0.5.1 | [#9](https://github.com/SteveStout/TheYard/pull/9) | full | 1 minor | 10.6 |
| 1.0.5.2 | [#10](https://github.com/SteveStout/TheYard/pull/10) | full | 2 minor | 10.8 |

## What is still thin

Named plainly, with the numbers:

- React files with no header comment saying what they do: 241 of 419. The site's own folders, src/app and src/library, carry one in every file, and so does every component folder's entry since 1.0.5.1; the components themselves and the rest of src/lib do not yet.
- XML documentation on TheYard.Data, the records every other ring reads: 49 per cent of its declarations.
- Service classes taking six or more dependencies: 8. Each one is a class doing more than one job.

The headers and the wide classes are ratchet numbers: each is paid down one version at a time, the payment lowers its limit in the same commit, and it cannot come back. The XML documentation figure is not on the ratchet yet; it is shown so it is not hidden.

## The rules, and the tests that hold them

Every rule a machine can check, from [ADR-075](https://theyard.stevenstout.biz/?doc=adr-rules), with the tests that hold it and how they did in the gate this build shipped from.

| The rule | Where it was decided | What holds it | In the last gate |
| --- | --- | --- | --- |
|  Record numbers run from one with no gap, and every record the sidebar offers has a file | ADR: The Decision Records index | RecordLinksTests  | 14 of 14 passed |
|  Every repository link in every document points at something that exists | ADR: Docs and testing | RecordLinksTests  | 14 of 14 passed |
|  Every record a comment cites, by name or by number, is a record that exists | ADR: Docs and testing | RecordLinksTests  | 14 of 14 passed |
|  Every link from a document to this site opens a page: a document as `?doc=` with a slug the catalogue serves, a drawing the catalogue draws, and no bare local address in prose | ADR: Docs and testing | RecordLinksTests  | 14 of 14 passed |
|  Every address this site serves answers with something, and a document is served as markdown | ADR: Every page, checked at every roll | PageStatusTests  | 30 of 30 passed |
|  The sweep checks every document and every drawing the catalogue serves, and its own requests are not counted as traffic | ADR: Every page, checked at every roll | PageStatusTests  | 30 of 30 passed |
|  The container samples its own memory and processor share, and each store's reading is the one that store actually keeps | ADR: What the machines are doing | MachinesTests  | 28 of 28 passed |
|  The request ring folds into minutes, each with its own median and its own errors, and the hour and the month are drawn from the one shape | ADR: The Admin tab, as a product | MachinesTests  | 28 of 28 passed |
|  A public ring hands on what it takes and not what it refuses, a kept entry is the entry the ring serves with the spine's private fields empty, it outlives the widest window that reads it, and the keyed log shows none of them | ADR: Logs that outlive the container | KeptRingTests  | 10 of 10 passed |
|  A kept minute leaves out a figure nobody read, a window is folded into the buckets it is drawn in, and the store's grouped query answers what the folding does | ADR: What the machines are doing | MachineHistoryTests  | 28 of 28 passed |
|  An identity token is asked for at whichever door the host has, and a web app's card claims no restart count it was never given | ADR: One plan, two sites | AzureSelfTests  | 22 of 22 passed |
|  Every setting a container group carried is a setting the two sites carry, and nothing deploys a template in complete mode | ADR: One plan, two sites | AppServiceTemplateTests  | 26 of 26 passed |
|  The living documents that describe what runs name the plan size the template declares | ADR: A rendering service beside the API | AppServiceTemplateTests  | 26 of 26 passed |
|  The rendering service names the session cookie the API issues, so the edge's copy of a page drawn for nobody is never handed to a signed-in visitor | ADR: A rendering service beside the API | CacheHeaderTests  | 32 of 32 passed |
|  A request on a store whose catalogue is cold waits for the load without blocking a thread, and a warm store is waited on for no time at all | ADR: One container, both stores | WarmthTests  | 4 of 4 passed |
|  No production comment leans on a version number, a date or a review to stand in for its reason | ADR: Code that reads like code | ProductionCommentTests  | 46 of 46 passed |
|  In the site's own code a production comment names no month, no written date, no review by its name and no person by first name; a format example in quotes or backticks is not history | ADR: Code that reads like code | ProductionCommentTests  | 46 of 46 passed |
|  In the job hunt's Function a comment explains by no date, no version number, no named review and nobody's ask, while the owner's name and a month name there are the subject the code acts on and not history. From 1.0.4.125 the rule is one body, tests/rules/HistoryRule.cs, asked in two strengths and shaped like the ratchet's own count | ADR: Code that reads like code | ProductionCommentTests  | 46 of 46 passed |
|  Every record opens with its title, says what became of it, says where it sits in the rings above its Files section, and has a Files section with at least one link | This record, ADR: Onion and SOLID, how this codebase holds them | RecordShapeTests  | 10 of 10 passed |
|  Every rule in this table names a test that exists, and every record it cites exists | This record | RuleTableTests  | 4 of 4 passed |
|  Dependencies point inward: Data and Domain use nothing outside .NET's base class library, Application uses only Domain and Data, and the document store adapter borrows only the shared user from the relational one | ADR: Onion and SOLID, how this codebase holds them | OnionTests  | 38 of 38 passed |
|  Endpoints never reach a store or the service container, reach the auction only through Application, the host never queries a database itself, and services are registered only in the composition root | ADR: Onion and SOLID, how this codebase holds them | OnionTests  | 38 of 38 passed |
|  Domain never reads a file, calls the network or reads the system clock or a random number itself, and Application never reads a file or calls the network | ADR: Onion and SOLID, how this codebase holds them | OnionTests  | 38 of 38 passed |
|  Every package the build uses has a row in the versions record with the version in use, and a row that is behind says why | ADR: Technology versions | TechnologyVersionsTests  | 8 of 8 passed |
|  Code shown in a document is read from the build at request time, never pasted | ADR: Live code samples | LiveSamplesTests, LiveSampleCoverageTests  | 84 of 84 passed |
|  The record count on every living document, and the README's xUnit and Playwright counts, are the counts the build declares | ADR: The public face | PublicFaceTests  | 40 of 40 passed |
|  The sitemap lists every document the catalogue serves and nothing else, and llms.txt links only to what the site serves | ADR: The public face | PublicFaceTests  | 40 of 40 passed |
|  The Cloud infrastructure drawing names every card the rail lists under it | ADR: One frame for every resource | CloudDrawingTests  | 2 of 2 passed |
|  /about is a served page with its own head, its Person names only his name, title, profiles and city, the sitemap lists it with the build's day, and the verification tag is written only when it is given | ADR: Every diagram opens on its own page, ADR: The public face | DiagramPageTests, PublicFaceTests, DockerBuildInputsTests  | 80 of 80 passed |
|  The slug, the catalog and the sidebar offer the same documents | ADR: The staff review | DocumentationCatalogTests  | 30 of 30 passed |
|  Every document sits in the folder of the sidebar section that offers it, the records in `docs/decisions/`, and the root of `docs/` holds only those folders, the changelog and the pictures | ADR: One folder per sidebar section | DocsFolderTests  | 6 of 6 passed |
|  Every file in `src/app` and `src/library`, and every stylesheet under `src`, opens with what it does, what it does not, and which files use it; the last is read against the files that import it, and no file there runs past 300 lines but the ones named with why | ADR: The React configuration, explained for a new developer | FileHeaderTests  | 8 of 8 passed |
|  No production C# file under `api/` and no TypeScript file under `src/` runs past 300 lines; a longer file is split by job and the file that keeps the name lists its parts (tests, migrations and generated files are left out). From 1.0.4.47 no C# type under `api/` runs past 300 lines either, counted across all of its partial files. From 1.0.4.70 the file rule is one body, tests/rules/LengthRule.cs, that the job hunt's suite runs over `functions/` too | ADR: The rules a change has to pass | FileShapeTests, RingTests  | 4 of 4 passed |
|  The five Style pages are served and are the Style section's rows, say "design token" and never a bare "token" (as do the design token files' comments), carry no em dash, and every live number and live fence on them is one the build can count or read, and every tile and glossary link lands on a real section | ADR: The palette | StyleSectionTests  | 12 of 12 passed |
|  One changelog line per shipped version, newest first, and the deploy reads the version from it | ADR: The changelog, ADR: The version comes from the changelog | ChangelogTests  | 6 of 6 passed |
|  Nothing this repository ships or serves contains an em dash | ADR: Style, enforced | HouseVoiceTests  | 10 of 10 passed |
|  No marker for work that is not happening, no focused test, no console call under `src` | ADR: Broken windows, and the rule that answers them | BrokenWindowsTests  | 10 of 10 passed |
|  Every class is sealed, static, abstract or inherited, and the analyzer that catches the internal half is a warning | Best Practices, Sealed by default | SealedByDefaultTests  | 10 of 10 passed |
|  A pinned package version is a decision, and a build error is not a reason to move it | The incident at 1.0.0.91, in the changelog | PackagePinTests  | 2 of 2 passed |
|  Both deploy workflows answer to one set of constants | ADR: A permanent address for the second site | DeployWorkflowTests  | 32 of 32 passed |
|  The SQL project in source control is the authority for the relational schema | ADR: Data first, and the database in source control | SchemaConformanceTests  | 16 of 16 passed |
|  The server owns the clock and every derived fact, and no request names a day | ADR: Three readers with no memory of the project | AuctionScheduleTests  | 10 of 10 passed |
|  Sold is decided before every other bid rule, for everybody | ADR: Accounts and per-user bids | BidRulesTests  | 26 of 26 passed |
|  Every public endpoint is in the API document with an operation id, a summary, its responses and its lock, and no operator endpoint is | ADR: The API describes itself | ApiDocumentTests  | 18 of 18 passed |
|  The first screen's one reading answers every field the band draws, and its latency figure is the request-weighted middle five minutes of the day, null when the day is empty | ADR: One reading for the first screen | PulseTests  | 10 of 10 passed |
|  A link into a section of another page names a slug the site serves and a second-level heading on it, which is the only kind the site gives an id | ADR: The staff review | DocumentationCatalogTests  | 30 of 30 passed |
|  What colleagues say comes from one file in one shape: every entry the same seven fields and nothing else, the month in words, the pull sentence as written, no two from one person, and the endpoint answers the file in its order | ADR: The sidebar | RecommendationsTests  | 14 of 14 passed |
|  The recommendations' count, years and groups are worked out from the file and answered on the wire, never stated; every LinkedIn relationship phrasing has its group, a line no group knows is a problem named by the shape check, and a fourteenth entry moves the count, the span and the groups | ADR: The sidebar | RecommendationFactsTests, RecommendationsTests  | 48 of 48 passed |
|  The recommendations page shows every recommendation the API answers, grouped as it groups them, drawn whole by the rendering service from its one read, at 1280 and 390 with no sideways scroll and no WCAG 2.1 AA violation; its short door keeps the code and its tagged open counts once under /recommendations | ADR: The recommendations have a page | RecommendationsOpenTests, recommendationsPage.test.ts, recommendations.test.ts, recommendations.spec.ts  | 2 of 2 passed |
|  /about lists every recommendation in the file by name, title and pull sentence, each linking to its card by the anchor the page gives the same name, under a count worked out from the file, and links the recommendations page and the review route | ADR: The recommendations have a page | AboutRecommendationsTests  | 8 of 8 passed |
|  The review route's last stop names who vouches for the resume and links the recommendations page, its sentence holds no number, and at a wide desk a rail beside the stops carries every pull quote the API answers, folding into the column on a phone | ADR: Ten minutes, seven stops | reviewStops.test.ts, review.spec.ts, AboutRecommendationsTests  | 8 of 8 passed |
|  No stylesheet or component carries a raw colour; every colour is a token in the one sheet | ADR: The palette | StyleRulesTests  | 28 of 28 passed |
|  Every hex on the Style pages (Colour and style, Background and ribbon) is a token's value, every colour token is on one of them, and every contrast figure they state is the figure the tokens give and clears its bar | ADR: The palette | StyleRulesTests  | 28 of 28 passed |
|  A chart series is never a status colour, and a line takes a status tone only for server errors | ADR: The Admin tab, as a product | StyleRulesTests  | 28 of 28 passed |
|  Gold is trim: only the header, the brand mark and the named trim use it, never a chart's line, a tile or a ring | ADR: The palette | StyleRulesTests  | 28 of 28 passed |
|  There is one header gradient, defined once, and every header bar uses it | ADR: The palette | StyleRulesTests  | 28 of 28 passed |
|  Every page title's underline and every stat tile's top rule is the gold bar, drawn from `--gradient-gold` with `border-image` | ADR: The palette | StyleRulesTests  | 28 of 28 passed |
|  Nothing that holds a word or an image is faded, a quiet word is never on the bare ground, and the browser suite and the token test that hold those are still there | ADR: The glass look | StyleRulesTests  | 28 of 28 passed |
|  One face for the whole site, IBM Plex Sans, with tabular figures set once on the body, and a monospaced face only on code | ADR: The palette | StyleRulesTests  | 28 of 28 passed |
|  Every panel, card and tile is the one shared glass with its rule and brackets, no sheet spaces capitals by a number of its own, and every button is a pill or a circle | ADR: The glass look | StyleRulesTests  | 28 of 28 passed |
|  The Author page holds no address, phone number, email address, age, wedding or engagement, and none of the private names and dates kept off it, which are held as digests so the test does not publish them | ADR: The sidebar | AuthorPageTests  | 24 of 24 passed |
|  Every photograph the Author page serves is a file with no metadata, of the width its `srcset` claims, 1920 wide or with its reason written down, with an alt text, in the one frame; the headed blocks alternate by order; nothing else is in the folder | ADR: The sidebar | AuthorPageTests  | 24 of 24 passed |
|  The Admin tab's charts and gauges are drawn in the Mark VII marks, each 3:1 on white, and every figure the style page states for them is the figure the tokens give; the glass is 30 per cent white and the secondary grey holds 4.5 over it on the ribbons' teal and gold stops (`tokens.test.ts`); no table cell breaks a word (`coverage.spec`) | ADR: The tweaks pass | StyleRulesTests  | 28 of 28 passed |
|  A colour is written once in the token sheet, a token that repeats one is written as it, and a see-through tint is mixed from its token; every width a page asks about is a step on the one scale in `src/lib/breakpoints.ts`; every size, weight, corner, tracking and layer a stylesheet writes comes from the token sheet | ADR: The tweaks pass | StyleRulesTests  | 28 of 28 passed |
|  A shipped test-results file is one only a green gate writes, every suite in it with its counts equal to its rows and nothing failed or skipped, the two passes on Cosmos DB the only ones a gate may carry forward and then only from a named version, and the Admin tab's endpoint serves it or says there is none | ADR: The five-minute gate | TestResultsTests  | 4 of 4 passed |
|  A browser test that passes only on its retry is written 'r' and a shipped results file holding one is refused; the README's xUnit number, everywhere it is stated, is the gate's own xunit-sqlite count | ADR: The five-minute gate | TestResultsTests, PublicFaceTests  | 44 of 44 passed |
|  Every 400, 401 and 404 a status test asserts is a ProblemDetails with a title, a sentence in detail and no public cache header | ADR: The exception handler, and the endpoint that proves it | AccountEndpointStatusTests, BidEndpointStatusTests, LinkEndpointStatusTests, VehicleEndpointStatusTests  | 22 of 22 passed |
|  The clock-bound tests read the day and the windows from the answer, never from the test machine's clock | ADR: Three readers with no memory of the project | ActivityTests, ApiIntegrationTests  | 234 of 234 passed |
|  CI runs on every push to main that touches the site, on every pull request and by hand, and a push that touches only the sample skips it | ADR: The five-minute gate | CiTriggerTests  | 4 of 4 passed |
|  A line on a Cloud infrastructure card that is not read says so and never colours the card; the Cosmos DB card judges the site's own throttles, the live tests' copies counted apart | ADR: One frame for every resource | CardFrameTests, CloudThresholdTests  | 80 of 80 passed |
|  The shared Cosmos DB database never needs a twenty-sixth container: the definitions and the live tests' copies stay at its limit, and the nightly card keeps its minutes and runs in the plan container under kinds of its own | ADR: The Nightly Function on the Admin tab | CosmosDefinitionTests, NightlyCardTests  | 118 of 118 passed |
|  The listing and the filter values leave compressed for a caller that asks, and no other address is compressed | ADR: Cache headers | CompressionTests  | 30 of 30 passed |
|  The listing and the filter values may be kept by the edge for seconds, and what only a deploy changes (the documents, the diagrams, the share picture) for a day; never for a request that carries a cookie, and never the resume, About Steven, the version, the admin reads or the sign-in; the browser is still told no-cache; and every address the edge card scores is one the edge may keep | ADR: Cache headers | CacheHeaderTests, EdgeKeepsTests  | 66 of 66 passed |
|  The default listing reads its page off the day's schedule order, and that order is the full ending-soonest sort at every instant, ties included | ADR: The search index | ScheduleOrderTests  | 152 of 152 passed |
|  Program.cs is a table of contents under eighty lines that maps no route itself, every route is mapped from a file under `Endpoints/` or `Composition/`, and every class in those two folders is static | ADR: The composition root, split by job | CompositionRootTests  | 10 of 10 passed |
|  The box posts a snapshot a minute and a live sample every two seconds behind the operator's key, read only after the key is checked; each reading passes the box's rules and list limits; three minutes of silence turns its card red, measured from the later of the newest snapshot and this process's start; no address or port reaches the card; an accepted post stays out of the ring and the request telemetry | ADR: The box reports itself | BoxSnapshotRulesTests, BoxCardTests, BoxRoutesTests, BoxWordsTests, BoxRowsTests, boxLive.test.ts, box.spec.ts  | 86 of 86 passed |
|  The nightly picker's card reads the 2 o'clock pick and the 1 AM scan from the Function's own run lines, red on a failed run, amber past a day and an hour and while postings are blocked, and names no company, title or lead | ADR: The nightly picker, code gates and the model ranks | PickerCardTests  | 38 of 38 passed |
|  Every card has a live route that answers 200, a source runs only while its card was read in the last minute and at its own grain, one ring type holds every live reading, and every live route and self-read stays out of the request telemetry | ADR: Live dials where the source allows | LiveTests, LiveRouteTests, live.test.ts  | 42 of 42 passed |
|  The plan card's live source reads memory as what is not available of MemTotal and the processor as the busy share between two reads of /proc, and says so where there is no /proc | ADR: Live dials where the source allows | ProcLiveSourceTests  | 6 of 6 passed |
|  Azure SQL's live line reads DTU as the greatest of the newest fifteen-second interval's processor, data IO and log write shares, adds no sample when nothing newer is there, and says so where the site keeps no relational store | ADR: Live dials where the source allows | SqlLiveSourceTests  | 10 of 10 passed |
|  Cosmos DB's live line sums this process's requests over the last five seconds into request units a second, counts the throttled ones, reads a quiet window as zero, and says so where the site keeps no document store | ADR: Live dials where the source allows | CosmosChargeSourceTests  | 4 of 4 passed |
|  Every public class and record in the solution says what it is for in an XML summary, and every positional record names each parameter; only the generated migrations are excused, by name | ADR: The composition root, split by job | XmlSummaryTests  | 4 of 4 passed |
|  The bill on the Admin tab is read from Azure once an hour and never on a request, a resource path is cut to its name and type before anything reaches the wire, the donut names four resources and folds the rest into Others, and a reading that is absent is a sentence and never a zero | ADR: What Azure charges | CostTests  | 64 of 64 passed |
|  The cost is graded on the month at yesterday's rate against the $60 budget, a day over three times the median of the week before it (never under $5) is red first, and every meter that can run away is joined by name to the rule that emails for it, unjudged and never red while a rule waits | ADR: What Azure charges | CostSpikeTests, TemplateTests, spendSpike.test.ts, ranges.test.ts  | 12 of 12 passed |
|  Every task in `.vscode/tasks.json` runs a script `package.json` declares or a project in the tree, every launch configuration runs a project that exists on the port its own `launchSettings.json` names, and the Working in VS Code page names every task and configuration | ADR: The editor is set up by the repository | WorkspaceTests  | 12 of 12 passed |
|  The gate on GitHub Actions runs every check the laptop's gate ran, writes every report the results writer reads, turns red when any check fails, runs The Shed's suites on Windows, and runs only on `gate/` branches with no permission to write | ADR: The gate runs where the memory is | GateWorkflowTests  | 38 of 38 passed |
|  The resume at /resume is the locked resume, byte for byte, inline under his name and the lock's date, and the door in its link is recorded as one allowed word, never the query | ADR: The resume has an address | ResumeAddressTests  | 22 of 22 passed |
|  A browser asking /resume for a page gets the door, one band to the review route above the same PDF; ?pdf=1 and every other caller get the locked bytes, a value that is not a code is never carried, and the embed carries no code | ADR: The resume has an address | ResumeDoorPageTests, resume.spec.ts, axe.spec.ts  | 10 of 10 passed |
|  The App Service plan is read a minute by the SQL site alone and kept thirty-one days, every window is drawn from the kept copy, and CPU, memory, the HTTP queue and sockets turn amber and red only when fifteen minutes in a row hold the line | ADR: The App Service plan, read every minute | PlanThresholdTests, PlanViewTests  | 40 of 40 passed |
|  Every resource under Cloud infrastructure is a definition drawn in the one frame, found in the resource group rather than typed, linked to the blade Azure returned, and turns amber and red at the lines its card names; a key the catalogue does not name is a 404 | ADR: One frame for every resource | CloudThresholdTests, CloudViewTests  | 78 of 78 passed |
|  The hundred thousand vehicles live in the store, each with the slot the hash gives it, and the slot is the hash's window on any day; the store filters, orders and pages and answers what the list in memory answers; a raised price is merged back where the full sort puts it; once the store answers the process holds none of the catalogue | ADR: The store does the work | StoreCatalogueTests, StockTests, CosmosDefinitionTests  | 80 of 80 passed |
|  Every collection a long-lived object keeps is named with what bounds it, every cache is bounded and expires, every outbound call shares one pool, and each .NET site runs under a heap limit of thirty per cent | ADR: The store does the work | MemoryRulesTests  | 20 of 20 passed |
|  A typed word of three characters or more matches the start of a word and a shorter one matches anywhere, on every store and every in-memory filter; on SQL a word page seeks the words table's word index and never reads every row's text; on Cosmos DB a page deep in the whole catalogue's order, the live segment by end, the upcoming by start or the ended by end is read from a kept place, the same rows as OFFSET for under 100 RU | ADR: The store does the work | VehicleSearchIndexTests, StoreCatalogueTests, CosmosKeysetTests  | 69 of 69 passed |
|  Memory that climbs while traffic is flat reads red on the Admin tab, and the week the catalogue moved into each process reads red on the readings the site kept | ADR: Memory follows traffic | MemoryTrafficTests  | 16 of 16 passed |
|  Every reader behind the plan card and the six resource cards runs against Azure's and Netlify's recorded answers through the one outbound pool: what it asks for, what it makes of the answer, and a refused metric, a refused query or an unseen site read as less and never as a failed card | ADR: One frame for every resource | CloudReadersTests  | 72 of 72 passed |
|  Rule 1 of the slices: every feature is a folder under the host's Features/ with a Module that registers and maps it, Program.cs is a loop over the modules under eighty lines that maps nothing, and a slice uses no other slice | ADR: The onion cut into vertical slices | SliceTests, CompositionRootTests  | 36 of 36 passed |
|  Rule 2 of the slices: no composition record that every registration takes whole; each registration is handed what it needs by name, and what runs at startup is one hosted service per concern | ADR: The onion cut into vertical slices | SliceTests  | 26 of 26 passed |
|  Rule 3 of the slices: the sites and the stores are a configured list, and the types that pick a request's site and store carry no store key and no host name | ADR: The onion cut into vertical slices | SliceTests, SiteHostsTests  | 38 of 38 passed |
|  A store's key is written once, in StoreKeys, and nowhere else in the host or the Application ring's source | ADR: Onion and SOLID, how this codebase holds them | SliceTests  | 26 of 26 passed |
|  Rule 4 of the slices: a backend and its attachment name no adapter in any member, however deep a generic argument goes, both stores answer one diagnostics port, and an endpoint outside the Admin tab and the health report never sees a backend | ADR: The onion cut into vertical slices | SliceTests, OnionTests  | 64 of 64 passed |
|  Rule 5 of the slices: a guest site stands behind IHostedSite, The Shed is its one implementation, and only ShedSite and ShedApplication use The Shed's assembly | ADR: The onion cut into vertical slices | SliceTests, OnionTests, ShedMountTests  | 72 of 72 passed |
|  Rule 7 of the slices: in every slice that has its handlers, each route asks exactly one Application handler, every handler is tested with fakes at its ports and no host, and every status code a route declares has an integration case | ADR: The onion cut into vertical slices | HandlerRuleTests, BidHandlerTests, BidEndpointStatusTests, VehicleHandlerTests, VehicleEndpointStatusTests, AccountHandlerTests, AccountEndpointStatusTests, PlanHandlerTests, PlanEndpointStatusTests, CloudCardHandlerTests, CloudViewTests, AdminEndpointsNightlyRunTests  | 102 of 102 passed |
|  Data has no behaviour (accessors, constructors and what the compiler writes for a record only), Data and Domain read neither the disk, the network nor the machine (a clock, a process, a type found by name), and an adapter neither uses the web beyond Identity nor decides on money | ADR: Onion and SOLID, how this codebase holds them | OnionTests  | 38 of 38 passed |
|  An endpoint class is any type that maps a route, whatever its name; the host queries neither SQLite nor any System.Data.Common connection itself; and a route delegate or a handler takes its settings, never IConfiguration | ADR: Onion and SOLID, how this codebase holds them | OnionTests  | 38 of 38 passed |
|  Rule 1 by folder: a file under Features/<Slice>/ declares that slice's namespace (one body from 1.0.4.70, tests/rules/NamespaceRule.cs, which the job hunt's suite runs over its three rings), and a host-root type one slice alone uses lives in that slice or is named with its record's reason | ADR: The onion cut into vertical slices | SliceTests, RingTests  | 26 of 26 passed |
|  The host root holds Program.cs alone; Features/ and Shared/ hold folders alone; every Shared concern is a row in the record's table and declares its own namespace; a shared type one slice alone uses is red with the slice named | ADR: The host root holds one file | HostLayoutTests, SliceTests, CompositionRootTests  | 50 of 50 passed |
|  Every request is a sealed `<Verb><Noun>Query` or `<Verb><Noun>Command` with exactly one handler implementing IQueryHandler or ICommandHandler and named for it; a query handler takes no store and no writer; nothing in the Application ring's root or slices is named *Service; the CQRS page's counts are the build's. From 1.0.4.43 the Admin tab's 24 reads are queries with one handler each over a port split by what it reads; fifteen routes stay exempt by name with a reason (the host's own files, health, pulse and error rings) | ADR: A request is a query or a command | CqrsTests, HandlerRuleTests, AdminQueryTests  | 32 of 32 passed |
|  One count of people who have visited, all time: one record a visitor under a keyed hash that does not rotate, never the address or the agent; who is a person is one Domain rule the Activity card and the count share; the collector writes a visitor once a day at most; the count is one query read by the Admin tab and the pulse | ADR: People who have visited, counted once | VisitorTests  | 18 of 18 passed |
|  Rule 2 for every hosted service: each is named with its one concern, has one public constructor and takes no service container | ADR: The onion cut into vertical slices | SliceTests  | 26 of 26 passed |
|  Rule 7 in every slice: a route asks one handler and takes nothing else this codebase defines but what is named beside it, or is exempt by name with its reason; a [Covers] counts only beside an assertion of its status, and a handler is tested with fakes only in a test that asserts | ADR: The onion cut into vertical slices | HandlerRuleTests  | 6 of 6 passed |
|  The front end's layers: src/lib imports nothing from React, a hook imports no component, a request is written in src/lib inside the working store, and the browser's ordering bands equal the Domain's | ADR: Three readers with no memory of the project | FileHeaderTests, WorkingLockTests  | 14 of 14 passed |
|  Rule 6 of the slices: outside the composition root, a list of types each with its reason, the host never reads the environment, a service container (GetService, GetRequiredService, ActivatorUtilities, a request's RequestServices) or the built app's configuration, and the Application ring never does at all; the platform's settings are read once into BuildInfo and HostIdentity | ADR: The onion cut into vertical slices | OnionTests  | 38 of 38 passed |
|  A session is refused on any store but the one that opened it, and a session ended on its own store opens neither | ADR: The onion cut into vertical slices | RefuseSessionTests, AuthTests  | 14 of 14 passed |
|  Every test class that bids, buys, resets, runs the room or runs the proof through the booted host is in the shared bid store's collection, so no two write the shared Cosmos DB test database at once | ADR: The onion cut into vertical slices | SharedStoreTests  | 4 of 4 passed |
|  The plan's socket limit follows the size the plan record names, and the free tier's storage allowance and the Basic read rate apply only while the record says free tier and Basic | ADR: The onion cut into vertical slices | PlanThresholdTests, CloudThresholdTests  | 54 of 54 passed |
|  A tagged link's open is counted by its six-character code and its path, a preview fetcher's or a scanner's is not, a pass-through key the configuration does not name is 404, and the card's wire holds codes, paths and counts and nothing that names a person | ADR: Tagged links, who opened what | LinkHandlerTests, LinkEndpointStatusTests  | 96 of 96 passed |
|  A reach is folded by `ReviewFolding` and a lower stop never lowers a row | ADR: Ten minutes, seven stops | ReviewFoldingTests, ReviewHandlerTests, ReviewEndpointTests  | 40 of 40 passed |
|  Every review stop names a decision record the catalogue serves, seven distinct, none its own stop's address | ADR: Ten minutes, seven stops | ReviewRecordsTests, reviewStops.test.ts, render.test.ts, review.spec.ts  | 2 of 2 passed |
|  A Shed that will not start answers 503 and leaves the Yard up; a Shed request that fails past its handler is a 500 problem in TheYard's error record; The Shed's upload limit is The Shed's alone; The Shed is stopped by the last hosted service, after the drain | ADR: The onion cut into vertical slices | ShedMountTests  | 8 of 8 passed |
|  No name of this deployment, its resources, its edge, its public domain or its identity's ids, and no price, plan size or date other than a Resource Manager api-version, is written in the six projects' code; every string constant they compile is read back, and the allow list is empty | ADR: The onion cut into vertical slices | LiteralScanTests  | 8 of 8 passed |
|  Every card under Cloud infrastructure answers the same slots (title, link, tone, spec and its source, headline, dials, sparks, threshold chips, chart, rows, summary, read-at, refresh, cadence and its unread line), every summary line and row names its source, one tone rule in Domain gives the card its tone, the cadence on the wire is the one that rule judges with, and the page reads every card as often as that rule assumes | ADR: The onion cut into vertical slices | CardFrameTests  | 42 of 42 passed |
|  The nightly lane's slots are one table in Domain that the Function compiles by a link and its clock asks, judged on time, late or missed from five-minute firing counts on both daylight-saving days; the nightly card's dials turn at their lines, every Azure line reads "not read: no role on" the configured group while the identity has none, the run log warns on one failed run and alarms on two, GitHub's runs are parsed by lane, the snapshot count is the Function's own, and a run the workflow posted is kept under GitHub's own id, read by the same rules GitHub's own list is read by, and preferred over a read of GitHub while every slot due since it was answered by a push | ADR: The Nightly Function on the Admin tab | NightlySlotsTests, NightlyCardTests, AdminEndpointsNightlyRunTests  | 150 of 150 passed |
|  The working lock shows only after a request a person started has run half a second, clears on the last one answered or failed, never for a background read, covers the page and takes its clicks while it is up, and never shows for a fast answer | ADR: One working lock for the whole site, after half a second | WorkingLockTests, working.test.ts, working.spec.ts  | 6 of 6 passed |
|  The nightly card asks the job hunt's Function whether the tracker merger is keeping up and keeps only the five numbers its health route answers, so no file name, row or log line from the share reaches the site; the row is good under five minutes waiting and a warning past ten | ADR: The tracker merger runs in Azure | NightlyCardTests  | 92 of 92 passed |
|  A usage document is kept only when every rule holds (lane, model, run, counts, slot, mode, a start inside seven days), the route refuses without the operator's key before it reads a body, a document posted twice is kept once, the Claude usage card draws through the catalogue with the slot join's two sentences and dry runs out of the averages, and no source file but the one client names the Anthropic API | ADR: Every Claude lane reports its usage | UsageRecordTests, UsageLogTests, AdminEndpointsUsageTests, ClaudeCardTests, OnionTests  | 94 of 94 passed |
|  Only Infrastructure opens a socket: no host type but Program and a slice's Module names an HttpClient, a handler or a client factory, and every client is built in OutboundHttp beside the one pool; from 1.0.4.70 one body, tests/rules/SocketRule.cs, that the job hunt's suite runs over its Domain and Application | ADR: The onion cut into vertical slices | OnionTests, MemoryRulesTests, RingTests  | 58 of 58 passed |
|  Every file in Domain, Application and both adapters sits under Features/<Slice>/ or Shared/<Concern>/ and declares its folder as its namespace; only the types Entity Framework maps stay at the relational adapter's root, each named | ADR: The onion cut into vertical slices | SliceTests  | 26 of 26 passed |
|  The nightly card's six process sections read the Function's run lines and request rows through one Kusto shape, the runs route answers a page of twenty for one of the six and a 404 problem for any other name, a closed run history asks for nothing, and every figure names its source | ADR-109, the addendum on the six processes | ProcessRunsTests, ProcessReadersTests, cloud.spec.ts, axe.spec.ts  | 88 of 88 passed |
|  The words a process section prints are the code's own: each timer's summary and the Function's paragraph are read from the repository at the version deployed, and the schedule table holds the Function's own cron strings | ADR-109, the addendum on the six processes | ProcessReadersTests, ProcessRunsTests  | 88 of 88 passed |
|  A blog picture is served from the site's own address under the hash of its bytes with a year's immutable cache, a name the rule does not make is never looked up, the host's memory answers a second read, and the container is private | ADR-113, the addendum on where the pictures live | BlogImageTests, BlogImageRouteTests  | 10 of 10 passed |
|  A picture is put on a post only with the operator's key, and is refused by the figure it breaks: over a megabyte, not a PNG, JPEG or WebP by its own bytes, over 2000 pixels wide, or without an alt text; its size is read from its own header | ADR-113, the addendum on putting a picture in | BlogUploadTests, BlogUploadRouteTests, blog.test.ts  | 18 of 18 passed |
|  The nightly card draws the Function's seven processes, the campaign among them with its switch, and its next run is the next 8 AM Central under either clock | ADR-109, the addendum of 1.0.4.60 | ProcessRunsTests, ProcessReadersTests, cloud.spec.ts  | 88 of 88 passed |
|  A promotion moves main only for a run whose gate and Shed jobs are green on the commit it promotes, one commit on main, its version up by one in the fourth number; and no deploy rolls a commit main has left | ADR-098, the addendum of 1.0.4.107 | PromoteScriptTests, PromoteWorkflowTests, MachineFreeWorkflowsTests  | 106 of 106 passed |
|  The box's test runner skips a suite whose source folder the branch does not carry and says so, runs one that is there, and a red suite beside a skipped one still fails the run | ADR-098, the addendum of 1.0.4.163 | YardTestScriptTests  | 6 of 6 passed |
|  The campaign card reads counts only and never shows a name, a company, an address or a code, is red at two bounces in a day and at no send by 9 AM with leads ready, names the day its counts start, and its cap is the Function's own | ADR-118, Decision 6; ADR-102, the addendum of 1.0.4.63 | CampaignCardTests, CloudDrawingTests, cloud.spec.ts  | 30 of 30 passed |
|  Rule 1 across the rings: a type under Features/<Slice>/ in Domain, Application, either adapter or the host uses only its own slice and the Shared concerns in any ring, never another slice's type in any ring (the host's Admin sub-slices are the one Admin slice to the inner rings) | ADR-107, the addendum of 1.0.4.67 | SliceTests  | 26 of 26 passed |
|  A query handler is handed no port that can write: no constructor parameter among this codebase's types has a member, counting every inherited interface, whose name starts with Keep, Write, Save, Upsert, Delete, Add, Remove, Record, Put or Set; the name check stays beside it | ADR-115, the addendum of 1.0.4.68 | CqrsTests  | 14 of 14 passed |
|  Nothing in the job hunt Function's Domain or Application writes a mail search (no from:, subject:, in:inbox or newer_than: on a code line); a search is a MailSearch and only the Gmail adapter composes Gmail's syntax, every search held to the string it sent before | ADR-117, the addendum of 1.0.4.69 | RingTests, GmailQueryTests  | in its own suite, not this file |
|  Every CI and gate job installs .NET through .github/actions/dotnet, which tries the download twice a minute apart and then uses the runner image's own .NET 10 SDK, failing only when there is none | ADR-068 | DotnetInstallTests  | 6 of 6 passed |
|  The job hunt Function's Infrastructure reads the environment only in the four files named with their counts until stage B of ADR-117 hands each host its settings, and the rule bodies the two suites share live once under tests/rules/, linked into both test projects | ADR-117, ADR-075 the addendum of 1.0.4.70 | RingTests, OnionTests, SliceTests, FileShapeTests  | 68 of 68 passed |
|  The tracker's SQL copy is the CSV byte for byte: the file is cut at CRLFs outside quotes and put back identical, the mirror writes only the rows whose hash changed, and a rebuild from the copy is compared with the CSV, which stays the master | ADR-111, the addendum of 1.0.4.73 | TrackerSqlTests  | in its own suite, not this file |
|  The job hunt Function's slices: a type under a ring's Features/<Slice>/ uses only its own slice and the Shared concerns in any ring, shared code uses no slice, no file sits at a ring's root, and a use case that only reads is handed the reading half of a split port. From 1.0.4.127 which use cases those are is FOUND and not listed: one body, tests/rules/UseCaseRule.cs, reads the ring for every type handed a port and asks the compiled code which of them write, so a read-only use case nobody wrote down is covered too, and the Function's practices counts are the build's | ADR-107 and ADR-115, the addenda of 1.0.4.75 and of 1.0.4.127 | SliceTests, CqrsTests  | 40 of 40 passed |
|  Each process is one deployable cut into modules that are its slices: a slice's files name no other slice in any ring, every host module registers through a Module.cs, and the site, the Function and the machine lanes share rings and named linked files, never a project | ADR-119 | ModularMonolithTests  | 8 of 8 passed |
|  Every incident under docs/incidents/ keeps the title, the status line and the eight sections in order, names a source in every Timeline row, names only versions the changelog shipped under What changed, says a state for every follow-up, and is listed in the index | ADR-120 | IncidentShapeTests  | 10 of 10 passed |
|  The Foreman's page keeps its five sections in order, every reading names its route, rung 0 names no cause without three agreeing sources, and every place to start names a record, a file and a test that exist | ADR-121 | ForemanTests  | 8 of 8 passed |
|  A card's live read that times out is the recorder's gap and the card answers from its keep; only the request's own cancellation stops the read | ADR-102 | CloudTimeoutTests  | 8 of 8 passed |
|  Every quality number the ratchet file holds has a row in the record that explains what it counts, both workflows run the scanner against that file, the gate's verdict reads its result, and the coverage floor stays at ninety and seventy-five | ADR: The numbers that may only fall | QualityRatchetTests  | 12 of 12 passed |
|  Every async method in production C# takes a CancellationToken but the one framework override whose signature this codebase does not own; the parameters a declaration takes are read across an attribute's brackets, a tuple's and the lines a wide signature wraps onto; and every timer the job hunt Function runs declares the token Azure hands it and passes it on | ADR: The numbers that may only fall | CancellationTests  | 18 of 18 passed |
|  Outside a composition root (a slice's Module, the wiring, Program.cs or the Clocks seam) a time is read from a TimeProvider handed in by constructor, and the thing it was handed to uses that clock rather than the real one | ADR: Onion and SOLID, how this codebase holds them | ClockSeamTests  | 14 of 14 passed |
|  How many things a class is handed is counted in parameters and not in commas, so a comma inside a generic type argument is not a separator and a parameter list that wraps is read to its closing bracket; the classes still handed six or more are named one by one and their number is the ratchet's limit; and every part split off one of them resolves from the real host | ADR: The numbers that may only fall | ConstructorWidthTests  | 50 of 50 passed |
|  The projects whose declarations all carry a summary are named one by one, and in a named project every public, internal or protected declaration says what it does, asked through one rule body both suites share and the same question the ratchet's scanner asks | ADR: The numbers that may only fall | MemberSummaryTests  | 6 of 6 passed |
|  What the campaign and the network log both use is a shared concern of the Function's Domain and Infrastructure, never one slice reaching into another: the former employers, the company key and the personal domains under Shared/Companies, the tells and the stop phrases under Shared/Writing, the MIME parts under Shared/Google and the SQL command builder under Shared/Sql, each moved with the campaign's answers unchanged | ADR-119, Decision 4 | NetworkSharedTests, SliceTests  | 26 of 26 passed |
|  The network log's rules, each with named cases: a person is not a machine, not Steve and not a former employer's work address; a thread is two-way when a person and Steve both wrote or a person sent an invite; a row is keyed by its lower-case address or its LinkedIn slug and joined across channels by name and company; a personal address counts only when the job hunt knows the person; a follow-up is owed 21 to 45 days after the last exchange with a TopicLine, at most fifteen a Monday; a sent follow-up met by 21 days of silence is Quiet; a stop phrase stops and a bounce closes; and FOLLOWUP-v1 renders with no dash, no tell, no blank, one question and a one-line Re: subject | ADR-118, Decision 1 | NetworkLogRulesTests, NetworkLogFollowUpTests  | in its own suite, not this file |
|  The network log's store names only columns the SQL project declares, its record's fields are its table's columns, the card view carries counts only, the Gmail adapters read a thread's metadata as the rules expect, write a draft into its thread byte for byte with the label listed once, and nothing in the network log can send | ADR-118, Decision 2 | NetworkSqlTests, NetworkGmailTests  | in its own suite, not this file |
|  The network log's daily pass runs once a Central day in the 6 o'clock hour (or any hour while its any-hour switch is on), retries a pass that began two hours ago and never finished, reads 120 days on its first pass and two after, leaves the campaign's open threads alone, counts and skips a stranger on a personal address, moves a stored row forward and never back, stops on a stop phrase, closes a stale silence, joins a LinkedIn spool row to its email row by name and company and moves the file to done, writes the TopicLine export and the Monday would-drafts, and in shadow never calls the draft port | ADR-118, Decision 3 | NetworkLogPassTests  | in its own suite, not this file |
|  A TopicLine is one plain clause of 12 to 160 characters on one line with no dash, no tell, no question or second sentence, no link and not the subject over again; the import reads the last three Central days of the 4 AM lane's files oldest first so the newest wins, a re-read changes nothing, and a refused line leaves its row waiting | ADR-118, Decision 5 | NetworkTopicTests  | in its own suite, not this file |
|  The inbox pass skips LinkedIn's digest header and counts it, keeps the company, title and location in their columns, and passes a lead whose location is the country alone as remote; the two days of leads files it wrote on 4 and 5 November are re-filtered and their pass counts held | ADR-111, the addendum of 1.0.4.141 | LeadsFixtureTests  | in its own suite, not this file |
|  The board scan runs at 1 AM Central and keeps every posting as one row keyed by its board and the board's id, two scans make no second row, a moved title, level, band or stance is one change row each, a posting gone from its board is closed, a re-post one level down within 30 days is linked, a schema not yet published leaves the scan marking companies as before, the three feeds give the band the board published or null, and the boards inbox adds a board once up to four hundred | ADR-118, the addendum of 1.0.4.142 | PostingsTests, PostingsSqlTests  | in its own suite, not this file |
|  The night's picker holds every role to its gates in code with a named case each (staffing firm, former employer, remote or St. Louis hybrid at one day, 21 days, a lead level and a Senior only over the pass line, the band's two lines from one PayFloor class, a C#, .NET, Azure or AI-native lead stack, the same role applied to, RULE 50), writes the candidates file with its supply line and every failure under its gate, drops an alert the scan confirmed, falls back to the alert leads and the share's CSV, runs in the 2 o'clock hour on the nightly switch, reads only columns the SQL project declares, and nightly.yml runs the jobs lane on Opus with the web (1.0.4.144) | ADR-125 | JobsTests, CampaignTextTests  | in its own suite, not this file |
|  Template A v2 is the only A the send selects, sixty words or fewer with one link and no dash or tell; the week's applications with a named person become one Track A lead a company however many passes run; a shared mailbox or no address holds a Track A lead and never reaches the send port; Track A goes first, the oldest application first; and shadow writes its rows and sends nothing | ADR-118, the addendum of 1.0.4.145 | TrackATests, CampaignSendTests  | in its own suite, not this file |
|  In on, a Monday's follow-up is a Gmail draft written into the row's own thread to the address the person wrote from, under the label id the port answered, read back before the row is Drafted, never written twice in one Monday, and nothing for a failed render; a row last heard on LinkedIn gets no Gmail draft and goes to the week's LinkedIn queue instead; in shadow the same rows are would-drafts and the draft port is never called | ADR-118, Decision 3 | NetworkDraftTests  | in its own suite, not this file |
|  A Monday's due LinkedIn follow-ups are the week's queue in the reply queue's format 2, every item under section A with its draft beside it and its thread and profile noted, the rows left Open and no Gmail draft written, the subject check not run on a message with no subject, and the morning card shows the week's queue beside the day's reply queue with each draft in full | ADR: The network log drafts, Steve sends | NetworkLinkedInQueueTests  | in its own suite, not this file |
|  The network card reads counts only from card.Network and never shows a name, a company, an address or a code, names the Function's own Monday cap and states, reads this week against the four before, says unread when nothing was read, and the alert emails Steve when no network pass ran, or one failed, by the 13:00 UTC hour | ADR: The network log drafts, Steve sends | NetworkCardTests, TemplateTests  | 12 of 12 passed |
|  The network card's logging row reads the newest pass the run history lists: failed is alarm with what it came to, blocked or late is warning in its words, no pass for 25 hours is warning with the last one's time, a pass that came through is good, an unread history is info and says why, and the switch off is off | ADR: The network log drafts, Steve sends | NetworkPassTests  | 18 of 18 passed |
|  The network pass's Gmail reads wait out a 429, a server error and the 403 Gmail gives a user over its quota, five times with a doubling wait, and an answer they give up on fails with Gmail's own reason word | ADR: The network log drafts, Steve sends | NetworkGmailTests  | in its own suite, not this file |
|  The network pass's Gmail reads are spaced 50 milliseconds apart, under the user's quota; a first pass cut by its budget or its thread cap leaves its resume point on the share, one second past the oldest thread it read, the next pass reads the window before that point beside its two days and says done once a read is whole, a read that gets no further never loops, and a Monday flipped to on after its shadow pass runs once more outside the 6 o'clock hour | ADR: The network log drafts, Steve sends | NetworkBackfillTests, NetworkGmailTests, NetworkSqlTests  | in its own suite, not this file |
|  A follow-up names a TheYard post only when the 4 AM lane handed its row a slug of the feed's shape and a six-character make_ref code, the lane is asked for one from three days before due until stale on an Open email row with none, the import stores the first good one once and refuses a bad one, the post is on the feed and newer than Steve's last message, the link is the post's address with the code and an anchor in the HTML, its question mark is not the draft's question, a line that fails a check is dropped with the draft still written, and the feed is read only when a due row names a post | ADR: The network log drafts, Steve sends | NetworkBlogLineTests  | in its own suite, not this file |
|  Every resource the network card names, its database in the header and the Function in its first row, carries its tenant-qualified portal link from the API, read or unread, and no name is left as plain text | ADR: The network log drafts, Steve sends | NetworkCardTests  | 12 of 12 passed |
|  Every card under Cloud infrastructure in the host's catalogue, walked card by card: drawn from nothing read it names a source on every row and line and no dial it did not read is coloured; fifteen quiet minutes of every reading raise no dial (a dial whose line runs downward reads alarm at zero); its cadence on the wire is its catalogue flag's; three reads old is still judged and one second more is unread; a warning row outranks an old reading | ADR: One frame for every resource | CardContractTests  | 86 of 86 passed |
|  The Azure SQL Database card's DTU dial reads good, information within five of amber, warning from amber and alarm from red, each held fifteen minutes, and fourteen minutes are not judged; data space reads against the database's own cap; a deadlock is red; nothing read says so; every row and line is sourced | ADR: One frame for every resource | SqlCardTests  | 28 of 28 passed |
|  The edge's retire row is information before its date and counts the days, and a warning on it and after it that names the date; the credits dial is judged on its newest hourly reading alone; a certificate inside two weeks and a failed deploy are each a warning | ADR: One frame for every resource | EdgeCardTests  | 18 of 18 passed |
|  With no Edge:Retires set the edge's retire row reads "the edge stays" as information and the readout says the date is not set; the host starts without the setting | ADR-102, the addendum of 1.0.4.167 | EdgeCardTests  | 18 of 18 passed |
|  When no reply run of the day wrote linkedin-queue.md the 5 o'clock hour in Central dispatches the reply lane once more, on both sides of the clock change; a queue from any real slot is enough and a dry run's never is | ADR-117, the addendum of 1.0.4.168 | ReplyRetryTests  | in its own suite, not this file |
|  Every test class that starts TheYard with The Shed mounted runs in the ShedHosts collection, one after the other | ADR-075, the addendum of 1.0.4.169 | ShedHostsTests  | 2 of 2 passed |
|  The job hunt funnel reads the Function's daily process:Funnel line into its day and six counts, counts a day written twice once, and grades the newest seven days' calls booked: two or more fine, one amber, none red, no line unread; a refused read is unread, never a 500 | ADR-109, the addendum of 1.0.4.170 | FunnelTests, FunnelEndpointTests  | 24 of 24 passed |
|  TODAY.md is rewritten whole in the 7 o'clock hour Central in a fixed order, CRITICAL sends first with their full text; an answered ask or a draft with a DO-NOT-SEND note never reaches it; rejection reads carry forward; past 15 minutes the held replies fold; the mail goes to his own address only | ADR-117, the addendum of 1.0.4.171 | TodayCardTests  | in its own suite, not this file |
|  The Function's funnel line counts one Central day from its logs and each tracker row's opening phrase, a person once a day, never a NO or NOT send; its detail is the day; the share's log sums into the week's line on TODAY.md, each day its latest line and a missing day named | ADR-109, the addendum of 1.0.4.175 | FunnelLineTests  | in its own suite, not this file |
|  The container's own sampler keeps an hour at fifteen seconds (240 samples) in the host, drops its oldest sample when full, keeps one when asked for none, and reads the runtime's own limit and processors | ADR: What the machines are doing | ContainerSamplerTests  | 8 of 8 passed |
|  A Cloud card's request answers from a view under two minutes old and builds the next behind it past one minute; a view at two minutes is not served; the keeper builds each window asked for in the last hour once a minute and drops the rest | ADR-102, the addendum of 1.0.4.164 | CloudKeepingTests  | 8 of 8 passed |
|  Every rule CodeRabbit is told ends with the record that decided it and that record exists, the rules it is told are the ones ADR-129 lists, and its profile and two switches are the ones ADR-129 names for the current level | ADR-129 | CodeRabbitRuleTests  | 26 of 26 passed |
|  The gate promotes only after CodeRabbit's review of the gate's pull request is read or its ceiling passed, never holds a ship on a finding at Level 0, folds the review's row into the findings log, and closes the request on main's commit | ADR-129 | PromoteWorkflowTests, PromoteScriptTests  | 92 of 92 passed |
|  The findings log counts each CodeRabbit finding by the label in its header alone, and a remark with no label as a nitpick; from 1.0.4.178 only the gated commit's findings and never a reply in a thread, and every ship has exactly one row whatever the read did | ADR-129, the addenda of 1.0.4.177 and 1.0.4.178 | CodeRabbitRuleTests  | 26 of 26 passed |
|  The quality history starts on 15 October, before the ratchet went in, with no limit before it, runs in version order with every number the ratchet names, and its newest row is what the scanner reads at HEAD (from 1.0.5.2; a newest row behind the changelog is a gap, never a red gate); every number on the Quality page is read live from data the build carries, and the page types none of its own | ADR-130 | QualityHistoryTests  | 8 of 8 passed |
|  A version that moves the first three numbers ships only by hand, with the person promoting naming it as OWNER_YES, moves the third number by one and starts the fourth at 0; the gate ends green with a notice and moves nothing, whatever its environment holds | ADR-130 | PromoteScriptTests  | 32 of 32 passed |

## The ratchet, read from this build

The limits, one per number:

```json
{
 "undocumented_declarations": 399,
 "onion_outward_refs": 0,
 "inner_ring_leaks": 0,
 "cross_slice_usings": 0,
 "wide_service_classes": 8,
 "async_without_cancellation": 1,
 "clock_outside_composition": 35,
 "history_or_name_comments": 0,
 "blocking_waits": 0,
 "files_over_300": 0,
 "files_within_10_of_cap": 2,
 "behavior_types_never_named_in_a_test": 0,
 "react_files_without_header": 241,
 "test_to_prod_ratio_higher_is_better": 0.81,
 "dotnet_tests_higher_is_better": 3473
}
```
*Live from [`.github/quality-ratchet.json`](https://github.com/SteveStout/TheYard/blob/59de5d1/.github/quality-ratchet.json#L1-L17), region `*`, read from this build at 59de5d1.*

And the block of the scanner that measures them:

```python
# The ratchet: one number per line, lower is better unless the name says otherwise.
R["ratchet"] = {
    "undocumented_declarations": sum(v["decls"] - v["documented"] for v in docs.values()),
    "onion_outward_refs": len(outward),
    "inner_ring_leaks": len(leak),
    "cross_slice_usings": len(cross),
    "wide_service_classes": len(wide),
    "async_without_cancellation": len(smell["async_no_token"]),
    "clock_outside_composition": len(clock),
    "history_or_name_comments": len(hist),
    "blocking_waits": len(smell["blocking_wait"]),
    "files_over_300": sum(d["over_300"] for d in size.values()),
    "files_within_10_of_cap": len(near),
    "behavior_types_never_named_in_a_test": len(untested),
    "react_files_without_header": len(hdr_missing),
    "test_to_prod_ratio_higher_is_better": R["tests"]["test_to_prod"],
    "dotnet_tests_higher_is_better": facts + rows,
}
```
*Live from [`.github/quality.py`](https://github.com/SteveStout/TheYard/blob/59de5d1/.github/quality.py#L553-L570), region `ratchet`, read from this build at 59de5d1.*

## Files

- [`data/quality-history.json`](https://github.com/SteveStout/TheYard/blob/main/data/quality-history.json): the history, one row per shipped version
- [`scripts/quality_history.py`](https://github.com/SteveStout/TheYard/blob/main/scripts/quality_history.py): rebuilds it from git and adds a row on every ship
- [`api/TheYard.Api/Features/Docs/QualityCounts.cs`](https://github.com/SteveStout/TheYard/blob/main/api/TheYard.Api/Features/Docs/QualityCounts.cs): every live number on this page
- [`api/TheYard.Tests/QualityHistoryTests.cs`](https://github.com/SteveStout/TheYard/blob/main/api/TheYard.Tests/QualityHistoryTests.cs): holds the history to the scanner and this page to the data
