diff --git a/.gitignore b/.gitignore index 552c123..acc0c95 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ gitea-mcp*.json !gitea-mcp.example.json .vscode/ graphify-out/ +branches/ diff --git a/docs/llm-workflow-runbooks.md b/docs/llm-workflow-runbooks.md index 0628cd8..226611a 100644 --- a/docs/llm-workflow-runbooks.md +++ b/docs/llm-workflow-runbooks.md @@ -161,6 +161,62 @@ Legacy environment-only setups keep working unchanged until migrated. Each runbook names the **profile role** it runs under, the steps, and a safe prompt. Confirm the active profile first (`gitea_get_profile` / `gitea_whoami`). +## Branch worktree isolation + +All LLM implementation and review work happens in an isolated branch worktree +under `branches/`. The main repository checkout is an orchestration checkout: +use it for status checks, issue creation/claiming, and creating worktrees, but +do not edit tracked repository files there. + +Branch folders are ignored by git via `branches/`, so dirty work in one issue +does not block starting an unrelated issue in a separate branch folder. No LLM +may edit another issue's branch folder unless explicitly assigned to that issue. +No LLM may clean another issue's branch folder unless the PR is merged or closed +and cleanup is explicitly part of the task. + +Implementation work and review work must use separate branch folders. For +example, an implementation branch might live under +`branches/fix-issue-123-example`, while a review branch for the resulting PR +uses its own folder. + +Issue creation and claiming may happen from the orchestration checkout: + +1. Create or identify the tracking issue. +2. Claim it with `status:in-progress`. +3. Create the issue branch worktree. +4. `cd` into the branch worktree and perform all file edits there. + +Preferred helper: + +```bash +scripts/worktree-start fix/issue-123-example +cd branches/fix-issue-123-example +``` + +Because `venv/` is ignored and not copied into new worktrees, run checks with a +known Python interpreter. Either create a venv inside the branch folder, or use +the orchestration checkout's venv by explicit path. + +Equivalent manual commands: + +```bash +git fetch prgs --prune +git worktree add -b fix/issue-123-example branches/fix-issue-123-example prgs/master +cd branches/fix-issue-123-example +``` + +For review work, create a separate review worktree/folder instead of reusing the +author's implementation folder. + +Cleanup is explicit and only after merge or close: + +```bash +cd +git fetch prgs --prune +git worktree remove branches/fix-issue-123-example +git branch -d fix/issue-123-example +``` + ### Create an issue / child issues - **Profile:** issue-manager or author (any profile allowed to create issues). @@ -172,9 +228,10 @@ prompt. Confirm the active profile first (`gitea_get_profile` / `gitea_whoami`). ### Implement an issue and open a PR - **Profile:** author. -- **Steps:** claim the issue (`status:in-progress`); branch from latest - `master` (`feat/issue--...` / `fix/...` / `docs/...`); implement narrowly; - add/update tests if behavior changes; run the full suite; commit with an +- **Steps:** claim the issue (`status:in-progress`); create an isolated branch + worktree from latest `master` under `branches/` (`feat/issue--...` / + `fix/...` / `docs/...`); `cd` into that worktree; implement narrowly; add or + update tests if behavior changes; run the full suite; commit with an issue-linked message; open a PR to `master`. **Do not** review or merge your own PR. - **Prompt:** `Use an author profile to implement issue #N and open a PR to diff --git a/scripts/worktree-start b/scripts/worktree-start new file mode 100755 index 0000000..ebd683a --- /dev/null +++ b/scripts/worktree-start @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -euo pipefail + +usage() { + cat <<'EOF' +usage: scripts/worktree-start [--dry-run] [start-ref] + +Create an issue-specific git worktree under branches/. + +Examples: + scripts/worktree-start fix/issue-123-example + scripts/worktree-start --dry-run review/pr-123-scope-check prgs/master +EOF +} + +dry_run=0 +if [[ "${1:-}" == "--dry-run" ]]; then + dry_run=1 + shift +fi + +if [[ $# -lt 1 || $# -gt 2 ]]; then + usage >&2 + exit 2 +fi + +branch="$1" +start_ref="${2:-prgs/master}" + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repo_root="$(cd "$script_dir/.." && pwd)" +worktree_name="${branch//\//-}" +worktree_path="$repo_root/branches/$worktree_name" + +if [[ -e "$worktree_path" ]]; then + cat >&2 <