@@ -176,14 +176,14 @@ jobs:
176176 with :
177177 gpg-private-key : ${{ secrets.BOT_GPG_PRIVATE_KEY }}
178178
179- - name : Run updating skill with Claude Code
180- id : claude
181- timeout-minutes : 15
179+ - name : Update dependencies (haiku — fast, cheap)
180+ id : update
181+ timeout-minutes : 10
182+ shell : bash
182183 env :
183184 ANTHROPIC_API_KEY : ${{ secrets.ANTHROPIC_API_KEY }}
184185 GITHUB_ACTIONS : ' true'
185186 run : |
186- # Wrap pnpm through Socket firewall for all subprocesses (not just this shell).
187187 if [ -n "$SFW_BIN" ]; then
188188 mkdir -p /tmp/sfw-bin
189189 printf '#!/bin/bash\nexec "%s" pnpm "$@"\n' "$SFW_BIN" > /tmp/sfw-bin/pnpm
@@ -199,9 +199,12 @@ jobs:
199199
200200 set +e
201201 claude --print \
202- --allowedTools "Bash(pnpm:*)" "Bash(git:*)" "Read" "Write" "Edit" "Glob" "Grep" \
203- --model sonnet \
204- --max-turns 25 \
202+ --model haiku \
203+ --max-turns 15 \
204+ --allowedTools \
205+ "Bash(pnpm:*)" \
206+ "Bash(git add:*)" "Bash(git commit:*)" "Bash(git status:*)" "Bash(git diff:*)" "Bash(git log:*)" "Bash(git rev-parse:*)" \
207+ "Read" "Write" "Edit" "Glob" "Grep" \
205208 "$(cat <<'PROMPT'
206209 /updating
207210
@@ -215,7 +218,7 @@ jobs:
215218 Update all dependencies to their latest versions, including npm packages and upstream submodule pins.
216219 Create one atomic commit per dependency update with a conventional commit message.
217220 Leave all changes local — the workflow handles pushing and PR creation.
218- Skip running builds, tests, and type checks — CI runs those separately .
221+ Do not run builds or tests — the next step handles that .
219222 </instructions>
220223
221224 <success_criteria>
@@ -235,15 +238,109 @@ jobs:
235238 echo "success=false" >> $GITHUB_OUTPUT
236239 fi
237240
241+ - name : Run tests
242+ id : tests
243+ if : steps.update.outputs.success == 'true'
244+ shell : bash
245+ run : |
246+ if [ -n "$SFW_BIN" ]; then
247+ mkdir -p /tmp/sfw-bin
248+ printf '#!/bin/bash\nexec "%s" pnpm "$@"\n' "$SFW_BIN" > /tmp/sfw-bin/pnpm
249+ chmod +x /tmp/sfw-bin/pnpm
250+ export PATH="/tmp/sfw-bin:$PATH"
251+ fi
252+
253+ BUILD_EXIT=0
254+ pnpm run build 2>&1 | tee build-output.log || BUILD_EXIT=$?
255+
256+ TEST_EXIT=0
257+ pnpm test 2>&1 | tee test-output.log || TEST_EXIT=$?
258+
259+ if [ "$BUILD_EXIT" -eq 0 ] && [ "$TEST_EXIT" -eq 0 ]; then
260+ echo "tests-passed=true" >> $GITHUB_OUTPUT
261+ else
262+ echo "tests-passed=false" >> $GITHUB_OUTPUT
263+ fi
264+
265+ - name : Fix test failures (sonnet — smarter, escalated)
266+ id : claude
267+ if : steps.update.outputs.success == 'true' && steps.tests.outputs.tests-passed == 'false'
268+ timeout-minutes : 15
269+ shell : bash
270+ env :
271+ ANTHROPIC_API_KEY : ${{ secrets.ANTHROPIC_API_KEY }}
272+ GITHUB_ACTIONS : ' true'
273+ run : |
274+ if [ -n "$SFW_BIN" ]; then
275+ mkdir -p /tmp/sfw-bin
276+ printf '#!/bin/bash\nexec "%s" pnpm "$@"\n' "$SFW_BIN" > /tmp/sfw-bin/pnpm
277+ chmod +x /tmp/sfw-bin/pnpm
278+ export PATH="/tmp/sfw-bin:$PATH"
279+ fi
280+
281+ FAILURE_LOG=""
282+ if [ -f build-output.log ]; then
283+ FAILURE_LOG+="=== BUILD OUTPUT (last 50 lines) ==="$'\n'
284+ FAILURE_LOG+="$(tail -50 build-output.log)"$'\n\n'
285+ fi
286+ if [ -f test-output.log ]; then
287+ FAILURE_LOG+="=== TEST OUTPUT (last 100 lines) ==="$'\n'
288+ FAILURE_LOG+="$(tail -100 test-output.log)"$'\n'
289+ fi
290+
291+ set +e
292+ claude --print \
293+ --model sonnet \
294+ --max-turns 25 \
295+ --allowedTools \
296+ "Bash(pnpm:*)" \
297+ "Bash(git add:*)" "Bash(git commit:*)" "Bash(git status:*)" "Bash(git diff:*)" "Bash(git log:*)" "Bash(git rev-parse:*)" \
298+ "Read" "Write" "Edit" "Glob" "Grep" \
299+ "$(cat <<PROMPT
300+ Build or tests failed after dependency updates. Fix them.
301+
302+ <failure_output>
303+ $FAILURE_LOG
304+ </failure_output>
305+
306+ <instructions>
307+ Diagnose the failure from the logs above.
308+ Fix the code — do not revert dependency updates.
309+ Re-run the failing build or tests to confirm the fix.
310+ Commit all fixes with conventional commit messages.
311+ </instructions>
312+ PROMPT
313+ )" \
314+ 2>&1 | tee -a claude-output.log
315+ CLAUDE_EXIT=${PIPESTATUS[0]}
316+ set -e
317+
318+ if [ "$CLAUDE_EXIT" -eq 0 ]; then
319+ echo "success=true" >> $GITHUB_OUTPUT
320+ else
321+ echo "success=false" >> $GITHUB_OUTPUT
322+ fi
323+
324+ - name : Set final status
325+ id : final
326+ if : always()
327+ run : |
328+ if [ "${{ steps.update.outputs.success }}" = "true" ] && \
329+ ( [ "${{ steps.tests.outputs.tests-passed }}" = "true" ] || [ "${{ steps.claude.outputs.success }}" = "true" ] ); then
330+ echo "success=true" >> $GITHUB_OUTPUT
331+ else
332+ echo "success=false" >> $GITHUB_OUTPUT
333+ fi
334+
238335 - name : Validate changes
239336 id : validate
240- if : steps.claude .outputs.success == 'true'
337+ if : steps.final .outputs.success == 'true'
241338 run : |
242- # Only allow changes to dependency-related files.
243339 UNEXPECTED=""
244340 for file in $(git diff --name-only origin/main..HEAD); do
245341 case "$file" in
246342 package.json|*/package.json|pnpm-lock.yaml|*/pnpm-lock.yaml|.npmrc|pnpm-workspace.yaml) ;;
343+ src/*|test/*|*.ts|*.mts|*.js|*.mjs) ;;
247344 *) UNEXPECTED="$UNEXPECTED $file" ;;
248345 esac
249346 done
@@ -264,13 +361,13 @@ jobs:
264361 fi
265362
266363 - name : Push branch
267- if : steps.claude .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
364+ if : steps.final .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
268365 env :
269366 BRANCH_NAME : ${{ steps.branch.outputs.branch }}
270367 run : git push origin "$BRANCH_NAME"
271368
272369 - name : Create Pull Request
273- if : steps.claude .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
370+ if : steps.final .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
274371 env :
275372 GH_TOKEN : ${{ github.token }}
276373 UPDATE_SUMMARY_B64 : ${{ needs.check-updates.outputs.update-summary }}
@@ -312,7 +409,7 @@ jobs:
312409 --base main
313410
314411 - name : Add job summary
315- if : steps.claude .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
412+ if : steps.final .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
316413 env :
317414 UPDATE_SUMMARY_B64 : ${{ needs.check-updates.outputs.update-summary }}
318415 BRANCH_NAME : ${{ steps.branch.outputs.branch }}
@@ -341,7 +438,10 @@ jobs:
341438 uses : actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
342439 with :
343440 name : claude-output-${{ github.run_id }}
344- path : claude-output.log
441+ path : |
442+ claude-output.log
443+ build-output.log
444+ test-output.log
345445 retention-days : 7
346446
347447 - uses : SocketDev/socket-registry/.github/actions/cleanup-git-signing@6096b06b1790f411714c89c40f72aade2eeaab7c # main
0 commit comments