Files
agent-skills/skills/work/SKILL.md
T
naps62 17677c18df feat(land): never merge, user clicks
Auto-merge burned a client PR meant for manual merge. Human gate
needed on public/client repos; one click on private is cheap, so
rule is universal. Land now stops at green + approved + updated
branch, notifies, and leaves the merge button alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLkYHLzszmzq5fMGpFAkHh
2026-07-30 08:33:00 +00:00

117 lines
5.5 KiB
Markdown

---
name: work
description: "Pick a task from the tracker (Linear or Gitea issues), implement in a worktree, open a PR, and iterate on reviews autonomously"
user-invocable: true
args:
- name: input
description: "A Linear issue ID (e.g. ERN-347), a Gitea issue number (e.g. #23), an ad-hoc task description, or omit to auto-pick next unblocked task"
required: false
---
# Work - Proper PR Flow
Autonomous workflow: tracking issue -> worktree -> implementation -> PR -> review iteration -> done. The tracker (Linear or Gitea issues) is selected by `tracker` in `linear.json`.
**First:** Read `linear-common/COMMON.md` (sibling skill, same skills root) for shared setup instructions.
## Workflow
### 1. Setup (from COMMON.md)
- Load project config
- Select task (from `$ARGUMENTS`)
- Set up worktree
- Gather context
### 2. Plan
1. Analyze the issue requirements and the codebase context you gathered.
2. Break the work into logical commits.
3. If the issue is non-trivial, write a brief plan as a comment on the tracking issue (Linear comment, or Gitea `POST $BASE/api/v1/repos/$REPO/issues/$N/comments`).
4. Identify risks or open questions. If they're blocking, ask the user. If not, note them and proceed with best judgment.
### 3. Implement
Follow the implementation guidelines from COMMON.md.
After implementation is complete:
1. Run the `buildCommand` from the config through the gate — `<skills-root>/linear-common/scripts/gate.sh -- <buildCommand>` (see "Local verification budget" in COMMON.md). All checks must pass before opening a PR. Exit 75 = the machine was busy and it never ran: open the PR and let CI be the check, saying so in the PR body. Exit 137 = memory cap, not a failing test.
2. If tests fail, fix them. Do not ship broken code.
3. During implementation, check only the module you touched. This is the one full run.
### 3.5 Self-review gate (before opening the PR)
Spawn the **`cavecrew-reviewer`** subagent on your own diff (Agent tool, `subagent_type: caveman:cavecrew-reviewer`; point it at `git diff <defaultBranch>...HEAD`). It returns one line per finding, severity-tagged, no praise. Fix anything real it surfaces, then re-check **only the modules those fixes touched** — don't run the whole suite a second time; CI covers the rest. This catches obvious issues before `/land` waits on human/bot review — cheaper than a review round-trip.
Advisory, not a hard gate: for a trivial diff (typo, one-liner, config bump) skip it. Don't loop on it — one pass, address the genuine findings, move on.
### 4. Open PR
1. Push the branch: `git push -u origin <branch>`
2. Open a PR. The exact commands depend on `remoteHost` from `linear.json`:
- `github` (default): see **GitHub variant** below.
- `gitea`: see **Gitea variant** below.
3. PR title and body in both cases:
- Title: concise, under 70 characters
- Body format:
```
## Summary
<bullets>
## Issue
Closes <REF>
## Test plan
<what was tested and how>
```
where `<REF>` is the Linear issue ID (`ERN-347`) for `tracker: linear`, or `#<N>` for `tracker: gitea` / `tracker: github` (both auto-close the issue when the PR merges to the default branch).
- Request reviewers from `prReviewers` if configured.
4. Move the tracking issue to "In Review":
- **linear**: set the issue status to "In Review" (or equivalent).
- **gitea**: no review state exists — leave the issue open (the PR's `Closes #N` closes it on merge); optionally add an `in-review` label if one already exists in the repo.
- **github**: no review state exists — leave the issue open (the PR's `Closes #N` closes it on merge); optionally add an `in-review` label if one already exists in the repo.
### 5. Hand off to `/land`
The PR is open — now drive it to ready-to-merge. **Invoke `/land <N>`** (the `land` skill). It owns the whole review/CI iteration loop: waits for CI + reviews without idling, fixes failures, resolves every comment (including bot reviewers), pushes, re-arms, and once green + approved it updates the branch and hands the merge click to the user — it never merges.
Do not re-implement that loop here — `/land` is the single source of truth for it, and it reads the same `remoteHost` / tracker config. `/land` derives the tracking issue from the PR body's `Closes <REF>`, so no extra hand-off state is needed.
The success bar `/land` enforces (all must hold before it declares ready): CI green, all review threads resolved, approved with no pending review requests.
---
## GitHub variant (open PR)
```
gh pr create --title "<title>" --body "<body>" --reviewer <r1>,<r2>
```
Then go to step 5 (`/land <N>`).
## Gitea variant (open PR)
Requires `$GITEA_TOKEN` in the environment (`source ~/.env.claude` if needed) and `remoteBaseUrl` from `linear.json`. Set `BASE=$remoteBaseUrl` and `REPO=<owner>/<repo>` (from `git remote get-url origin`).
```bash
curl -sS -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$BASE/api/v1/repos/$REPO/pulls" \
-d "$(jq -nc --arg title "<title>" --arg body "<body>" --arg head "<branch>" --arg base "<defaultBranch>" \
'{title:$title, body:$body, head:$head, base:$base}')"
```
The response includes `number` and `html_url`. Save the number — it's the PR index `/land` uses.
To request reviewers (if `prReviewers` is set):
```bash
curl -sS -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
"$BASE/api/v1/repos/$REPO/pulls/$N/requested_reviewers" \
-d '{"reviewers": ["alice","bob"]}'
```
Then go to step 5 (`/land <N>`).