Checkwright v0.34.0

2026-10-25

Checkwright catches reproducible classes of unsupported claims in coding-agent delivery before merge, and this release keeps the git hooks a clone already ran working when the checks are placed, and makes the personal install and its removal leave every file they touch byte-exact.

In brief

Section Entries Who acts
New and tightened gates 0 everyone: these may red on upgrade
Knob changes 0 if you set knobs
Gate-authoring changes 0 if you write or shadow gates
Platforms 0 if you install on a listed platform
Behavior changes 14 if you depend on a listed behavior
  • If your clone already ran its own git hooks, placing the checks now chains them rather than silently replacing them, and the receipt prints a quoted command restoring your prior hooks setting.
  • A personal install now gives each linked worktree its own exclude block, and removing it restores the exclude file to its exact earlier bytes.
  • A damaged exclude block, a link under the install directories, or a CRLF file is now handled before anything is written, rather than leaving a half-finished install.
  • Nothing to reconcile on upgrade: no gate is new or stricter, and no knob moved.

New and tightened gates

None.

Knob changes

None.

Gate-authoring changes

None.

Platforms

None.

Behavior changes

  • installer uninstall, personal install — the exclude block’s removal now also drops the newline its append put on an exclude file whose last line had none, so info/exclude reads its pre-install bytes again rather than one newline longer. Nothing to do.
  • installer init --dry-run — no longer creates the gates directory, nor outside a personal install the workflow directory, where an empty one was left behind; it writes nothing. Nothing to do; remove an empty directory an earlier dry run left if you mind it.
  • installer init --personal — the exclude block collapses to one directory line only a kit directory the index holds nothing beneath, where it collapsed any such first component, so a project’s untracked files under the gates directory or another directory the install shares stay visible to git status. Nothing to do; a re-run rewrites the block.
  • installer init --personal and uninstall, linked worktrees — each worktree of a clone now writes and removes only its own exclude block, a linked worktree’s markers carrying worktrees/<name> after one space, so one worktree’s install, re-run or uninstall no longer un-excludes another’s files; a block whose worktree git no longer records is dropped, with a line saying so. A block an earlier release wrote from a linked worktree reads as the main worktree’s. Nothing to do; re-run init in each linked worktree holding a personal install to give it its own block.
  • installer init --personal, a damaged exclude block — an exclude file carrying this worktree’s begin marker without its end marker is now refused at exit 2 before the first write, where the payload and checkwright.lock were written first and left unexcluded. Nothing to do; restore the end marker or delete the begin line, then re-run.
  • installer init, links — a destination under a kit directory or the gates directory with a symlink or junction at any component below the root, the file itself included, is now refused at exit 2 before the first write, where the payload was copied through the link to wherever it pointed. Nothing to do unless init names such a link; replace it with the directory or file itself, or remove it, then re-run.
  • gate-sdk --install-hooks — a clone whose prior hooks directory, core.hooksPath’s effective value or else git’s default hooks, holds a live hook now keeps running those hooks, chained from the placed ones, where core.hooksPath was repointed and they silently stopped. A hook the gates serve runs ahead of them, and each other through a forwarding hook. The receipt and uninstall print the command restoring the prior core.hooksPath. On native Windows a git without git hook run --to-stdin is refused at exit 2 placing nothing. Nothing to do unless the arm refuses; then upgrade git, or call <bin> --git-hook pre-commit and <bin> --git-hook commit-msg <message-file> from your hook manager.
  • installer prove, personal install — over a personal install, prove now copies the install (each recorded file the working tree holds and checkwright.lock) into its scratch clone and proves HEAD with it, where it refused at exit 2; a held verdict reads PROVE: held — caught at <head>; personal install, no time to proof, and the not-held help names CANON_KIT_TASK_LIST_GLOBS rather than a profile. A roster path HEAD tracks, or a destination through a link in HEAD’s tree, refuses at exit 2. Nothing to do.
  • marker blocks: installer init --personal and uninstall, --install-doctrine, --install-lifecycle, --emit env-probe — rewriting or removing one marker block now leaves a file whose last line had no newline without one, where it added one, so another block ending such a file stays byte-identical; and two worktrees’ personal installs removed in either order restore the exclude file’s pre-install bytes, where removing the first-installed block first left one newline more. Nothing to do.
  • marker blocks, CRLF files: installer init --personal and uninstall, --install-doctrine, --install-lifecycle, --emit env-probe — a marker line ending in a carriage return now matches, so a file converted to CRLF keeps its block where a re-run appended a second, and a personal install’s prune no longer reads a live linked worktree’s CRLF block as a gone worktree’s and drops it. Nothing to do; delete a duplicate block an earlier release appended.
  • installer uninstall, a damaged exclude block — over a personal install whose exclude file carries this worktree’s begin marker without its end marker, uninstall and uninstall --dry-run now refuse at exit 2 before any removal, where every owned file and checkwright.lock were removed first and the block step then refused. Nothing to do; restore the end marker or delete the begin line, then re-run.
  • lifecycle-kit stage templates and lead template — each stage template’s last step now has a resumed session append DONE again before the report of any later turn that appends to its journal, and the lead’s completion read names the re-stamp, so a resumed session reads as finished its newest turn. Nothing to do; a vendored copy takes it on re-vendor.
  • gate-sdk --install-hooks and installer uninstall, the restore line — the prior core.hooksPath value the printed restore command names is now single-quoted for the host’s shell, POSIX off Windows and PowerShell on native Windows, so a value with a space or a shell metacharacter pastes as itself, where it printed bare and set another value or ran another command. Nothing to do.
  • doctrine-kit --install-doctrine --remove — removing a doctrine block that was the agent file’s unterminated last line now leaves the line before it with its newline, where it stripped that newline, so the rest of the file stays byte-identical. Nothing to do.

Upgrading

Replace the vendored kit directories wholesale at v0.34.0, or run checkwright update. Regenerate your generated artifacts; each freshness gate that reds prints its own regen command. Then run the full battery.

No allowed reds.

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.