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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 44 additions & 14 deletions .agents/skills/setup/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,21 +258,51 @@ A value counts as "set" if it is present, uncommented, and non-empty in `.codeca

---

### Phase 2 — Commit signing
### Phase 2 — Permission audit

Check whether the agent's permission configuration covers the shell commands Code Cannon skills use. Read `CodeCannon/permissions.yaml` to get the list of required command prefixes.

**Claude Code:** Read `.claude/settings.local.json` (if it exists) and `.claude/settings.json` (if it exists). Collect all `Bash(...)` entries from the `permissions.allow` arrays in both files. For each command prefix in `permissions.yaml`, check whether an allow rule covers it (e.g. `Bash(git:*)` or `Bash(git *)` covers the `git` prefix).

If all prefixes are covered, display `Agent permissions: all skill commands pre-approved` and continue to Phase 3.

If any prefixes are missing, show:

```
Agent permissions: some skill commands may prompt for approval.

Missing allow rules:
- Bash(cd:*)
- Bash(make:*)
...

To pre-approve these, add them to .claude/settings.local.json (git-ignored)
or .claude/settings.json (shared with team). See docs/index.md for a full example.

This is optional — you can approve commands individually when prompted instead.
```

Do not modify any settings file. This is advisory only.

**Other agents (Cursor, Codex, Gemini):** Skip this phase silently — Cursor doesn't prompt, and Codex/Gemini permission systems vary. The docs cover these agents separately.

---

### Phase 3 — Commit signing

Check whether commit signing is already configured at any level (local or global):

```bash
git config --get commit.gpgsign
```

If the output is `true`, display `Commit signing: enabled` in the health summary area and skip to Phase 3.
If the output is `true`, display `Commit signing: enabled` in the health summary area and skip to Phase 4.

If not `true`, ask: **"Does this project require signed commits? (yes/no)"**

Wait for response.

- **no / skip** → continue to Phase 3.
- **no / skip** → continue to Phase 4.
- **yes** → proceed with signing setup.

**Verify a signing key exists:**
Expand All @@ -294,9 +324,9 @@ I'll enable commit and tag signing for this repo:
Proceed? (yes/no)
```

Wait for confirmation. Write only on yes. If no, skip to Phase 3.
Wait for confirmation. Write only on yes. If no, skip to Phase 4.

Continue to Phase 3.
Continue to Phase 4.

**If no signing key is found**, detect the signing format:

Expand All @@ -319,13 +349,13 @@ I'll configure signing for this repo:
Proceed? (yes/no)
```

Wait for confirmation. Write only on yes. If no, skip to Phase 3.
Wait for confirmation. Write only on yes. If no, skip to Phase 4.

If the user has no signing key and doesn't know how to create one, point them to GitHub's signing key documentation and stop: "Set up a signing key first, then run `/setup` again to enable commit signing."

---

### Phase 3 — Label population
### Phase 4 — Label population

Run:

Expand Down Expand Up @@ -357,7 +387,7 @@ Wait for response.

After this step (or if labels were non-zero initially), run `gh label list --limit 100 --json name,color,description` again.

If `TICKET_LABELS` is unset or fewer than 5 labels exist, add a note: "`/start` works best with a clear issue-label pool (`TICKET_LABELS`), and `/qa` needs explicit QA lifecycle labels (`ready-for-qa`, `qa-passed`, `qa-failed`). Consider a lightweight priority scheme (e.g. `priority:high`, `priority:medium`, `priority:low`) if the team needs triage support. If the team runs planned iterations, set `DEFAULT_MILESTONE` in Phase 4; otherwise leave it unset so `/start` auto-detects."
If `TICKET_LABELS` is unset or fewer than 5 labels exist, add a note: "`/start` works best with a clear issue-label pool (`TICKET_LABELS`), and `/qa` needs explicit QA lifecycle labels (`ready-for-qa`, `qa-passed`, `qa-failed`). Consider a lightweight priority scheme (e.g. `priority:high`, `priority:medium`, `priority:low`) if the team needs triage support. If the team runs planned iterations, set `DEFAULT_MILESTONE` in Phase 5; otherwise leave it unset so `/start` auto-detects."

Display the results as a numbered list:

Expand All @@ -375,7 +405,7 @@ Wait for the user's response.

- **yes** → use all labels
- **numbers** (e.g. `1,3,5`) → use only those labels
- **no / skip / anything else** → skip this phase, continue to Phase 4
- **no / skip / anything else** → skip this phase, continue to Phase 5

Show the exact change before writing:

Expand All @@ -391,7 +421,7 @@ Wait for confirmation. Write only on yes.

---

### Phase 4 — Optional config walkthrough (profile-aware)
### Phase 5 — Optional config walkthrough (profile-aware)

First, infer the current profile using the same rules as Phase 1.

Expand All @@ -413,7 +443,7 @@ The walkthrough adapts based on profile. Walk through each applicable unset valu

---

### Phase 5 — Team sharing
### Phase 6 — Team sharing

After completing or skipping the config walkthrough, say:

Expand All @@ -431,11 +461,11 @@ Add a note: `/start` can be used to create well-formed GitHub issues without wri

## Hard rules

- Only modify `.codecannon.yaml` and local git config (Phase 2 signing setup). Do not touch any other file (except running `CodeCannon/sync.py`, which modifies `.claude/commands/` — permitted only with explicit user approval).
- Only modify `.codecannon.yaml` and local git config (Phase 3 signing setup). Do not touch any other file (except running `CodeCannon/sync.py`, which modifies `.claude/commands/` — permitted only with explicit user approval).
- Do not run `sync.py` without explicit user permission.
- Do not create `.codecannon.yaml` without explicit user permission.
- Do not report a configuration problem unless confident the condition is genuinely broken. Prefer false negatives over false positives on all diagnostic checks.
- Never fetch more than 100 labels in a single command. `gh label list --limit 100` is the ceiling.
- Do not skip any human gate in Phase 2, Phase 3, or Phase 4 — each write requires confirmation.
- Do not skip any human gate in Phase 3, Phase 4, or Phase 5 — each write requires confirmation.
- If the user skips a config value, do not ask again. Move on.
<!-- generated by CodeCannon/sync.py | skill: setup | adapter: codex | hash: 47495978 | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->
<!-- generated by CodeCannon/sync.py | skill: setup | adapter: codex | hash: d5d997f8 | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->
14 changes: 7 additions & 7 deletions .agents/skills/submit-for-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ If the current branch matches any of the above, **abort immediately** and say:

## Step 2 — Type-check gate

First, move to the repository root so the command resolves against the correct Makefile / project config:
First, find the repository root:

```
cd "$(git rev-parse --show-toplevel)"
git rev-parse --show-toplevel
```

Then verify the make target exists before running it. Extract the target name from `make check` (e.g. `make check` → `check`) and run:
Then `cd` to the returned path and verify the make target exists. Extract the target name from `make check` (e.g. `make check` → `check`) and run:

```
make -n <target> 2>/dev/null
cd <repo-root> && make -n <target> 2>/dev/null
```

If `make -n` exits non-zero, **stop** and say:
Expand Down Expand Up @@ -188,10 +188,10 @@ Wait for the review to complete and report its verdict.

## Step 8 — Act on verdict

Before merging, verify the merge target exists. Move to the repo root, extract the target name from `make merge` (e.g. `make merge` → `merge`), and run:
Before merging, verify the merge target exists. Find the repo root with `git rev-parse --show-toplevel`, then extract the target name from `make merge` (e.g. `make merge` → `merge`) and run:

```
cd "$(git rev-parse --show-toplevel)" && make -n <target> 2>/dev/null
cd <repo-root> && make -n <target> 2>/dev/null
```

If `make -n` exits non-zero, **stop** and say:
Expand Down Expand Up @@ -350,4 +350,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.py | skill: submit-for-review | adapter: codex | hash: 8ff703a5 | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->
<!-- generated by CodeCannon/sync.py | skill: submit-for-review | adapter: codex | hash: 0ba1c425 | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->
58 changes: 44 additions & 14 deletions .claude/commands/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,21 +253,51 @@ A value counts as "set" if it is present, uncommented, and non-empty in `.codeca

---

### Phase 2 — Commit signing
### Phase 2 — Permission audit

Check whether the agent's permission configuration covers the shell commands Code Cannon skills use. Read `CodeCannon/permissions.yaml` to get the list of required command prefixes.

**Claude Code:** Read `.claude/settings.local.json` (if it exists) and `.claude/settings.json` (if it exists). Collect all `Bash(...)` entries from the `permissions.allow` arrays in both files. For each command prefix in `permissions.yaml`, check whether an allow rule covers it (e.g. `Bash(git:*)` or `Bash(git *)` covers the `git` prefix).

If all prefixes are covered, display `Agent permissions: all skill commands pre-approved` and continue to Phase 3.

If any prefixes are missing, show:

```
Agent permissions: some skill commands may prompt for approval.

Missing allow rules:
- Bash(cd:*)
- Bash(make:*)
...

To pre-approve these, add them to .claude/settings.local.json (git-ignored)
or .claude/settings.json (shared with team). See docs/index.md for a full example.

This is optional — you can approve commands individually when prompted instead.
```

Do not modify any settings file. This is advisory only.

**Other agents (Cursor, Codex, Gemini):** Skip this phase silently — Cursor doesn't prompt, and Codex/Gemini permission systems vary. The docs cover these agents separately.

---

### Phase 3 — Commit signing

Check whether commit signing is already configured at any level (local or global):

```bash
git config --get commit.gpgsign
```

If the output is `true`, display `Commit signing: enabled` in the health summary area and skip to Phase 3.
If the output is `true`, display `Commit signing: enabled` in the health summary area and skip to Phase 4.

If not `true`, ask: **"Does this project require signed commits? (yes/no)"**

Wait for response.

- **no / skip** → continue to Phase 3.
- **no / skip** → continue to Phase 4.
- **yes** → proceed with signing setup.

**Verify a signing key exists:**
Expand All @@ -289,9 +319,9 @@ I'll enable commit and tag signing for this repo:
Proceed? (yes/no)
```

Wait for confirmation. Write only on yes. If no, skip to Phase 3.
Wait for confirmation. Write only on yes. If no, skip to Phase 4.

Continue to Phase 3.
Continue to Phase 4.

**If no signing key is found**, detect the signing format:

Expand All @@ -314,13 +344,13 @@ I'll configure signing for this repo:
Proceed? (yes/no)
```

Wait for confirmation. Write only on yes. If no, skip to Phase 3.
Wait for confirmation. Write only on yes. If no, skip to Phase 4.

If the user has no signing key and doesn't know how to create one, point them to GitHub's signing key documentation and stop: "Set up a signing key first, then run `/setup` again to enable commit signing."

---

### Phase 3 — Label population
### Phase 4 — Label population

Run:

Expand Down Expand Up @@ -352,7 +382,7 @@ Wait for response.

After this step (or if labels were non-zero initially), run `gh label list --limit 100 --json name,color,description` again.

If `TICKET_LABELS` is unset or fewer than 5 labels exist, add a note: "`/start` works best with a clear issue-label pool (`TICKET_LABELS`), and `/qa` needs explicit QA lifecycle labels (`ready-for-qa`, `qa-passed`, `qa-failed`). Consider a lightweight priority scheme (e.g. `priority:high`, `priority:medium`, `priority:low`) if the team needs triage support. If the team runs planned iterations, set `DEFAULT_MILESTONE` in Phase 4; otherwise leave it unset so `/start` auto-detects."
If `TICKET_LABELS` is unset or fewer than 5 labels exist, add a note: "`/start` works best with a clear issue-label pool (`TICKET_LABELS`), and `/qa` needs explicit QA lifecycle labels (`ready-for-qa`, `qa-passed`, `qa-failed`). Consider a lightweight priority scheme (e.g. `priority:high`, `priority:medium`, `priority:low`) if the team needs triage support. If the team runs planned iterations, set `DEFAULT_MILESTONE` in Phase 5; otherwise leave it unset so `/start` auto-detects."

Display the results as a numbered list:

Expand All @@ -370,7 +400,7 @@ Wait for the user's response.

- **yes** → use all labels
- **numbers** (e.g. `1,3,5`) → use only those labels
- **no / skip / anything else** → skip this phase, continue to Phase 4
- **no / skip / anything else** → skip this phase, continue to Phase 5

Show the exact change before writing:

Expand All @@ -386,7 +416,7 @@ Wait for confirmation. Write only on yes.

---

### Phase 4 — Optional config walkthrough (profile-aware)
### Phase 5 — Optional config walkthrough (profile-aware)

First, infer the current profile using the same rules as Phase 1.

Expand All @@ -408,7 +438,7 @@ The walkthrough adapts based on profile. Walk through each applicable unset valu

---

### Phase 5 — Team sharing
### Phase 6 — Team sharing

After completing or skipping the config walkthrough, say:

Expand All @@ -426,11 +456,11 @@ Add a note: `/start` can be used to create well-formed GitHub issues without wri

## Hard rules

- Only modify `.codecannon.yaml` and local git config (Phase 2 signing setup). Do not touch any other file (except running `CodeCannon/sync.py`, which modifies `.claude/commands/` — permitted only with explicit user approval).
- Only modify `.codecannon.yaml` and local git config (Phase 3 signing setup). Do not touch any other file (except running `CodeCannon/sync.py`, which modifies `.claude/commands/` — permitted only with explicit user approval).
- Do not run `sync.py` without explicit user permission.
- Do not create `.codecannon.yaml` without explicit user permission.
- Do not report a configuration problem unless confident the condition is genuinely broken. Prefer false negatives over false positives on all diagnostic checks.
- Never fetch more than 100 labels in a single command. `gh label list --limit 100` is the ceiling.
- Do not skip any human gate in Phase 2, Phase 3, or Phase 4 — each write requires confirmation.
- Do not skip any human gate in Phase 3, Phase 4, or Phase 5 — each write requires confirmation.
- If the user skips a config value, do not ask again. Move on.
<!-- generated by CodeCannon/sync.py | skill: setup | adapter: claude | hash: 410c035d | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->
<!-- generated by CodeCannon/sync.py | skill: setup | adapter: claude | hash: d15a6e01 | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->
14 changes: 7 additions & 7 deletions .claude/commands/submit-for-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ If the current branch matches any of the above, **abort immediately** and say:

## Step 2 — Type-check gate

First, move to the repository root so the command resolves against the correct Makefile / project config:
First, find the repository root:

```
cd "$(git rev-parse --show-toplevel)"
git rev-parse --show-toplevel
```

Then verify the make target exists before running it. Extract the target name from `make check` (e.g. `make check` → `check`) and run:
Then `cd` to the returned path and verify the make target exists. Extract the target name from `make check` (e.g. `make check` → `check`) and run:

```
make -n <target> 2>/dev/null
cd <repo-root> && make -n <target> 2>/dev/null
```

If `make -n` exits non-zero, **stop** and say:
Expand Down Expand Up @@ -183,10 +183,10 @@ Wait for the review to complete and report its verdict.

## Step 8 — Act on verdict

Before merging, verify the merge target exists. Move to the repo root, extract the target name from `make merge` (e.g. `make merge` → `merge`), and run:
Before merging, verify the merge target exists. Find the repo root with `git rev-parse --show-toplevel`, then extract the target name from `make merge` (e.g. `make merge` → `merge`) and run:

```
cd "$(git rev-parse --show-toplevel)" && make -n <target> 2>/dev/null
cd <repo-root> && make -n <target> 2>/dev/null
```

If `make -n` exits non-zero, **stop** and say:
Expand Down Expand Up @@ -345,4 +345,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.py | skill: submit-for-review | adapter: claude | hash: 626b7a97 | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->
<!-- generated by CodeCannon/sync.py | skill: submit-for-review | adapter: claude | hash: baa11804 | DO NOT EDIT — run CodeCannon/sync.py to regenerate -->
1 change: 1 addition & 0 deletions .claude/settings.local.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"permissions": {
"allow": [
"Bash(cat:*)",
"Bash(cd:*)",
"Bash(cp:*)",
"Bash(gh:*)",
"Bash(git:*)",
Expand Down
Loading
Loading