From 208ae00953e88cd0d628965575f97db688f1e0a9 Mon Sep 17 00:00:00 2001 From: Timothy Date: Fri, 4 Sep 2026 23:39:20 +0200 Subject: [PATCH] =?UTF-8?q?fix(907):=20round=20four=20=E2=80=94=20a=20resu?= =?UTF-8?q?me=20that=20updated=20its=20existing=20PR=20is=20a=20success,?= =?UTF-8?q?=20and=20a=20post-push=20error=20says=20so?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_015QqCpYFsKgnAnx6jVwrKiV --- .claude/workflows/ersatztv-issue-build.js | 4 ++-- .claude/workflows/ersatztv-resume-branch.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.claude/workflows/ersatztv-issue-build.js b/.claude/workflows/ersatztv-issue-build.js index 7018bab9a..4f3eb2108 100644 --- a/.claude/workflows/ersatztv-issue-build.js +++ b/.claude/workflows/ersatztv-issue-build.js @@ -54,7 +54,7 @@ const gateFor = (port, where) => `LOCAL GATE (process.local-gate-before-push) - SPA: cd web && npm run check:api && npm run lint && npm run typecheck && npm run build && npm test. - scripts/, .claude/, .husky/, .gitea/: PYTHONPATH=. python3 -m pytest scripts/tests -q, plus ruff check and ruff format --check on any Python you touched. A new executable under scripts/ or .claude/hooks/ needs its row in docs/remote-state-inventory.md and, if it is a guard, in docs/guard-inventory.md — the suites say so. - Docs: python3 scripts/check-doc-narrative.py --diff origin/main and answer what it flags (it is advisory, the rule is not). -- Live-E2E${args.needs_e2e ? ' IS REQUIRED for this change (write path or UI)' : ' only if you changed a write path or a screen'}: ETV_UI_PORT=${port} scripts/e2e-local.sh — port ${port} is this slot's; one run at a time in this worktree; curl the endpoints, never a browser tab; when done, kill the PID the launcher printed and nothing else. The launcher's pre-flight refuses a busy port and names the holder: report that, do not pick another port and never kill the holder. +- Live-E2E${args.needs_e2e ? ' IS REQUIRED for this change (write path or UI)' : ' only if you changed a write path or a screen'}: ETV_UI_PORT=${port} scripts/e2e-local.sh — port ${port} is yours; one run at a time in that worktree; curl the endpoints, never a browser tab; when done, kill the PID the launcher printed and nothing else. The launcher's pre-flight refuses a busy port and names the holder: report that, do not pick another port and never kill the holder. - Builds on this Mac are capped at 3–4 concurrent and other slots are building too: run the .NET and web gates sequentially, not in parallel with each other.` const GATE = gateFor(args.port, WT) @@ -193,7 +193,7 @@ ${WORKTREE} You are the finisher. The branch has passed its review loop (${round} round(s)); nothing is pushed yet. ${FINISH}`, { label: `land:${REF}`, model: 'sonnet', effort: 'medium', schema: LAND_SCHEMA }) if (!land || !land.done) return { issues, error: 'finisher stopped', land, history } -if (!land.pr_url || !land.head_sha) return { issues, error: 'finisher reported done without a PR URL or head sha', land, history } +if (!land.pr_url || !land.head_sha) return { issues, error: 'finisher reported done without a PR URL or head sha — the branch may already be pushed; read its report before re-running', land, history } log(`${REF} PR: ${land.pr_url || 'none'} @ ${land.head_sha || '?'}${land.patch_changed ? ' (patch changed by the pre-push rebase)' : ''}`) let post_rebase_reviews = null if (land.patch_changed) { diff --git a/.claude/workflows/ersatztv-resume-branch.js b/.claude/workflows/ersatztv-resume-branch.js index 1b8fbb65e..e8d43ad5b 100644 --- a/.claude/workflows/ersatztv-resume-branch.js +++ b/.claude/workflows/ersatztv-resume-branch.js @@ -39,7 +39,7 @@ const gateFor = (port, where) => `LOCAL GATE (process.local-gate-before-push) - SPA: cd web && npm run check:api && npm run lint && npm run typecheck && npm run build && npm test. - scripts/, .claude/, .husky/, .gitea/: PYTHONPATH=. python3 -m pytest scripts/tests -q, plus ruff on touched Python. - Docs: python3 scripts/check-doc-narrative.py --diff origin/main. -- Live-E2E${args.needs_e2e ? ' IS REQUIRED (write path or UI)' : ' only for a write path or screen change'}: ETV_UI_PORT=${port} scripts/e2e-local.sh — port ${port} is this slot's; one run at a time in this worktree; curl, never a browser tab; kill the PID the launcher printed when done and nothing else; a busy port is reported, never taken over. +- Live-E2E${args.needs_e2e ? ' IS REQUIRED (write path or UI)' : ' only for a write path or screen change'}: ETV_UI_PORT=${port} scripts/e2e-local.sh — port ${port} is yours; one run at a time in that worktree; curl, never a browser tab; kill the PID the launcher printed when done and nothing else; a busy port is reported, never taken over. - Run the .NET and web gates sequentially; other slots are building.` const GATE = gateFor(args.port, WT) @@ -156,7 +156,7 @@ const land = await agent(`${COMMON} You are the finisher. The rebased branch has passed its review loop (${round} round(s)); nothing is pushed yet. ${FINISH}`, { label: `land:${REF}`, model: 'sonnet', effort: 'medium', schema: LAND_SCHEMA }) if (!land || !land.done) return { issues, error: 'finisher stopped', land, history } -if (!land.pr_url || !land.head_sha) return { issues, error: 'finisher reported done without a PR URL or head sha', land, history } +if (!(land.pr_url || args.pr) || !land.head_sha) return { issues, error: 'finisher reported done without a PR or head sha — the branch may already be pushed; read its report before re-running', land, history } log(`${REF} PR: ${land.pr_url || args.pr} @ ${land.head_sha || '?'}${land.patch_changed ? ' (patch changed by the pre-push rebase)' : ''}`) let post_rebase_reviews = null if (land.patch_changed) {