Skip to content

D6 · Docs pipeline in CI (minimal version)

Done 2026-10-27 on autopilot/D6 · minimal version, on Thomas's request (tight budget) · the build check now covers the hooks/progress.py output · Virgil licence unconfirmed: excalidraw/virgil declares OFL-1.1, its font file says freeware for personal use; the font stays uncommitted · mike, Zensical, shared_images.py, CI PNG rendering and the F4 and F6 figures deferred · review-code approved · doc-review approve 14/14

D6 figure: mkdocs build --strict runs hooks/progress.py, which fills the progress strip on the landing page and the roadmap and the progress table on the Progress tab. check_progress_hook() then looks at the built HTML for a placeholder comment left unrendered and for the rendered markers sp-waves and the Kind column header. With the hook on, the gate has 0 failures; with the hook commented out of mkdocs.yml, it has 6 D6 figure: mkdocs build --strict runs hooks/progress.py, which fills the progress strip on the landing page and the roadmap and the progress table on the Progress tab. check_progress_hook() then looks at the built HTML for a placeholder comment left unrendered and for the rendered markers sp-waves and the Kind column header. With the hook on, the gate has 0 failures; with the hook commented out of mkdocs.yml, it has 6

What changed

This is the minimal version of D6. It does three of the prompt's items. The rest is listed under Deferred.

  • tools/docs/check.py: the build check now checks the built site for the output of hooks/progress.py, in a new function check_progress_hook():
    • it fails when any built HTML page still holds a spectio:progress-strip or spectio:progress-table placeholder comment;
    • it fails when a page whose source carries a placeholder was not built, or has no rendered strip (class="sp-waves") or table (a Kind column header);
    • the pages with placeholders are found from the sources, not listed by hand: today index.md and roadmap/index.md (strip) and progress/index.md (table).
  • tools/docs/test_check.py, new: 7 unit tests, written before the code they test. Six cover the check, on a temporary docs folder and site. The seventh covers the escaping of %, CR and LF in the ::error annotations, which fail() now does, so a multi-line message stays one annotation.
  • .github/workflows/docs.yml: the docs-gate job runs the unit tests before the docs gate.
  • mkdocs.yml: exclude_docs: fonts/*.ttf, so a local Virgil font is never copied into the site.
  • docs/fonts/OFL.txt, new: the copyright line of excalidraw/virgil's LICENSE.md and the SIL Open Font License 1.1 text. The font itself is still not committed (inbox #1).
  • tools/diagrams/FONT-LICENSE.md: rewritten with the dated sources. The licence is not confirmed, because the sources conflict:
    • the repository's LICENSE.md declares OFL-1.1, by Ellinor Rapp;
    • the repository's own Virgil.woff2 names another foundry, says "All rights reserved" and "Freeware for personal use";
    • the depictio copy used locally so far is a third build (Virgil GS, Jason Smith, 2002, "All rights reserved"). It must not be committed.
  • tools/diagrams/README.md: the font line points to the unconfirmed status.
  • Figure, new: tools/diagrams/d6_progress_hook_check.py and its four outputs, listed in docs/assets/media.yaml.
  • Spec: documentation-system.md:
    • §3.3 item 1 names the new hook-output check and says where to write a full placeholder;
    • §1: the size of docs/assets is now about 11 MB, not 3.3 MB.

The docs-gate job already ran the full check.py, so the new check runs there on every PR with no other workflow change. The pr-body job and the freshness check of the figure SVGs were already in place.

Why

Prompt: next-phase.md · D6. Thomas asked for a minimal D6 for this tick. Two reasons for these three items:

  • the repository is now public, so the font licence matters;
  • a broken hooks/progress.py would leave the landing page and the Progress tab without their status, and mkdocs build --strict would not notice: an HTML comment is valid output.

No decision-log entry: the step decided no behaviour.

How to test it

The step test, from the repository root:

python3 -m unittest tools/docs/test_check.py && python3 tools/docs/check.py --only build

To see the check fail on the real site, disable the hook in mkdocs.yml (comment out - hooks/progress.py) and run python3 tools/docs/check.py --only build. Restore the file afterwards.

Evidence

Unit tests, first run before check_progress_hook() existed (red), then after (green). The escaping test was added in the review round, red then green the same way; the suite now has 7 tests:

$ python3 -m unittest tools/docs/test_check.py
Ran 6 tests in 0.015s
FAILED (errors=6)
$ python3 -m unittest tools/docs/test_check.py
Ran 6 tests in 0.023s
OK
$ python3 -m unittest tools/docs/test_check.py     # review round: escaping test added, fail() not yet changed
Ran 7 tests in 0.010s
FAILED (failures=1)
$ python3 -m unittest tools/docs/test_check.py
Ran 7 tests in 0.013s
OK

On the real site, with the hook enabled, then with hooks/progress.py commented out of mkdocs.yml (restored afterwards):

$ python3 tools/docs/check.py --only build
build: progress hook output checked on 3 pages
docs gate: 0 failure(s)
$ python3 tools/docs/check.py --only build     # hook disabled
::error::[build] unrendered progress placeholder in index.html (hooks/progress.py did not run)
::error::[build] unrendered progress placeholder in progress/index.html (hooks/progress.py did not run)
::error::[build] unrendered progress placeholder in roadmap/index.html (hooks/progress.py did not run)
::error::[build] index.html has no rendered progress strip (hooks/progress.py), source index.md
::error::[build] progress/index.html has no rendered progress table (hooks/progress.py), source progress/index.md
::error::[build] roadmap/index.html has no rendered progress strip (hooks/progress.py), source roadmap/index.md
build: progress hook output checked on 3 pages
docs gate: 6 failure(s)

The full docs gate, after the review fixes, with this page, its figure and the review record in the tree:

$ python3 tools/docs/check.py
build: progress hook output checked on 3 pages
mermaid: 5 blocks checked
diagrams: 16 scripts re-run, 32 SVGs compared
media: 85 outputs in the manifest
progress: 29 pages checked
docs gate: 0 failure(s)

review-code (the review record):

CODE  step=D6  review=approve b/M/m=0/0/4  security=approve b/M/m=0/0/2  rounds=1  simplify=nochange -0/+0  tests=pass
  • code-reviewer and security-reviewer: approve in round 1, on d22b4d1.
  • Six minor findings: five applied in 0930f5c, and CR-4 kept.

Virgil licence sources, read 2026-10-27; quotes in FONT-LICENSE.md:

Source What it says
excalidraw/virgil, LICENSE.md "Copyright (c) 2021 - Present, Ellinor Rapp, with Reserved Font Name Virgil." and the SIL Open Font License 1.1, in full
excalidraw/virgil, repository page licence badge "OFL-1.1"; the font ships as Virgil.woff2
the name table of that Virgil.woff2 Virgil 3 YOFF, "Copyright (c) 2011 by Your Own Font Foundry. All rights reserved.", "Freeware for personal use!"
the depictio copy's name table (2026-10-26) Virgil GS, "Copyright (c) Jason Smith fonted by Font Garden, 2002. All rights reserved."

Figures and media

  • d6-progress-hook-check sketch, light and dark, at the top of this page: python3 tools/diagrams/d6_progress_hook_check.py. The PNGs were rendered locally with the excalidraw/virgil font file, converted to TTF and kept out of the repository. Earlier figures used the depictio copy, so a few letters may be drawn differently.
  • No cast or screenshot: the change is one check in a contributor tool, and Evidence shows it passing and failing on the real site. The prompt's figures (F4, F6) are deferred.

Findings and open questions

Deferred to a follow-up step

These parts of the D6 prompt are not done:

  1. mike versions on the Cloudflare previews of D5: dev from main, X.Y on release, the latest and stable aliases, versions side by side, and the /versions page.
  2. The Zensical evaluation against this site: hooks, md_in_html, mike-style versions (§1).
  3. hooks/shared_images.py, the size hook from depictio. §1 makes it due before the first mike version, or when docs/assets passes 50 MB. Neither has happened: no mike version exists, and docs/assets holds about 11 MB of tracked files.
  4. The same PNGs in CI: the figure scripts still render PNGs locally only, because the font is not committed (§3.3 item 3). CI checks SVGs only.
  5. The F4 and F6 figures: the magic-link and share-link sketch, and the three telemetry systems.
  6. Opening the PR with the autopilot-loop figure: done by the coordinator (PR into autopilot/integration).

For Thomas

  1. The Virgil licence is not settled (inbox #1). excalidraw/virgil declares OFL-1.1, but its own font file says "Freeware for personal use" and names another foundry. Committing the font, which would let CI render the PNGs (deferred item 4), needs that conflict settled first, for example by asking the excalidraw/virgil maintainers. Until then, the font stays local.
  2. Outside this step: §3.3 item 3 says sketch.py fails without the font unless --allow-fallback-font is passed. sketch.py has no such flag, and it falls back silently. Left for a follow-up (review record).