Skip to content

docs: add reference documentation, and actually publish the site - #275

Merged
refeed merged 5 commits into
feat/gate-capable-enginefrom
docs/reference-documentation
Aug 13, 2026
Merged

docs: add reference documentation, and actually publish the site#275
refeed merged 5 commits into
feat/gate-capable-enginefrom
docs/reference-documentation

Conversation

@refeed

@refeed refeed commented Aug 13, 2026

Copy link
Copy Markdown
Member

Adds the reference material the site never had, and fixes the reason none of it would have been visible.

The docs explained how to write a policy but never said what you could put in one: no list of providers, no list of operation types and their arguments, no list of condition types, no CLI or exit-code reference. This adds 14 pages, and publishes the site.

Publishing was broken

deploy_docs.yml built the site and then published ./build. Docusaurus builds to ./documentation/build. So every push to main published an empty directory — which is why gh-pages contains nothing but .nojekyll and https://stackguardian.github.io/tirith/ has always returned 404.

  • publish_dir./documentation/build
  • url / baseUrl were still the create-docusaurus placeholders (your-docusaurus-site.example.com, /). A project site is served under /<projectName>/, so baseUrl must be /tirith/ or every asset and link on the deployed site resolves to the wrong path.
  • npm ci rather than yarn install, in both workflows: package-lock.json is the committed lockfile and there is no yarn.lock, so yarn ignored it and re-resolved the dependency tree on every deploy.
  • New build_docs.yml builds the site on pull requests. The site sets onBrokenLinks: 'throw', so one bad cross-link fails the build — previously discoverable only after merging to main.

The homepage

It was the untouched scaffold: the hero rendered the single word "Tirith", and HomepageFeatures rendered nothing at all because its FeatureList was entirely commented out. It now carries the landing-page copy, derived from README.md so there is one source of truth. All prose lives in one content object apart from the JSX, so it can be edited without reading markup. The dead component is removed.

This supersedes #274, which put the same page in docs/index.html as a standalone file — one site is better than two, and this way the reference pages are reachable from it. I will close that PR when this merges.

The new pages

Directory Pages
tirith-usage/ cli-reference, exit-codes, ci-integration, platform-check
tirith-providers/ overview + one page per provider, each with every operation type, its arguments, and what it returns
tirith-reference/ evaluators (all 13 condition types), eval-expressions
tirith-policies/ tirith-policy-reference (field-by-field schema), tirith-policy-cookbook (6 recipes)

Every claim comes from the code, and the examples were executed rather than written from memory — 6 cookbook recipes, 11 provider policies and roughly 88 evaluator probes were run against the real CLI, and the quoted output and exit codes are what came back. The observed exit codes:

Case Exit
Passing policy, --fail-on-error 0
Failing policy, --fail-on-error 3
Unresolved variable 1
Every check skipped 1
Failing policy, no flag 0

Existing pages fixed

tirith-policy-variables.md was actively harmful. It used {{ max_epoch }}, but the engine's pattern is {{ var.NAME }}. A reader following that page got a policy that compared against the literal placeholder string — a check that looks like it passes while measuring nothing. Its policy JSON was also invalid (missing comma) and lacked the required eval_expression. The corrected version is one that was actually run, and the quoted output is its real output.

Cross-links now point at the .md file rather than the URL. Relative URLs resolve against the page's own directory, so ../tirith-reference/evaluators from a page at /docs/tirith-providers/x/ resolved to /docs/tirith-providers/tirith-reference/evaluators. Linking by file lets Docusaurus resolve through the file graph, which also survives a slug change. 30 links rewritten.

sidebars.js is a manual sidebar, so the new pages are registered under Using Tirith, Providers and Reference. Without an entry a page builds but is unreachable.

meta.enforcement

Documented as what it is: inert in the engine, and read by the layer above it. The CLI copies it through untouched and it never affects the exit code; the GitHub Action downgrades a failing policy to a warning for soft_mandatory and friends, and blocks on anything it does not recognise. Both statements are true of different layers, and a reader needs to know which one applies to them.

Verification

npm ci && npm run build passes locally — [SUCCESS] Generated static files in "build" — and the built site was served and spot-checked: homepage and pages from all four new directories return 200.

Bugs found and deliberately not fixed here

These are code changes, and do not belong in a docs PR:

  1. ExitStatus.ERROR_TIMEOUT = 2 is unreachable. A platform-run timeout raises SGErrorCheckErrorExitStatus.ERROR, so it exits 1. The enum, the README and docs/platform-check.md all document 2 for a timeout and nothing can produce it.
  2. The kubernetes provider crashes on a single-document YAML — core unwraps a one-document YAML to a dict, but the handler iterates it as a list, giving TypeError: string indices must be integers. Documented as a caveat.
  3. Infracost sums only the first projectreturn total_sum sits inside the for project in ... loop in both cost functions, so later projects are never counted.
  4. sg_workflow silently returns "" for an unknown workflow_attribute, so a typo evaluates an empty string instead of erroring.
  5. tests/providers/sg_workflow/policy.json fails against its own input.json, and tests/providers/policy.json / wfPolicy.json use argument names and unprefixed provider names that no longer match PROVIDERS_DICT.
  6. Docstrings in equals.py, not_equals.py, greater_than*.py and less_than*.py claim values are "automatically cast to the same type" — no casting occurs.

refeed added 2 commits August 13, 2026 17:47
The deploy workflow built the Docusaurus site and then published `./build`,
which does not exist -- the site is built at `./documentation/build`. So every
push to main published an empty directory, which is why the gh-pages branch
holds nothing but .nojekyll and https://stackguardian.github.io/tirith/ has
always returned 404.

Fixing publish_dir is the whole fix. Alongside it:

- url and baseUrl were still the create-docusaurus placeholders. A project site
  is served under /<projectName>/, so baseUrl has to be /tirith/ or every asset
  and link on the deployed site resolves to the wrong path.

- The homepage was the untouched scaffold: the hero rendered the single word
  "Tirith", and HomepageFeatures rendered nothing at all because its FeatureList
  was entirely commented out. It now carries the landing-page copy, derived from
  README.md so there is one source of truth. All prose sits in one `content`
  object apart from the markup, so it can be edited without reading JSX. The
  dead HomepageFeatures component is removed.

- npm ci rather than yarn install, in both workflows: package-lock.json is the
  committed lockfile and there is no yarn.lock, so yarn ignored it and resolved
  the dependency tree fresh on every deploy.

- A new build_docs.yml builds the site on pull requests. The site sets
  onBrokenLinks: 'throw', so one bad cross-link fails the build -- previously
  discoverable only after merging to main.
The site documented how to write a policy but never said what you could
actually put in one: no list of providers, no list of operation types and their
arguments, no list of condition types, and no CLI or exit-code reference. This
adds 14 pages covering all of it.

Every claim is taken from the code rather than from the existing prose, and the
examples were executed rather than written from memory -- 6 cookbook recipes,
11 provider policies and ~88 evaluator probes were run against the real CLI,
and the quoted output and exit codes are what came back.

New:

  tirith-usage/       cli-reference, exit-codes, ci-integration, platform-check
  tirith-providers/   overview + one page per provider, with every operation
                      type, its arguments and what it returns
  tirith-reference/   evaluators (all 13 condition types) and eval-expressions
  tirith-policies/    tirith-policy-reference (field-by-field schema) and
                      tirith-policy-cookbook (6 executed recipes)

Fixed in the existing pages:

- tirith-policy-variables.md used `{{ max_epoch }}`, but the engine's pattern is
  `{{ var.NAME }}`. Following that page produced a policy that compared against
  the literal placeholder string instead of the variable -- a check that looks
  like it passes while measuring nothing. Its policy JSON was also invalid
  (missing comma) and lacked the required eval_expression. The corrected
  version is one that was run; the quoted output is its real output.

- Cross-links now point at the .md file rather than the URL. Relative URLs
  resolve against the page's own directory, so `../tirith-reference/evaluators`
  from a page at /docs/tirith-providers/x/ resolved to
  /docs/tirith-providers/tirith-reference/evaluators. Linking by file lets
  Docusaurus resolve through the file graph, which also survives a slug change.

- sidebars.js is a manual sidebar, so the new pages are registered there under
  Using Tirith, Providers and Reference; without an entry a page builds but is
  unreachable in navigation.

meta.enforcement is documented as what it is: inert in the engine, and read by
the layer above it. The CLI copies it through untouched, while the GitHub Action
downgrades a failing policy to a warning for soft_mandatory and friends and
blocks on anything it does not recognise.
Copilot AI lite review requested due to automatic review settings August 13, 2026 10:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

refeed added 3 commits August 13, 2026 18:40
Clicking a site's own logo goes to that site's home. This one opened
tirith-policy-builder.vercel.app in a new tab, so the one control every reader
expects to take them home instead took them off the site, with no way back.

The builder is still reachable -- it moves to a named navbar item next to
GitHub, which is a clearer place for it than an unlabelled logo. The in-content
link on the getting-started page is untouched; that site is live and the
reference there is deliberate.
Listing a system purely to say it is unsupported tells a reader nothing the
"Works with" list does not already tell them, and reads as a roadmap hint that
was never intended. Removed from all three places it appeared: the landing page,
the CI integration page and the README.

Nothing is claimed about Azure DevOps either way now, which was the point of
mentioning it in the first place.
The hand-rolled button rule set the label to var(--ifm-background-color), which
resolves to #0000 in light mode -- fully transparent. The result was a purple
rectangle with no readable text in it.

Replaced with Docusaurus's own button classes, which resolve their foreground
through --ifm-button-color to white over the dark purple in light mode and to
near-black over the lighter purple in dark mode. That removes the custom rules
rather than patching them, so there is one less place to get contrast wrong.
@sonarqubecloud

Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants