CI workflow checks

The repository no longer keeps a generated CI baseline inventory or CI policy manifest. CI routing is intentionally smaller: workflows either use their native GitHub filters or the direct changed-path classifier in cmd/ciclassify.

cmd/ciclassify reads newline-delimited repository paths, rejects blank, absolute, traversal, or whitespace-padded rows, and emits the exact GitHub output names expected by each migrated workflow gate.

Run the checks

Run the retained workflow checks with the normal package tests:

  go test ./internal/ciworkflow ./cmd/ciclassify
  

Try the classifier locally with a changed-file list:

  git diff --name-only origin/main...HEAD |
  go run ./cmd/ciclassify -mode libghostty
  

Use -json for local diagnostics, or -github-output "$GITHUB_OUTPUT" when a workflow wants the command to append outputs directly.

Pull-request workflows that use the classifier check out the PR base SHA before running it. PR-modified policy code is treated as input to validate, not authority for narrowing CI.

Classifier consumers

Current classifier consumers and rollback boundaries:

WorkflowConsumerOutputsStatusFail-safe behavior
ci.ymlmacOS test and integration jobsmacosmigratedfile-list or classifier failure runs macOS jobs
coverage.ymlSwift coverage job and coverage commentguimigratedfile-list or classifier failure runs Swift coverage
sandbox.ymlmacOS safehouse jobmacosmigratedfile-list or classifier failure runs the macOS enforcement job
libghostty-native.ymlnative runtime matrix and dependency-unit race/fuzz gatesnative, dependency-unitmigratedfile-list, classifier, or detector job failure requires native and dependency-unit validation
dev-release.ymldev release-shaped package validationreleasemigratedfile-list or classifier failure runs dev release
docs-preview.ymlworkflow trigger and Hugo build gate; page selection stays local to the workflowtrigger, global, buildmigratedfile-list or classifier failure runs the Hugo build; local detector failure expands page selection globally
goreleaser.ymlstable release-shaped package validationreleaseparity onlyexisting inline classifier remains; file-list failure runs stable release

Stable release must not be migrated until the parity fixtures in internal/ciworkflow/testdata/workflow_classifiers.json prove the shared rules match the current inline stable-release classifier for representative release paths. Keep that migration in a separate rollback boundary from non-release gates.

CI workflow source changes conservatively select every migrated non-release gate. Changes to cmd/ciclassify or internal/ciworkflow also select the dev-release and docs-preview gates, because both workflows now rely on the shared classifier.

Retained Workflow Tests

internal/ciworkflow still owns local tests that parse workflow YAML and assert the security properties that matter for current workflows:

  • changed-path parity for migrated gates and stable-release fixtures;
  • fail-safe behavior when file listing or classification fails;
  • workflow trigger, timeout, concurrency, shell, and pinned-tool policies;
  • docs-preview, renovate retry, libghostty native, and release workflow checks;
  • credential boundary checks for synthetic token class, trust tier, scope, and filesystem target roots.

The tests are local compatibility checks. They do not claim to prove live GitHub branch protection, check freshness, repository ruleset binding, or live artifact provenance. Current mergeability still comes from repository-owned workflows and GitHub required checks.

Sandbox Tool Pinning

The macOS sandbox job in .github/workflows/sandbox.yml installs Safehouse from the reviewed upstream release asset:

  https://github.com/eugene1g/agent-safehouse/releases/download/v${SAFEHOUSE_VERSION}/safehouse.sh
  

CI verifies SAFEHOUSE_SHA256 before installing anything, copies the script to $HOME/.local/bin/safehouse, then re-checks the installed file hash and safehouse --version. The only consumers are the later Safehouse availability probe and the safehouse_enforce tagged sandbox tests in the same job.

Renovate tracks SAFEHOUSE_VERSION in sandbox.yml, but Safehouse does not publish GitHub build attestations for this asset. Safehouse update PRs are manual-review only: a version-only Renovate bump should fail the macOS sandbox job until a maintainer updates SAFEHOUSE_SHA256.

To update Safehouse, inspect the upstream release notes, then read the GitHub asset digest:

  gh api repos/eugene1g/agent-safehouse/releases/tags/vX.Y.Z \
  --jq '.assets[] | select(.name == "safehouse.sh") | .digest'
  

Strip the sha256: prefix for SAFEHOUSE_SHA256, or download safehouse.sh and verify the same value with shasum -a 256. Let the macOS enforcement job prove the reviewed bytes before merge. To roll back, restore the previous SAFEHOUSE_VERSION and SAFEHOUSE_SHA256 pair in sandbox.yml; the install step fails closed if the release asset no longer matches the reviewed digest.

Artifact boundary

Native and release artifact boundaries remain enforced by the current workflow and libghostty-specific checks. internal/ciworkflow does not expose a supported artifact manifest, run-plan, or producer-result contract.