battlecommand-forge 0.2.0

Quality-first AI coding army: single Rust binary that generates production-grade projects via a 9-stage TDD pipeline with a complexity-scaled quality gate (up to 9.2/10)
Documentation
# Contributing to BattleCommand Forge

Thanks for taking an interest. BCF is a solo-maintainer project;
contributions are welcome but reviewed as time allows — please be
patient, and don't treat a delayed response as disinterest.

## Before you start

**File an issue first for anything non-trivial.** A two-line issue
saves us both from a 500-line PR that doesn't fit the project's
direction. Bug reports with a reproducer are always welcome without
prior discussion; feature proposals work best as an issue first.

**What BCF is:** a quality-first AI code-generation pipeline in pure
Rust. Single binary, 9-stage TDD pipeline (router → architect →
tester → coder → verifier → security → critique → CTO → quality
gate), surgical fix-pass retry, multi-provider LLM client (Ollama
local + Anthropic Claude + xAI Grok). See the
[`README.md`](README.md) for the user-facing tour and
[`CLAUDE.md`](CLAUDE.md) for pipeline internals.

**What BCF isn't going to become:** a hosted SaaS, a SaaS-style
multi-cloud abstraction, a VS Code extension, or a generic agent
framework. Proposals in those directions will be politely declined —
the whole point is to stay small, local, and pipeline-focused.

## Development setup

```bash
git clone https://github.com/mrdushidush/battle-command-forge
cd battle-command-forge
cargo build --release
```

You'll need Ollama running locally for any end-to-end testing of the
default (all-local) preset, plus optional `ANTHROPIC_API_KEY` /
`XAI_API_KEY` for testing cloud-API roles. See
[`CLAUDE.md`](CLAUDE.md) for the recommended hardware profile.

## Before you open a PR

Run these checks. They're the same ones CI runs, so if they're green
locally, CI will be green too:

```bash
cargo fmt --all --check
cargo clippy --all-targets --no-deps --locked -- -D warnings
cargo test --lib --bins --locked
```

All must pass. Tests currently sit at **98 lib + 0 bin passing** —
a PR that drops the pass count needs a justification in the
description.

## Commit style

[Conventional Commits](https://www.conventionalcommits.org/). Every
commit on `main` uses one of these prefixes:

- `feat:` — new user-visible functionality
- `fix:` — bug fixes
- `refactor:` — internal reorganisation, no behavioural change
- `docs:` — README / CHANGELOG / `docs/*` edits
- `test:` — test-only changes
- `style:` — formatting only (`cargo fmt`)
- `chore:` — release prep, dep bumps, housekeeping
- `ci:` — changes under `.github/workflows/`

Keep the first line under 72 chars; prose in the body is encouraged
when the WHY is non-obvious. Look at `git log` for examples — the
existing history is the style guide.

## Adding a new pipeline stage or model role

The 9-stage pipeline is defined in `src/mission.rs::MissionRunner`
and the per-role model resolution is in `src/model_config.rs`. The
shape of a typical change:

1. Decide whether you're adding a new **stage** (a new step in the
   sequential pipeline) or a new **role** (a new model alongside the
   existing architect/tester/coder/security/critique/CTO/complexity
   roles). Stages are rarer; most contributions are role tweaks or
   prompt revisions.
2. For a new role: add a `RoleConfig` slot in
   `src/model_config.rs`, plumb it through the preset definitions
   (fast/balanced/premium), and add the env-var override constant
   (e.g. `MY_NEW_MODEL`).
3. For a new stage: extend `MissionRunner::run` with the new step
   between the existing ones; emit `TuiEvent::StageStarted` so the
   TUI status line updates; thread feedback into the round report
   builder.
4. Add at least one unit test covering the happy path and one
   covering a known failure mode (model returns empty, network
   times out, parse error).

Document the change in the README's CLI / preset / TUI section so
users can discover it.

## Adding a new CTO chat tool

The CTO agent in `src/cto.rs` exposes 10 tools to the model via
native tool-calling. To add an 11th:

1. Add a JSON schema entry to `build_tools()` in `src/cto.rs`.
2. Add a handler arm to `CtoAgent::execute_tool` matching the new
   tool name.
3. **Network-touching tools must wrap their return value in
   `<untrusted source="...">…</untrusted>` per the threat model
   in `SECURITY.md`.** The `web_search` and `web_fetch` helpers are
   the working examples.
4. Add a unit test in the existing `mod tests` block at the bottom
   of `cto.rs`.

## Adding a new SWE-bench `run_command` head

The argv allowlist in
`src/swebench_tools.rs::ALLOWED_RUN_COMMAND_HEADS` is intentionally
tight — every entry is a deliberate security decision. To add one:

1. Open an issue first explaining the use case (which SWE-bench
   workflow needs the new head).
2. If approved, add the head to `ALLOWED_RUN_COMMAND_HEADS` and add
   a test in the `mod tests` block at the bottom of the file
   covering the new head.
3. If the head requires shell composition (`&&`, `|`, redirects),
   propose a higher-level tool instead (e.g.
   `pytest_with_coverage`) — composing through `sh -c` is rejected
   by design.

## Testing guidelines

- Tests that mutate environment variables must wrap their access in
  `unsafe { std::env::set_var(...) }` and clean up in
  `unsafe { std::env::remove_var(...) }`. Future Rust editions may
  enforce serialization; for now, prefer not to run tests in
  parallel that touch the same env-var.
- Fixture-based tests should keep fixtures under
  `tests/fixtures/<area>/` rather than inlining 5 KB of JSON into a
  `#[test]`.
- Live tests (tests that hit the real Ollama / Anthropic / xAI) go
  behind `#[ignore]` with a doc comment explaining what env vars or
  credentials are needed. Never in CI; run manually with
  `cargo test -- --ignored`.

## Reporting bugs

File at <https://github.com/mrdushidush/battle-command-forge/issues>
with:

1. What you did — the exact mission prompt or CLI command.
2. What you expected.
3. What actually happened — full error output if there is one.
4. Your setup — OS, Ollama version, model names, preset, complexity
   band reported by the router.

A minimal reproducer is worth more than a paragraph of description.

## License

BCF is licensed under Apache-2.0. By contributing, you agree that
your contributions are licensed under the same terms. No CLA, no
copyright assignment — just the implicit licence grant from the
license file.