013 — Release refuses a dirty tree (#35)

Status: shipped (v0.8.0)

Why

Releasing pta2svg v0.2.0, Execute step 1 (git add -A) swept an untracked .vscode/settings.json into the "Release prep" commit (#35). The step shows git status and asks "Add all changes?", but the answer is yes by habit and always yes under --yes, and the question is the wrong one: the release cannot tell the story's last edits from a stray file, and neither can the person at a glance. Every other release commit adds only what its own step changed, because the tree is clean when it runs; the dirty-tree commit is the one place the release commits work it did not make. The "Release prep" commit has been used three times across task-plus and gobank; the practice the method asks for is to commit the work, then release.

What changes

  • tp release fails in Gather when the working tree has changes, in every mode and in --dry-run: "working tree is dirty; commit, stash or ignore before releasing", followed by git status --short. The tag runs already refused a dirty tree; now every run does.
  • .tp-release-comment is tp's own file: it does not make the tree dirty and no release commit stages it, whether or not the project ignores it.
  • The "Add all changes?" and "Commit message" questions go, with Execute step 1. The release comment's default chain loses the commit message; .tp-release-comment stays its fallback.
  • Rollback of a pull request run leaves the tree clean: the release branch carried only the release's own edits, which the next run remakes, so there is no longer any work to keep as uncommitted changes.
  • docs/release-workflow.md and README.md describe the rule.

Acceptance

Working tree Run Outcome
clean any as before
tracked file modified direct error naming the file; nothing committed, no tag
untracked file release PR from the base branch error; no release branch, no PR
untracked file story branch error; nothing pushed, no PR
untracked file --dry-run same error
only .tp-release-comment, not ignored any treated as clean; the file is not committed
PR creation fails after the release branch is made base rollback returns to base with a clean tree
dirty, merged release PR or prepared heading on base base error, as before

Out of scope

  • Staging a chosen subset of the changes: the person commits what the release should carry.
  • tp check reporting a dirty tree.

Decisions

None recorded as an ADR. The fork was between filtering the sweep (tracked files only, or named release files only) and refusing the tree. Filtering keeps a convenience used three times and needs every later git add in the release to become path-specific, including the WASM build whose outputs it cannot name; refusing is one check with one message, and matches the rule the tag runs already apply.

Done when

  • tests express the acceptance table and pass
  • spec updated (docs/release-workflow.md, README.md)
  • roadmap ticked and stamped; changelog entry
  • issue closed with a link to the release (v0.8.0)