Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ jobs:
# would switch the guards off precisely when prose changes. The job is
# cheap enough that running it redundantly alongside the matrix on code
# PRs costs less than maintaining a list of which packages are guards.
#
# The capabilities gate rides along for the same reason. The semantic
# assertion — the checked-in capabilities page is the rendering of the
# YAML — is already a unit test; the make target adds the generator's
# own `go run` entry point, which release.yml runs against the tagged
# tree, so a broken target fails a PR here rather than a release.
unit:
name: unit tests (no Docker; docs guards)
runs-on: ubuntu-latest
Expand All @@ -83,6 +89,7 @@ jobs:
with:
go-version-file: go.mod
- run: make test-unit
- run: make check-capabilities

lint:
needs: changes
Expand Down Expand Up @@ -213,7 +220,7 @@ jobs:
# Single required status for branch protection ("all-green" is the
# context to require). Succeeds when nothing failed — including
# docs-only PRs, where the code-gated jobs were skipped but the unit
# job (and its docs guards) still had to pass.
# job still had to pass.
all-green:
if: always()
needs: [changes, unit, lint, build, test, demo]
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ jobs:
# previous workflow could have poisoned.
cache: false

# A tag cannot ship a capabilities matrix that disagrees with its YAML.
- name: Check the capabilities matrix
run: make check-capabilities

# Belt and braces on top of the ancestry gate: re-run the suite against
# the exact tree being released.
- name: Test the tagged tree
Expand Down
16 changes: 15 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ PG_DSN_LOCAL = postgres://$(PG_USER):$(PG_PASSWORD)@localhost:$(PG_PORT)/$(PG_DA
# Which corpus replay project to run (replay/<project>/project.conf).
REPLAY_PROJECT ?= buzz

.PHONY: build gen-capabilities test test-unit test-db test-supported-postgres test-aws-boundary lint setup db-up db-down demos clean demo demo-seed demo-check replay replay-refresh replay-down
.PHONY: build gen-capabilities check-capabilities test test-unit test-db test-supported-postgres test-aws-boundary lint setup db-up db-down demos clean demo demo-seed demo-check replay replay-refresh replay-down

# The first target is make's default goal: keep build here so a bare
# `make` builds the binary rather than rewriting a checked-in document.
Expand Down Expand Up @@ -58,6 +58,20 @@ lint:
gen-capabilities:
$(GO) run ./internal/cmd/gen-capabilities

# Regenerate the capabilities page and fail if regeneration changed it. Only the
# generator's own edits count, so an uncommitted edit to the hand-written prose
# outside the marker regions does not trip the gate; the stale generated output
# is left in place, with the diff printed, for review.
check-capabilities:
@before=$$(mktemp); cp docs/capabilities.md "$$before"; \
$(GO) run ./internal/cmd/gen-capabilities || { rm -f "$$before"; exit 1; }; \
if ! diff -u --label docs/capabilities.md --label regenerated "$$before" docs/capabilities.md; then \
rm -f "$$before"; \
echo "docs/capabilities.md disagrees with pkg/capabilities/capabilities.yaml; run make gen-capabilities and commit the result" >&2; \
exit 1; \
fi; \
rm -f "$$before"

# Configure git hooks (relative path so worktrees work too).
setup:
git config core.hooksPath .githooks
Expand Down
16 changes: 10 additions & 6 deletions docs/capabilities-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ path on T3 rows.
│ go:embed │ regenerate │ committed
▼ ▼ ▼
┌───────────────────────┐ ┌─────────────────────────────────────────────────────┐
│ pkg/capabilities │ │ CI gate: regenerate, then require an empty git diff
│ pkg/capabilities │ │ CI gate: regenerate, then require a no-op rewrite
└───────────┬───────────┘ └─────────────────────────────────────────────────────┘
Expand Down Expand Up @@ -154,10 +154,14 @@ markers — the introduction, tier explanation, legend, peer comparison, refusal
and operator recipes — remains hand-written. Generated output is deterministic: source
order is display order, formatting has no timestamps, and a second generation is a no-op.

The generator lands with the YAML file, not later. A Make target runs its `go run`
entry point. CI runs that target and then fails unless `git diff --exit-code` is empty.
The test validates semantics; regenerate-and-diff proves the checked-in human page is
the rendering of the validated data.
The generator lands with the YAML file, not later. `make check-capabilities` runs its
`go run` entry point and fails unless regeneration leaves the page byte-identical; only
the generator's own edits count, so an uncommitted edit to the hand-written prose does
not trip it. The unconditional unit job in `.github/workflows/ci.yml` runs that target
beside the unit tests on code and docs-only changes alike, and
`.github/workflows/release.yml` repeats it for the tagged tree before the test sweep. The
test validates semantics; regenerate-and-diff proves the checked-in human page is the
rendering of the validated data.

The capability-statement rule still applies beyond the generated matrix. A behavior
change updates the YAML, [limitations.md](limitations.md), and the README's short
Expand Down Expand Up @@ -263,7 +267,7 @@ does not change any capability, tier, refusal, or runtime behavior.

Implementation order is:

**Status:** step 1 is complete; steps 24 remain planned.
**Status:** steps 1 and 3 are complete; steps 2 and 4 remain planned.

1. add the typed package, `pkg/capabilities/capabilities.yaml`, validator, generator,
and markers together, making the repository single-source on day one;
Expand Down
Loading