Show a "Last verified on" date
Doc Detective can record when a page or a procedure was last verified. You name the test or spec that covers it. After a run, if that test passed, Doc Detective writes the date into your source file. A failed, skipped, or warning result writes nothing, so a stale date signals that the page needs attention.
You can record a date in two places:
- Front matter dates the whole page.
- An inline
metastatement dates one procedure, so an untested procedure on the same page doesn’t borrow a date it didn’t earn.
Both use the shared verification fields from manni, so manni meta validate checks what Doc Detective writes. To show a visible badge as well, see Step 3.
By default, Doc Detective writes only where you’ve named a check. To have it name the checks for you on the first passing run, or to turn writing off, see Choose what Doc Detective writes.
Before you begin
- A test or spec with a stable
id. You name a testtestIdor a specspecId. - The page you want to date, in a supported format: Markdown or MDX, AsciiDoc, HTML, or DITA (
.ditaor.ditamap).
How it works
- You name the check, and Doc Detective records the result. You add a
verified-byentry withtool: doc-detectiveand acheckset to the test or specid. - Doc Detective writes only on PASS. The date alone is the trust signal. A non-pass result leaves the existing date to age.
- Other tools’ entries stay untouched. A link checker or code-sample runner can list its own entry beside Doc Detective’s, and Doc Detective never changes it.
- Re-runs are idempotent and keep your formatting. Running again writes a byte-identical file. Doc Detective rewrites front matter and statements in the style and comment form you authored.
- Doc Detective warns and skips an unknown
check. A typo or a deleted test logs a warning and doesn’t fail the run. - Coverage spans the whole input set. Doc Detective scans every file it detected for the run. A prose-only page can name a test defined in another file and still get dated.
Step 1: Name the check
Choose where the date belongs.
Date the whole page in front matter
Add a verified-by entry to the page’s YAML front matter:
Date one procedure with a meta statement
Add a meta statement on the line above the procedure. The statement is the keyword meta followed by one JSON object, inside a comment:
The statement covers the paragraph or code block that follows it. Use the comment form that matches your file format:
In MDX, use the {/* */} form so the statement is a valid JSX comment. For AsciiDoc, the // ( ) form ends at the first ), so a check there can’t contain ). For DITA, a statement covers an element instead of a paragraph. As an element’s first child, it covers that element. Anywhere else, it covers the next element:
Doc Detective ignores a statement inside a code block or inline code. A page can show the syntax without Doc Detective filling it in.
In AsciiDoc, a statement above any delimited block covers the whole block. Doc Detective ignores a statement inside a listing (----), literal (....), passthrough (++++), or comment (////) block. A statement inside an example (====), sidebar (****), or quote (____) block still counts, because those blocks hold prose.
Step 2: Run your tests
Run Doc Detective as usual:
When the named test or spec passes, Doc Detective fills in its entry. It writes version, the Doc Detective version that ran, and passed, the UTC day of the run. It also sets last-verified.
In front matter:
In a statement, the change is a one-line diff in the same comment form:
last-verifiedis the oldestpassedacross every entry in the list. Doc Detective sets it only once every entry has passed, so one lagging check holds the date back.- The
sha256-pin records exactly which lines passed. If someone edits those lines later,manni meta validatewarns that the date may no longer hold. The next passing run writes a fresh pin. The pin never covers statement text, so writes to this statement or any other one don’t count as edits.
Step 3 (optional): Show a badge
To show a visible “Last verified” badge next to a procedure, keep an inline test beside it and set badge: true on the test statement. You don’t need a testId:
On a passing run, Doc Detective inserts or updates a shields.io badge on the line directly above the statement:
Doc Detective writes only the badge URL. Shields.io renders the image, so the badge needs no theme work. On re-runs, Doc Detective updates the badge in place instead of adding a duplicate. A failed, skipped, or warning result leaves the badge to age.
Set badge inside the test statement in your format’s comment style:
badge: true works only on a test detected from an inline test statement, because the badge needs a line above the statement. A test authored in a JSON or YAML spec file has no such line, so Doc Detective logs a warning and skips the badge. To date that test on a page, name its testId in a verified-by entry instead.
You can combine a badge with a meta statement directly above the same test. Doc Detective places the badge first, so the statement’s pin covers the badge as written.
Choose what Doc Detective writes
The verification.write setting controls what Doc Detective writes back after a run:
With true, a passing run adds:
- A page entry. A Markdown or MDX page whose tests pass gets a
verified-byentry in its front matter. Itscheckis the page’s spec id, which is the page’s path from where you run Doc Detective. A page without front matter gets a front-matter block. - A procedure entry. A passing inline test gets a
metastatement on the line above it, and above its badge if it has one. - A fixed
testId. An inline test without atestIdfirst gets the id Doc Detective generated for it, written into itsteststatement. A generated id changes whenever the test changes, so this keeps the entry pointing at the right test. Doc Detective edits only ateststatement whose options are JSON, or that has none. For any other statement, it logs a warning so you can add atestIdyourself.
Doc Detective adds an entry only once. On later runs it fills the entry in place, like one you wrote yourself.
Set it in your config file:
Or override it for one run with the --verification flag:
Because a page entry names the page’s path, run Doc Detective from the same folder each time, usually your repository root. A page that moves gets a new entry on its next passing run, and the old entry reports an unknown check until you remove it.
Surface the change in CI
Because Doc Detective writes the date into your source file, the change shows up in CI as a file change. The GitHub Action’s create_pr_on_change input turns those edits into a pull request for review with no extra setup. See Open a pull request when files change.
Troubleshooting
The date didn’t update after a run
Cause: Doc Detective writes only when the named test or spec passes. A failed, skipped, or warning result leaves the existing date in place so it ages.
Solution: Check the run results for the unit named by the check, then fix the failing or skipped test. See Troubleshoot a failing or flaky test.
last-verified isn’t set
Cause: Another entry in the same verified-by list hasn’t passed yet. The date waits until every listed check has passed at least once.
Solution: Run the other tool’s check, or remove its entry if it no longer applies.
A warning says an entry references an unknown id
Cause: The check doesn’t match any testId or specId in the run. Usually it’s a typo, or a test you renamed or removed.
Solution: Update the check to match a test or spec that runs against this set of files. An unknown check only warns, and it doesn’t fail the run.
Validation warns that a statement’s block changed
Cause: Someone edited the lines a statement covers after Doc Detective pinned them, so the recorded date may no longer hold.
Solution: Run the tests again. A passing run re-pins the statement with its new content.
What’s next
- Define inline tests close to the content they verify.
- Run in CI with the GitHub Action and open a pull request when a run changes files.