Files
EVOLV/.claude/skills/ship-it/iterate.md

71 lines
5.1 KiB
Markdown
Raw Normal View History

# ship-it iterate — one issue, end-to-end
You are running ONE iteration of the ship-it AFK loop. Implement, verify, and ship exactly one issue, then exit. The outer shell loop will pick the next one.
**Mode: AFK.** Do not ask questions. If the issue is genuinely undecidable from its body + linked PRD + grilling notes already in the issue or repo, drop a comment on the issue with the specific question, label it `needs-decision`, and exit with status=needs-decision. Do not guess at user intent.
Variables provided below this prompt: `ISSUE_NUMBER`, `TRACKER_CLI` (`gh` or `tea`), `TRUNK_BRANCH`, `REPO_ROOT`.
## Steps
1. **Read the issue.**
- GitHub: `gh issue view $ISSUE_NUMBER --json number,title,body,labels`
- Gitea: `tea issues $ISSUE_NUMBER --output json`
- Parse: `Slice — layers touched`, `Scope`, `Acceptance criteria`, `Slice check`, `Notes`, linked PRD path.
- If `Acceptance criteria` is missing or non-testable → exit status=needs-decision with reason "acceptance criteria not testable".
2. **Branch from latest trunk.**
`git fetch origin && git switch -c "slice/${ISSUE_NUMBER}-<short-kebab-slug>" "origin/$TRUNK_BRANCH"`
3. **Write the failing e2e test first.** Anchored at the OUTERMOST layer named in `Slice — layers touched` (HTTP endpoint, UI smoke, dashboard query, log assertion — whatever the acceptance criterion observes). Run it. Confirm it fails for the right reason. If you can't write an e2e test for this slice, that's a sign the acceptance criterion isn't really observable end-to-end → exit status=needs-decision.
4. **Implement layer by layer.** Walk the `Slice — layers touched` list. Make the minimal change at each layer to satisfy the slice — do not gold-plate, do not refactor adjacent code, do not "improve" things outside scope. Re-run the e2e test after each layer change.
5. **Run the broader test suite.** Catch regressions caused by the slice. Fix any test that was green before and is now red — do not skip or mark tests. If a test was already red before your changes, leave it (note in PR body).
6. **Outermost-layer smoke check.** The 30-second-demo check: hit the endpoint with curl, query the dashboard, tail the log, load the page. Observe what the acceptance criterion observes. Capture the output (curl response body, log snippet, query result) — you'll paste it into the PR body as evidence.
7. **Commit.** One commit per slice (or a tight series — no WIP commits, no fixup commits, no "address review" before review exists). Read the repo's recent `git log` to match commit style. Message ends with `Closes #${ISSUE_NUMBER}`.
8. **Push and open PR.**
- GitHub: `git push -u origin HEAD && gh pr create --fill`
- Gitea: `git push -u origin HEAD && tea pr create --title "..." --description "..."`
- PR body must include:
- Each acceptance criterion as a checked `- [x]` line.
- The smoke-check evidence (curl output / log snippet / screenshot path) in a fenced block.
- `Closes #${ISSUE_NUMBER}` (so the issue auto-closes on merge).
9. **Wait for CI and decide merge.**
- Poll: `gh pr checks --watch` (or `tea pr status`).
- **All green + branch protection allows direct merge** → `gh pr merge --squash --delete-branch`. Verify the merge commit landed on trunk.
- **All green + branch protection requires human review** → leave PR open. Comment `Ready for review — all acceptance criteria verified, smoke check passed.` on the issue. Exit status=shipped with the PR number.
- **Red CI** → one fix-and-push cycle. Read the failing log, fix the actual cause (do not skip the test). If still red after the second attempt: label issue `ci-failed`, comment with the CI excerpt, leave PR open, exit status=failed with reason "ci-red".
10. **Return to trunk.** `git switch $TRUNK_BRANCH && git pull --ff-only`. If the slice was merged, run the smoke check one more time against integrated trunk. If it fails there → revert the merge, label `regression`, exit status=failed with reason "regression-on-trunk".
## Boundaries
- Never force-push, never rewrite shared history, never delete branches you didn't create.
- Never bypass branch protection (`--admin`) or skip CI hooks (`--no-verify`).
- Never auto-merge a PR whose CI is red or pending.
- Never close an issue without the outermost-layer smoke check passing.
- Never modify CI/CD config, IaC, or production data unless the slice's `layers touched` explicitly names that layer.
- Never invent acceptance criteria. If they're vague, label `needs-decision`.
- Never assign issues or change milestones.
## Final output line
The shell loop greps for this exact line to determine outcome. Print it as the LAST line before exiting, on its own line, no decoration:
```
ITERATION_RESULT: status=<shipped|failed|needs-decision> issue=#<N> pr=<#N|none> reason=<short single-line reason>
```
Examples:
```
ITERATION_RESULT: status=shipped issue=#142 pr=#287 reason=merged-to-main
ITERATION_RESULT: status=shipped issue=#143 pr=#288 reason=open-for-review
ITERATION_RESULT: status=failed issue=#144 pr=#289 reason=ci-red-after-retry
ITERATION_RESULT: status=needs-decision issue=#145 pr=none reason=acceptance-criteria-not-testable
```