Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions .hermes/agent-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Agent Context

Agent-customization instructions for diffguard. Root files (`AGENTS.md`, `CLAUDE.md`, `GEMINI.md`) point here.

## Project

**diffguard** is a diff-scoped governance linter for PR automation. It applies rules only to added/changed lines in Git diffs, emitting JSON receipts, Markdown summaries, and GitHub Actions annotations.

## Design Goals

1. **Diff-only scope** — Only lint added/modified lines, not entire files
2. **Deterministic** — Same inputs always produce same outputs (no randomness, stable ordering)
3. **Clean architecture** — I/O at edges, pure logic in core crates

## Architecture

Dependency direction flows downward (CLI depends on app, app depends on domain/diff, all depend on types):

```
diffguard (CLI) I/O boundary: clap, file I/O, git subprocess, env vars
diffguard-core Engine: run_check(), render_markdown_for_receipt(), compute verdicts

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The description for diffguard-core in the architecture diagram is inconsistent with the project's style guide. The style guide mentions that diffguard-core orchestrates run_check and run_sensor, and renders outputs. The current description is missing run_sensor() and uses a more specific render_markdown_for_receipt() instead of the general render outputs.

To maintain consistency with the style guide and provide accurate information, please update the description.

Suggested change
diffguard-core Engine: run_check(), render_markdown_for_receipt(), compute verdicts
diffguard-core Engine: run_check(), run_sensor(), compute verdicts, render outputs
References
  1. The style guide (line 18) defines diffguard-core as the engine that orchestrates check runs (run_check, run_sensor), computes verdicts, and renders outputs. (link)

├────────────────────────┐
▼ ▼
diffguard-domain diffguard-diff
Pure business logic Pure diff parsing
- rules.rs - unified.rs
- evaluate.rs
- preprocess.rs
│ │
└──────────┬─────────────┘
diffguard-types
Pure DTOs (serde + schemars)
```

| Crate | Purpose |
|-------|---------|
| `diffguard-types` | Serializable DTOs, severity/scope enums, built-in rule definitions |
| `diffguard-diff` | Parse unified diff format, handle binary/submodule/rename detection |
| `diffguard-domain` | Compile rules, evaluate lines, preprocess (mask comments/strings) |
| `diffguard-core` | Engine: check runs, verdicts, render markdown/annotations |
| `diffguard` | CLI binary: arg parsing, config loading, git invocation, file output |
| `diffguard-lsp` | LSP server for editor integration |
| `diffguard-analytics` | Trend history and analytics |
| `diffguard-testkit` | Shared test utilities, fixtures, proptest strategies |
| `xtask` | Repo automation (ci, schema, conformance) |
Comment on lines +39 to +49

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The descriptions for diffguard-types and diffguard-core in the crate purpose table are incomplete or inconsistent compared to the project's style guide.

  • diffguard-types: The description is missing that it also contains JSON schemas, and built-in rule definitions is inaccurate as it only defines the rule structures.
  • diffguard-core: The description is missing that it also orchestrates run_sensor and the more general renders outputs is preferred over the specific render markdown/annotations.

To ensure the documentation is accurate and aligned with the style guide, please update these descriptions.

Suggested change
| Crate | Purpose |
|-------|---------|
| `diffguard-types` | Serializable DTOs, severity/scope enums, built-in rule definitions |
| `diffguard-diff` | Parse unified diff format, handle binary/submodule/rename detection |
| `diffguard-domain` | Compile rules, evaluate lines, preprocess (mask comments/strings) |
| `diffguard-core` | Engine: check runs, verdicts, render markdown/annotations |
| `diffguard` | CLI binary: arg parsing, config loading, git invocation, file output |
| `diffguard-lsp` | LSP server for editor integration |
| `diffguard-analytics` | Trend history and analytics |
| `diffguard-testkit` | Shared test utilities, fixtures, proptest strategies |
| `xtask` | Repo automation (ci, schema, conformance) |
| Crate | Purpose |
|-------|---------|
| `diffguard-types` | Serializable DTOs, enums, and JSON schemas |
| `diffguard-diff` | Parse unified diff format, handle binary/submodule/rename detection |
| `diffguard-domain` | Compile rules, evaluate lines, preprocess (mask comments/strings) |
| `diffguard-core` | Engine: orchestrates check and sensor runs, computes verdicts, renders outputs |
| `diffguard` | CLI binary: arg parsing, config loading, git invocation, file output |
| `diffguard-lsp` | LSP server for editor integration |
| `diffguard-analytics` | Trend history and analytics |
| `diffguard-testkit` | Shared test utilities, fixtures, proptest strategies |
| `xtask` | Repo automation (ci, schema, conformance) |
References
  1. The style guide defines the purpose of diffguard-core (line 18) as orchestrating check and sensor runs and rendering outputs, and diffguard-types (line 21) as containing DTOs, enums, and JSON schemas. The table's descriptions are inconsistent with these definitions. (link)


## Common Commands

```bash
cargo build # Build
cargo test --workspace # Run all tests
cargo fmt --check # Format check
cargo clippy --workspace --all-targets -- -D warnings # Lint
cargo run -p xtask -- ci # Full CI suite
cargo run -p xtask -- schema # Generate JSON schemas
cargo run -p diffguard -- check --base origin/main --head HEAD # Run CLI
cargo mutants # Mutation testing
cargo +nightly fuzz run unified_diff_parser # Fuzz testing
```

## Key Invariants

These are contracts that must be maintained:

- **Exit codes are stable API**: `0`=pass, `1`=tool error, `2`=policy fail, `3`=warn-fail
- **Receipt schemas are versioned** — avoid breaking changes to JSON output structure
- **Domain crates are I/O-free** — `diffguard-diff`, `diffguard-domain`, `diffguard-types` must not use `std::process`, filesystem, or environment variables
- **Diff parsing never panics** — malformed input returns errors, never crashes (fuzz-tested)
- **Language preprocessing is best-effort** — uses C-like syntax heuristics; not a full parser for any language

## Testing

- **Unit tests:** Co-located in source files (`#[cfg(test)]`)
- **Integration tests:** `tests/` directories per crate
- **Snapshot tests:** `insta` crate for output stability
- **Property tests:** `proptest` for generative testing
- **Mutation tests:** `cargo-mutants` (config in `mutants.toml`)
- **Fuzz tests:** `fuzz/fuzz_targets/` — `unified_diff_parser`, `preprocess`, `rule_matcher`

## Configuration

Rules defined in `diffguard.toml`. See `diffguard.toml.example`. Key fields:
- `patterns`: regex patterns to match
- `paths`/`exclude_paths`: glob-based file filtering
- `ignore_comments`/`ignore_strings`: preprocessor control (best-effort, C-like syntax)
- `languages`: optional language filter (auto-detected from extension)
- `includes`: compose configs via `includes = [...]`
- `env`: supports `${VAR}` or `${VAR:-default}` expansion
- Presets: `diffguard init --preset <name>`

## Governance

Diffguard dogfoods its own governance. See:
- `.github/PULL_REQUEST_TEMPLATE/conveyor-pr.md` — 6-gate conveyor checklist
- `.github/ISSUE_TEMPLATE/` — gate-framed (feature), gate-bug (bug)
- `CONTRIBUTING.md` — contributor flow
- `.github/settings.yml` — branch protection, required checks

## MSRV

Rust 1.92 (Minimum Supported Rust Version)

## Extending diffguard

### Adding a new rule config field

1. Add field to `RuleConfig` in `diffguard-types/src/lib.rs`
2. Update `CompiledRule` in `diffguard-domain/src/rules.rs` if needed at compile time
3. Update evaluation logic in `diffguard-domain/src/evaluate.rs`
4. Regenerate schemas: `cargo run -p xtask -- schema`
5. Update `diffguard.toml.example`

### Adding new rule behavior

1. Modify `evaluate_line()` in `diffguard-domain/src/evaluate.rs`
2. Add unit tests in same file
3. Add property tests if behavior is complex
4. Run `cargo mutants` to verify test coverage

### Changes to diff parsing

1. Modify `diffguard-diff/src/unified.rs`
2. Add regression test cases
3. Run fuzz target: `cargo +nightly fuzz run unified_diff_parser`
4. Ensure no panics on malformed input

### Adding CLI flags

1. Add to `Args` struct in `diffguard/src/main.rs`
2. Wire through to `diffguard-core` if it affects orchestration
3. Update `--help` text and any documentation
8 changes: 8 additions & 0 deletions .hermes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

Artifacts from reasoning, planning, and fixing — permanent repo history.

## Agent Customization

| File | Purpose |
|------|---------|
| `agent-context.md` | Canonical repo-specific agent instructions (architecture, commands, invariants, testing, governance) |

Root files (`AGENTS.md`, `CLAUDE.md`, `GEMINI.md`) are thin pointers here.

## Flows

| File | Title | Date |
Expand Down
122 changes: 3 additions & 119 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,121 +1,5 @@
# CLAUDE.md
# AGENTS.md

Guidance for Claude Code when working with this repository.
Repo-specific agent context lives in `.hermes/agent-context.md`. See that file for architecture, commands, invariants, testing, and governance details.

## Project Overview

**diffguard** is a diff-scoped governance linter for PR automation. It applies rules only to added/changed lines in Git diffs, emitting JSON receipts, Markdown summaries, and GitHub Actions annotations.

## Design Goals

1. **Diff-only scope** - Only lint added/modified lines, not entire files
2. **Deterministic** - Same inputs always produce same outputs (no randomness, stable ordering)
3. **Clean architecture** - I/O at edges, pure logic in core crates

## Common Commands

```bash
cargo build # Build
cargo test --workspace # Run all tests
cargo fmt --check # Format check
cargo clippy --workspace --all-targets -- -D warnings # Lint
cargo run -p xtask -- ci # Full CI suite
cargo run -p xtask -- schema # Generate JSON schemas
cargo run -p diffguard -- check --base origin/main --head HEAD # Run CLI
cargo mutants # Mutation testing
cargo +nightly fuzz run unified_diff_parser # Fuzz testing
```

## Architecture

Dependency direction flows downward (CLI depends on app, app depends on domain/diff, all depend on types):

```
diffguard (CLI) I/O boundary: clap, file I/O, git subprocess, env vars
diffguard-core Use-cases: run_check(), render_markdown_for_receipt(), compute verdicts
├────────────────────────┐
▼ ▼
diffguard-domain diffguard-diff
Pure business logic Pure diff parsing
- rules.rs - unified.rs
- evaluate.rs
- preprocess.rs
│ │
└──────────┬─────────────┘
diffguard-types
Pure DTOs (serde + schemars)
```

| Crate | Purpose |
|-------|---------|
| `diffguard-types` | Serializable DTOs, severity/scope enums, built-in rule definitions |
| `diffguard-diff` | Parse unified diff format, handle binary/submodule/rename detection |
| `diffguard-domain` | Compile rules, evaluate lines, preprocess (mask comments/strings) |
| `diffguard-core` | Orchestrate check runs, compute verdicts, render markdown/annotations |
| `diffguard` | CLI binary: arg parsing, config loading, git invocation, file output |
| `xtask` | Repo automation tasks (ci, schema generation) |

## Key Invariants

These are contracts that must be maintained:

- **Exit codes are stable API**: `0`=pass, `1`=tool error, `2`=policy fail, `3`=warn-fail
- **Receipt schemas are versioned** - avoid breaking changes to JSON output structure
- **Domain crates are I/O-free** - `diffguard-diff`, `diffguard-domain`, `diffguard-types` must not use `std::process`, filesystem, or environment variables
- **Diff parsing never panics** - malformed input returns errors, never crashes (fuzz-tested)
- **Language preprocessing is best-effort** - uses C-like syntax heuristics; not a full parser for any language

## Testing

- **Unit tests:** Co-located in source files (`#[cfg(test)]`)
- **Integration tests:** `tests/` directories per crate
- **Snapshot tests:** `insta` crate for output stability
- **Property tests:** `proptest` for generative testing
- **Mutation tests:** `cargo-mutants` (config in `mutants.toml`)
- **Fuzz tests:** `fuzz/fuzz_targets/` - `unified_diff_parser`, `preprocess`, `rule_matcher`

## Extending diffguard

### Adding a new rule config field

1. Add field to `RuleConfig` in `diffguard-types/src/lib.rs`
2. Update `CompiledRule` in `diffguard-domain/src/rules.rs` if needed at compile time
3. Update evaluation logic in `diffguard-domain/src/evaluate.rs`
4. Regenerate schemas: `cargo run -p xtask -- schema`
5. Update `diffguard.toml.example`

### Adding new rule behavior

1. Modify `evaluate_line()` in `diffguard-domain/src/evaluate.rs`
2. Add unit tests in same file
3. Add property tests if behavior is complex
4. Run `cargo mutants` to verify test coverage

### Changes to diff parsing

1. Modify `diffguard-diff/src/unified.rs`
2. Add regression test cases
3. Run fuzz target: `cargo +nightly fuzz run unified_diff_parser`
4. Ensure no panics on malformed input

### Adding CLI flags

1. Add to `Args` struct in `diffguard/src/main.rs`
2. Wire through to `diffguard-core` if it affects orchestration
3. Update `--help` text and any documentation

## Configuration

Rules defined in `diffguard.toml`. See `diffguard.toml.example`. Key fields:
- `patterns`: regex patterns to match
- `paths`/`exclude_paths`: glob-based file filtering
- `ignore_comments`/`ignore_strings`: preprocessor control (best-effort, C-like syntax)
- `languages`: optional language filter (auto-detected from extension)

## MSRV

Rust 1.92 (Minimum Supported Rust Version)
This file exists so agents that only read root-level files find the pointer.
120 changes: 2 additions & 118 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,121 +1,5 @@
# CLAUDE.md

Guidance for Claude Code when working with this repository.
Repo-specific agent context lives in `.hermes/agent-context.md`. See that file for architecture, commands, invariants, testing, and governance details.

## Project Overview

**diffguard** is a diff-scoped governance linter for PR automation. It applies rules only to added/changed lines in Git diffs, emitting JSON receipts, Markdown summaries, and GitHub Actions annotations.

## Design Goals

1. **Diff-only scope** - Only lint added/modified lines, not entire files
2. **Deterministic** - Same inputs always produce same outputs (no randomness, stable ordering)
3. **Clean architecture** - I/O at edges, pure logic in core crates

## Common Commands

```bash
cargo build # Build
cargo test --workspace # Run all tests
cargo fmt --check # Format check
cargo clippy --workspace --all-targets -- -D warnings # Lint
cargo run -p xtask -- ci # Full CI suite
cargo run -p xtask -- schema # Generate JSON schemas
cargo run -p diffguard -- check --base origin/main --head HEAD # Run CLI
cargo mutants # Mutation testing
cargo +nightly fuzz run unified_diff_parser # Fuzz testing
```

## Architecture

Dependency direction flows downward (CLI depends on core, core depends on domain/diff, all depend on types):

```
diffguard (CLI) I/O boundary: clap, file I/O, git subprocess, env vars
diffguard-core Engine: run_check(), run_sensor(), render outputs, compute verdicts
├────────────────────────┐
▼ ▼
diffguard-domain diffguard-diff
Pure business logic Pure diff parsing
- rules.rs - unified.rs
- evaluate.rs
- preprocess.rs
│ │
└──────────┬─────────────┘
diffguard-types
Pure DTOs (serde + schemars)
```

| Crate | Purpose |
|-------|---------|
| `diffguard-types` | Serializable DTOs, severity/scope enums, built-in rule definitions |
| `diffguard-diff` | Parse unified diff format, handle binary/submodule/rename detection |
| `diffguard-domain` | Compile rules, evaluate lines, preprocess (mask comments/strings) |
| `diffguard-core` | Engine: check runs, sensor reports, verdicts, render markdown/annotations |
| `diffguard` | CLI binary: arg parsing, config loading, git invocation, file output |
| `xtask` | Repo automation tasks (ci, schema generation) |

## Key Invariants

These are contracts that must be maintained:

- **Exit codes are stable API**: `0`=pass, `1`=tool error, `2`=policy fail, `3`=warn-fail
- **Receipt schemas are versioned** - avoid breaking changes to JSON output structure
- **Domain crates are I/O-free** - `diffguard-diff`, `diffguard-domain`, `diffguard-types` must not use `std::process`, filesystem, or environment variables
- **Diff parsing never panics** - malformed input returns errors, never crashes (fuzz-tested)
- **Language preprocessing is best-effort** - uses C-like syntax heuristics; not a full parser for any language

## Testing

- **Unit tests:** Co-located in source files (`#[cfg(test)]`)
- **Integration tests:** `tests/` directories per crate
- **Snapshot tests:** `insta` crate for output stability
- **Property tests:** `proptest` for generative testing
- **Mutation tests:** `cargo-mutants` (config in `mutants.toml`)
- **Fuzz tests:** `fuzz/fuzz_targets/` - `unified_diff_parser`, `preprocess`, `rule_matcher`

## Extending diffguard

### Adding a new rule config field

1. Add field to `RuleConfig` in `diffguard-types/src/lib.rs`
2. Update `CompiledRule` in `diffguard-domain/src/rules.rs` if needed at compile time
3. Update evaluation logic in `diffguard-domain/src/evaluate.rs`
4. Regenerate schemas: `cargo run -p xtask -- schema`
5. Update `diffguard.toml.example`

### Adding new rule behavior

1. Modify `evaluate_line()` in `diffguard-domain/src/evaluate.rs`
2. Add unit tests in same file
3. Add property tests if behavior is complex
4. Run `cargo mutants` to verify test coverage

### Changes to diff parsing

1. Modify `diffguard-diff/src/unified.rs`
2. Add regression test cases
3. Run fuzz target: `cargo +nightly fuzz run unified_diff_parser`
4. Ensure no panics on malformed input

### Adding CLI flags

1. Add to `Args` struct in `diffguard/src/main.rs`
2. Wire through to `diffguard-core` if it affects orchestration
3. Update `--help` text and any documentation

## Configuration

Rules defined in `diffguard.toml`. See `diffguard.toml.example`. Key fields:
- `patterns`: regex patterns to match
- `paths`/`exclude_paths`: glob-based file filtering
- `ignore_comments`/`ignore_strings`: preprocessor control (best-effort, C-like syntax)
- `languages`: optional language filter (auto-detected from extension)

## MSRV

Rust 1.92 (Minimum Supported Rust Version)
This file exists so agents that only read root-level files find the pointer.
Loading
Loading