feat(cadre): ship Bonfire cadre as Claude Code subagent definitions#155
Draft
Antawari wants to merge 2 commits into
Draft
feat(cadre): ship Bonfire cadre as Claude Code subagent definitions#155Antawari wants to merge 2 commits into
Antawari wants to merge 2 commits into
Conversation
Two install rails ship from this repo:
1. Claude Code plugin (canonical, colon-namespaced). Adds a
`.claude-plugin/plugin.json` manifest and pre-rendered
`agents/<role>.md` files. After install, dispatches surface as
`bonfire:<role>` (sister-shape to vercel:*, agent-sdk-dev:*, etc.)
instead of the generic `general-purpose` label.
2. Raw-files CLI fallback (flat-named). `bonfire install-agents`,
`bonfire uninstall-agents`, `bonfire list-agents` Typer subcommands
drop `bonfire-<role>.md` files at user or project scope, recorded
via a manifest at `.installed.json` for paired-clean uninstall. Pip
post-install hooks are deliberately rejected (wheel installs don't
run install-time code; pip uninstall can't clean files outside
site-packages).
v1 publishes six cadre roles plus a standalone catch-all:
- bonfire:scout-innovative + bonfire:scout-conservative
(dual-workflow split preserved at the subagent layer)
- bonfire:knight (writes RED tests, no Bash)
- bonfire:warrior (runs the RED->GREEN cycle, has Bash)
- bonfire:sage (synthesizes across two Scouts)
- bonfire:wizard (composes workflows; read-only)
- bonfire-powered (flat-named catch-all, CLI-rail-only,
head-to-head with general-purpose in the picker)
New modules:
- src/bonfire/prompts/<role>.md - canonical prompt bodies
- src/bonfire/agent/role_metadata.py - per-role metadata
(description, tools, model)
- src/bonfire/cadre/__init__.py - CADRE_CONTRACT_VERSION constant
+ resolve_role_prompt(role) adapter (skeleton; dispatch-side
refusal-on-mismatch deferred to a follow-up to keep this PR
single-concern)
- src/bonfire/cli/commands/build_agents.py - generator that emits
agents/<role>.md from prompts + metadata; CI gates with --check
- src/bonfire/cli/commands/install_agents.py - install / uninstall /
list subcommands
Versioning uses three orthogonal pins: bonfire_ai.__version__ (library
releases), plugin.json `version` (prompt-text changes), and
CADRE_CONTRACT_VERSION (dispatch-boundary breaking changes; stamped
into each subagent's `cadre_contract` frontmatter for drift detection).
Warrior Bash discipline: ships .claude/settings.local.json.example
with allow-list entries for the canonical Warrior-pattern Bash commands
(pytest, ruff, git add/commit, etc.) since background-dispatched
subagents auto-deny Bash outside cached permission rules.
Tests: 54 new (test_cadre.py + test_build_agents.py +
test_install_agents.py). Full unit suite green (3860 passed).
Knight extraction note: the knight prompt body was authored fresh in
this repo (no migration of any prior template); the source-of-truth
for the cadre body lives in src/bonfire/prompts/ from this PR forward.
…uble-prefix Two related corrections in `bonfire install-agents`: 1. CLI-installed cadre files now write `name: bonfire-<role>` in the frontmatter (not the bare `name: <role>`). The plugin path produces `bonfire:<role>` by prepending the plugin name; the raw-files path has no plugin to prepend, so the brand prefix must live in the file for the subagent type to surface as `bonfire-<role>`. 2. The catch-all role is already named `bonfire-powered`; the install helper no longer prepends the prefix a second time. Previous output produced `bonfire-bonfire-powered.md` with `name: bonfire-bonfire- powered`; now produces `bonfire-powered.md` with `name: bonfire-powered`. New helper `_flat_name(role_name)` centralises the prefix policy (prefix if absent, leave alone if present). New `_compose_flat(role)` builds the CLI-shape frontmatter using `_flat_name` so the install output's `name:` field matches the filename. Plugin-shipped agents (built via `bonfire build-agents`) are unchanged — they continue to use the bare `name:` so the plugin loader can prepend the colon namespace cleanly. Two new tests pin the contract: `test_install_writes_flat_prefixed _names_for_cadre` confirms the cadre files carry `name: bonfire-<role>`; `test_install_does_not_double_prefix_catchall` confirms the catch-all lands as `bonfire-powered.md` (not the double-prefixed form).
6618d4c to
d577669
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
When the Bonfire cadre dispatches via Claude Code's Agent tool today, every dispatch surfaces as
subagent_type: "general-purpose". The substance is Bonfire — the cadre methodology, the role discipline, the TDD law — but the label is generic. The framework is invisible at the most visible API boundary, and there's no discovery surface for users who installbonfire-aiand use Claude Code.This PR fixes that. After install, dispatches surface as
bonfire:scout-innovative,bonfire:knight,bonfire:warrior, etc. — the cadre at the API surface, sister-shape tovercel:*,agent-sdk-dev:*, and the other published Claude Code plugins.What ships
Two install rails, one ship-train, same
bonfire-publicrepo:Plugin (canonical · colon-namespaced)
```bash
/plugin install bonfire@
```
Adds:
After install, the Claude Code subagent picker shows `bonfire:` entries and dispatches surface with that literal label.
Raw-files CLI (fallback · flat-named)
```bash
user scope (~/.claude/agents/bonfire/) is the default
bonfire install-agents
project scope
bonfire install-agents --scope project
inspect
bonfire list-agents
clean removal (manifest-driven)
bonfire uninstall-agents
```
The CLI rail exists for three structural reasons:
The CLI rail also installs the `bonfire-powered` catch-all — a Bonfire-flavored general-purpose agent that sits flat-named in the picker next to `general-purpose` for users who want the cadre's discipline without picking a specific role. The catch-all does NOT ship via the plugin (head-to-head brand contrast requires flat naming).
New modules
Versioning
Three orthogonal pins:
Inaugural ship: plugin `0.1.0` + `CADRE_CONTRACT_VERSION = "0.1.0"`.
Per-role tool scoping
Warrior Bash discipline
Background-dispatched subagents auto-deny Bash calls outside cached permission rules — listing `Bash` in `tools:` is necessary but not sufficient. This PR ships `.claude/settings.local.json.example` with allow-list entries for the canonical Warrior-pattern Bash commands (`pytest`, `ruff`, `mypy`, `git add/commit/status/diff/log`). Documented as opt-in recommendation; never silently auto-installed.
Out of scope (intentional · follow-up tickets)
To keep this PR single-concern:
Verification
```bash
.venv/bin/bonfire build-agents --check # OK: generated files match canonical sources
.venv/bin/pytest tests/unit/ -q # 3860 passed (54 new tests added by this PR)
.venv/bin/ruff check src/ tests/ # All checks passed!
.venv/bin/ruff format --check src/ tests/ # 8 files already formatted
claude plugin validate ./.claude-plugin # passes (one pre-existing warning about repo-root CLAUDE.md placement, unrelated to this PR)
```
The `claude plugin validate --strict` warning is about the repo-root `CLAUDE.md` being a contributor-facing doc (not a plugin skill); fixing it is a documentation-restructuring follow-up, not blocking.
Test plan
Status
DRAFT. Opening for review and to make the surface visible; not for merge until reviewer sign-off and the marketplace submission decision lands separately.