diff --git a/.agents/skills/checkpoint/SKILL.md b/.agents/skills/checkpoint/SKILL.md index cab107f..9864762 100644 --- a/.agents/skills/checkpoint/SKILL.md +++ b/.agents/skills/checkpoint/SKILL.md @@ -90,4 +90,4 @@ Say: - Never apply labels or modify issues. - Never run `make check` — checkpoints are not quality gates. - Do not prompt for confirmation — `/checkpoint` is a quick save, not a ceremony. - + diff --git a/.agents/skills/deploy/SKILL.md b/.agents/skills/deploy/SKILL.md index 5ae2bbb..48dadbe 100644 --- a/.agents/skills/deploy/SKILL.md +++ b/.agents/skills/deploy/SKILL.md @@ -253,4 +253,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 ``. Run `make deploy-prod` to ship to production." - + diff --git a/.agents/skills/qa/SKILL.md b/.agents/skills/qa/SKILL.md index 3caff8a..143b1b9 100644 --- a/.agents/skills/qa/SKILL.md +++ b/.agents/skills/qa/SKILL.md @@ -141,4 +141,4 @@ After applying labels, tell the user what was done: - Never post the comment without showing it to the user first. - Never apply labels without user confirmation (the confirmation in Step 3 is the single gate for both posting the comment and applying labels). - Never merge, deploy, or take any action beyond labeling and commenting. - + diff --git a/.agents/skills/review/SKILL.md b/.agents/skills/review/SKILL.md index 3b05b77..0e80566 100644 --- a/.agents/skills/review/SKILL.md +++ b/.agents/skills/review/SKILL.md @@ -17,7 +17,7 @@ description: Code Cannon: Run a standalone code review on a pull request If `ai` is `"off"`, say: -> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.sh." +> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.py." Do not proceed. @@ -65,4 +65,4 @@ After the review agent completes, relay its verdict to the user: - This command does not commit, push, or merge anything. It only reviews. - It may be called manually at any time, not just from `/submit-for-review`. - The review comment is posted to GitHub for the audit trail. - + diff --git a/.agents/skills/setup/SKILL.md b/.agents/skills/setup/SKILL.md index db355b6..f86ffc7 100644 --- a/.agents/skills/setup/SKILL.md +++ b/.agents/skills/setup/SKILL.md @@ -14,7 +14,7 @@ Before taking any action, determine which state the project is in. Run these che **Check A — Is this the Code Cannon skill library repo itself?** ```bash -test -f sync.sh && test -d skills +test -f sync.py && test -d skills ``` If both exist at the working directory root → **go to State 1**. @@ -52,7 +52,7 @@ Offer two forward paths and ask which they want: Explain the three-layer model: - **Skills** (`skills/*.md`) — portable workflow instructions with `main`-style tokens for project-specific values (see `config.schema.yaml`) - **Config** (`.codecannon.yaml`) — a project's values that fill those tokens at sync time -- **Sync** (`sync.sh`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) +- **Sync** (`sync.py`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) Point to README.md for the full skill list and documentation. Do not touch any file. @@ -66,7 +66,7 @@ git submodule add https://github.com/LightbridgeLab/CodeCannon.git CodeCannon git submodule update --init cp CodeCannon/templates/codecannon.yaml .codecannon.yaml # Edit .codecannon.yaml — set branch names, commands, adapters -CodeCannon/sync.sh +CodeCannon/sync.py ``` Do not touch any file. The user runs these commands in their project directory. @@ -77,10 +77,10 @@ Do not touch any file. The user runs these commands in their project directory. Run checks 1–7 in order. Stop at the first failing check and address it. After describing the fix, tell the user to run `/setup` again once they've resolved it. Do not continue past a failing check. -### Check 1 — CodeCannon/sync.sh present +### Check 1 — CodeCannon/sync.py present ```bash -test -f CodeCannon/sync.sh +test -f CodeCannon/sync.py ``` If missing: the submodule was added to `.gitmodules` or `CodeCannon/` exists as an empty directory, but it hasn't been initialized. Show: @@ -191,18 +191,18 @@ If anything is flagged: show the specific key names and what they should likely ### Check 7 — Generated skill output present -Check whether sync.sh has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: +Check whether sync.py has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: ```bash test -d .claude/commands || test -d .cursor/rules || test -d .agents/skills || test -d .gemini/skills ``` -If none exist: "sync.sh hasn't been run yet — the skill commands don't exist." +If none exist: "sync.py hasn't been run yet — the skill commands don't exist." Show: ```bash -CodeCannon/sync.sh +CodeCannon/sync.py ``` Ask permission to run it. If the user agrees, run it. If they decline, tell them to run it manually before continuing. Stop. @@ -364,11 +364,11 @@ Add a note: `/start` can be used to create well-formed GitHub issues without wri ## Hard rules -- Only modify `.codecannon.yaml`. Do not touch any other file (except running `CodeCannon/sync.sh`, which modifies `.claude/commands/` — permitted only with explicit user approval). -- Do not run `sync.sh` without explicit user permission. +- Only modify `.codecannon.yaml`. 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 or Phase 3 — each write requires confirmation. - If the user skips a config value, do not ask again. Move on. - + diff --git a/.agents/skills/start/SKILL.md b/.agents/skills/start/SKILL.md index 27c02ed..28e63a4 100644 --- a/.agents/skills/start/SKILL.md +++ b/.agents/skills/start/SKILL.md @@ -313,4 +313,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/.agents/skills/status/SKILL.md b/.agents/skills/status/SKILL.md index 0c97559..6f0f98b 100644 --- a/.agents/skills/status/SKILL.md +++ b/.agents/skills/status/SKILL.md @@ -366,4 +366,4 @@ Do not post, comment, write files, or take any action. Output only. - If `gh` is unauthenticated or any fetch fails, report the error and stop immediately. - Do not retry failed commands. - Strip the leading `@` from the subject when passing to `gh` flags that do not accept it. - + diff --git a/.agents/skills/submit-for-review/SKILL.md b/.agents/skills/submit-for-review/SKILL.md index 5cab5f5..f031964 100644 --- a/.agents/skills/submit-for-review/SKILL.md +++ b/.agents/skills/submit-for-review/SKILL.md @@ -325,4 +325,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/checkpoint.md b/.claude/commands/checkpoint.md index c7e8473..cb398f5 100644 --- a/.claude/commands/checkpoint.md +++ b/.claude/commands/checkpoint.md @@ -85,4 +85,4 @@ Say: - Never apply labels or modify issues. - Never run `make check` — checkpoints are not quality gates. - Do not prompt for confirmation — `/checkpoint` is a quick save, not a ceremony. - + diff --git a/.claude/commands/deploy.md b/.claude/commands/deploy.md index 9a5a2cb..54a296d 100644 --- a/.claude/commands/deploy.md +++ b/.claude/commands/deploy.md @@ -248,4 +248,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 ``. Run `make deploy-prod` to ship to production." - + diff --git a/.claude/commands/qa.md b/.claude/commands/qa.md index 7a09d4d..d10b822 100644 --- a/.claude/commands/qa.md +++ b/.claude/commands/qa.md @@ -136,4 +136,4 @@ After applying labels, tell the user what was done: - Never post the comment without showing it to the user first. - Never apply labels without user confirmation (the confirmation in Step 3 is the single gate for both posting the comment and applying labels). - Never merge, deploy, or take any action beyond labeling and commenting. - + diff --git a/.claude/commands/review.md b/.claude/commands/review.md index 6be83ca..9f544e3 100644 --- a/.claude/commands/review.md +++ b/.claude/commands/review.md @@ -12,7 +12,7 @@ Code Cannon: Run a standalone code review on a pull request If `ai` is `"off"`, say: -> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.sh." +> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.py." Do not proceed. @@ -60,4 +60,4 @@ After the review agent completes, relay its verdict to the user: - This command does not commit, push, or merge anything. It only reviews. - It may be called manually at any time, not just from `/submit-for-review`. - The review comment is posted to GitHub for the audit trail. - + diff --git a/.claude/commands/setup.md b/.claude/commands/setup.md index 299789b..15d78d5 100644 --- a/.claude/commands/setup.md +++ b/.claude/commands/setup.md @@ -9,7 +9,7 @@ Before taking any action, determine which state the project is in. Run these che **Check A — Is this the Code Cannon skill library repo itself?** ```bash -test -f sync.sh && test -d skills +test -f sync.py && test -d skills ``` If both exist at the working directory root → **go to State 1**. @@ -47,7 +47,7 @@ Offer two forward paths and ask which they want: Explain the three-layer model: - **Skills** (`skills/*.md`) — portable workflow instructions with `main`-style tokens for project-specific values (see `config.schema.yaml`) - **Config** (`.codecannon.yaml`) — a project's values that fill those tokens at sync time -- **Sync** (`sync.sh`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) +- **Sync** (`sync.py`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) Point to README.md for the full skill list and documentation. Do not touch any file. @@ -61,7 +61,7 @@ git submodule add https://github.com/LightbridgeLab/CodeCannon.git CodeCannon git submodule update --init cp CodeCannon/templates/codecannon.yaml .codecannon.yaml # Edit .codecannon.yaml — set branch names, commands, adapters -CodeCannon/sync.sh +CodeCannon/sync.py ``` Do not touch any file. The user runs these commands in their project directory. @@ -72,10 +72,10 @@ Do not touch any file. The user runs these commands in their project directory. Run checks 1–7 in order. Stop at the first failing check and address it. After describing the fix, tell the user to run `/setup` again once they've resolved it. Do not continue past a failing check. -### Check 1 — CodeCannon/sync.sh present +### Check 1 — CodeCannon/sync.py present ```bash -test -f CodeCannon/sync.sh +test -f CodeCannon/sync.py ``` If missing: the submodule was added to `.gitmodules` or `CodeCannon/` exists as an empty directory, but it hasn't been initialized. Show: @@ -186,18 +186,18 @@ If anything is flagged: show the specific key names and what they should likely ### Check 7 — Generated skill output present -Check whether sync.sh has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: +Check whether sync.py has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: ```bash test -d .claude/commands || test -d .cursor/rules || test -d .agents/skills || test -d .gemini/skills ``` -If none exist: "sync.sh hasn't been run yet — the skill commands don't exist." +If none exist: "sync.py hasn't been run yet — the skill commands don't exist." Show: ```bash -CodeCannon/sync.sh +CodeCannon/sync.py ``` Ask permission to run it. If the user agrees, run it. If they decline, tell them to run it manually before continuing. Stop. @@ -359,11 +359,11 @@ Add a note: `/start` can be used to create well-formed GitHub issues without wri ## Hard rules -- Only modify `.codecannon.yaml`. Do not touch any other file (except running `CodeCannon/sync.sh`, which modifies `.claude/commands/` — permitted only with explicit user approval). -- Do not run `sync.sh` without explicit user permission. +- Only modify `.codecannon.yaml`. 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 or Phase 3 — each write requires confirmation. - If the user skips a config value, do not ask again. Move on. - + diff --git a/.claude/commands/start.md b/.claude/commands/start.md index b769146..dc01d24 100644 --- a/.claude/commands/start.md +++ b/.claude/commands/start.md @@ -308,4 +308,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/status.md b/.claude/commands/status.md index f7d3554..6fb7c49 100644 --- a/.claude/commands/status.md +++ b/.claude/commands/status.md @@ -361,4 +361,4 @@ Do not post, comment, write files, or take any action. Output only. - If `gh` is unauthenticated or any fetch fails, report the error and stop immediately. - Do not retry failed commands. - Strip the leading `@` from the subject when passing to `gh` flags that do not accept it. - + diff --git a/.claude/commands/submit-for-review.md b/.claude/commands/submit-for-review.md index 6ae24c6..cb9f0ce 100644 --- a/.claude/commands/submit-for-review.md +++ b/.claude/commands/submit-for-review.md @@ -320,4 +320,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/review-agent-prompt.md b/.claude/review-agent-prompt.md index 8c167c1..1f2b743 100644 --- a/.claude/review-agent-prompt.md +++ b/.claude/review-agent-prompt.md @@ -107,4 +107,4 @@ If no findings: "No issues found. Code looks correct and follows project convent - Do not suggest improvements outside the scope of the PR. - Do not re-review files that haven't changed. - Your review is posted to GitHub for the audit trail — keep it professional. - + diff --git a/.claude/settings.local.json.example b/.claude/settings.local.json.example index dfb9d30..4e6cacb 100644 --- a/.claude/settings.local.json.example +++ b/.claude/settings.local.json.example @@ -10,7 +10,7 @@ "Bash(python3:*)", "Bash(which:*)", "Bash(wc:*)", - "Bash(./sync.sh:*)", + "Bash(./sync.py:*)", "WebSearch" ] } diff --git a/.codecannon.yaml b/.codecannon.yaml index bfed680..ac659f4 100644 --- a/.codecannon.yaml +++ b/.codecannon.yaml @@ -1,7 +1,7 @@ # .codecannon.yaml — project configuration for Code Cannon skill sync # -# This is Code Cannon's own config. Unlike consumer projects (which run CodeCannon/sync.sh), -# this repo runs sync as ./sync.sh — Code Cannon is not a submodule of itself. +# This is Code Cannon's own config. Unlike consumer projects (which run CodeCannon/sync.py), +# this repo runs sync as ./sync.py — Code Cannon is not a submodule of itself. # # See config.schema.yaml for documentation on each placeholder. @@ -14,7 +14,7 @@ adapters: - gemini # Placeholder values substituted into skill files during sync. -# Remove any you don't need; sync.sh will warn about unresolved placeholders. +# Remove any you don't need; sync.py will warn about unresolved placeholders. config: BRANCH_PROD: main BRANCH_DEV: dev diff --git a/.cursor/rules/checkpoint.mdc b/.cursor/rules/checkpoint.mdc index 5ec2e26..fede9c4 100644 --- a/.cursor/rules/checkpoint.mdc +++ b/.cursor/rules/checkpoint.mdc @@ -91,4 +91,4 @@ Say: - Never apply labels or modify issues. - Never run `make check` — checkpoints are not quality gates. - Do not prompt for confirmation — `/checkpoint` is a quick save, not a ceremony. - + diff --git a/.cursor/rules/deploy.mdc b/.cursor/rules/deploy.mdc index 664a54a..4bfab50 100644 --- a/.cursor/rules/deploy.mdc +++ b/.cursor/rules/deploy.mdc @@ -254,4 +254,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 ``. Run `make deploy-prod` to ship to production." - + diff --git a/.cursor/rules/qa.mdc b/.cursor/rules/qa.mdc index d5e2f97..f7cbb47 100644 --- a/.cursor/rules/qa.mdc +++ b/.cursor/rules/qa.mdc @@ -142,4 +142,4 @@ After applying labels, tell the user what was done: - Never post the comment without showing it to the user first. - Never apply labels without user confirmation (the confirmation in Step 3 is the single gate for both posting the comment and applying labels). - Never merge, deploy, or take any action beyond labeling and commenting. - + diff --git a/.cursor/rules/review.mdc b/.cursor/rules/review.mdc index 76f26ec..aa42ebb 100644 --- a/.cursor/rules/review.mdc +++ b/.cursor/rules/review.mdc @@ -18,7 +18,7 @@ alwaysApply: false If `ai` is `"off"`, say: -> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.sh." +> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.py." Do not proceed. @@ -66,4 +66,4 @@ After the review agent completes, relay its verdict to the user: - This command does not commit, push, or merge anything. It only reviews. - It may be called manually at any time, not just from `/submit-for-review`. - The review comment is posted to GitHub for the audit trail. - + diff --git a/.cursor/rules/setup.mdc b/.cursor/rules/setup.mdc index b8e89a5..689ece5 100644 --- a/.cursor/rules/setup.mdc +++ b/.cursor/rules/setup.mdc @@ -15,7 +15,7 @@ Before taking any action, determine which state the project is in. Run these che **Check A — Is this the Code Cannon skill library repo itself?** ```bash -test -f sync.sh && test -d skills +test -f sync.py && test -d skills ``` If both exist at the working directory root → **go to State 1**. @@ -53,7 +53,7 @@ Offer two forward paths and ask which they want: Explain the three-layer model: - **Skills** (`skills/*.md`) — portable workflow instructions with `main`-style tokens for project-specific values (see `config.schema.yaml`) - **Config** (`.codecannon.yaml`) — a project's values that fill those tokens at sync time -- **Sync** (`sync.sh`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) +- **Sync** (`sync.py`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) Point to README.md for the full skill list and documentation. Do not touch any file. @@ -67,7 +67,7 @@ git submodule add https://github.com/LightbridgeLab/CodeCannon.git CodeCannon git submodule update --init cp CodeCannon/templates/codecannon.yaml .codecannon.yaml # Edit .codecannon.yaml — set branch names, commands, adapters -CodeCannon/sync.sh +CodeCannon/sync.py ``` Do not touch any file. The user runs these commands in their project directory. @@ -78,10 +78,10 @@ Do not touch any file. The user runs these commands in their project directory. Run checks 1–7 in order. Stop at the first failing check and address it. After describing the fix, tell the user to run `/setup` again once they've resolved it. Do not continue past a failing check. -### Check 1 — CodeCannon/sync.sh present +### Check 1 — CodeCannon/sync.py present ```bash -test -f CodeCannon/sync.sh +test -f CodeCannon/sync.py ``` If missing: the submodule was added to `.gitmodules` or `CodeCannon/` exists as an empty directory, but it hasn't been initialized. Show: @@ -192,18 +192,18 @@ If anything is flagged: show the specific key names and what they should likely ### Check 7 — Generated skill output present -Check whether sync.sh has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: +Check whether sync.py has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: ```bash test -d .claude/commands || test -d .cursor/rules || test -d .agents/skills || test -d .gemini/skills ``` -If none exist: "sync.sh hasn't been run yet — the skill commands don't exist." +If none exist: "sync.py hasn't been run yet — the skill commands don't exist." Show: ```bash -CodeCannon/sync.sh +CodeCannon/sync.py ``` Ask permission to run it. If the user agrees, run it. If they decline, tell them to run it manually before continuing. Stop. @@ -365,11 +365,11 @@ Add a note: `/start` can be used to create well-formed GitHub issues without wri ## Hard rules -- Only modify `.codecannon.yaml`. Do not touch any other file (except running `CodeCannon/sync.sh`, which modifies `.claude/commands/` — permitted only with explicit user approval). -- Do not run `sync.sh` without explicit user permission. +- Only modify `.codecannon.yaml`. 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 or Phase 3 — each write requires confirmation. - If the user skips a config value, do not ask again. Move on. - + diff --git a/.cursor/rules/start.mdc b/.cursor/rules/start.mdc index 58440b6..720171b 100644 --- a/.cursor/rules/start.mdc +++ b/.cursor/rules/start.mdc @@ -314,4 +314,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/status.mdc b/.cursor/rules/status.mdc index 373745b..38287b2 100644 --- a/.cursor/rules/status.mdc +++ b/.cursor/rules/status.mdc @@ -367,4 +367,4 @@ Do not post, comment, write files, or take any action. Output only. - If `gh` is unauthenticated or any fetch fails, report the error and stop immediately. - Do not retry failed commands. - Strip the leading `@` from the subject when passing to `gh` flags that do not accept it. - + diff --git a/.cursor/rules/submit-for-review.mdc b/.cursor/rules/submit-for-review.mdc index 085ebad..8fa4491 100644 --- a/.cursor/rules/submit-for-review.mdc +++ b/.cursor/rules/submit-for-review.mdc @@ -326,4 +326,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/checkpoint/SKILL.md b/.gemini/skills/checkpoint/SKILL.md index beb2bf8..1f2c0ff 100644 --- a/.gemini/skills/checkpoint/SKILL.md +++ b/.gemini/skills/checkpoint/SKILL.md @@ -90,4 +90,4 @@ Say: - Never apply labels or modify issues. - Never run `make check` — checkpoints are not quality gates. - Do not prompt for confirmation — `/checkpoint` is a quick save, not a ceremony. - + diff --git a/.gemini/skills/deploy/SKILL.md b/.gemini/skills/deploy/SKILL.md index c50671f..0671f7f 100644 --- a/.gemini/skills/deploy/SKILL.md +++ b/.gemini/skills/deploy/SKILL.md @@ -253,4 +253,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 ``. Run `make deploy-prod` to ship to production." - + diff --git a/.gemini/skills/qa/SKILL.md b/.gemini/skills/qa/SKILL.md index c0a1c01..8f4ce48 100644 --- a/.gemini/skills/qa/SKILL.md +++ b/.gemini/skills/qa/SKILL.md @@ -141,4 +141,4 @@ After applying labels, tell the user what was done: - Never post the comment without showing it to the user first. - Never apply labels without user confirmation (the confirmation in Step 3 is the single gate for both posting the comment and applying labels). - Never merge, deploy, or take any action beyond labeling and commenting. - + diff --git a/.gemini/skills/review/SKILL.md b/.gemini/skills/review/SKILL.md index 6ed1327..bf39c80 100644 --- a/.gemini/skills/review/SKILL.md +++ b/.gemini/skills/review/SKILL.md @@ -17,7 +17,7 @@ description: Code Cannon: Run a standalone code review on a pull request If `ai` is `"off"`, say: -> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.sh." +> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.py." Do not proceed. @@ -65,4 +65,4 @@ After the review agent completes, relay its verdict to the user: - This command does not commit, push, or merge anything. It only reviews. - It may be called manually at any time, not just from `/submit-for-review`. - The review comment is posted to GitHub for the audit trail. - + diff --git a/.gemini/skills/setup/SKILL.md b/.gemini/skills/setup/SKILL.md index 1c274f2..3ca9690 100644 --- a/.gemini/skills/setup/SKILL.md +++ b/.gemini/skills/setup/SKILL.md @@ -14,7 +14,7 @@ Before taking any action, determine which state the project is in. Run these che **Check A — Is this the Code Cannon skill library repo itself?** ```bash -test -f sync.sh && test -d skills +test -f sync.py && test -d skills ``` If both exist at the working directory root → **go to State 1**. @@ -52,7 +52,7 @@ Offer two forward paths and ask which they want: Explain the three-layer model: - **Skills** (`skills/*.md`) — portable workflow instructions with `main`-style tokens for project-specific values (see `config.schema.yaml`) - **Config** (`.codecannon.yaml`) — a project's values that fill those tokens at sync time -- **Sync** (`sync.sh`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) +- **Sync** (`sync.py`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) Point to README.md for the full skill list and documentation. Do not touch any file. @@ -66,7 +66,7 @@ git submodule add https://github.com/LightbridgeLab/CodeCannon.git CodeCannon git submodule update --init cp CodeCannon/templates/codecannon.yaml .codecannon.yaml # Edit .codecannon.yaml — set branch names, commands, adapters -CodeCannon/sync.sh +CodeCannon/sync.py ``` Do not touch any file. The user runs these commands in their project directory. @@ -77,10 +77,10 @@ Do not touch any file. The user runs these commands in their project directory. Run checks 1–7 in order. Stop at the first failing check and address it. After describing the fix, tell the user to run `/setup` again once they've resolved it. Do not continue past a failing check. -### Check 1 — CodeCannon/sync.sh present +### Check 1 — CodeCannon/sync.py present ```bash -test -f CodeCannon/sync.sh +test -f CodeCannon/sync.py ``` If missing: the submodule was added to `.gitmodules` or `CodeCannon/` exists as an empty directory, but it hasn't been initialized. Show: @@ -191,18 +191,18 @@ If anything is flagged: show the specific key names and what they should likely ### Check 7 — Generated skill output present -Check whether sync.sh has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: +Check whether sync.py has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: ```bash test -d .claude/commands || test -d .cursor/rules || test -d .agents/skills || test -d .gemini/skills ``` -If none exist: "sync.sh hasn't been run yet — the skill commands don't exist." +If none exist: "sync.py hasn't been run yet — the skill commands don't exist." Show: ```bash -CodeCannon/sync.sh +CodeCannon/sync.py ``` Ask permission to run it. If the user agrees, run it. If they decline, tell them to run it manually before continuing. Stop. @@ -364,11 +364,11 @@ Add a note: `/start` can be used to create well-formed GitHub issues without wri ## Hard rules -- Only modify `.codecannon.yaml`. Do not touch any other file (except running `CodeCannon/sync.sh`, which modifies `.claude/commands/` — permitted only with explicit user approval). -- Do not run `sync.sh` without explicit user permission. +- Only modify `.codecannon.yaml`. 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 or Phase 3 — each write requires confirmation. - If the user skips a config value, do not ask again. Move on. - + diff --git a/.gemini/skills/start/SKILL.md b/.gemini/skills/start/SKILL.md index 640d717..a84528a 100644 --- a/.gemini/skills/start/SKILL.md +++ b/.gemini/skills/start/SKILL.md @@ -313,4 +313,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/status/SKILL.md b/.gemini/skills/status/SKILL.md index 3b4fb5c..bd4caca 100644 --- a/.gemini/skills/status/SKILL.md +++ b/.gemini/skills/status/SKILL.md @@ -366,4 +366,4 @@ Do not post, comment, write files, or take any action. Output only. - If `gh` is unauthenticated or any fetch fails, report the error and stop immediately. - Do not retry failed commands. - Strip the leading `@` from the subject when passing to `gh` flags that do not accept it. - + diff --git a/.gemini/skills/submit-for-review/SKILL.md b/.gemini/skills/submit-for-review/SKILL.md index 5a58f16..c2bab6e 100644 --- a/.gemini/skills/submit-for-review/SKILL.md +++ b/.gemini/skills/submit-for-review/SKILL.md @@ -325,4 +325,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/.github/workflows/sync-check.yml b/.github/workflows/sync-check.yml index 171ea5a..9eebc17 100644 --- a/.github/workflows/sync-check.yml +++ b/.github/workflows/sync-check.yml @@ -7,5 +7,5 @@ jobs: - uses: actions/checkout@v5 - name: Check for sync drift run: | - ./sync.sh --dry-run + ./sync.py --dry-run # exits non-zero if any files would be written diff --git a/AGENTS.md b/AGENTS.md index d38f85d..8fa85f9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ Instructions for AI coding agents working on the CodeCannon project itself. -CodeCannon is a skill distribution system. It stores generic agent workflow skills in `skills/`, adapter configs in `adapters/`, and a `sync.sh` script that generates agent-specific skill files for downstream projects. One source of truth, synced to every project and every AI agent. +CodeCannon is a skill distribution system. It stores generic agent workflow skills in `skills/`, adapter configs in `adapters/`, and a `sync.py` script that generates agent-specific skill files for downstream projects. One source of truth, synced to every project and every AI agent. ## Branch strategy @@ -35,7 +35,7 @@ These are the single source of truth for all generated output. Every edit to age .gemini/skills/ Gemini agent skills ``` -These are regenerated by `./sync.sh`. Each file contains a hash marker for change detection. If you need to change agent output, edit the source skill in `skills/` and re-run sync. +These are regenerated by `./sync.py`. Each file contains a hash marker for change detection. If you need to change agent output, edit the source skill in `skills/` and re-run sync. ### Adapters @@ -75,7 +75,7 @@ When asked to update documentation, check `docs/` first — most detailed docs l ``` Makefile CodeCannon-specific targets (sync, versioning, deployment) Makefile.agents.mk Generic git workflow targets (branch, pr, abandon, merge, promote) -sync.sh The core sync engine (Python 3) +sync.py The core sync engine (Python 3) VERSION Current version number (plain text, e.g. 0.3.3) ``` @@ -130,13 +130,13 @@ Skills support conditional rendering: ### Change detection -`sync.sh` embeds an MD5 hash in a marker comment at the end of each generated file: +`sync.py` embeds an MD5 hash in a marker comment at the end of each generated file: ``` - + ``` -If someone manually edits a generated file, the hash won't match and `sync.sh` will refuse to overwrite it (unless run with `--force`). +If someone manually edits a generated file, the hash won't match and `sync.py` will refuse to overwrite it (unless run with `--force`). ## Working on CodeCannon @@ -167,7 +167,7 @@ The primary commands for working on this project: 1. Create `adapters/{name}/config.yaml` — set `agent`, `output_directory`, and `output_extension`. 2. Create `adapters/{name}/header.md` — invocation header template using `{skill}` and `{description}`. -3. Test with `./sync.sh --skill start`. +3. Test with `./sync.py --skill start`. 4. Document any adapter limitations in `config.yaml` under `notes`. 5. Update `docs/adapters.md`. @@ -181,7 +181,7 @@ The primary commands for working on this project: ## Self-hosting: using CodeCannon to develop CodeCannon -This repo is the only project that runs sync as `./sync.sh` instead of `CodeCannon/sync.sh`. Every consumer project uses the submodule path — this is the exception. +This repo is the only project that runs sync as `./sync.py` instead of `CodeCannon/sync.py`. Every consumer project uses the submodule path — this is the exception. - **Edit-test loop**: edit a skill in `skills/` → `make check` → `make dev` → `make sync` → commit source + generated files together. - **All adapter outputs are generated**: after editing a skill, `make sync` regenerates `.claude/commands/`, `.cursor/rules/`, `.agents/skills/`, and `.gemini/skills/`. Commit all of them. @@ -215,7 +215,7 @@ docs/ user-facing documentation skills/ per-skill documentation config.schema.yaml placeholder documentation (canonical) .codecannon.yaml this project's config -sync.sh the sync engine +sync.py the sync engine Makefile project-specific targets Makefile.agents.mk generic git workflow targets VERSION current version diff --git a/Makefile b/Makefile index 75c1bff..737c6ff 100644 --- a/Makefile +++ b/Makefile @@ -35,16 +35,16 @@ help: # Validate that all skill placeholders resolve against the config. check: - ./sync.sh --validate + ./sync.py --validate # Preview what sync would generate without writing any files. dev: - ./sync.sh --validate - ./sync.sh --dry-run + ./sync.py --validate + ./sync.py --dry-run # Regenerate .claude/commands/ and other adapter output from skills/. sync: - ./sync.sh + ./sync.py # Bump the patch segment (X.Y.Z → X.Y.Z+1), commit, and tag. bump-patch: diff --git a/README.md b/README.md index 9bdd05d..590d56c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Code Cannon](.github/assets/readme-header.png) -[![CI](https://github.com/LightbridgeLab/CodeCannon/actions/workflows/sync-check.yml/badge.svg)](https://github.com/LightbridgeLab/CodeCannon/actions/workflows/sync-check.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![GitHub release](https://img.shields.io/github/v/release/LightbridgeLab/CodeCannon)](https://github.com/LightbridgeLab/CodeCannon/releases) [![Last Commit](https://img.shields.io/github/last-commit/LightbridgeLab/CodeCannon)](https://github.com/LightbridgeLab/CodeCannon/commits) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/contributing.md) [![Python](https://img.shields.io/badge/Python-3.x-blue?logo=python&logoColor=white)](sync.sh) [![Install](https://img.shields.io/badge/install-git%20submodule-blue?logo=git&logoColor=white)](https://github.com/LightbridgeLab/CodeCannon#quick-start) +[![CI](https://github.com/LightbridgeLab/CodeCannon/actions/workflows/sync-check.yml/badge.svg)](https://github.com/LightbridgeLab/CodeCannon/actions/workflows/sync-check.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![GitHub release](https://img.shields.io/github/v/release/LightbridgeLab/CodeCannon)](https://github.com/LightbridgeLab/CodeCannon/releases) [![Last Commit](https://img.shields.io/github/last-commit/LightbridgeLab/CodeCannon)](https://github.com/LightbridgeLab/CodeCannon/commits) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](docs/contributing.md) [![Python](https://img.shields.io/badge/Python-3.x-blue?logo=python&logoColor=white)](sync.py) [![Install](https://img.shields.io/badge/install-git%20submodule-blue?logo=git&logoColor=white)](https://github.com/LightbridgeLab/CodeCannon#quick-start) # Code Cannon @@ -15,7 +15,7 @@ AI coding agents are powerful, but every project reinvents the same workflows: h 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 +skills/*.md → sync.py + .codecannon.yaml → .claude/commands/*.md → .cursor/rules/*.mdc ``` @@ -51,10 +51,12 @@ Plus `/qa` for structured QA workflows and `/setup` for guided onboarding. ## Quick start +Requires Python 3.8+ (stdlib only — no pip install needed). + ```bash git submodule add https://github.com/LightbridgeLab/CodeCannon.git CodeCannon cp CodeCannon/templates/codecannon.yaml .codecannon.yaml -CodeCannon/sync.sh +CodeCannon/sync.py ``` Then optionally run `/setup` for a guided walkthrough. @@ -62,14 +64,14 @@ Then optionally run `/setup` for a guided walkthrough. To update to the latest version: ```bash -CodeCannon/sync.sh --update +CodeCannon/sync.py --update ``` ## Documentation - **[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, sync.sh reference +- **[Customization](docs/customization.md)** — tailoring skills, sync.py 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:** [/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) diff --git a/docs/adapters.md b/docs/adapters.md index 45a19ab..ad33bad 100644 --- a/docs/adapters.md +++ b/docs/adapters.md @@ -45,7 +45,7 @@ adapters: - gemini ``` -Run `sync.sh` to generate files for all listed adapters. You can enable both simultaneously — they write to different directories and don't conflict. +Run `sync.py` to generate files for all listed adapters. You can enable both simultaneously — they write to different directories and don't conflict. ## How adapters work @@ -70,7 +70,7 @@ To support a new AI coding agent: 2. Create `adapters//header.md` — the invocation header that tells the agent how to interpret the skill. Use `{skill}` and `{description}` as placeholders for the skill name and description. -3. Test with `sync.sh --skill start` against a test project. +3. Test with `sync.py --skill start` against a test project. 4. Document any adapter limitations in `config.yaml` under `notes`. diff --git a/docs/branching.md b/docs/branching.md index bc06611..6964337 100644 --- a/docs/branching.md +++ b/docs/branching.md @@ -84,9 +84,9 @@ The agent will not proceed past these checks. There is no override flag — if y When working on multiple features simultaneously, **sequence tasks that touch overlapping files — don't parallelize them.** Submit and merge the first branch before starting the second. -This is especially important for tasks that involve renaming, restructuring, or updating cross-references across skills. These changes tend to be broad in scope (touching many files) even though the individual edits are small. Running `sync.sh` amplifies the problem further: a one-line edit in a source skill becomes changes across every adapter directory (`.claude/`, `.cursor/`, `.agents/`, `.gemini/`), multiplying the conflict surface. +This is especially important for tasks that involve renaming, restructuring, or updating cross-references across skills. These changes tend to be broad in scope (touching many files) even though the individual edits are small. Running `sync.py` amplifies the problem further: a one-line edit in a source skill becomes changes across every adapter directory (`.claude/`, `.cursor/`, `.agents/`, `.gemini/`), multiplying the conflict surface. -If you do end up with parallel branches that conflict, the cleanest resolution is usually to re-apply the smaller change on a fresh branch off the updated integration branch, rather than resolving conflicts file-by-file. The mechanical nature of most cross-cutting changes (find-and-replace + `sync.sh`) makes this fast and reliable. +If you do end up with parallel branches that conflict, the cleanest resolution is usually to re-apply the smaller change on a fresh branch off the updated integration branch, rather than resolving conflicts file-by-file. The mechanical nature of most cross-cutting changes (find-and-replace + `sync.py`) makes this fast and reliable. ## Cleaning up merged branches diff --git a/docs/config-reference.md b/docs/config-reference.md index eef34dc..8572236 100644 --- a/docs/config-reference.md +++ b/docs/config-reference.md @@ -1,6 +1,6 @@ # Config Reference -All placeholders available in `.codecannon.yaml`. Each is substituted into skill files by `sync.sh`. +All placeholders available in `.codecannon.yaml`. Each is substituted into skill files by `sync.py`. For the canonical source, see [`config.schema.yaml`](../config.schema.yaml). @@ -73,4 +73,4 @@ adapters: - cursor ``` -This controls which agent adapters `sync.sh` generates files for. See [adapters](adapters.md) for details on each. +This controls which agent adapters `sync.py` generates files for. See [adapters](adapters.md) for details on each. diff --git a/docs/contributing.md b/docs/contributing.md index 00301a6..0ce9a48 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -14,14 +14,14 @@ Install it once per clone: cat > .git/hooks/pre-commit << 'EOF' #!/bin/sh # Ensure agent skill files are in sync before committing. -# sync.sh --dry-run exits 1 if any files need regeneration. -./sync.sh --dry-run 2>/dev/null +# sync.py --dry-run exits 1 if any files need regeneration. +./sync.py --dry-run 2>/dev/null if [ $? -ne 0 ]; then - echo "Skills are out of sync. Run ./sync.sh --force before committing." + echo "Skills are out of sync. Run ./sync.py --force before committing." exit 1 fi EOF chmod +x .git/hooks/pre-commit ``` -If a commit is rejected, run `./sync.sh --force` and retry. +If a commit is rejected, run `./sync.py --force` and retry. diff --git a/docs/customization.md b/docs/customization.md index 2dcecd6..5b13479 100644 --- a/docs/customization.md +++ b/docs/customization.md @@ -4,7 +4,7 @@ Code Cannon is designed to be configured, not forked. All project-specific behav ## How placeholders work -Skills in `skills/` use `{{PLACEHOLDER}}` tokens wherever behavior needs to vary between projects. When you run `sync.sh`, it reads your `.codecannon.yaml`, substitutes each placeholder with your project's value, and writes the generated skill files. +Skills in `skills/` use `{{PLACEHOLDER}}` tokens wherever behavior needs to vary between projects. When you run `sync.py`, it reads your `.codecannon.yaml`, substitutes each placeholder with your project's value, and writes the generated skill files. For example, the `/submit-for-review` skill contains: @@ -125,24 +125,24 @@ After running sync, add project-specific sections to `AGENTS.md` below the separ The `AGENTS.md` template provides the structure. Your additions live alongside the generated content and give agents broader context about your project beyond what the skill placeholders cover. -## sync.sh and manual edits +## sync.py and manual edits Every generated file includes a hash comment in its header: ``` - + ``` -When you run `sync.sh`, it computes the expected hash for each file. If the file on disk has a different hash (because you edited it manually), sync.sh warns and skips that file. This protects intentional customizations. +When you run `sync.py`, it computes the expected hash for each file. If the file on disk has a different hash (because you edited it manually), sync.py warns and skips that file. This protects intentional customizations. -To overwrite anyway: `sync.sh --force`. +To overwrite anyway: `sync.py --force`. -To regenerate only specific skills: `sync.sh --skill start,submit-for-review`. +To regenerate only specific skills: `sync.py --skill start,submit-for-review`. -### sync.sh reference +### sync.py reference ``` -./CodeCannon/sync.sh [options] +./CodeCannon/sync.py [options] Options: --config path Project config file (default: .codecannon.yaml) diff --git a/docs/index.md b/docs/index.md index 6202157..74b590c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,8 +5,8 @@ Code Cannon is a portable agent workflow skill library. Write your team's develo ## How it works 1. **Skills** live in `skills/` as plain markdown with `{{PLACEHOLDER}}` tokens for project-specific values. -2. **`sync.sh`** reads your project config (`.codecannon.yaml`), substitutes values, wraps each skill in an agent-specific invocation header, and writes the generated files to the right place (`.claude/commands/`, `.cursor/rules/`, etc.). -3. **Generated files** carry a hash so sync.sh can detect manual edits and warn before overwriting. +2. **`sync.py`** reads your project config (`.codecannon.yaml`), substitutes values, wraps each skill in an agent-specific invocation header, and writes the generated files to the right place (`.claude/commands/`, `.cursor/rules/`, etc.). +3. **Generated files** carry a hash so sync.py can detect manual edits and warn before overwriting. ## The workflow @@ -37,6 +37,8 @@ The agent commits; you test. `/start` writes code but does not commit — it han ## Quickstart +**Requires Python 3.8+** (stdlib only — no pip install needed). + ### 1. Add Code Cannon as a submodule ```bash @@ -55,7 +57,7 @@ Edit `.codecannon.yaml` — set your branch names, check command, deploy command ### 3. Run sync ```bash -CodeCannon/sync.sh +CodeCannon/sync.py ``` This generates skill files for each adapter listed in your config. For Claude Code, that's `.claude/commands/*.md`. For Cursor, `.cursor/rules/*.mdc`. @@ -89,10 +91,10 @@ Or skip all of this and run `/setup` for a guided walkthrough. ```bash git submodule update --remote CodeCannon # pull latest skills -CodeCannon/sync.sh # regenerate skill files +CodeCannon/sync.py # regenerate skill files ``` -If any generated files have been manually customized, sync.sh will warn and skip them. Use `--force` to overwrite. +If any generated files have been manually customized, sync.py will warn and skip them. Use `--force` to overwrite. ## Migrating from the old `agentgate` submodule @@ -100,7 +102,7 @@ If your project still uses the previous repo URL or folder name: 1. Point `.gitmodules` at `https://github.com/LightbridgeLab/CodeCannon.git` and use submodule path `CodeCannon/` (or rename your existing checkout to match). 2. Rename `.agentgate.yaml` to `.codecannon.yaml`. -3. Run `CodeCannon/sync.sh --force` once if needed so generated file headers match the new provenance marker. +3. Run `CodeCannon/sync.py --force` once if needed so generated file headers match the new provenance marker. ## Further reading diff --git a/docs/skills/setup.md b/docs/skills/setup.md index 5cc1869..681b8d1 100644 --- a/docs/skills/setup.md +++ b/docs/skills/setup.md @@ -9,7 +9,7 @@ First-run onboarding and configuration walkthrough. `/setup` detects the current state of Code Cannon in your project and guides you through configuration. It handles three scenarios: 1. **You're in the Code Cannon repo itself** — explains how Code Cannon works and offers to help you add it to your project. -2. **Partial setup** — the submodule exists but something is missing (sync.sh not initialized, `gh` not installed, config file missing, etc.). Walks through fixes one at a time. +2. **Partial setup** — the submodule exists but something is missing (sync.py not initialized, `gh` not installed, config file missing, etc.). Walks through fixes one at a time. 3. **Fully configured** — runs a health check, offers to populate labels from your GitHub repo, and walks through optional config values. ## Usage @@ -24,7 +24,7 @@ No arguments. Run it in any project where Code Cannon is (or should be) installe When the submodule is present, `/setup` runs these checks in order, stopping at the first failure: -1. **`CodeCannon/sync.sh` present** — submodule initialized? +1. **`CodeCannon/sync.py` present** — submodule initialized? 2. **`gh` installed** — GitHub CLI available? 3. **`gh` authenticated** — logged in to GitHub? 4. **Inside a GitHub repo** — remote configured? diff --git a/skills/qa.md b/skills/qa.md index 0512bb5..969a3b7 100644 --- a/skills/qa.md +++ b/skills/qa.md @@ -8,7 +8,7 @@ args: "none | issue number" {{#if !QA_READY_LABEL}} > **QA workflow is not configured.** `/qa` requires `QA_READY_LABEL` to be set in `.codecannon.yaml` so it can find issues waiting for QA. > -> To enable: add `QA_READY_LABEL: ready-for-qa` (or your preferred label name) to `.codecannon.yaml` and re-run `CodeCannon/sync.sh`. +> To enable: add `QA_READY_LABEL: ready-for-qa` (or your preferred label name) to `.codecannon.yaml` and re-run `CodeCannon/sync.py`. > > Note: In trunk mode, `/submit-for-review` does not apply this label automatically — you would need to apply it manually or via a separate workflow. diff --git a/skills/review.md b/skills/review.md index d9834af..74e2b99 100644 --- a/skills/review.md +++ b/skills/review.md @@ -15,7 +15,7 @@ args: "PR number (optional — defaults to current branch's open PR)" If `{{REVIEW_GATE}}` is `"off"`, say: -> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.sh." +> "Code review is disabled for this project (REVIEW_GATE is set to 'off' in .codecannon.yaml). To enable reviews, set REVIEW_GATE to 'ai' or 'advisory' and re-run CodeCannon/sync.py." Do not proceed. diff --git a/skills/setup.md b/skills/setup.md index d4d59ea..f6b63b4 100644 --- a/skills/setup.md +++ b/skills/setup.md @@ -12,7 +12,7 @@ Before taking any action, determine which state the project is in. Run these che **Check A — Is this the Code Cannon skill library repo itself?** ```bash -test -f sync.sh && test -d skills +test -f sync.py && test -d skills ``` If both exist at the working directory root → **go to State 1**. @@ -50,7 +50,7 @@ Offer two forward paths and ask which they want: Explain the three-layer model: - **Skills** (`skills/*.md`) — portable workflow instructions with `{{BRANCH_PROD}}`-style tokens for project-specific values (see `config.schema.yaml`) - **Config** (`.codecannon.yaml`) — a project's values that fill those tokens at sync time -- **Sync** (`sync.sh`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) +- **Sync** (`sync.py`) — reads the config, substitutes values, and writes generated command files for each adapter (Claude Code → `.claude/commands/`, Cursor → `.cursor/rules/`) Point to README.md for the full skill list and documentation. Do not touch any file. @@ -64,7 +64,7 @@ git submodule add https://github.com/LightbridgeLab/CodeCannon.git CodeCannon git submodule update --init cp CodeCannon/templates/codecannon.yaml .codecannon.yaml # Edit .codecannon.yaml — set branch names, commands, adapters -CodeCannon/sync.sh +CodeCannon/sync.py ``` Do not touch any file. The user runs these commands in their project directory. @@ -75,10 +75,10 @@ Do not touch any file. The user runs these commands in their project directory. Run checks 1–7 in order. Stop at the first failing check and address it. After describing the fix, tell the user to run `/setup` again once they've resolved it. Do not continue past a failing check. -### Check 1 — CodeCannon/sync.sh present +### Check 1 — CodeCannon/sync.py present ```bash -test -f CodeCannon/sync.sh +test -f CodeCannon/sync.py ``` If missing: the submodule was added to `.gitmodules` or `CodeCannon/` exists as an empty directory, but it hasn't been initialized. Show: @@ -189,18 +189,18 @@ If anything is flagged: show the specific key names and what they should likely ### Check 7 — Generated skill output present -Check whether sync.sh has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: +Check whether sync.py has been run by looking for any of the adapter output directories configured in `.codecannon.yaml`: ```bash test -d .claude/commands || test -d .cursor/rules || test -d .agents/skills || test -d .gemini/skills ``` -If none exist: "sync.sh hasn't been run yet — the skill commands don't exist." +If none exist: "sync.py hasn't been run yet — the skill commands don't exist." Show: ```bash -CodeCannon/sync.sh +CodeCannon/sync.py ``` Ask permission to run it. If the user agrees, run it. If they decline, tell them to run it manually before continuing. Stop. @@ -362,8 +362,8 @@ Add a note: `/start` can be used to create well-formed GitHub issues without wri ## Hard rules -- Only modify `.codecannon.yaml`. Do not touch any other file (except running `CodeCannon/sync.sh`, which modifies `.claude/commands/` — permitted only with explicit user approval). -- Do not run `sync.sh` without explicit user permission. +- Only modify `.codecannon.yaml`. 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. diff --git a/sync.sh b/sync.py similarity index 93% rename from sync.sh rename to sync.py index af6e906..7f35d11 100755 --- a/sync.sh +++ b/sync.py @@ -1,18 +1,18 @@ #!/usr/bin/env python3 """ -CodeCannon/sync.sh — generate agent-specific skill files from source skills + project config +CodeCannon/sync.py — generate agent-specific skill files from source skills + project config Usage: - ./CodeCannon/sync.sh # use .codecannon.yaml in current dir - ./CodeCannon/sync.sh --config path/to/config.yaml - ./CodeCannon/sync.sh --force # overwrite customized files without prompting - ./CodeCannon/sync.sh --dry-run # preview what would be written, exits 1 if any writes pending - ./CodeCannon/sync.sh --validate # check all placeholders are defined, exits 1 if any missing - ./CodeCannon/sync.sh --skill start # sync only the named skill(s), comma-separated - -Generated files carry a hash comment so sync.sh can detect manual edits. -If a generated file has been customized (hash mismatch), sync.sh warns and skips it. -Pass --force to overwrite, or delete the file to let sync.sh regenerate it cleanly. + ./CodeCannon/sync.py # use .codecannon.yaml in current dir + ./CodeCannon/sync.py --config path/to/config.yaml + ./CodeCannon/sync.py --force # overwrite customized files without prompting + ./CodeCannon/sync.py --dry-run # preview what would be written, exits 1 if any writes pending + ./CodeCannon/sync.py --validate # check all placeholders are defined, exits 1 if any missing + ./CodeCannon/sync.py --skill start # sync only the named skill(s), comma-separated + +Generated files carry a hash comment so sync.py can detect manual edits. +If a generated file has been customized (hash mismatch), sync.py warns and skips it. +Pass --force to overwrite, or delete the file to let sync.py regenerate it cleanly. """ import sys @@ -24,13 +24,16 @@ from pathlib import Path CODECANNON_DIR = Path(__file__).parent -MARKER = "generated by CodeCannon/sync.sh" -LEGACY_MARKER = "generated by agentgate/sync.sh" +MARKER = "generated by CodeCannon/sync.py" +LEGACY_MARKERS = [ + "generated by CodeCannon/sync.sh", + "generated by agentgate/sync.sh", +] def first_line_has_sync_marker(first_line): """True if the line was produced by this tool (current or legacy marker).""" - return MARKER in first_line or LEGACY_MARKER in first_line + return MARKER in first_line or any(m in first_line for m in LEGACY_MARKERS) # ── YAML parsing ────────────────────────────────────────────────────────────── @@ -192,7 +195,7 @@ def read_file_info(file_path): stored_hash — hash recorded in the marker line when the file was last written body_hash — hash of the file's actual content (excluding the marker line) is_generated — True if the file was written by this sync tool (current or legacy marker) - needs_migration — True if the marker is in legacy position (start) and should be moved to end + needs_migration — True if the marker needs rewriting (legacy position or legacy marker text) Comparing stored_hash vs body_hash tells us whether the file was edited after the last sync. Comparing body_hash vs the freshly-computed h tells @@ -232,7 +235,11 @@ def read_file_info(file_path): body = '\n'.join(lines[1:]) + '\n' body_hash = content_hash(body) - return stored_hash, body_hash, True, (marker_pos == 'start') + # Migration needed if marker is at the start (legacy position) or uses a legacy marker string + has_legacy_marker_text = MARKER not in marker_line and any(m in marker_line for m in LEGACY_MARKERS) + migrate = (marker_pos == 'start') or has_legacy_marker_text + + return stored_hash, body_hash, True, migrate # ── Adapter loading ─────────────────────────────────────────────────────────── @@ -306,7 +313,7 @@ def sync_skill(skill_path, adapter, project_config, project_root, args): # Compute hash (of content, before marker line) h = content_hash(full_content) - marker_line = f"" + marker_line = f"" final_content = full_content + marker_line + '\n' # Check existing file diff --git a/templates/AGENTS.md.template b/templates/AGENTS.md.template index 81e16e3..aa7855e 100644 --- a/templates/AGENTS.md.template +++ b/templates/AGENTS.md.template @@ -37,8 +37,8 @@ This project uses the **Lightweight / Standard / Governed** workflow profile. Se `.codecannon.yaml` and the generated `.claude/commands/` files are committed to this repo. Every developer gets a consistent workflow on `git clone` + `git submodule update --init` — no further setup required. -To update skills: `git submodule update --remote CodeCannon && CodeCannon/sync.sh` -To reconfigure: edit `.codecannon.yaml` and re-run `CodeCannon/sync.sh`, then commit the changes. +To update skills: `git submodule update --remote CodeCannon && CodeCannon/sync.py` +To reconfigure: edit `.codecannon.yaml` and re-run `CodeCannon/sync.py`, then commit the changes. ## Agent Workflow diff --git a/templates/codecannon.yaml b/templates/codecannon.yaml index a139182..4144dfd 100644 --- a/templates/codecannon.yaml +++ b/templates/codecannon.yaml @@ -1,7 +1,7 @@ # .codecannon.yaml — project configuration for Code Cannon skill sync # # Copy this file to your project root as .codecannon.yaml and customize. -# Run: CodeCannon/sync.sh +# Run: CodeCannon/sync.py # # See CodeCannon/config.schema.yaml for documentation on each placeholder. @@ -14,7 +14,7 @@ adapters: # - codex # Placeholder values substituted into skill files during sync. -# Remove any you don't need; sync.sh will warn about unresolved placeholders. +# Remove any you don't need; sync.py will warn about unresolved placeholders. config: # ── Workflow profile ───────────────────────────────────────────────────────── diff --git a/templates/github/workflows/sync-check.yml b/templates/github/workflows/sync-check.yml index 9e3a613..b98c8d7 100644 --- a/templates/github/workflows/sync-check.yml +++ b/templates/github/workflows/sync-check.yml @@ -7,5 +7,5 @@ jobs: - uses: actions/checkout@v4 - name: Check for sync drift run: | - CodeCannon/sync.sh --dry-run + CodeCannon/sync.py --dry-run # exits non-zero if any files would be written