Files
Gitea-Tools/skills/llm-project-workflow/SKILL.md
T
sysadmin 8bff54d5ac feat: enforce issue-linked branches + document versioning/tagging policy (#48)
Formalize the branch↔issue relationship and add a release/version-tagging policy.

Branch/issue linkage:
- scripts/worktree-start now validates branch names: implementation branches
  must match (fix|feat|docs|chore)/issue-<number>-<slug>; review branches
  review/pr-<number>-<slug>. Untraceable names are rejected with a clear error
  (exit 2). New --allow-unlinked override for genuine exceptions. --dry-run
  preserved.
- Documented issue → branch → worktree → PR → cleanup traceability in the
  runbook and the portable SKILL, including the claim-comment convention and
  Closes #n / Refs #n PR-body usage.
- Noted that Gitea exposes no native issue→branch API field (only a PR head
  branch), so linkage is enforced via branch name + claim comment + PR body +
  cleanup.

Versioning / tagging policy (docs only; no release automation yet):
- SemVer vMAJOR.MINOR.PATCH (v0.x.y while unstable) with PATCH/MINOR/MAJOR bump
  rules.
- Annotated tags only, from the exact commit on remote master, only after the
  full suite passes, with release notes referencing merged PRs/issues. Never tag
  feature branches, dirty worktrees, unreviewed/self-authored work, or commits
  not on remote master.
- Release runbook in the runbook + SKILL, plus a new
  skills/llm-project-workflow/templates/release-tag.md prompt template.

Tests: worktree-start branch validation — accepts fix/feat/docs/chore/issue-*
and review/pr-*, rejects fix/random-name / my-branch / non-numeric issue,
honors --allow-unlinked, preserves --dry-run. Full suite 291 passed / 0 failures;
bash -n clean; git diff --check clean; no secrets.

Release-tag automation (a scripts/release-tag helper) intentionally deferred to a
later issue to keep this diff narrow and testable.

Closes #48. Refs #38, #39, #46.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 03:41:59 -04:00

10 KiB

LLM Project Workflow

Use this skill when an LLM is asked to create issues, implement repository changes, review pull requests, merge pull requests, or recover from unsafe git state in any project.

This skill is intentionally portable. Replace the remote name, default branch, profile names, and repository URL conventions with the target project's local standards, but keep the safety rules intact.

Core Rule

No repository change happens without a tracking issue first.

Repository changes include creating files, editing files, deleting files, changing executable bits, changing documentation, adding scripts, changing config, committing, pushing, and opening pull requests.

If no issue exists, create one before touching the repository. If issue creation or issue claiming fails, stop immediately and report the blocker.

Worktree Isolation

Never implement or review directly in the main checkout.

The main checkout is for orchestration only: status checks, issue creation, issue claiming, fetching, and creating branch worktrees. Each issue gets a separate branch worktree under an ignored branches/ directory. Review work gets its own separate review worktree.

Dirty work in one branch folder must not block unrelated work in another branch folder. No LLM may edit or clean another issue's worktree unless explicitly assigned to that issue and cleanup is part of the task.

Branch Naming

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 when the PR should close the issue, Refs #123 when related but not closing,
  • cleanup after merge — remove the remote branch, local branch, and the issue worktree folder, and drop status:in-progress.

Forges like Gitea do not expose a native issue→branch association through the API (only a PR's head branch), so linkage is enforced by the branch name, claim comment, PR body, and cleanup process above — not a dedicated API field.

Worktree Creation

Generic pattern:

git fetch <remote> --prune
git worktree add -b <branch> branches/<safe-branch-folder> <remote>/master
cd branches/<safe-branch-folder>

For Gitea-Tools specifically:

./scripts/worktree-start fix/issue-123-example
cd branches/fix-issue-123-example

If the default branch is not master, use the target project's default branch. If local master is ahead of the remote unexpectedly, stop before creating the worktree and ask for explicit recovery instructions.

Identity And Profile Safety

Use canonical execution profiles where available. The profile is the role; the LLM is not permanently an author, reviewer, or merger.

Author and reviewer identities must be distinct. Before review, approval, merge, or branch cleanup, verify both the authenticated user and the PR author. If the authenticated user is the PR author, stop immediately.

Never place raw tokens or passwords in LLM configs, prompts, commits, PR comments, logs, or tool outputs. Prefer profile references such as:

  • GITEA_MCP_CONFIG
  • GITEA_MCP_PROFILE

If identity cannot be determined, fail closed. Do not approve, merge, close, or clean up with an unknown identity.

Implementation Workflow

  1. Verify the request has a tracking issue. If not, create one.
  2. Claim the issue using the project's in-progress convention, such as status:in-progress.
  3. Fetch/prune and confirm the local default branch matches the remote default branch.
  4. Create an issue-specific branch worktree from the latest remote default branch.
  5. Implement only the issue scope inside that worktree.
  6. Run focused checks and the project's required full checks.
  7. Inspect the diff for scope, secrets, and unrelated files.
  8. Commit.
  9. Push.
  10. Open a PR to the default branch.
  11. Stop before review or merge if you authored the PR.

Review Workflow

  1. Use a separate review worktree.
  2. Verify authenticated identity.
  3. Verify PR author.
  4. Stop if authenticated identity matches the PR author.
  5. Verify the PR is open and targets the expected base branch.
  6. Verify the PR head matches the reviewed commit or includes it.
  7. Verify the review worktree is clean.
  8. Inspect changed files and diff against the linked issue scope.
  9. Run required tests and checks.
  10. Inspect for secrets, credential paths, raw environment dumps, unrelated work, and disallowed behavior.
  11. If checks fail, leave exact blockers and do not approve or merge.
  12. If checks pass and the reviewer is eligible, approve or leave the requested review comment according to the task.

Merge And Cleanup Workflow

Only merge when assigned merge duty and reviewer-eligible.

After an eligible merge:

  1. Confirm the PR is still open and targets the expected base branch.
  2. Confirm the PR head is still the reviewed commit or includes it.
  3. Confirm the authenticated user is not the PR author.
  4. Merge through the project's gated merge workflow.
  5. Confirm remote master or the target default branch contains the merge.
  6. Close or release the linked issue according to project workflow.
  7. Remove status:in-progress or the equivalent in-progress label when applicable.
  8. Delete the merged remote branch when policy allows.
  9. Remove the local PR branch.
  10. Remove the local branch worktree folder only after confirming it is merged or no longer needed.
  11. Fetch/prune.
  12. Confirm the main checkout is clean and current.

Do not delete branches or worktrees containing unmerged work.

Fail-Closed Cases

Stop immediately if any of these are true:

  • no issue exists and one cannot be created
  • the issue cannot be claimed
  • a worktree is dirty and belongs to the current task, but its state is unclear
  • dirty work belongs to another issue or another LLM
  • branch or PR state conflicts with the prompt
  • the PR is closed but not merged
  • local master is ahead of the remote unexpectedly
  • authenticated identity cannot be verified
  • authenticated user is the PR author for review, approval, or merge
  • the active profile is unknown or not allowed for the requested operation
  • secrets, tokens, passwords, auth headers, or credential paths are found in the diff
  • tests or required checks fail
  • branch cleanup would delete unmerged work
  • production, deploy, rollback, migration, restart, CI trigger, or unrelated service behavior appears outside the issue scope

Fail closed means no mutation, no approval, no merge, and no cleanup that could destroy work.

Recovery Patterns

Dirty worktree from another issue:

  • Do not edit, reset, delete, or clean it.
  • Create or use a separate branch worktree for the assigned issue.
  • Report the unrelated dirty files only if they affect the task.

Dirty worktree from the current issue:

  • Inspect status and diff.
  • Preserve useful work in a commit, patch, or explicit handoff only when asked.
  • Do not reset or delete ambiguous work without explicit approval.

Local default branch ahead of remote:

  • Stop.
  • Report the local and remote commit hashes.
  • Ask whether to push, preserve, or reset. Do not choose destructively.

PR closed but not merged:

  • Do not merge.
  • Release the issue from in-progress only if the task explicitly asks and the project workflow allows it.
  • Leave a clear comment explaining the PR is closed without merge.

Branch deleted before merge:

  • Verify whether the PR was merged.
  • If merged, cleanup can continue.
  • If not merged, stop and report that the source branch is missing.

Unauthorized untracked file created:

  • Stop immediately.
  • Report the exact file path.
  • Do not commit it.
  • Remove it only when explicitly instructed or when the recovery request asks for removal.
  • Recreate the change only after an issue exists and is claimed.

Need to preserve commits before reset:

  • Prefer non-destructive preservation: tag, branch, patch file, or pushed backup branch.
  • Do not use destructive reset or checkout commands unless the user explicitly requests that operation.

Prompt Templates

Ready-to-copy templates live in templates/:

  • start-issue.md
  • review-pr.md
  • merge-pr.md
  • recover-dirty-worktree.md
  • release-tag.md

Adapt the placeholders to the project before use.

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.

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.