diff --git a/.claude/commands/qa.md b/.claude/commands/qa.md index bab055b..1dbb3d4 100644 --- a/.claude/commands/qa.md +++ b/.claude/commands/qa.md @@ -1,4 +1,3 @@ - You are executing the `/qa` skill. Your argument is: $ARGUMENTS --- diff --git a/.claude/commands/release.md b/.claude/commands/release.md index c43395c..5642a08 100644 --- a/.claude/commands/release.md +++ b/.claude/commands/release.md @@ -1,4 +1,3 @@ - You are executing the `/release` skill. Your argument is: $ARGUMENTS --- diff --git a/.claude/commands/setup.md b/.claude/commands/setup.md index 99d3bee..1a4b5c5 100644 --- a/.claude/commands/setup.md +++ b/.claude/commands/setup.md @@ -1,4 +1,3 @@ - You are executing the `/setup` skill. Your argument is: $ARGUMENTS --- @@ -470,4 +469,4 @@ Add a note: `/start` can be used to create well-formed GitHub issues without wri - Never fetch more than 100 labels in a single command. `gh label list --limit 100` is the ceiling. - Do not skip any human gate in Phase 2 or Phase 3 — each write requires confirmation. - If the user skips a config value, do not ask again. Move on. - + diff --git a/.claude/commands/ship.md b/.claude/commands/ship.md index bd287f3..53b3351 100644 --- a/.claude/commands/ship.md +++ b/.claude/commands/ship.md @@ -1,4 +1,3 @@ - You are executing the `/ship` skill. Your argument is: $ARGUMENTS --- diff --git a/.claude/commands/start.md b/.claude/commands/start.md index cc4235f..4afee6e 100644 --- a/.claude/commands/start.md +++ b/.claude/commands/start.md @@ -151,7 +151,7 @@ Show the user: `On branch feature/` Now write the code. Do NOT commit anything. -When done, say: **"The code is ready for review. Please run `make dev` and test locally. Let me know if it looks good, needs changes, or should be scrapped."** +When done, say: **"The code is ready for review. Please run `make dev` and test locally. Let me know if it looks good, needs changes, or should be scrapped. When you're happy, run `/ship` to commit, push, and open a PR."** - User says looks good → run `/ship` - User requests changes → iterate, repeat this message @@ -213,7 +213,7 @@ gh issue comment --body "Resuming work. You are executing the `/version` skill. Your argument is: $ARGUMENTS --- @@ -80,4 +79,4 @@ Report based on mode: - **Trunk mode** (`dev` empty): "Tagged vX.Y.Z. Run `/release` to create the GitHub Release." - **Two-branch mode** (`dev` set, `` empty): "Tagged vX.Y.Z. Run `make deploy-preview` to deploy to preview for testing. When testing is complete, run `/release`." - **Three-branch mode** (both set): "Tagged vX.Y.Z. Run `make deploy-preview` to deploy to staging. When testing is complete, run `/release`." - + diff --git a/Makefile b/Makefile index 3a1989c..487f153 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,9 @@ +# Makefile — CodeCannon project-specific targets +# +# Workflow targets (branch, pr, abandon, merge, promote) come from Makefile.agents.mk. +# This file adds CodeCannon-specific targets: sync, versioning, and deployment. + +INTEGRATION_BRANCH = dev include Makefile.agents.mk .PHONY: check dev sync bump-patch bump-minor bump-major set-version deploy-preview deploy-prod @@ -57,10 +63,10 @@ endif git commit -m "Bump version to $(V)" git tag v$(V) -# Publish the integration branch so consumers can pick up changes via submodule update. +# Push the integration branch for preview/testing. deploy-preview: - git push origin development + git push origin $(INTEGRATION_BRANCH) -# Publish a tagged release to main. +# Publish a tagged release to production. deploy-prod: - git push origin main --tags + git push origin $(PRODUCTION_BRANCH) --tags diff --git a/Makefile.agents.mk b/Makefile.agents.mk index c846c10..35a3ea9 100644 --- a/Makefile.agents.mk +++ b/Makefile.agents.mk @@ -10,13 +10,23 @@ # Configuration: # INTEGRATION_BRANCH — the branch PRs target (default: development) # PRODUCTION_BRANCH — the production branch (default: main) +# STAGING_BRANCH — optional staging/pre-prod branch (default: empty) # FEATURE_PREFIX — prefix for feature branches (default: feature/) +# +# Workflow modes: +# Two-branch (default): feature → INTEGRATION_BRANCH → PRODUCTION_BRANCH +# Three-branch: feature → INTEGRATION_BRANCH → STAGING_BRANCH → PRODUCTION_BRANCH +# +# Set STAGING_BRANCH to enable three-branch mode. When set: +# - `promote` target becomes available (PR: integration → staging) +# - STAGING_BRANCH is protected from direct feature work INTEGRATION_BRANCH ?= development PRODUCTION_BRANCH ?= main +STAGING_BRANCH ?= FEATURE_PREFIX ?= feature/ -.PHONY: branch pr abandon merge +.PHONY: branch pr abandon merge promote # Create a feature branch from the integration branch. # Usage: make branch name= @@ -33,6 +43,9 @@ pr: if [ "$$branch" = "$(PRODUCTION_BRANCH)" ] || [ "$$branch" = "$(INTEGRATION_BRANCH)" ]; then \ echo "Error: cannot PR from $$branch. Use a feature branch."; exit 1; \ fi; \ + if [ -n "$(STAGING_BRANCH)" ] && [ "$$branch" = "$(STAGING_BRANCH)" ]; then \ + echo "Error: cannot PR from $$branch. Use a feature branch."; exit 1; \ + fi; \ git push -u origin "$$branch" && \ gh pr create --base $(INTEGRATION_BRANCH) --fill @@ -42,6 +55,9 @@ abandon: if [ "$$branch" = "$(PRODUCTION_BRANCH)" ] || [ "$$branch" = "$(INTEGRATION_BRANCH)" ]; then \ echo "Error: cannot abandon $$branch."; exit 1; \ fi; \ + if [ -n "$(STAGING_BRANCH)" ] && [ "$$branch" = "$(STAGING_BRANCH)" ]; then \ + echo "Error: cannot abandon $$branch."; exit 1; \ + fi; \ git checkout . && \ git clean -fd && \ git checkout $(INTEGRATION_BRANCH) && \ @@ -54,6 +70,9 @@ merge: if [ "$$branch" = "$(PRODUCTION_BRANCH)" ] || [ "$$branch" = "$(INTEGRATION_BRANCH)" ]; then \ echo "Error: cannot merge from $$branch. Use a feature branch."; exit 1; \ fi; \ + if [ -n "$(STAGING_BRANCH)" ] && [ "$$branch" = "$(STAGING_BRANCH)" ]; then \ + echo "Error: cannot merge from $$branch. Use a feature branch."; exit 1; \ + fi; \ pr_url=$$(gh pr view --json url -q .url 2>/dev/null); \ if [ -z "$$pr_url" ]; then \ echo "Error: no open PR found for $$branch."; exit 1; \ @@ -66,3 +85,12 @@ merge: git checkout $(INTEGRATION_BRANCH) && \ git pull origin $(INTEGRATION_BRANCH) && \ echo "PR merged into $(INTEGRATION_BRANCH)." + +# Promote integration branch to staging. Creates a PR: INTEGRATION_BRANCH → STAGING_BRANCH. +# Only available in three-branch mode (STAGING_BRANCH is set). +promote: +ifndef STAGING_BRANCH + $(error promote requires STAGING_BRANCH to be set (three-branch mode)) +endif + gh pr create --base $(STAGING_BRANCH) --head $(INTEGRATION_BRANCH) \ + --title "Promote $(INTEGRATION_BRANCH) → $(STAGING_BRANCH)" --fill diff --git a/skills/start.md b/skills/start.md index d7f1ba1..8c75c54 100644 --- a/skills/start.md +++ b/skills/start.md @@ -154,7 +154,7 @@ Show the user: `On branch feature/` Now write the code. Do NOT commit anything. -When done, say: **"The code is ready for review. Please run `{{DEV_CMD}}` and test locally. Let me know if it looks good, needs changes, or should be scrapped."** +When done, say: **"The code is ready for review. Please run `{{DEV_CMD}}` and test locally. Let me know if it looks good, needs changes, or should be scrapped. When you're happy, run `/ship` to commit, push, and open a PR."** - User says looks good → run `/ship` - User requests changes → iterate, repeat this message @@ -216,7 +216,7 @@ gh issue comment --body "Resuming work.