fix: resolve conflicts for PR #509

Merge prgs/master into PR branch to restore mergeability.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
2026-07-08 22:28:13 -04:00
co-authored by Claude Opus 4.8
64 changed files with 10181 additions and 113 deletions
+19
View File
@@ -13,6 +13,25 @@ credentials.** Every test mocks the HTTP client and the keychain/auth lookup.
## 1. Standard test commands
### Canonical runner: `./run-tests.sh`
The canonical full-validation command is the root-level runner. It invokes the
project virtualenv interpreter and passes any extra arguments straight through
to `pytest`:
```bash
# Full validation
./run-tests.sh
# Focused validation (extra args forward to pytest)
./run-tests.sh tests/test_mcp_server.py -q
```
`run-tests.sh` runs `venv/bin/python -m pytest "$@"` and fails with a clear
setup message if the virtualenv Python is missing (so a session never silently
falls back to the wrong interpreter). The explicit `venv/bin/python -m pytest`
forms below remain valid and equivalent.
The test suite needs the project virtualenv (it provides the MCP SDK):
```bash
+97
View File
@@ -377,6 +377,37 @@ explicit control-checkout repair.
Portable wording: [`skills/llm-project-workflow/SKILL.md`](../skills/llm-project-workflow/SKILL.md).
### Root checkout guard (#475)
The MCP server enforces a fail-closed **root checkout guard** before author,
reviewer, and merger mutations when the active workspace is not an isolated
`branches/...` worktree (reconciler close paths remain exempt per #468).
The guard blocks when the **control checkout** (repository root) is:
- on a non-stable branch (`master` / `main` / `dev` expected),
- detached HEAD,
- dirty (tracked edits),
- or its `HEAD` does not match `prgs/master` when that ref is available.
**Remediation (never auto-reset or stash):**
> Root checkout is not on master. Preserve state, switch root back to master,
> and use `scripts/worktree-review` or the sanctioned issue worktree flow.
**Recovery after root hijack:**
1. Preserve any in-progress edits (copy paths, note branch name, or commit on a
rescue branch from a `branches/...` worktree).
2. From the repository root: `git checkout master` (or `main` / `dev` per repo
policy) and `git fetch prgs && git merge --ff-only prgs/master` when safe.
3. Confirm `git status` is clean and `git branch --show-current` is `master`.
4. Resume work only inside `branches/issue-<n>-<slug>` via `gitea_lock_issue` /
`git worktree add`.
`branches/...` directories are disposable role worktrees; the root checkout is
the stable orchestration surface only.
## Shell Spawn Hard-Stop Rule
Symptom: a shell tool call returns `exit_code: -1` with empty stdout/stderr.
@@ -641,6 +672,33 @@ loop and do **not** substitute WebFetch/Playwright/manual base64.
- **Prompt:** `Use any eligible merger profile to merge PR #N if checks pass and
it is mergeable. Confirm with "MERGE PR N". Do not force-merge.`
#### Merger lease adoption (#536)
When review and merge run in **separate sessions**, the merger must **not**
manually seed `reviewer_pr_lease._SESSION_LEASE` or equivalent in-process state.
That ad hoc pattern was used incidentally for PR #493 and PR #421; it is not
canonical proof and is rejected by mutation gates.
**Canonical merger handoff:**
1. Confirm a reviewer session holds an active PR lease and posted **APPROVED**
at the current live head (`gitea_get_pr_review_feedback`).
2. In a clean merger worktree under `branches/`, call
`gitea_adopt_merger_pr_lease` with `worktree`, `expected_head_sha`, and
optional `issue_number`.
3. The tool posts durable adoption proof on the PR thread (`<!-- mcp-review-lease-adoption:v1 -->`)
recording actor, profiles, adopted-from session/comment, adoption reason, and
timestamp, then records sanctioned in-session provenance.
4. Call `gitea_merge_pr` with the same pinned `expected_head_sha`.
**Forbidden:** Python one-liners or scripts that call `record_session_lease()`
without provenance from `gitea_acquire_reviewer_pr_lease`,
`gitea_adopt_merger_pr_lease`, or `gitea_heartbeat_reviewer_pr_lease`.
**Same-session review+merge:** the reviewer session may use
`gitea_acquire_reviewer_pr_lease` directly; adoption is only for cross-session
merger handoff.
### Close the issue after merge / Reconciliation
- **Profile:** issue-manager or merger.
@@ -844,6 +902,45 @@ scripts/release-tag v0.4.0 --notes-file /tmp/release-notes.md
scripts/release-tag v0.4.0 --notes-file /tmp/release-notes.md --push
```
## Namespace workspace binding (#510)
Each MCP namespace resolves its **own** active task workspace. Foreign role
worktree environment variables must not poison another namespace's purity
checks.
| Namespace | Workspace env vars (in priority under `GITEA_ACTIVE_WORKTREE`) | Allowed roots |
|-----------|------------------------------------------------------------------|---------------|
| author | `GITEA_AUTHOR_WORKTREE` | `branches/<task>` worktree only (#274) |
| reviewer | `GITEA_REVIEWER_WORKTREE` | clean `branches/<review>` worktree |
| merger | `GITEA_MERGER_WORKTREE` | clean `branches/<merge>` worktree **or** clean control checkout |
| reconciler | `GITEA_RECONCILER_WORKTREE` | clean `branches/<reconcile>` worktree **or** clean control checkout |
`GITEA_AUTHOR_WORKTREE` is **author-only**. Reviewer, merger, and reconciler
MCP processes ignore it even when it points at a dirty author WIP tree.
### Safe reconnect / rebind procedure
When a mutation blocks on workspace binding:
1. Read the error — it names the **resolved workspace path**, **role
namespace**, and **binding source** (tool arg, env var, or process root).
2. Reconnect or relaunch the correct namespace MCP server from the intended
workspace (or set the role-specific env var before launch).
3. Pass `worktree_path` on reviewer/merger mutation tools when the active
branches/ worktree differs from the MCP process root.
4. **Do not** clean, reset, or discard foreign role worktrees to unblock your
own namespace — that destroys another agent's WIP.
### CTH guidance for workspace binding blockers
When posting a Canonical Thread Handoff after a binding blocker:
- State which namespace was active (author / reviewer / merger / reconciler).
- Quote the resolved workspace path and binding source from the error.
- Name the safe reconnect action (relaunch MCP from `branches/...`, set
`GITEA_*_WORKTREE`, or pass `worktree_path`).
- Explicitly note that foreign worktrees must not be cleaned to unblock.
## Safety notes
- Never place raw tokens or passwords in any LLM MCP config; reference secrets
+67
View File
@@ -0,0 +1,67 @@
# MCP operator shell menu
## Purpose
`./mcp-menu.sh` is a repository-root terminal menu for onboarding and operating
the Gitea-Tools MCP/Gitea workflow without memorizing every prompt, script path,
or runbook section.
It is intentionally **safe by default**: status checks and copy-paste workflow
prompts. It does not delete branches, force-push, edit lock files, or bypass
sanctioned MCP tools.
## How to run
From the repository root:
```bash
./mcp-menu.sh
```
The script must be executable (`chmod +x mcp-menu.sh`). It uses bash with
`set -euo pipefail`.
## Safety rules
- **Read-only by default** — root checkout health is inspection only.
- **No destructive git** — no `git push --force`, branch deletion, or
`--delete` refspecs.
- **No lock-file editing** — issue locks are acquired only through
`gitea_lock_issue`.
- **No raw API bypass** — prompts direct operators to sanctioned MCP tools.
- **Remote mutations require confirmation** — any future menu action that would
mutate remote or server state must be clearly labeled and require explicit
operator confirmation before running.
- **Author work stays under `branches/`** — the root checkout is a stable
control checkout on `master` / `prgs/master`.
## Menu options
| Option | Description |
|--------|-------------|
| Project status / root checkout health | Shows cwd, branch, `git status --short --branch`, HEAD SHA, `prgs/master` SHA, and warnings when the root checkout is dirty or off `master`. |
| Author workflow prompts | Ready-to-copy prompts for issue work, conflict-fix sessions, and root checkout recovery. |
| Reviewer workflow prompts | PR review prompt (review-only; no merge). |
| Merger workflow prompts | PR merge prompt (merge gates and explicit approval). |
| Reconciler workflow prompts | Already-landed / closed PR reconciliation prompt. |
| Onboarding new project | Checklist prompt for adding a repository to the MCP workflow. |
| Proxmox deployment placeholder | **Not implemented** — informational message only. |
| Create Proxmox LXC placeholder | **Not implemented** — informational message only. |
| Run tests | Runs `./run-tests.sh` when present; otherwise `venv/bin/python -m pytest`; otherwise fails closed with a clear error. |
| Exit | Quit the menu. |
## Placeholder-only entries
**Proxmox deployment** and **Create Proxmox LXC** are placeholders until
dedicated issues implement sanctioned automation. The menu prints a clear
message and does not invoke deploy scripts.
## Related documentation
- [`docs/llm-workflow-runbooks.md`](llm-workflow-runbooks.md) — Gitea-specific workflow runbooks
- [`skills/llm-project-workflow/SKILL.md`](../skills/llm-project-workflow/SKILL.md) — portable workflow skill
- [`skills/llm-project-workflow/workflows/`](../skills/llm-project-workflow/workflows/) — canonical task workflows
## Tests
Hermetic coverage lives in `tests/test_mcp_menu_script.py`.
+2
View File
@@ -24,6 +24,8 @@
- `gitea_dry_run_pr_review` — validation-phase review mechanics.
- `gitea_mark_final_review_decision` — mark validation complete.
- `gitea_submit_pr_review` / `gitea_review_pr` — gated live review.
- `gitea_acquire_reviewer_pr_lease` / `gitea_heartbeat_reviewer_pr_lease` — per-PR reviewer lease (#407).
- `gitea_adopt_merger_pr_lease` — guarded cross-session merger lease adoption (#536).
- `gitea_merge_pr` — gated merge (only merge path).
## Read tools