v3.2.0: create-issue leaves GitHub, and create-pr takes a fix off main
Released 2026-09-26. Four features and four fixes, plus the test and docs commits that rode along.
What we were trying to fix
Three themes.
create-issue refused every repository that was not on GitHub. With the skill on the tracker
contract, a GitLab project still stopped at Step 1: tracker.capable answered unsupported because
scripts/tracker/gitlab.sh did not exist, and an Azure DevOps project stopped the same way for want
of scripts/tracker/azure-devops.sh. Azure DevOps is the host furthest from GitHub: work items
instead of issues, tags instead of labels, an HTML description by default, and Markdown in large
text fields reachable only through the REST API.
A fix debug-issue committed had no way to become a pull request. Only implement-issue could
open one, and create-pr refused the default branch outright. A debug-issue run that committed on
main, or left changes uncommitted, ended with an empty recap hand-off.
Two scripts trusted a wrong default. make-worktree.sh hardcoded BASE_BRANCH=main and
branched off the local ref without fetching. On phmatray/FormCraft, whose default branch is dev
and whose origin has no main, the local main sat at a commit dated 2025-08-08 while origin/dev
was at 2026-09-23. A phase-1 worker caught it by hand during an auto-dev run. In the other case,
wire-edges.sh kept its own copy of the dry-run message that the GitHub backend’s link verbs
already print, and spawned one tracker.sh per edge, each re-resolving the backend.
What we decided
Both backends implement every verb in contract.json’s skills.create-issue (#508 for GitLab
through glab api, #509 for Azure DevOps through az devops invoke). A decomposed job on Azure
DevOps gets native Parent and Predecessor links.
create-pr becomes the one home for opening a pull request (#636). Step 02 stops refusing the
default branch: it refuses [DEBUG- probes, switches to fix/<slug>, and commits leftover changes
through guarded-commit.sh. A new guard, skills/create-pr/scripts/rewind-default.sh, puts the
local default back on origin/<default>, and only once the pushed branch contains every local
commit on it. It ships with a refusal-first golden suite, a CI step and a not_decisions entry.
make-worktree.sh now branches off the remote default branch rather than a hardcoded local main
(#678). wire-edges.sh resolves the tracker once and relays the backend’s own dry-run output (#603).
The git write gate walks a $(...) or backtick span through one function shared by the unquoted and
double-quoted states instead of two hand-kept copies (#602).
The public surfaces now lead with Tagout: the README, the site and the host table put the lifecycle
first, tagout-migrate second, and install both plugins (#612). The README also gained a wordmark
banner (#679).
What got cut
The backends and the rebrand are each one child of a larger parent (#503 and #610). This release ships the GitLab and Azure DevOps children and the public surfaces, each as its own pull request.
What bit us
docs/methodology.md had drifted from recap.md: once create-pr could take a debug-issue fix,
the methodology page no longer matched the recap’s behaviour. #689 and #691 brought the two back
into agreement.
The test commits close the other gap. open-pr’s draft flag, base and Closes #N line now run
under golden tests (#641), and the BLOCKED_BY pointer text in read-the-plan.md is pinned (#596).