Sweep the code in scope and check it against the project's own ubiquitous
language — the terms CONTEXT.md and docs/adr/ already define. Code that
drifts from those terms makes every reader re-translate between what the docs
call a thing and what the code calls it.
The default deliverable is a report, not applied edits. The sweep writes
a machine-readable findings log and a grouped HTML summary; it touches no
code.
The one test
A finding fires only when a code name displaces a specific named domain
term. Default is NO FINDING: the burden of proof is on the finding, not the
name. A name that is merely vague, generic, or not what you'd have chosen —
with no defined term standing behind it — is not this audit's business. If
you cannot point at the term the name displaces and where it's defined, there
is no finding, no matter how bad the name is.
This is not a style pass. data, helper, process in a file with no
glossary are ugly, not drift — nothing has been displaced, because nothing
was ever defined. The moment a term is defined and the code disagrees, that
disagreement — and only that — is in scope.
Extract the term set first — and print it
Before judging anything, read every CONTEXT.md in the repo (root and
nested, e.g. <some-skill>/docs/CONTEXT.md) and every file under
docs/adr/, and build the term set: each defined noun/verb, its definition,
and its source file. Glossary entries (**Term** — definition) and ADR
decision titles/bodies that name a concept both count.
Print this term set at the top of the report, verbatim — term, one-line gloss,
source. A wrong or incomplete extraction must be visible in the report, not
silent — if the repo has no CONTEXT.md/docs/adr/, the term set is empty
and the report says so plainly; that is a correct, boring result, not an
error to paper over.
Buckets & categories
rename / generic-standin — a code name is generic where the project
has a specific defined term for exactly that thing (data where the domain
term is Order; process() where the term is reconcile).
consolidate / synonym-sprawl — two (or more) code names refer to the
same concept the glossary treats as one term (job and task both meaning
what CONTEXT.md calls a Run).
misuse / term-misuse — a defined term is used in code for something
the glossary says it is not (a variable named parent holding what the
glossary defines as a blocker — CONTEXT.md's own _Avoid_ note may name
the mix-up directly).
extra carries should_be (the displaced/correct term) and source (where
it's defined, e.g. CONTEXT.md or docs/adr/0001-....md). The displaced term
must be named in both failure and extra.should_be — a finding that can't
name the term it displaces is not a finding, per the one test above.
The audit, worked
CONTEXT.md defines Run — "one orchestrator invocation, loops
plan→execute until the backlog drains." The code has two names fighting over
that concept:
function startJob(cfg: Config) { ... } // job.ts
function runTask(id: string) { ... } // scheduler.ts — same invocation
Neither name is wrong on its own — startJob and runTask both read fine
in isolation, which is exactly why a style pass would pass them. Set beside
CONTEXT.md's Run, they're two names for the one term the glossary already
settled: a consolidate / synonym-sprawl finding, should_be: "Run",
source: "CONTEXT.md".
Contrast a name the audit leaves alone: cfg in the same file. Generic,
sure — but nothing in CONTEXT.md or the ADRs defines a term cfg displaces.
No finding.
Out of scope
Pure style naming — snake_case vs camelCase, unclear-but-undefined names,
abbreviation style — is a different axis and stays with ruff N. This audit
only fires where a defined term exists and the code disagrees with it. Do
not flag a name for being bad; flag it only for being wrong against a
specific, sourced term.
Run
Scope. Audit $ARGUMENTS if given; with no argument, scope defaults
per ~/.agents/skills/all-audits/SKILL.md's Scope section. Skip vendored, generated, and dependency trees
(node_modules, dist, .venv, build output, lockfiles) and any
worktrees/ tree.
Extract and print the term set as above, before judging any code.
Sweep every name in scope against the term set — identifiers, class
names, function names, key variable names, not a sample. For each one,
check: does a defined term describe exactly what this name refers to, and
does the code's name disagree with it (generic-standin), collide with
another name for the same concept (synonym-sprawl), or borrow the term for
something else (term-misuse)? A name with no term behind it is silently
fine — do not record it, do not almost-flag it.
Then, for each confirmed drifted word, enumerate every site — grep, do
not eyeball. A rename executed from this finding must be safe and total,
so the site list has to be both exhaustive and clean. grep the whole
repo — not just the audit scope; a drifted word's occurrences straddle
files the diff never touched, and a rename touches all of them — for the
word in every form it takes: identifiers, string literals, dict keys, CSS
class names, filenames. Then re-check each hit against the term's meaning
before you emit it — the same one test as above, applied per site: a hit
that uses the word in a different, correct sense is not drift (invalid puzzle document covering broken JSON, when the glossary excludes that from
malformed, is a defensible clear, not a rename target). Emit one finding
row per real drift site, all sharing the same should_be and source.
Miss a real site and the rename half-applies — renaming the dispatch call
but not the constructor literal it dispatches to breaks the code; sweep in
a defensible clear and the rename corrupts a correct use. If you cannot
confirm the list is complete, flag the term partial coverage in the
summary rather than presenting a half-list as the finding.
Write the findings log and render the summary — the default
deliverable. See
~/.agents/skills/all-audits/harness/AUDIT-RUN.md for the shared
write-and-deliver step (tmpdir resolution, findings.jsonl +
report.html, opening, and the final print). This skill's own bucket
names and metabar:
Write the log and render the summary
- Log — one JSONL line per finding, the six required fields plus
extra:
file and line where the drifting name sits, summary (one line, what
drifted), bucket (rename / consolidate / misuse), category
(generic-standin / synonym-sprawl / term-misuse), and failure naming
the displaced term and the concrete confusion it causes ("reader sees data
and can't tell this is the Order CONTEXT.md defines without opening the
file"). extra carries should_be and source.
- Summary — the term set (term, gloss, source) printed in full at the
top, then the verdict, the
N findings · R rename · C consolidate · M misuse metabar, findings grouped by bucket then category with counts, and
a vt-callout naming the highest-value finds by file:line. No
per-finding cards. Any term whose site list isn't confirmed exhaustive
carries a partial coverage flag here.
1---2name: domain-drift3description: Audit whether code names match the project's own domain vocabulary — a generic name standing in for a defined term, two names for one concept, or a term used for the wrong thing.4---56Sweep the code in scope and check it against the project's own ubiquitous7language — the terms `CONTEXT.md` and `docs/adr/` already define. Code that8drifts from those terms makes every reader re-translate between what the docs9call a thing and what the code calls it.1011The default deliverable is a **report**, not applied edits. The sweep writes12a machine-readable findings log and a grouped HTML summary; it touches no13code.1415## The one test1617**A finding fires only when a code name displaces a specific named domain18term.** Default is NO FINDING: the burden of proof is on the finding, not the19name. A name that is merely vague, generic, or not what you'd have chosen —20with no defined term standing behind it — is not this audit's business. If21you cannot point at the term the name displaces and where it's defined, there22is no finding, no matter how bad the name is.2324This is not a style pass. `data`, `helper`, `process` in a file with no25glossary are ugly, not drift — nothing has been displaced, because nothing26was ever defined. The moment a term *is* defined and the code disagrees, that27disagreement — and only that — is in scope.2829## Extract the term set first — and print it3031Before judging anything, read every `CONTEXT.md` in the repo (root and32nested, e.g. `<some-skill>/docs/CONTEXT.md`) and every file under33`docs/adr/`, and build the term set: each defined noun/verb, its definition,34and its source file. Glossary entries (`**Term** — definition`) and ADR35decision titles/bodies that name a concept both count.3637Print this term set at the top of the report, verbatim — term, one-line gloss,38source. **A wrong or incomplete extraction must be visible in the report, not39silent** — if the repo has no `CONTEXT.md`/`docs/adr/`, the term set is empty40and the report says so plainly; that is a correct, boring result, not an41error to paper over.4243## Buckets & categories4445- **`rename`** / `generic-standin` — a code name is generic where the project46 has a specific defined term for exactly that thing (`data` where the domain47 term is `Order`; `process()` where the term is `reconcile`).48- **`consolidate`** / `synonym-sprawl` — two (or more) code names refer to the49 same concept the glossary treats as one term (`job` and `task` both meaning50 what `CONTEXT.md` calls a `Run`).51- **`misuse`** / `term-misuse` — a defined term is used in code for something52 the glossary says it is not (a variable named `parent` holding what the53 glossary defines as a `blocker` — `CONTEXT.md`'s own `_Avoid_` note may name54 the mix-up directly).5556`extra` carries `should_be` (the displaced/correct term) and `source` (where57it's defined, e.g. `CONTEXT.md` or `docs/adr/0001-....md`). The displaced term58must be named in both `failure` and `extra.should_be` — a finding that can't59name the term it displaces is not a finding, per the one test above.6061## The audit, worked6263`CONTEXT.md` defines **Run** — "one orchestrator invocation, loops64plan→execute until the backlog drains." The code has two names fighting over65that concept:6667```ts68function startJob(cfg: Config) { ... } // job.ts69function runTask(id: string) { ... } // scheduler.ts — same invocation70```7172Neither name is *wrong* on its own — `startJob` and `runTask` both read fine73in isolation, which is exactly why a style pass would pass them. Set beside74`CONTEXT.md`'s `Run`, they're two names for the one term the glossary already75settled: a `consolidate` / `synonym-sprawl` finding, `should_be: "Run"`,76`source: "CONTEXT.md"`.7778Contrast a name the audit leaves alone: `cfg` in the same file. Generic,79sure — but nothing in `CONTEXT.md` or the ADRs defines a term `cfg` displaces.80No finding.8182## Out of scope8384Pure style naming — `snake_case` vs `camelCase`, unclear-but-undefined names,85abbreviation style — is a different axis and stays with ruff `N`. This audit86only fires where a *defined* term exists and the code disagrees with it. Do87not flag a name for being bad; flag it only for being wrong against a88specific, sourced term.8990## Run91921. **Scope.** Audit `$ARGUMENTS` if given; with no argument, scope defaults93 per `~/.agents/skills/all-audits/SKILL.md`'s Scope section. Skip vendored, generated, and dependency trees94 (`node_modules`, `dist`, `.venv`, build output, lockfiles) and any95 `worktrees/` tree.96972. **Extract and print the term set** as above, before judging any code.98993. **Sweep every name in scope against the term set** — identifiers, class100 names, function names, key variable names, not a sample. For each one,101 check: does a defined term describe exactly what this name refers to, and102 does the code's name disagree with it (generic-standin), collide with103 another name for the same concept (synonym-sprawl), or borrow the term for104 something else (term-misuse)? A name with no term behind it is silently105 fine — do not record it, do not almost-flag it.106107 **Then, for each confirmed drifted word, enumerate every site — grep, do108 not eyeball.** A rename executed from this finding must be safe and total,109 so the site list has to be both exhaustive and clean. `grep` the whole110 repo — not just the audit scope; a drifted word's occurrences straddle111 files the diff never touched, and a rename touches all of them — for the112 word in every form it takes: identifiers, string literals, dict keys, CSS113 class names, filenames. Then re-check each hit against the term's meaning114 before you emit it — the same one test as above, applied per site: a hit115 that uses the word in a different, correct sense is not drift (`invalid116 puzzle document` covering broken JSON, when the glossary excludes that from117 `malformed`, is a defensible clear, not a rename target). Emit one finding118 row per real drift site, all sharing the same `should_be` and `source`.119 Miss a real site and the rename half-applies — renaming the dispatch call120 but not the constructor literal it dispatches to breaks the code; sweep in121 a defensible clear and the rename corrupts a correct use. If you cannot122 confirm the list is complete, flag the term `partial coverage` in the123 summary rather than presenting a half-list as the finding.1241254. **Write the findings log and render the summary — the default126 deliverable.** See127 `~/.agents/skills/all-audits/harness/AUDIT-RUN.md` for the shared128 write-and-deliver step (tmpdir resolution, `findings.jsonl` +129 `report.html`, opening, and the final print). This skill's own bucket130 names and metabar:131132## Write the log and render the summary133134- **Log** — one JSONL line per finding, the six required fields plus `extra`:135 `file` and `line` where the drifting name sits, `summary` (one line, what136 drifted), `bucket` (`rename` / `consolidate` / `misuse`), `category`137 (`generic-standin` / `synonym-sprawl` / `term-misuse`), and `failure` naming138 the displaced term and the concrete confusion it causes ("reader sees `data`139 and can't tell this is the `Order` `CONTEXT.md` defines without opening the140 file"). `extra` carries `should_be` and `source`.141- **Summary** — the term set (term, gloss, source) printed in full at the142 top, then the verdict, the `N findings · R rename · C consolidate · M143 misuse` metabar, findings grouped by bucket then category with counts, and144 a `vt-callout` naming the highest-value finds by `file:line`. No145 per-finding cards. Any term whose site list isn't confirmed exhaustive146 carries a `partial coverage` flag here.