wardley-maps.sgit.ai / Admin

Admin & engineering

This site is hand-written static HTML with programmatically injected chrome, deployed to GitHub Pages from dev. No framework, no build step you have to run to read a page, and no server. The same pipeline as pki.sgit.ai and graphs.sgit.ai, with one addition no sibling has.

The pipeline

Every push to dev runs deploy-pages.yml: validate → tag → deploy, in that order, with each gating the next. A push to main is deploy-only. Pull requests run validation alone, so branch work is gated before it reaches the release branch.

StageWhat it doesOn failure
validatenode admin/build/validate.js — seven checks, belowNo tag, no publish
tag-releaseReads version.txt, finds the commit whose subject carries the same version, verifies the bump is the next minor, tags that commit. Backfills any historical release from the commit subjects, idempotently.No tag, no publish
deployRsyncs the tree minus .git, .github and .sg_vault, and publishes to Pages.

The release commit is HEAD on a direct push and HEAD's parent when a pull request lands as a merge commit, so every check anchors to the newest commit whose subject carries a version rather than to HEAD itself.

The release gate — seven checks

Four are the house gate, inherited unchanged in intent. Three exist because this site makes promises the others do not.

  1. Version agreement. version.txt against every page's version badge, the versions table, llms.txt, llms-full.txt and index.md — and that the versions table lists each release exactly once, because a blanket version-bump sed that touches the history table produces duplicates, which has shipped on a sibling site.
  2. Internal links. Every relative href and src in every page resolves to a file in the tree.
  3. Canonical host. Every rel="canonical" and og:url points at the host in CNAME, and every page declares one.
  4. Key-leak tripwire. Nothing in the tree may look like an sgit vault key. This site links to vaults; it must never contain a key.
  5. Licence stamp. Every raw markdown document under /briefs/ carries the CC BY 4.0 stamp. The site sits inside a CC BY-SA ecosystem; an unstamped document is the first step towards a mixed, unlabelled licence.
  6. Maps ship their source, and render. Every maps/*.mmd has an .svg beside it, no .svg is orphaned, and no rendered SVG contains Mermaid's error-text. A broken wardley-beta source renders a byte-identical "Syntax error in text" SVG with exit status zero — in a batch render that is indistinguishable from success, which is how thirteen broken maps sat in a repository for three months.
  7. Resource pages carry a verification date. Every page under /resources/ has a data-verified stamp. It is the site's whole differentiator in that category and the one rule with no exceptions.

The link-verification job

No sibling site has one. This site needs one, because it spends a page saying that awesome-wardley-maps, Wikipedia and Simon Wardley's own resources page all list five dead things as live. A site that makes that criticism and does not check its own links has no standing to make it.

verify-links.yml runs every Monday and on demand: fetches every external URL the site publishes, writes data/link-check.json with the run date, commits it if a verdict actually moved — not merely the timestamp — and dispatches a deploy, because a push made with GITHUB_TOKEN deliberately does not trigger another workflow. Hosts that block automated retrieval are recorded as skipped, never as ok. A dead link does not fail the build: the point is that links rot, and a red pipeline would tempt somebody to delete the evidence. The report →

Why the chrome is generated

Every page is hand-written and a human can open any file and edit it. What is not hand-maintained is the nav row, the version badge and the footer columns: admin/build/chrome.py is the single definition of all three and rewrites them in place across the tree. That is what stops a hundred-page site drifting, and it is why the version badge can be enforced by CI at all.

What is generated, and from what

GeneratorWritesFrom
gen_resources.py45 pages under /resources/data/industry-resources.json + screenshots/captured.json. Wipes the directory first, so a renamed resource cannot leave an orphan page behind that still validates and still says "verified".
gen_dinis.py/dinis/data/dinis-published.json — 26 items, each with a date-precision flag, because seven are month-and-weekday only and synthesising a date would be inventing evidence.
gen_concepts.py/glossary/ and /agents/concepts.jsonParsed from briefs/01__concepts-index.md rather than retyped, so the page and the endpoint cannot drift from the research and a correction lands in one place.
gen_documents.py/documents/The raw markdown in /briefs/, which stays the source of truth and is served as-is.

The scripts

ScriptWhat it does
bin/bump.pyBumps version.txt and adds a row to the versions table, in one step, so the two cannot disagree.
bin/render-maps.shRenders every .mmd to .svg via Mermaid CLI 11.14.0 against an existing Chromium, and greps for the silent syntax error.
bin/verify-links.jsThe link check. HEAD then GET, redirects followed, blocked hosts recorded as skipped.
screenshots/capture.jsScreenshots the 30 targets, recording status, title, final URL and timestamp for every attempt including failures. Has a PROXY_FETCH=1 mode for sandboxes where the process has egress and the browser does not.
bin/optimise-shots.pyResizes the captures to WebP and records the transformation per image — a screenshot offered as evidence should say that the published file is a derivative. Also flags captures that photographed an interstitial rather than a page.

The repository

SGit-AI/SGit-AI__Website__Wardley-Mapsdev is the release branch and what Pages serves. Content CC BY 4.0; code under the repository licence. The licence position in full →