# GitHub Copilot Coding Agent Instructions for brush

## Project Overview

**brush** (Bourne Rusty Shell) is a POSIX- and bash-compatible shell implemented in Rust. It's a multi-crate workspace (~60K lines of Rust code) targeting Linux, macOS, and WSL, with experimental Windows and WASM support. The project emphasizes compatibility testing against bash as an oracle.

**Key Stats:** Rust 2024 edition, MSRV 1.88.0, 5 main crates, 1500+ compatibility test cases, published to crates.io.

## Critical: Read AGENTS.md First

**BEFORE making any changes, read `/AGENTS.md`.** It contains detailed architecture patterns, testing workflows, and development guidelines specific to this project. The information below supplements (not replaces) AGENTS.md.

## Code Review Checklist

When reviewing PRs, verify:

- [ ] **Documentation**: All exported APIs have rustdoc comments (missing docs = CI failure)
- [ ] **Forbidden patterns**: No `panic`, `unwrap_in_result`, `expect_used`, or `todo` (all denied by clippy)
- [ ] **Error handling**: Uses `thiserror` for crate errors; `anyhow` only in tests
- [ ] **Logging**: Uses `tracing::debug!(target: trace_categories::CATEGORY, "msg")` pattern
- [ ] **Testing**: Compatibility fixes include YAML test cases in `brush-shell/tests/cases/`
- [ ] **Testing**: Builtin changes have tests in `brush-shell/tests/cases/builtin/`
- [ ] **Testing**: Unit tests expected for new public APIs (when feasible) (see AGENTS.md section 2)
- [ ] **Platform code**: Platform-specific code is in `brush-core/src/sys/` modules
- [ ] **Breaking changes**: Public API changes are clearly highlighted and documented
- [ ] **Builder pattern**: Configuration uses builder pattern (see `Shell::builder()`)
- [ ] **Code quality**: Passes `cargo fmt --check` and `cargo clippy` without warnings
- [ ] **Commit format**: Follows [Conventional Commits](https://www.conventionalcommits.org/) (feat:, fix:, docs:, test:)
- [ ] **Dependencies**: No unnecessary cloning (use references when possible)
- [ ] **Cross-platform**: Uses appropriate `cfg(unix)`, `cfg(windows)`, `cfg(target_family = "wasm")`

## Workspace Structure

```
brush/
├── brush-shell/        # CLI application & main entry point
├── brush-interactive/  # Interactive shell (readline, completion)
├── brush-core/         # Core shell runtime & builtins
├── brush-builtins/     # Shell builtin implementations
├── brush-parser/       # AST generation & parsing
├── xtask/             # Build automation tasks
└── docs/              # Diátaxis-structured documentation
```

**Dependency flow:** brush-shell → brush-interactive → brush-core → brush-parser
                                  ↘ brush-builtins ↗

## Build & Validation Commands

### Terminal Command Execution

When running commands that may take more than a few seconds (cargo build, cargo check, cargo test, cargo clippy, cargo xtask, etc.), **run them in background mode and poll for results** rather than blocking. This prevents commands from being cancelled due to timeouts. Use `isBackground: true` with `run_in_terminal`, then use `get_terminal_output` to check results.

### Using xtask (Recommended)

The project provides a `cargo xtask` command that centralizes common development tasks. This is the recommended approach for running checks and tests.

#### Quick Development Cycle

```bash
# Run quick inner-loop checks (~7s warm): fmt, build, lint, unit tests
cargo xtask ci quick

# Run full pre-commit checks (~45s warm): quick + deps, schemas, integration tests
cargo xtask ci pre-commit

# Run with --continue-on-error to see all failures at once
cargo xtask ci pre-commit -k

# Add -v for verbose output showing exact commands being run
cargo xtask -v ci pre-commit
```

#### Individual Checks

```bash
# Format check
cargo xtask check fmt

# Lint check (clippy)
cargo xtask check lint

# Dependency check (cargo-deny)
cargo xtask check deps

# Build check
cargo xtask check build

# Schema check (regenerates and diffs)
cargo xtask check schemas
```

#### Running Tests

```bash
# Run unit tests (fast tests excluding integration binaries)
cargo xtask test unit

# Run integration tests (all workspace tests including compat tests)
cargo xtask test integration

# Run tests with coverage
cargo xtask test integration --coverage --coverage-output codecov.xml
```

### Manual Approach (Alternate)

For finer-grained control or when xtask isn't available:

#### Quick Development Cycle (Use These Frequently)

```bash
# Fast syntax/type checking (< 5 seconds)
cargo check --workspace

# Package-specific checking (even faster)
cargo check --package brush-core

# Format code (ALWAYS run before committing)
cargo fmt --all

# Lint code (ALWAYS run before committing)
cargo clippy --workspace --all-features --all-targets

# Run package-specific tests (fast iteration)
cargo test --package brush-parser
cargo test --package brush-core
```

**Note:** `cargo fmt --check` may show warnings about unstable rustfmt features (`wrap_comments`, `comment_width`) on stable Rust. These are harmless and expected.

### Comprehensive Testing Workflow

Follow this **exact order** for efficient testing:

1. **Inner loop** (during development):
   ```bash
   cargo check --package <changed-package>
   cargo test --package <changed-package>
   ```

2. **Compatibility tests** (critical for shell behavior):
   ```bash
   cargo test --test brush-compat-tests
   
   # Run specific test case:
   cargo test --test brush-compat-tests -- 'builtin/echo'
   ```

3. **Full workspace tests** (before considering work complete):
   ```bash
   cargo test --workspace
   ```

**Test timing:** Package tests: 3-20 seconds. Compat tests: ~18 seconds build + test time. Full workspace: several minutes.

### Pre-Commit Validation (Before Every Commit)

**Recommended:** Run the xtask pre-commit workflow:

```bash
cargo xtask ci pre-commit
```

**Manual approach:** Run these before every commit:

```bash
cargo fmt --check --all
cargo clippy --workspace --all-features --all-targets
```

### Pre-PR Validation (Before Opening Pull Request)

**Recommended:** Run pre-commit checks which includes full test suite:

```bash
cargo xtask ci pre-commit
```

**Manual approach:** In addition to pre-commit checks, also run:

```bash
cargo test --workspace
```

### Pre-Finish Quality Gates (Run Before Completing Task)

**Recommended:** Run the xtask pre-commit workflow which covers all essential checks:

```bash
cargo xtask ci pre-commit
```

**Manual approach:**

```bash
cargo test --test brush-compat-tests
cargo deny check all       # License/security audit (run LAST, not frequently)
cargo clippy --workspace --all-features --all-targets
cargo fmt --check --all
cargo test --workspace
```

**Timing note:** `cargo deny check all` takes ~1-5 seconds. Only run as final validation step.

### Build Variants

```bash
# Standard debug build
cargo build

# Release build (takes ~2+ minutes, avoid during iteration)
cargo build --release

# Check all targets and features
cargo check --all-features --all-targets
```

## Testing Philosophy

**Test-driven approach:** When fixing bugs or adding features, write test cases in `brush-shell/tests/cases/*.yaml` BEFORE implementation. Use these to validate your changes.

**Integration test structure:** Tests are YAML-based, run shell commands, compare stdout/stderr/exit codes against bash oracle. See `docs/reference/integration-testing.md` and AGENTS.md section 2 for detailed testing strategy.

**Test categories:**
- Unit tests: In-file with `#[cfg(test)]`
- Integration tests: `brush-shell/tests/` directory
- Compatibility tests: YAML cases in `brush-shell/tests/cases/`
- Benchmarks: `brush-shell/benches/` and crate-level `benches/`

## Common Pitfalls & Solutions

### ❌ Don't Do This
- Run full test suite on every change (too slow)
- Skip `cargo fmt` and `cargo clippy` before committing
- Use `cargo deny check` during development iteration
- Clone values unnecessarily (use references)
- Add breaking changes to public APIs without highlighting them
- Forget to add compat test cases for compatibility fixes

### ✅ Do This
- Target specific packages/tests during development
- Run fmt/clippy before every commit
- Follow builder pattern for configuration (see `Shell::builder()`)
- Keep platform-specific code in `brush-core/src/sys/`
- Document all exported APIs with rustdoc
- Use `tracing::debug!(target: trace_categories::CATEGORY, "msg")` for logging
- Add test cases to `brush-shell/tests/cases/` for compatibility changes

## Error Handling & Logging

```rust
// Use thiserror for crate-specific errors
use thiserror::Error;

#[derive(Error, Debug)]
pub enum MyError { ... }

// Use anyhow ONLY in tests
#[cfg(test)]
use anyhow::Result;

// Logging with trace categories
use crate::trace_categories;
tracing::debug!(target: trace_categories::COMMANDS, "executing: {}", cmd);
```

**Available trace categories:** COMMANDS, COMPLETION, EXPANSION, FUNCTIONS, INPUT, JOBS, PARSE, PATTERN, UNIMPLEMENTED

## Linting Configuration

The project uses **extremely strict** linting (workspace-level in `Cargo.toml`):
- All Rust warnings denied
- All clippy warnings denied (pedantic, cargo, nursery, perf)
- `expect_used`, `panic`, `todo`, `unwrap_in_result` are **forbidden**
- Missing docs on exported items are errors

**Your code MUST pass `cargo clippy` without warnings.**

## Cross-Platform Considerations

- Primary targets: Linux (x86_64, aarch64), macOS (aarch64)
- Secondary: Windows (x86_64), WASM (wasm32-unknown-unknown, wasm32-wasip2)
- Platform-specific code goes in `brush-core/src/sys/` modules
- Use `cfg(unix)`, `cfg(windows)`, `cfg(target_family = "wasm")` appropriately
- See `.cargo/config.toml` for target-specific configurations

## CI Pipeline (What Will Run on Your PR)

GitHub Actions runs these checks (from `.github/workflows/ci.yaml`):

1. **Build** on multiple platforms (x86_64/aarch64 Linux, macOS, Windows, WASM)
2. **Tests** on Linux x86_64, Linux aarch64, macOS
3. **Static checks** (format, clippy, cargo-deny) on stable + MSRV (1.88.0)
4. **Compatibility tests** with bash as oracle
5. **Code coverage** reports (70% overall threshold, no 5% negative delta)
6. **External test suites** (bash-completion test suite)
7. **OS compatibility** (Arch, Debian, Fedora, NixOS, openSUSE)
8. **Benchmarks** (performance regression detection on PRs)
9. **Public API analysis** (breaking change detection)

**All of these must pass for PR to merge.**

## Making Changes

### Editing Core Shell Behavior
1. Check `brush-core/src/shell.rs` for `Shell` struct
2. Use `Shell::builder()` for construction
3. Update `brush-shell/src/main.rs` if CLI changes needed

### Adding/Modifying Builtins
1. Edit files in `brush-builtins/src/`
2. Register in `brush-builtins/src/factory.rs`
3. Add test cases in `brush-shell/tests/cases/builtin/`

### Parser Changes
1. Modify `brush-parser/src/`
2. Update AST definitions
3. Test with `cargo test --package brush-parser`

### Breaking Changes Policy
- Avoid breaking public APIs (all crate exports are public)
- If unavoidable, highlight clearly and document thoroughly
- New optional fields on public structs are OK if struct implements `Default`
- See AGENTS.md section 3 for complete breaking change policy

## Performance & Benchmarking

```bash
# Run benchmarks (using xtask)
cargo xtask analyze bench

# Run benchmarks with output file
cargo xtask analyze bench --output benchmarks.txt

# Run benchmarks (manual)
cargo bench --workspace --benches

# Collect flamegraphs (10 second profiling)
cargo bench --workspace --benches -- --profile-time 10
# Output: target/criterion/<benchmark_name>/profile/*.svg
```

**Note:** Performance regression testing runs automatically on PRs. Don't worry about it unless working on performance-specific features.

## Documentation Standards

**Rustdoc:** REQUIRED for all exported types, functions, traits, modules. Missing docs = CI failure.
**Examples:** Only needed for major feature additions.
**Style:** Follow Rust documentation best practices.

## Commit Messages

Use [Conventional Commits](https://www.conventionalcommits.org/):
```
feat: add support for X
fix: correct behavior of Y
docs: update Z documentation
test: add test cases for W
```

## AI-Assisted Contributions

If using AI assistance significantly, add to PR description or commit message:
```
Assisted-by: GitHub Copilot
```

## When Something Fails

1. **Test failures:** Focus on affected area first, check if new tests are needed
2. **Format/clippy failures:** Fix immediately before proceeding
3. **Compat test failures:** Indicates shell behavior change, may need test updates
4. **Build failures:** Check dependencies, verify Rust version (1.88.0+)
5. **Timeout issues:** Build from scratch can take 2+ minutes

## Quick Reference

| Command | When | Time |
|---------|------|------|
| `cargo xtask ci quick` | Rapid iteration (inner loop) | ~7s |
| `cargo xtask ci pre-commit` | Before commit (comprehensive) | ~45s |
| `cargo xtask ci pre-commit -k` | See all failures at once | ~45s |
| `cargo check` | Constantly during dev | ~3-5s |
| `cargo test --package X` | After each change | 3-20s |
| `cargo xtask test unit` | Fast unit tests | ~4.5s |
| `cargo xtask test integration` | All workspace tests | ~36s |
| `cargo xtask check fmt` | Before every commit | <1s |
| `cargo xtask check lint` | Before commit | ~5-10s |
| `cargo xtask check deps` | Final validation only | ~1-5s |

## Trust These Instructions

Only search the codebase if information here or in AGENTS.md is incomplete, contradictory, or proven incorrect. These instructions are validated against the actual working repository.
