790c2c80b1
Co-authored-by: Jason Walker <913443@dadeschools.net> Co-committed-by: Jason Walker <913443@dadeschools.net>
434 lines
18 KiB
Markdown
434 lines
18 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 Summary (§K).
|
|
- **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.
|
|
|
|
## 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` 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`.
|
|
|
|
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
|
|
- **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
|
|
|
|
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).
|
|
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).
|
|
9. Commit with an issue-linked message.
|
|
10. Push the branch.
|
|
11. Open a PR to `master`.
|
|
12. **If you are the author, stop before review/merge.**
|
|
13. **Normal issue work must not directly push to `master`.** PR content should be merged through the forge PR merge mechanism.
|
|
14. 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.**
|
|
4. Verify the worktree is clean.
|
|
5. Inspect the full diff; confirm scope matches the linked issue; flag unrelated files.
|
|
6. Run the tests.
|
|
7. **Do not merge if checks fail. Do not merge if the reviewer is the author.**
|
|
|
|
## G. Merge / cleanup workflow
|
|
|
|
Only an eligible (non-author) reviewer merges. Before merging: always verify
|
|
the authenticated identity **and** the PR author; respect runtime profile
|
|
gates; run independent validation (do not trust the author's reported
|
|
results); 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 (A PR is not done just because `master` moved. A PR is done only when: Gitea reports the PR merged or reconciliation documents equivalent content on `master`; remote `master` contains the expected content; 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 both: PR metadata (state, merged flag, merge commit/hash) and Git content (remote master hash, expected content present or not).
|
|
|
|
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.
|
|
- **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 Summary (required, every task)
|
|
|
|
Every LLM task **must end with a `Controller Handoff Summary`** — 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.
|
|
|
|
Rules:
|
|
|
|
- Never omit the summary.
|
|
- 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.
|
|
|
|
Required format:
|
|
|
|
```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.
|