chore(ai-workflow): tighten agent workflow and worktree tooling (#1107)

* chore(ai-workflow): tighten agent workflow and worktree tooling

* fix(ai-workflow): address review feedback

* fix(ai-workflow): make format hook portable
This commit is contained in:
Tommaso Casaburi
2026-03-17 19:58:30 +08:00
committed by GitHub
parent b9c7524f04
commit ebf5ab64e4
23 changed files with 561 additions and 455 deletions
+2 -25
View File
@@ -1,27 +1,4 @@
#!/bin/bash
# afterFileEdit hook: Auto-format files after AI edits them
# Receives JSON via stdin: {"file_path": "...", "edits": [...]}
# Read stdin (required for hooks)
input=$(cat)
# Extract file_path using grep/sed (jq-free for portability)
file_path=$(echo "$input" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/')
# Exit if no file path found
if [ -z "$file_path" ]; then
exit 0
fi
# Only format JS/TS files
case "$file_path" in
*.js|*.ts|*.tsx|*.mjs)
# Match the other hooks by resolving relative paths from the repo root.
cd "$(dirname "$0")/../.." || exit 0
# Run oxfmt on the file (silent on success)
npx oxfmt "$file_path" 2>/dev/null || true
;;
esac
exit 0
repo_root="$(cd "$(dirname "$0")/../.." && pwd)"
exec "$repo_root/scripts/agent-hooks/format.sh" "$@"
+2 -108
View File
@@ -1,110 +1,4 @@
#!/bin/bash
# stop hook: prune stale remote refs and remove integrated temporary local branches
# This is informational - always exits 0
# Consume stdin (required for hooks)
cat > /dev/null
# Change to project directory
cd "$(dirname "$0")/../.." || exit 0
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
exit 0
fi
default_branch="$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null | sed 's#^origin/##')"
if [ -z "$default_branch" ]; then
default_branch="master"
fi
current_branch="$(git branch --show-current 2>/dev/null || true)"
branch_looks_temporary() {
case "$1" in
pr/*|feature/*|fix/*|docs/*|chore/*) return 0 ;;
*) return 1 ;;
esac
}
branch_is_integrated() {
local branch="$1"
local cherry_output
cherry_output="$(git cherry "$default_branch" "$branch" 2>/dev/null || true)"
if echo "$cherry_output" | grep -q '^+'; then
return 1
fi
return 0
}
branch_has_live_upstream() {
local upstream="$1"
[ -n "$upstream" ] && git show-ref --verify --quiet "refs/remotes/$upstream"
}
merged_pr_number_for_branch() {
local branch="$1"
local pr_number=""
if ! command -v gh >/dev/null 2>&1; then
return 0
fi
case "$branch" in
pr/*)
pr_number="${branch#pr/}"
gh pr view "$pr_number" --repo bitsocialnet/5chan --json mergedAt --jq 'select(.mergedAt != null) | .mergedAt' >/dev/null 2>&1 || return 0
echo "$pr_number"
return 0
;;
esac
gh pr list --repo bitsocialnet/5chan --state merged --head "$branch" --json number --jq '.[0].number // empty' 2>/dev/null || true
}
echo "Syncing git refs and temporary branches..."
echo ""
echo "=== git config --local fetch.prune true ==="
git config --local fetch.prune true 2>&1 || true
echo ""
echo "=== git config --local remote.origin.prune true ==="
git config --local remote.origin.prune true 2>&1 || true
echo ""
echo "=== git fetch --prune origin ==="
git fetch --prune origin 2>&1 || true
echo ""
while IFS='|' read -r branch upstream; do
local_pr_number=""
[ -z "$branch" ] && continue
[ "$branch" = "$current_branch" ] && continue
[ "$branch" = "$default_branch" ] && continue
branch_looks_temporary "$branch" || continue
local_pr_number="$(merged_pr_number_for_branch "$branch")"
if branch_has_live_upstream "$upstream"; then
continue
fi
if ! branch_is_integrated "$branch" && [ -z "$local_pr_number" ]; then
continue
fi
if [ -n "$local_pr_number" ]; then
echo "=== merged PR #$local_pr_number allows deleting $branch ==="
echo ""
fi
echo "=== git branch -D $branch ==="
git branch -D "$branch" 2>&1 || true
echo ""
done < <(git for-each-ref --format='%(refname:short)|%(upstream:short)' refs/heads)
echo "Git ref sync complete."
exit 0
repo_root="$(cd "$(dirname "$0")/../.." && pwd)"
exec "$repo_root/scripts/agent-hooks/sync-git-branches.sh" "$@"
+2 -61
View File
@@ -1,63 +1,4 @@
#!/bin/bash
# stop hook: Run build, lint, type-check, and security audit when agent finishes
# This is informational - always exits 0
# Consume stdin (required for hooks)
cat > /dev/null
# Change to project directory
cd "$(dirname "$0")/../.." || exit 0
cleanup_generated_dir() {
local path="$1"
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
return
fi
if git ls-files --error-unmatch "$path" >/dev/null 2>&1; then
if git diff --quiet -- "$path"; then
return
fi
echo "=== git restore --worktree $path ==="
git restore --worktree -- "$path" 2>&1 || true
echo ""
return
fi
if [ -e "$path" ]; then
echo "=== rm -rf $path ==="
rm -rf "$path" 2>&1 || true
echo ""
fi
}
echo "Running build, lint, type-check, and security audit..."
echo ""
# Run build (catches compilation errors)
echo "=== yarn build ==="
yarn build 2>&1 || true
echo ""
# Run lint
echo "=== yarn lint ==="
yarn lint 2>&1 || true
echo ""
# Run type-check
echo "=== yarn type-check ==="
yarn type-check 2>&1 || true
echo ""
# Run security audit
echo "=== yarn audit ==="
yarn audit 2>&1 || true
echo ""
cleanup_generated_dir build
cleanup_generated_dir dist
echo "Verification complete."
exit 0
repo_root="$(cd "$(dirname "$0")/../.." && pwd)"
exec "$repo_root/scripts/agent-hooks/verify.sh" "$@"
+2 -23
View File
@@ -1,25 +1,4 @@
#!/bin/bash
# afterFileEdit hook: Run yarn install when package.json is changed
# Receives JSON via stdin: {"file_path": "...", "edits": [...]}
# Read stdin (required for hooks)
input=$(cat)
# Extract file_path using grep/sed (jq-free for portability)
file_path=$(echo "$input" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/.*:.*"\([^"]*\)"/\1/')
# Exit if no file path found
if [ -z "$file_path" ]; then
exit 0
fi
# Only run yarn install if package.json was changed
if [ "$file_path" = "package.json" ]; then
# Change to project directory
cd "$(dirname "$0")/../.." || exit 0
echo "package.json changed - running yarn install to update yarn.lock..."
yarn install
fi
exit 0
repo_root="$(cd "$(dirname "$0")/../.." && pwd)"
exec "$repo_root/scripts/agent-hooks/yarn-install.sh" "$@"
+6 -6
View File
@@ -41,21 +41,21 @@ fi
### 3. Ensure branch workflow is reviewable
- If already on a short-lived task branch such as `feature/*`, `fix/*`, `docs/*`, or `chore/*`, stay on it.
- If already on a short-lived task branch such as `codex/feature/*`, `codex/fix/*`, `codex/docs/*`, or `codex/chore/*`, stay on it.
- If on `master`, create a task branch before staging or committing.
- Do **not** commit the work directly on `master` when PR review bots are expected.
Suggested naming:
- `feature/short-slug`
- `fix/short-slug`
- `docs/short-slug`
- `chore/short-slug`
- `codex/feature/short-slug`
- `codex/fix/short-slug`
- `codex/docs/short-slug`
- `codex/chore/short-slug`
Example:
```bash
git switch -c fix/reply-editor-stuck
git switch -c codex/fix/reply-editor-stuck
```
### 4. Review diffs for relevance