Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,25 @@ Enforced by commitlint (`wagoid/commitlint-github-action@v5`). Violations block
- Required checks: `Lint (ubuntu)`, `Test (ubuntu-latest)`, `Test (macos-latest)`, `Test (windows-latest)`
- No force pushes, no deletion; `enforce_admins: false` (owner can bypass)

## AI workflow — standing orders (do not re-ask)

When the user says **"start the next issue"** (or any equivalent — "work on the next one", "what's next", "pick up the next issue"), treat the following as the **default, no-clarification-needed workflow**:

1. **Identify the next issue.** Run `gh issue list --state open --limit 30`. Pick the lowest-numbered open issue that is not a meta-tracking issue, unless the user says otherwise. If only meta-issues remain (e.g. Phase 6 cross-platform polish — issue #16), split the meta-issue into focused sub-issues first (one per concern, one PR each), then start the first sub-issue.
2. **Always pass the issue number through `issue-workflow.sh`.** Use `./scripts/issue-workflow.sh start <issue#>` to branch, and `./scripts/issue-workflow.sh pr-body <issue#>` to render the PR body. The body includes `Closes #<issue#>` — **do not edit this out**. The `Closes` keyword is what auto-closes the issue when the PR is merged.
3. **Verify the linkage before merging.** After `gh pr create`, run `gh pr view <PR#> --json body | grep -E 'Closes|Fixes' #<issue#>'` to confirm the PR body references the issue. If it does not, edit the PR body via `gh pr edit <PR#> --body-file <new-body.md>` before merging. **Do not squash-merge a PR that is not linked to its source issue.**
4. **Merge with admin override when needed.** This repo's `enforce_admins: false` means solo-author merges need `--admin`. The conventional sequence is:
```bash
gh pr merge <PR#> --squash --delete-branch --admin \
--body "Closes #<issue#>. Squash-merged per CONTRIBUTING.md."
git checkout main && git pull --ff-only origin main
git remote prune origin # clean up the deleted feature branch's tracking ref
```
5. **Verify the issue auto-closed.** After the merge, run `gh issue view <issue#> --json state --jq .state` and confirm `CLOSED`. If still `OPEN`, add the issue close manually with `gh issue close <issue#> -c "Closed by <PR#>"`.
6. **Then recurse.** Re-run `gh issue list --state open --limit 30`. If another issue is queued, ask the user to confirm continuation or proceed (if the user already said "keep going", just proceed).

The `make next-issue` target wraps steps 1 and 2 for humans. AI sessions should drive the same script directly.

## Phase status

| Phase | Status | Branch / PR |
Expand Down
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ config.manager=<name> explicitly, or omit the key for auto-detect.
5. **Squash-merge with the source branch deleted** — same as PRs #1–#10.
6. **No force-pushes after review.** Force-pushes during authoring are
fine (use `--force-with-lease`).
7. **Every PR must reference its source issue in the body** — use
`Closes #N` (closing the issue on merge) or `Refs #N` (linked but
not auto-closed). The `scripts/issue-workflow.sh pr-body` template
fills this in automatically from the issue number; do not strip it.
A PR without an issue reference will be sent back for revision.

## Local development

Expand Down
49 changes: 48 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,51 @@ deps: ## Print key Go module versions
@grep -E '(cobra|huh|bubbletea|lipgloss|semver|gjson|yaml)' go.mod

.PHONY: verify
verify: ci build ## Full pre-commit verification (CI + build)
verify: ci build ## Full pre-commit verification (CI + build)

# Drive a single GitHub issue from branch → PR → merge.
# Usage: make next-issue ISSUE=16
# Requires: gh authed for dipto0321/nodeup, conventional-commits commit on HEAD,
# clean working tree. See scripts/issue-workflow.sh and [redacted].md
# ("AI workflow — standing orders") for the full sequence.
.PHONY: next-issue
next-issue: ## Drive the next open issue end-to-end (branch → PR → squash-merge)
@if [ -z "$(ISSUE)" ]; then \
echo "usage: make next-issue ISSUE=<issue#>"; \
exit 1; \
fi
./scripts/issue-workflow.sh start $(ISSUE)
@echo ""
@echo "Now: edit code, then commit with a conventional-commits subject."
@echo "When CI is green and you're ready to merge, run:"
@echo " make finish-pr ISSUE=$(ISSUE)"

# Squash-merge the PR linked to ISSUE. Use after the branch is pushed
# and CI is green. Uses --admin because branch protection requires 1
# approving review but enforce_admins is disabled for solo author work.
# Usage: make finish-pr ISSUE=16 PR=23 (PR auto-detected if omitted)
.PHONY: finish-pr
finish-pr: ## Squash-merge the PR for ISSUE and verify the issue auto-closes
@if [ -z "$(ISSUE)" ]; then \
echo "usage: make finish-pr ISSUE=<issue#> [PR=<pr#>]"; \
exit 1; \
fi
@PR="$${PR:-$(shell gh pr list --state open --json number,headRefName --jq '.[] | select(.headRefName|test("$(ISSUE)")) | .number' | head -1)}"; \
if [ -z "$$PR" ]; then \
echo "no open PR found for issue $(ISSUE). Run \`make next-issue ISSUE=$(ISSUE)\` first."; \
exit 1; \
fi; \
echo "==> squash-merging PR #$$PR with admin override (closes #$(ISSUE))"; \
gh pr merge "$$PR" --squash --delete-branch --admin \
--body "Closes #$(ISSUE). Squash-merged per CONTRIBUTING.md."; \
echo "==> syncing local main"; \
git checkout main && git pull --ff-only origin main; \
git remote prune origin; \
echo "==> verifying issue #$(ISSUE) auto-closed"; \
STATE=$$(gh issue view $(ISSUE) --json state --jq .state); \
if [ "$$STATE" = "CLOSED" ]; then \
echo "✓ issue #$(ISSUE) is CLOSED"; \
else \
echo "warning: issue #$(ISSUE) is still $$STATE — closing manually"; \
gh issue close $(ISSUE) -c "Closed by PR #$$PR. Squash-merged per CONTRIBUTING.md."; \
fi
Loading