Files
Gitea-Tools/skills/llm-project-workflow/SKILL.md
T
sysadminandClaude Opus 4.8 2111c84e7d docs: add Work Selection Rule for LLM operating rules
Require lease verification (open PRs, branches, worktrees, leases,
merged completion) before any issue or PR work. Surface the rule in
the portable skill, Gitea runbooks, operator guide, and start-issue
template; add doc-contract tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-06 13:45:25 -04:00

647 lines
30 KiB
Markdown

---
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.
---
# 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](#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.
---
## 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).
## B. Isolated worktree rule
**Never implement or review in the main checkout.** The main checkout is for
orchestration and status only (issue creation, `git status`, creating worktrees).
- 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:
```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 <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
```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
0. Acquire or verify a work lease (Work Selection Rule) — complete all seven
checks before any claim, branch, or PR work.
1. Verify the orchestration checkout (right repo, clean tree).
2. Fetch/prune: `git fetch <remote> --prune`.
3. Confirm local `master` equals remote `master` (`git rev-list --left-right --count <remote>/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 <branch>`), 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 <repo> 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 -- <file>`, 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 <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 <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/`](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:
```
Role-specific fields (append to the compact block):
- review/merge tasks: `Selected PR:`, `Reviewer eligibility:`,
`Pinned reviewed head:`, `Review decision:`, `Merge result:`,
`Linked issue status:`, `Cleanup status:`
- 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:
```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
```
## 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`](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.