# Side-Effects Review — RevertDetector invalid git arg (EVO-003)

**Version / slug:** `evo003-revertdetector-git-arg`
**Date:** `2026-06-02`
**Author:** `Echo (Instar Agent)`
**Second-pass reviewer:** `not required`

## Summary of the change

`src/monitoring/RevertDetector.ts` builds a `git log` argv to find `Revert "..."` commits. That argv carried `--regexp-ignore-case=false`, which git rejects (`fatal: unrecognized argument` — git's `--grep` case flags take no `=value` form). The call therefore threw on every tick, was swallowed by the existing try/catch, and `scanForReverts` returned 0 — making revert detection a silent no-op on every install. The change deletes that one element (case-sensitive is git's `--grep` default, which is what we want) and adds a NOTE comment so it can't be reintroduced. `tests/unit/RevertDetector.test.ts` gains two regression tests: an argv-shape assertion (injected arg-recording git) and a real-git end-to-end test (real temp repo + real `git revert`). Files touched: `src/monitoring/RevertDetector.ts`, `tests/unit/RevertDetector.test.ts`.

## Decision-point inventory

This change touches no block/allow decision point. RevertDetector is an observer that opens forensic FailureLedger records; it never gates a message, job, or session.

- `RevertDetector.scanForReverts git argv` — modify — drop the invalid `--regexp-ignore-case=false` element so the scan command is valid git.

---

## 1. Over-block

**What legitimate inputs does this change reject that it shouldn't?**

No block/allow surface — over-block not applicable. The only behavioral change is that the scan command now executes successfully instead of throwing. Match semantics are unchanged in intent: `--grep=^Revert` already matched case-sensitively (git's default), which is exactly what the broken `=false` flag was *trying* to express. So no commit that should have matched is now excluded, and none that shouldn't is now included.

---

## 2. Under-block

**What failure modes does this still miss?**

No block/allow surface — under-block not applicable. Scope note: detection keys on the conventional `Revert "<subject>"` message that `git revert` produces by default. A hand-crafted revert with a non-standard subject still won't be detected — but that is pre-existing behavior, unchanged by this fix and out of scope for EVO-003.

---

## 3. Level-of-abstraction fit

**Is this at the right layer?**

Yes. RevertDetector is correctly a low-level detector that emits forensic records into the FailureLedger (a signal), not an authority. This change does not move it across that line — it only repairs the git invocation so the detector can run at all. No higher-level gate needs to consume this differently; the FailureLedger remains the consumer.

---

## 4. Signal vs authority compliance

**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)

**Does this change hold blocking authority with brittle logic?**

- [x] No — this change has no block/allow surface.

RevertDetector produces forensic FailureLedger entries (a signal). It holds no blocking authority. The fix is a pure correction of a malformed external-command argument; it neither adds nor removes any decision authority.

---

## 5. Interactions

**Does this interact with existing checks, recovery paths, or infrastructure?**

- **Shadowing:** None. The scan runs on RevertDetector's own tick and writes only to the FailureLedger. Before the fix it always threw → returned 0; after, it returns the real count. Nothing was relying on the always-throws behavior.
- **Double-fire:** The forensic entry is opened via `resolveByCommit`/ledger logic that already de-dupes by commit. Turning detection on does not change that path; it just lets it receive real input for the first time. A given revert commit yields one record.
- **Races:** The scan is lease-gated (`isLeaseHolder()` guard, unchanged), so only the awake machine scans. No new shared state is introduced.
- **Feedback loops:** RevertDetector feeds the FailureLedger, which the failure-learning loop reads. This change makes that input non-empty for revert events for the first time. The volume is bounded by the scan window (recent commits only) and de-duped per commit, so no runaway loop is created.

---

## 6. External surfaces

**Does this change anything visible outside the immediate code path?**

- Other agents on the same machine? No.
- Other users of the install base? Only positively: revert detection begins working fleet-wide on update — previously-silent reverts will now produce forensic FailureLedger records. No user-facing message or topic is generated by RevertDetector itself.
- External systems? No. The change *reduces* the git command to a valid form; it issues no new external calls.
- Persistent state? FailureLedger will, for the first time, gain `source: 'revert'` forensic entries on installs that have revert commits in their scan window. These are forensic (resolved) records, not open failures — they do not trigger escalation.
- Timing/runtime: No new timers. Same tick cadence, same lease gate.

---

## 7. Rollback cost

**If this turns out wrong in production, what's the back-out?**

Pure code change — revert the commit and ship a patch. No data migration. The only persistent residue is new `source: 'revert'` forensic entries in the FailureLedger; these are benign resolved records and need no cleanup on rollback. No agent state repair, no user-visible regression during the rollback window.

---

## Conclusion

This review found no block/allow surface and no risky interaction. The change is a one-line deletion of an invalid git argument that has silently disabled revert detection on every install, plus two regression tests (argv-shape + real-git end-to-end) that pin the fix. The net effect is that an existing, already-wired observer starts producing the forensic records it was always meant to produce. Clear to ship as a Tier-1 change.

---

## Second-pass review (if required)

**Reviewer:** not required (Tier-1)
**Independent read of the artifact: concur**

---

## Evidence pointers

- `tests/unit/RevertDetector.test.ts` — 11/11 pass, including the two EVO-003 regression tests (argv-shape + real-git end-to-end).
- `npx tsc --noEmit` — clean.
- `pnpm lint` — clean (includes lint-no-direct-destructive: the real-git test uses `SafeGitExecutor`/`SafeFsExecutor`, not raw exec/rm).
- `pnpm build` — clean (dist compiles).
- Bug confirmation: `JKHeadley/main:src/monitoring/RevertDetector.ts:143` carries `--regexp-ignore-case=false`; git 2.39.5 rejects it with `fatal: unrecognized argument`.
