Files
Gitea-Tools/skills/llm-project-workflow/SKILL.md
T
sysadminandClaude Opus 4.8 c05b2f4c05 docs(skill): load canonical review-merge prompt into workflow file
Replace summary workflow with full §0–§38 canonical PR review/merge rules.
Align review-merge-final-report schema with §37 controller handoff fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-07 03:37:42 -04:00

27 KiB

name, description
name description
llm-project-workflow 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.

LLM Project Workflow

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.

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.

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.

Task mode Workflow Final report schema
review-merge-pr workflows/review-merge-pr.md (canonical; §0–§38) schemas/review-merge-final-report.md
create-issue workflows/create-issue.md (planned — #333) schemas/create-issue-final-report.md (planned)
work-issue workflows/work-issue.md (planned — #333) schemas/work-issue-final-report.md (planned)

Mode isolation:

  • review-merge-pr — reviewer namespace only; no issue creation, no code edits, no approve/merge replay after terminal review
  • create-issue — author namespace; duplicate search + create_issue capability; no PR review/merge
  • work-issue — author namespace; implement, validate, commit, PR; no approve/merge

Shared gate references (all modes): gates/identity-capability-rules.md, gates/mutation-ledger-rules.md, gates/proof-wording-rules.md (planned — #333).

Until create-issue.md and work-issue.md land, author rules remain in this file (§A, §E) and review rules live in workflows/review-merge-pr.md.


Definitions

  • Merged: Gitea PR metadata says merged=true.
  • 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.

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.

Required checks:

  1. List open PRs.
  2. Search for PRs linked to the target issue.
  3. Search local and remote branches for the issue number.
  4. Search registered worktrees for the issue branch.
  5. Check dirty worktrees.
  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.

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.

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.

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.

  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.

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.

B. Isolated worktree rule

Never implement or review in the main checkout (Global LLM Worktree Rule). The main checkout is for orchestration and status only (issue creation, git status, creating worktrees) and must remain on the stable branch.

  • Each issue gets its own branch worktree under an ignored branches/ directory.
  • Review work uses a separate review worktree, never the author's folder.
  • 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.

Every implementation branch must include its issue number so it is traceable end to end: issue → branch → worktree folder → PR → cleanup.

Allowed implementation patterns:

  • 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-<number>-… (or a review/pr-<number>-… 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:

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:

git fetch <remote> --prune
git worktree add -b fix/issue-123-example branches/fix-issue-123-example <remote>/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

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

  1. 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).
  2. Verify the orchestration checkout (right repo, clean tree, on stable branch).
  3. Fetch/prune: git fetch <remote> --prune.
  4. Confirm local master equals remote master (git rev-list --left-right --count <remote>/master...master0 0).
  5. 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.
  6. Create the isolated worktree (§B) from latest remote master.
  7. Implement the narrow scope only — no unrelated refactors or formatting churn.
  8. Add/update focused tests when behavior changes.
  9. 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.
  10. 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.
  11. Commit with an issue-linked message.
  12. 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.
  13. Push the branch.
  14. Open a PR to master. The final report must include the branch proofs from steps 9 and 11 (author_proofs.build_commit_push_report).
  15. If you are the author, stop before review/merge.
  16. Normal issue work must not directly push to master. PR content should be merged through the forge PR merge mechanism.
  17. 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

Moved to workflows/review-merge-pr.md (#334). Load that file for PR inventory, validation, review mutation, merge preflight, cleanup, and reviewer hard walls. Final report: schemas/review-merge-final-report.md.

G. Merge / cleanup workflow

Moved to workflows/review-merge-pr.md §6–§7 and templates/worktree-cleanup.md. Load the workflow file before any merge mutation.

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 <remote>/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 <files>, 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 <sha> and git log <remote>/<branch>.

J. Prompt snippets

Ready-to-copy templates live in templates/:

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):

## Controller Handoff

- Task:
- Repo:
- Role:
- Identity:
- Issue/PR:
- Branch/SHA:
- Files changed:
- Validation:
- Mutations:
- Current status:
- Blockers:
- Next:
- Safety:

Role-specific fields (append to the compact block):

  • review/merge tasks: use schemas/review-merge-final-report.md (includes Selected PR:, Reviewer eligibility:, Pinned reviewed head:, Review decision:, Merge result:, Linked issue status:, Cleanup status:, and precise mutation categories — not Workspace mutations)
  • 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:

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:

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):

## 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

## 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

Adapting to a project

Replace these project-specific names when copying the skill elsewhere:

Placeholder Meaning Example here
<remote> 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.

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):

  1. git fetch <remote> --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 <last-tag>..<remote>/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.