diff --git a/docs/llm-workflow-runbooks.md b/docs/llm-workflow-runbooks.md index 4ea9c13..1b04cb3 100644 --- a/docs/llm-workflow-runbooks.md +++ b/docs/llm-workflow-runbooks.md @@ -257,6 +257,34 @@ Gitea-Tools lease gates: `gitea_lock_issue` (fail-closed before author mutations), `status:in-progress`, and claim comments. Full portable wording: [`skills/llm-project-workflow/SKILL.md`](../skills/llm-project-workflow/SKILL.md). +## Global LLM Worktree Rule + +The main project checkout is a stable control checkout. It must stay on the +configured stable branch: `master`, `main`, or `dev`. + +All LLM task work must happen inside the project's `branches/` directory. + +Before any mutation, prove: + +1. current project root +2. current working directory +3. current branch +4. stable branch for the main checkout +5. session-owned worktree path under `branches/` + +If `cwd` is not inside `branches/`, stop. Do not edit, create, delete, format, +test-write, commit, merge, rebase, checkout task branches, resolve conflicts, +or run cleanup. + +There are no exceptions for small fixes, docs, tests, cleanup, PR review fixes, +conflict resolution, or emergencies. + +The main checkout may only be used for read-only inspection, fetching, +stable-branch update after merged PRs, creating `branches/` worktrees, or +explicit control-checkout repair. + +Portable wording: [`skills/llm-project-workflow/SKILL.md`](../skills/llm-project-workflow/SKILL.md). + ## Branch worktree isolation All LLM implementation and review work happens in an isolated branch worktree diff --git a/docs/wiki/Operator-Guide.md b/docs/wiki/Operator-Guide.md index 35095ff..9052c47 100644 --- a/docs/wiki/Operator-Guide.md +++ b/docs/wiki/Operator-Guide.md @@ -13,6 +13,7 @@ Handbook for LLM operators and human developers using the Gitea-Tools MCP server 3. **One unit of work per session** — Implement one claimed issue *or* review/merge one PR; do not mix author and reviewer mutations in one session. 4. **No self-review / no self-merge** — The authenticated Gitea user must not approve or merge a PR they authored. 5. **Follow the gates** — Prompts express intent; MCP tools enforce safety. Never bypass gates via prompt instructions. +6. **Global LLM Worktree Rule** — Main checkout stays on `master`/`main`/`dev`; all mutations happen under `branches/`. Prove project root, `cwd`, branch, stable main-checkout branch, and session worktree path before editing. No exceptions. ## Supported Gitea instances diff --git a/docs/wiki/Workflow.md b/docs/wiki/Workflow.md index 708e0a6..2514dda 100644 --- a/docs/wiki/Workflow.md +++ b/docs/wiki/Workflow.md @@ -17,6 +17,9 @@ 0. Work Selection Rule — verify a work lease before any mutations (open PRs, issue-linked PRs, branches, worktrees, dirty worktrees, active leases/ handoffs, merged-PR completion). Stop if another session owns the lease. +0b. Global LLM Worktree Rule — main checkout on `master`/`main`/`dev` only; + mutate only from a `branches/` worktree after proving root, cwd, branch, + stable main-checkout branch, and session worktree path (no exceptions). 1. `gitea_resolve_task_capability` for the author task. 2. `gitea_lock_issue` before implementation mutations. 3. Claim with `gitea_mark_issue` / `status:in-progress` label. diff --git a/gitea_mcp_server.py b/gitea_mcp_server.py index ebee897..7a2c781 100644 --- a/gitea_mcp_server.py +++ b/gitea_mcp_server.py @@ -3473,6 +3473,16 @@ _GUIDE_RULES = { "'work already claimed'). Never create a parallel branch/PR unless " "the old branch is proven abandoned and takeover is recorded. " "gitea_lock_issue is the fail-closed author lease gate."), + "global_worktree": ( + "Main checkout is a stable control checkout on master/main/dev only. " + "All LLM task work happens under branches/. Before any mutation, prove " + "project root, cwd, branch, main-checkout stable branch, and " + "session-owned branches/ worktree path. If cwd is not under " + "branches/, stop — no edit/create/delete/format/test-write/commit/" + "merge/rebase/checkout/cleanup, with no exceptions (docs, tests, " + "small fixes, review fixes, conflicts, emergencies). Main checkout: " + "read-only inspect, fetch, create worktrees, post-merge stable " + "update, explicit repair only."), } _COMMON_WORKFLOWS = [ @@ -3481,6 +3491,9 @@ _COMMON_WORKFLOWS = [ "work selection: acquire or verify a work lease before any issue/PR work " "(open PRs, linked PRs, branches, worktrees, dirty worktrees, leases, " "merged completion); stop if another session owns the lease.", + "global worktree: main checkout on master/main/dev only; mutate only " + "from a branches/ worktree after proving root, cwd, branch, stable " + "main-checkout branch, and session worktree path.", "issue authoring: verify identity, create/claim the issue, keep scope " "explicit (remote/org/repo).", "implementation: claim issue, branch from fresh master, implement only " diff --git a/skills/llm-project-workflow/SKILL.md b/skills/llm-project-workflow/SKILL.md index d92aa0b..fcefe8f 100644 --- a/skills/llm-project-workflow/SKILL.md +++ b/skills/llm-project-workflow/SKILL.md @@ -89,10 +89,37 @@ mutations; `status:in-progress` and claim comments are supporting lease signals. Use `review_proofs.classify_issue_for_selection` when reporting fresh issue selection (#188). +## Global LLM Worktree Rule + +The main project checkout is a stable control checkout. It must stay on the +configured stable branch: `master`, `main`, or `dev`. + +All LLM task work must happen inside the project's `branches/` directory. + +Before any mutation, prove: + +1. current project root +2. current working directory +3. current branch +4. stable branch for the main checkout +5. session-owned worktree path under `branches/` + +If `cwd` is not inside `branches/`, stop. Do not edit, create, delete, format, +test-write, commit, merge, rebase, checkout task branches, resolve conflicts, +or run cleanup. + +There are no exceptions for small fixes, docs, tests, cleanup, PR review fixes, +conflict resolution, or emergencies. + +The main checkout may only be used for read-only inspection, fetching, +stable-branch update after merged PRs, creating `branches/` worktrees, or +explicit control-checkout repair. + ## B. Isolated worktree rule -**Never implement or review in the main checkout.** The main checkout is for -orchestration and status only (issue creation, `git status`, creating worktrees). +**Never implement or review in the main checkout** (Global LLM Worktree Rule). +The main checkout is for orchestration and status only (issue creation, +`git status`, creating worktrees) and must remain on the stable branch. - Each issue gets its own branch worktree under an ignored `branches/` directory. - Review work uses a **separate** review worktree, never the author's folder. @@ -180,7 +207,10 @@ Worktree folder = branch with `/` replaced by `-` 0. Acquire or verify a work lease (Work Selection Rule) — complete all seven checks before any claim, branch, or PR work. -1. Verify the orchestration checkout (right repo, clean tree). +0b. Global LLM Worktree Rule — prove project root, `cwd`, branch, main-checkout + stable branch, and session-owned `branches/` worktree path. If `cwd` is not + under `branches/`, stop before any mutation (no exceptions). +1. Verify the orchestration checkout (right repo, clean tree, on stable branch). 2. Fetch/prune: `git fetch --prune`. 3. Confirm local `master` equals remote `master` (`git rev-list --left-right --count /master...master` → `0 0`). 4. Create/claim the issue (§A). diff --git a/skills/llm-project-workflow/templates/start-issue.md b/skills/llm-project-workflow/templates/start-issue.md index bde01e7..c4b348c 100644 --- a/skills/llm-project-workflow/templates/start-issue.md +++ b/skills/llm-project-workflow/templates/start-issue.md @@ -22,6 +22,12 @@ Steps: as lease owner, review the existing PR, hand off, request takeover after expiry, or report "work already claimed"). Never open a parallel branch/PR unless the old branch is proven abandoned and takeover is recorded. +0b. Global LLM Worktree Rule — before any mutation, prove and state: project + root; cwd; current branch; stable branch for the main checkout (master/main/dev); + session-owned worktree path under branches/. If cwd is not inside branches/, + STOP (no exceptions — not for docs, tests, small fixes, review fixes, conflicts, + or cleanup). Main checkout is control-only: read-only inspect, fetch, create + worktrees, stable-branch update after merge, explicit repair. 1. Identity Checklist: Before claiming work, verify and state: - Required identity/profile for this task: author (allowed to push branches / create PRs) - Current authenticated identity (from whoami): diff --git a/tests/test_operator_guide.py b/tests/test_operator_guide.py index 01dd46e..602160a 100644 --- a/tests/test_operator_guide.py +++ b/tests/test_operator_guide.py @@ -133,7 +133,7 @@ class TestControlPlaneGuide(GuideTestBase): for key in ("hard_stops", "fail_closed", "head_sha_pinning", "merge_confirmation", "redaction", "separation", "profile_switching", "identity_verification", - "work_selection"): + "work_selection", "global_worktree"): self.assertIn(key, rules) self.assertIn("MERGE PR", json.dumps(rules["merge_confirmation"])) self.assertTrue(rules["hard_stops"]) diff --git a/tests/test_review_proofs.py b/tests/test_review_proofs.py index e61e98b..92bdfc0 100644 --- a/tests/test_review_proofs.py +++ b/tests/test_review_proofs.py @@ -1053,6 +1053,8 @@ class TestControllerHandoff(unittest.TestCase): self.assertIn("issue #182", skill) self.assertIn("## Work Selection Rule for LLMs", skill) self.assertIn("work already claimed", skill) + self.assertIn("## Global LLM Worktree Rule", skill) + self.assertIn("branches/", skill) def test_handoff_rejects_none_workspace_mutations_when_local_edits_exist(self): # 1. Workspace mutations: none is rejected when local_edits is True