Lint
- Versions
- History
archdoc lint runs every L rule over every document and prints findings. With --merge it also runs the merge rules. Exit code 2 if any error, 0 otherwise. Warnings do not affect the exit code unless --strict-warnings is given, in which case a warning alone exits 2.
Severity
Every rule reports an error unless stated. A rule comparing a front matter value against something else does not report where that value did not parse, which L01 reports, and L02 and L10 do not report a title or id that is missing or empty. A finding that no permitted edit to the named document could clear is a warning. This applies to L01, L02, L07, L08, L09, L10, L14, L16, L17, L20 and L21 when the document is frozen, to the L04 and L05 faults that only an edit to a frozen document could clear, and to L03 when every document holding the identifier is frozen. It does not apply to a fault another permitted edit can clear, such as a reference to a document that can be written, nor to L11.
Rules
- L01 Front matter parses and matches the schema for the type: no unknown keys, no missing required keys, no wrong types, no required key left empty, no
as_ofleft empty, and no empty item in a list. Front matter that is not valid YAML, or not a mapping, is reported once, at the first line at which it stops being valid, and no key in it is reported missing. That line is the first from which the block, cut after it or after any later line, fails as the whole block does, so a construct left open can be reported on a line after the one it opens on: a bracketed list left open after a comma is reported on the line that follows it. So is a file with no front matter block, or one never closed. Error in an editable document; warning in a frozen one. - L02
idequals the identifier derived from type and filename. The filename matches<NNNN>-<slug>.md. Error in an editable document; warning in a frozen one. - L03 No identifier appears on more than one document. Error, or a warning when every document holding the identifier is frozen.
- L04 Every identifier in
depends,updates,obsoletesandincludes, and a term'snamed_by, resolves to an existing document of a permitted type. Every member of a group resolves, an identifier to an RFC, ADR or ref and any other member to a spec page, and no group lists a member twice. Each finding is reported at the line of the list. A document in no group is not reported. A ref named independsorincludes, and a reference that is not an identifier any document can hold, such asfoo,rfc-0001orADR-0000, are warnings in a frozen document. A reference to a valid identifier no document holds is always an error. - L05
updatesandobsoletesreference only accepted documents of the same type. No document updates or obsoletes itself. No document appears in both lists of the same document. Error in an editable document; warning in a frozen one, except that a target that is not accepted is an error unless it is frozen too. - L06
includesreferences only accepted documents. - L07
decidedis set if and only if the status is terminal.decidedis not beforecreated. Ifbackfilledis set, the status is terminal andbackfilledis not beforedecided. Neither condition on the status is checked against an empty status, which L01 reports. On a ref,as_ofis not afterverified. Error in an editable document; warning in a frozen one. - L08 Required sections are present, with exact titles, in the listed relative order. Other H2 sections are permitted between or after them.
Rejection rationaleis present if and only if the document is rejected. Where the type has a closing section, it is the document's last H2. Error in an editable document; warning in a frozen one. - L09 An accepted document has no non-empty
Open questionssection. Error in an editable document; warning in a frozen one. - L10 The H1 matches the front matter. Error in an editable document; warning in a frozen one.
- L11 Frozen documents are unchanged. For every document whose status on
branchis terminal, the working tree file is unchanged from the file at the merge base of HEAD andbranch, or from the file atbranch's tip, as git judges it; onbranchitself, the merge base is its tip. Each revision's documents are found under its own root, from its ownarchdoc.json, and matched to the working tree's by their path within root, so moving the root is followed. The whole of each revision is listed, whichever directoryarchdocruns in. A revision'sarchdoc.jsonis the one at the working tree's location, or failing that the one the working tree's moved from: of everyarchdoc.jsonin the revision, the only one absent from the working tree, where the revision holds no document under the root it names or holds one that is still under the working tree's root. Where there is no such file, or several, the working tree's settings stand. Where the file cannot be read they stand too, and the rule reports one warning namingbranch, whichever revision holds it. Where the revision lists nothing under the root its file names, and the file is at the working tree's location, that root is the directory it names in the working tree, as git spells it, so a root differing from git's listing in case, in Unicode normalisation or through a symbolic link is matched. Where the revision still lists nothing under it, or the file is the one moved from, the root is the first directory in the revision's listing, in git's order, that matches it case-folded and in Unicode normalisation form C, whatever the filesystem; with none, it is taken as written.branchis always the working tree's, so a pull request changing it is judged against the branch it names. It names the local branch,refs/heads/<branch>, orrefs/remotes/origin/<branch>where there is no local one, never a tag or one of git's own refs of the same name. A file absent frombranchis new and the rule does not apply. A document terminal onbranch, present at the merge base and absent from the working tree is an error; a rename is a deletion and a new file. Where HEAD andbranchshare no commit, the rule reports an error saying a shallow clone needs its full history (fetch-depth: 0). With no commits, the rule is skipped with a warning. Whenbranchdoes not exist in a repository that has commits, the rule reports an error naming the branch. Outside a git repository, the rule is skipped with a warning. - L12 A spec page includes no document that is effectively obsolete. Warning.
- L13 A ref's
verifieddate is not older thanref_stale_days. A ref carryingas_ofis not reported. Warning. - L14 No required section is empty. Warning for
proposed; error for a document that is terminal in the working tree but not yet onbranch; warning once frozen. Not applied towithdrawn. - L15 Term structure: exactly one paragraph of definition, and nothing else. The definition runs from the H1 to the end of the file, subsections included. A heading, a thematic break, a setext underline, a list, a blockquote, a table row, or a code or HTML block in it is reported, whether or not a blank line precedes it, as is prose above the H1. A setext underline or table row is one indented at most three spaces. A lone carriage return ends a line. A comment beginning a line outside a code block opens an HTML block, and text after the marker closing it is reported as one. No terms is valid.
- L19 A
spec/glossary.mdleft behind by a repository scaffolded before terms became files. A warning: the page is valid Markdown and nothing else is wrong with the repository. - L16 No unresolved
[[...]]wiki link anywhere. The finding names the edit that clears it: runningarchdoc link, writing a heading without the link, or, for a terminal document outside a git repository, replacing it by hand. In a frozen document, heading or not, it says the link is left as written. Error in an editable document; warning in a frozen one. - L17 Every relative Markdown link resolves to an existing file within the repository, named in its exact case, and where it has an anchor, to an existing heading or explicit anchor. A destination with a URI scheme or beginning with
/is not relative. The repository is the git repository holdingroot, orrootoutside one. Error in an editable document; warning in a frozen one. - L18 Every
dependsentry references a document that is accepted, or that shares the referencing document's non-terminal status. Warning. - L20 The question sections have the shape markdown Markdown gives them. Reported at the first line before a section's first question that is not blank or a comment; at a question whose heading produces no anchor, or the same anchor as another heading, and of two questions at the later; at a heading beneath a question; at a blockquote line holding a heading, a comment, or a fence's opening line, the lines within a quoted fence being code; at an open question's final blockquote; at an empty
Resolved questionssection's heading, or, in a document that has anOpen questionssection, one that does not follow it; at a resolved question with no heading beneath it that does not end with a blockquote; at an answer with another blockquote before it, or an empty one; and at eachResolved questionsheading after the first, whose questions and blockquotes are checked as the first section's are and whose section is otherwise not checked. Not applied to theOpen questionssection of an accepted document, which L09 checks, or to a withdrawn document. Error in an editable document; warning in a frozen one. - L21 Every
Changelogsection has the shape markdown Markdown gives it. Reported at the first line belonging to no entry after the section's heading and after each entry; at a heading opening or ending the section that is indented by two or three spaces, or is a heading only once a comment on its line is masked; at an entry with no date, one beginning with a date shape not followed by:and a space or the end of the line, one whose date is not a real date, and one with a date and no text; at an entry dated earlier than the dated entry before it, before a validcreated, or afterdecided, the last two unchecked wheredecidedis beforecreated; at eachChangelogheading after the first; and at a level two heading differing fromChangelogonly in case, spacing or punctuation. Not applied to a withdrawn document. Error in an editable document; warning in a frozen one.
Merge rules
archdoc lint --merge also runs M01 to M04, which compare the working tree with the base: the merge base of HEAD and the configured branch, the branch resolved as L11 resolves it, with the same fallback to origin/<branch>. In a checkout of a pull request merged into the branch, that is the branch as the merge was made; on a branch not rebased since it was cut, it is the commit it was cut from. Every document on the base is read in one batch from its file listing, and the base's archdoc.json in another. Outside a git repository, where the branch does not exist, or where HEAD shares no history with it, --merge exits 1 naming the branch and reports nothing; the last case says a shallow clone needs its full history (fetch-depth: 0). Without --merge no merge rule runs, including in the transition commands. The merge rules report alongside the L rules, with the same output, --json, --strict-warnings and exit codes, and every one reports an error.
A document in the working tree was on the base when the base holds a document at its path, or, for a numbered document, one carrying its identifier at a path absent from the working tree, which is a rename. Any other document arrives.
- M01 An RFC or ADR arrives as a draft. Reported at its
statusline, namingarchdoc proposewith its identifier where it has one. - M02 A numbered document arrives carrying an identifier that a document on the base, still in the working tree, carries. Reported at the arriving document's
idline, naming the other document's path andarchdoc renumberwith the arriving document's path. - M03 An RFC or ADR's status differs from its status on the base by a transition lifecycle Lifecycle does not permit, under the
strictof the base'sarchdoc.json, found as L11 finds it, or of the working tree's where none is found or it cannot be read. An arriving document is judged as moving fromdraft, except an arriving draft, which M01 reports, and one carryingbackfilled, which L07 requires to be terminal. A document terminal on the base, and a status on either side that is not one of the five, are not judged. Reported at thestatusline; where the base'sstrictis on and the move is fromdraft, the message says to merge the proposal first. - M04 An RFC or ADR proposed on the base whose identifier no document in the working tree carries: deleted, or renumbered. Reported at its path on the base, naming
archdoc withdraw. A draft may be deleted, and a terminal document's deletion is L11's.
Rule entries
Each rule in the registry carries, besides its code and check:
| Field | Content |
|---|---|
Title |
A few words naming what the rule checks |
Summary |
What a finding means, as inline Markdown |
Remedy |
How a finding is cleared, as inline Markdown |
Since |
The tag of the first release carrying the rule: v0.1.0-alpha.1 for L01 to L18, v0.5.0 for L19, v0.6.0 for L20, L21 and M01 to M04 |
Changes |
Each later release that changed what the rule reports, with a one-line account, in release order. Changes in v0.5.1 and earlier releases, tagged before the registry recorded them, are not listed |
A test refuses an entry without a title, summary, remedy or since. The table of rules in the triage guide is the registry's summaries and remedies, one row per rule in code order; a test compares the two, and go test ./internal/template -update-triage rewrites the table. archdoc reference publishes every entry.
Output
One finding per line: <path>:<line>: <severity>: <message> where a line is known, <path>: <severity>: <message> otherwise. <path> is relative to root. Findings are sorted by path, then line, then rule. With --json, a bare JSON array of objects with path, line, severity, message and rule; line is omitted where unknown.
Source spec/lint.md · commit aa43057 · exported