Normal author work is unchanged: gitea_lock_issue still requires the worktree
to be base-equivalent to master/main/dev, and gitea_create_pr still targets a
normal base branch. A *stacked* PR (based on another unmerged PR's branch) is a
new explicit, proof-backed path — it never bypasses the issue lock.
- stacked_pr_support.py: pure policy. Approve a non-master base only when it is
declared AND owned by a live OPEN PR whose number matches; reject arbitrary,
mismatched, or stale (merged/closed) branches; require the PR body to document
the stack (base branch, stacked-on PR, merge ordering).
- issue_lock_worktree.py: read_worktree_git_state / _find_matching_base_ref gain
an opt-in extra_bases arg so an approved stacked base can anchor
base-equivalence in addition to master/main/dev (empty by default = unchanged).
- gitea_mcp_server.py:
- gitea_lock_issue gains stacked_base_branch + stacked_base_pr. When declared,
it verifies the open PR owns the branch, anchors base-equivalence to it, and
records approved_stacked_base = {branch, pr_number, verified_open} on the lock.
- gitea_create_pr validates a non-master base against the lock's approved
stacked base, re-checks the dependency PR is still open, and enforces the
stacked-PR body fields. Master-based path untouched.
- Docs: llm-workflow-runbooks.md and work-issue.md document when stacked PRs are
allowed and the required PR-body wording.
Tests: test_stacked_pr_support.py (18 policy cases), stacked base-equivalence in
test_issue_lock_worktree.py, approved_stacked_base persistence round-trip in
test_issue_lock_store.py. Existing lock/create_pr regressions still pass.
The #482 -> #479/#478 case motivates this: create_pr previously could not open a
stacked PR because the lock required a master-equivalent worktree.
Closes#484.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Allow issue lock from base-equivalent branches/ worktrees instead of
requiring the literal master/main branch name. Runtime preflight and
mark_issue/lock_issue now inspect the declared active task workspace so
dirty control-checkout state does not block clean task worktrees.
Closes#275
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
gitea_lock_issue and gitea_create_pr accept worktree_path so lock
preconditions validate the caller's scratch clone instead of the shared
MCP server CWD. Lock records store the validated path; PR creation fails
closed when the declared path does not match.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>