fix(mcp): allow create_issue from clean control checkout (#749)

Provide a narrow phase-scoped bootstrap so gitea_create_issue can run from
a clean canonical control checkout when no issue number—and therefore no
issue-backed worktree—can exist yet. Dirty roots, non-base branches, base
races, foreign workspaces, and all post-creation author mutations remain
fail-closed under the ordinary branches-only guard.

Closes #749.
This commit is contained in:
2026-07-18 16:19:04 -04:00
parent fdab6b6c69
commit e349839fd7
7 changed files with 781 additions and 35 deletions
@@ -450,6 +450,35 @@ If any gate fails, do not create the issue.
Produce a recovery handoff or duplicate report.
### 18a. Sanctioned first-mutation path (#749)
`gitea_create_issue` is a **pure remote mutation** (no local tree write). The
issue-first gate forbids creating `branches/issue-<N>-*` before the issue
number exists. Therefore the **only sanctioned first mutation** is:
1. Read-only identity + capability + duplicate search from the control checkout.
2. Ensure the **canonical control checkout** is:
* the configured repository root for the requested remote/org/repo;
* on an accepted base branch (`master` / `main` / `dev`);
* base-equivalent to live master;
* clean (no tracked local edits);
* in runtime/master parity.
3. Resolve exact task `create_issue`, then call `gitea_create_issue` **from that
clean control checkout** (no `worktree_path` required for this step alone).
4. After the issue number exists: create a **registered** worktree under
`branches/issue-<N>-*`, claim/lock, and perform every subsequent author
mutation from that worktree only.
**Forbidden improvisations (fail closed):**
* `mkdir` dummy directories under `branches/` (#713)
* borrowing an unrelated pre-existing worktree
* creating a pre-issue worktree in violation of issue-first
* running create_issue from a dirty, drifted, detached, or non-canonical root
Post-creation mutations (`lock_issue`, commit, push, `create_pr`, etc.) **never**
receive this bootstrap exemption.
## 19. Issue commenting gate
Before commenting on an existing issue, verify: