Checkwright v0.30.0

2026-09-29

Checkwright is the verification layer under agent orchestration, and this release checks a Spec Kit or OpenSpec task list against the tree it describes and lets each install choose the kits and gates it carries.

In brief

  • If Spec Kit or OpenSpec writes your specs, the recipe now holds the task list to your tree: a ticked task naming a path that does not exist reds, and on Spec Kit so does a [USn] label with no matching user story beside the list. The Spec Kit extension installs the full profile when you ask for it.
  • One install can now add or drop kits and gates: init and update take --with-kit, --without-kit, --with-gate, --without-gate and --no-selection, and a re-run keeps the choice.
  • The git hooks now hand off to the gate binary, so an edit to a # graph: manifest or the gate registry needs no hook regeneration.
  • Close drains a capture log to a file it reads before removing it, so lines logged while a close runs are no longer lost.
  • You may have steps to take after upgrading. Register the two new canon-kit task-list gates or declare them unregistered, move any hand-written hook region into a shell gate, and spell a gitignored close-surface reclaim with --emit capture-drain. The allowed reds below name each.

Tightened gates

  • check-close-surfaces — a new assertion D reds a gitignored roster row whose reclaim= does not rotate its log, since close reads every row before reclaiming it and a truncation erases the lines appended in between. Spell the reclaim <gate binary> --emit capture-drain <path>, and read the drain file it prints rather than the live log.
  • check-task-path-claim — new in canon-kit: a ticked task in a task list CANON_KIT_TASK_LIST_GLOBS names reds on each path it names that does not exist. It registers disarmed and asserts nothing until that knob is set; a path absent by design takes task-path-exempt: <reason> on the task’s line or the one above.
  • check-task-label-resolution — new in canon-kit: a label a task list cites, per a family in CANON_KIT_TASK_LABEL_CITES and CANON_KIT_TASK_LABEL_DEFINES, reds unless a markdown file beside the list defines it. It registers disarmed and asserts nothing until the cite knob and the task-list knob are set; the two knobs must carry one key set of one-group EREs, or every canon-kit gate exits 2.
  • check-gate-substrate-parity — reds after upgrading through assertion I, which holds every gate the binary carries for a kit you vendor to be registered in your gates.list or declared # unregistered: there. If you vendor canon-kit, the new check-task-path-claim and check-task-label-resolution are such gates: register each, or declare # unregistered: <gate> — <reason>.
  • check-graph — reds on a # graph: manifest that still carries gen=, the key gen=manual retired with the hook handoff. Delete the key, and move any hand-written hook region into a trigger=* shell gate that reads the staged set itself.

Renamed knobs

None. Knobs were added, not renamed.

Behavior changes

  • delegation-kit/SPEC.md §The turn-end liveness hook and §bin/wait-probe — the turn-end hook’s log and the probe’s evidence file now reclaim by --emit capture-drain instead of truncation, so close reads the drain file it prints and removes it with --done. A consumer allowlisting the old : > <log> clear may drop that entry.
  • gate-sdk/SPEC.md §git-hook — the generated hooks become a two-line handoff to the gate binary’s --git-hook arm, which reads the # graph: manifests at commit time, so a manifest or registry edit no longer needs a regeneration, and update rewrites an adopter’s hooks. The lines the hooks print are unchanged.
  • gate-sdk/SPEC.md §The # graph: manifest — gen=manual is retired and a manifest carrying gen= reds check-graph; a hand-written hook region becomes a trigger=* shell gate that reads the staged set itself.
  • update — its usage: line names [--recipe <name>]... and [--no-recipe], the recipe flags it already forwarded to init; nothing an adopter runs changes.
  • init and update — five selection flags, --with-kit, --without-kit, --with-gate, --without-gate and --no-selection, adjust a profile’s kit set and registry per install, recorded under the manifest’s new selection key and re-applied by a bare re-run (installer/SPEC.md §Selecting kits and gates). An install passing none records none and changes nothing.
  • the Spec Kit extension’s install command — it installs full when the user’s input asks for it, naming full’s costs first, and prose otherwise; a prose install is unchanged.
  • the Spec Kit and OpenSpec recipes — each arms check-task-path-claim on its toolkit’s task lists, and the Spec Kit recipe binds the user-story label family for check-task-label-resolution. A tree applying either recipe from this release reds on a ticked task naming a missing path, and on Spec Kit on a [USn] label with no ### User Story n in the spec.md beside it; correct the task, untick it, or valve it.
  • site-kit/SPEC.md §check-docs-liquid-parse — the Liquid template set is the new knob SITE_KIT_LIQUID_TEMPLATES, repo-relative pathspecs defaulting to the three directories the gate read before (docs/_layouts/*, docs/_includes/*, docs/_posts/*), so a site that renames its template directories or moves its docs dir sets it.

Upgrading

Replace the vendored kit directories wholesale at v0.30.0, or run checkwright update, which also rewrites your git hooks as the handoff. Regenerate your generated artifacts; each freshness gate that reds prints its own regen command. Then run the full battery.

The allowed reds. check-gate-substrate-parity reds if you vendor canon-kit, until you register check-task-path-claim and check-task-label-resolution in your gates.list or declare each # unregistered: with a reason. check-task-path-claim and check-task-label-resolution red only once armed, as a Spec Kit or OpenSpec recipe arms them, on a ticked task naming a missing path or a label with no definition beside the list; correct the task, untick it, or valve it. check-close-surfaces reds on a gitignored roster row whose reclaim= truncates its log; spell it --emit capture-drain <path>. check-graph reds on a manifest still carrying gen=; delete the key and move any hand-written hook region into a trigger=* shell gate.

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.