Skip to content

fix(robot-repo-automaton): make ContentMatch detection compile#299

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/determined-cerf-s4zaob
Jun 20, 2026
Merged

fix(robot-repo-automaton): make ContentMatch detection compile#299
hyperpolymath merged 1 commit into
mainfrom
claude/determined-cerf-s4zaob

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Fixes the pre-existing robot-repo-automaton build error noted (out of scope) in #298.

The bug

Detector::detect_content_match read file contents with std::fs::read (→ Vec<u8>) and passed &content to a string regex::Regex::is_match, which wants &str:

let re = regex::Regex::new(regex_str).ok()?;     // string Regex
...
if let Ok(content) = std::fs::read(file_path) {  // Vec<u8>
    if re.is_match(&content) {                   // ❌ expects &str, got &Vec<u8>

So the crate never compiled, and the entire DetectionMethod::ContentMatch detection path (dispatched at detector.rs:149) was dead. CI didn't catch it because the rust CodeQL job runs build-mode none (buildless) — nothing in CI did a full cargo build/test of this crate.

The fix (one line)

Switch to std::fs::read_to_string. This both fixes the type error and implements the "skip non-UTF8" intent already written in the comment directly above the read (read_to_string returns Err on non-UTF8 bytes, which the existing if let Ok skips). It matches the sibling content scan in hypatia.rs:433-435, which already uses read_to_string + is_match(&content).

I considered regex::bytes::Regex instead, but that changes detection semantics and contradicts the stated non-UTF8-skipping intent — read_to_string is the smaller, intent-preserving fix.

Regression test

Added test_content_match_detects_and_skips_non_utf8 (this path had zero coverage since it never compiled): asserts a positive regex match is detected, a non-match yields nothing, and a non-UTF8 file is skipped without panicking.

Verification

Scope is detector.rs only (+58/−1, no file deletions).

🤖 Generated with Claude Code

https://claude.ai/code/session_01RozeeLxpJsd3WWFngaZWz3


Generated by Claude Code

`detect_content_match` read file contents with `std::fs::read` (→ `Vec<u8>`)
and passed `&content` to a string `regex::Regex::is_match`, which wants
`&str`. The crate therefore never compiled and the whole
`DetectionMethod::ContentMatch` detection path was dead code.

Switch to `std::fs::read_to_string`. This fixes the type error and also
implements the "skip non-UTF8" intent already stated in the comment just
above (`read_to_string` returns `Err` on non-UTF8 bytes, which the
`if let Ok` then skips), matching the sibling content scan in
`hypatia.rs`.

Add a regression test for the previously-uncompilable path: a positive
regex match, a non-match, and a non-UTF8 file that must be skipped
without panicking. `cargo build` is clean and all 101 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RozeeLxpJsd3WWFngaZWz3
@hyperpolymath hyperpolymath marked this pull request as ready for review June 20, 2026 23:15
@hyperpolymath hyperpolymath merged commit e6f9b26 into main Jun 20, 2026
20 checks passed
@hyperpolymath hyperpolymath deleted the claude/determined-cerf-s4zaob branch June 20, 2026 23:15
hyperpolymath added a commit that referenced this pull request Jun 21, 2026
Items #2 (clippy sweep) and #1 (close the CI gap) from the follow-up
list, as one PR — the lint fixes and the gate that enforces them belong
together so CI is self-consistent.

## Why
The only Rust CI was CodeQL in build-mode `none` (**buildless**) —
nothing compiled or tested `robot-repo-automaton` / `shared-context` /
`dashboard`. That's exactly how the non-compiling content-match path
reached `main` before #299 fixed it. This closes that gap.

## The gate — `.github/workflows/rust.yml`
Per-crate matrix (modeled on `e2e.yml`: SHA-pinned checkout,
`permissions: contents: read`, SPDX header):
- `cargo build --all-targets`
- `cargo test`
- `cargo clippy --all-targets -- -D warnings` *(blocking)*
- `cargo fmt --check` *(informational, `continue-on-error`)* — there's
~180 hunks of **pre-existing** formatting drift; gating it would mean a
giant reformat that buries this change, so it's surfaced but not yet
enforced. A dedicated `cargo fmt` pass can flip it to blocking later.

## Clippy fixes (to make the gate green)
| File | Finding | Fix |
|---|---|---|
| `fixer.rs` | `.replace("hyperpolymath", "hyperpolymath")` | no-op —
removed |
| `registry_guard.rs` | manual `splitn(2, '/')` | `split_once('/')` |
| `exclusion_registry.rs` | `from_str` shadows `FromStr` | rename
inherent `from_str` → `parse` (matches `Catalog::parse`; 2 internal call
sites) |
| `exclusion_registry.rs` | `.ok()` + `if let Some` | `if let Ok(..)` |
| `hypatia.rs`, `main.rs` | `&PathBuf` arg | `&Path` |
| `Cargo.toml` ×2 | `toml = "1.1.2+spec-1.1.0"` | drop ignored `+spec`
build-metadata (resolution-neutral; silences cargo warning) |
| `benches/fleet_benchmarks.rs` | deprecated `criterion::black_box` |
import `std::hint::black_box` (one import swap covers all call sites) |

## Verification
All three crates: **clippy `-D warnings` clean**, build clean. Tests:
**101** (robot-repo-automaton) + **84** (shared-context) pass. Locally
simulated the full matrix (build + test + clippy) green per crate;
`rust.yml` parses as valid YAML.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01RozeeLxpJsd3WWFngaZWz3

---
_Generated by [Claude
Code](https://claude.ai/code/session_01RozeeLxpJsd3WWFngaZWz3)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants