diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cb14d7a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,15 @@ +name: ci +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo test --all-features + - run: cargo build --release --features cli diff --git a/Cargo.toml b/Cargo.toml index d674048..779a399 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,43 +1,40 @@ -[package] -name = "dirigent_fermata" -version = "0.1.0" -edition = "2021" -rust-version = "1.75" -description = "Harness-agnostic policy gate for AI coding agents (.botignore + botignore.toml)" -license = "MIT OR Apache-2.0" -repository = "https://git.g4b.org/dirigence/fermata" -readme = "README.md" -keywords = ["ai", "agents", "security", "policy", "gitignore"] -categories = ["command-line-utilities", "development-tools"] - -[lib] -path = "src/lib.rs" - -[[bin]] -name = "fermata" -path = "src/bin/fermata.rs" -required-features = ["cli"] - -[dependencies] -globset = "0.4" -ignore = "0.4" -walkdir = "2" -toml = "0.8" -regex = "1.10" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -thiserror = "2.0" -clap = { version = "4.5", features = ["derive"], optional = true } - -[dev-dependencies] -tempfile = "3.10" -assert_cmd = "2.0" -predicates = "3.1" - -[features] -default = ["cli", "harness-claude"] -cli = ["dep:clap"] -harness-claude = [] - -[lints] -workspace = true +[package] +name = "dirigent_fermata" +version = "0.1.0" +edition = "2021" +rust-version = "1.75" +description = "Harness-agnostic policy gate for AI coding agents (.botignore + botignore.toml)" +license = "MIT OR Apache-2.0" +repository = "https://git.g4b.org/dirigence/fermata" +readme = "README.md" +keywords = ["ai", "agents", "security", "policy", "gitignore"] +categories = ["command-line-utilities", "development-tools"] + +[lib] +path = "src/lib.rs" + +[[bin]] +name = "fermata" +path = "src/bin/fermata.rs" +required-features = ["cli"] + +[dependencies] +globset = "0.4" +ignore = "0.4" +walkdir = "2" +toml = "0.8" +regex = "1.10" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +thiserror = "2.0" +clap = { version = "4.5", features = ["derive"], optional = true } + +[dev-dependencies] +tempfile = "3.10" +assert_cmd = "2.0" +predicates = "3.1" + +[features] +default = ["cli", "harness-claude"] +cli = ["dep:clap"] +harness-claude = [] diff --git a/README.md b/README.md index 2a3d7c9..c1fd9e0 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,37 @@ -# dirigent_fermata +# fermata -`𝄐 fermata` — a fast, harness-agnostic guard that blocks AI coding agents from reading, writing, or executing things they shouldn't. +`𝄐` — a fast, harness-agnostic policy gate for AI coding agents. -Reads `.botignore` (gitignore syntax) and an optional `botignore.toml` for advanced rules. Designed to be called from agent hooks, used as an MCP server (future), or consumed as a library. - -## Status - -v0.1 — first releasable slice: -- Library: `Op`, `Decision`, `Policy::check`, `Policy::check_command`, project-root walk-up, `.botignore` walker (via `ignore`), `botignore.toml` parsing, path identification heuristics. -- CLI: `fermata check ...`, `fermata hook --harness `. -- Harness: Claude Code (PreToolUse) only. - -Out of scope for v0.1: Codex, Gemini, MCP server, audit log, filesystem watcher. +Reads `.botignore` files (gitignore syntax) and an optional `botignore.toml` +to decide whether an agent's read / write / bash operation should proceed. +Designed to be called from agent hooks (Claude Code first; Codex and Gemini +planned). ## Install -From a published release (after `cargo publish`): - ```bash cargo install dirigent_fermata ``` -From source (this monorepo): +## Usage ```bash -cargo install --path crates/dirigent_fermata --features cli +fermata check --op read ./.env # exit 1 if blocked +fermata hook --harness claude < req.json ``` -This installs the `fermata` binary into `~/.cargo/bin/`. +## About this repository -## Quick start +This is a downstream mirror. Fermata is developed inside the upstream +[Dirigent](https://git.g4b.org/dirigence/dirigent) monorepo and exported here +for distribution. Issues and pull requests are accepted on the `develop` +branch, but the canonical development branch is upstream. -```bash -# As a CLI -fermata check --op read /path/to/.env -echo $? # 1 if blocked, 0 if allowed +## License -# As a Claude Code hook -fermata hook --harness claude < hook_payload.json -``` +Licensed under either of -## Configuration +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE)) +- MIT License ([LICENSE-MIT](LICENSE-MIT)) -`.botignore` (gitignore syntax, applies to read + write): -``` -.env -.env.* -secrets/** -``` - -`botignore.toml` (per-op rules): -```toml -[read] -patterns = [".env*", "secrets/**"] - -[write] -patterns = ["vendor/**", "*.lock"] - -[bash] -deny = ["rm -rf /", "git push --force*"] -ask = ["rm:*", "mv:*"] -allow_prefixes = ["make test", "git checkout:*"] -``` - -## See also - -- `docs/tools/fermata.md` — Dirigent integration plan -- `docs/workpad/brainstorm/fermata.md` — full product spec +at your option.