Repository navigation
fix(kix): continue a retried job from its published branch - #171
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new plan, start, or bootstrap job whose target's latest job failed now starts from the head, pending commit, and pull request that job recorded, the way a reassigned attempt resumes. A branch moved outside kix since still pauses on the existing publication decision. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Outcome: the quest is complete. A retry now continues the failed job's branch and PR, and a branch moved outside kix still pauses on the existing decision. (Written by Claude Opus 5.5) |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5b996d469d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| SELECT ?,id,?,?,?,?,?,?,?,?,?,'queued',?,? FROM github_projects WHERE id=? AND state='enabled' AND ${pinnable}`, | ||
| `INSERT OR IGNORE INTO jobs(id,repository,workflow,target,revision,branch,head,pending,pendingAt,pull,actor,trusted,pinRunner,pinAccount,state,createdAt,updatedAt) | ||
| SELECT ?,p.id,?,?,?,?,COALESCE(?,f.head),f.pending,f.pendingAt,f.pull,?,?,?,?,'queued',?,? FROM github_projects p | ||
| LEFT JOIN jobs f ON ?<>'iterate' AND f.state='failed' AND f.branch=? AND f.id=(SELECT id FROM jobs WHERE repository=p.id AND target=? ORDER BY createdAt DESC,id LIMIT 1) |
There was a problem hiding this comment.
Permit retrying a quest claimed by its failed job
When a failed start job has already opened the carried pull request and that PR has been observed, its quest/... branch makes readState() remove the target from project.available (cloudflare/src/github/state.ts:247-253). The inbox then suppresses “Try again” in blocked(), and the jobs POST would also reject it in resolve() (cloudflare/src/inbox/page.tsx:258-261, cloudflare/src/jobs/routes.ts:181-186), so this new f.head/f.pull continuation is unreachable for published start jobs once occupancy has refreshed. Retry authorization needs to recognize when the claim belongs to the latest failed job rather than treating that job's own PR as unrelated.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Agreed, fixed in 2509d21. startable in cloudflare/src/github/state.ts now lets a start through when the quest is ready and its only occupant is the open pull request recorded on the target's latest failed job. The inbox (blocked) and the jobs route (resolve, via store.failedPull) both use it. An upstream branch claim or any other pull request on the quest still blocks. A regression test in cloudflare/test/inbox.test.ts covers both cases.
(Written by Claude Opus 5.5)
A failed start job that opened its pull request occupies its quest, so the inbox hid "Try again" and the jobs route refused the retry. Both now treat the target's latest failed job's open pull request as the one the retry continues, while any other claim still blocks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2509d21def
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| export async function failedPull(db: D1Database, repository: number, target: string) { | ||
| const latest = await db | ||
| .prepare("SELECT state,pull FROM jobs WHERE repository=? AND target=? ORDER BY createdAt DESC,id LIMIT 1") | ||
| .bind(repository, target) | ||
| .first<Pick<Job, "state" | "pull">>(); | ||
| return latest?.state === "failed" ? latest.pull : null; |
There was a problem hiding this comment.
Preserve unrecorded pull requests when authorizing retries
When GitHub successfully creates a pull request but the subsequent delivered() write is lost, the failed job retains pull = NULL even though reconciliation observes its open PR as a claim. Unlike the previously fixed recorded-PR case, failedPull() then returns null, so startable() rejects the retry and the job cannot use the existing delivery-reconciliation path. Authorizing a retry therefore needs to associate an observed PR on the failed job's branch even when its number was not recorded.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Leaving this one as is. Two reasons:
- Observations only record a pull request's
headRefName, not its head repository. Matching on the branch name alone would also let a retry through when a contributor's fork PR on the samequest/...branch claims the quest, which is exactly the claimstartablemust respect. - Even if authorized, the retry could not adopt that PR.
deliveronly looks up unrecorded PRs created since the current job, so a recovered PR from the failed job would still fail delivery. Fixing that means widening the lookup to earlier jobs, which is a separate change.
The case needs GitHub to create the PR and then the following D1 write to be lost, and the job to fail before its next publication re-finds it. The PR is still open and offered in the inbox as "Iterate on this PR", so the work is not stranded. I will suggest a follow-up quest to record a delivery before or with the creation, or to match observed PRs by head repository, rather than widen this PR.
(Written by Claude Opus 5.5)
# Conflicts: # quest/m0/kix/README.md
|
Merge summary:
(Written by Claude Opus 5.5) |
…es its PR A retried plan job continues the failed job's pull request (#171), but the decision section rendered only the new job's answers, so the first delivery after a retry erased the earlier rounds. Render the answers of every job on the target that delivered the same pull request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…172) * chore(quest): claim quest/m0/kix/paper-trail.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(kix): render planning decisions into PRs from recorded answers The service now writes a planning pull request's decision section from the job's answered decision questions, with a check mark on each choice and the maintainer's own words. Permission requests and account or publication questions stay out. Every prompt and answer appears only in a code span, so GitHub links no mention, reference, URL, or closing keyword in them. Each delivery re-renders the section and drops any the agent wrote, and planning assignments tell the agent not to write the trail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(kix): keep a failed planning job's decisions when a retry continues its PR A retried plan job continues the failed job's pull request (#171), but the decision section rendered only the new job's answers, so the first delivery after a retry erased the earlier rounds. Render the answers of every job on the target that delivered the same pull request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(kix): end a decision section only at a marker on its own line An untrusted prompt containing the end marker stopped the section match inside its code span when an agent copied the published body back, so the rest of the section leaked outside code spans. Code spans never start a line, so the section now ends only at an end marker on its own line, or at the end of the body. Also drop U+061C, U+200E, and U+200F with the other bidirectional controls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Completes quest/m0/kix/retry.md.
Problem
"Try again" on a failed plan, start, or bootstrap job creates a new job with
headunset. If the failed job had already published, the retry's first publication paused with "already has the branch … Delete it on GitHub to start over".Change
store.createJob(cloudflare/src/jobs/store.ts): when the target's latest job failed on the same branch, the new job starts from that job's recordedhead,pending/pendingAt, andpull, the same state a reassigned attempt resumes from. Iterations still start from the PR head. The existing fence and branch checks inpublish.tsare unchanged, so a branch moved outside kix since that head still pauses on the existing "changed outside this job" decision.A failed start job that already opened its pull request occupies its quest, so the inbox and the jobs route would refuse the retry.
startable(cloudflare/src/github/state.ts) lets a start through when the quest is ready and its only occupant is the open pull request recorded on the target's latest failed job; any other claim still blocks.Docs in
cloudflare/README.mdandcloudflare/GITHUB.mdmention retries alongside reassignment. The quest file and its entry in the kix epic are removed.Decisions (made unattended, recommended option)
deliverignores PRs opened before the job was created, and GitHub refuses a second PR from the same branch. If the maintainer closed the failed job's PR, the retry is refused with "reopen it on GitHub", the same rule a single job follows.Validation
cloudflare/test/publish.test.tscover a retry after a published checkpoint (continues the branch and the same PR), a retry with nothing published (fresh branch), and a branch moved outside kix (pauses on the decision without overwriting). Two of them fail against the previouscreateJob.cloudflare/test/inbox.test.tscovers retrying a quest claimed by its failed job's own pull request, and refusing it when another pull request claims it.just checkandjust testpass in the Nix shell.Suggested follow-ups
/quest-planfollow-up: let the maintainer pick "start over" on a blocked-branch decision so kix resets the fork branch itself. That would also cover leftover branches from completed or cancelled work.(Written by Claude Opus 5.5)