check-avoided-words.yml
Diff-scoped check that flags words and phrases a style source advises against, in .qmd and .md prose. This is psw#418.
Rules
Position words.
aboveorbelowused for a place in the document (“the table above”, “as shown below”); refer to the result by its label. Source: Google developer documentation style guide, word list, entries “above” and “below”. “A value above the threshold” is a comparison and passes.Effort words.
just,easy,easily. Source: the same word list.just before,just after,just as,just like,just then,just enough,just in time,just onceandjust nowpass.Time-relative words.
currently,recently,nowadays,at present,at the moment,these days. Source: Google, “Timeless documentation”. The guide listsnowandnewtoo, but this check does not flag them, because “now we compute” and the term “new observation” are correct uses a regex cannot tell apart.recentlyis psw’s own extension.Generic placeholders. A domain, codomain, range or sample space named by a bare capital letter (“domain A”) or by “some” (“some domain”). Name the specific set, such as “the range of X”. Source: psw’s “be as specific as feasible” (psw#427). A regex cannot know whether a specific object exists, so a finding only asks the author to check.
Back-references to a setup. “The setup of ?@exr-x” or “the same setup as”. Name the data, variables or model the part reuses. Source: psw’s “Talk about the ideas, not the notes” (psw#442).
“Score” for a linear predictor. “score” or “scores” on a line that also has
\eta, “linear predictor”, “log-odds”, “logit”, “sigmoid”, or “logistic function”. Write “log-odds” for a logistic regression and “linear predictor” for a GLM in general. The statistical score keeps its name, so “score function”, “score equation”, “score test”, “Brier score”, “z-score”, “F1 score”, “component score”, a link whose text is “score”, and a line holding#def-scorepass. Source: Ezra’s rule (gha#1568).Trailing parenthetical links. A crossref after a word, such as
differentiable at $c$ (@def-differentiable), or a([why](url))link after a claim. Link the term itself, or make the whole claim the link text.(see @thm-x)passes, since no word can carry that link. Source: Ezra’s review of mds, 2026-11-02 (gha#1402). This rule fails the run whateverfailsays.The word “thing”.
thingorthingsas a whole word;something,anything, andnothingpass. Name the object, quantity, step, or idea instead. Source: psw’s “Say which thing” (gha#1454). This rule also fails the run whateverfailsays, and<!-- check-avoided-words: allow -->exempts a deliberate use. A consumer on thev3tag sees its check turn red on any added line containing the word.Normal for the Gaussian distribution. “Normal distribution”, “standard normal”, “multivariate normal”, “bivariate normal”, “normally distributed”, “normal random variable”, or “normal random vector”. Write “Gaussian” instead, since “normal” also means perpendicular and usual. “Normal equations”, normal vectors, and normal subgroups pass. Source: psw’s rule to write “Gaussian” (psw#510, gha#1570). This rule only warns, even with
failon, while it is new.
The other rules fail by default; set fail to false to make them warn.
The check does not flag a code fence or code span, an HTML comment, YAML front matter, or a line carrying, or following, <!-- check-avoided-words: allow -->. It reports at most one finding per rule per line.
Scope
Only lines a pull request adds are reported, so existing uses are not reflagged on every unrelated edit. An added line whose exact text was also deleted in the same diff counts as moved rather than new.
With no base-ref, or when the diff cannot be computed (a shallow clone, an unresolvable ref), the check skips with a warning. It never falls back to a whole-tree scan. Set whole-tree: true to scan every tracked file in full on purpose.
Every run prints how many lines and files it examined.
Inputs
| Input | Type | Default | Description |
|---|---|---|---|
globs |
string | '*.qmd *.md' |
Space-separated git pathspecs of tracked files to check (recursive by default). |
paths-ignore |
string | '' |
Comma- or newline-separated glob patterns (relative paths) to skip. Supports *, ? and recursive **. |
fail |
boolean | true |
Fail the workflow when an avoided word is found. Set false for warnings only; a trailing parenthetical link and the words “thing” and “things” always fail, and the Gaussian rule only warns. |
whole-tree |
boolean | false |
Scan every tracked file in full instead of only a PR’s added lines. |
python-version |
string | '3.x' |
Python version to set up. |
runs-on |
string | empty (CI_RUNNER variable, else ubuntu-latest) |
Runner label for the job. Use a self-hosted label only for a private repository; never for a public one, whose pull requests can run arbitrary code on it (#1167). |
Permissions
Only contents: read (the default), so no permissions: block is needed.
Example
# Copy to .github/workflows/check-avoided-words.yml in your repo.
name: Check avoided words
on:
push:
branches:
- main
pull_request:
workflow_dispatch:
jobs:
check:
uses: Morrison-Lab/gha/.github/workflows/check-avoided-words.yml@v3
# with:
# globs: '*.qmd *.md' # pathspecs to check (recursive)
# paths-ignore: 'chapters/outtakes/**' # skip known-noisy paths
# fail: false # warn on all but the always-failing rules (defaults to true)
# whole-tree: true # scan every line, not just a PR's additions
# runs-on: private-runner # self-hosted runner label (private repositories only)See examples/check-avoided-words.yml for the full caller stub.