Checkwright v0.15.0

2026-07-25

Checkwright is the verification layer under agent orchestration, and this release closes a supply-chain hole in the workflows the kits ship: every uses: ref is now pinned to a full commit SHA, and check-action-pinning holds it there. A tag is repointable by whoever owns it, so a tag-pinned action means the code a run executes is not the code that was reviewed.

Tightened gates

  • check-action-pinning — new. Every uses: ref in a scanned YAML file must be immutable: a full 40-hex commit SHA, or a repo-local ./ path to an in-repo composite action, which the checkout already pins. A tag or branch ref (@v5, @main) reds. The ref is read as the first whitespace-delimited token after a key-position uses:, so a trailing # v1.2.3 comment falls away and a commented-out step — the copy-paste seed a template ships — is read like a live one. The scan set is derived by a gate_find walk for *.yml / *.yaml from an optional scan root rather than a maintained roster, so there is no new knob, and a tree holding no YAML exits clean on a zero count: a consumer running no GitHub Actions pays nothing for it. What it deliberately does not assert is that a trailing version comment names the tag the SHA resolves to — that needs a network call, which the hermetic-gate contract bars.

Renamed knobs

None.

Behavior changes

  • gate-sdk/templates/gates-workflow.yml — the shipped checkout step is SHA-pinned (actions/checkout@fbc6f399…, the tag kept as a trailing comment) where it read @v5. The pin buys immutability, not currency: no update bot refreshes a pinned SHA, so it stays exactly as old as the day it was written and refreshing it is a manual act at release time — a pinned ref is not a maintained ref. What a consumer reconciles: a copied-out workflow still carries the mutable @v5 and check-action-pinning reds on it — re-sync the template, or apply the pin in your copy.
  • site-kit/templates/site-health.yml — the same checkout pin, with the same reconciliation for a copied-out monitor workflow.
  • site-kit/checks/check-docs-render-fidelity.sh — the gate’s output text drops the word “pinned” from “the pinned Pages parser” in all three places it appeared (the # spec: line, the renderer-missing help, and the divergence header), and site-kit/SPEC.md’s invariant sentence with them. The renderer is SITE_KIT_RENDERER, a consumer-overridable command, so the word claimed a guarantee the kit does not make. What a consumer reconciles: nothing functional; a tree matching on the old output strings updates its match.
  • lifecycle-kit/templates/skills/align.md/align now audits the amendment against itself before auditing it against the tree: an author-stated count is checked against what the deltas actually mandate, and every ## Existing sections updated entry must name the delta that owns it. Both defects are visible on the amendment alone and both survive a green battery. What a consumer reconciles: a copied-out /align skill lacks the step — re-sync it.
  • canon-kit/templates/SPEC-amendment.md — the ## Existing sections updated guidance now states that each entry names the delta that owns it, and that an update target no delta claims reaches build as an orphan a batch adopts on its own authority. This is the surface the /align step above reads. What a consumer reconciles: a copied-out amendment template carries the old guidance — re-sync it.
  • docs/install.md §The upgrade contract — the empty-section form is now fixed rather than left to the author: a bare “None.”, with a trailing clause only where it rules out a near-miss the reader would otherwise mis-classify (an advisory KPI that never joins the gate registry, knobs added but not renamed). A clause that only restates the heading’s own negation is a restatement to delete. What a consumer reconciles: a note-authoring convention only — no gate reads it.

Upgrading

Replace the vendored kit directories wholesale at v0.15.0, then regenerate the generated artifacts — the pre-commit hook and the graph projection. Then run the full battery.

The allowed red. check-action-pinning, the gate landing this release, is the clean upgrade’s allowed-red set of one: it clears once every uses: ref in your tree is a full commit SHA or a repo-local ./ path. Replace each mutable ref with the SHA its tag resolves to, keeping the tag as a trailing comment.

The behavior changes above are declared for reading, not a mechanical scan. If a gate reds that this note does not name, the upgrade smoke was supposed to catch it first — open an issue, because that is a defect in the release rather than work for you.