mati_core/hooks/codex_pre_apply_patch.rs
1/// Codex PreToolUse(apply_patch) hook — hard edit enforcement via exit 2 + stderr.
2///
3/// Delegates to `mati hook-decide codex-pre-apply-patch`. Codex delivers the
4/// raw patch envelope in `tool_input.command` (`*** Update File: <path>` /
5/// `*** Add File:` / `*** Delete File:` / `*** Move to:`); the Rust side parses
6/// the target paths and evaluates each against the gotcha store.
7///
8/// Unlike the pre-bash wrapper (which `exec`s mati), this one deliberately does
9/// NOT exec: it captures mati's output so it can tell a real DENY (exit 2 + a
10/// line starting `mati:`) apart from a mati *fault* — most importantly an older
11/// binary that doesn't know this variant, which clap also reports with exit 2.
12/// Any fault fails OPEN. Wrongly blocking *every* edit on a mati error would be
13/// far worse than missing one gotcha, so the edit path is biased to allow on
14/// uncertainty (mirrors the parser's fail-open contract).
15pub const SCRIPT: &str = r#"#!/usr/bin/env bash
16set -uo pipefail
17HOOKS_DIR="$(cd "$(dirname "$0")" && pwd)" && export PATH="$HOOKS_DIR:$PATH"
18command -v mati >/dev/null 2>&1 || exit 0
19out="$(mati hook-decide codex-pre-apply-patch 2>&1)"; rc=$?
20# exit 2 AND a "mati:" message == deliberate deny. Anything else (allow, or a
21# mati/clap fault that also exits 2) fails OPEN so edits never block on a fault.
22if [ "$rc" -eq 2 ] && printf '%s' "$out" | grep -q '^mati:'; then
23 printf '%s\n' "$out" >&2
24 exit 2
25fi
26exit 0
27"#;