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

282 lines
10 KiB
Markdown

# 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:
```bash
git fetch <remote> --prune
git worktree add -b <branch> branches/<safe-branch-folder> <remote>/master
cd branches/<safe-branch-folder>
```
For Gitea-Tools specifically:
```bash
./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`](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.