From 60ce4545a05c3b2ddc2364adc7240a0a7b2d58e0 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart Date: Thu, 9 Apr 2026 19:59:11 -0400 Subject: [PATCH 01/12] Fix deploy-prod tag clobber and add validate to make dev --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f2f11d9..75c1bff 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,7 @@ check: # Preview what sync would generate without writing any files. dev: + ./sync.sh --validate ./sync.sh --dry-run # Regenerate .claude/commands/ and other adapter output from skills/. @@ -97,5 +98,6 @@ deploy-preview: # Publish a tagged release to production. deploy-prod: git checkout $(PRODUCTION_BRANCH) - git pull --rebase origin $(PRODUCTION_BRANCH) --tags + git pull --rebase origin $(PRODUCTION_BRANCH) + git fetch origin --tags --force git push origin $(PRODUCTION_BRANCH) --tags From b9ef018619b1e431488b0fe9de4699fa68253521 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart Date: Fri, 10 Apr 2026 09:38:33 -0400 Subject: [PATCH 02/12] Add Verification / QA effort complexity indicator to issue body template --- .agents/skills/start/SKILL.md | 14 ++++++++++++-- .claude/commands/start.md | 14 ++++++++++++-- .cursor/rules/start.mdc | 14 ++++++++++++-- .gemini/skills/start/SKILL.md | 14 ++++++++++++-- skills/start.md | 12 +++++++++++- 5 files changed, 59 insertions(+), 9 deletions(-) diff --git a/.agents/skills/start/SKILL.md b/.agents/skills/start/SKILL.md index 740cfa5..92be2cc 100644 --- a/.agents/skills/start/SKILL.md +++ b/.agents/skills/start/SKILL.md @@ -115,12 +115,22 @@ Resolve labels and milestone using the resolution steps in the Parsing section a ## General Approach +## Complexity +**Verification / QA effort:** + + ## Acceptance Criteria - - ``` -All four sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). +All five sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). + +**Complexity scale guidance (for agent use only — do not include the scale definition in the issue body):** +- **trivial** — single obvious check (e.g. color change, label text, toggle visibility) +- **moderate** — a few scenarios to verify, minor setup needed (e.g. form validation, a new UI component with a couple of states) +- **significant** — many scenarios, data setup, or cross-feature impact (e.g. multi-step workflow, permission changes across roles) +- **extensive** — complex data flows, integration testing, or edge cases spanning multiple areas (e.g. data import/export mapping, API contract changes consumed by multiple clients) **Title rules:** - ✅ `Fix 'Contact Us' footer link pointing to 404 instead of /contact-us` @@ -244,4 +254,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.claude/commands/start.md b/.claude/commands/start.md index dc9d2b3..2bd19c1 100644 --- a/.claude/commands/start.md +++ b/.claude/commands/start.md @@ -110,12 +110,22 @@ Resolve labels and milestone using the resolution steps in the Parsing section a ## General Approach +## Complexity +**Verification / QA effort:** + + ## Acceptance Criteria - - ``` -All four sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). +All five sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). + +**Complexity scale guidance (for agent use only — do not include the scale definition in the issue body):** +- **trivial** — single obvious check (e.g. color change, label text, toggle visibility) +- **moderate** — a few scenarios to verify, minor setup needed (e.g. form validation, a new UI component with a couple of states) +- **significant** — many scenarios, data setup, or cross-feature impact (e.g. multi-step workflow, permission changes across roles) +- **extensive** — complex data flows, integration testing, or edge cases spanning multiple areas (e.g. data import/export mapping, API contract changes consumed by multiple clients) **Title rules:** - ✅ `Fix 'Contact Us' footer link pointing to 404 instead of /contact-us` @@ -239,4 +249,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.cursor/rules/start.mdc b/.cursor/rules/start.mdc index 56b6728..54ca08c 100644 --- a/.cursor/rules/start.mdc +++ b/.cursor/rules/start.mdc @@ -116,12 +116,22 @@ Resolve labels and milestone using the resolution steps in the Parsing section a ## General Approach +## Complexity +**Verification / QA effort:** + + ## Acceptance Criteria - - ``` -All four sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). +All five sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). + +**Complexity scale guidance (for agent use only — do not include the scale definition in the issue body):** +- **trivial** — single obvious check (e.g. color change, label text, toggle visibility) +- **moderate** — a few scenarios to verify, minor setup needed (e.g. form validation, a new UI component with a couple of states) +- **significant** — many scenarios, data setup, or cross-feature impact (e.g. multi-step workflow, permission changes across roles) +- **extensive** — complex data flows, integration testing, or edge cases spanning multiple areas (e.g. data import/export mapping, API contract changes consumed by multiple clients) **Title rules:** - ✅ `Fix 'Contact Us' footer link pointing to 404 instead of /contact-us` @@ -245,4 +255,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.gemini/skills/start/SKILL.md b/.gemini/skills/start/SKILL.md index 5ad7329..28593a4 100644 --- a/.gemini/skills/start/SKILL.md +++ b/.gemini/skills/start/SKILL.md @@ -115,12 +115,22 @@ Resolve labels and milestone using the resolution steps in the Parsing section a ## General Approach +## Complexity +**Verification / QA effort:** + + ## Acceptance Criteria - - ``` -All four sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). +All five sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). + +**Complexity scale guidance (for agent use only — do not include the scale definition in the issue body):** +- **trivial** — single obvious check (e.g. color change, label text, toggle visibility) +- **moderate** — a few scenarios to verify, minor setup needed (e.g. form validation, a new UI component with a couple of states) +- **significant** — many scenarios, data setup, or cross-feature impact (e.g. multi-step workflow, permission changes across roles) +- **extensive** — complex data flows, integration testing, or edge cases spanning multiple areas (e.g. data import/export mapping, API contract changes consumed by multiple clients) **Title rules:** - ✅ `Fix 'Contact Us' footer link pointing to 404 instead of /contact-us` @@ -244,4 +254,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/skills/start.md b/skills/start.md index 0f72dc6..19d448f 100644 --- a/skills/start.md +++ b/skills/start.md @@ -158,12 +158,22 @@ Resolve labels and milestone using the resolution steps in the Parsing section a ## General Approach +## Complexity +**Verification / QA effort:** + + ## Acceptance Criteria - - ``` -All four sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). +All five sections are required. Write for a non-developer audience — no code, no file paths. Acceptance Criteria must be concrete and verifiable (not vague goals). + +**Complexity scale guidance (for agent use only — do not include the scale definition in the issue body):** +- **trivial** — single obvious check (e.g. color change, label text, toggle visibility) +- **moderate** — a few scenarios to verify, minor setup needed (e.g. form validation, a new UI component with a couple of states) +- **significant** — many scenarios, data setup, or cross-feature impact (e.g. multi-step workflow, permission changes across roles) +- **extensive** — complex data flows, integration testing, or edge cases spanning multiple areas (e.g. data import/export mapping, API contract changes consumed by multiple clients) **Title rules:** - ✅ `Fix 'Contact Us' footer link pointing to 404 instead of /contact-us` From 110cf6227abaf95f4cdda3171f0305cace40e8c0 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart Date: Sat, 11 Apr 2026 08:50:21 -0400 Subject: [PATCH 03/12] Add resolution comment step to submit-for-review post-merge flow --- .agents/skills/submit-for-review/SKILL.md | 22 +++++++++++++++++++++- .claude/commands/submit-for-review.md | 22 +++++++++++++++++++++- .cursor/rules/submit-for-review.mdc | 22 +++++++++++++++++++++- .gemini/skills/submit-for-review/SKILL.md | 22 +++++++++++++++++++++- skills/submit-for-review.md | 20 ++++++++++++++++++++ 5 files changed, 104 insertions(+), 4 deletions(-) diff --git a/.agents/skills/submit-for-review/SKILL.md b/.agents/skills/submit-for-review/SKILL.md index 4bb8b8c..edb53ad 100644 --- a/.agents/skills/submit-for-review/SKILL.md +++ b/.agents/skills/submit-for-review/SKILL.md @@ -198,6 +198,26 @@ gh issue edit --add-label "ready-for-qa" ``` If no linked issue was found, skip silently. +**Post a resolution comment** on the linked issue (skip silently if no linked issue): + +Read the issue body (from Step 3 or via `gh issue view `) to recall the original problem description. Then post a comment summarizing what was done: + +``` +gh issue comment --body-file - <<'EOF' +## Resolution + +<1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> + +See # for full technical details. +EOF +``` + +**Resolution writing rules:** +- Write for PMs and BAs, not developers. Describe the *outcome*, not the implementation. +- Reference the original problem from the issue body so the resolution reads as a direct answer to it. +- Keep it to 1-3 sentences. If one sentence covers it, don't pad. +- Use the unqualified `#N` form for the PR reference. + Report success based on mode: "PR merged. Issues stay open until testing confirms the fix. Run `make deploy-preview` when ready to deploy to preview." @@ -261,4 +281,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. - + diff --git a/.claude/commands/submit-for-review.md b/.claude/commands/submit-for-review.md index cf071a5..12b8720 100644 --- a/.claude/commands/submit-for-review.md +++ b/.claude/commands/submit-for-review.md @@ -193,6 +193,26 @@ gh issue edit --add-label "ready-for-qa" ``` If no linked issue was found, skip silently. +**Post a resolution comment** on the linked issue (skip silently if no linked issue): + +Read the issue body (from Step 3 or via `gh issue view `) to recall the original problem description. Then post a comment summarizing what was done: + +``` +gh issue comment --body-file - <<'EOF' +## Resolution + +<1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> + +See # for full technical details. +EOF +``` + +**Resolution writing rules:** +- Write for PMs and BAs, not developers. Describe the *outcome*, not the implementation. +- Reference the original problem from the issue body so the resolution reads as a direct answer to it. +- Keep it to 1-3 sentences. If one sentence covers it, don't pad. +- Use the unqualified `#N` form for the PR reference. + Report success based on mode: "PR merged. Issues stay open until testing confirms the fix. Run `make deploy-preview` when ready to deploy to preview." @@ -256,4 +276,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. - + diff --git a/.cursor/rules/submit-for-review.mdc b/.cursor/rules/submit-for-review.mdc index 7ac52cf..d0909d3 100644 --- a/.cursor/rules/submit-for-review.mdc +++ b/.cursor/rules/submit-for-review.mdc @@ -199,6 +199,26 @@ gh issue edit --add-label "ready-for-qa" ``` If no linked issue was found, skip silently. +**Post a resolution comment** on the linked issue (skip silently if no linked issue): + +Read the issue body (from Step 3 or via `gh issue view `) to recall the original problem description. Then post a comment summarizing what was done: + +``` +gh issue comment --body-file - <<'EOF' +## Resolution + +<1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> + +See # for full technical details. +EOF +``` + +**Resolution writing rules:** +- Write for PMs and BAs, not developers. Describe the *outcome*, not the implementation. +- Reference the original problem from the issue body so the resolution reads as a direct answer to it. +- Keep it to 1-3 sentences. If one sentence covers it, don't pad. +- Use the unqualified `#N` form for the PR reference. + Report success based on mode: "PR merged. Issues stay open until testing confirms the fix. Run `make deploy-preview` when ready to deploy to preview." @@ -262,4 +282,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. - + diff --git a/.gemini/skills/submit-for-review/SKILL.md b/.gemini/skills/submit-for-review/SKILL.md index fa2e5d5..f834417 100644 --- a/.gemini/skills/submit-for-review/SKILL.md +++ b/.gemini/skills/submit-for-review/SKILL.md @@ -198,6 +198,26 @@ gh issue edit --add-label "ready-for-qa" ``` If no linked issue was found, skip silently. +**Post a resolution comment** on the linked issue (skip silently if no linked issue): + +Read the issue body (from Step 3 or via `gh issue view `) to recall the original problem description. Then post a comment summarizing what was done: + +``` +gh issue comment --body-file - <<'EOF' +## Resolution + +<1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> + +See # for full technical details. +EOF +``` + +**Resolution writing rules:** +- Write for PMs and BAs, not developers. Describe the *outcome*, not the implementation. +- Reference the original problem from the issue body so the resolution reads as a direct answer to it. +- Keep it to 1-3 sentences. If one sentence covers it, don't pad. +- Use the unqualified `#N` form for the PR reference. + Report success based on mode: "PR merged. Issues stay open until testing confirms the fix. Run `make deploy-preview` when ready to deploy to preview." @@ -261,4 +281,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. - + diff --git a/skills/submit-for-review.md b/skills/submit-for-review.md index d598aec..639dd8d 100644 --- a/skills/submit-for-review.md +++ b/skills/submit-for-review.md @@ -228,6 +228,26 @@ If no linked issue was found, skip silently. {{/if}} {{/if}} +**Post a resolution comment** on the linked issue (skip silently if no linked issue): + +Read the issue body (from Step 3 or via `gh issue view `) to recall the original problem description. Then post a comment summarizing what was done: + +``` +gh issue comment --body-file - <<'EOF' +## Resolution + +<1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> + +See # for full technical details. +EOF +``` + +**Resolution writing rules:** +- Write for PMs and BAs, not developers. Describe the *outcome*, not the implementation. +- Reference the original problem from the issue body so the resolution reads as a direct answer to it. +- Keep it to 1-3 sentences. If one sentence covers it, don't pad. +- Use the unqualified `#N` form for the PR reference. + Report success based on mode: {{#if !BRANCH_DEV}} "PR merged. Issue #N closed automatically. Run `{{DEPLOY_PROD_CMD}}` when ready to deploy to production." From 59b17dcacdce16612cefab7d12e0f4f9c48763c2 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart Date: Sat, 11 Apr 2026 09:01:48 -0400 Subject: [PATCH 04/12] Add post-review human gate for non-blocking findings before merge --- .agents/skills/submit-for-review/SKILL.md | 21 +++++++++++++++++++-- .claude/commands/submit-for-review.md | 21 +++++++++++++++++++-- .cursor/rules/submit-for-review.mdc | 21 +++++++++++++++++++-- .gemini/skills/submit-for-review/SKILL.md | 21 +++++++++++++++++++-- skills/submit-for-review.md | 19 ++++++++++++++++++- 5 files changed, 94 insertions(+), 9 deletions(-) diff --git a/.agents/skills/submit-for-review/SKILL.md b/.agents/skills/submit-for-review/SKILL.md index edb53ad..dd35ec9 100644 --- a/.agents/skills/submit-for-review/SKILL.md +++ b/.agents/skills/submit-for-review/SKILL.md @@ -180,7 +180,24 @@ Apply QA label and report success (see below). **If `ai` is `"ai"` (default):** -**If APPROVE (no CRITICAL findings):** Run the merge command. Apply QA label and report success (see below). +**If APPROVE (no CRITICAL findings):** + +Collect any non-blocking findings (`[WARNING]` or `[NOTE]` lines) from the review output. + +- **If there are no non-blocking findings** (clean review): Run the merge command immediately. Apply QA label and report success (see below). + +- **If there are non-blocking findings**: Present the findings as a numbered list (preserve the `[WARNING]` / `[NOTE]` prefix) and say: + + > "The review approved with N non-blocking finding(s): + > + > + > + > Would you like to **address these first** before merging, or **merge now**?" + + Wait for the user to respond. + + - User says **address / fix** → return to the coding loop. Say: "Fix the findings and run `/submit-for-review` again when ready." Do NOT merge. + - User says **merge now** → run the merge command. Apply QA label and report success (see below). Proceed to Step 9 as normal (which will offer to create follow-up issues for any remaining findings). **If REQUEST CHANGES (at least one CRITICAL finding):** Report the findings to the user. Do NOT merge. Say: @@ -281,4 +298,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. - + diff --git a/.claude/commands/submit-for-review.md b/.claude/commands/submit-for-review.md index 12b8720..95d9218 100644 --- a/.claude/commands/submit-for-review.md +++ b/.claude/commands/submit-for-review.md @@ -175,7 +175,24 @@ Apply QA label and report success (see below). **If `ai` is `"ai"` (default):** -**If APPROVE (no CRITICAL findings):** Run the merge command. Apply QA label and report success (see below). +**If APPROVE (no CRITICAL findings):** + +Collect any non-blocking findings (`[WARNING]` or `[NOTE]` lines) from the review output. + +- **If there are no non-blocking findings** (clean review): Run the merge command immediately. Apply QA label and report success (see below). + +- **If there are non-blocking findings**: Present the findings as a numbered list (preserve the `[WARNING]` / `[NOTE]` prefix) and say: + + > "The review approved with N non-blocking finding(s): + > + > + > + > Would you like to **address these first** before merging, or **merge now**?" + + Wait for the user to respond. + + - User says **address / fix** → return to the coding loop. Say: "Fix the findings and run `/submit-for-review` again when ready." Do NOT merge. + - User says **merge now** → run the merge command. Apply QA label and report success (see below). Proceed to Step 9 as normal (which will offer to create follow-up issues for any remaining findings). **If REQUEST CHANGES (at least one CRITICAL finding):** Report the findings to the user. Do NOT merge. Say: @@ -276,4 +293,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. - + diff --git a/.cursor/rules/submit-for-review.mdc b/.cursor/rules/submit-for-review.mdc index d0909d3..ef6b002 100644 --- a/.cursor/rules/submit-for-review.mdc +++ b/.cursor/rules/submit-for-review.mdc @@ -181,7 +181,24 @@ Apply QA label and report success (see below). **If `ai` is `"ai"` (default):** -**If APPROVE (no CRITICAL findings):** Run the merge command. Apply QA label and report success (see below). +**If APPROVE (no CRITICAL findings):** + +Collect any non-blocking findings (`[WARNING]` or `[NOTE]` lines) from the review output. + +- **If there are no non-blocking findings** (clean review): Run the merge command immediately. Apply QA label and report success (see below). + +- **If there are non-blocking findings**: Present the findings as a numbered list (preserve the `[WARNING]` / `[NOTE]` prefix) and say: + + > "The review approved with N non-blocking finding(s): + > + > + > + > Would you like to **address these first** before merging, or **merge now**?" + + Wait for the user to respond. + + - User says **address / fix** → return to the coding loop. Say: "Fix the findings and run `/submit-for-review` again when ready." Do NOT merge. + - User says **merge now** → run the merge command. Apply QA label and report success (see below). Proceed to Step 9 as normal (which will offer to create follow-up issues for any remaining findings). **If REQUEST CHANGES (at least one CRITICAL finding):** Report the findings to the user. Do NOT merge. Say: @@ -282,4 +299,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. - + diff --git a/.gemini/skills/submit-for-review/SKILL.md b/.gemini/skills/submit-for-review/SKILL.md index f834417..c494469 100644 --- a/.gemini/skills/submit-for-review/SKILL.md +++ b/.gemini/skills/submit-for-review/SKILL.md @@ -180,7 +180,24 @@ Apply QA label and report success (see below). **If `ai` is `"ai"` (default):** -**If APPROVE (no CRITICAL findings):** Run the merge command. Apply QA label and report success (see below). +**If APPROVE (no CRITICAL findings):** + +Collect any non-blocking findings (`[WARNING]` or `[NOTE]` lines) from the review output. + +- **If there are no non-blocking findings** (clean review): Run the merge command immediately. Apply QA label and report success (see below). + +- **If there are non-blocking findings**: Present the findings as a numbered list (preserve the `[WARNING]` / `[NOTE]` prefix) and say: + + > "The review approved with N non-blocking finding(s): + > + > + > + > Would you like to **address these first** before merging, or **merge now**?" + + Wait for the user to respond. + + - User says **address / fix** → return to the coding loop. Say: "Fix the findings and run `/submit-for-review` again when ready." Do NOT merge. + - User says **merge now** → run the merge command. Apply QA label and report success (see below). Proceed to Step 9 as normal (which will offer to create follow-up issues for any remaining findings). **If REQUEST CHANGES (at least one CRITICAL finding):** Report the findings to the user. Do NOT merge. Say: @@ -281,4 +298,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. - + diff --git a/skills/submit-for-review.md b/skills/submit-for-review.md index 639dd8d..9def763 100644 --- a/skills/submit-for-review.md +++ b/skills/submit-for-review.md @@ -204,7 +204,24 @@ Apply QA label and report success (see below). **If `{{REVIEW_GATE}}` is `"ai"` (default):** -**If APPROVE (no CRITICAL findings):** Run the merge command. Apply QA label and report success (see below). +**If APPROVE (no CRITICAL findings):** + +Collect any non-blocking findings (`[WARNING]` or `[NOTE]` lines) from the review output. + +- **If there are no non-blocking findings** (clean review): Run the merge command immediately. Apply QA label and report success (see below). + +- **If there are non-blocking findings**: Present the findings as a numbered list (preserve the `[WARNING]` / `[NOTE]` prefix) and say: + + > "The review approved with N non-blocking finding(s): + > + > + > + > Would you like to **address these first** before merging, or **merge now**?" + + Wait for the user to respond. + + - User says **address / fix** → return to the coding loop. Say: "Fix the findings and run `/submit-for-review` again when ready." Do NOT merge. + - User says **merge now** → run the merge command. Apply QA label and report success (see below). Proceed to Step 9 as normal (which will offer to create follow-up issues for any remaining findings). **If REQUEST CHANGES (at least one CRITICAL finding):** Report the findings to the user. Do NOT merge. Say: From 08aeb94d02f328d02b4da06b8a208b39990337a0 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart Date: Sat, 11 Apr 2026 09:20:28 -0400 Subject: [PATCH 05/12] Clarify /start human gate messages with intent classification and 'go' shorthand --- .agents/skills/start/SKILL.md | 28 +++++++++++++++++++--------- .claude/commands/start.md | 28 +++++++++++++++++++--------- .cursor/rules/start.mdc | 28 +++++++++++++++++++--------- .gemini/skills/start/SKILL.md | 28 +++++++++++++++++++--------- skills/start.md | 26 ++++++++++++++++++-------- 5 files changed, 94 insertions(+), 44 deletions(-) diff --git a/.agents/skills/start/SKILL.md b/.agents/skills/start/SKILL.md index 92be2cc..3c8989c 100644 --- a/.agents/skills/start/SKILL.md +++ b/.agents/skills/start/SKILL.md @@ -76,15 +76,20 @@ Read the relevant code. Propose a concrete implementation approach. Be specific ### Step 2 — HUMAN GATE -Say exactly: **"Does this approach sound right? I'll create a GitHub issue and branch before writing any code."** +Say exactly: -Stop. Wait for the user to confirm. +> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** + +Stop. Wait for the user to respond. The friendly text question is required regardless of harness mode. If your harness is currently in a preview / plan / dry-run mode where you cannot passively stop and wait (and must instead invoke the harness's own approval mechanism), still include the text question in your response. The harness's approval UI mediates the wait, but it is not a substitute for the question itself. Users expect to see the consistent text language across all modes; do not silently swap it for the harness's UI. -- User says yes → continue to Step 3. -- User redirects → revise approach, ask again. -- User abandons → stop. Nothing to clean up. +**Intent classification (not keyword matching):** + +- **Affirmative with no conditions** ("go", "yes", "looks good", "let's do it") → continue to Step 3. +- **Affirmative with conditions** ("go, but first change X", "yes but can we also...") → treat as discussion. Address the conditions, revise the approach if needed, then re-ask. +- **Questions or pushback** ("what about...", "I'm not sure about...", any adjustment) → discuss, revise approach, re-ask. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Create GitHub Issue @@ -203,10 +208,15 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Continue this ticket, or open a fresh one?"** +Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** + +**Intent classification (not keyword matching):** -- Continue → Step 3. -- New ticket → restart as Case A with a new description. +- **Affirmative with no conditions** ("go", "yes", "continue", "looks right") → proceed to Step 3. +- **Affirmative with conditions** ("go, but first...", "yes but let's also...") → treat as discussion. Address the conditions, then re-ask. +- **Questions or discussion** ("what about...", "can we change...", any adjustment) → discuss, then re-ask. +- **Fresh start** ("open a new one", "start fresh", "new ticket") → restart as Case A with a new description. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Check out branch @@ -254,4 +264,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.claude/commands/start.md b/.claude/commands/start.md index 2bd19c1..8a95539 100644 --- a/.claude/commands/start.md +++ b/.claude/commands/start.md @@ -71,15 +71,20 @@ Read the relevant code. Propose a concrete implementation approach. Be specific ### Step 2 — HUMAN GATE -Say exactly: **"Does this approach sound right? I'll create a GitHub issue and branch before writing any code."** +Say exactly: -Stop. Wait for the user to confirm. +> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** + +Stop. Wait for the user to respond. The friendly text question is required regardless of harness mode. If your harness is currently in a preview / plan / dry-run mode where you cannot passively stop and wait (and must instead invoke the harness's own approval mechanism), still include the text question in your response. The harness's approval UI mediates the wait, but it is not a substitute for the question itself. Users expect to see the consistent text language across all modes; do not silently swap it for the harness's UI. -- User says yes → continue to Step 3. -- User redirects → revise approach, ask again. -- User abandons → stop. Nothing to clean up. +**Intent classification (not keyword matching):** + +- **Affirmative with no conditions** ("go", "yes", "looks good", "let's do it") → continue to Step 3. +- **Affirmative with conditions** ("go, but first change X", "yes but can we also...") → treat as discussion. Address the conditions, revise the approach if needed, then re-ask. +- **Questions or pushback** ("what about...", "I'm not sure about...", any adjustment) → discuss, revise approach, re-ask. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Create GitHub Issue @@ -198,10 +203,15 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Continue this ticket, or open a fresh one?"** +Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** + +**Intent classification (not keyword matching):** -- Continue → Step 3. -- New ticket → restart as Case A with a new description. +- **Affirmative with no conditions** ("go", "yes", "continue", "looks right") → proceed to Step 3. +- **Affirmative with conditions** ("go, but first...", "yes but let's also...") → treat as discussion. Address the conditions, then re-ask. +- **Questions or discussion** ("what about...", "can we change...", any adjustment) → discuss, then re-ask. +- **Fresh start** ("open a new one", "start fresh", "new ticket") → restart as Case A with a new description. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Check out branch @@ -249,4 +259,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.cursor/rules/start.mdc b/.cursor/rules/start.mdc index 54ca08c..e6a3dfd 100644 --- a/.cursor/rules/start.mdc +++ b/.cursor/rules/start.mdc @@ -77,15 +77,20 @@ Read the relevant code. Propose a concrete implementation approach. Be specific ### Step 2 — HUMAN GATE -Say exactly: **"Does this approach sound right? I'll create a GitHub issue and branch before writing any code."** +Say exactly: -Stop. Wait for the user to confirm. +> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** + +Stop. Wait for the user to respond. The friendly text question is required regardless of harness mode. If your harness is currently in a preview / plan / dry-run mode where you cannot passively stop and wait (and must instead invoke the harness's own approval mechanism), still include the text question in your response. The harness's approval UI mediates the wait, but it is not a substitute for the question itself. Users expect to see the consistent text language across all modes; do not silently swap it for the harness's UI. -- User says yes → continue to Step 3. -- User redirects → revise approach, ask again. -- User abandons → stop. Nothing to clean up. +**Intent classification (not keyword matching):** + +- **Affirmative with no conditions** ("go", "yes", "looks good", "let's do it") → continue to Step 3. +- **Affirmative with conditions** ("go, but first change X", "yes but can we also...") → treat as discussion. Address the conditions, revise the approach if needed, then re-ask. +- **Questions or pushback** ("what about...", "I'm not sure about...", any adjustment) → discuss, revise approach, re-ask. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Create GitHub Issue @@ -204,10 +209,15 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Continue this ticket, or open a fresh one?"** +Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** + +**Intent classification (not keyword matching):** -- Continue → Step 3. -- New ticket → restart as Case A with a new description. +- **Affirmative with no conditions** ("go", "yes", "continue", "looks right") → proceed to Step 3. +- **Affirmative with conditions** ("go, but first...", "yes but let's also...") → treat as discussion. Address the conditions, then re-ask. +- **Questions or discussion** ("what about...", "can we change...", any adjustment) → discuss, then re-ask. +- **Fresh start** ("open a new one", "start fresh", "new ticket") → restart as Case A with a new description. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Check out branch @@ -255,4 +265,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.gemini/skills/start/SKILL.md b/.gemini/skills/start/SKILL.md index 28593a4..b829f50 100644 --- a/.gemini/skills/start/SKILL.md +++ b/.gemini/skills/start/SKILL.md @@ -76,15 +76,20 @@ Read the relevant code. Propose a concrete implementation approach. Be specific ### Step 2 — HUMAN GATE -Say exactly: **"Does this approach sound right? I'll create a GitHub issue and branch before writing any code."** +Say exactly: -Stop. Wait for the user to confirm. +> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** + +Stop. Wait for the user to respond. The friendly text question is required regardless of harness mode. If your harness is currently in a preview / plan / dry-run mode where you cannot passively stop and wait (and must instead invoke the harness's own approval mechanism), still include the text question in your response. The harness's approval UI mediates the wait, but it is not a substitute for the question itself. Users expect to see the consistent text language across all modes; do not silently swap it for the harness's UI. -- User says yes → continue to Step 3. -- User redirects → revise approach, ask again. -- User abandons → stop. Nothing to clean up. +**Intent classification (not keyword matching):** + +- **Affirmative with no conditions** ("go", "yes", "looks good", "let's do it") → continue to Step 3. +- **Affirmative with conditions** ("go, but first change X", "yes but can we also...") → treat as discussion. Address the conditions, revise the approach if needed, then re-ask. +- **Questions or pushback** ("what about...", "I'm not sure about...", any adjustment) → discuss, revise approach, re-ask. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Create GitHub Issue @@ -203,10 +208,15 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Continue this ticket, or open a fresh one?"** +Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** + +**Intent classification (not keyword matching):** -- Continue → Step 3. -- New ticket → restart as Case A with a new description. +- **Affirmative with no conditions** ("go", "yes", "continue", "looks right") → proceed to Step 3. +- **Affirmative with conditions** ("go, but first...", "yes but let's also...") → treat as discussion. Address the conditions, then re-ask. +- **Questions or discussion** ("what about...", "can we change...", any adjustment) → discuss, then re-ask. +- **Fresh start** ("open a new one", "start fresh", "new ticket") → restart as Case A with a new description. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Check out branch @@ -254,4 +264,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/skills/start.md b/skills/start.md index 19d448f..90f8bda 100644 --- a/skills/start.md +++ b/skills/start.md @@ -119,15 +119,20 @@ Read the relevant code. Propose a concrete implementation approach. Be specific ### Step 2 — HUMAN GATE -Say exactly: **"Does this approach sound right? I'll create a GitHub issue and branch before writing any code."** +Say exactly: -Stop. Wait for the user to confirm. +> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** + +Stop. Wait for the user to respond. The friendly text question is required regardless of harness mode. If your harness is currently in a preview / plan / dry-run mode where you cannot passively stop and wait (and must instead invoke the harness's own approval mechanism), still include the text question in your response. The harness's approval UI mediates the wait, but it is not a substitute for the question itself. Users expect to see the consistent text language across all modes; do not silently swap it for the harness's UI. -- User says yes → continue to Step 3. -- User redirects → revise approach, ask again. -- User abandons → stop. Nothing to clean up. +**Intent classification (not keyword matching):** + +- **Affirmative with no conditions** ("go", "yes", "looks good", "let's do it") → continue to Step 3. +- **Affirmative with conditions** ("go, but first change X", "yes but can we also...") → treat as discussion. Address the conditions, revise the approach if needed, then re-ask. +- **Questions or pushback** ("what about...", "I'm not sure about...", any adjustment) → discuss, revise approach, re-ask. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Create GitHub Issue @@ -262,10 +267,15 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Continue this ticket, or open a fresh one?"** +Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** + +**Intent classification (not keyword matching):** -- Continue → Step 3. -- New ticket → restart as Case A with a new description. +- **Affirmative with no conditions** ("go", "yes", "continue", "looks right") → proceed to Step 3. +- **Affirmative with conditions** ("go, but first...", "yes but let's also...") → treat as discussion. Address the conditions, then re-ask. +- **Questions or discussion** ("what about...", "can we change...", any adjustment) → discuss, then re-ask. +- **Fresh start** ("open a new one", "start fresh", "new ticket") → restart as Case A with a new description. +- **Abandonment** ("never mind", "not now", "stop") → stop. Nothing to clean up. ### Step 3 — Check out branch From ecb534e0ed9dd2b92d39127e79ab8fa5a333ec86 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart Date: Sat, 11 Apr 2026 09:24:06 -0400 Subject: [PATCH 06/12] Fix nested double quotes in gate messages by using backtick-quoted go --- .agents/skills/start/SKILL.md | 6 +++--- .claude/commands/start.md | 6 +++--- .cursor/rules/start.mdc | 6 +++--- .gemini/skills/start/SKILL.md | 6 +++--- skills/start.md | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.agents/skills/start/SKILL.md b/.agents/skills/start/SKILL.md index 3c8989c..44a5230 100644 --- a/.agents/skills/start/SKILL.md +++ b/.agents/skills/start/SKILL.md @@ -78,7 +78,7 @@ Read the relevant code. Propose a concrete implementation approach. Be specific Say exactly: -> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** +> **"Does this approach sound right? Type `go` to create a GitHub issue and branch, or share any questions/adjustments first."** Stop. Wait for the user to respond. @@ -208,7 +208,7 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** +Ask: **"Does this match your understanding? Type `go` to start coding, or share any questions/adjustments first."** **Intent classification (not keyword matching):** @@ -264,4 +264,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.claude/commands/start.md b/.claude/commands/start.md index 8a95539..6ad8207 100644 --- a/.claude/commands/start.md +++ b/.claude/commands/start.md @@ -73,7 +73,7 @@ Read the relevant code. Propose a concrete implementation approach. Be specific Say exactly: -> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** +> **"Does this approach sound right? Type `go` to create a GitHub issue and branch, or share any questions/adjustments first."** Stop. Wait for the user to respond. @@ -203,7 +203,7 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** +Ask: **"Does this match your understanding? Type `go` to start coding, or share any questions/adjustments first."** **Intent classification (not keyword matching):** @@ -259,4 +259,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.cursor/rules/start.mdc b/.cursor/rules/start.mdc index e6a3dfd..50a2546 100644 --- a/.cursor/rules/start.mdc +++ b/.cursor/rules/start.mdc @@ -79,7 +79,7 @@ Read the relevant code. Propose a concrete implementation approach. Be specific Say exactly: -> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** +> **"Does this approach sound right? Type `go` to create a GitHub issue and branch, or share any questions/adjustments first."** Stop. Wait for the user to respond. @@ -209,7 +209,7 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** +Ask: **"Does this match your understanding? Type `go` to start coding, or share any questions/adjustments first."** **Intent classification (not keyword matching):** @@ -265,4 +265,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/.gemini/skills/start/SKILL.md b/.gemini/skills/start/SKILL.md index b829f50..f5121dd 100644 --- a/.gemini/skills/start/SKILL.md +++ b/.gemini/skills/start/SKILL.md @@ -78,7 +78,7 @@ Read the relevant code. Propose a concrete implementation approach. Be specific Say exactly: -> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** +> **"Does this approach sound right? Type `go` to create a GitHub issue and branch, or share any questions/adjustments first."** Stop. Wait for the user to respond. @@ -208,7 +208,7 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** +Ask: **"Does this match your understanding? Type `go` to start coding, or share any questions/adjustments first."** **Intent classification (not keyword matching):** @@ -264,4 +264,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. - + diff --git a/skills/start.md b/skills/start.md index 90f8bda..421c404 100644 --- a/skills/start.md +++ b/skills/start.md @@ -121,7 +121,7 @@ Read the relevant code. Propose a concrete implementation approach. Be specific Say exactly: -> **"Does this approach sound right? Type "go" to create a GitHub issue and branch, or share any questions/adjustments first."** +> **"Does this approach sound right? Type `go` to create a GitHub issue and branch, or share any questions/adjustments first."** Stop. Wait for the user to respond. @@ -267,7 +267,7 @@ Tell the user: - What was previously done (from agent notes if present) - What appears to remain -Ask: **"Does this match your understanding? Type "go" to start coding, or share any questions/adjustments first."** +Ask: **"Does this match your understanding? Type `go` to start coding, or share any questions/adjustments first."** **Intent classification (not keyword matching):** From cb458970bee0d4bd06a1e8af59acf8066d05a7c7 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart Date: Sat, 11 Apr 2026 09:30:50 -0400 Subject: [PATCH 07/12] Fix start.md gh commands missed in #82 body-file conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original fix converted submit-for-review.md and deploy.md but missed start.md, where gh issue create and gh issue comment still used inline --body with multi-line content — causing Claude to wrap them in $(cat < --- skills/start.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/skills/start.md b/skills/start.md index 421c404..aefb3b8 100644 --- a/skills/start.md +++ b/skills/start.md @@ -141,12 +141,16 @@ Run `gh issue create` with explicit flags (do NOT open an interactive editor): ```bash gh issue create \ --title "" \ - --body "" \ --assignee @me \ [--label ""] \ - [--milestone ""] + [--milestone ""] \ + --body-file - <<'EOF' + +EOF ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. + Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label ""` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. - **Milestone**: use the value from three-tier milestone resolution. If non-empty, add `--milestone ""` to the command. If empty (no flag, no config default, no open milestones), omit `--milestone` entirely. @@ -191,9 +195,11 @@ Show the user: `Created issue #: ` Then immediately post agent implementation notes as a comment: ```bash -gh issue comment <number> --body "## Agent Implementation Notes +gh issue comment <number> --body-file - <<'EOF' +## Agent Implementation Notes -<full technical plan: exact files to change, approach, key decisions, edge cases>" +<full technical plan: exact files to change, approach, key decisions, edge cases> +EOF ``` ### Step 4 — Create feature branch From e12dfdfba006e0a2408ad2f440461d8c7fec7758 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart <sebastien.taggart@gmail.com> Date: Sat, 11 Apr 2026 09:39:37 -0400 Subject: [PATCH 08/12] Regenerate start skill adapter files after body-file conversion --- .agents/skills/start/SKILL.md | 16 +++++++++++----- .claude/commands/start.md | 16 +++++++++++----- .cursor/rules/start.mdc | 16 +++++++++++----- .gemini/skills/start/SKILL.md | 16 +++++++++++----- 4 files changed, 44 insertions(+), 20 deletions(-) diff --git a/.agents/skills/start/SKILL.md b/.agents/skills/start/SKILL.md index 44a5230..47881d4 100644 --- a/.agents/skills/start/SKILL.md +++ b/.agents/skills/start/SKILL.md @@ -98,12 +98,16 @@ Run `gh issue create` with explicit flags (do NOT open an interactive editor): ```bash gh issue create \ --title "<standalone full sentence — must make sense with no context>" \ - --body "<structured markdown body — see sections below>" \ --assignee @me \ [--label "<resolved labels>"] \ - [--milestone "<resolved milestone>"] + [--milestone "<resolved milestone>"] \ + --body-file - <<'EOF' +<structured markdown body — see sections below> +EOF ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. + Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. - **Milestone**: use the value from three-tier milestone resolution. If non-empty, add `--milestone "<value>"` to the command. If empty (no flag, no config default, no open milestones), omit `--milestone` entirely. @@ -148,9 +152,11 @@ Show the user: `Created issue #<number>: <title>` Then immediately post agent implementation notes as a comment: ```bash -gh issue comment <number> --body "## Agent Implementation Notes +gh issue comment <number> --body-file - <<'EOF' +## Agent Implementation Notes -<full technical plan: exact files to change, approach, key decisions, edge cases>" +<full technical plan: exact files to change, approach, key decisions, edge cases> +EOF ``` ### Step 4 — Create feature branch @@ -264,4 +270,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit <number> --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. -<!-- generated by CodeCannon/sync.sh | skill: start | adapter: codex | hash: 8f527994 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: start | adapter: codex | hash: 5603cf1a | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.claude/commands/start.md b/.claude/commands/start.md index 6ad8207..edbe3e6 100644 --- a/.claude/commands/start.md +++ b/.claude/commands/start.md @@ -93,12 +93,16 @@ Run `gh issue create` with explicit flags (do NOT open an interactive editor): ```bash gh issue create \ --title "<standalone full sentence — must make sense with no context>" \ - --body "<structured markdown body — see sections below>" \ --assignee @me \ [--label "<resolved labels>"] \ - [--milestone "<resolved milestone>"] + [--milestone "<resolved milestone>"] \ + --body-file - <<'EOF' +<structured markdown body — see sections below> +EOF ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. + Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. - **Milestone**: use the value from three-tier milestone resolution. If non-empty, add `--milestone "<value>"` to the command. If empty (no flag, no config default, no open milestones), omit `--milestone` entirely. @@ -143,9 +147,11 @@ Show the user: `Created issue #<number>: <title>` Then immediately post agent implementation notes as a comment: ```bash -gh issue comment <number> --body "## Agent Implementation Notes +gh issue comment <number> --body-file - <<'EOF' +## Agent Implementation Notes -<full technical plan: exact files to change, approach, key decisions, edge cases>" +<full technical plan: exact files to change, approach, key decisions, edge cases> +EOF ``` ### Step 4 — Create feature branch @@ -259,4 +265,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit <number> --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. -<!-- generated by CodeCannon/sync.sh | skill: start | adapter: claude | hash: 70ba0327 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: start | adapter: claude | hash: 3c1bac69 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.cursor/rules/start.mdc b/.cursor/rules/start.mdc index 50a2546..58a770b 100644 --- a/.cursor/rules/start.mdc +++ b/.cursor/rules/start.mdc @@ -99,12 +99,16 @@ Run `gh issue create` with explicit flags (do NOT open an interactive editor): ```bash gh issue create \ --title "<standalone full sentence — must make sense with no context>" \ - --body "<structured markdown body — see sections below>" \ --assignee @me \ [--label "<resolved labels>"] \ - [--milestone "<resolved milestone>"] + [--milestone "<resolved milestone>"] \ + --body-file - <<'EOF' +<structured markdown body — see sections below> +EOF ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. + Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. - **Milestone**: use the value from three-tier milestone resolution. If non-empty, add `--milestone "<value>"` to the command. If empty (no flag, no config default, no open milestones), omit `--milestone` entirely. @@ -149,9 +153,11 @@ Show the user: `Created issue #<number>: <title>` Then immediately post agent implementation notes as a comment: ```bash -gh issue comment <number> --body "## Agent Implementation Notes +gh issue comment <number> --body-file - <<'EOF' +## Agent Implementation Notes -<full technical plan: exact files to change, approach, key decisions, edge cases>" +<full technical plan: exact files to change, approach, key decisions, edge cases> +EOF ``` ### Step 4 — Create feature branch @@ -265,4 +271,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit <number> --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. -<!-- generated by CodeCannon/sync.sh | skill: start | adapter: cursor | hash: 563587df | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: start | adapter: cursor | hash: fad7e3ef | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.gemini/skills/start/SKILL.md b/.gemini/skills/start/SKILL.md index f5121dd..6695df4 100644 --- a/.gemini/skills/start/SKILL.md +++ b/.gemini/skills/start/SKILL.md @@ -98,12 +98,16 @@ Run `gh issue create` with explicit flags (do NOT open an interactive editor): ```bash gh issue create \ --title "<standalone full sentence — must make sense with no context>" \ - --body "<structured markdown body — see sections below>" \ --assignee @me \ [--label "<resolved labels>"] \ - [--milestone "<resolved milestone>"] + [--milestone "<resolved milestone>"] \ + --body-file - <<'EOF' +<structured markdown body — see sections below> +EOF ``` +> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. + Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. - **Milestone**: use the value from three-tier milestone resolution. If non-empty, add `--milestone "<value>"` to the command. If empty (no flag, no config default, no open milestones), omit `--milestone` entirely. @@ -148,9 +152,11 @@ Show the user: `Created issue #<number>: <title>` Then immediately post agent implementation notes as a comment: ```bash -gh issue comment <number> --body "## Agent Implementation Notes +gh issue comment <number> --body-file - <<'EOF' +## Agent Implementation Notes -<full technical plan: exact files to change, approach, key decisions, edge cases>" +<full technical plan: exact files to change, approach, key decisions, edge cases> +EOF ``` ### Step 4 — Create feature branch @@ -264,4 +270,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit <number> --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. -<!-- generated by CodeCannon/sync.sh | skill: start | adapter: gemini | hash: 8d797a55 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: start | adapter: gemini | hash: 064b9454 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> From 22c61f7f9145cb7dba5fa7c1587f1ce701ef55ac Mon Sep 17 00:00:00 2001 From: Sebastien Taggart <sebastien.taggart@gmail.com> Date: Sat, 11 Apr 2026 10:14:28 -0400 Subject: [PATCH 09/12] Update docs for recent features and simplify README into a marketing page --- README.md | 92 ++++++++------------------------ docs/index.md | 2 +- docs/skills/start.md | 17 ++++-- docs/skills/submit-for-review.md | 4 +- 4 files changed, 39 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 0177c8c..7535f6f 100644 --- a/README.md +++ b/README.md @@ -2,123 +2,75 @@ # Code Cannon -A portable agent workflow skill library. Write your team's development workflow once — start, submit-for-review, review, deploy — and sync it to Claude Code, Cursor, and other AI coding agents across all your projects. - -Repository: [github.com/LightbridgeLab/CodeCannon](https://github.com/LightbridgeLab/CodeCannon) +Write your team's AI agent workflow once — start, submit-for-review, review, deploy — and sync it to Claude Code, Cursor, Gemini, and Codex across all your projects. ## The problem -AI coding agents are powerful, but every project reinvents the same workflows: how to create issues, open PRs, run reviews, bump versions, deploy releases. These instructions live in scattered prompt files, maintained per-project, per-agent, with no consistency and no reuse. +AI coding agents are powerful, but every project reinvents the same workflows: how to create issues, open PRs, run reviews, deploy releases. These instructions live in scattered prompt files, maintained per-project, per-agent, with no consistency and no reuse. ## The solution -Code Cannon is a shared skill library that lives as a git submodule. Skills are written once as portable markdown with placeholder tokens. A sync script reads your project config, substitutes values, and generates agent-specific command files for each AI tool your team uses. +Code Cannon is a shared skill library that lives as a git submodule. Skills are written once as portable markdown. A sync script reads your project config and generates agent-specific command files: ``` skills/*.md → sync.sh + .codecannon.yaml → .claude/commands/*.md → .cursor/rules/*.mdc ``` -One source of truth. Every project. Every agent. +One source of truth for every project and every agent. ## What you get -**A complete development workflow in five commands:** +A complete development workflow in five commands: ``` /start → [code + test] → /submit-for-review → [QA] → /deploy ``` -- `/start` — creates a GitHub issue, feature branch, and writes code (with human approval before any work begins) -- `/submit-for-review` — checks, commits, opens PR, runs AI review, merges -- `/review` — standalone code review on any PR -- `/deploy` — bumps version, creates a GitHub Release, promotes to production -- `/status` — standup-ready snapshot of PRs, issues, and progress +| Command | What it does | +|---|---| +| `/start` | Create a GitHub issue, feature branch, and write code | +| `/submit-for-review` | Check, commit, open PR, run AI review, merge | +| `/review` | Standalone code review on any PR | +| `/deploy` | Bump version, create a GitHub Release, promote to production | +| `/status` | Standup-ready snapshot of PRs, issues, and progress | Plus `/qa` for structured QA workflows and `/setup` for guided onboarding. +![Code Cannon Agents Working With Humans](.github/assets/readme-inline-agents-working-with-humans.png) + ## Philosophy -**Humans stay in the loop.** The agent proposes; you approve. `/start` waits for your sign-off before creating anything. `/deploy` requires explicit confirmation. The agent commits; you test. +**Humans stay in the loop.** The agent proposes; you approve. `/start` waits for your sign-off before creating anything. `/deploy` requires explicit confirmation. **Every change has a ticket.** There is no path for code without an issue. The issue is the unit of work — branch, PR, and release all link back to it. -## GitHub baseline for PM/BA setup - -If your repo is new and you want predictable behavior from `/start` and `/qa`, configure a minimal GitHub baseline before day-to-day usage: - -- **Starter labels for issue intake:** `bug`, `enhancement`, `chore`, `documentation` -- **QA lifecycle labels:** `ready-for-qa`, `qa-passed`, `qa-failed` -- **Optional planning labels:** a single priority scheme (for example `priority:high`, `priority:medium`, `priority:low`) - -How this maps to Code Cannon behavior: - -- `/start` uses `TICKET_LABELS` as its allowed label pool when creating issues. -- `/qa` depends on `QA_READY_LABEL` to build the QA queue and applies `QA_PASSED_LABEL` or `QA_FAILED_LABEL` as verdicts. -- Milestones can stay dynamic (auto-detected from GitHub open milestones) or be pinned using `DEFAULT_MILESTONE` when your team runs fixed iterations (for example `Sprint 12` or `Release 2026.04`). - -For first-time setup, run `/setup`; it can populate labels and walk through these options interactively. - -**Reviewer selection is never automatic.** `/submit-for-review` adds reviewers only from two sources: a detected `CODEOWNERS` file (checked in `CODEOWNERS`, `.github/CODEOWNERS`, and `docs/CODEOWNERS`) and the `DEFAULT_REVIEWERS` config key. The agent never infers reviewers from git history, blame, or team membership. - -**Configure, don't fork.** Skills use `{{PLACEHOLDER}}` tokens for project-specific values. Your `.codecannon.yaml` fills them in. When upstream skills improve, pull the submodule and re-sync. - -**Agent-agnostic.** Skills are written once. Adapters handle the translation to Claude Code, Cursor, or any future agent. - -![Code Cannon Agents Working With Humans](.github/assets/readme-inline-agents-working-with-humans.png) +**Configure, don't fork.** Skills use `{{PLACEHOLDER}}` tokens. Your `.codecannon.yaml` fills them in. When upstream improves, pull the submodule and re-sync. ## Quick start ```bash -# Add Code Cannon to your project git submodule add https://github.com/LightbridgeLab/CodeCannon.git CodeCannon -git submodule update --init - -# Create and edit your config cp CodeCannon/templates/codecannon.yaml .codecannon.yaml - -# Generate skill files CodeCannon/sync.sh ``` -To update Code Cannon to the latest version, run from your project root: - -```bash -CodeCannon/sync.sh --update -``` - -This pulls the latest `main` in the CodeCannon checkout and regenerates your project's skill files in one step. If the CodeCannon checkout is on a branch other than `main`, `--update` stops with a message — update it manually and re-run `sync.sh` without `--update`. +Then optionally run `/setup` for a guided walkthrough. -If you installed Code Cannon as a git submodule, you can instead pin to the new commit: +To update to the latest version: ```bash -git submodule update --remote CodeCannon -git add CodeCannon -git commit -m "Update CodeCannon submodule to latest" -CodeCannon/sync.sh +CodeCannon/sync.sh --update ``` -Or run `/setup` for a guided walkthrough that detects your project state and configures everything interactively. - ## Documentation -- **[Getting started](docs/index.md)** — detailed overview, full quickstart, migration guide +- **[Getting started](docs/index.md)** — full quickstart, migration guide, and workflow details - **[Branching models](docs/branching.md)** — trunk, two-branch, and three-branch workflows -- **[Customization](docs/customization.md)** — tailoring skills to your project, sync.sh reference +- **[Customization](docs/customization.md)** — tailoring skills, sync.sh reference - **[Config reference](docs/config-reference.md)** — every `.codecannon.yaml` setting documented - **[Adapters](docs/adapters.md)** — supported agents and how to add new ones - -### Skill reference - -| Skill | Docs | Description | -|---|---|---| -| `/start` | [docs](docs/skills/start.md) | Create a GitHub issue, branch, and write code | -| `/submit-for-review` | [docs](docs/skills/submit-for-review.md) | Check, commit, open PR, review, merge | -| `/review` | [docs](docs/skills/review.md) | Standalone code review on a PR | -| `/deploy` | [docs](docs/skills/deploy.md) | Bump version, create GitHub Release, promote to production | -| `/qa` | [docs](docs/skills/qa.md) | QA queue and structured review workflow | -| `/status` | [docs](docs/skills/status.md) | Snapshot of PRs, issues, and progress | -| `/setup` | [docs](docs/skills/setup.md) | Guided onboarding and configuration | +- **Skill reference:** [/start](docs/skills/start.md) · [/submit-for-review](docs/skills/submit-for-review.md) · [/review](docs/skills/review.md) · [/deploy](docs/skills/deploy.md) · [/qa](docs/skills/qa.md) · [/status](docs/skills/status.md) · [/setup](docs/skills/setup.md) ## License diff --git a/docs/index.md b/docs/index.md index 9d92188..6202157 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,9 +29,9 @@ The intended sequence for a complete change: Code Cannon is opinionated about where humans stay in the loop: - `/start` pauses before creating the issue to confirm the implementation approach. +- `/submit-for-review` pauses after review if there are non-blocking findings, letting you choose to address them or merge now. - `/deploy` requires an explicit "release" confirmation before promoting to production. - `/qa` shows the review comment and waits for approval before posting. -- Everything else runs unattended. The agent commits; you test. `/start` writes code but does not commit — it hands off to you with "run your dev command and test locally." Committing happens in `/submit-for-review`. The human approval loop before shipping is where you catch things the agent missed. diff --git a/docs/skills/start.md b/docs/skills/start.md index db2c2db..2fbab94 100644 --- a/docs/skills/start.md +++ b/docs/skills/start.md @@ -40,9 +40,20 @@ Flags replace auto-selection entirely; they do not append. 1. **Investigate** — the agent reads relevant code and proposes a concrete implementation approach, specifying which files change and how. -2. **Human gate** — the agent asks: *"Does this approach sound right? I'll create a GitHub issue and branch before writing any code."* Nothing happens until you confirm. +2. **Human gate** — the agent asks: *"Does this approach sound right? Type `go` to create a GitHub issue and branch, or share any questions/adjustments first."* The agent uses intent classification (not keyword matching) to interpret your response: + - **Affirmative with no conditions** ("go", "yes", "looks good") → proceeds + - **Affirmative with conditions** ("go, but first change X") → treats as discussion, addresses conditions, re-asks + - **Questions or pushback** ("what about...", "I'm not sure") → discusses, revises, re-asks + - **Abandonment** ("never mind", "stop") → stops with nothing to clean up -3. **Create GitHub issue** — runs `gh issue create` with a descriptive title, human-readable body, and resolved labels/milestone. Posts a technical implementation plan as an issue comment. +3. **Create GitHub issue** — runs `gh issue create` with a descriptive title, structured body, and resolved labels/milestone. The issue body contains five required sections: + - **Problem to Fix** — what is broken or missing, in plain language + - **Why it Matters** — the impact or motivation + - **General Approach** — high-level direction for the fix + - **Complexity** — verification/QA effort rating (trivial, moderate, significant, or extensive) with a one-line justification + - **Acceptance Criteria** — specific, verifiable outcomes + + After the issue is created, a technical implementation plan is posted as an issue comment. 4. **Create feature branch** — runs `gh issue develop` to create a `feature/*` branch linked to the issue in GitHub. Verifies the branch before proceeding. @@ -52,7 +63,7 @@ Flags replace auto-selection entirely; they do not append. 1. **Load context** — reads the issue body, all comments, and any prior agent implementation notes. -2. **Summarize and gate** — tells you what the issue is about, what was done, and what remains. Asks if this matches your understanding. +2. **Summarize and gate** — tells you what the issue is about, what was done, and what remains. Uses the same intent classification as new work to interpret your response. 3. **Check out branch** — finds or creates the linked feature branch. diff --git a/docs/skills/submit-for-review.md b/docs/skills/submit-for-review.md index 1d2c1f7..73dc060 100644 --- a/docs/skills/submit-for-review.md +++ b/docs/skills/submit-for-review.md @@ -37,9 +37,9 @@ No arguments. `/submit-for-review` operates on the current branch. - `advisory`: spawns a review agent, posts findings, merges regardless - `off`: skips review entirely -7. **Act on verdict** — if `REVIEW_GATE` is `ai` and the review finds CRITICAL issues, `/submit-for-review` stops and asks you to fix them. Otherwise, it merges the PR. +7. **Act on verdict** — if `REVIEW_GATE` is `ai` and the review finds CRITICAL issues, `/submit-for-review` stops and asks you to fix them. If the review approves but includes non-blocking findings (warnings or notes), a human gate asks whether you want to address them first or merge now. -8. **Post-merge** — in two-branch mode, applies `QA_READY_LABEL` to the linked issue if configured. Reports next steps based on your branching model. +8. **Post-merge** — in two-branch mode, applies `QA_READY_LABEL` to the linked issue if configured. Posts a resolution comment to the linked issue summarizing what was done in plain language (written for non-technical audiences like PMs or QA). Reports next steps based on your branching model. ## Reviewer selection From 060f218e24c7718516bd3b02f8c16cc1ef88e50c Mon Sep 17 00:00:00 2001 From: Sebastien Taggart <sebastien.taggart@gmail.com> Date: Sat, 11 Apr 2026 10:06:57 -0400 Subject: [PATCH 10/12] Use Write tool + --body-file for start.md gh commands (test approach) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Heredocs in Bash commands — quoted, unquoted, or via $(cat) — all trigger Claude Code permission prompts due to shell metacharacter detection (#, $, quotes). Moving body content to a temp file via the Write tool bypasses shell parsing entirely. The gh command becomes a clean prefix match for Bash(gh:*). Testing in start.md first before applying to other skills. Ref #82 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- skills/start.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/skills/start.md b/skills/start.md index aefb3b8..a52d979 100644 --- a/skills/start.md +++ b/skills/start.md @@ -136,7 +136,13 @@ The friendly text question is required regardless of harness mode. If your harne ### Step 3 — Create GitHub Issue -Run `gh issue create` with explicit flags (do NOT open an interactive editor): +Run `gh issue create` with explicit flags (do NOT open an interactive editor). + +First, write the issue body to a temp file using the **Write tool** (not Bash): + +**Write** `/tmp/cc_issue_body.md` with the structured markdown body (see sections below). + +Then create the issue: ```bash gh issue create \ @@ -144,12 +150,10 @@ gh issue create \ --assignee @me \ [--label "<resolved labels>"] \ [--milestone "<resolved milestone>"] \ - --body-file - <<'EOF' -<structured markdown body — see sections below> -EOF + --body-file /tmp/cc_issue_body.md ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. +> **Why Write tool + `--body-file`?** Passing multi-line markdown content inline in a Bash command — whether via `$(...)`, quoted heredocs (`<<'EOF'`), or unquoted heredocs (`<<EOF` with `#` headings) — triggers Claude Code permission prompts that cannot be permanently allowed. Writing the body with the Write tool bypasses shell parsing entirely, and the resulting `gh` command is a clean prefix match for `Bash(gh:*)`. This pattern works identically across Claude Code, Gemini CLI, Cursor, and Codex. Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. @@ -192,14 +196,18 @@ After the command runs, note the issue number from the output URL (e.g. `https:/ Show the user: `Created issue #<number>: <title>` -Then immediately post agent implementation notes as a comment: +Then immediately post agent implementation notes as a comment. -```bash -gh issue comment <number> --body-file - <<'EOF' +**Write** `/tmp/cc_issue_comment.md`: +```markdown ## Agent Implementation Notes <full technical plan: exact files to change, approach, key decisions, edge cases> -EOF +``` + +Then post it: +```bash +gh issue comment <number> --body-file /tmp/cc_issue_comment.md ``` ### Step 4 — Create feature branch From e5e8b3eb0ffba41758003f3ee9d757ebbcec325e Mon Sep 17 00:00:00 2001 From: Sebastien Taggart <sebastien.taggart@gmail.com> Date: Sat, 11 Apr 2026 15:35:11 -0400 Subject: [PATCH 11/12] Use Write tool + --body-file for all gh commands with multi-line bodies Replace heredoc patterns (--body-file - <<EOF, --notes-file - <<EOF) with a two-step approach: write body to /tmp/cc_*.md via the file-writing tool, then pass --body-file /tmp/cc_*.md to gh. This avoids all shell metacharacter issues that trigger Claude Code permission prompts ($, #, quoted delimiters). Updated skills: start.md, submit-for-review.md, deploy.md Regenerated all 12 adapter files via sync.sh. Closes #82 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- .agents/skills/deploy/SKILL.md | 34 ++++++---- .agents/skills/start/SKILL.md | 26 +++++--- .agents/skills/submit-for-review/SKILL.md | 49 +++++++++----- .claude/commands/deploy.md | 34 ++++++---- .claude/commands/start.md | 26 +++++--- .claude/commands/submit-for-review.md | 49 +++++++++----- .cursor/rules/deploy.mdc | 34 ++++++---- .cursor/rules/start.mdc | 26 +++++--- .cursor/rules/submit-for-review.mdc | 49 +++++++++----- .gemini/skills/deploy/SKILL.md | 34 ++++++---- .gemini/skills/start/SKILL.md | 26 +++++--- .gemini/skills/submit-for-review/SKILL.md | 49 +++++++++----- skills/deploy.md | 80 +++++++++++++++-------- skills/start.md | 14 ++-- skills/submit-for-review.md | 47 +++++++++---- 15 files changed, 380 insertions(+), 197 deletions(-) diff --git a/.agents/skills/deploy/SKILL.md b/.agents/skills/deploy/SKILL.md index 037b39a..7d00d24 100644 --- a/.agents/skills/deploy/SKILL.md +++ b/.agents/skills/deploy/SKILL.md @@ -166,10 +166,9 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo ## Step 6 — Create PR: `dev` → `main` -```bash -gh pr create --base main --head dev \ - --title "Release vX.Y.Z" \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_release_pr_body.md`: + +```markdown Release vX.Y.Z PRs included: @@ -178,7 +177,14 @@ PRs included: Closes #14 Closes #15 -EOF +``` + +Then create the PR (do NOT use `--body`, `--body-file -`, or heredocs): + +```bash +gh pr create --base main --head dev \ + --title "Release vX.Y.Z" \ + --body-file /tmp/cc_release_pr_body.md ``` Note the PR number from the output. @@ -209,19 +215,23 @@ git describe --abbrev=0 <version-tag>^ 2>/dev/null If no previous tag exists, omit the "Full changelog" line. -Create the release: +Use your file-writing tool (not Bash) to create `/tmp/cc_release_notes.md`: -```bash -gh release create <version-tag> \ - --title "<version-tag>" \ - --notes-file - <<'EOF' +```markdown ## Changes - #<issue> — <PR title> (PR #<pr-number>) [... one line per PR included in this release ...] **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> -EOF +``` + +Then create the release (do NOT use `--notes`, `--notes-file -`, or heredocs): + +```bash +gh release create <version-tag> \ + --title "<version-tag>" \ + --notes-file /tmp/cc_release_notes.md ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -235,4 +245,4 @@ After the command runs, note the release URL from the output. Tell the user: > "Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at `<url>`. Run `make deploy-prod` to ship to production." -<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: codex | hash: 0e47902b | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: codex | hash: 6d8dd3bb | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.agents/skills/start/SKILL.md b/.agents/skills/start/SKILL.md index 47881d4..837fb80 100644 --- a/.agents/skills/start/SKILL.md +++ b/.agents/skills/start/SKILL.md @@ -93,7 +93,11 @@ The friendly text question is required regardless of harness mode. If your harne ### Step 3 — Create GitHub Issue -Run `gh issue create` with explicit flags (do NOT open an interactive editor): +Create the issue in two steps — **this exact sequence is mandatory**: + +**Step 3a — Write the body to a temp file.** Use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_issue_body.md` with the structured markdown body (see sections below). Do NOT use Bash/shell to write this file. Do NOT use heredocs, `cat`, or `echo`. The file-writing tool bypasses shell parsing entirely. + +**Step 3b — Run `gh issue create`** with `--body-file` pointing to the temp file: ```bash gh issue create \ @@ -101,12 +105,10 @@ gh issue create \ --assignee @me \ [--label "<resolved labels>"] \ [--milestone "<resolved milestone>"] \ - --body-file - <<'EOF' -<structured markdown body — see sections below> -EOF + --body-file /tmp/cc_issue_body.md ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. @@ -149,14 +151,18 @@ After the command runs, note the issue number from the output URL (e.g. `https:/ Show the user: `Created issue #<number>: <title>` -Then immediately post agent implementation notes as a comment: +Then immediately post agent implementation notes as a comment. -```bash -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_issue_comment.md`: +```markdown ## Agent Implementation Notes <full technical plan: exact files to change, approach, key decisions, edge cases> -EOF +``` + +Then post it (do NOT use `--body` or heredocs — same rule as Step 3): +```bash +gh issue comment <number> --body-file /tmp/cc_issue_comment.md ``` ### Step 4 — Create feature branch @@ -270,4 +276,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit <number> --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. -<!-- generated by CodeCannon/sync.sh | skill: start | adapter: codex | hash: 5603cf1a | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: start | adapter: codex | hash: 7ba07088 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.agents/skills/submit-for-review/SKILL.md b/.agents/skills/submit-for-review/SKILL.md index dd35ec9..d711c85 100644 --- a/.agents/skills/submit-for-review/SKILL.md +++ b/.agents/skills/submit-for-review/SKILL.md @@ -109,16 +109,23 @@ Use `Issue #<number>` as the issue reference — the issue stays open until `/de > **Critical:** Use the unqualified `#N` form (e.g. `Closes #42`), never the fully-qualified `owner/repo#N` form (e.g. `Closes LightbridgeLab/CodeCannon#42`), even for same-repo references. GitHub's closing-keyword parser reliably populates `closingIssuesReferences` only for the unqualified form; the qualified form leaves that GraphQL edge empty, which silently breaks GitHub's native auto-close and any downstream automation that reads it. This overrides any general "use owner/repo#N for cross-linking" guidance your harness may have — closing-keyword lines in PR bodies are a special case. -Then create the PR with explicit title and body (never use an interactive editor): -``` -gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' +Then create the PR in two steps — **this exact sequence is mandatory**: + +First, use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_pr_body.md`. Do NOT use Bash/shell to write this file. + +```markdown <description of what changed and why> <Closes #N OR Issue #N, based on target above> -EOF ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). +Then create the PR (do NOT use `--body`, `--body-file -`, heredocs, or `$(cat ...)`): + +``` +gh pr create --base <target-branch> --title "<title>" --body-file /tmp/cc_pr_body.md +``` + +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Add `--reviewer` to the `gh pr create` command above using the handles from `@sebastientaggart`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. @@ -219,14 +226,20 @@ If no linked issue was found, skip silently. Read the issue body (from Step 3 or via `gh issue view <number>`) to recall the original problem description. Then post a comment summarizing what was done: -``` -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_resolution_comment.md`: + +```markdown ## Resolution <1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> See #<PR-number> for full technical details. -EOF +``` + +Then post it (do NOT use `--body` or heredocs): + +``` +gh issue comment <number> --body-file /tmp/cc_resolution_comment.md ``` **Resolution writing rules:** @@ -262,17 +275,23 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is **Create the selected issues.** For each selected finding, run `gh issue create` with explicit flags: -``` -gh issue create \ - --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - [--label "<pool-selected labels>"] \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_followup_body.md` for each finding: + +```markdown Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. -EOF +``` + +Then create the issue (do NOT use `--body` or heredocs): + +``` +gh issue create \ + --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ + [--label "<pool-selected labels>"] \ + --body-file /tmp/cc_followup_body.md ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `bug, documentation, enhancement, chore` that genuinely fit the finding. If `bug, documentation, enhancement, chore` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. @@ -298,4 +317,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. -<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: codex | hash: ba60d5aa | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: codex | hash: d09ab40d | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.claude/commands/deploy.md b/.claude/commands/deploy.md index 4c919ad..962a484 100644 --- a/.claude/commands/deploy.md +++ b/.claude/commands/deploy.md @@ -161,10 +161,9 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo ## Step 6 — Create PR: `dev` → `main` -```bash -gh pr create --base main --head dev \ - --title "Release vX.Y.Z" \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_release_pr_body.md`: + +```markdown Release vX.Y.Z PRs included: @@ -173,7 +172,14 @@ PRs included: Closes #14 Closes #15 -EOF +``` + +Then create the PR (do NOT use `--body`, `--body-file -`, or heredocs): + +```bash +gh pr create --base main --head dev \ + --title "Release vX.Y.Z" \ + --body-file /tmp/cc_release_pr_body.md ``` Note the PR number from the output. @@ -204,19 +210,23 @@ git describe --abbrev=0 <version-tag>^ 2>/dev/null If no previous tag exists, omit the "Full changelog" line. -Create the release: +Use your file-writing tool (not Bash) to create `/tmp/cc_release_notes.md`: -```bash -gh release create <version-tag> \ - --title "<version-tag>" \ - --notes-file - <<'EOF' +```markdown ## Changes - #<issue> — <PR title> (PR #<pr-number>) [... one line per PR included in this release ...] **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> -EOF +``` + +Then create the release (do NOT use `--notes`, `--notes-file -`, or heredocs): + +```bash +gh release create <version-tag> \ + --title "<version-tag>" \ + --notes-file /tmp/cc_release_notes.md ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -230,4 +240,4 @@ After the command runs, note the release URL from the output. Tell the user: > "Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at `<url>`. Run `make deploy-prod` to ship to production." -<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: claude | hash: b1efee29 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: claude | hash: 88439028 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.claude/commands/start.md b/.claude/commands/start.md index edbe3e6..2458d44 100644 --- a/.claude/commands/start.md +++ b/.claude/commands/start.md @@ -88,7 +88,11 @@ The friendly text question is required regardless of harness mode. If your harne ### Step 3 — Create GitHub Issue -Run `gh issue create` with explicit flags (do NOT open an interactive editor): +Create the issue in two steps — **this exact sequence is mandatory**: + +**Step 3a — Write the body to a temp file.** Use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_issue_body.md` with the structured markdown body (see sections below). Do NOT use Bash/shell to write this file. Do NOT use heredocs, `cat`, or `echo`. The file-writing tool bypasses shell parsing entirely. + +**Step 3b — Run `gh issue create`** with `--body-file` pointing to the temp file: ```bash gh issue create \ @@ -96,12 +100,10 @@ gh issue create \ --assignee @me \ [--label "<resolved labels>"] \ [--milestone "<resolved milestone>"] \ - --body-file - <<'EOF' -<structured markdown body — see sections below> -EOF + --body-file /tmp/cc_issue_body.md ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. @@ -144,14 +146,18 @@ After the command runs, note the issue number from the output URL (e.g. `https:/ Show the user: `Created issue #<number>: <title>` -Then immediately post agent implementation notes as a comment: +Then immediately post agent implementation notes as a comment. -```bash -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_issue_comment.md`: +```markdown ## Agent Implementation Notes <full technical plan: exact files to change, approach, key decisions, edge cases> -EOF +``` + +Then post it (do NOT use `--body` or heredocs — same rule as Step 3): +```bash +gh issue comment <number> --body-file /tmp/cc_issue_comment.md ``` ### Step 4 — Create feature branch @@ -265,4 +271,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit <number> --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. -<!-- generated by CodeCannon/sync.sh | skill: start | adapter: claude | hash: 3c1bac69 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: start | adapter: claude | hash: d1144b46 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.claude/commands/submit-for-review.md b/.claude/commands/submit-for-review.md index 95d9218..98a6d71 100644 --- a/.claude/commands/submit-for-review.md +++ b/.claude/commands/submit-for-review.md @@ -104,16 +104,23 @@ Use `Issue #<number>` as the issue reference — the issue stays open until `/de > **Critical:** Use the unqualified `#N` form (e.g. `Closes #42`), never the fully-qualified `owner/repo#N` form (e.g. `Closes LightbridgeLab/CodeCannon#42`), even for same-repo references. GitHub's closing-keyword parser reliably populates `closingIssuesReferences` only for the unqualified form; the qualified form leaves that GraphQL edge empty, which silently breaks GitHub's native auto-close and any downstream automation that reads it. This overrides any general "use owner/repo#N for cross-linking" guidance your harness may have — closing-keyword lines in PR bodies are a special case. -Then create the PR with explicit title and body (never use an interactive editor): -``` -gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' +Then create the PR in two steps — **this exact sequence is mandatory**: + +First, use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_pr_body.md`. Do NOT use Bash/shell to write this file. + +```markdown <description of what changed and why> <Closes #N OR Issue #N, based on target above> -EOF ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). +Then create the PR (do NOT use `--body`, `--body-file -`, heredocs, or `$(cat ...)`): + +``` +gh pr create --base <target-branch> --title "<title>" --body-file /tmp/cc_pr_body.md +``` + +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Add `--reviewer` to the `gh pr create` command above using the handles from `@sebastientaggart`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. @@ -214,14 +221,20 @@ If no linked issue was found, skip silently. Read the issue body (from Step 3 or via `gh issue view <number>`) to recall the original problem description. Then post a comment summarizing what was done: -``` -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_resolution_comment.md`: + +```markdown ## Resolution <1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> See #<PR-number> for full technical details. -EOF +``` + +Then post it (do NOT use `--body` or heredocs): + +``` +gh issue comment <number> --body-file /tmp/cc_resolution_comment.md ``` **Resolution writing rules:** @@ -257,17 +270,23 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is **Create the selected issues.** For each selected finding, run `gh issue create` with explicit flags: -``` -gh issue create \ - --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - [--label "<pool-selected labels>"] \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_followup_body.md` for each finding: + +```markdown Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. -EOF +``` + +Then create the issue (do NOT use `--body` or heredocs): + +``` +gh issue create \ + --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ + [--label "<pool-selected labels>"] \ + --body-file /tmp/cc_followup_body.md ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `bug, documentation, enhancement, chore` that genuinely fit the finding. If `bug, documentation, enhancement, chore` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. @@ -293,4 +312,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. -<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: claude | hash: 28da1f65 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: claude | hash: 7cc1a5b2 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.cursor/rules/deploy.mdc b/.cursor/rules/deploy.mdc index a34de2c..d4e7d70 100644 --- a/.cursor/rules/deploy.mdc +++ b/.cursor/rules/deploy.mdc @@ -167,10 +167,9 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo ## Step 6 — Create PR: `dev` → `main` -```bash -gh pr create --base main --head dev \ - --title "Release vX.Y.Z" \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_release_pr_body.md`: + +```markdown Release vX.Y.Z PRs included: @@ -179,7 +178,14 @@ PRs included: Closes #14 Closes #15 -EOF +``` + +Then create the PR (do NOT use `--body`, `--body-file -`, or heredocs): + +```bash +gh pr create --base main --head dev \ + --title "Release vX.Y.Z" \ + --body-file /tmp/cc_release_pr_body.md ``` Note the PR number from the output. @@ -210,19 +216,23 @@ git describe --abbrev=0 <version-tag>^ 2>/dev/null If no previous tag exists, omit the "Full changelog" line. -Create the release: +Use your file-writing tool (not Bash) to create `/tmp/cc_release_notes.md`: -```bash -gh release create <version-tag> \ - --title "<version-tag>" \ - --notes-file - <<'EOF' +```markdown ## Changes - #<issue> — <PR title> (PR #<pr-number>) [... one line per PR included in this release ...] **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> -EOF +``` + +Then create the release (do NOT use `--notes`, `--notes-file -`, or heredocs): + +```bash +gh release create <version-tag> \ + --title "<version-tag>" \ + --notes-file /tmp/cc_release_notes.md ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -236,4 +246,4 @@ After the command runs, note the release URL from the output. Tell the user: > "Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at `<url>`. Run `make deploy-prod` to ship to production." -<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: cursor | hash: 96c1037f | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: cursor | hash: a7a8fe00 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.cursor/rules/start.mdc b/.cursor/rules/start.mdc index 58a770b..3adac90 100644 --- a/.cursor/rules/start.mdc +++ b/.cursor/rules/start.mdc @@ -94,7 +94,11 @@ The friendly text question is required regardless of harness mode. If your harne ### Step 3 — Create GitHub Issue -Run `gh issue create` with explicit flags (do NOT open an interactive editor): +Create the issue in two steps — **this exact sequence is mandatory**: + +**Step 3a — Write the body to a temp file.** Use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_issue_body.md` with the structured markdown body (see sections below). Do NOT use Bash/shell to write this file. Do NOT use heredocs, `cat`, or `echo`. The file-writing tool bypasses shell parsing entirely. + +**Step 3b — Run `gh issue create`** with `--body-file` pointing to the temp file: ```bash gh issue create \ @@ -102,12 +106,10 @@ gh issue create \ --assignee @me \ [--label "<resolved labels>"] \ [--milestone "<resolved milestone>"] \ - --body-file - <<'EOF' -<structured markdown body — see sections below> -EOF + --body-file /tmp/cc_issue_body.md ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. @@ -150,14 +152,18 @@ After the command runs, note the issue number from the output URL (e.g. `https:/ Show the user: `Created issue #<number>: <title>` -Then immediately post agent implementation notes as a comment: +Then immediately post agent implementation notes as a comment. -```bash -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_issue_comment.md`: +```markdown ## Agent Implementation Notes <full technical plan: exact files to change, approach, key decisions, edge cases> -EOF +``` + +Then post it (do NOT use `--body` or heredocs — same rule as Step 3): +```bash +gh issue comment <number> --body-file /tmp/cc_issue_comment.md ``` ### Step 4 — Create feature branch @@ -271,4 +277,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit <number> --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. -<!-- generated by CodeCannon/sync.sh | skill: start | adapter: cursor | hash: fad7e3ef | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: start | adapter: cursor | hash: 99965523 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.cursor/rules/submit-for-review.mdc b/.cursor/rules/submit-for-review.mdc index ef6b002..89107be 100644 --- a/.cursor/rules/submit-for-review.mdc +++ b/.cursor/rules/submit-for-review.mdc @@ -110,16 +110,23 @@ Use `Issue #<number>` as the issue reference — the issue stays open until `/de > **Critical:** Use the unqualified `#N` form (e.g. `Closes #42`), never the fully-qualified `owner/repo#N` form (e.g. `Closes LightbridgeLab/CodeCannon#42`), even for same-repo references. GitHub's closing-keyword parser reliably populates `closingIssuesReferences` only for the unqualified form; the qualified form leaves that GraphQL edge empty, which silently breaks GitHub's native auto-close and any downstream automation that reads it. This overrides any general "use owner/repo#N for cross-linking" guidance your harness may have — closing-keyword lines in PR bodies are a special case. -Then create the PR with explicit title and body (never use an interactive editor): -``` -gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' +Then create the PR in two steps — **this exact sequence is mandatory**: + +First, use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_pr_body.md`. Do NOT use Bash/shell to write this file. + +```markdown <description of what changed and why> <Closes #N OR Issue #N, based on target above> -EOF ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). +Then create the PR (do NOT use `--body`, `--body-file -`, heredocs, or `$(cat ...)`): + +``` +gh pr create --base <target-branch> --title "<title>" --body-file /tmp/cc_pr_body.md +``` + +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Add `--reviewer` to the `gh pr create` command above using the handles from `@sebastientaggart`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. @@ -220,14 +227,20 @@ If no linked issue was found, skip silently. Read the issue body (from Step 3 or via `gh issue view <number>`) to recall the original problem description. Then post a comment summarizing what was done: -``` -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_resolution_comment.md`: + +```markdown ## Resolution <1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> See #<PR-number> for full technical details. -EOF +``` + +Then post it (do NOT use `--body` or heredocs): + +``` +gh issue comment <number> --body-file /tmp/cc_resolution_comment.md ``` **Resolution writing rules:** @@ -263,17 +276,23 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is **Create the selected issues.** For each selected finding, run `gh issue create` with explicit flags: -``` -gh issue create \ - --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - [--label "<pool-selected labels>"] \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_followup_body.md` for each finding: + +```markdown Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. -EOF +``` + +Then create the issue (do NOT use `--body` or heredocs): + +``` +gh issue create \ + --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ + [--label "<pool-selected labels>"] \ + --body-file /tmp/cc_followup_body.md ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `bug, documentation, enhancement, chore` that genuinely fit the finding. If `bug, documentation, enhancement, chore` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. @@ -299,4 +318,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. -<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: cursor | hash: d2df6354 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: cursor | hash: 141fa52f | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.gemini/skills/deploy/SKILL.md b/.gemini/skills/deploy/SKILL.md index 9146f22..aaf65c2 100644 --- a/.gemini/skills/deploy/SKILL.md +++ b/.gemini/skills/deploy/SKILL.md @@ -166,10 +166,9 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo ## Step 6 — Create PR: `dev` → `main` -```bash -gh pr create --base main --head dev \ - --title "Release vX.Y.Z" \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_release_pr_body.md`: + +```markdown Release vX.Y.Z PRs included: @@ -178,7 +177,14 @@ PRs included: Closes #14 Closes #15 -EOF +``` + +Then create the PR (do NOT use `--body`, `--body-file -`, or heredocs): + +```bash +gh pr create --base main --head dev \ + --title "Release vX.Y.Z" \ + --body-file /tmp/cc_release_pr_body.md ``` Note the PR number from the output. @@ -209,19 +215,23 @@ git describe --abbrev=0 <version-tag>^ 2>/dev/null If no previous tag exists, omit the "Full changelog" line. -Create the release: +Use your file-writing tool (not Bash) to create `/tmp/cc_release_notes.md`: -```bash -gh release create <version-tag> \ - --title "<version-tag>" \ - --notes-file - <<'EOF' +```markdown ## Changes - #<issue> — <PR title> (PR #<pr-number>) [... one line per PR included in this release ...] **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> -EOF +``` + +Then create the release (do NOT use `--notes`, `--notes-file -`, or heredocs): + +```bash +gh release create <version-tag> \ + --title "<version-tag>" \ + --notes-file /tmp/cc_release_notes.md ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -235,4 +245,4 @@ After the command runs, note the release URL from the output. Tell the user: > "Released vX.Y.Z. Issues #N, #M closed automatically. GitHub Release vX.Y.Z created at `<url>`. Run `make deploy-prod` to ship to production." -<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: gemini | hash: cde00382 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: deploy | adapter: gemini | hash: 1b252e14 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.gemini/skills/start/SKILL.md b/.gemini/skills/start/SKILL.md index 6695df4..bd2678f 100644 --- a/.gemini/skills/start/SKILL.md +++ b/.gemini/skills/start/SKILL.md @@ -93,7 +93,11 @@ The friendly text question is required regardless of harness mode. If your harne ### Step 3 — Create GitHub Issue -Run `gh issue create` with explicit flags (do NOT open an interactive editor): +Create the issue in two steps — **this exact sequence is mandatory**: + +**Step 3a — Write the body to a temp file.** Use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_issue_body.md` with the structured markdown body (see sections below). Do NOT use Bash/shell to write this file. Do NOT use heredocs, `cat`, or `echo`. The file-writing tool bypasses shell parsing entirely. + +**Step 3b — Run `gh issue create`** with `--body-file` pointing to the temp file: ```bash gh issue create \ @@ -101,12 +105,10 @@ gh issue create \ --assignee @me \ [--label "<resolved labels>"] \ [--milestone "<resolved milestone>"] \ - --body-file - <<'EOF' -<structured markdown body — see sections below> -EOF + --body-file /tmp/cc_issue_body.md ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc avoids this — the matcher sees a clean `gh …` invocation and `Bash(gh:*)` matches. +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. @@ -149,14 +151,18 @@ After the command runs, note the issue number from the output URL (e.g. `https:/ Show the user: `Created issue #<number>: <title>` -Then immediately post agent implementation notes as a comment: +Then immediately post agent implementation notes as a comment. -```bash -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_issue_comment.md`: +```markdown ## Agent Implementation Notes <full technical plan: exact files to change, approach, key decisions, edge cases> -EOF +``` + +Then post it (do NOT use `--body` or heredocs — same rule as Step 3): +```bash +gh issue comment <number> --body-file /tmp/cc_issue_comment.md ``` ### Step 4 — Create feature branch @@ -270,4 +276,4 @@ When done, say: **"The code is ready for review. Please run `make dev` and test - The issue is assigned to `@me` at creation. If you are creating a ticket on someone else's behalf, remove the assignee after creation with `gh issue edit <number> --remove-assignee @me`. - Apply resolved labels and milestone to every new issue. Label resolution order: per-invocation flag → pool selection from `bug, documentation, enhancement, chore` → omit `--label` entirely. Never apply a label outside `bug, documentation, enhancement, chore`. - Milestone resolution order: per-invocation flag → auto-detected from GitHub open milestones. Never prompt for a milestone more than once per invocation. -<!-- generated by CodeCannon/sync.sh | skill: start | adapter: gemini | hash: 064b9454 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: start | adapter: gemini | hash: 250dcb74 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/.gemini/skills/submit-for-review/SKILL.md b/.gemini/skills/submit-for-review/SKILL.md index c494469..ec193b8 100644 --- a/.gemini/skills/submit-for-review/SKILL.md +++ b/.gemini/skills/submit-for-review/SKILL.md @@ -109,16 +109,23 @@ Use `Issue #<number>` as the issue reference — the issue stays open until `/de > **Critical:** Use the unqualified `#N` form (e.g. `Closes #42`), never the fully-qualified `owner/repo#N` form (e.g. `Closes LightbridgeLab/CodeCannon#42`), even for same-repo references. GitHub's closing-keyword parser reliably populates `closingIssuesReferences` only for the unqualified form; the qualified form leaves that GraphQL edge empty, which silently breaks GitHub's native auto-close and any downstream automation that reads it. This overrides any general "use owner/repo#N for cross-linking" guidance your harness may have — closing-keyword lines in PR bodies are a special case. -Then create the PR with explicit title and body (never use an interactive editor): -``` -gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' +Then create the PR in two steps — **this exact sequence is mandatory**: + +First, use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_pr_body.md`. Do NOT use Bash/shell to write this file. + +```markdown <description of what changed and why> <Closes #N OR Issue #N, based on target above> -EOF ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). +Then create the PR (do NOT use `--body`, `--body-file -`, heredocs, or `$(cat ...)`): + +``` +gh pr create --base <target-branch> --title "<title>" --body-file /tmp/cc_pr_body.md +``` + +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Add `--reviewer` to the `gh pr create` command above using the handles from `@sebastientaggart`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. @@ -219,14 +226,20 @@ If no linked issue was found, skip silently. Read the issue body (from Step 3 or via `gh issue view <number>`) to recall the original problem description. Then post a comment summarizing what was done: -``` -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_resolution_comment.md`: + +```markdown ## Resolution <1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> See #<PR-number> for full technical details. -EOF +``` + +Then post it (do NOT use `--body` or heredocs): + +``` +gh issue comment <number> --body-file /tmp/cc_resolution_comment.md ``` **Resolution writing rules:** @@ -262,17 +275,23 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is **Create the selected issues.** For each selected finding, run `gh issue create` with explicit flags: -``` -gh issue create \ - --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - [--label "<pool-selected labels>"] \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_followup_body.md` for each finding: + +```markdown Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. -EOF +``` + +Then create the issue (do NOT use `--body` or heredocs): + +``` +gh issue create \ + --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ + [--label "<pool-selected labels>"] \ + --body-file /tmp/cc_followup_body.md ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `bug, documentation, enhancement, chore` that genuinely fit the finding. If `bug, documentation, enhancement, chore` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. @@ -298,4 +317,4 @@ If a single `gh issue create` call fails, report the failure for that finding an - `/submit-for-review` merges only to `dev` — never directly to `main`. - If `make merge` fails for any reason, report it and stop — do not attempt workarounds. - The follow-up issue offer in Step 9 runs only after a successful merge and only when the review produced non-blocking findings. Never prompt the user for follow-ups when the review blocked the merge — those findings should be fixed, not ticketed. -<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: gemini | hash: 156f1ee6 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> +<!-- generated by CodeCannon/sync.sh | skill: submit-for-review | adapter: gemini | hash: ba3271f2 | DO NOT EDIT — run CodeCannon/sync.sh to regenerate --> diff --git a/skills/deploy.md b/skills/deploy.md index a0c21c4..cbf7cdc 100644 --- a/skills/deploy.md +++ b/skills/deploy.md @@ -239,17 +239,23 @@ Wait for the user to type "release" or an explicit confirmation. Any other respo The version tag and PR/issue list are already known. If no previous tag exists, omit the "Full changelog" line. -```bash -gh release create <version-tag> \ - --title "<version-tag>" \ - --notes-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_release_notes.md`: + +```markdown ## Changes - #<issue> — <PR title> (PR #<pr-number>) [... one line per PR included in this release ...] **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> -EOF +``` + +Then create the release (do NOT use `--notes`, `--notes-file -`, or heredocs): + +```bash +gh release create <version-tag> \ + --title "<version-tag>" \ + --notes-file /tmp/cc_release_notes.md ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, use just the PR title. @@ -268,10 +274,9 @@ Tell the user: {{#if !BRANCH_TEST}} ## Step 6 — Create PR: `{{BRANCH_DEV}}` → `{{BRANCH_PROD}}` -```bash -gh pr create --base {{BRANCH_PROD}} --head {{BRANCH_DEV}} \ - --title "Release vX.Y.Z" \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_release_pr_body.md`: + +```markdown Release vX.Y.Z PRs included: @@ -280,7 +285,14 @@ PRs included: Closes #14 Closes #15 -EOF +``` + +Then create the PR (do NOT use `--body`, `--body-file -`, or heredocs): + +```bash +gh pr create --base {{BRANCH_PROD}} --head {{BRANCH_DEV}} \ + --title "Release vX.Y.Z" \ + --body-file /tmp/cc_release_pr_body.md ``` Note the PR number from the output. @@ -311,19 +323,23 @@ git describe --abbrev=0 <version-tag>^ 2>/dev/null If no previous tag exists, omit the "Full changelog" line. -Create the release: +Use your file-writing tool (not Bash) to create `/tmp/cc_release_notes.md`: -```bash -gh release create <version-tag> \ - --title "<version-tag>" \ - --notes-file - <<'EOF' +```markdown ## Changes - #<issue> — <PR title> (PR #<pr-number>) [... one line per PR included in this release ...] **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> -EOF +``` + +Then create the release (do NOT use `--notes`, `--notes-file -`, or heredocs): + +```bash +gh release create <version-tag> \ + --title "<version-tag>" \ + --notes-file /tmp/cc_release_notes.md ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. @@ -341,10 +357,9 @@ Tell the user: {{#if BRANCH_TEST}} ## Step 6 — Create PR: `{{BRANCH_TEST}}` → `{{BRANCH_PROD}}` -```bash -gh pr create --base {{BRANCH_PROD}} --head {{BRANCH_TEST}} \ - --title "Release vX.Y.Z" \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_release_pr_body.md`: + +```markdown Release vX.Y.Z PRs included: @@ -353,7 +368,14 @@ PRs included: Closes #14 Closes #15 -EOF +``` + +Then create the PR (do NOT use `--body`, `--body-file -`, or heredocs): + +```bash +gh pr create --base {{BRANCH_PROD}} --head {{BRANCH_TEST}} \ + --title "Release vX.Y.Z" \ + --body-file /tmp/cc_release_pr_body.md ``` Note the PR number from the output. @@ -384,19 +406,23 @@ git describe --abbrev=0 <version-tag>^ 2>/dev/null If no previous tag exists, omit the "Full changelog" line. -Create the release: +Use your file-writing tool (not Bash) to create `/tmp/cc_release_notes.md`: -```bash -gh release create <version-tag> \ - --title "<version-tag>" \ - --notes-file - <<'EOF' +```markdown ## Changes - #<issue> — <PR title> (PR #<pr-number>) [... one line per PR included in this release ...] **Full changelog:** https://github.com/<owner>/<repo>/compare/<previous-tag>...<version-tag> -EOF +``` + +Then create the release (do NOT use `--notes`, `--notes-file -`, or heredocs): + +```bash +gh release create <version-tag> \ + --title "<version-tag>" \ + --notes-file /tmp/cc_release_notes.md ``` Format each PR line as `- #<linked-issue> — <PR title> (PR #<N>)`. If a PR had no linked issue, omit the `#<issue>` prefix and use just the PR title. diff --git a/skills/start.md b/skills/start.md index a52d979..3d43eed 100644 --- a/skills/start.md +++ b/skills/start.md @@ -136,13 +136,11 @@ The friendly text question is required regardless of harness mode. If your harne ### Step 3 — Create GitHub Issue -Run `gh issue create` with explicit flags (do NOT open an interactive editor). +Create the issue in two steps — **this exact sequence is mandatory**: -First, write the issue body to a temp file using the **Write tool** (not Bash): +**Step 3a — Write the body to a temp file.** Use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_issue_body.md` with the structured markdown body (see sections below). Do NOT use Bash/shell to write this file. Do NOT use heredocs, `cat`, or `echo`. The file-writing tool bypasses shell parsing entirely. -**Write** `/tmp/cc_issue_body.md` with the structured markdown body (see sections below). - -Then create the issue: +**Step 3b — Run `gh issue create`** with `--body-file` pointing to the temp file: ```bash gh issue create \ @@ -153,7 +151,7 @@ gh issue create \ --body-file /tmp/cc_issue_body.md ``` -> **Why Write tool + `--body-file`?** Passing multi-line markdown content inline in a Bash command — whether via `$(...)`, quoted heredocs (`<<'EOF'`), or unquoted heredocs (`<<EOF` with `#` headings) — triggers Claude Code permission prompts that cannot be permanently allowed. Writing the body with the Write tool bypasses shell parsing entirely, and the resulting `gh` command is a clean prefix match for `Bash(gh:*)`. This pattern works identically across Claude Code, Gemini CLI, Cursor, and Codex. +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. Resolve labels and milestone using the resolution steps in the Parsing section above: - **Labels**: use the value from three-tier label resolution. If non-empty, add `--label "<value>"` to the command. If empty (no flag, empty pool, creation not allowed), omit `--label` entirely. @@ -198,14 +196,14 @@ Show the user: `Created issue #<number>: <title>` Then immediately post agent implementation notes as a comment. -**Write** `/tmp/cc_issue_comment.md`: +Use your file-writing tool (not Bash) to create `/tmp/cc_issue_comment.md`: ```markdown ## Agent Implementation Notes <full technical plan: exact files to change, approach, key decisions, edge cases> ``` -Then post it: +Then post it (do NOT use `--body` or heredocs — same rule as Step 3): ```bash gh issue comment <number> --body-file /tmp/cc_issue_comment.md ``` diff --git a/skills/submit-for-review.md b/skills/submit-for-review.md index 9def763..c1bdf67 100644 --- a/skills/submit-for-review.md +++ b/skills/submit-for-review.md @@ -126,16 +126,23 @@ Use `Closes #<number>` as the issue reference — merging to the default branch > **Critical:** Use the unqualified `#N` form (e.g. `Closes #42`), never the fully-qualified `owner/repo#N` form (e.g. `Closes LightbridgeLab/CodeCannon#42`), even for same-repo references. GitHub's closing-keyword parser reliably populates `closingIssuesReferences` only for the unqualified form; the qualified form leaves that GraphQL edge empty, which silently breaks GitHub's native auto-close and any downstream automation that reads it. This overrides any general "use owner/repo#N for cross-linking" guidance your harness may have — closing-keyword lines in PR bodies are a special case. -Then create the PR with explicit title and body (never use an interactive editor): -``` -gh pr create --base <target-branch> --title "<title>" --body-file - <<'EOF' +Then create the PR in two steps — **this exact sequence is mandatory**: + +First, use your file-writing tool (Write in Claude Code, equivalent in other agents) to create `/tmp/cc_pr_body.md`. Do NOT use Bash/shell to write this file. + +```markdown <description of what changed and why> <Closes #N OR Issue #N, based on target above> -EOF ``` -> **Why `--body-file -` + stdin heredoc?** Claude Code's permission matcher refuses to extend any `Bash(gh:*)` allow rule over a command containing `$(...)` substitution, so `--body "$(cat <<'EOF' ...)"` triggers a Yes/No prompt on every run with no "Allow always" option. Piping the body in on stdin via heredoc redirection is not command substitution — the matcher sees a clean `gh pr create …` invocation and `Bash(gh:*)` matches. Apply this pattern to every multi-line `--body` / `--notes` in skills (`gh pr create`, `gh issue create`, `gh issue comment`, and `gh release create` all accept `-` for their `*-file` flags). +Then create the PR (do NOT use `--body`, `--body-file -`, heredocs, or `$(cat ...)`): + +``` +gh pr create --base <target-branch> --title "<title>" --body-file /tmp/cc_pr_body.md +``` + +> **IMPORTANT — never pass body content inline in the `gh` command.** Do not use `--body`, `--body-file -`, heredocs (`<<EOF` or `<<'EOF'`), or `$(cat ...)`. All of these embed markdown in a Bash command, which triggers permission prompts that cannot be permanently allowed (the shell parser flags `#` headings, quoted delimiters, and substitutions). The two-step pattern above — file-writing tool then `--body-file <path>` — is the only approach that works without prompts across Claude Code, Gemini CLI, Cursor, and Codex. {{#if DEFAULT_REVIEWERS}} Add `--reviewer` to the `gh pr create` command above using the handles from `{{DEFAULT_REVIEWERS}}`. Before passing them, strip any leading `@` from each comma-separated handle (e.g. `@alice,@org/team` becomes `alice,org/team`) — the `gh` CLI requires bare usernames. @@ -249,14 +256,20 @@ If no linked issue was found, skip silently. Read the issue body (from Step 3 or via `gh issue view <number>`) to recall the original problem description. Then post a comment summarizing what was done: -``` -gh issue comment <number> --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_resolution_comment.md`: + +```markdown ## Resolution <1-3 sentences explaining what was done to fix the problem, written in plain language for a non-technical audience — no code, no file paths, no jargon. Focus on what changed from the user's perspective and why it solves the problem described in the issue.> See #<PR-number> for full technical details. -EOF +``` + +Then post it (do NOT use `--body` or heredocs): + +``` +gh issue comment <number> --body-file /tmp/cc_resolution_comment.md ``` **Resolution writing rules:** @@ -302,17 +315,23 @@ Accept: comma-separated numbers, `all`, or `none`/`skip`/empty. If the input is **Create the selected issues.** For each selected finding, run `gh issue create` with explicit flags: -``` -gh issue create \ - --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ - [--label "<pool-selected labels>"] \ - --body-file - <<'EOF' +Use your file-writing tool (not Bash) to create `/tmp/cc_followup_body.md` for each finding: + +```markdown Follow-up from PR #<merged-pr-number> — auto-proposed from the code review. **Finding:** <full finding text, prefix included> See the review comment on the PR for context. -EOF +``` + +Then create the issue (do NOT use `--body` or heredocs): + +``` +gh issue create \ + --title "<finding text with [WARNING]/[NOTE]/[CRITICAL] prefix stripped, trimmed to a standalone sentence>" \ + [--label "<pool-selected labels>"] \ + --body-file /tmp/cc_followup_body.md ``` Label resolution for each follow-up issue: use the pool-based selection tier from `/start` — pick 1–3 labels from `{{TICKET_LABELS}}` that genuinely fit the finding. If `{{TICKET_LABELS}}` is empty or no pool label fits, omit `--label`. Do not attempt per-invocation flag resolution (there is no flag here) and never create new labels from follow-ups, even if label creation is enabled for the project. From 6eccf01def8c9bc57ae96c3f9671b6a47d718917 Mon Sep 17 00:00:00 2001 From: Sebastien Taggart <sebastien.taggart@gmail.com> Date: Sat, 11 Apr 2026 15:42:44 -0400 Subject: [PATCH 12/12] Bump version to 0.4.1 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1d0ba9e..267577d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.0 +0.4.1