Skip to content

F: publish a finished task's pull request in production #103

Closed

Description

@mchwang

Why

After #91, the runner can execute a task, but nothing opens the task's pull request. PullRequestPublisher (runner/publish.ts) and GitBranchPusher (runner/branch-push.ts, #98, PR #101) are built and tested, but no production code constructs them or calls publish(). #91 part 1 (PR #102) builds the execution deps in runner/production.ts. #91 part 2 adds start and resume. Neither mentions publishing. So a task that finishes its last item stays running and has no PR.

Needed

  • In runner/production.ts, build PullRequestPublisher with the real gateways: GhAlreadyFixedGateway, the gh pull request gateway, and a GitBranchPusher.
  • Publish when a task's run ends:
    • All items done, task running, no active attempt: publish(identity) (ready).
    • The task moved to needs human: publish(identity, { problems }) (draft).
    • Run the publish after the run settles, with no attempt active, because assertPublishable refuses while an attempt is active.
  • Shutdown: track each in-flight publish like an ItemExecutor run. Abort it and await it before the Store closes (AGENTS.md: track an in-flight irreversible subprocess as part of shutdown). PullRequestPublisher.close() already aborts its runs.
  • Add an /api/runner action publish to retry a publish that failed or was refused (for example OpeningUnsettled, BranchPushRefused, or a GitHub error). It takes expectedStateVersion and an action ID, like the other runner actions. Show the last publish outcome in GET /api/runner.
  • Keep publishing off in demo mode, even when a github block exists (AGENTS.md: keep irreversible integrations disabled in demo mode).

Tests

  • A real Git remote (local bare repository) and fake gh gateways: a task that completes opens one PR, and the branch is at the task head.
  • A needs-human task opens a draft PR with its problems.
  • Shutdown during the push or during the PR opening: the Store closes only after the publish has settled, and the next start recovers the opening by its marker.
  • A refused publish (BranchPushRefused) leaves the task running. The publish action retries it once a person has fixed the branch.

Depends on #91 (PR #102) and #98 (PR #101).

🤖 Generated with Claude Code

Activity

  1. mchwang commented on Oct 3, 2026

    @mchwang
    ContributorAuthor

    Decisions for this issue, made 2026-10-03. Implemented in PR #110.

    1. Base branch: a new github.baseBranch, required when a runner block exists. The CLI checks it before the lock, and setUpRunner checks it before anything is created.
    2. Trigger: the task's status, once the run has settled:
      • a running task with every plan item done gets a ready publish;
      • a task in needs human, by any path (safety finding, time limit, budget expiry at admission), gets a draft publish. Its problems say what sent it there.
    3. Last publish outcome: durable. Schema v10 adds publish_outcomes, and GET /api/runner shows it as publish.last.
    4. Startup: one background publish if one is owed (a lost opening, or a finished run whose publish did not complete). The CLI starts it after it re-verifies the runner lock.

    Defaults I chose:

    Follow-ups, deliberately not done in #110:

    • Cancel during a draft opening: it can leave a cancelled task with an open draft PR. The PR is recorded, and closing it belongs to "close the draft on cancel".
    • Untracked push on a crash: the production push registers no process group, so a push running when the process crashes is not tracked. A normal shutdown aborts and awaits it.
    • Commits outside the ledger: the pushed head is snapshot.head, which may contain commits the ledger does not record. This belongs with Add pre-merge rebase and head-bound command checks #22.
    • Outcome version stamp (low confidence): the state version saved with the outcome is read at record time, not at the publish's last guarded write. No failing interleaving was found.
  2. mchwang commented on Oct 3, 2026

    @mchwang
    ContributorAuthor

    Follow-up issues for the deferred findings: #111 (close the draft on cancel), #112 (track the push's process group across a crash), #113 (publish only ledger-recorded commits; with #22), #114 (outcome version stamp, low confidence).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions