Checkwright v0.29.0

2026-09-28

Checkwright is the verification layer under agent orchestration, and this release applies a spec toolkit’s recipe as part of the install and ships the license text inside every kit it installs.

In brief

  • If Spec Kit or OpenSpec writes your specs, one install line now fits Checkwright to that tree: init --recipe <toolkit>, with the default prose profile or with full. There is no block to paste, and an upgrade re-applies the recipe. The Spec Kit and OpenSpec page has each toolkit’s line.
  • Every installed kit now carries its LICENSE.
  • Items only an operator can settle get their own committed inbox, which a consultation drains.
  • You may have steps to take after upgrading. Stricter gates ask you to re-run --install-lifecycle, bind the lead template’s new consultation slot, and cite a family heading such as Requirement: <name> whole. The allowed reds below name each.

Tightened gates

  • check-skill-binding — lifecycle-kit/templates/lead.md gained the consult-dispatch slot, so a lead binding shim reds until it binds it. Bind the agent type your lead dispatches a consultation as, and a threshold or off — or state that your lead dispatches none.
  • check-merge-attrs — the derived union-merge set gained the consult inbox (LIFECYCLE_KIT_CONSULT_INBOX_FILE), so a .gitattributes marker block written before it reds until it carries that path’s merge=union line. Re-run --install-lifecycle to regenerate the block.
  • check-spec-pointer — a prose citation’s lead clause is no longer admitted where another heading in the file shares it, or where the citation continues with the heading’s own separator, so a bare citation of a missing member of a heading family such as Requirement: <name> now reds. Cite the member whole, or, where a citation names a lead and runs on with its separator as prose, cite the whole heading or follow the lead with punctuation other than the heading’s own separator.

Renamed knobs

None.

Behavior changes

  • lifecycle-kit/SPEC.md §The consult inbox — a committed consult inbox (LIFECYCLE_KIT_CONSULT_INBOX_FILE, default .workflow/consult-items.md) whose items only the consult skill rules on and any session may re-class or discard with cause, written by the new --emit file-consult arm; --install-lifecycle now writes a merge=union line for it and check-merge-attrs reds its absence; close’s gap drain gains a →forward disposition for a bullet only the operator can settle, and the consult template a drain step. Re-run --install-lifecycle to add the attribute, and re-read your close and consult bindings if they restate the drain or the ritual.
  • delegation-kit/SPEC.md §The statusline arm — an optional inbox counter group, DELEGATION_KIT_STATUSLINE_INBOXES (<label>=<path> elements), empty by default so the bar is unchanged; set it to show a bullet count per inbox. Nothing to do otherwise.
  • lifecycle-kit/templates/stages/close.md — close files a consult-owed item with --emit file-consult when a [roadmap:] entry leaves the roadmap during the iteration or the first configured horizon is vacant; it re-tags nothing. Inert where QUEUE_KIT_HORIZONS is empty; re-read your close binding if it restates step 5.
  • gate-sdk/SPEC.md §Consumer payload — every packed kit and the package now carry the license text as LICENSE, placed by --pack-installer from the new knob GATE_SDK_PAYLOAD_LICENSE, which defaults to the root license file; a set value naming no file tracked at the packed commit refuses the pack. A publisher whose license file is named otherwise sets the knob; set it explicitly empty to place none. An adopter’s next init or update vendors a LICENSE into each kit root.
  • init --recipe — the package carries payload recipes and init --recipe <name> applies one by name, composing its lines into the seams init writes and dropping the gates it names, recorded in checkwright.lock as recipes so a re-run re-applies it (installer/SPEC.md §Payload recipes). A tree that applied a companion recipe with the old pasted block keeps its seams as the adopter’s changes; take init’s files with --force --recipe <name>.
  • gate-sdk/SPEC.md §Consumer payload — a keyed knob GATE_SDK_PAYLOAD_RECIPES (<name> → a tracked directory, default empty) makes --pack-installer place each directory at recipes/<name>/ in the package root; a name outside [a-z0-9][a-z0-9-]* or a directory with no tracked file refuses the pack. Nothing to do unless you publish recipes.
  • the Spec Kit recipe — it keeps check-fence-command-head registered and admits Task: as a fence command head (CANON_KIT_FENCE_PROGRAMS_EXTRA[] = Task:), so a tree applying it through init --recipe speckit gains that gate. A task list holding a bash fence of other non-commands now reds there; the gate’s help names the remedy, another info string or a CANON_KIT_FENCE_PROGRAMS_EXTRA line.

Upgrading

Replace the vendored kit directories wholesale at v0.29.0, or run checkwright update. Re-run --install-lifecycle if you vendor lifecycle-kit. Regenerate your generated artifacts; each freshness gate that reds prints its own regen command. Then run the full battery.

The allowed reds. check-skill-binding reds on a lead binding shim that does not bind consult-dispatch; bind it, or state that your lead dispatches none. check-merge-attrs reds on a .gitattributes block without the consult inbox’s merge=union line; re-run --install-lifecycle. check-spec-pointer reds on a bare citation of a heading-family member the file lacks, or a lead clause run on with the heading’s own separator; cite the heading whole.

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.