docs: add portable llm-project-workflow skill + templates (#46)

Extract the project's operating rules into a reusable, project-agnostic skill
so any repo can adopt the same safe LLM workflow.

- skills/llm-project-workflow/SKILL.md: issue-first; isolated branch worktrees
  (main checkout = orchestration only); distinct author/reviewer identities and
  profile safety (secrets by reference only; stop if authenticated user == PR
  author); branch naming; start/review/merge/cleanup workflows; fail-closed
  cases; recovery patterns; and an "Adapting to a project" table for the
  forge-specific names.
- templates/: copy/paste prompts for start-issue, review-pr, merge-pr,
  recover-bad-state, worktree-cleanup.
- Link the skill from README.md and docs/llm-workflow-runbooks.md (the runbook
  is framed as the Gitea-specific application of the portable skill).

Docs-only; no code, no secrets, safe placeholder examples only. No change to
MCP runtime, Gitea API, credential storage, or worktree helpers.

Checks: full suite 287 passed / 0 failures; git diff --check clean; secret scan
of skills/ clean.

Closes #46. Refs #38, #39.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-02 03:26:25 -04:00
parent 92b449f080
commit 00ec883014
8 changed files with 280 additions and 273 deletions
@@ -1,43 +1,28 @@
# Merge PR Prompt
# Template: merge a PR (eligible reviewer only)
You are the merge operator for PR `<pr-number>` in `<repo-name>`.
Copy, fill the `<...>` fields, and paste as the task prompt.
Hard gate:
```text
Task: merge PR #<pr> for issue #<n> if it is eligible and checks pass.
- Verify authenticated identity before reviewing or merging.
- Verify PR author.
- If authenticated user matches the PR author, stop immediately.
- Merge only if assigned merge duty and reviewer-eligible.
Rules (llm-project-workflow):
- Only an eligible, NON-author reviewer merges. If authenticated user == PR
author → STOP.
- Do not merge unless the PR is open, mergeable, and its checks/review pass.
- No force-merge, no bypassing branch protections.
Workflow:
Steps:
1. Verify authenticated identity + active profile.
2. Confirm PR #<pr>: author (not you), state open, mergeable, review approved.
3. If any gate fails → STOP and report.
4. Merge with explicit confirmation (e.g. confirmation="MERGE PR <pr>"),
optionally pinning the reviewed head SHA / changed-file set.
5. Confirm remote master now contains the merge commit.
1. Confirm PR `<pr-number>` is open and targets `<default-branch>`.
2. Confirm the PR head is still `<reviewed-commit>` or includes it.
3. Confirm changed files still match the reviewed file list.
4. Confirm previous validation still applies or rerun required checks.
5. Merge through the gated project merge workflow.
6. Confirm remote `<default-branch>` contains the merge.
7. Close or release linked issue `<issue-number>` according to project policy.
8. Remove `status:in-progress` if applicable.
9. Delete the merged remote branch if policy allows.
10. Remove local PR branch and branch worktree only after merge is confirmed.
11. Fetch/prune.
12. Confirm main checkout is clean/current.
Then run the cleanup template (worktree-cleanup.md):
- close/release issue #<n>, remove status:in-progress
- delete remote branch, remove local branch + worktree folder
- fetch/prune; confirm main checkout is clean and current (0 0).
Stop if:
- authenticated user is the PR author
- PR head changed after review
- PR is closed but not merged
- tests/checks fail
- cleanup would delete unmerged work
Report:
- authenticated user
- PR author
- eligibility result
- merge commit/hash
- issue final state
- branch/worktree cleanup result
- final PR URL
Handoff: reviewer identity, merge result + commit, cleanup done, issue closed.
```
@@ -0,0 +1,32 @@
# Template: recover from bad state
Copy, fill the `<...>` fields, paste as the task prompt. Recovery is read-then-
act: gather facts first, never discard unmerged work.
```text
Task: recover repo state for <situation>. Do not lose unmerged work.
Rules (llm-project-workflow):
- Fail closed: if state is unclear or a step would delete unmerged work, STOP.
- Never push master. Never discard commits not safely pushed to <remote>.
Diagnose first:
1. git fetch <remote> --prune
2. git status --short; git worktree list
3. git rev-list --left-right --count <remote>/master...master # ahead/behind
4. For any PR involved: confirm state (open/closed/merged) AND whether
<remote>/master actually contains its commits ("closed" != "merged").
Act per case:
- Dirty worktree from another issue: leave it; start yours in a new worktree.
- Local master ahead of remote: confirm the extra commits live on a branch
pushed to <remote>, THEN git reset --hard <remote>/master. Verify with
`git branch --contains <sha>` first.
- PR closed but not merged: re-push the branch, reopen/replace the PR, let an
eligible reviewer merge. Do not merge your own.
- Branch deleted before merge: recover commits from a local branch/reflog (or
git fsck --lost-found), re-push, reopen the PR.
- Unauthorized untracked file: do not commit it; leave pre-existing artifacts.
Handoff: what was wrong, evidence, action taken, current state, what remains.
```
@@ -1,34 +1,26 @@
# Review PR Prompt
# Template: review a PR
You are independently reviewing PR `<pr-number>` in `<repo-name>`.
Copy, fill the `<...>` fields, and paste as the task prompt.
Hard gate:
```text
Task: review PR #<pr> for issue #<n>.
- Verify authenticated identity.
- Verify PR author.
- If authenticated user matches the PR author, stop immediately.
- Do not approve or merge unless reviewer-eligible.
Rules (llm-project-workflow):
- Review in a SEPARATE detached review worktree, never the author's folder.
- You must NOT be the PR author. If the authenticated user == PR author, stop.
- Do not merge if any check fails.
Workflow:
Steps:
1. Verify your authenticated identity (whoami) and the active profile.
2. Fetch the PR facts: PR author, head SHA, state (must be open), base branch.
3. If authenticated user == PR author → STOP (no self-review).
4. scripts/worktree-review <pr-head-branch> # detached, branches/review-*
cd branches/review-<pr-head-branch-slug>
5. Confirm the worktree is clean. Inspect the FULL diff; confirm scope matches
issue #<n>; flag any unrelated files, secrets, or formatting churn.
6. Run the test suite; note results.
7. Post the review verdict: approve only if scope is clean and checks pass;
otherwise request changes with specifics. Never merge from this review step.
1. Create or use a separate review worktree.
2. Fetch/prune.
3. Confirm PR `<pr-number>` is open and targets `<default-branch>`.
4. Confirm the PR head is `<expected-commit>` or includes it.
5. Confirm changed files match the issue scope.
6. Inspect the diff for correctness, secrets, unrelated behavior, and forbidden
changes.
7. Run `<required-checks>`.
8. If anything fails, leave exact blockers and do not approve.
9. If everything passes, approve only if reviewer-eligible.
Report:
- authenticated user
- PR author
- eligibility result
- commit reviewed
- files changed
- checks run and results
- blockers or risks
- final PR URL
Handoff: reviewer identity, PR author, scope verdict, checks + results, decision.
```
@@ -1,34 +1,29 @@
# Start Issue Prompt
# Template: start a new issue
You are implementing issue `<issue-number>` in `<repo-name>`.
Copy, fill the `<...>` fields, and paste as the task prompt.
Rules:
```text
Task: implement <issue title / one-line goal>.
- No repository changes unless the issue exists and is claimed.
- Use an isolated branch worktree under `branches/`.
- Branch from latest `<remote>/<default-branch>`.
- Keep the change limited to issue `<issue-number>`.
Rules (llm-project-workflow):
- No repo changes without a tracking issue. If none exists, create one first;
if it can't be created, stop.
- Work only in an isolated branch worktree under branches/. The main checkout
is orchestration/status only.
- Do not self-review or self-merge.
Workflow:
Steps:
1. Verify the orchestration checkout is the right repo and clean.
2. git fetch <remote> --prune; confirm local master == <remote>/master (0 0).
3. Create the issue "<title>" (problem, scope, acceptance) and claim it
(status:in-progress + a "starting work" comment naming the branch).
4. scripts/worktree-start <type>/issue-<n>-<slug> # type = fix|feat|docs
cd branches/<type>-issue-<n>-<slug>
5. Implement the narrow scope only; add/update focused tests if behavior changes.
6. Checks: run the test suite, compile/lint changed files, git diff --check,
and scan the diff for secrets.
7. Commit (issue-linked message), push the branch, open a PR to master.
8. Stop before review/merge — you are the author.
1. Verify the issue exists and is open.
2. Claim it with the project in-progress label.
3. Fetch/prune and confirm local `<default-branch>` matches
`<remote>/<default-branch>`.
4. Create branch `<branch-name>` in `branches/<safe-folder-name>`.
5. Implement only the scoped change.
6. Run `<required-checks>`.
7. Inspect for secrets and unrelated files.
8. Commit, push, and open a PR.
9. Stop before review or merge.
Final handoff:
- issue number/title
- branch name
- isolated worktree path
- files changed
- checks run and results
- PR URL
- reviewer/merge instructions
Handoff: issue #, branch, worktree path, files changed, checks + results, PR URL.
```
@@ -0,0 +1,28 @@
# Template: clean up after merge
Copy, fill the `<...>` fields, and paste as the task prompt. Only run AFTER a
real merge is confirmed on remote master.
```text
Task: clean up branch/worktree for PR #<pr> / issue #<n> after merge.
Rules (llm-project-workflow):
- Do NOT clean up until the merge is confirmed on <remote>/master.
- Cleanup would-delete-unmerged-work → STOP. Never --force-remove a dirty tree.
Steps:
1. git fetch <remote> --prune
2. Confirm <remote>/master contains the merge of PR #<pr>
(git log <remote>/master | grep the merge, or git branch -r --contains <sha>).
If not merged → STOP; run the recovery template instead.
3. Close issue #<n> if not auto-closed; remove the status:in-progress label.
4. scripts/worktree-clean --delete-branch <type>/issue-<n>-<slug>
(removes branches/<type>-issue-<n>-<slug>; refuses if dirty; git branch -d is
safe-delete only — fails on unmerged.)
5. Delete the remote branch if the merge did not already remove it.
6. From the main checkout: git fetch <remote> --prune; git checkout master;
git reset --hard <remote>/master ONLY if local master safely matches remote.
7. Confirm main checkout clean and current (git status; 0 0 vs <remote>/master).
Handoff: merge confirmed, issue closed, branch+worktree removed, checkout clean.
```