mirror of
https://github.com/actualbudget/actual.git
synced 2026-07-16 07:04:23 -05:00
* [AI] Replace mechanical agent rules with shared agent hooks + nano-staged Move the mechanical "remember to run X" rules out of AGENTS.md and the agent guidance docs into deterministic, cross-agent hooks, and migrate the pre-commit runner from lint-staged to nano-staged. - Add shared hook scripts in scripts/agent-hooks/ (git-guard, format-edited-file, no-strict-ignore-new-file, prefer-one-component, check-on-stop, common helpers) wired for Claude (.claude/settings.json), Codex (.codex/config.toml), and Cursor (.cursor/hooks.json + adapters). - Enforce "avoid enum" via a new actual/no-enum lint rule, grandfathering the two existing declarations in .oxlintrc.json overrides. - Migrate lint-staged -> nano-staged (.nano-staged.json, .husky/pre-commit, package.json). - Trim AGENTS.md, .github/agents/pr-and-commit-rules.md, the Cursor rule, and the committing skill down to the rules that aren't auto-enforced. - Add release note 8089.md. * [AI] Align PR-title wording in AGENTS.md with canonical rules * [AI] Fix check-on-stop hook on bash 3.2 and TSV column collapse The Stop hook silently no-op'd in two ways: - `declare -A` isn't supported on stock macOS bash 3.2, and the slash/hyphen path subscript aborted under `set -u`. Dedupe via a space-padded string match instead. - jq emitted an empty middle TSV field for a package with test but no typecheck; tab is IFS-whitespace so `read` collapsed it and shifted the columns (eslint-plugin-actual then ran neither). Emit non-empty sentinels (-, yes/no) so no field can collapse. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
41 lines
1.3 KiB
Bash
Executable File
41 lines
1.3 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.
|
|
|
|
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.
|
|
. "$(dirname "$0")/common.sh"
|
|
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
|