cli.sgit.ai / Engineering

Engineering: how this site is built and released

One folder of content, one generator, one gate, one version number. Deployed to https://cli.sgit.ai by GitHub Pages on every push to dev, the same pipeline as sgit.ai and pki.sgit.ai.

The shape

PathWhat it is
admin/content/<path>.mdthe source of the page at <path>.html: flat front matter, then markdown
admin/content/articles/<slug>.mdone article; adding the file publishes it (the contract)
admin/content/reference/sgit-cli-reference.jsonthe output of sgit help all --format json; the command reference is generated from it
REALITY.md, BRIEF-CORRECTIONS.mdat the repository root, published as Reality and Corrections
admin/build/build.pythe generator: pages, markdown twins, nav and footer, llms.txt, llms-full.txt, sitemap, assets/version.js
admin/build/md.pythe markdown renderer, from pki.sgit.ai and newsroom.sgit.ai; escapes everything, so content cannot carry HTML
admin/build/validate.jsthe gate
admin/build/import_sgit_ai.pymoves pages from sgit.ai, from their markdown twins (what moved)
admin/build/import_cli_research.pypublishes documents from the CLI repository as articles
admin/build/version.txtthe site version, the one place it is written
.github/workflows/deploy-pages.ymlvalidate, tag, deploy

Every generated file is listed in admin/build/generated.json, and the build deletes a listed file it no longer produces, so removing a content file removes its page and its twin.

Releasing

  1. Bump admin/build/version.txt (vX.Y.Z, once per release) and add a row to admin/content/admin/versions.md with one sentence on what changed and why.
  2. python3 admin/build/build.py
  3. node admin/build/validate.js
  4. git commit -am "site vX.Y.Z: ..." && git push origin dev. The site vX.Y.Z: prefix is load-bearing: the tag job finds the release commit by it and refuses a release whose newest prefix disagrees with version.txt.
  5. Check that https://cli.sgit.ai/assets/version.js serves the new version. A clean push is not a release.

The gate

node admin/build/validate.js fails the build on any of these, in CI on every push and pull request, before anything is tagged or deployed:

CheckWhy
The build is current (build.py --check)a page edited by hand, or content committed without building, ships something the source does not say
The version agrees: version.txt, assets/version.js, llms.txt, one row in the release historythe badge on every page reads version.js; a release without its row has no record
Every internal link and asset resolvesan orphaned or misspelled link is a page nobody can reach
Every page has a canonical link on the CNAME host, and a markdown twin, and is in llms.txtpages agents cannot read, or that claim to live elsewhere
No page is an orphan: every page is linked from another pagea page nothing links to is unpublished in practice
The leak tripwire: vault-key shapes, private-key markers, cloud and provider key prefixes, across every filethis site discusses keys constantly; it must never contain one
Advisory, not failing: em-dashes in prose on this site's own pagesthe estate's writing rule; pages moved or published verbatim keep their authors' punctuation

Against the estate's guidance

Every sgit repository lists what each repository carries. Where this one stands at v0.1.0:

The guidance asks forHere
The brief, published in fullyes, with the initial prompt
A reality file and a corrections fileyes, yes
One version, up on every push, shown on every pageyes: version.txt, the badge, the release history
A gate that fails the buildyes, above
Machine-readable twins and llms.txtyes, generated from the same source
Licences and a participant disclosureyes: Apache-2.0 for code, CC BY 4.0 for content, the disclosure
Nav and footer injected at buildyes, from one definition in build.py
A credentials tier that is never committed.local/ is gitignored; nothing in this repository needs a secret to build
The review folder (review/)not yet, recorded in the reality file
Roles and a board, as filesnot yet, recorded in the reality file
A release script that verifies the live sitenot yet: step 5 above is by hand

This page as markdown · its source, admin/content/admin/index.md