brokecrew/docs/superpowers/plans/2026-09-26-brokecrew.md

16 KiB

BrokeCrew Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Build brokecrew, a high-performance, async-first Rust CLI and core library enabling users to interact with a resilient multi-persona AI team backed by OpenRouter models with two-stage routing, automatic candidate fallbacks, budget tracking, and typed multi-agent pipelines.

Architecture: A dual-target crate (src/lib.rs + src/main.rs). lib.rs encapsulates all domain types, OpenRouter client with SSE streaming, live registry caching, rate-limit budgeting, two-stage routing, and multi-agent pipelines with zero UI/terminal coupling. main.rs is a thin entrypoint providing clap argument parsing, indicatif spinners, owo-colors terminal output, and OS keyring integration.

Tech Stack: Rust 2021 edition, tokio (async runtime), reqwest (HTTP client with connection pooling & json), tokio-util / futures-util (SSE streaming), clap (CLI parser with derive), serde & toml & serde_json (serialization), keyring (OS credential store), indicatif (terminal progress/spinners), owo-colors (terminal colors), tracing & tracing-subscriber (structured logging), wiremock (integration testing).

Spec: docs/superpowers/specs/2026-09-26-brokecrew-design.md

Global Constraints

  • Must compile on stable Rust with zero warnings under cargo clippy --all-targets -- -D warnings.
  • No API keys ever printed in logs, debug representations, error messages, or terminal outputs.
  • main.rs must remain a thin entrypoint; no persona, registry, router, or budget logic may leak into main.rs.
  • Network calls must never .unwrap() or panic; all failures mapped cleanly into typed ClientError variants.
  • Dual-licensed under MIT OR Apache-2.0.

Review Focus

  1. Invalid API Key (HTTP 401): Must fail fast with ClientError::Unauthorized without uselessly cycling through remaining candidate models.
  2. Exhausted Credits (HTTP 402): Must abort immediately with ClientError::PaymentRequired without retrying free candidates.
  3. Stage B Router Hallucination: If the small LLM router outputs unparseable text or an unknown persona, system must smoothly fall back to default_persona (e.g. general).
  4. Candidate Rate Limiting (HTTP 429): Candidate cascade must catch rate limits, log the fallback event with model IDs, and invoke the next viable candidate seamlessly.
  5. Total Cascade Failure: If all candidates in a persona's fallback list fail or are unlisted, an aggregated error must report every attempt cleanly without panicking.

Task 1: Crate Scaffolding, Governance & Default Config

Files:

  • Create: Cargo.toml
  • Create: LICENSE-MIT
  • Create: LICENSE-APACHE
  • Create: CODEOWNERS
  • Create: CONTRIBUTING.md
  • Create: CHANGELOG.md
  • Create: README.md
  • Create: .github/workflows/ci.yml
  • Create: config/personas.example.toml
  • Create: src/lib.rs
  • Create: src/main.rs

Interfaces:

  • Produces: Compilable Rust package with brokecrew library and binary targets.

  • Step 1: Create Cargo.toml with dependencies

[package]
name = "brokecrew"
version = "0.1.0"
edition = "2021"
authors = ["oiupoyt <oiupoyt.cat@gmail.com>"]
description = "A Rust-native multi-model AI team CLI with resilient OpenRouter fallback routing"
license = "MIT OR Apache-2.0"
readme = "README.md"
repository = "https://github.com/brokecrew/brokecrew"
keywords = ["cli", "llm", "openrouter", "multi-agent", "ai"]
categories = ["command-line-utilities", "development-tools"]

[dependencies]
tokio = { version = "1.40", features = ["full"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "stream"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.8"
clap = { version = "4.5", features = ["derive", "env"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
thiserror = "1.0"
async-trait = "0.1"
futures-util = "0.3"
keyring = { version = "3.0", features = ["linux-native"] }
indicatif = "0.17"
owo-colors = "4.1"
regex = "1.10"
chrono = { version = "0.4", features = ["serde"] }
dirs = "5.0"
tempfile = "3.12"

[dev-dependencies]
wiremock = "0.6"
tokio-test = "0.4"
  • Step 2: Create initial src/lib.rs and src/main.rs

Create minimal placeholder library and binary to ensure baseline compilation.

  • Step 3: Create licenses, governance, CI workflow, and personas.example.toml

Add LICENSE-MIT, LICENSE-APACHE, CODEOWNERS, CONTRIBUTING.md, CHANGELOG.md, README.md, .github/workflows/ci.yml, and config/personas.example.toml matching the spec.

  • Step 4: Verify build and test compilation

Run: cargo check and cargo test Expected: PASS

  • Step 5: Commit
git add Cargo.toml src/ LICENSE* CODEOWNERS CONTRIBUTING.md CHANGELOG.md README.md .github/ config/
git commit -m "chore: scaffold project structure, licenses, CI and default config"

Task 2: Core Domain Models & Fallback Resolution (persona.rs)

Files:

  • Create: src/persona.rs
  • Modify: src/lib.rs

Interfaces:

  • Produces: Tier, ModelCandidate, Persona, DispatchResult, ModelAttempt, PersonaRegistry, and fallback candidate selection logic.

  • Step 1: Write failing unit test for candidate fallback selection

Test that candidate selection properly skips stealth models when allow_stealth is false, prioritizes paid tier when escalated, and returns candidates in declared priority order.

  • Step 2: Run test to verify failure

Run: cargo test --lib persona Expected: FAIL with missing types.

  • Step 3: Implement persona domain types and candidate selector

Implement Tier, ModelCandidate, Persona, DispatchResult, ModelAttempt, PersonaRegistry::get_eligible_candidates(&self, persona_name: &str, allow_stealth: bool, require_paid: bool).

  • Step 4: Run tests to verify pass

Run: cargo test --lib persona Expected: PASS

  • Step 5: Commit
git add src/persona.rs src/lib.rs
git commit -m "feat: implement persona domain models and candidate resolution"

Task 3: Free-Tier Budget Awareness & Rate Limiter (budget.rs)

Files:

  • Create: src/budget.rs
  • Modify: src/lib.rs

Interfaces:

  • Produces: BudgetTracker, BudgetStatus, CreditTier, rolling window check (20 req/min), daily quota check (50 or 1,000 req/day), atomic persistence to disk.

  • Step 1: Write failing tests for rolling window and daily rollover

Write tests covering:

  • Permitting requests up to 20 per minute; rejecting or returning delay on 21st.

  • Accurately reporting remaining daily budget.

  • Warning when exceeding 80% daily quota threshold.

  • Persisting state and reloading from JSON.

  • Step 2: Run test to verify failure

Run: cargo test --lib budget Expected: FAIL with module not found.

  • Step 3: Implement BudgetTracker with atomic persistence

Implement BudgetTracker using a sliding timestamp queue for the 60-second window, UTC date tracking for daily counts, and atomic writes via tempfile.

  • Step 4: Run tests to verify pass

Run: cargo test --lib budget Expected: PASS

  • Step 5: Commit
git add src/budget.rs src/lib.rs
git commit -m "feat: implement account-wide budget tracker and rate limiter"

Task 4: Model Client & SSE Streaming Engine (client.rs)

Files:

  • Create: src/client.rs
  • Modify: src/lib.rs

Interfaces:

  • Produces: ModelClient trait, ClientError, OpenRouterClient, complete(), complete_stream(), SSE event parser.

  • Consumes: tokio::sync::mpsc::Sender<String> for streaming deltas.

  • Step 1: Write failing tests for SSE chunk parsing and error status mapping

Unit test the SSE stream line parser to ensure data: {"choices":[{"delta":{"content":"foo"}}]} parses correctly, data: [DONE] signals completion, 401 maps to Unauthorized, 402 maps to PaymentRequired, and 429 extracts Retry-After.

  • Step 2: Run test to verify failure

Run: cargo test --lib client Expected: FAIL with missing module.

  • Step 3: Implement ModelClient and OpenRouterClient

Implement OpenRouterClient with custom headers (HTTP-Referer, X-Title, Authorization: Bearer <key>), request timeouts, SSE stream consumption, and robust ClientError mapping. Implement custom Debug to ensure API keys are never printed.

  • Step 4: Run tests to verify pass

Run: cargo test --lib client Expected: PASS

  • Step 5: Commit
git add src/client.rs src/lib.rs
git commit -m "feat: implement OpenRouter HTTP client with SSE streaming"

Task 5: Live Model Registry & Cache (registry.rs)

Files:

  • Create: src/registry.rs
  • Modify: src/lib.rs

Interfaces:

  • Produces: ModelInfo, ModelPricing, ModelRegistry, fetch_models(), is_model_available(), start_background_sync().

  • Step 1: Write failing test for ModelRegistry catalog parsing & filtering

Test deserializing OpenRouter /v1/models JSON response, caching models in memory, and verifying model availability.

  • Step 2: Run test to verify failure

Run: cargo test --lib registry Expected: FAIL with missing module.

  • Step 3: Implement ModelRegistry

Implement ModelRegistry holding Arc<RwLock<HashMap<String, ModelInfo>>>, background sync with configurable duration, and helper to filter candidate lists based on live availability.

  • Step 4: Run tests to verify pass

Run: cargo test --lib registry Expected: PASS

  • Step 5: Commit
git add src/registry.rs src/lib.rs
git commit -m "feat: implement live model registry cache and background sync"

Task 6: Two-Stage Router & Complexity Escalation (router/)

Files:

  • Create: src/router/mod.rs
  • Create: src/router/keyword.rs
  • Create: src/router/llm.rs
  • Modify: src/lib.rs

Interfaces:

  • Produces: Router, RouteDecision, Stage A KeywordRouter::classify, Stage B LlmRouter::classify, Stage C estimate_complexity().

  • Step 1: Write failing table-driven unit tests for Stage A keyword routing

Test matching keywords against personas ("build me a website" -> coder, "audit this code" -> reviewer, "hello how are you" -> None).

  • Step 2: Write failing unit tests for Stage B LLM fallback & Stage C escalation

Test router output sanitization (valid persona accepted, unparseable output falls back to default_persona), and complexity score calculation triggering paid tier flag.

  • Step 3: Run tests to verify failure

Run: cargo test --lib router Expected: FAIL.

  • Step 4: Implement KeywordRouter, LlmRouter, and combined Router

Implement word-boundary regex matching in keyword.rs, single-token LLM dispatch with fallback in llm.rs, and complexity evaluation.

  • Step 5: Run tests to verify pass

Run: cargo test --lib router Expected: PASS

  • Step 6: Commit
git add src/router/ src/lib.rs
git commit -m "feat: implement two-stage router with keyword filter and complexity escalation"

Task 7: Multi-Agent Handoff Pipeline (pipeline.rs)

Files:

  • Create: src/pipeline.rs
  • Modify: src/lib.rs

Interfaces:

  • Produces: PipelineStep, PipelineConfig, PipelineExecutor, PipelineEvent (StepStart, Chunk, StepDone), execute_pipeline().

  • Step 1: Write failing test for sequential pipeline execution

Test pipeline passing step 1 output into step 2 context when pass_previous_output = true, emitting proper lifecycle events.

  • Step 2: Run test to verify failure

Run: cargo test --lib pipeline Expected: FAIL.

  • Step 3: Implement PipelineExecutor

Implement sequential execution of pipeline steps using candidate fallback per step, streaming deltas via event channel.

  • Step 4: Run tests to verify pass

Run: cargo test --lib pipeline Expected: PASS

  • Step 5: Commit
git add src/pipeline.rs src/lib.rs
git commit -m "feat: implement multi-agent handoff pipeline engine"

Task 8: Configuration Loader & Keyring Credential Storage (config.rs)

Files:

  • Create: src/config.rs
  • Modify: src/lib.rs

Interfaces:

  • Produces: AppConfig, load_config(), get_api_key(), save_api_key_to_keyring().

  • Resolves key priority: CLI argument -> OPENROUTER_API_KEY env -> OS Keyring -> config.toml.

  • Step 1: Write unit tests for configuration loading and key resolution priority

Test fallback hierarchy from CLI argument to environment variable to config file.

  • Step 2: Run test to verify failure

Run: cargo test --lib config Expected: FAIL.

  • Step 3: Implement config loading and keyring storage

Support default configuration directory (~/.config/brokecrew/), loading personas.toml, loading config.toml, storing and retrieving key via keyring crate with safe fallback when headless/keyring unavailable.

  • Step 4: Run tests to verify pass

Run: cargo test --lib config Expected: PASS

  • Step 5: Commit
git add src/config.rs src/lib.rs
git commit -m "feat: implement config loading and OS keyring credential storage"

Task 9: CLI UX, Terminal Presentation & Subcommands (cli.rs, main.rs)

Files:

  • Create: src/cli.rs
  • Modify: src/main.rs

Interfaces:

  • Subcommands:

    • brokecrew chat [PROMPT] [--persona <NAME>] [--pipeline <NAME>] [--allow-stealth] [--escalate]
    • brokecrew config set-key
    • brokecrew personas list
    • brokecrew status
  • Features: indicatif spinner during TTFT, owo-colors distinct persona styling, real-time SSE chunk streaming, --json-logs structured logging toggle.

  • Step 1: Implement clap CLI hierarchy in src/cli.rs

Define Cli, Commands, flags (--json-logs, --allow-stealth, --escalate, --config-file, --api-key).

  • Step 2: Implement subcommand handlers in src/main.rs

Connect CLI args to library calls:

  • chat: Route prompt, display persona badge with unique color, stream response, display fallback notices if any candidate failed.

  • config set-key: Prompt securely for key and save to keyring.

  • personas list: Pretty-print personas, candidates, triggers, and pipelines.

  • status: Show live registry statistics and daily/minute budget usage.

  • Step 3: Verify CLI commands with cargo run

Run: cargo run -- --help, cargo run -- personas list, cargo run -- status Expected: Formatted terminal output.

  • Step 4: Commit
git add src/cli.rs src/main.rs
git commit -m "feat: implement clap CLI subcommands and terminal UX"

Task 10: Integration Tests, Fallback Simulation & WireMock (tests/)

Files:

  • Create: tests/router_tests.rs
  • Create: tests/fallback_tests.rs
  • Create: tests/wiremock_client.rs

Interfaces:

  • Verifies:

    • Full candidate fallback cascade on 429/503 errors.
    • WireMock SSE stream ingestion and status code handling.
    • Table-driven router classification.
    • Budget tracker integration.
  • Step 1: Implement router_tests.rs

Add comprehensive table-driven tests for prompt routing and edge cases.

  • Step 2: Implement fallback_tests.rs

Implement mock ModelClient simulating failures on top candidates to verify seamless candidate fallback and audit logs.

  • Step 3: Implement wiremock_client.rs

Implement WireMock HTTP tests verifying SSE streaming, 401 fast failure, 402 payment required handling, and /v1/models catalog parsing.

  • Step 4: Run the complete test suite and clippy

Run: cargo test and cargo clippy --all-targets -- -D warnings Expected: 100% tests PASS and zero clippy warnings.

  • Step 5: Commit
git add tests/
git commit -m "test: add comprehensive integration tests and WireMock test harness"

Task 11: Final Polish, Verification & Documentation

Files:

  • Modify: README.md

  • Verify: Acceptance criteria checklist

  • Step 1: Complete README.md

Include quickstart guide, install command, architecture diagram, persona configuration tutorial, and "Why BrokeCrew vs LiteLLM/RouteLLM" comparison.

  • Step 2: End-to-end verification

Run cargo check, cargo clippy --all-targets -- -D warnings, cargo test, and run CLI subcommands locally.

  • Step 3: Commit
git add README.md
git commit -m "docs: complete comprehensive README and user documentation"