mirror of
https://github.com/actualbudget/actual.git
synced 2026-11-09 10:45:04 -06:00
* [AI] Fail agent hooks with an actionable error when jq is missing The shared agent-hook scripts all parse their payload with jq but never checked it exists. A missing jq made git-guard.sh block every Bash call with a misleading 'could not parse the hook payload' message, while other hooks silently failed open and skipped their checks (issue #8629). Add require_jq to common.sh — called by every hook before its first jq use — so a missing jq fails closed with a clear install message, distinct from a malformed-payload error. The script name in the message is derived from $0 rather than passed by each caller. The Cursor adapters emit a static JSON deny (their deny() helper itself needs jq to build JSON) or an advisory where blocking isn't possible, and AGENTS.md now documents the prerequisite. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [AI] Address review: advisory wording for PostToolUse hooks, hook tests PostToolUse hooks (format-edited-file, prefer-one-component) run after the edit already happened, so a missing jq now reports 'Agent hook skipped' instead of claiming a block. Exit 2 stays: it is the only exit code that feeds stderr back to the agent. Add scripts/agent-hooks/test-hooks.sh, a standalone runnable check covering the missing-jq path for every hook plus malformed-JSON, missing-field, and guard-behavior cases, and soften the release-note verb. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [AI] Remove standalone hook test script Not wired into CI, so it only served as a manual check; the hook behavior was verified by hand and the script isn't worth maintaining. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
43 lines
1.4 KiB
Bash
Executable File
43 lines
1.4 KiB
Bash
Executable File
#!/bin/sh
|
|
# Agent hook (PostToolUse / afterFileEdit), shared across Claude, Codex, Cursor.
|
|
#
|
|
# "Prefer one component per file" — surfaced as a soft warning for *newly
|
|
# created* .tsx files only. Existing multi-component files are grandfathered
|
|
# (skipped if already tracked by git), and this never touches `yarn lint`, so
|
|
# react/no-multi-comp stays out of .oxlintrc.json.
|
|
|
|
. "$(dirname "$0")/common.sh"
|
|
require_jq advisory
|
|
|
|
file=$(jq -r '.tool_input.file_path // empty')
|
|
[ -n "$file" ] && [ -f "$file" ] || exit 0
|
|
case "$file" in
|
|
*.tsx) ;;
|
|
*) exit 0 ;;
|
|
esac
|
|
|
|
dir=$(dirname "$file")
|
|
|
|
# Resolve the repo root regardless of which agent invoked us.
|
|
ROOT=$(resolve_repo_root "$dir")
|
|
|
|
# Normalize to an absolute + repo-root-relative path so the git pathspec is
|
|
# unambiguous whether the agent passed an absolute or relative file_path.
|
|
abs=$(CDPATH= cd "$dir" 2>/dev/null && pwd)/$(basename "$file")
|
|
rel=${abs#"$ROOT"/}
|
|
|
|
# Only new (untracked) files; grandfather everything already in git.
|
|
git -C "$ROOT" ls-files --error-unmatch "$rel" >/dev/null 2>&1 && exit 0
|
|
|
|
BIN="$ROOT/node_modules/.bin"
|
|
[ -x "$BIN/oxlint" ] || exit 0
|
|
|
|
out=$(cd "$ROOT" && "$BIN/oxlint" -D react/no-multi-comp "$abs" 2>&1)
|
|
case "$out" in
|
|
*no-multi-comp*)
|
|
echo "Prefer one component per file — this new file defines multiple components; split them into separate files (AGENTS.md)." >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
exit 0
|