Context
Issue #64 publishes an approved chat workspace to a protected, server-assigned Forge branch and returns a durable publication receipt. Issue #1 adds pull requests as a general repository capability with per-repository controls.
Chat needs a safe final step that turns the published branch into a reviewable pull request. This step must use the general pull-request domain from #1 instead of introducing a chat-only pull-request implementation.
Outcome
Add a public model tool named open_pull_request that consumes a valid #64 publication receipt and creates or updates one draft pull request on the owned Forge. The tool must never accept an arbitrary source repository, source branch, or remote from the model.
Tool contract
Accept:
publication_receipt_ref: The durable receipt returned by publish_changes.
title: The pull-request title.
body: The pull-request description.
draft: An optional Boolean that defaults to true.
Derive the repository, head branch, head OID, and permitted base branch from the receipt and repository policy. Default the base to the repository's default branch. Allow another base only when repository policy explicitly permits it.
Return:
- The repository and pull-request number.
- The Forge pull-request URL.
- The draft or open state.
- The head branch, base branch, and current head OID.
- The publication and pull-request receipt references.
- The current checks or mergeability state when available.
Pull-request behavior
- Create one draft pull request from the agent publication branch into the allowed base branch.
- Reuse and update the same open pull request for later publications from that branch. A retry must not create a duplicate.
- Verify that the Forge head ref still matches the publication receipt before creating or updating the pull request. Reject a stale, moved, or mismatched receipt.
- Use the general pull-request service, API, authorization rules, and repository switch from #1. Do not add a private chat-only pull-request table or engine.
- Add a changed-file summary and relevant publication receipts to the pull-request body. Include a linked issue when the conversation has an unambiguous issue reference. Do not include reasoning, prompts, credentials, or private tool output.
- Update the existing pull request when a later
publish_changes call advances its head branch. Report the new head OID and check state to chat and the API.
- When pull requests are disabled, return a typed
pull_requests_disabled result with the protected branch and compare URL. Never fall back to pushing the default branch.
- Do not auto-merge, force-push, close an issue, or mutate the default branch. Those actions require separate policy and authority.
Authority and policy
- Require current repository membership, the valid branch publication receipt, and pull-request write authority.
- Apply the per-repository pull-request enable switch from #1.
- Treat pull-request creation as an external effect. Require explicit approval unless repository policy grants the user a durable, revocable permission for draft pull requests from agent-owned branches.
- Refuse a receipt from another conversation, account, repository, or branch. Refuse cross-repository heads until the general pull-request system explicitly supports them.
- Keep Forge credentials in the server-side service. Never expose them to the model, shell, or workspace.
Chat and API behavior
- Render the pull-request tool with the shared tool components, including approval, draft or open state, head and base, checks, URL, duration, receipts, and typed errors.
- Persist the ordered pull-request lifecycle with the conversation.
- Publish the same lifecycle and result through the account API so browser and programmatic clients have parity.
- Let clients retry with the same publication receipt and receive the existing pull request.
Acceptance criteria
- A valid #64 publication receipt creates a draft pull request through the general #1 pull-request service.
- Retrying the same request returns the same pull request without creating a duplicate.
- Publishing another commit to the same agent branch updates the existing pull request and its reported head OID.
- Tests prove that the tool cannot select another source branch, repository, remote, unauthorized base, or stale receipt.
- A repository with pull requests disabled returns
pull_requests_disabled, the protected branch, and a compare URL without mutating the default branch.
- Browser and API tests expose the same lifecycle, URL, head OID, and receipt references.
- An integration test exercises the tool through a captured or live-compatible Ox Alpha Responses tool sequence.
mix precommit passes.
Dependencies
- #1 provides the general pull-request capability and per-repository controls.
- #64 provides the protected Forge branch and durable publication receipt.
- #61 provides the shared chat tool runtime and authority boundary.
Context
Issue #64 publishes an approved chat workspace to a protected, server-assigned Forge branch and returns a durable publication receipt. Issue #1 adds pull requests as a general repository capability with per-repository controls.
Chat needs a safe final step that turns the published branch into a reviewable pull request. This step must use the general pull-request domain from #1 instead of introducing a chat-only pull-request implementation.
Outcome
Add a public model tool named
open_pull_requestthat consumes a valid #64 publication receipt and creates or updates one draft pull request on the owned Forge. The tool must never accept an arbitrary source repository, source branch, or remote from the model.Tool contract
Accept:
publication_receipt_ref: The durable receipt returned bypublish_changes.title: The pull-request title.body: The pull-request description.draft: An optional Boolean that defaults totrue.Derive the repository, head branch, head OID, and permitted base branch from the receipt and repository policy. Default the base to the repository's default branch. Allow another base only when repository policy explicitly permits it.
Return:
Pull-request behavior
publish_changescall advances its head branch. Report the new head OID and check state to chat and the API.pull_requests_disabledresult with the protected branch and compare URL. Never fall back to pushing the default branch.Authority and policy
Chat and API behavior
Acceptance criteria
pull_requests_disabled, the protected branch, and a compare URL without mutating the default branch.mix precommitpasses.Dependencies