Missing documentation announces itself. Drifted documentation does the opposite — it was true when somebody wrote it, the code moved underneath, and the file still reads as authoritative. It still carries a date. It still passes review.
[high] doc stale docs/modules/billing/limiter.md · the code's commit is a descendant of the doc's
Staleness is decided by git commit ancestry, not a hand-written date. Sometimes ancestry cannot decide — a rebase, divergent branches, a shallow clone. That is a third answer, and it gets reported as one.
The doc's commit follows the code's, or they landed together. It was actually checked.
The code's commit is a descendant of the doc's. The doc got left behind, and the gate refuses the next commit.
Reported under [skipped], never counted as a pass. A tool that cannot tell and answers "fine" is worse than no tool at all, because you believe it. Every amber mark on this page is that third answer.
No timestamps, no hand-written "last reviewed" line to forget. If the code's commit is a descendant of the doc's, the doc was left behind — and git already knows.
adda sync --map
An explicit, greppable map from every code path to the document that must change with it. Derived from the repo, not hand-kept.
adda audit
Missing, stale, orphaned and unmapped docs across the whole repository. Exits non-zero, so it drops straight into CI.
adda hook install
A commit gate. Staged code without its staged document does not get committed — not a warning you learn to scroll past.
$ git commit -m "switch limiter to token bucket"Commit blocked: 1 code change(s) without their doc. src/billing/limiter.py -> update and stage docs/modules/billing/limiter.md Update the doc (bump `Last verified`, append to its Change Log), then stage it.To bypass deliberately: `git commit --no-verify`, or set ADDA_SKIP=1.
Commit SHAs are recorded, because otherwise the numbers are reproducible mechanically but not in time. The amber column is the point: it is what ADDA declined to map, said out loud.
| repo | commit | files mapped | reported as skipped | collisions | time |
|---|---|---|---|---|---|
| django | 0b40210 | 719 | — | 0 | 2.18s |
| date-fns | a0a3922 | 1256 | — | 0 | 1.33s |
| fastapi | 9a8a13f | 41 | 458 · docs_src/ | 0 | 0.26s |
| flask | d318b68 | 21 | — | 0 | 0.01s |
| requests | 5460f46 | 18 | — | 0 | 0.01s |
__init__.py — so the call is yours rather
than the tool's. Zero collisions across 2,066 mapped files: a doc path
shared by two code paths is a module reported as documented while having no
documentation of its own, and the mapping is derived so that cannot happen.
ADDA detects the document nobody touched. It does not detect the document somebody touched carelessly — if the code and the doc are committed together but the doc was updated wrongly, ancestry says they moved together and every check passes.
Catching that needs a model reading both and forming a judgement. ADDA is deterministic and offline by design, so it does not cross that line. The limit is published rather than left for you to find.