From 6200e6bbecfdd32543b871595664d6c19df42f16 Mon Sep 17 00:00:00 2001 From: Jason Walker <913443@dadeschools.net> Date: Tue, 7 Jul 2026 03:44:21 -0400 Subject: [PATCH] docs: split LLM project workflow into task-specific modes (Closes #333) Consolidate all four canonical workflow files and router SKILL.md: - review-merge-pr.md (from #334 canonical prompt) - reconcile-landed-pr.md (reconciliation gates + handoff schema) - create-issue.md (canonical issue-creation prompt) - work-issue.md (canonical author/coder prompt) SKILL.md is now a short router with mode isolation and universal rules. Adds final-report schemas for all modes and 13 doc-contract tests. Supersedes partial split work in PR #335; full #333 acceptance in one PR. --- skills/llm-project-workflow/SKILL.md | 752 ++--------- .../schemas/create-issue-final-report.md | 46 + .../schemas/reconcile-landed-final-report.md | 53 + .../schemas/review-merge-final-report.md | 82 ++ .../templates/merge-pr.md | 4 + .../templates/review-pr.md | 4 + .../templates/start-issue.md | 3 +- .../workflows/create-issue.md | 666 ++++++++++ .../workflows/reconcile-landed-pr.md | 387 ++++++ .../workflows/review-merge-pr.md | 1153 +++++++++++++++++ tests/test_llm_workflow_split.py | 109 +- 11 files changed, 2568 insertions(+), 691 deletions(-) create mode 100644 skills/llm-project-workflow/schemas/create-issue-final-report.md create mode 100644 skills/llm-project-workflow/schemas/reconcile-landed-final-report.md create mode 100644 skills/llm-project-workflow/schemas/review-merge-final-report.md create mode 100644 skills/llm-project-workflow/workflows/create-issue.md create mode 100644 skills/llm-project-workflow/workflows/reconcile-landed-pr.md create mode 100644 skills/llm-project-workflow/workflows/review-merge-pr.md diff --git a/skills/llm-project-workflow/SKILL.md b/skills/llm-project-workflow/SKILL.md index 89040a8..a47cb6b 100644 --- a/skills/llm-project-workflow/SKILL.md +++ b/skills/llm-project-workflow/SKILL.md @@ -1,85 +1,74 @@ --- name: llm-project-workflow description: >- - Portable, safe operating workflow for LLMs working on any Git/forge project: - issue-first, isolated branch worktrees, no self-review/self-merge, distinct - author/reviewer profiles, cleanup after merge, and fail-closed behavior. - Use at the start of any implementation, review, or merge task on a repo. + Router skill for safe LLM project work: identify task mode, load the matching + canonical workflow file, enforce mode isolation, and emit the correct final + report schema. Use at the start of any implementation, review, merge, + reconciliation, or issue-filing task. --- -# LLM Project Workflow +# LLM Project Workflow Skill -A reusable workflow any LLM can follow to work on any repository safely. Copy -this `skills/llm-project-workflow/` directory into another project unchanged; -adapt only the forge-specific names in [Adapting to a project](#adapting-to-a-project). +This skill is a **router**. Do not perform project work from this file alone. -The core promise: **an LLM never does unsafe or untracked work.** Every change -is tracked by an issue, isolated in its own worktree, reviewed by a different -identity, and cleaned up only after a real merge. +Before any project mutation, identify the task mode and load the matching +workflow file. -## Task mode router (#333) - -**Identify task mode before any mutation.** Load the matching workflow file and -final-report schema; do not apply rules from other modes. +## Workflow modes | Task mode | Workflow | Final report schema | |-----------|----------|---------------------| -| `work-issue` | [`workflows/work-issue.md`](workflows/work-issue.md) (canonical; §0–§30) | [`schemas/work-issue-final-report.md`](schemas/work-issue-final-report.md) | -| `review-merge-pr` | `workflows/review-merge-pr.md` (planned — #334) | `schemas/review-merge-final-report.md` (planned) | -| `create-issue` | `workflows/create-issue.md` (planned — #333) | `schemas/create-issue-final-report.md` (planned) | +| PR review / approval / merge | [`workflows/review-merge-pr.md`](workflows/review-merge-pr.md) | [`schemas/review-merge-final-report.md`](schemas/review-merge-final-report.md) | +| Reconcile already-landed open PRs | [`workflows/reconcile-landed-pr.md`](workflows/reconcile-landed-pr.md) | [`schemas/reconcile-landed-final-report.md`](schemas/reconcile-landed-final-report.md) | +| Create or update Gitea issues | [`workflows/create-issue.md`](workflows/create-issue.md) | [`schemas/create-issue-final-report.md`](schemas/create-issue-final-report.md) | +| Work on an assigned issue / author code | [`workflows/work-issue.md`](workflows/work-issue.md) | [`schemas/work-issue-final-report.md`](schemas/work-issue-final-report.md) | -Mode isolation: +## Universal rules -- **work-issue** — author namespace; implement, validate, commit, PR; no approve/merge -- **review-merge-pr** — reviewer namespace only; no issue creation, no code edits -- **create-issue** — author namespace; duplicate search + `create_issue` capability; no PR review/merge +- Prove identity, active profile, runtime context, and **exact** capability before + mutation. +- A nearby capability does not count. +- Do not self-review or self-merge. +- Do not mix modes in one run. +- If the required workflow cannot be loaded, stop and produce a recovery handoff + only. +- Final report must use the schema for the loaded workflow. +- If a task requires a different mode, stop and produce a handoff for the + correct workflow. -For a full work-issue run, load [`workflows/work-issue.md`](workflows/work-issue.md) -instead of relying on the §E summary below. +## Mode isolation + +A run that starts in `review-merge-pr` mode may not create process issues, +implement fixes, or edit source files. + +A run that starts in `reconcile-landed-pr` mode may not approve, request +changes, merge, implement fixes, or create normal issues. + +A run that starts in `create-issue` mode may not review, approve, request +changes, merge, implement fixes, create branches, commit, push, or create PRs. + +A run that starts in `work-issue` mode may not review, approve, request changes, +merge, close PRs, or act as reviewer. + +If the task requires a different mode, stop and produce a handoff for the +correct workflow. --- - ## Definitions - **Merged**: Gitea PR metadata says `merged=true`. -- **Landed**: Equivalent content is present on remote `master`, but PR metadata may not say merged. +- **Landed**: Equivalent content is present on remote `master`, but PR metadata + may not say merged. - **Closed-not-merged**: PR state is closed and `merged=false`. -- **Reconciled**: A human/LLM verified whether closed-not-merged content landed, partially landed, or was lost, and repaired issue/label/tracker state. - -## A. Issue-first rule - -**No repository change without a tracking issue.** This includes creating, -editing, deleting, or `chmod`-ing files; docs; scripts; commits; pushes; and PRs. - -1. Before any change, confirm a tracking issue exists. -2. If none exists, create one first (title + problem + scope + acceptance). -3. Claim it (assign yourself or apply the `status:in-progress` label) and comment - that work is starting, including the planned branch name. -4. **If the issue cannot be created or claimed, stop.** Do not touch files. - -Reading the repo, running read-only status/`git log`, and creating/claiming the -issue itself are allowed from the orchestration checkout without a prior issue. - -Additional issue-first rules: - -- Do not implement code without an issue unless explicitly authorized. -- **Design-only work uses a discussion/RFC issue** — create one or comment on - the existing one. Design debates belong on the issue, where other LLMs - comment directly. Discussion-only tasks must **not** create branches or PRs; - their comments should include recommendations, risks, open questions, and a - Controller Handoff (§K; compact format unless high-risk). -- **If the repo/tracker home for the work is unclear, stop and ask for an - owner decision.** Do not create a new repository or a new tracker unless - explicitly approved by the owner. +- **Reconciled**: Verified whether closed-not-merged or already-landed content + is present on the target branch; issue/label/tracker state repaired. ## Work Selection Rule for LLMs -Before starting any issue or PR work, acquire or verify a work lease. - -Do not begin coding, reviewing, fixing, branching, committing, pushing, -commenting, or creating a PR until you prove the target is not already being -worked. +Before starting any issue or PR work, acquire or verify a work lease. Do not +begin coding, reviewing, fixing, branching, committing, pushing, commenting, or +creating a PR until you prove the target is not already being worked. Required checks: @@ -91,636 +80,75 @@ Required checks: 6. Check active leases or recent handoffs. 7. Check whether the issue was already completed by a merged PR. -If another active LLM/session owns the lease, stop. - -Allowed responses: - -- continue as the lease owner, -- review the existing PR if reviewer capability allows, -- produce a handoff, -- request takeover after lease expiry, -- stop with "work already claimed." - -Never create a parallel branch or PR for the same issue unless the old branch -is proven abandoned and the takeover is recorded. +If another active session owns the lease, stop with "work already claimed" or +produce a handoff. For Gitea-Tools: `gitea_lock_issue` is the fail-closed lease gate before author 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`. +The main project checkout is a stable control checkout on `master`, `main`, or +`dev`. All LLM task work must happen inside the project's `branches/` directory. -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. +If `cwd` is not inside `branches/`, stop before any file edit, test write, +commit, merge, rebase, or cleanup. The main checkout is orchestration-only. ## Shell Spawn Hard-Stop Rule -A shell tool result of `exit_code: -1` with empty stdout/stderr means the -executor failed to spawn — it is not a command failure, and retrying the same -call cannot succeed. +`exit_code: -1` with empty stdout/stderr means the shell failed to spawn — not a +command failure. After two consecutive spawn failures, hard-stop shell use for +the session and emit a recovery report (#258). -1. On the first spawn failure, run one trivial probe (`echo ok` or `pwd`). - If the probe also fails, mark shell unavailable for the session. -2. After two consecutive spawn failures, hard-stop all further shell tool - use for the session. Never retry the same failing spawn. -3. Stop and emit a recovery report instead of improvising fallbacks. The - report must tell the operator to: restart the session, kill hung - background terminals (a hung test runner is a known contributor), and - prefer MCP-native paths (for example `gitea_commit_files`) for any - remaining mutations. +## Isolated worktree naming -Retry spirals are a real failure mode (issue #258: 100+ tool calls on a -trivial encode-and-commit task). The hard-stop is fail-closed: no shell means -stop-and-report, not workarounds. +Implementation: `(fix|feat|docs|chore)/issue--` -## B. Isolated worktree rule +Review: `review/pr--` -**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. +Worktree folder: branch with `/` replaced by `-` under `branches/`. -- Each issue gets its own branch worktree under an ignored `branches/` directory. -- Review work uses a **separate** review worktree, never the author's folder. -- Dirty work in one branch folder must not block starting another issue. -- No LLM may edit another issue's worktree unless explicitly assigned to it. -- Branch folders are removed only after the PR is merged/closed **and** cleanup - is explicitly part of the task. +Helpers: `scripts/worktree-start`, `scripts/worktree-review`, +`scripts/worktree-clean`. -Every implementation branch **must include its issue number** so it is -traceable end to end: **issue → branch → worktree folder → PR → cleanup.** +## Identity and profile safety -Allowed implementation patterns: +- Author and reviewer identities must be distinct. +- Never place raw tokens in LLM/MCP config. +- Use `gitea_whoami` and `gitea_resolve_task_capability` before mutating. -- `fix/issue-123-short-description` -- `feat/issue-123-short-description` -- `docs/issue-123-short-description` -- `chore/issue-123-short-description` - -Review-only branches: - -- `review/pr-456-short-description` - -Use a filesystem-safe folder under `branches/` by replacing slashes with -hyphens, for example `branches/fix-issue-123-short-description`. - -`scripts/worktree-start` **enforces** this: it rejects an implementation branch -that does not match `(fix|feat|docs|chore)/issue--…` (or a -`review/pr--…` branch), unless `--allow-unlinked` is passed. Traceability -is maintained by: - -- the branch name (contains the issue number), -- a claim comment on the issue, e.g. - `Claimed. Branch: fix/issue-123-short-description. Worktree: branches/fix-issue-123-short-description.`, -- the PR body — `Closes #123` or `Fixes #123` when the PR should close the issue - (do NOT use `Implements #123` or `Refs #123` to close, as Gitea will not auto-close), -- cleanup after merge — remove the remote branch, local branch, and the issue - worktree folder, and drop `status:in-progress`. - -For projects using `Gitea-Tools` helpers: - -```bash -scripts/worktree-start fix/issue-123-example # → branches/fix-issue-123-example -scripts/worktree-review fix/issue-123-example # → branches/review-fix-issue-123-example (detached) -scripts/worktree-clean --delete-branch fix/issue-123-example -``` - -Manual equivalent: - -```bash -git fetch --prune -git worktree add -b fix/issue-123-example branches/fix-issue-123-example /master -cd branches/fix-issue-123-example -``` - -`venv/` and similar are not copied into new worktrees — run checks with a known -interpreter path, or create a venv inside the branch folder. - -## C. Identity and profile safety - -- Use canonical execution profiles where available; the profile is the role, not the LLM. A task selects a profile; a profile is not permanently assigned. -- **Author and reviewer identities must be distinct.** -- Never place raw tokens/passwords in an LLM/MCP client config. Reference secrets by keychain id or environment variable name only. Prefer a single canonical config file selected by two env vars, e.g.: - - `GITEA_MCP_CONFIG` — path to the canonical profiles file - - `GITEA_MCP_PROFILE` — the profile to activate -- **Dual-Profile MCP Launcher Pattern (Recommended):** To avoid relaunch bottlenecks and PR-author deadlocks, register multiple instances of the same MCP server in the client's configuration simultaneously (e.g., `gitea-author` and `gitea-reviewer`), each pointing to its respective `GITEA_MCP_PROFILE`. - - Tool calls become namespace-scoped: `mcp__gitea-author__*` and `mcp__gitea-reviewer__*`. - - **Trust Model:** Separate tokens remain separate. Profile gates enforce allowed operations, `whoami` is still checked, and self-review/self-merge prevention remains mandatory. This pattern is for convenience and does not bypass security gates. - - **Deadlock Warning:** Reviewer/merge identities must not be used to create PRs, as this makes the reviewer the PR author in Gitea and blocks independent review. PRs should normally be created by the author/work identity, keeping the reviewer identity available for reviews. - - **Fallback:** If a dual-server launcher is not available in the client, relaunch or restart the client with the correct profile environment variable before claiming work. -- **If the authenticated user equals the PR author, stop** — no self-review, no self-merge. - -## D. Branch naming - -```text -fix/issue-123-short-description -feat/issue-123-short-description -docs/issue-123-short-description -review/pr-456-scope-check -``` - -Worktree folder = branch with `/` replaced by `-` -(`branches/fix-issue-123-short-description`). - -## E. Start-work workflow - -**Canonical author workflow:** [`workflows/work-issue.md`](workflows/work-issue.md) -(§0–§30). The steps below are a compact summary; load the workflow file for -gates, proof wording, mutation ledger, and controller handoff schema. - -0. Acquire or verify a work lease (Work Selection Rule) — complete all seven - checks before any claim, branch, or PR work. -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). -4b. **Issue lock from your scratch clone (#249):** when using - `gitea_lock_issue`, pass `worktree_path` pointing at your own clean - scratch clone (or set `GITEA_AUTHOR_WORKTREE`). The lock gate validates - *that* path — clean tree on `master`/`main`, no tracked edits yet — - not the shared MCP/orchestration checkout. Another session's dirty - feature branch in the shared dev worktree must not block your lock. - Never stash, reset, or checkout files in the shared worktree to satisfy - the gate. Pass the same `worktree_path` to `gitea_create_pr` so the PR - gate matches the lock record. -5. Create the isolated worktree (§B) from latest remote `master`. -6. Implement the narrow scope only — no unrelated refactors or formatting churn. -7. Add/update focused tests when behavior changes. -8. Run the checks (tests, compile/lint, `git diff --check`, secret scan). - Record the branch name and `HEAD` SHA at validation time — the drift - check in step 9 compares against exactly this state. -9. **Branch proof before commit (#177):** prove and state, immediately - before staging/committing (`author_proofs.verify_branch_for_commit`, - `author_proofs.detect_branch_drift`): - - current branch (`git branch --show-current`) equals the intended - feature branch from the issue claim - - current branch is not `master`, `main`, `develop`, `development`, or - `dev` - - branch and `HEAD` have not changed since validation (step 8) — in a - shared checkout another session may switch branches mid-session; - treat that as expected and **stop before committing** when detected - If any check fails, stop and reconcile; do not commit. -10. Commit with an issue-linked message. -11. **Branch proof before push (#177):** prove that the local branch, the - push target branch, and the intended issue branch all match, and that - none of them is a protected branch - (`author_proofs.verify_push_target`). If a commit accidentally landed - on a protected branch, do **not** push: report the accident and the - exact repair steps (`author_proofs.assess_protected_branch_commit`) — - never silently continue after a repair. -12. Push the branch. -13. Open a PR to `master`. The final report must include the branch proofs - from steps 9 and 11 (`author_proofs.build_commit_push_report`). -14. **If you are the author, stop before review/merge.** -15. **Normal issue work must not directly push to `master`.** PR content should be merged through the forge PR merge mechanism. -16. Direct push to `master` is allowed only as a documented recovery exception. If used, the final report must include: - - why the PR merge path could not be used - - exact commits pushed - - PR metadata state - - issue labels/state repaired - - whether the PR is closed-not-merged - - -## F. Review workflow - -1. Use a separate review worktree (`scripts/worktree-review `), detached. -2. Verify your authenticated identity. -3. Verify the PR author — **you must not be the author.** Self-review - contamination must be *evidence-backed* (#173): state the authenticated - reviewer identity, the PR author identity, whether this session - authored/touched the PR branch, and the evidence source for any - "same-session author" claim. If the evidence is missing, report the - status as **unknown** — never declare contamination by assumption — and - choose another PR or stop (`review_proofs.assess_self_review_contamination`). -4. Verify the worktree is clean. -5. **Checkout proof (#173):** before reviewing or validating, prove and - state: the selected PR head SHA from Gitea (pinned), the local checkout - SHA (`git rev-parse HEAD`), that `HEAD ==` the pinned PR head SHA, and - that the diff base is the PR base branch. If `HEAD` does not match the - pinned head, **stop before review/merge** - (`review_proofs.verify_pinned_head_checkout`). -6. **Inventory proof (#173 + repo disambiguation hardening):** a blind queue - review must prove listing completeness before claiming "only PRs found". - Use repo-name disambiguation: - - "Gitea-Tools" / "gitea tool" / "MCP Gitea tool" / "gitea MCP tool" / - "gitea-tools repo" resolve **only** to `Scaled-Tech-Consulting/Gitea-Tools`. - - "mcp-control-plane" resolves only to `Scaled-Tech-Consulting/mcp-control-plane`. - - Ambiguous ("open PRs", no explicit repo, "MCP Gitea tooling") → inventory - **both** configured repos. - Report must state exactly which repo(s) were checked. If only one checked: - "Only was checked. Other configured repos were not checked. This is - not a complete queue inventory." Never let a single-repo zero hide PRs in - the other. - Both configured repos must be reported with state filter, pagination proof, - and open-PR count (`review_proofs.assess_inventory_completeness` and - `resolve_repos_from_user_reference`). Before inventory, reconcile the - operator-supplied PR backlog against the target repo - (`review_proofs.reconcile_queue_target`); never report `trusted_empty` - for one repo while ignoring contradictory supplied PR numbers in another. -7. **Role-boundary proof (#175):** a reviewer queue task must not silently - become author implementation. If no eligible PR exists, stop with the - queue report. Do not claim issues, create branches, commit, push, or open - PRs unless the operator explicitly retasks the run as author work. Mixed - reviewer+author namespace use must be reported with a justification, and - scratch-only notes are not durable evidence unless posted or committed - intentionally (`review_proofs.assess_role_boundary`). -8. Inspect the full diff; confirm scope matches the linked issue; flag unrelated files. -9. Run the tests. Validation reporting must include the exact command and - exact results: pass/fail, counts of tests passed/skipped/failed, any - ignored paths and why they are safe to ignore, and whether the command - differs from the repository's canonical validation command. Only claim a - validation result after the command has completed and its output has - been read (`review_proofs.assess_validation_report`). - During validation, review work is **read-only**: use - `gitea_dry_run_pr_review` to prove submission mechanics — never post live - APPROVE, REQUEST_CHANGES, or review comments to probe tool paths. After - validation completes, call `gitea_mark_final_review_decision`, then submit - exactly one live review via - `gitea_submit_pr_review(..., final_review_decision_ready=True)`. - After submitting, re-read `gitea_get_pr_review_feedback` and confirm the - verdict is visible (`approval_visible` true for APPROVE; PENDING drafts do - not count — #244). Do not merge until a visible APPROVED review exists. - Final reports must list exactly one review mutation - (`review_proofs.assess_review_mutation_final_report`) unless an - operator-approved correction flow was invoked and explained. -10. **Do not merge if checks fail. Do not merge if the reviewer is the author.** -11. **#179 A-bar proofs** (all fail closed when missing — - `review_proofs.assess_capability_evidence`, `assess_sweep_evidence`, - `assess_live_state_recheck`, `assess_role_boundary`): - - Capability claims must cite exact `gitea_resolve_task_capability` - output (or runtime context); a bare "capability checks passed" is - downgraded. - - The secret/provenance sweep must state the exact command/script/ - pattern/named method and the scope scanned. - - Immediately before submitting a review verdict (and again before any - merge), re-read live PR state and prove: still open, live head == - pinned head, base unchanged, no unresolved blocking review state. - - Reviewer runs stay in the reviewer namespace; any author-namespace - call requires an explicit justification in the report. -12. The final report must distinguish (`review_proofs.build_final_report`): - identity eligible; PR author different from reviewer; session - contamination absent (with evidence); validation performed on the pinned - head; capability evidence; sweep verdict; live-state recheck; role - boundary; merge performed; issue status verified. If any proof is - missing, stop or downgrade the result instead of merging confidently. - -## G. Merge / cleanup workflow - -Only an eligible (non-author) reviewer merges. Before merging: always verify -the authenticated identity **and** the PR author; cite exact capability -evidence for merge_pr (#179); respect runtime profile gates; run independent -validation (do not trust the author's reported results); perform the **final -live-state recheck** (#179 — PR still open, live head == pinned head, base -unchanged, no unresolved blocking review state) immediately before the merge -mutation; and merge with a **pinned head SHA** and, where supported, the -**expected changed-file set**, so a moved head or widened diff refuses the -merge. After a real merge: - -1. Confirm remote `master` actually contains the merge commit or expected squashed changes via post-merge file-presence verification (A PR is not done just because `master` moved or is marked "closed". Verify that expected files added/modified in the PR are actually present on `master` using `git pull`, `git log --oneline -- `, or `git merge-base --is-ancestor`; linked issues are closed; `status:in-progress` is removed). -2. Close/release the issue. -3. Whenever an issue is closed, check for `status:in-progress`: remove it, or report why it could not be removed. -4. Do not delete the remote source branch until: PR `merged=true`, or reconciliation confirms content is safely landed, or the issue owner explicitly abandons the work. -5. Remove the local branch. -6. Remove the branch worktree folder (`scripts/worktree-clean --delete-branch `). Branches/worktrees are cleaned only after the above is verified. -7. Fetch/prune. -8. Confirm the main checkout is clean and current (`0 0` vs remote). -9. Final merge/reconciliation reports must include: PR metadata (state, merged flag, merge commit/hash), Git content (remote master hash, expected content present or not), and the exact post-merge verification method used & results. - -Never run cleanup before the merge is confirmed on remote `master`. - -## H. Fail-closed cases - -**Stop and report — take no mutating action — if:** - -- No issue exists and one cannot be created. -- Worktree state is unclear or unexpected. -- Branch/PR state conflicts with the prompt (e.g. prompt says "merged" but it is not). -- A PR is closed but not merged (closed with `merged=false`). In this case: - - stop normal review/merge - - do not delete branches/worktrees - - do not start dependent work - - run reconciliation -- Local `master` is ahead of remote unexpectedly. -- The authenticated user is the PR author (for review/merge). -- Secrets/tokens appear in the diff. -- Tests fail. -- A cleanup step would delete unmerged work. - -When in doubt, stop and surface the discrepancy; do not guess or work around a gate. - -## I. Recovery patterns - -- **Dirty worktree from another issue:** do not touch it. Start your issue in its - own new worktree; unrelated dirty work must not block you. For Gitea-Tools - author flows, lock the issue from your scratch clone (`worktree_path` on - `gitea_lock_issue`) — do not manipulate the shared dev checkout. -- **Local `master` ahead of remote unexpectedly:** do not push `master`. Confirm - the commits are preserved on a feature branch (local + remote) first, then - `git reset --hard /master` to realign. Never discard commits that are - not safely pushed elsewhere. -- **PR closed but not merged (`merged=false`):** do not merge. Run reconciliation: compare PR content to remote `master` and decide: - - **fully landed:** comment that content is present on `master`, remove `status:in-progress`, keep/close issue as appropriate, clean up only after content equivalence is confirmed. - - **partially landed:** do not clean up, reopen issue if needed, create corrective issue/PR for missing pieces. - - **not landed:** reopen issue if needed, reopen PR or create replacement PR, do not clean up source branch/worktree. -- **Branch deleted before merge:** if the commits still exist locally (a branch or - reflog), re-push them and reopen the PR; otherwise recover via - `git fsck --lost-found`. Preserve first, then proceed. -- **Unauthorized/untracked file created:** do not commit it. Leave pre-existing - untracked artifacts (e.g. editor/agent dirs, reports) alone; stage only the - files your issue names (`git add `, never blind `git add -A`). -- **Preserve commits before a reset:** confirm the target commits are reachable - from a branch that is pushed to the remote, then reset. Verify with - `git branch --contains ` and `git log /`. - -## J. Prompt snippets - -Ready-to-copy templates live in [`templates/`](templates/): - -- [`start-issue.md`](templates/start-issue.md) — start a new issue. -- [`review-pr.md`](templates/review-pr.md) — review a PR. -- [`merge-pr.md`](templates/merge-pr.md) — merge a PR (eligible reviewer only). -- [`recover-bad-state.md`](templates/recover-bad-state.md) — recover from bad state. -- [`reconcile-closed-not-merged-pr.md`](templates/reconcile-closed-not-merged-pr.md) — reconcile a closed-not-merged PR. -- [`worktree-cleanup.md`](templates/worktree-cleanup.md) — clean up after merge. -- [`release-tag.md`](templates/release-tag.md) — create a release tag. - -## K. Controller Handoff (required, every task) - -Every LLM task **must end with a `Controller Handoff`** (exact title) — whether the -task was implementation, review, merge, issue triage, documentation, -discussion-only, or blocked planning. It lets a controller LLM understand the -current state immediately, without rereading the conversation. - -The section title must be exactly "Controller Handoff" (or "Controller Handoff Summary" for long form). Reports without it are downgraded (see review_proofs.assess_controller_handoff). - -**The compact format is the default.** It is written for controller-LLM -readability, not as a full human status report. PR bodies still carry the -full review detail — the handoff never replaces PR documentation. - -Compact format (default, canonical field set per issue #182): - -```md ## Controller Handoff -- Task: -- Repo: -- Role: -- Identity: -- Issue/PR: -- Branch/SHA: -- Files changed: -- Validation: -- Mutations: -- Current status: -- Blockers: -- Next: -- Safety: -``` +Every task must end with a section titled exactly `Controller Handoff`. Compact +format canonical field set per issue #182; mode-specific schemas in +`schemas/*-final-report.md` define required fields. Use the final report schema +for the loaded workflow mode — not the legacy compact block alone. +`review_proofs.assess_controller_handoff()` validates presence. -Role-specific fields (append to the compact block): +## Prompt templates -- review/merge tasks: `Selected PR:`, `Reviewer eligibility:`, - `Pinned reviewed head:`, `Review decision:`, `Merge result:`, - `Linked issue status:`, `Cleanup status:` -- issue-filing tasks (#191): `Issue created or updated:`, `Related issues:`; - body must cite exact issue number/title, duplicate-search summary (issues - searched, closest matches, why update rejected / new issue justified), full - 40-char SHAs when citing commits, exact mutation capability per change, and - `Only mutation(s):` when a single mutation was performed - (`review_proofs.assess_issue_filing_final_report`). -- author tasks: `Selected issue:`, `Claim/comment status:`, - `PR number opened:`, `No review/merge:` (explicit confirmation) -- continuation tasks (#188): `Continuation mode:`, `Existing PR:`, - `PR author:`, `Branch:`, `Old PR head:`, `New PR head:`, - `Session authored PR:`, `Why continuation allowed:` — issues with open - PRs are excluded from fresh selection unless operator explicitly requests - continuation (`review_proofs.classify_issue_for_selection`, - `assess_issue_selection_final_report`) -- queue/inventory tasks: `Repositories checked:`, `Open PR counts:`, - `Selected PR or reason none selected:`, `Inventory completeness:` +Ready-to-copy task prompts live in [`templates/`](templates/): -The section title must be exactly `Controller Handoff`. -`review_proofs.assess_controller_handoff()` validates this section; reports -missing it (or missing required fields) are downgraded. The handoff never -replaces the full report — it is the compact continuation summary at the end, -and the full report must still carry exact validation results and mutation -confirmation. - -The `Safety:` line is never omitted; it is usually: - -```text -no self-review; no self-merge; no tags; no secrets; no prod -``` - -Rules (both formats): - -- Never omit the handoff, and never omit the safety confirmations. -- Never bury blockers in earlier text only — they must appear here. -- If you opened a PR, state clearly that review is needed. -- If you reviewed but could not merge, name the exact gate that blocked it. -- If you only commented on a discussion issue, say no code review is needed - but owner/design feedback may be needed. -- If release state was touched, state exactly which tag/commit changed and why. -- If blocked (permissions, missing repo, missing second reviewer identity, - stale dependency, unclear tracker home): stop and report clearly; **never - bypass classifiers, profile gates, missing permissions, or live-consent - requirements**; give the owner concrete options. - -**Use the long format below instead of the compact one only when the task was -high-risk or complex** — i.e. when any of these happened: - -- a merge, tag, or release -- failed validation -- permissions/profile gates blocked work -- secrets or production access were involved -- a complicated owner decision -- multiple repos or cross-issue state -- the owner explicitly asks for the full format - -Long format (high-risk/complex tasks only): - -```md -## Controller Handoff Summary - -### Work performed - -Briefly state what was done. - -### Current state - -Include: -- current repo -- current branch or master commit -- issue number(s) -- PR number(s), if any -- whether work is complete, blocked, ready for review, or discussion-only - -### Files changed - -List files changed, or say `None`. - -### Validation - -List commands run and results, or say `Not applicable — discussion only`. - -### Issues encountered - -List errors, confusing state, permission/profile problems, stale branches, -failing tests, missing labels, or blocked decisions. - -### Review needed? - -Say one of: -- `No review needed — discussion/comment only` -- `Review needed — PR is open` -- `Independent non-author review needed` -- `Owner decision needed` -- `Blocked` - -### Next recommended action - -State exactly what should happen next. - -### Safety confirmations - -Confirm: -- no self-review -- no self-merge -- no release/tag changes unless explicitly requested -- no secrets committed -- no production access used unless explicitly authorized -``` - -### Example blocked handoff - -```md -## Example blocked handoff - -### Work performed - -Audited phase-2 MCP Control Plane planning. Found target repo -`mcp-control-plane` does not exist. Prepared issue pack but did not file it. - -### Current state - -- Repo: `Scaled-Tech-Consulting/Gitea-Tools`, unmodified -- Target repo: `mcp-control-plane`, missing -- Issues: none open in Gitea-Tools -- PRs: none open -- Status: blocked pending owner decision - -### Files changed - -None. - -### Validation - -Tracker/repo audit only. No code validation required. - -### Issues encountered - -Repo creation was denied by permission/classifier because it would be scope -escalation without live consent. - -### Review needed? - -Owner decision needed. - -### Next recommended action - -Owner must choose: -1. create `Scaled-Tech-Consulting/mcp-control-plane` -2. authorize repo creation while present -3. file phase-2 issues in Gitea-Tools instead - -### Safety confirmations - -- no self-review -- no self-merge -- no release/tag changes -- no secrets committed -- no production access used -``` +- [`start-issue.md`](templates/start-issue.md) — author work (loads `work-issue.md`) +- [`review-pr.md`](templates/review-pr.md) — review (loads `review-merge-pr.md`) +- [`merge-pr.md`](templates/merge-pr.md) — merge (loads `review-merge-pr.md`) +- [`recover-bad-state.md`](templates/recover-bad-state.md) +- [`reconcile-closed-not-merged-pr.md`](templates/reconcile-closed-not-merged-pr.md) +- [`worktree-cleanup.md`](templates/worktree-cleanup.md) +- [`release-tag.md`](templates/release-tag.md) ## Adapting to a project -Replace these project-specific names when copying the skill elsewhere: - -| Placeholder | Meaning | Example here | -|-------------|---------|--------------| -| `` | Git remote for the forge | `prgs` | -| default branch | Integration branch | `master` | -| profile env vars | Canonical config + profile selectors | `GITEA_MCP_CONFIG`, `GITEA_MCP_PROFILE` | -| `branches/` | Ignored worktree directory | `branches/` | -| helper scripts | Worktree helpers | `scripts/worktree-start` / `-review` / `-clean` | - -The rules in §A–§K are project-agnostic and should not change. +| Placeholder | Example here | +|-------------|--------------| +| `` | `prgs` | +| default branch | `master` | +| profile env vars | `GITEA_MCP_CONFIG`, `GITEA_MCP_PROFILE` | +| `branches/` | `branches/` | +| helpers | `scripts/worktree-start` / `-review` / `-clean` | ## Versioning And Tagging -Releases follow SemVer: **`vMAJOR.MINOR.PATCH`** (use **`v0.x.y`** while -unstable). Choose the bump by the largest change since the last tag: - -- **PATCH** — bug fixes, docs, tests, wrappers, non-breaking workflow polish. -- **MINOR** — new tools/helpers/config features; backward-compatible behavior. -- **MAJOR** — breaking config/schema/API behavior or a changed MCP contract. - -Tags must: - -- be created **only from `master`** (the exact commit on remote `master`), -- be created **only after the full test suite passes**, -- be **annotated** tags (`git tag -a`), never lightweight, -- include release notes / a changelog summary referencing the merged PRs/issues. - -**Never tag** feature branches, dirty worktrees, unreviewed or self-authored -work, or commits not present on remote `master`. - -Additional tag rules: - -- Do **not** create, move, delete, or push tags unless explicitly instructed. -- Tag only **after** the intended PR is merged, and tag only the **verified - final master merge commit** (never the PR branch head unless the merge - commit is exactly that commit). -- Always **report the tag target commit** in the final report / handoff. - -Release process (see [`templates/release-tag.md`](templates/release-tag.md)): - -1. `git fetch --prune`. -2. Verify local `master` equals remote `master` (`0 0`) and the tree is clean. -3. Run the full test suite; stop on any failure. -4. Inspect merged issues/PRs since the last tag - (`git log --oneline ../master`). -5. Choose the version bump. -6. Create the annotated tag on remote `master` with release notes. -7. Push the tag. -8. Create/update release notes if the forge supports it. - -Where present, `scripts/release-tag` automates this with all gates built in -(SemVer, fetch/prune, on-master, clean tree, local==remote master, HEAD on -remote master, no duplicate tag, tests, annotated-only). Safe by default: no -push without `--push`; `--dry-run` changes nothing; `--skip-tests` must be -explicit and warns. +Releases follow SemVer from remote `master` only, after full test suite passes. +See [`templates/release-tag.md`](templates/release-tag.md) and +`scripts/release-tag`. \ No newline at end of file diff --git a/skills/llm-project-workflow/schemas/create-issue-final-report.md b/skills/llm-project-workflow/schemas/create-issue-final-report.md new file mode 100644 index 0000000..f35c233 --- /dev/null +++ b/skills/llm-project-workflow/schemas/create-issue-final-report.md @@ -0,0 +1,46 @@ +# Create-issue controller handoff schema + +**Task mode:** `create-issue` + +End every create-issue run with a section titled exactly `Controller Handoff`. +Use this canonical field set. Do not omit fields — use `none` or +`not verified in this session` where appropriate. + +Do not use legacy fields: `Workspace mutations`, `Mutations: None` (when +mutations occurred). + +```md +## Controller Handoff + +- Task: +- Repo: +- Role: +- Identity: +- Active profile: +- Runtime context: +- Requested issue task: +- Workflow source: +- Capability proof: +- Duplicate search terms: +- Duplicate search pagination proof: +- Duplicates found: +- Issues created: +- Issues commented: +- Issues edited: +- Issues skipped as duplicates: +- Labels/assignees/milestones changed: +- File edits by issue creator: +- Worktree/index mutations: +- Git ref mutations: +- MCP/Gitea mutations: +- Issue mutations: +- Label/assignment/milestone mutations: +- External-state mutations: +- Read-only diagnostics: +- Blockers: +- Current status: +- Safe next action: +- Safety statement: +``` + +Identity format: `username / profile` (not personal email unless required — #305). diff --git a/skills/llm-project-workflow/schemas/reconcile-landed-final-report.md b/skills/llm-project-workflow/schemas/reconcile-landed-final-report.md new file mode 100644 index 0000000..d7bf77b --- /dev/null +++ b/skills/llm-project-workflow/schemas/reconcile-landed-final-report.md @@ -0,0 +1,53 @@ +# Reconcile-landed controller handoff schema + +**Task mode:** `reconcile-landed-pr` + +End every reconciliation run with a section titled exactly `Controller Handoff`. +Use this canonical field set. Do not omit fields — use `none` or +`not verified in this session` where appropriate. + +Reject stale author/reviewer fields: `PR number opened`, `Pinned reviewed head`, +`Scratch worktree used`, `Workspace mutations`, `Mutations: None` (when mutations +occurred). + +```md +## Controller Handoff + +- Task: +- Repo: +- Role: +- Identity: +- Active profile: +- Runtime context: +- Selected PR: +- PR live state: +- Candidate head SHA: +- Target branch: +- Target branch SHA: +- Ancestor proof: +- Linked issue: +- Linked issue live status: +- Eligibility class: +- Capabilities proven: +- Missing capabilities: +- PR comments posted: +- Issue comments posted: +- PRs closed: +- Issues closed: +- File edits by reconciler: +- Worktree/index mutations: +- Git ref mutations: +- MCP/Gitea mutations: +- Reconciliation mutations: +- External-state mutations: +- Read-only diagnostics: +- Blockers: +- Current status: +- Safe next action: +- Safety statement: +- No review/merge confirmation: +``` + +Identity format: `username / profile` (not personal email unless required — #305). + +`git fetch` belongs under `Git ref mutations`, not read-only diagnostics (#297). \ No newline at end of file diff --git a/skills/llm-project-workflow/schemas/review-merge-final-report.md b/skills/llm-project-workflow/schemas/review-merge-final-report.md new file mode 100644 index 0000000..237d2f2 --- /dev/null +++ b/skills/llm-project-workflow/schemas/review-merge-final-report.md @@ -0,0 +1,82 @@ +# Review-merge controller handoff schema + +**Task mode:** `review-merge-pr` + +End every review/merge run with a section titled exactly `Controller Handoff`. +Use this canonical field set. Do not omit fields — use `none` or +`not verified in this session` where appropriate. + +Do not use legacy fields: `Pinned reviewed head`, `Scratch worktree used`, +`Workspace mutations`, `Mutations: None` (when mutations occurred). + +```md +## Controller Handoff + +- Task: +- Repo: +- Role: +- Identity: +- Active profile: +- Runtime context: +- Selected PR: +- Linked issue: +- Eligibility class: +- Queue ordering policy: +- Inventory pagination proof: +- Earlier PRs skipped: +- Candidate head SHA: +- Reviewed head SHA: +- Target branch: +- Target branch SHA: +- Already-landed gate: +- Author-safety result: +- Prior request-changes state: +- Review worktree used: +- Review worktree path: +- Review worktree inside branches: +- Review worktree HEAD state: +- Review worktree dirty before validation: +- Review worktree dirty after validation: +- Baseline worktree used: +- Baseline worktree path: +- Files reviewed: +- Validation: +- Official validation integrity status: +- Terminal review mutation: +- Review decision: +- Merge preflight: +- Merge result: +- Linked issue status: +- Main checkout branch: +- Main checkout dirty state: +- Main checkout updated: +- File edits by reviewer: +- Worktree/index mutations: +- Git ref mutations: +- MCP/Gitea mutations: +- Review mutations: +- Merge mutations: +- Cleanup mutations: +- External-state mutations: +- Read-only diagnostics: +- Blockers: +- Current status: +- Safe next action: +- Safety statement: +``` + +### Already-landed handoff overrides + +When eligibility class is `ALREADY_LANDED_RECONCILE_REQUIRED`: + +- Reviewed head SHA: `none` +- Review worktree used: `false` +- Review worktree path: `none` +- Review decision: `none` +- Merge result: `none` + +Identity format: `username / profile` (not personal email unless required — #305). + +Narrative final report and controller handoff must agree on eligibility class, +candidate/reviewed head SHA, mutation state, worktree usage, review decision, +terminal review mutation, merge result, and linked issue status. \ No newline at end of file diff --git a/skills/llm-project-workflow/templates/merge-pr.md b/skills/llm-project-workflow/templates/merge-pr.md index bee3b75..ae99544 100644 --- a/skills/llm-project-workflow/templates/merge-pr.md +++ b/skills/llm-project-workflow/templates/merge-pr.md @@ -5,6 +5,10 @@ Copy, fill the `<...>` fields, and paste as the task prompt. ```text Task: merge PR # for issue # if it is eligible and checks pass. +Load the canonical workflow first: +`skills/llm-project-workflow/workflows/review-merge-pr.md` (task mode: review-merge-pr). +Final report schema: `schemas/review-merge-final-report.md`. + Rules (llm-project-workflow): - Only an eligible, NON-author reviewer merges. If authenticated user == PR author → STOP. diff --git a/skills/llm-project-workflow/templates/review-pr.md b/skills/llm-project-workflow/templates/review-pr.md index 088243b..391f962 100644 --- a/skills/llm-project-workflow/templates/review-pr.md +++ b/skills/llm-project-workflow/templates/review-pr.md @@ -30,6 +30,10 @@ Repo name disambiguation (Gitea-Tools blind review hardening): commit is not valid corroboration. Author-bound sessions must not present reviewer queue inventory as a reviewer decision. +Load the canonical workflow first: +`skills/llm-project-workflow/workflows/review-merge-pr.md` (task mode: review-merge-pr). +Final report schema: `schemas/review-merge-final-report.md`. + Rules (llm-project-workflow): - Review in a SEPARATE detached review worktree, never the author's folder. - Worktree safety (#233): before checkout, diff, validation, review, or merge, diff --git a/skills/llm-project-workflow/templates/start-issue.md b/skills/llm-project-workflow/templates/start-issue.md index 8055966..4b8c159 100644 --- a/skills/llm-project-workflow/templates/start-issue.md +++ b/skills/llm-project-workflow/templates/start-issue.md @@ -5,8 +5,9 @@ Copy, fill the `<...>` fields, and paste as the task prompt. ```text Task: implement . -Canonical workflow: skills/llm-project-workflow/workflows/work-issue.md +Load canonical workflow: skills/llm-project-workflow/workflows/work-issue.md Final report schema: skills/llm-project-workflow/schemas/work-issue-final-report.md +Router: skills/llm-project-workflow/SKILL.md (task mode: work-issue) Rules (llm-project-workflow): - No repo changes without a tracking issue. If none exists, create one first; diff --git a/skills/llm-project-workflow/workflows/create-issue.md b/skills/llm-project-workflow/workflows/create-issue.md new file mode 100644 index 0000000..00f34f8 --- /dev/null +++ b/skills/llm-project-workflow/workflows/create-issue.md @@ -0,0 +1,666 @@ +--- +task_mode: create-issue +canonical: true +final_report_schema: ../schemas/create-issue-final-report.md +--- + +# Create issue workflow (canonical) + +**Task mode:** `create-issue` + +This file is the canonical issue-creation workflow for Gitea-Tools. Load it +before any issue mutation. Final report schema: +[`schemas/create-issue-final-report.md`](../schemas/create-issue-final-report.md). + +**Default task prompt:** + +> Create or update Gitea issues in this project only if every identity, +> capability, duplicate-search, issue-scope, final-report, mutation-ledger, +> and proof-wording gate passes. + +Do not improvise around the gates. Follow project skills, MCP gates, and +workflow rules exactly. + +This is an issue-creation workflow. It is not a reviewer workflow and not an +implementation workflow. + +--- + +## 0. Load the canonical workflow first + +Before starting issue creation or issue update work, check whether the project provides a canonical create-issue workflow through a project skill, runbook, or MCP helper. + +If available, load it first and report: + +* workflow source +* workflow version, commit, or hash +* whether this prompt conflicts with the loaded workflow + +If the canonical workflow cannot be loaded and the project requires it, stop and produce a recovery handoff only. + +## 1. Mode isolation + +This run is `create-issue` mode only. + +Do not: + +* review PRs +* approve PRs +* request changes +* merge PRs +* close PRs +* close issues unless the user explicitly asks and exact close capability is proven +* implement code +* edit repo files +* create branches +* create commits +* push branches +* create PRs +* run tests unless the canonical workflow explicitly requires validation for issue creation +* perform reviewer-only actions +* perform author/coder-only actions +* perform MCP repair + +If the task requires review, merge, issue implementation, or MCP repair mode, stop and produce a handoff for the correct workflow. + +Do not mix modes in one run. + +## 2. Start with live identity, profile, runtime, and capability checks + +Prove: + +* authenticated identity +* active profile +* repo/project +* runtime context +* exact capability for reading/searching issues +* exact capability for creating issues, if creating issues +* exact capability for commenting on issues, if commenting on existing issues +* exact capability for editing issues, if editing existing issues +* exact capability for applying labels, if applying labels +* exact capability for assigning issues, if assigning issues +* exact capability for closing issues, only if explicitly requested + +A nearby capability does not count. + +Examples: + +* `create_issue` does not authorize `issue_comment` +* `issue_comment` does not authorize `create_issue` +* `create_pr` does not authorize `create_issue` +* `review_pr` does not authorize `create_issue` +* `merge_pr` does not authorize `issue_comment` +* `gitea.read` does not authorize creating, commenting, editing, labeling, assigning, or closing issues + +If exact capability cannot be proven, stop and produce a recovery handoff only. + +## 3. Stop immediately on blocked infrastructure + +If any of the following appears, stop immediately: + +* `infra_stop` +* MCP reconnect failure +* stale capability state +* missing capability +* workspace mismatch +* dirty control checkout, if the canonical workflow treats that as blocking +* broken canonical workflow loading +* failed required preflight +* capability resolver warning that says the current state may be unsafe +* stale or inconsistent runtime context + +Do not continue duplicate search, issue creation, issue commenting, issue editing, labeling, assignment, or cleanup. + +Produce an executable recovery handoff only. + +Blocked recovery handoffs must not include direct issue-create or issue-comment replay commands. + +Blocked handoffs must say to rerun the full workflow after the blocker clears. + +## 4. Main checkout rule + +This workflow should not mutate repo files. + +Do not edit files in the main checkout. + +Do not create branches. + +Do not create commits. + +Do not push. + +Do not run implementation work. + +Do not run reviewer validation. + +Reading repository files is allowed only when needed to understand the requested issue and only if the canonical workflow permits it. + +If the main checkout is dirty and the project treats dirty control checkout as blocking, stop and produce a recovery handoff. + +## 5. No raw MCP repair during issue creation + +Do not run `pkill`, kill MCP processes, edit MCP config, restart servers, or perform control-checkout repair during issue creation. + +If MCP repair is required, stop issue creation and produce a separate `CONTROL-CHECKOUT REPAIR MODE` handoff. + +Do not mix MCP repair mode with create-issue mode. + +After repair, rerun the full workflow from the beginning. + +## 6. No background task tools + +Do not use `schedule`, `manage_task`, background jobs, async waits, delayed task tools, or monitoring tasks during issue creation. + +Use direct commands and MCP tools only. + +If a required action cannot complete synchronously, stop and produce a recovery handoff. + +Do not say “I will check later,” “I will monitor,” or “I will continue in the background.” + +## 7. No local Gitea fallback during normal issue creation + +During normal issue-creation workflows, do not read Gitea profile secret files. + +Do not inspect or open files such as: + +* `profiles.json` +* local token stores +* credential files +* local Gitea auth/profile config files +* `.env` files containing Gitea credentials +* keychain dumps +* token helper outputs + +Do not run local Gitea helper scripts when MCP tools are available. + +Use MCP tools for Gitea operations. + +Local fallback is allowed only in explicit recovery mode when MCP is unavailable and identity/profile/capability can be independently proven. + +If local fallback is used, report: + +* why MCP was unavailable +* exact identity proof +* exact profile proof +* exact repo proof +* exact capability proof +* exact local command used + +Do not use local fallback to bypass MCP gates. + +## 8. Understand the requested issue work + +Before searching or creating issues, restate the requested issue-creation task in operational terms. + +Identify: + +* target repo/project +* issue topic +* issue type, if known +* whether this is a new issue, duplicate check, issue update, or issue-comment task +* whether the user provided exact title/body text +* whether acceptance criteria were provided +* whether multiple issues are requested +* whether labels, assignees, milestones, or links are requested +* whether any requested action requires capability beyond issue creation + +Do not invent missing requirements. + +If the request is ambiguous but safe to proceed, make a reasonable best-effort issue with clear assumptions. + +If ambiguity would cause unsafe or wrong mutation, stop and ask for clarification or produce a recovery handoff according to project policy. + +## 9. Duplicate search before mutation + +Before creating any issue, search open and closed issues for duplicates. + +Duplicate search must happen before each issue creation unless a batch search clearly covers all proposed issues. + +Search terms must include: + +* exact proposed issue title +* key noun phrase from the problem +* key workflow/tool name +* key failure phrase or error phrase +* likely alternate wording +* linked PR number, issue number, or file name, if relevant + +If the user supplied search terms, use those too. + +For each proposed issue, report: + +* search terms used +* matching issue numbers/titles +* whether each match is open or closed +* whether any match fully covers the requested issue +* whether any match partially covers the requested issue +* whether a new issue is still needed + +Do not create a duplicate issue if an existing issue fully covers the problem. + +If a duplicate exists and fully covers the problem, stop issue creation for that topic and report the duplicate. + +If a duplicate exists but is missing important acceptance criteria, comment on the existing issue only if exact `issue_comment` capability is proven and the user/task authorizes commenting. + +If commenting is not authorized, report the existing issue and the missing criteria in the final handoff. + +## 10. Issue inventory pagination rule + +If listing/searching issues returns paginated results, follow pagination until the tool proves there are no more pages. + +Do not assume search results or issue inventory are complete. + +Pagination proof must not rely on assumed default API page size. + +Search/inventory is complete only if one of the following is proven: + +* the MCP response explicitly says there is no next page / `has_more=false` / final page +* the workflow traversed pages until an empty page or explicit final page was returned +* the tool response includes total-count or pagination metadata proving all relevant issues were returned +* the request explicitly set `page` / `limit` / `per_page`, and the response explicitly proves the server honored that page size and did not truncate results + +Do not say “duplicate search complete” merely because the result count is less than an assumed default page size. + +If pagination metadata is absent and the tool cannot page, report `ISSUE_SEARCH_PAGINATION_UNPROVEN`. + +If duplicate search cannot be trusted, do not create the issue unless the canonical workflow explicitly permits best-effort issue creation with that limitation disclosed. + +## 11. Issue creation scope rule + +Create only issues within the requested scope. + +Do not create extra issues just because related problems are noticed. + +Do not create process-hardening issues unless the user explicitly requested process-hardening or the current task is explicitly about workflow/tooling gaps. + +Do not create implementation issues during reviewer mode. + +Do not create reviewer issues during work-on-issue mode. + +Do not create issues in a different repository unless the user explicitly asked and exact capability is proven. + +If multiple issues are requested, create only the requested issues and only after duplicate search for each one. + +If a proposed issue is too broad, split it only if the user requested splitting or the canonical workflow requires issue granularity. + +## 12. Issue content quality rule + +Every created issue must be actionable. + +Include, when applicable: + +* title +* problem statement +* observed evidence +* expected behavior +* required behavior +* acceptance criteria +* affected workflow/tool/files +* safety or security considerations +* duplicate search summary +* related issues or PRs +* non-goals, if useful + +Acceptance criteria must be concrete and testable. + +Avoid vague issues like: + +* “make workflow better” +* “fix LLM behavior” +* “improve process” +* “handle this better” + +Instead, describe the exact wall, gate, verifier, test, schema, helper, or prompt change required. + +## 13. Issue title rule + +Use concise, specific titles. + +Good title patterns: + +* `Enforce ` +* `Add verifier for ` +* `Split into ` +* `Block during ` +* `Require before ` + +Avoid titles that are too broad or emotional. + +The title should be unique enough that duplicate search can find it later. + +## 14. Issue body rule + +Issue body must include the full acceptance criteria. + +Do not create placeholder issues. + +Do not create issues with only a title unless the user explicitly requested title-only creation. + +If the user supplied exact issue body text, preserve it unless it contains unsafe instructions, stale facts, or contradictions. + +If edits are needed, make the smallest correction necessary and report the correction. + +Do not silently change requested meaning. + +## 15. Labels, assignees, and metadata + +Apply labels, assignees, milestones, or project fields only if: + +* the user requested them, or +* the canonical workflow requires them, and +* exact capability is proven. + +Do not guess labels if project label policy is unknown. + +If labels are useful but capability or policy is unclear, mention recommended labels in the final report instead of applying them. + +Do not assign issues to people unless explicitly requested or required by project workflow. + +## 16. Comment-on-existing issue rule + +Comment on an existing issue only if: + +* an existing issue partially covers the requested work, or +* the user asked to add information to an existing issue, or +* the canonical workflow requires duplicate consolidation comments, and +* exact `issue_comment` capability is proven. + +Comment must be specific and useful. + +Include: + +* why the existing issue is relevant +* what acceptance criteria or evidence should be added +* whether this avoids creating a duplicate + +Do not comment just to say “duplicate found” unless the project workflow requires it. + +Do not close duplicate issues unless explicitly requested and exact close capability is proven. + +## 17. No hidden mutations + +Do not perform unreported mutations. + +Every issue creation, issue comment, issue edit, label change, assignment, milestone change, close/reopen action, or external-state change must be reported. + +If a tool call is dry-run-only, confirmation-gated, rejected, or no-op, report it separately from performed mutations. + +A dry run is not a mutation. + +A rejected call is not a performed mutation. + +A successful issue creation is an issue mutation. + +A successful issue comment is an issue mutation. + +A successful label/assignment/milestone update is an issue mutation or external-state mutation. + +## 18. Issue creation gate + +Before creating each issue, verify: + +* identity is still valid +* active profile is still valid +* runtime context is still safe +* exact `create_issue` capability is still valid +* duplicate search was completed or limitation was explicitly allowed +* proposed title is not a duplicate +* proposed body includes actionable acceptance criteria +* target repo is correct +* no mode switch has occurred + +If any gate fails, do not create the issue. + +Produce a recovery handoff or duplicate report. + +## 19. Issue commenting gate + +Before commenting on an existing issue, verify: + +* identity is still valid +* active profile is still valid +* runtime context is still safe +* exact `issue_comment` capability is still valid +* target issue number is correct +* comment body is specific and useful +* comment will not duplicate an existing comment +* no mode switch has occurred + +If any gate fails, do not comment. + +Produce a recovery handoff or report the intended comment as a recommendation only. + +## 20. Issue edit/update gate + +Before editing an existing issue, verify: + +* identity is still valid +* active profile is still valid +* runtime context is still safe +* exact edit capability is still valid +* target issue number is correct +* update is explicitly requested or required by canonical workflow +* update does not erase useful existing content +* no mode switch has occurred + +If any gate fails, do not edit. + +Prefer commenting over editing unless the user explicitly requested an edit or the canonical workflow requires issue body updates. + +## 21. Final report must be precise + +Include: + +* canonical workflow source/version/hash, if available +* authenticated identity/profile +* repo/project +* runtime context summary +* exact capability proof summary +* requested issue-creation task +* duplicate search terms used +* duplicate search result +* pagination/final-page proof for issue search, if applicable +* issues created, with issue numbers and URLs +* existing issues commented, with issue numbers and URLs +* existing issues edited, with issue numbers and URLs +* issues skipped as duplicates, with issue numbers and titles +* labels/assignees/milestones applied, if any +* blockers, if stopped +* confirmation that no PR review, approval, request-changes, merge, branch, checkout, commit, push, or repo-file mutation was performed + +If the report and actual tool/command log disagree, fix the report before final output. + +## 22. Final report must distinguish mutation types + +Do not use the legacy field `Workspace mutations`. + +Use only precise categories: + +* File edits by issue creator: +* Worktree/index mutations: +* Git ref mutations: +* MCP/Gitea mutations: +* Issue mutations: +* Label/assignment/milestone mutations: +* External-state mutations: +* Read-only diagnostics: + +Use precise wording: + +* `File edits by issue creator: none` +* `Worktree/index mutations: none` +* `Git ref mutations: none` +* `Issue mutations: ...` + +If no repo files were edited, say: + +`File edits by issue creator: none` + +If no branches/worktrees were touched, say: + +`Worktree/index mutations: none` + +If no git refs were updated, say: + +`Git ref mutations: none` + +Do not hide issue mutations inside vague `MCP/Gitea mutations`. + +## 23. Local artifact and report consistency rule + +Do not create local walkthrough, notes, markdown, JSON, or report artifacts during issue-creation runs unless the canonical workflow or operator explicitly requires it. + +If any file is edited, created, generated, or written, report it under `File edits by issue creator`. + +For each file write, report: + +* exact path +* whether it was inside the repo +* whether it was tracked or untracked +* why it was created +* whether final status was checked after the write + +Do not say `File edits by issue creator: none` if any file write occurred. + +Do not write files after the final clean-status check unless you rerun and report a new final clean-status check. + +Default behavior: do not create local artifacts during issue creation. + +## 24. Forbidden final-report claims unless proven + +Do not claim: + +* `duplicate search complete` +* `no duplicate found` +* `issue created` +* `issue commented` +* `issue updated` +* `label applied` +* `capability proven` +* `runtime safe` +* `all gates passed` +* `no file edits` +* `no unsafe mutation` +* `no PR mutation` +* `no repo mutation` +* `pagination complete` +* `final page` +* `no next page` + +unless the corresponding proof is included. + +If anything blocks safe issue creation or issue update, stop immediately and produce an executable recovery handoff. + +Do not improvise around the gates. + +## 25. Proof wording enforcement + +The following phrases are forbidden unless directly supported by current-session evidence: + +* duplicate search complete +* no duplicate found +* issue created +* issue commented +* issue updated +* labels applied +* capability proven +* runtime safe +* all gates passed +* no file edits +* no unsafe mutation +* no PR mutation +* no repo mutation +* pagination complete +* final page +* no next page + +If the proof comes from prior state rather than a command/tool run in the current session, label it as prior proof, not live proof. + +If a tool call was rejected, confirmation-gated, dry-run-only, or no-op, report it separately from performed mutations. + +## 26. Final self-check before output + +Before final output, check the report for contradictions. + +Verify: + +* if any file was edited, `File edits by issue creator` is not `none` +* if any worktree was added/removed, `Worktree/index mutations` lists it +* if any fetch happened, `Git ref mutations` lists it +* if any issue was created, `Issue mutations` lists it +* if any issue was commented, `Issue mutations` lists it +* if any issue was edited, `Issue mutations` lists it +* if any labels/assignees/milestones were changed, the correct mutation category lists it +* if duplicate search is claimed complete, pagination/final-page proof is present or limitation is disclosed +* if no duplicate is claimed, search terms and results are present +* if issue created is claimed, issue number and URL are present +* if no PR mutation is claimed, no PR tool/action was used +* if no repo mutation is claimed, no branch/worktree/file/commit/push action occurred +* if all gates passed is claimed, every required gate has proof + +If any contradiction exists, fix the final report before output. + +## 27. Controller handoff schema + +End every run with a controller handoff using this schema. + +Do not omit fields. Use `none` or `not verified in this session` where appropriate. + +Controller Handoff: + +* Task: +* Repo: +* Role: +* Identity: +* Active profile: +* Runtime context: +* Requested issue task: +* Workflow source: +* Capability proof: +* Duplicate search terms: +* Duplicate search pagination proof: +* Duplicates found: +* Issues created: +* Issues commented: +* Issues edited: +* Issues skipped as duplicates: +* Labels/assignees/milestones changed: +* File edits by issue creator: +* Worktree/index mutations: +* Git ref mutations: +* MCP/Gitea mutations: +* Issue mutations: +* Label/assignment/milestone mutations: +* External-state mutations: +* Read-only diagnostics: +* Blockers: +* Current status: +* Safe next action: +* Safety statement: + +## 28. Stop conditions summary + +Stop immediately and produce a recovery handoff if: + +* canonical workflow is required but cannot be loaded +* identity/profile/capability cannot be proven +* runtime context is blocked +* infra stop appears +* MCP reconnect fails +* capability state is stale +* duplicate search cannot be performed and best-effort creation is not allowed +* issue search pagination cannot be proven and best-effort creation is not allowed +* duplicate fully covers the requested issue +* requested issue body is unsafe or not actionable +* target repo cannot be proven +* create_issue capability is missing +* issue_comment capability is missing for a required comment +* issue edit capability is missing for a required edit +* mode switch would be required +* any report contradiction cannot be resolved + +Blocked handoffs must not include direct issue-create or issue-comment replay commands. + +Blocked handoffs must say to rerun the full workflow after the blocker clears. + +Do not improvise around the gates. diff --git a/skills/llm-project-workflow/workflows/reconcile-landed-pr.md b/skills/llm-project-workflow/workflows/reconcile-landed-pr.md new file mode 100644 index 0000000..80a7c4b --- /dev/null +++ b/skills/llm-project-workflow/workflows/reconcile-landed-pr.md @@ -0,0 +1,387 @@ +--- +task_mode: reconcile-landed-pr +canonical: true +final_report_schema: ../schemas/reconcile-landed-final-report.md +--- + +# Reconcile already-landed open PR workflow (canonical) + +**Task mode:** `reconcile-landed-pr` + +This file is the canonical reconciliation workflow for open PRs whose head SHA +is already an ancestor of the target branch. Load it before any reconciliation +mutation. Final report schema: +[`schemas/reconcile-landed-final-report.md`](../schemas/reconcile-landed-final-report.md). + +**Default task prompt:** + +> Reconcile already-landed open PRs in this project. Do not review or merge +> normal PRs. Close or comment only when exact capability is proven. + +Do not improvise around the gates. Follow project skills, MCP gates, and +workflow rules exactly. + +This is a reconciliation workflow. It is not a normal PR review/merge workflow. + +--- + +## 0. Load the canonical workflow first + +Before starting reconciliation work, check whether the project provides a +canonical reconcile-landed-PR workflow through a project skill, runbook, or MCP +helper. + +If available, load it first and report: + +* workflow source +* workflow version, commit, or hash +* whether this prompt conflicts with the loaded workflow + +If the canonical workflow cannot be loaded and the project requires it, stop and +produce a recovery handoff only. + +## 1. Mode isolation + +This run is `reconcile-landed-pr` mode only. + +**Do not review or merge normal PRs.** + +Do not: + +* approve PRs +* request changes on PRs +* merge PRs +* implement code +* edit repo files +* create branches +* create commits +* push branches +* create PRs +* run normal PR validation as review approval input +* perform author/coder implementation work +* perform raw MCP repair + +If the task requires review, merge, issue implementation, or MCP repair mode, +stop and produce a handoff for the correct workflow. + +Do not mix modes in one run. + +## 2. Start with live identity, profile, runtime, and capability checks + +Prove: + +* authenticated identity +* active profile (reconciler or author with close capabilities, as required) +* repo/project +* runtime context +* exact capability for reading/listing PRs and issues +* exact capability for PR inspect (`gitea.read` / view PR) +* exact capability for issue inspect +* exact capability for PR comment, if commenting +* exact capability for issue comment, if commenting +* exact capability for PR close, if closing PRs +* exact capability for issue close, if closing issues + +A nearby capability does not count. + +Examples: + +* `review_pr` does not authorize PR close +* `merge_pr` does not authorize PR close or issue close +* `create_issue` does not authorize `issue_comment` +* `issue_comment` does not authorize PR close +* `gitea.read` does not authorize close or comment mutations + +If exact capability cannot be proven, stop and produce a recovery handoff only. + +## 3. Stop immediately on blocked infrastructure + +If any of the following appears, stop immediately: + +* `infra_stop` +* MCP reconnect failure +* stale capability state +* missing capability +* workspace mismatch +* broken canonical workflow loading +* failed required preflight +* capability resolver warning that says the current state may be unsafe +* stale or inconsistent runtime context + +Do not continue inventory, ancestry proof, commenting, closing, or cleanup. + +Produce an executable recovery handoff only. + +Blocked recovery handoffs must not include direct close or comment replay +commands. + +Blocked handoffs must say to rerun the full workflow after the blocker clears. + +## 4. Main checkout rule + +This workflow should not mutate repo files. + +Do not edit files in the main checkout. + +Do not create branches, commits, or pushes. + +Do not run implementation or reviewer validation worktrees for code edits. + +Reading repository files is allowed only when needed to understand +reconciliation scope and only if this workflow permits it. + +## 5. No raw MCP repair during reconciliation + +Do not run `pkill`, kill MCP processes, edit MCP config, restart servers, or +perform control-checkout repair during reconciliation. + +If MCP repair is required, stop and produce a separate `CONTROL-CHECKOUT REPAIR +MODE` handoff. + +After repair, rerun the full workflow from the beginning. + +## 6. No background task tools + +Do not use `schedule`, `manage_task`, background jobs, async waits, delayed task +tools, or monitoring tasks during reconciliation. + +Use direct commands and MCP tools only. + +If a required action cannot complete synchronously, stop and produce a recovery +handoff. + +## 7. No local Gitea fallback during normal reconciliation + +During normal reconciliation workflows, do not read Gitea profile secret files. + +Do not inspect `profiles.json`, local token stores, credential files, `.env` +Gitea credentials, keychain dumps, or token helper outputs. + +Do not run local Gitea helper scripts when MCP tools are available. + +Use MCP tools for Gitea operations. + +Local fallback is allowed only in explicit recovery mode when MCP is unavailable +and identity/profile/capability can be independently proven. + +## 8. Build a complete live open PR inventory + +List open PRs for the target repo according to project policy. + +Follow pagination until the tool proves there are no more pages. + +Do not assume inventory is complete. + +Pagination proof must not rely on assumed default API page size. + +Inventory is complete only if one of the following is proven: + +* the MCP response explicitly says there is no next page / `has_more=false` / + final page +* the workflow traversed pages until an empty page or explicit final page was + returned +* the tool response includes total-count or pagination metadata proving all + relevant PRs were returned +* the request explicitly set `page` / `limit` / `per_page`, and the response + explicitly proves the server honored that page size and did not truncate results + +If pagination cannot be proven, report `INVENTORY_PAGINATION_UNPROVEN` and stop +unless project policy allows best-effort reconciliation with that limitation +disclosed. + +## 9. Already-landed proof + +For each candidate PR, prove whether the PR head SHA is already landed on the +target branch. + +**Already-landed proof** must include: + +* PR number and title +* candidate head SHA (full 40-hex) +* target branch name +* target branch SHA (full 40-hex) after fetch +* ancestor proof method (`git merge-base --is-ancestor`, equivalent forge API, or + documented project helper) +* ancestor proof result (true/false) +* live PR state (open/closed, merged flag) + +Do not classify a PR as already-landed without live ancestor proof. + +If ancestry cannot be proven, classify as `ANCESTRY_UNPROVEN` and skip close +mutations. + +## 10. Linked issue live verification + +If the PR claims to close or link an issue, fetch the linked issue live before +reporting its status. + +If the linked issue was not fetched live in the current session, report: + +`Linked issue status: not verified in this session` + +Do not claim `issue open`, `issue closed`, or `issue resolved` without live +proof. + +## 11. Reconciliation selection rules + +Select PRs eligible for reconciliation: + +* open PR state +* `merged=false` unless project policy says otherwise +* head SHA is ancestor of target branch (already-landed proof passed) +* not selected for normal review/merge in this run + +Eligibility class for selected PRs: `ALREADY_LANDED_RECONCILE_REQUIRED` + +Do not select PRs that fail already-landed proof for normal review/merge +treatment in this mode. + +## 12. Reconciliation comment policy + +Post a reconciliation comment only if: + +* exact PR-comment or issue-comment capability is proven +* the comment adds durable evidence (ancestor proof summary, recommended close + action, linked issue status) +* the comment will not duplicate an equivalent recent reconciliation comment + +If comment capability is missing, record the intended comment in the final +handoff only. + +## 13. PR close rules + +Close a PR only if: + +* already-landed proof passed in this session +* exact PR-close capability is proven +* PR is still open at mutation time (live re-fetch) +* head SHA still matches the proved candidate head SHA + +If PR-close capability is missing, produce a recovery handoff with exact PR, +proof, and required capability. Do not loop forever re-blocking the reviewer +queue. + +## 14. Issue close rules + +Close a linked issue only if: + +* exact issue-close capability is proven +* linked issue was fetched live +* issue resolution is justified by landed content and project policy +* issue is still open at mutation time + +If issue-close capability is missing, report the gap in the handoff. + +## 15. Missing capability behavior + +If any required mutation capability is missing: + +* do not improvise with review/merge tools +* do not ask the operator to bypass capability gates +* produce a recovery handoff listing exact missing capabilities +* include safe next action (profile switch, human close, or dedicated reconciler + profile) + +## 16. Mutation classification + +Use precise mutation categories in the final report: + +* File edits by reconciler: (expect `none`) +* Worktree/index mutations: +* Git ref mutations: (`git fetch` belongs here, not read-only diagnostics) +* MCP/Gitea mutations: +* Reconciliation mutations: (PR comment, issue comment, PR close, issue close) +* External-state mutations: +* Read-only diagnostics: + +Do not use legacy `Workspace mutations`. + +## 17. Identity privacy rule + +Report identity as `username / profile` (#305). + +Do not disclose personal email in final reports unless explicitly required. + +## 18. Precise final report + +Include: + +* canonical workflow source/version/hash +* authenticated identity/profile +* repo/project +* capability proof summary (separate lines for inspect, comment, PR close, + issue close) +* inventory pagination proof +* selected PR(s) with already-landed proof +* linked issue live status +* mutations performed or blocked +* missing capabilities +* confirmation that no normal review, approval, request-changes, or merge was + performed + +## 19. Local artifact and report consistency rule + +Do not create local walkthrough, notes, markdown, JSON, or report artifacts +during reconciliation unless explicitly required. + +If any file is edited, report under `File edits by reconciler`. + +Default: no repo file edits. + +## 20. Forbidden unsupported claims unless proven + +Do not claim: + +* `already-landed` +* `PR closed` +* `issue closed` +* `pagination complete` +* `inventory complete` +* `all gates passed` +* `no unsafe mutation` + +unless the corresponding proof is included. + +## 21. Proof wording enforcement + +Forbidden unless supported by current-session evidence: + +* pagination complete +* final page +* no next page +* PR closed +* issue closed +* all gates passed + +If proof comes from prior state, label as prior proof, not live proof. + +## 22. Final self-check before output + +Verify: + +* no normal review/merge mutations occurred +* `git fetch` is under Git ref mutations if it occurred +* already-landed proof is present for each selected PR +* handoff uses reconciliation schema, not author/reviewer merge schema +* no contradiction between narrative report and controller handoff + +## 23. Controller handoff schema + +End every run with `Controller Handoff` per +[`schemas/reconcile-landed-final-report.md`](../schemas/reconcile-landed-final-report.md). + +## 24. Stop conditions summary + +Stop immediately and produce a recovery handoff if: + +* canonical workflow cannot be loaded +* identity/profile/capability cannot be proven +* runtime context is blocked +* `infra_stop` appears +* inventory pagination cannot be proven and best-effort is not allowed +* already-landed proof cannot be completed +* required close capability is missing and mutation was attempted +* live PR/issue state contradicts proof +* any report contradiction cannot be resolved + +Do not improvise around the gates. \ No newline at end of file diff --git a/skills/llm-project-workflow/workflows/review-merge-pr.md b/skills/llm-project-workflow/workflows/review-merge-pr.md new file mode 100644 index 0000000..86eb359 --- /dev/null +++ b/skills/llm-project-workflow/workflows/review-merge-pr.md @@ -0,0 +1,1153 @@ +--- +task_mode: review-merge-pr +canonical: true +final_report_schema: ../schemas/review-merge-final-report.md +--- + +# Review and merge PR workflow (canonical) + +**Task mode:** `review-merge-pr` + +This file is the canonical PR review/merge workflow for Gitea-Tools. Load it +before any PR mutation. Final report schema: +[`schemas/review-merge-final-report.md`](../schemas/review-merge-final-report.md). + +**Default task prompt:** + +> Review the next eligible open PR in this project. Merge it only if every +> identity, capability, author-safety, inventory, queue-ordering, worktree, +> validation, already-landed, prior-review, final-report, mutation-ledger, +> proof-wording, and merge gate passes. + +Do not improvise around the gates. Follow project skills, MCP gates, and +workflow rules exactly. + +--- + +## 0. Load the canonical workflow first + +Before starting PR work, check whether the project provides a canonical PR review/merge workflow through a project skill, runbook, or MCP helper. + +If available, load it first and report: + +* workflow source +* workflow version, commit, or hash +* whether this prompt conflicts with the loaded workflow + +If the canonical workflow cannot be loaded and the project requires it, stop and produce a recovery handoff only. + +## 1. Start with live identity, profile, runtime, and capability checks + +Prove: + +* authenticated identity +* active reviewer profile +* repo/project +* runtime context +* exact capabilities needed for inventory, review, request-changes, approve, comment, and merge + +A nearby capability does not count. + +Examples: + +* `create_issue` does not authorize `issue_comment` +* `review_pr` does not authorize `merge_pr` +* `issue_comment` does not authorize `create_issue` +* `review_pr` does not authorize `request_changes` unless the capability explicitly covers that operation +* `review_pr` does not authorize `approve` unless the capability explicitly covers that operation + +If capability cannot be proven, stop and produce a recovery handoff only. + +## 2. Stop immediately on blocked infrastructure + +If any of the following appears, stop immediately: + +* `infra_stop` +* MCP reconnect failure +* stale capability state +* dirty control checkout +* dirty review worktree +* missing capability +* workspace mismatch +* stale target branch state +* broken canonical workflow loading +* failed required preflight +* capability resolver warning that says the current state may be unsafe +* stale or inconsistent runtime context + +Do not continue PR selection, validation, review, approval, merge, cleanup, or reconciliation. + +Produce an executable recovery handoff only. + +Blocked recovery handoffs must not include direct approve or merge replay commands. + +Blocked handoffs must say to rerun the full workflow after the blocker clears. + +Do not preserve stale `ready to merge`, `approved`, or `all gates passed` state across MCP failures, reconnects, or capability re-resolution. + +## 3. Author safety + +If you are the PR author, stop immediately. + +Do not approve, request changes, comment as reviewer, merge, close, or mutate the PR. + +Produce a recovery handoff only. + +If author identity cannot be proven, stop and produce a recovery handoff only. + +If authenticated identity changes during the run, restart identity/profile/capability checks before any further mutation. + +## 4. Main checkout rule + +The main project checkout must stay on `master`, `main`, or `dev`. + +Do not review, test, fix, merge, resolve conflicts, or cleanup from the main checkout. + +Do not run tests in the main checkout. + +Do not run baseline validation in the main checkout. + +All PR validation and baseline comparison work must happen under the project’s `branches/` directory. + +No exceptions for small fixes, docs, tests, cleanup, conflict resolution, emergencies, or “just one file.” + +Updating the main checkout is allowed only after a successful merge and only if the project workflow explicitly allows stable-branch update. + +Do not update the main checkout if merge failed, was blocked, or produced reconciliation-only status. + +If the main checkout is dirty before selection, stop and produce a recovery handoff. + +If the main checkout becomes dirty during the run, stop and produce a recovery handoff unless the only change is the explicitly allowed post-merge stable-branch fast-forward. + +## 5. No raw MCP repair during normal review + +Do not run `pkill`, kill MCP processes, edit MCP config, restart servers, or perform control-checkout repair during normal PR review. + +If MCP repair is required, stop PR review and produce a separate `CONTROL-CHECKOUT REPAIR MODE` handoff. + +Do not mix MCP repair mode with PR review/merge mode. + +Do not use successful repair as permission to resume the same review flow. After repair, rerun the full workflow from the beginning. + +## 6. No background task tools + +Do not use `schedule`, `manage_task`, background jobs, async waits, or delayed task tools during PR review/merge. + +Use direct commands and MCP tools only. + +If a required action cannot complete synchronously, stop and produce a recovery handoff. + +Long synchronous commands, such as a test suite, are allowed only if they are run directly and reported with exact command, working directory, and result. + +Do not say “I will check later,” “I will monitor,” or “I will continue in the background.” + +## 7. No local Gitea fallback during normal review + +During normal reviewer workflows, do not read Gitea profile secret files. + +Do not inspect or open files such as: + +* `profiles.json` +* local token stores +* credential files +* local Gitea auth/profile config files +* `.env` files containing Gitea credentials +* keychain dumps +* token helper outputs + +Do not run local Gitea helper scripts when MCP tools are available. + +Use MCP tools for Gitea operations. + +Local fallback is allowed only in explicit recovery mode when MCP is unavailable and identity/profile/capability can be independently proven. + +If local fallback is used, report: + +* why MCP was unavailable +* exact identity proof +* exact profile proof +* exact repo proof +* exact capability proof +* exact local command used + +Do not use local fallback to bypass MCP gates. + +## 8. Build a complete live PR inventory + +List all open PRs. + +Follow pagination until the tool proves there are no more pages. + +Do not assume inventory is complete. + +Do not claim `oldest eligible PR`, `next eligible PR`, or complete queue inventory unless pagination is proven. + +Pagination proof must not rely on assumed default API page size. + +Inventory is complete only if one of the following is proven: + +* the MCP response explicitly says there is no next page / `has_more=false` / final page +* the workflow traversed pages until an empty page or explicit final page was returned +* the tool response includes total-count or pagination metadata proving all open PRs were returned +* the request explicitly set `page` / `limit` / `per_page`, and the response explicitly proves the server honored that page size and did not truncate results + +Do not say “inventory complete” merely because the result count is less than an assumed default page size. + +If the tool returns exactly the requested page size, assume there may be more pages unless the tool proves otherwise. + +If pagination metadata is absent and the tool cannot page, report `INVENTORY_PAGINATION_UNPROVEN` and stop unless the canonical workflow explicitly permits continuing with an incomplete inventory. + +For each open PR, identify: + +* PR number +* title +* author +* base branch +* head branch +* draft/WIP state +* mergeability +* linked issue +* current head SHA +* whether the PR appears already landed + +Final report must include pagination/final-page proof. + +## 9. Queue ordering proof rule + +State the queue ordering policy before selecting a PR. + +If the project uses oldest-first review, explicitly sort or reason by PR number or created date. + +Do not rely on the API response order unless the tool proves that order matches the project policy. + +If newer PRs appear before the selected PR in the API response, explain that they are newer and not earlier in the queue. + +Final report must include: + +* queue ordering policy used +* whether API order matched that policy +* selected PR’s position under that policy +* earlier PRs considered +* earlier PRs skipped and why + +If queue ordering cannot be proven, stop and produce a recovery handoff. + +## 10. Select the next actionable PR using project rules + +Do not review your own PR. + +Do not review stale, draft, blocked, duplicate, already-owned, dependency-blocked, already-landed, already-requested-changes work unless the rules explicitly allow it. + +Do not skip an earlier actionable PR without documenting why. + +Use these terms precisely: + +* `Oldest open PR requiring action` +* `Eligibility class` +* `Next review/merge eligible PR` + +Do not call an already-landed PR `eligible for review` or `eligible for merge`. + +If the oldest open PR is already landed, classify it as: + +`ALREADY_LANDED_RECONCILE_REQUIRED` + +If the oldest open PR is `ALREADY_LANDED_RECONCILE_REQUIRED`, stop normal review immediately unless project policy explicitly allows skipping reconciliation blockers. + +Report: + +`Queue blocked by already-landed PR requiring reconciliation` + +Do not keep rerunning normal review on the same already-landed PR. + +If the selected PR is not the oldest open PR requiring action, report why every earlier PR was not actionable. + +## 11. Skip-prior-PR rule + +Do not skip an earlier open PR without live proof or explicitly labeled prior proof from current-session review feedback. + +If skipping because of prior `REQUEST_CHANGES`, fetch current review feedback and verify the head SHA has not changed since the blocking review. + +If skipping because of non-mergeable status, fetch live PR state and provide conflict proof. + +Report for every skipped earlier PR: + +* skipped PR number +* current head SHA +* blocking category +* blocking review decision, if applicable +* blocking review head SHA, if applicable +* mergeability result, if applicable +* conflict proof command/tool, if applicable +* conflicting files, if available +* whether the head changed after the blocker +* reason it remains blocked + +If blocker proof cannot be fetched, classify the PR as: + +`BLOCKER_STATUS_UNVERIFIED` + +Then stop or produce a recovery handoff according to project policy. + +Do not skip an earlier PR based only on memory from a previous session. + +## 11A. Skipped PRs are read-only + +Skipping an earlier PR must be a read-only classification step. + +Do not submit `REQUEST_CHANGES`, approve, comment, merge, close, or otherwise mutate a skipped PR. + +If an earlier PR already has unresolved `REQUEST_CHANGES` at the same head SHA, do not duplicate the review. Fetch the review feedback, verify the head SHA is unchanged, classify the PR as blocked, and move on only if project policy allows skipping blocked PRs. + +If the head SHA changed after the blocking review, the PR is not safely skippable based on the old blocker. Re-evaluate it according to queue policy. + +The final report must distinguish: + +* prior blocker reused +* blocker revalidated live in this session +* blocker status unverified + +Do not claim live proof unless the proof command or MCP tool ran in the current session. + +If you mutate a skipped PR, stop immediately and report a workflow violation. + +## 12. Non-mergeable skip proof rule + +Do not skip a non-mergeable earlier PR without live proof. + +For every skipped non-mergeable PR, report: + +* PR number +* current head SHA +* mergeability result +* command/tool used to prove conflict +* conflicting files, if available +* whether head changed since any prior blocker + +If conflict proof cannot be retrieved, classify the PR as: + +`MERGEABILITY_UNVERIFIED` + +Then stop or produce a recovery handoff according to project policy. + +Conflict proof must be obtained in a session-owned diagnostic worktree under `branches/`, unless the MCP tool itself provides exact conflict files and proof. + +Do not perform conflict proof in the main checkout. + +## 13. Prior request-changes override rule + +Before approving a PR, fetch current PR review feedback. + +If the PR has a prior `REQUEST_CHANGES` review, report: + +* blocking reviewer +* blocking review timestamp +* blocking review head SHA +* current head SHA +* blocker text +* whether the head changed since the blocker + +If the head changed after the request-changes review, verify the new head addresses the blocker before approving. + +If the head did not change after the request-changes review, do not approve unless you prove one of: + +* the earlier blocker was incorrect +* the validation environment was wrong +* the issue was resolved externally in a way that does not require PR head changes +* project policy explicitly permits overriding that blocker with proof + +If this proof is missing, do not approve. + +If the selected PR still has unresolved `REQUEST_CHANGES` at the same head SHA and no override proof exists, submit `REQUEST_CHANGES` only if no equivalent unresolved request-changes review already exists at that same head SHA. Otherwise stop with a recovery handoff or classify it blocked according to project policy. + +Final report must include the prior blocker, current head, whether head changed, and why approval is safe. + +## 14. Pin the PR head SHA before validation + +Re-fetch the selected PR. + +Record the current head SHA. + +Call this the `candidate head SHA`. + +Do not call it the `reviewed head SHA` until validation and diff review have actually passed. + +If the head SHA changes before review submission or merge, restart review or stop. + +If the head SHA changes after approval but before merge, do not merge. Restart review or stop. + +Final report must include: + +* candidate head SHA +* reviewed head SHA, only if validation and diff review passed +* whether head changed during the run + +## 15. Refresh target branch before ancestry checks + +Fetch the PR target branch from the remote before checking whether the PR head is already landed. + +Do not rely on stale local `master`, `main`, or `dev`. + +Record the fetched target branch SHA used for ancestry checks. + +If the target branch cannot be fetched or verified, stop and produce a recovery handoff. + +`git fetch`, `git remote update`, and any command that updates refs must be reported under `Git ref mutations`, not read-only diagnostics. + +## 16. Already-landed PR gate + +After pinning the PR head SHA and refreshing the target branch, check whether the PR head SHA is already an ancestor of the target branch. + +If the PR head SHA is already landed on the target branch, stop normal review/merge flow. + +Do not approve the PR. + +Do not request changes unless there is a real code/review blocker. + +Do not call the merge API. + +Produce an `ALREADY_LANDED_RECONCILE_REQUIRED` handoff instead. + +The handoff must include: + +* PR number/title +* eligibility class +* candidate head SHA +* reviewed head SHA: `none` +* target branch +* target branch SHA +* ancestor proof +* linked issue status, if verified +* recommended reconciliation action +* required capabilities for reconciliation + +Any close/comment/issue mutation requires separate exact capability proof. + +Do not tell the user or another agent to manually close a PR or issue unless the handoff clearly says capability must be proven first or an authorized human must do it. + +## 17. Linked issue verification + +If the PR claims to close or link an issue, fetch the linked issue live before reporting its status. + +If the linked issue was not fetched live in the current session, report: + +`Linked issue status: not verified in this session` + +Do not claim `issue open`, `issue closed`, or `issue resolved` without live proof. + +Any PR close, issue close, or comment recommendation must say exact capability must be proven first, unless an authorized human performs it. + +The linked issue number in diagnostics, final report, and controller handoff must match the selected PR. + +Do not include stale issue numbers from prior PRs. + +If linked issue status changes after merge, fetch the issue again before reporting post-merge status. + +## 18. Review worktree ownership rule + +Prefer a fresh session-owned review worktree under `branches/`, named like: + +`branches/review-pr-` + +Do not reuse a branch-named or existing worktree unless safe-reuse proof passes. + +Safe-reuse proof must include: + +* exact worktree path +* worktree is inside `branches/` +* worktree is not the main checkout +* worktree is not owned by another active task/session +* clean tracked state +* clean untracked state +* current branch/head before reset +* reset target SHA +* explicit project policy allowing reuse/reset + +Do not run `git reset --hard`, `git clean`, checkout, or other destructive worktree commands unless the worktree is session-owned or safe-reuse proof passes. + +If safe-reuse proof cannot be produced, create a fresh session-owned review worktree. + +## 19. Reviewer worktree no-edit rule + +The PR validation worktree is for validating the submitted PR head only. + +Do not edit files in the PR validation worktree. + +Do not apply local fixes in the PR validation worktree. + +Do not run official validation after modifying the PR validation worktree. + +If you need to test a possible fix, create a separate diagnostic scratch worktree and label it clearly: + +`Diagnostic local experiment — not PR-head validation` + +Any diagnostic edits must be reported under `File edits by reviewer`. + +Diagnostic test results must not be reported as official PR validation results. + +Do not say `File edits by reviewer: none` if any file was edited in any review, diagnostic, baseline, or artifact worktree. + +## 20. Validate in a session-owned worktree under `branches/` + +Prove: + +* exact review worktree path +* worktree is inside `branches/` +* worktree is clean before validation +* PR head is checked out in that worktree +* review worktree HEAD matches candidate head SHA + +Run required validation: + +* tests +* compile checks +* lint checks +* diff checks +* secret/provenance checks +* dangerous artifact checks +* project-specific validation + +If validation fails, request changes with exact blockers, unless an equivalent unresolved request-changes review already exists at the same head SHA. + +If an equivalent unresolved request-changes review already exists at the same head SHA, do not duplicate it. Stop with a final report or recovery handoff according to project policy. + +If validation cannot run, do not approve or merge. + +## 21. Official validation integrity rule + +Record the PR head SHA before validation. + +Prove the validation worktree is clean before validation. + +Run validation against the unmodified PR head. + +After validation, prove the validation worktree is still clean. + +If validation fails, submit `REQUEST_CHANGES` using the unmodified PR-head failure, unless an equivalent unresolved request-changes review already exists at the same head SHA. + +If the worktree was edited after validation for diagnosis, report it separately and do not use post-edit test results as official validation. + +If official validation was contaminated by a local edit, stop and produce a recovery handoff. + +Official validation integrity status must be one of: + +* `passed` +* `failed` +* `not run` +* `contaminated — recovery required` + +Do not invent a softer status. + +## 22. Baseline validation rule + +Do not run tests in the main checkout. + +If the PR full suite fails and you need to compare failures against `master`, create a clean baseline worktree under `branches/`, such as: + +`branches/baseline-master-pr` + +Baseline comparison must include: + +* baseline worktree path +* baseline target SHA +* PR head SHA +* exact command run on both worktrees +* baseline failures +* PR failures +* proof the failure signatures match +* proof the baseline worktree was clean before and after validation +* proof the PR worktree was clean before and after validation + +Do not approve a PR with full-suite failures unless: + +* project policy allows baseline comparison +* baseline proof is complete +* failure signatures match +* new/changed tests pass +* failures are proven unrelated to the PR + +If full-suite failures differ or proof is incomplete, submit `REQUEST_CHANGES`, unless an equivalent unresolved request-changes review already exists at the same head SHA. + +Do not claim “same as master” unless the clean baseline worktree proof is included. + +Do not claim “full-suite failures are pre-existing” unless baseline proof is complete and the failure signatures match. + +## 23. Validation command proof rule + +Report the exact validation command as executed. + +Report the working directory where validation ran. + +If using bare `pytest`, also report: + +* `which pytest` +* `pytest --version` +* whether it resolves to the project venv + +Prefer the project venv executable when available, for example: + +`/Users/jasonwalker/Development/Gitea-Tools/venv/bin/pytest tests/` + +Do not summarize validation as just `pytest passed` unless the exact command, working directory, and result are included. + +For every validation command, report: + +* command +* working directory +* exit code or pass/fail result +* summary count if available +* whether it was official PR-head validation, baseline validation, or diagnostic-only validation + +## 24. Local merge simulation rule + +A local merge simulation is not read-only. + +Commands such as the following must be reported as worktree/index mutations: + +* `git merge --no-commit` +* `git merge --abort` +* `git reset` +* `git checkout` +* `git clean` +* `git worktree add` +* `git worktree remove` + +If merge simulation is needed, prefer a separate session-owned diagnostic worktree. + +If merge simulation is run in the review worktree, prove: + +* worktree clean before simulation +* exact merge command +* result/conflict status +* abort/reset command +* worktree clean after abort + +Do not list merge simulation under read-only diagnostics. + +Do not call the worktree clean after simulation unless clean status was actually checked after abort/reset. + +If conflicting files are reported, they must come from current-session proof. + +## 25. Review the actual diff + +Check: + +* correctness +* tests +* scope +* security boundaries +* workflow rule compliance +* whether the PR really closes or satisfies the linked issue +* unrelated changes +* dangerous generated artifacts +* secrets +* provenance markers +* temporary agent files +* whether the PR is redundant because the diff is already present on the target branch +* whether the PR modifies reviewer workflow, MCP gates, profiles, routing, or authorization boundaries +* whether documentation and tests match behavior + +Do not approve based only on test pass/fail status. Review the diff. + +Report files reviewed. + +## 26. Review decision + +If blockers exist, submit `REQUEST_CHANGES`, unless an equivalent unresolved request-changes review already exists at the same head SHA. + +If non-blocking notes exist, comment clearly only if exact comment capability is proven. + +If everything passes, approve only if exact approve/review capability is proven. + +Do not approve and merge unless both actions are separately authorized. + +Submit review only after dry-run review passes if the tool supports dry run. + +Do not approve already-landed, redundant, stale, or reconciliation-only PRs. + +Do not approve a PR with unresolved prior `REQUEST_CHANGES` unless the prior-request-changes override rule is satisfied. + +Do not submit review mutations on skipped PRs. + +## 26A. Terminal review mutation hard-stop + +A live review mutation is terminal for the current reviewer run except for same-PR merge continuation after approval. + +Terminal review mutations include: + +* `REQUEST_CHANGES` +* `APPROVED` +* review comment submission +* PR comment submission used as review feedback +* any tool that records final review decision state +* any tool that changes PR review state +* any tool that consumes a session review-mutation budget + +After `REQUEST_CHANGES` or blocking feedback, stop immediately and produce the final report. + +After `APPROVED`, continue only to merge preflight and merge for the same selected PR, if merge is authorized and all merge gates pass. + +Do not mutate one PR and then continue reviewing, approving, requesting changes, commenting on, or merging another PR in the same run. + +Do not consume a live review mutation on an earlier skipped PR. + +If a live mutation happens on a non-selected or skipped PR, stop immediately and report the workflow violation. + +If a tool blocks further review mutation because a live mutation already occurred, stop immediately. Do not continue validation of another PR. + +The final report must identify: + +* the terminal mutation +* PR number affected by the terminal mutation +* whether same-PR merge continuation was allowed +* whether the run stopped as required + +## 27. Merge rules + +Before merge, rerun fresh live checks: + +* whoami +* active profile/runtime +* exact merge capability +* author safety +* PR re-fetch +* reviewed head SHA unchanged +* target branch freshly fetched +* PR still open +* PR still mergeable +* PR head is not already landed +* required checks still pass +* linked issue handling is correct +* review worktree is clean + +Merge only after all gates pass. + +Do not merge if: + +* MCP reconnect failed +* capability state is stale +* worktree is dirty +* PR head changed +* validation failed +* inventory was incomplete +* PR is already landed +* target branch is stale +* you are the PR author +* prior request-changes override proof is missing +* terminal review mutation occurred on a different PR earlier in the run +* final decision was not marked for the selected PR, if the workflow requires final-decision marking + +If the merge tool requires an explicit confirmation string, report: + +* first gated/no-op call, if any +* confirmation string used +* which call actually performed the merge + +Rejected, dry-run, or confirmation-gated merge calls must not be reported as performed merge mutations. + +## 28. After merge + +Confirm: + +* merge result +* target branch updated +* merged commit/SHA, if available +* selected PR head SHA is now ancestor of target branch +* linked issue status if the PR claims to close an issue + +Clean only the session-owned `branches/` review worktree if the project workflow explicitly allows cleanup. + +Do not delete or mutate unrelated branches/worktrees. + +Do not touch the main checkout except to update the stable branch after merge if explicitly allowed by the workflow. + +Any stable-branch update after merge is a git mutation and must be reported. + +Do not update the main checkout if merge failed, was blocked, or produced reconciliation-only status. + +If any local artifact is created after final cleanup, run and report a new final status check. + +## 29. Recovery handoff rules + +If blocked, produce a recovery handoff with: + +* exact blocker +* failed tool/function, if any +* repo/project +* selected PR, if one was safely selected +* eligibility class +* candidate head SHA, if known +* reviewed head SHA, only if validation and diff review passed +* target branch and target branch SHA, if known +* linked issue status, or `not verified in this session` +* worktree path, if created +* exact state reached before stopping +* safe next action +* statement that no unsafe mutation was attempted + +Blocked handoffs must not include direct approve or merge replay commands. + +Blocked handoffs must say to rerun the full workflow after the blocker clears. + +If the blocker is a terminal review mutation already consumed in the current run, the handoff must say that the next run must start from the beginning and must not reuse stale ready/approved state. + +## 30. Final report must be precise + +Include: + +* canonical workflow source/version/hash, if available +* authenticated identity/profile +* repo/project +* complete PR inventory proof, including pagination/final-page proof +* queue ordering policy used +* selected PR number/title/author +* eligibility class +* author-safety result +* skipped earlier PRs and live blocker proof or prior blocker proof, if any +* prior request-changes proof, if any +* candidate head SHA +* target branch and target branch SHA used for ancestry checks +* reviewed head SHA, only if validation and diff review passed +* already-landed gate result +* linked issue proof/status, if applicable +* main checkout branch +* main checkout dirty state +* review worktree used: true/false +* review worktree path +* review worktree inside `branches/`: true/false +* review worktree HEAD state: detached/branch/none +* review worktree dirty before validation: true/false/not applicable +* review worktree dirty after validation: true/false/not applicable +* baseline validation worktree, if used +* baseline validation result, if used +* files reviewed +* validation commands and results +* official validation integrity status +* diagnostic scratch experiments, if any +* local merge simulation result, if any +* review decision +* terminal review mutation, if any +* merge preflight results, if merge was attempted +* merge result, if merged +* cleanup result +* blockers, if stopped +* confirmation that the main checkout was not used for task work +* final proof that no unsupported proof wording is used + +If the report and actual tool/command log disagree, fix the report before final output. + +## 31. Final report must distinguish mutation types + +Do not use the legacy field `Workspace mutations`. + +Use only precise categories: + +* File edits by reviewer: +* Worktree/index mutations: +* Git ref mutations: +* MCP/Gitea mutations: +* Review mutations: +* Merge mutations: +* Cleanup mutations: +* External-state mutations: +* Read-only diagnostics: + +`git fetch`, `git remote update`, and any command that updates refs must be listed under `Git ref mutations`, not read-only diagnostics. + +If `git reset --hard`, checkout, clean, worktree add/remove, merge simulation, merge abort, or similar commands occurred, report them under `Worktree/index mutations`. + +Use precise wording: + +* `File edits by reviewer: none` +* `Worktree/index mutations: ...` +* `Git ref mutations: ...` +* `MCP/Gitea mutations: ...` + +Do not collapse review, merge, cleanup, or external-state mutations into vague wording. + +## 31A. Local artifact and report consistency rule + +Do not create local walkthrough, notes, markdown, JSON, or report artifacts during reviewer runs unless the canonical workflow or operator explicitly requires it. + +If any file is edited, created, generated, or written, report it under `File edits by reviewer`. + +For each file write, report: + +* exact path +* whether it was inside the repo +* whether it was tracked or untracked +* why it was created +* whether final `git status` was run after the write + +Do not say `File edits by reviewer: none` if any file write occurred. + +Do not write files after the final clean-status check unless you rerun and report a new final clean-status check. + +If the action log says `Edited`, `Created`, `Wrote`, or equivalent, the mutation ledger must include that file. + +If the file was created outside the repo, still report it under `File edits by reviewer` and label it `outside repo`. + +If the file was created inside the repo, report whether it is tracked or untracked. + +If an artifact was created only for operator handoff, state that explicitly. + +Default behavior: do not create `walkthrough.md` or similar artifacts unless the workflow explicitly requires it. + +## 32. Controller handoff consistency rule + +The controller handoff must use the same canonical schema and facts as the final report. + +If the already-landed gate fires, the controller handoff must include: + +* Eligibility class: `ALREADY_LANDED_RECONCILE_REQUIRED` +* Candidate head SHA: +* Reviewed head SHA: `none` +* Review worktree used: `false` +* Review worktree path: `none` +* Git ref mutations: +* Review decision: `none` +* Merge result: `none` + +Do not use these legacy fields: + +* `Pinned reviewed head` +* `Scratch worktree used` +* `Workspace mutations` +* `Mutations: None` when any git ref, MCP, Gitea, review, merge, cleanup, or external-state mutation occurred + +The narrative report and controller handoff must agree on: + +* eligibility class +* candidate head SHA +* reviewed head SHA +* mutation state +* worktree usage +* review decision +* terminal review mutation +* merge result +* linked issue status + +If they disagree, fix the report before final output. + +## 33. Forbidden final-report claims unless proven + +Do not claim: + +* `oldest eligible PR` +* `next eligible PR` +* `reviewed head SHA` +* `ready to merge` +* `workspace mutations none` +* `scratch worktree false` +* `all gates passed` +* `inventory complete` +* `already landed` +* `merged` +* `issue closed` +* `manual close required` +* `target branch up to date` +* `read-only merge simulation` +* `no file edits by reviewer` +* `same as master` +* `full-suite failures are pre-existing` +* `prior request-changes resolved` +* `local fallback was safe` +* `live proof` +* `live blocker proof` +* `skipped PR` +* `terminal mutation none` +* `no unsafe mutation` + +unless the corresponding proof is included. + +If anything blocks safe review or merge, stop immediately and produce an executable recovery handoff. + +Do not improvise around the gates. + +Do not preserve stale `ready to merge` state across MCP failures or reconnects. + +Do not include approve or merge replay commands in a blocked handoff. Say to restart the full workflow after the blocker clears. + +## 34. Proof wording enforcement + +The following phrases are forbidden unless directly supported by current-session evidence: + +* live proof +* live blocker proof +* inventory complete +* same as master +* no file edits +* full-suite failures are pre-existing +* issue closed +* merged +* target branch up to date +* all gates passed +* next eligible PR +* oldest eligible PR +* no unsafe mutation +* worktree clean +* linked issue verified +* PR still mergeable +* head unchanged +* final page +* no next page + +If the proof comes from prior review feedback rather than a command/tool run in the current session, label it as prior proof, not live proof. + +If relying on prior review feedback at unchanged head SHA, say: + +`Prior blocker reused; head SHA unchanged since blocking review.` + +Do not say: + +`Live blocker proof` + +unless the blocker was actually revalidated in the current session. + +If a tool call was rejected, confirmation-gated, dry-run-only, or no-op, report it separately from performed mutations. + +A dry run is not a mutation. + +A confirmation-gated rejected call is not a performed mutation. + +A successful merge call is a merge mutation. + +A successful review submission is a review mutation. + +A final-decision marking call is a review mutation if it records durable review state or consumes review-mutation budget. + +## 35. Duplicate request-changes prevention + +Before submitting `REQUEST_CHANGES`, fetch current review feedback. + +If an unresolved `REQUEST_CHANGES` review already exists at the same head SHA with the same blocker, do not submit another `REQUEST_CHANGES`. + +Report: + +* prior blocking reviewer +* prior blocking timestamp +* prior blocking head SHA +* current head SHA +* blocker text +* why the blocker still applies +* that no duplicate review mutation was submitted + +If the head SHA changed or the old blocker is not equivalent, evaluate normally. + +Do not consume the session’s review mutation budget just to duplicate an existing blocker. + +## 36. Final self-check before output + +Before final output, check the report for contradictions. + +Verify: + +* if any file was edited, `File edits by reviewer` is not `none` +* if any worktree was added/removed, `Worktree/index mutations` lists it +* if any fetch happened, `Git ref mutations` lists it +* if any review was submitted, `Review mutations` lists it +* if any merge was performed, `Merge mutations` lists it +* if any cleanup happened, `Cleanup mutations` lists it +* if any issue/PR external state changed, `External-state mutations` lists it +* if pagination is claimed complete, final-page proof is present +* if live proof is claimed, the proof ran in the current session +* if same-as-master is claimed, baseline proof is complete +* if issue closed is claimed, linked issue was fetched after merge +* if merged is claimed, merge result and target ancestry proof are present +* if selected PR is claimed next eligible, every earlier PR has proof-backed skip reasoning +* if a terminal mutation happened, no other PR was reviewed or mutated afterward + +If any contradiction exists, fix the final report before output. + +## 37. Controller handoff schema + +End every run with a controller handoff using this schema. + +Do not omit fields. Use `none` or `not verified in this session` where appropriate. + +Controller Handoff: + +* Task: +* Repo: +* Role: +* Identity: +* Active profile: +* Runtime context: +* Selected PR: +* Linked issue: +* Eligibility class: +* Queue ordering policy: +* Inventory pagination proof: +* Earlier PRs skipped: +* Candidate head SHA: +* Reviewed head SHA: +* Target branch: +* Target branch SHA: +* Already-landed gate: +* Author-safety result: +* Prior request-changes state: +* Review worktree used: +* Review worktree path: +* Review worktree inside branches: +* Review worktree HEAD state: +* Review worktree dirty before validation: +* Review worktree dirty after validation: +* Baseline worktree used: +* Baseline worktree path: +* Files reviewed: +* Validation: +* Official validation integrity status: +* Terminal review mutation: +* Review decision: +* Merge preflight: +* Merge result: +* Linked issue status: +* Main checkout branch: +* Main checkout dirty state: +* Main checkout updated: +* File edits by reviewer: +* Worktree/index mutations: +* Git ref mutations: +* MCP/Gitea mutations: +* Review mutations: +* Merge mutations: +* Cleanup mutations: +* External-state mutations: +* Read-only diagnostics: +* Blockers: +* Current status: +* Safe next action: +* Safety statement: + +## 38. Stop conditions summary + +Stop immediately and produce a recovery handoff if: + +* canonical workflow is required but cannot be loaded +* identity/profile/capability cannot be proven +* authenticated identity is the PR author +* runtime context is blocked +* infra stop appears +* MCP reconnect fails +* capability state is stale +* inventory pagination cannot be proven +* queue ordering cannot be proven +* earlier PR blocker status cannot be verified +* selected PR is already landed +* target branch cannot be fetched +* linked issue cannot be verified when required for decision +* review worktree is dirty +* validation cannot run +* validation fails and request-changes cannot be safely submitted +* baseline comparison is required but incomplete +* prior request-changes override proof is missing +* PR head changes before review or merge +* merge preflight fails +* terminal review mutation occurs on a different PR +* any report contradiction cannot be resolved + +Blocked handoffs must not include direct approve or merge replay commands. + +Blocked handoffs must say to rerun the full workflow after the blocker clears. + +Do not improvise around the gates. diff --git a/tests/test_llm_workflow_split.py b/tests/test_llm_workflow_split.py index c690c73..327b17d 100644 --- a/tests/test_llm_workflow_split.py +++ b/tests/test_llm_workflow_split.py @@ -3,43 +3,96 @@ from pathlib import Path REPO_ROOT = Path(__file__).resolve().parent.parent SKILL_DIR = REPO_ROOT / "skills" / "llm-project-workflow" +SKILL = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8") -def test_work_issue_workflow_file_exists(): - path = SKILL_DIR / "workflows" / "work-issue.md" - text = path.read_text(encoding="utf-8") +def test_skill_md_exists(): + assert SKILL_DIR.joinpath("SKILL.md").is_file() + + +def test_all_workflow_files_exist(): + for name in ( + "review-merge-pr.md", + "reconcile-landed-pr.md", + "create-issue.md", + "work-issue.md", + ): + assert (SKILL_DIR / "workflows" / name).is_file(), name + + +def test_skill_references_all_workflow_files(): + for name in ( + "workflows/review-merge-pr.md", + "workflows/reconcile-landed-pr.md", + "workflows/create-issue.md", + "workflows/work-issue.md", + ): + assert name in SKILL + + +def test_skill_contains_mode_isolation_language(): + assert "## Mode isolation" in SKILL + assert "review-merge-pr" in SKILL + assert "reconcile-landed-pr" in SKILL + assert "create-issue" in SKILL + assert "work-issue" in SKILL + assert "Do not mix modes" in SKILL or "do not mix modes" in SKILL.lower() + + +def test_skill_is_router_not_monolithic_review_body(): + assert "This skill is a **router**" in SKILL or "router" in SKILL.lower() + assert "## F. Review workflow" not in SKILL + assert "gitea_mark_final_review_decision" not in SKILL + assert "gitea_submit_pr_review" not in SKILL + + +def test_review_merge_workflow_contract(): + text = (SKILL_DIR / "workflows" / "review-merge-pr.md").read_text(encoding="utf-8") assert "canonical: true" in text - assert "work-issue" in text - assert "## 0. Load the canonical workflow first" in text - assert "## 29. Controller handoff schema" in text - assert "## 30. Stop conditions summary" in text - assert "ISSUE_ELIGIBILITY_UNVERIFIED" in text - assert "OPEN_PR_EXISTS" in text - assert "author/coder workflow" in text.lower() + assert "## 26A. Terminal review mutation hard-stop" in text + assert "## 11A. Skipped PRs are read-only" in text + assert "## 35. Duplicate request-changes prevention" in text + assert "ALREADY_LANDED_RECONCILE_REQUIRED" in text -def test_work_issue_final_report_schema_exists(): - path = SKILL_DIR / "schemas" / "work-issue-final-report.md" - text = path.read_text(encoding="utf-8") - assert "Controller Handoff" in text - assert "Issue inventory pagination proof:" in text - assert "File edits by author:" in text - assert "Workspace mutations" in text # documented as rejected +def test_reconcile_landed_workflow_contract(): + text = (SKILL_DIR / "workflows" / "reconcile-landed-pr.md").read_text(encoding="utf-8") + assert "canonical: true" in text + assert "Do not review or merge normal PRs" in text + assert "Already-landed proof" in text -def test_skill_router_points_to_work_issue_workflow(): - skill = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8") - assert "## Task mode router" in skill - assert "workflows/work-issue.md" in skill - assert "schemas/work-issue-final-report.md" in skill - assert "Identify task mode before any mutation" in skill +def test_create_issue_workflow_contract(): + text = (SKILL_DIR / "workflows" / "create-issue.md").read_text(encoding="utf-8") + assert "canonical: true" in text + assert "## 9. Duplicate search before mutation" in text -def test_skill_still_declares_controller_handoff_contract(): - skill = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8") - assert "## Controller Handoff" in skill - assert "assess_controller_handoff" in skill - assert "## Global LLM Worktree Rule" in skill +def test_work_issue_workflow_contract(): + text = (SKILL_DIR / "workflows" / "work-issue.md").read_text(encoding="utf-8") + assert "canonical: true" in text + assert "Do not merge your own PR" in text + assert "## 21. PR creation rules" in text + + +def test_final_report_schemas_exist(): + for name in ( + "review-merge-final-report.md", + "reconcile-landed-final-report.md", + "create-issue-final-report.md", + "work-issue-final-report.md", + ): + assert (SKILL_DIR / "schemas" / name).is_file(), name + + +def test_review_pr_template_references_workflow(): + text = (SKILL_DIR / "templates" / "review-pr.md").read_text(encoding="utf-8") + assert "workflows/review-merge-pr.md" in text + + +def test_merge_pr_template_references_workflow(): + text = (SKILL_DIR / "templates" / "merge-pr.md").read_text(encoding="utf-8") + assert "workflows/review-merge-pr.md" in text def test_start_issue_template_references_work_issue_workflow():