xff v0.8.0

Release website

Release notes use .github/release-notes.md.template,
rendered by tools/release_notes.sh TAG, to link to that tag's
versioned website and related release resources. The existing changelog and installation notes
remain included.

The website forwards to the latest published stable release at
site/tag/<tag>/, preserving the exact Git tag name. Each release keeps its converted HTML,
images, and configured files. Retrying publication leaves an existing snapshot unchanged; a
different commit cannot replace it. Older versions remain directly accessible.

release-site.json defines the layout. Source names are relative to the
repository root; destinations are relative to that release's site directory. For example:

{
  "pages": {
    "README.md": "index.html",
    "docs/guide.md": "guide/index.html"
  },
  "files": {
    "schema/example.json": "schema/v1.json"
  },
  "links": [
    {
      "label": "Release",
      "href": "https://github.com/{owner}/{repo}/releases/tag/{tag}"
    }
  ]
}

Use existing source files in the actual configuration. pages converts Markdown; optional files
copies other files unchanged. generated_html maps a tracked Markdown source name to a generated
standalone HTML source and its destination. This lets repository links to XFF.md resolve to the
native XFF.html emitted by the released binary instead of a second rendering of the Markdown.
README.md must map to index.html. The generated
documents.html, release.json, release-site.json, and assets/ paths are reserved.
Destination paths cannot have hidden components (names starting with a dot), because the Pages
artifact uploader excludes them. Hidden source paths remain valid; for example,
.github/workflows/README.md maps to workflows/index.html.

Navigation links support {owner}, {repo}, {tag}, {version}, and {commit}. {version}
omits a leading v for compatibility with coverage report paths. By default, the configuration
and content come from the release tag. Every linked local Markdown page, including directory
README links, must have a pages mapping. Publication fails for an omitted mapping, a missing
generated file, or a broken anchor within the snapshot. Links to configured pages follow their
destination mappings; other local source links use the exact release commit. Embedded images are
copied, including remote badges. Markdown conversion uses the
GitHub Markdown API at publication time;
browsing the result requires no Markdown renderer or CDN.

After the Release workflow succeeds, Publish release site retains the snapshot on
coverage-pages and deploys the complete Pages tree. Coverage and site publication share a
concurrency group to preserve both trees. GitHub's latest stable release selects the root redirect;
backfilling an older release does not make it latest. The workflow can also be dispatched with a
published tag to retry publication. Enable GitHub Pages with GitHub Actions as its source, and
set the repository's About website to https://mboworks.github.io/xff/.

The release site renders NOTICE.md as NOTICE.html, with the same navigation as other pages.
The Markdown notice is generated from the all-extras binary via --help=notice --help-format=markdown. LICENSE links remain pinned to the tagged commit on
GitHub, where readers can use GitHub's license analysis.

Navigation starts with Home and Release & downloads, followed by configured links in their
authored order, then Source and Documentation. The xff configuration orders those links as
CLI reference, Coverage, and Benchmarks.

Backfill a historical release

No new release or tag change is needed. Manually dispatch Publish release site with tag set to
the historical release and config_path set to a tracked JSON file on main. Leave config_path
empty to use a configuration already in the tag. For example, after selecting a compatible
configuration and an existing tag:

gh workflow run pages.yml --repo mboworks/xff --ref main \
  -f tag="${RELEASE_TAG}" -f config_path=release-site.json

The override controls only publication layout; all Markdown and copied files come from the selected
tag. Each new snapshot retains the exact configuration as release-site.json, with its SHA-256,
origin, and source commit in release.json. A configuration can serve several historical tags when
its sources exist in each. For another layout, commit another configuration and select its path.
Missing sources or links fail publication instead of using newer content. Retrying a published tag
without an override preserves its original HTML and configuration. An explicit config_path
rebuilds an existing site for the same tagged commit, including its navigation. Rendering and link
validation finish before replacing the retained site; a failed rebuild preserves the previous
files. An override cannot replace a release with a different source commit.

Local regression tests:

python3 -m unittest discover -s tools -p release_site_test.py

CI also converts the configured documentation and checks the generated links in a disposable
runner directory. It never commits, retains, or deploys that preview.

Publication downloads the immutable, attested xff_full-linux-x86_64 release executable and runs
the reference generator from the same trusted release tag, whose arguments match the released
binary. Current generators use --help=full --help-format=html. The resulting standalone document is copied byte-for-byte into the snapshot and
participates in the same link and anchor validation as Markdown-rendered pages. release.json
records its SHA-256 alongside the release commit and configuration hash.

Release coverage links select https://mboworks.github.io/xff/coverage/tag/<version>/, matching the
coverage publisher rather than the moving main-branch report.

Site artwork

The README uses the original transparent MBO Works logo in
docs/assets/mboworks-logo.png. Release-site rendering copies this image with the README.
The favicon assets are derived from that same artwork: a 32-pixel PNG, a 180-pixel Apple
Touch icon, and an ICO containing 16-, 32-, 48-, and 256-pixel PNG images.

Both Pages publishers run tools/site_artwork.py on the final deployment directory.
This supplies favicons to documentation, native HTML references, redirects, and coverage
reports, including existing releases. Relative links work at every nesting depth and under
xff's project URL. Only the deployment copy receives these links; retained release files and
their recorded hashes stay unchanged. The standalone CLI HTML output remains self-contained.

To regenerate the images on macOS, resize the original square PNG with sips -z SIZE SIZE
for each size, preserving transparency. The ICO stores those four PNG images in a standard
ICO directory. Keep the existing artwork unchanged when generating icon sizes.

The release site publishes Lean build notices for xff-* downloads
and Full build notices for xff_full-* downloads. Release notes link
to both inventories. ./notice-update.sh regenerates both from their corresponding
binaries; Bazel drift tests verify each. Custom builds report their own inventory with
--help=notice, exportable with --help-format=markdown.