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, soinfo/excludereads 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 togit status. Nothing to do; a re-run rewrites the block. - installer
init --personalanduninstall, linked worktrees — each worktree of a clone now writes and removes only its own exclude block, a linked worktree’s markers carryingworktrees/<name>after one space, so one worktree’s install, re-run oruninstallno 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-runinitin 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 andcheckwright.lockwere 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 unlessinitnames 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 defaulthooks, holds a live hook now keeps running those hooks, chained from the placed ones, wherecore.hooksPathwas repointed and they silently stopped. A hook the gates serve runs ahead of them, and each other through a forwarding hook. The receipt anduninstallprint the command restoring the priorcore.hooksPath. On native Windows a git withoutgit hook run --to-stdinis refused at exit 2 placing nothing. Nothing to do unless the arm refuses; then upgrade git, or call<bin> --git-hook pre-commitand<bin> --git-hook commit-msg <message-file>from your hook manager. - installer
prove, personal install — over a personal install,provenow copies the install (each recorded file the working tree holds andcheckwright.lock) into its scratch clone and provesHEADwith it, where it refused at exit 2; a held verdict readsPROVE: held — caught at <head>; personal install, no time to proof, and the not-held help namesCANON_KIT_TASK_LIST_GLOBSrather than a profile. A roster pathHEADtracks, or a destination through a link inHEAD’s tree, refuses at exit 2. Nothing to do. - marker blocks: installer
init --personalanduninstall,--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 --personalanduninstall,--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,uninstallanduninstall --dry-runnow refuse at exit 2 before any removal, where every owned file andcheckwright.lockwere 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
DONEagain 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-hooksand installeruninstall, the restore line — the priorcore.hooksPathvalue 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.