mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-08-27 23:33:31 +02:00
Redesign the AI issue-triage pipeline so it can fix confidently on its own, ask for approval only when unsure, and always yield to manual actions — while staying cheap and fast. - Tier 2 (daily_ai_fix) becomes graded: high-confidence small fixes open a READY-for-review PR; anything medium/large gets a full Opus-written plan comment (ai:plan-pending) instead of a PR. - New Tier 3 (on_issue_approved): maintainer adds ai:approved and the posted plan is executed on Opus into a ready PR — immediate, zero cost until asked. - New @claude interactive workflow (on_claude_mention): maintainer-only, Sonnet-low, full precedence over the automated tiers. - New CodeRabbit follow-up (on_pr_coderabbit): one-shot Sonnet pass that fixes or replies to CodeRabbit's review of an ai-fix/* PR. - Tier 1 self-healing: a reporter's reply to a needs-info request re-runs classification exactly once (ai:needs-info); a daily catch-up re-dispatches any issue that never got triaged. - Extras: global kill switch (repo var AI_DISABLED), stale-bot exemption for AI labels, shared ai_guard_paths.sh, track_progress on the Opus tiers, CLAUDE.md documentation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54 lines
2.4 KiB
Bash
Executable File
54 lines
2.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Destination: .github/scripts/ai_guard_paths.sh
|
|
#
|
|
# Belt-and-braces enforcement of the one rule every AI fix prompt is told
|
|
# never to break: no add-on fix may touch `.github/` or `.templates/`, because
|
|
# those are inherited by all 100+ add-ons — a change there is a repo-wide
|
|
# incident, not a per-add-on fix. The prompts forbid it; this script is what
|
|
# actually enforces it after the model finishes, on the PRs it opened.
|
|
#
|
|
# Any AI PR that touches a protected path is pulled out of review (converted
|
|
# back to draft), labelled `ai:blocked`, and commented on. This is shared by
|
|
# every tier that can open or push to an `ai-fix/` PR (tiers 2 and 3, and the
|
|
# CodeRabbit follow-up) so the rule is defined and fixed in exactly one place.
|
|
#
|
|
# Env:
|
|
# GH_TOKEN (required) — token with pull-requests:write on REPO
|
|
# REPO (required) — owner/name
|
|
# PR_NUMBER (optional) — check only this PR; if unset, scan every open
|
|
# `ai-fix/` PR in the repo.
|
|
|
|
set -euo pipefail
|
|
|
|
: "${REPO:?REPO must be set}"
|
|
: "${GH_TOKEN:?GH_TOKEN must be set}"
|
|
|
|
PROTECTED='^(\.github/|\.templates/)'
|
|
|
|
if [ -n "${PR_NUMBER:-}" ]; then
|
|
PRS="$PR_NUMBER"
|
|
else
|
|
# gh pr list applies --limit before the headRefName filter, so a low cap
|
|
# could silently drop older ai-fix/ PRs once total open PRs (of any kind)
|
|
# grow past it. 300 is far above anything this repo runs; gh paginates.
|
|
PRS=$(gh pr list --repo "$REPO" --state open --limit 300 \
|
|
--json number,headRefName \
|
|
--jq '.[] | select(.headRefName|startswith("ai-fix/")) | .number')
|
|
fi
|
|
|
|
for pr in $PRS; do
|
|
[ -n "$pr" ] || continue
|
|
BAD=$(gh pr diff "$pr" --repo "$REPO" --name-only | grep -E "$PROTECTED" || true)
|
|
if [ -n "$BAD" ]; then
|
|
echo "::error::PR #$pr touches protected paths:"
|
|
echo "$BAD"
|
|
# Ensure the label exists before adding it — with set -e a missing
|
|
# label would abort the whole loop and skip any PRs behind this one.
|
|
gh label create "ai:blocked" --repo "$REPO" --color ededed >/dev/null 2>&1 || true
|
|
gh pr ready "$pr" --repo "$REPO" --undo || true
|
|
gh pr edit "$pr" --repo "$REPO" --add-label "ai:blocked"
|
|
gh pr comment "$pr" --repo "$REPO" --body \
|
|
"Blocked automatically: this PR modifies shared infrastructure (\`.github/\` or \`.templates/\`), which is inherited by every add-on in the repo. Needs manual review before it goes anywhere."
|
|
fi
|
|
done
|