Skip to content

Commit 853e278

Browse files
committed
Merge remote-tracking branch 'fork/dev' into feature/poe2-build-export-improved
# Conflicts: # src/Modules/Build.lua # src/TreeData/0_4/tree.json
2 parents f4c216f + a854ee5 commit 853e278

82 files changed

Lines changed: 5007 additions & 3166 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.busted

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
return {
22
_all = {
3-
coverage = false,
3+
coverage = true,
44
verbose = true,
55
},
66
default = {
77
directory = "src",
88
lpath = "../runtime/lua/?.lua;../runtime/lua/?/init.lua",
99
helper = "HeadlessWrapper.lua",
1010
ROOT = { "../spec" },
11-
["exclude-tags"] = "builds",
1211
}
1312
}

.github/ISSUE_TEMPLATE/ai_fix.yaml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: AI fix request
2+
description: Report a well-scoped bug or task for the AI agent to fix automatically.
3+
labels: [ai-fix]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Issues with this template are automatically picked up by the AI agent when labelled **ai-fix**.
9+
Keep the description concrete and focused — the agent works best with a single, well-defined task.
10+
11+
- type: checkboxes
12+
id: scope
13+
attributes:
14+
label: Confirm scope
15+
options:
16+
- label: This is a single, well-scoped task (not a broad refactor or multi-feature request)
17+
required: true
18+
- label: I've checked there are no open PRs already addressing this
19+
required: true
20+
21+
- type: textarea
22+
id: description
23+
attributes:
24+
label: What needs to be fixed or done?
25+
description: Be specific. Include file names, function names, or error messages where possible.
26+
placeholder: |
27+
e.g. The Boneshatter damage calculation in `src/Modules/CalcOffence.lua` does not account for
28+
the stun threshold modifier added in 0.2.0. Expected value: X, actual value: Y.
29+
validations:
30+
required: true
31+
32+
- type: textarea
33+
id: acceptance
34+
attributes:
35+
label: Acceptance criteria
36+
description: How will you know the fix is correct? What should the tests verify?
37+
placeholder: |
38+
- Calculation matches expected value from PoE2 tooltip
39+
- Existing busted tests still pass
40+
- New test added covering the stun threshold case
41+
validations:
42+
required: true
43+
44+
- type: textarea
45+
id: build_code
46+
attributes:
47+
label: PoB build code (if relevant)
48+
description: A build code that reproduces the issue helps the agent verify the fix.
49+
render: shell
50+
validations:
51+
required: false
52+
53+
- type: textarea
54+
id: context
55+
attributes:
56+
label: Additional context
57+
description: Screenshots, error messages, or links to PoE2 patch notes.
58+
validations:
59+
required: false

.github/tweak_changelogs.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ sed -i 's/\[learn2draw/\[Lexy/' temp_change.md
3737
sed -i 's/\[Voronoff/\[Tom Clancy Is Dead/' temp_change.md
3838
sed -i 's/\[PJacek/\[TPlant/' temp_change.md
3939
sed -i 's/\[justjuangui/\[trompetin17/' temp_change.md
40+
sed -i 's/\[krryan/\[DragoonWraith/' temp_change.md
4041

4142
cp temp_change.md changelog_temp.txt
4243
# Append existing CHANGELOG.md content (excluding first line) to temp_change.md

.github/workflows/ai-fix.yml

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
name: AI Fix
2+
on:
3+
issues:
4+
types: [labeled]
5+
6+
jobs:
7+
apply-fix:
8+
if: github.event.label.name == 'ai-fix'
9+
runs-on: ubuntu-latest
10+
timeout-minutes: 60
11+
permissions:
12+
contents: write
13+
issues: write
14+
env:
15+
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
16+
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
17+
EMERGENCY_ANTHROPIC_API_KEY: ${{ secrets.EMERGENCY_ANTHROPIC_API_KEY }}
18+
outputs:
19+
branch: ${{ steps.push.outputs.branch }}
20+
issue_num: ${{ steps.meta.outputs.issue_num }}
21+
issue_title: ${{ steps.meta.outputs.issue_title }}
22+
steps:
23+
- uses: actions/checkout@v4
24+
with:
25+
ref: dev
26+
fetch-depth: 0
27+
28+
- name: Verify ANTHROPIC_API_KEY is NOT set
29+
run: |
30+
if [[ -n "${ANTHROPIC_API_KEY:-}" ]]; then
31+
echo "::error::ANTHROPIC_API_KEY is set; would override Pro subscription auth and incur PAYG charges"
32+
exit 1
33+
fi
34+
35+
- name: Extract issue metadata
36+
id: meta
37+
run: |
38+
echo "issue_num=$(jq -r '.issue.number' "$GITHUB_EVENT_PATH")" >> "$GITHUB_OUTPUT"
39+
echo "issue_title=$(jq -r '.issue.title' "$GITHUB_EVENT_PATH")" >> "$GITHUB_OUTPUT"
40+
41+
- name: Install agent tooling if missing
42+
run: |
43+
command -v claude || npm install -g @anthropic-ai/claude-code
44+
command -v opencode || curl -fsSL https://opencode.ai/install | bash
45+
46+
- name: Checkout or create fix branch
47+
id: branch_setup
48+
run: |
49+
BRANCH="ai-fix/issue-${{ steps.meta.outputs.issue_num }}"
50+
echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
51+
52+
if git ls-remote --exit-code --heads origin "$BRANCH" > /dev/null 2>&1; then
53+
echo "is_retry=true" >> "$GITHUB_OUTPUT"
54+
echo "Branch $BRANCH exists — checking out for retry"
55+
git checkout -b "$BRANCH" "origin/$BRANCH"
56+
else
57+
echo "is_retry=false" >> "$GITHUB_OUTPUT"
58+
echo "Branch $BRANCH does not exist — creating fresh from dev"
59+
git checkout -b "$BRANCH"
60+
fi
61+
62+
- name: Build agent prompt
63+
run: |
64+
ISSUE_BODY=$(jq -r '.issue.body' "$GITHUB_EVENT_PATH")
65+
66+
# If resuming an existing branch, include prior commit context so the
67+
# agent knows what was already attempted and can build on or correct it
68+
RETRY_CONTEXT=""
69+
if [[ "${{ steps.branch_setup.outputs.is_retry }}" == "true" ]]; then
70+
PREV_COMMITS=$(git log "origin/dev..HEAD" --oneline 2>/dev/null || echo "none")
71+
RETRY_CONTEXT="
72+
NOTE: A previous fix attempt exists on this branch. Prior commits:
73+
${PREV_COMMITS}
74+
75+
Review the existing changes and either build on them or correct them.
76+
Do not revert work that is already correct."
77+
fi
78+
79+
cat > /tmp/fix-prompt.txt << PROMPT_EOF
80+
You are resolving GitHub issue #${{ steps.meta.outputs.issue_num }} in jay9297/PathOfBuilding-PoE2.
81+
82+
Title: ${{ steps.meta.outputs.issue_title }}
83+
84+
Body:
85+
${ISSUE_BODY}
86+
${RETRY_CONTEXT}
87+
88+
Follow the rules in CLAUDE.md. Make the minimal correct change.
89+
Add or update tests to cover your fix. Do NOT run tests yourself.
90+
PROMPT_EOF
91+
92+
- name: Run AI agent
93+
run: |
94+
source scripts/agent-lib.sh
95+
run_agent_with_fallback /tmp/fix-prompt.txt fix 80
96+
97+
- name: Commit and push branch
98+
id: push
99+
run: |
100+
BRANCH="${{ steps.branch_setup.outputs.branch }}"
101+
git config user.name "ai-agent[bot]"
102+
git config user.email "ai-agent@users.noreply.github.com"
103+
git add -A
104+
105+
if git diff --cached --quiet; then
106+
# Agent made no new changes — check if prior work already exists on the branch
107+
AHEAD=$(git rev-list --count "origin/dev..HEAD" 2>/dev/null || echo "0")
108+
if [[ "${{ steps.branch_setup.outputs.is_retry }}" == "true" && "$AHEAD" -gt 0 ]]; then
109+
echo "Agent made no new changes but branch has $AHEAD existing commit(s) — proceeding with existing work"
110+
echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
111+
exit 0
112+
fi
113+
echo "::error::No changes produced by agent and no existing commits on branch"
114+
exit 1
115+
fi
116+
117+
git commit -m "fix: resolve issue #${{ steps.meta.outputs.issue_num }}
118+
119+
Generated by AI agent. Requires human review before merge."
120+
121+
source scripts/agent-lib.sh
122+
retry_op 5 10 git push -u origin "$BRANCH"
123+
echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
124+
125+
- name: Post failure comment
126+
if: failure()
127+
env:
128+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
129+
run: |
130+
source scripts/agent-lib.sh
131+
retry_op 3 10 gh issue comment ${{ steps.meta.outputs.issue_num }} \
132+
--body "⚠️ **AI Fix Failed**
133+
134+
The \`apply-fix\` job failed after exhausting all agent tiers and retry cycles.
135+
This likely indicates an API outage or expired credentials.
136+
137+
**What to check:**
138+
- \`CLAUDE_CODE_OAUTH_TOKEN\` — is the Pro subscription active?
139+
- \`OPENCODE_API_KEY\` — is the key valid?
140+
- \`EMERGENCY_ANTHROPIC_API_KEY\` — set this secret for last-resort fallback.
141+
142+
Re-add the \`ai-fix\` label once credentials are restored to retry." || true
143+
144+
verify-and-fix:
145+
needs: apply-fix
146+
runs-on: ubuntu-latest
147+
timeout-minutes: 90
148+
permissions:
149+
contents: write
150+
env:
151+
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
152+
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
153+
EMERGENCY_ANTHROPIC_API_KEY: ${{ secrets.EMERGENCY_ANTHROPIC_API_KEY }}
154+
steps:
155+
- uses: actions/checkout@v4
156+
with:
157+
ref: ${{ needs.apply-fix.outputs.branch }}
158+
fetch-depth: 0
159+
160+
- name: Configure git
161+
run: |
162+
git config user.name "ai-agent[bot]"
163+
git config user.email "ai-agent@users.noreply.github.com"
164+
165+
- name: Install agent tooling if missing
166+
run: |
167+
command -v claude || npm install -g @anthropic-ai/claude-code
168+
command -v opencode || curl -fsSL https://opencode.ai/install | bash
169+
170+
- name: Cache test image
171+
id: image-cache
172+
uses: actions/cache@v4
173+
with:
174+
path: /tmp/pob-test-image.tar
175+
key: pob-test-image-${{ hashFiles('docker-compose.yml') }}
176+
restore-keys: pob-test-image-
177+
178+
- name: Pull or restore image
179+
run: |
180+
if [[ "${{ steps.image-cache.outputs.cache-hit }}" == "true" ]]; then
181+
docker load < /tmp/pob-test-image.tar
182+
else
183+
docker pull ghcr.io/pathofbuildingcommunity/pathofbuilding-tests:latest
184+
docker save ghcr.io/pathofbuildingcommunity/pathofbuilding-tests:latest \
185+
-o /tmp/pob-test-image.tar
186+
fi
187+
188+
# Separated into its own step — no ${{ }} expressions here so the heredoc
189+
# delimiter is never mangled by GitHub Actions' format() evaluator
190+
- name: Build verify-fix prompt template
191+
run: |
192+
cat > /tmp/verify-fix-prompt-template.txt << 'PROMPT_EOF'
193+
The AI agent previously made changes to fix a GitHub issue, but the test
194+
suite is now failing. Fix the failing tests without reverting the original
195+
fix. Make the minimal change needed. Follow CLAUDE.md.
196+
197+
Failing test output:
198+
PROMPT_EOF
199+
200+
- name: Verify and auto-fix loop
201+
run: |
202+
source scripts/agent-lib.sh
203+
204+
MAX_RETRIES=3
205+
ATTEMPT=0
206+
207+
run_tests() {
208+
local output_file="$1"
209+
local failed=0
210+
echo "--- unit ---" | tee -a "$output_file"
211+
docker compose run --rm busted-tests --exclude-tags builds,data \
212+
2>&1 | tee -a "$output_file" || failed=1
213+
echo "--- builds ---" | tee -a "$output_file"
214+
docker compose run --rm busted-tests --tags builds \
215+
2>&1 | tee -a "$output_file" || failed=1
216+
echo "--- data ---" | tee -a "$output_file"
217+
docker compose run --rm busted-tests --tags data \
218+
2>&1 | tee -a "$output_file" || failed=1
219+
return $failed
220+
}
221+
222+
while [ $ATTEMPT -lt $MAX_RETRIES ]; do
223+
ATTEMPT=$((ATTEMPT + 1))
224+
OUTPUT_FILE="/tmp/test-output-attempt-${ATTEMPT}.txt"
225+
> "$OUTPUT_FILE"
226+
227+
echo "::group::Test attempt $ATTEMPT of $MAX_RETRIES"
228+
if run_tests "$OUTPUT_FILE"; then
229+
echo "✅ Tests passed on attempt $ATTEMPT"
230+
echo "::endgroup::"
231+
exit 0
232+
fi
233+
echo "::endgroup::"
234+
echo "::warning::Tests failed on attempt $ATTEMPT"
235+
236+
cp "$OUTPUT_FILE" "/tmp/test-failures-attempt-${ATTEMPT}.txt"
237+
238+
if [ $ATTEMPT -ge $MAX_RETRIES ]; then
239+
echo "::error::Tests still failing after $MAX_RETRIES fix attempts"
240+
exit 1
241+
fi
242+
243+
# Rebuild prompt fresh each iteration with the latest failure output
244+
cp /tmp/verify-fix-prompt-template.txt /tmp/verify-fix-prompt-current.txt
245+
cat "$OUTPUT_FILE" >> /tmp/verify-fix-prompt-current.txt
246+
247+
echo "🤖 Running agent to fix test failures (attempt $ATTEMPT)..."
248+
run_agent_with_fallback /tmp/verify-fix-prompt-current.txt fix 20
249+
250+
if git diff --quiet && git diff --cached --quiet; then
251+
echo "::error::Agent produced no changes — cannot recover from test failures"
252+
exit 1
253+
fi
254+
255+
git add -A
256+
retry_op 5 10 git commit -m "fix(tests): address failures — attempt $ATTEMPT [ai-agent]
257+
258+
Issue: #${{ needs.apply-fix.outputs.issue_num }}"
259+
retry_op 5 10 git push
260+
done
261+
262+
- name: Upload test failure logs
263+
if: failure()
264+
uses: actions/upload-artifact@v4
265+
with:
266+
name: test-failures-issue-${{ needs.apply-fix.outputs.issue_num }}
267+
path: /tmp/test-failures-attempt-*.txt
268+
retention-days: 7
269+
270+
open-pr:
271+
needs: [apply-fix, verify-and-fix]
272+
runs-on: ubuntu-latest
273+
timeout-minutes: 10
274+
permissions:
275+
pull-requests: write
276+
steps:
277+
- uses: actions/checkout@v4
278+
with:
279+
ref: ${{ needs.apply-fix.outputs.branch }}
280+
281+
- name: Create pull request
282+
env:
283+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
284+
run: |
285+
source scripts/agent-lib.sh
286+
287+
# If a PR already exists for this branch (from a previous run), skip creation
288+
EXISTING_PR=$(gh pr list \
289+
--head "${{ needs.apply-fix.outputs.branch }}" \
290+
--json number --jq '.[0].number' 2>/dev/null || echo "")
291+
292+
if [[ -n "$EXISTING_PR" ]]; then
293+
echo "PR #${EXISTING_PR} already exists for this branch — skipping creation"
294+
exit 0
295+
fi
296+
297+
retry_op 5 15 gh pr create \
298+
--base dev \
299+
--head "${{ needs.apply-fix.outputs.branch }}" \
300+
--title "${{ needs.apply-fix.outputs.issue_title }}" \
301+
--body "Closes #${{ needs.apply-fix.outputs.issue_num }}
302+
303+
🤖 Generated by AI agent. Automated review will follow.
304+
Final approval required from @jay9297." \
305+
--label "ai-generated"

0 commit comments

Comments
 (0)