Skip to content

What The Helper Checks

m4bwav edited this page Oct 4, 2026 · 1 revision

Four subcommands of wikiwright.py decide whether a wiki is ready: check before the push, outputs and snippets against the verification run, and live after the push. This page sets out what each one looks at, read from the 0.9.0 source and shown by the runs on Commands. Each exits 0 when clean, 1 on findings and 2 on a usage or environment error.

check: the working copy

check DIR reads every .md file in the folder and reports errors (which fail it) and warnings (which do not).

Errors:

  • Home.md missing.
  • _Sidebar.md or _Footer.md missing, unless --partial says the folder is a draft of a few pages.
  • A carriage return anywhere in a page (wiki pages are LF only), or a byte order mark.
  • A code fence that is never closed.
  • A backslash placeholder, <BS>, left on any line, code blocks included (see Backslashes).
  • AI attribution on any line: a Co-Authored-By trailer, or "generated with" or "written by" followed by Claude, ChatGPT, Copilot or "an AI".
  • A first heading with the same words as the file name, which GitHub already prints as the page title, and the same heading twice in a row.
  • A wikilink ([[Page]]) outside code; on Gitea, Forgejo and GitLab this is a warning instead.
  • A link to a page that does not exist, a link ending in .md, and an anchor (Page#heading or #heading) with no matching heading. Anchors are slugged the way the host does it.
  • A footer that does not name the --version given, or names no date in YYYY-MM-DD form.

Warnings:

  • A heading in Title Case. Words the page's own prose capitalizes mid-sentence count as names, so ".NET Framework, .NET 8 and Linux" passes.
  • A page the sidebar does not link.
  • A link whose case differs from the file name, and a site-absolute link (/owner/repo/...), which breaks outside github.com.
  • Home.md not mentioning the --version given.

Code blocks and inline code are blanked before links, wikilinks and headings are read, so an example of a broken link inside a fence is not reported.

--host switches the rules for another host. GitLab wants _sidebar.md in lower case and shows no footer, and Azure DevOps orders pages with a .order file. Gitea and Forgejo cannot open a page with a space in its file name, or list pages kept in a folder.

outputs: every output came from the run

outputs DIR VERIFY... finds every place a page presents output and checks that it appears in one of the saved verification outputs. A page shows output in one of these ways:

  • a block fenced as text, txt, plaintext, console or output;
  • an untagged or data block (json, yaml, xml and the like) after a lead-in that ends with a colon, where one of the six words before the colon names output: "prints", "returns", "is", "gives", "exits", "stdout" and about thirty more;
  • a block that directly follows its input block with only blank lines between: two untagged blocks, two blocks of the same data language, or a code block and an untagged block;
  • a //=> or # => value in code;
  • a value in a code comment: quoted, JSON-like, a number or a literal (// "Marguerita"), or any trailing comment after a print call;
  • a run of whole-line comments that ends a code block after a blank line.

In a transcript (a block with $ , PS> or > prompts) only the text after each command is compared, so the commands themselves need not be in the output. A block is compared as a whole, after line endings and trailing spaces are normalised; a short value from a comment must match a whole line.

The fixture's http://127.0.0.1:<port> in the saved output is read as https://example.com, so a page can show a real-looking address. --address '' turns that off, for pages that show the real host names the run used.

Pages that hold code blocks and no output that outputs recognised fail with "no output recognised", since nothing checked is not a pass. Tag output fences text.

Markers on the line before a block steer it:

Marker Effect
<!-- outputs: skip (reason) --> The block is not checked and is counted as skipped. For output no script can print, such as a hand-run install.
<!-- outputs: check --> The block is checked as output whatever its fence says.
<!-- outputs: node>=22 --> The block is checked only against outputs whose Node vN line is in the range (>=, <=, =, <, >).

snippets: every code block is the code that ran

snippets DIR PROGRAM... looks for each program code block on the pages in the verification program. It reads blocks fenced as C#, F#, JavaScript, TypeScript, Python, PowerShell and shell (csharp, fsharp, js, ts, python, powershell, sh and their aliases). Each line is stripped, and blank lines, whole-line comments and comments that show a value are left out on both sides, so indentation and output comments do not matter. The block must appear in the program as one run of lines.

The program can hold a page's code as written, inside a JavaScript template literal, or inside a one-line string literal with \n escapes; snippets undoes those escapes before comparing.

A shell block that only runs commands (pip install widget, dotnet add package X) is counted as a command and not checked. A block with a loop, a branch or an assignment is a script and is checked. <!-- snippets: skip (reason) --> on the line before a block skips it. Blocks in other languages are listed in a note; code blocks with none checked fail, as with outputs.

When a block is missing, the error names the first line that is in no program, or says that every line is somewhere but not as one run.

live: the published pages

live OWNER/REPO DIR fetches every page of the working copy from https://github.com/OWNER/REPO/wiki/<Page> and expects 200, or a 301 from Home to /wiki. It fetches the wiki root and looks for the text of the sidebar and footer in it. Then it checks every Page#anchor link in the working copy against the id="user-content-..." ids on the rendered target page, using the pages it already fetched. --no-anchors skips that last part.

On Gitea, Forgejo and GitLab it also asks the host's page API for the page list. GitLab and Azure DevOps render anchor ids in a form nobody has measured, so their anchors are reported as not checked.

Backslashes

Some agent file tools decode \u escapes, and shell heredocs drop backslashes. The skill therefore writes each backslash that would be mangled as the placeholder <BS> and runs wikiwright.py unbs on the pages afterwards. check fails while any placeholder is left. It scans code blocks too, so a page cannot show the placeholder as typed, even in a fence; this page spells it with HTML entities for that reason.

Clone this wiki locally