Context
Issues #61, #62, and #63 give a chat an isolated repository workspace and the tools to read, change, and test it. Those changes need a durable publication path.
OpenAgents already has OpenAgents.Tools.RepoCommitPush. It stages all changes in a coding job checkout, creates a commit, and pushes only to that job's fixed openagents/job-<id> branch on the owned Forge. The Forge records the push in its write-ahead log, and the tool returns the commit and branch receipts.
The current implementation is tied to one configured repository and a coding job context. It is not yet a repository-generic chat tool.
Outcome
Add a public model tool named publish_changes that commits an approved chat workspace and pushes it to a server-assigned branch on the selected OpenAgents Forge repository. Keep the existing low-level repo_commit_push behavior behind a shared publication service.
Publishing a branch must never update the default branch, an operator branch, a GitHub mirror, or a model-supplied ref.
Tool contract
Accept:
message: The commit message.
expected_workspace_digest: The optional digest that the model or client last observed.
Derive the repository, remote, source commit, and destination branch from the authenticated conversation workspace. Do not accept those values from the model.
Return:
- The Forge repository identity.
- The server-assigned branch.
- The source and published commit OIDs.
- The changed-file and line summary.
- A Forge compare URL.
- The durable commit, branch, push, and effect receipt references.
Publication behavior
- Assign one stable, opaque publication branch to each repository workspace, such as
openagents/chat/<opaque-run-id>. Do not put prompts, user input, or secrets in branch names.
- Re-read the workspace and reject a stale
expected_workspace_digest before staging files.
- Reject an empty commit with a typed
nothing_to_publish result.
- Stage the complete workspace change, commit with an auditable OpenAgents agent identity, and push only to the assigned branch.
- Protect retries with an idempotency key and a force-with-lease equivalent. Never overwrite a branch that advanced outside the current publication receipt.
- Record the Forge WAL acknowledgment before reporting success.
- Preserve the local commit and an uncertain result when the remote outcome cannot be proven. Reconcile the branch before retrying.
- Update the repository activity timestamp and publish branch activity only after the Forge accepts a ref-changing push.
Authority and policy
- Require current repository membership,
repository.write, the workspace's mutation receipts, and the repository's agent-publication policy.
- Treat the push as an external effect. Require explicit approval unless repository policy grants the user a durable, revocable permission for agent-owned branches.
- Scope the Forge credential to one repository and one server-assigned branch. Never give the model, shell, or workspace the credential.
- Keep the canonical repository and GitHub mirror read-only to the workspace. The Forge push service performs the external effect.
- Redact remote credentials, environment secrets, and private repository metadata from logs and tool results.
Chat and API behavior
- Render approval, commit, push, reconciliation, and terminal states with the shared tool components.
- Persist the exact tool call, commit message, diff summary, branch, OIDs, receipts, duration, and typed failure with the conversation.
- Publish the same ordered lifecycle through the account API.
- Return a branch and compare link even when pull requests are disabled for the repository.
- Let the later pull-request tool consume the publication receipt instead of trusting model-supplied branch data.
Acceptance criteria
- A chat workspace based on a connected Forge repository can publish one commit to its assigned agent branch.
- Tests prove that the tool refuses the default branch, another conversation's branch, another repository, GitHub, an arbitrary remote, and a stale workspace digest.
- A duplicate request returns the original publication result and does not create another commit or push.
- A concurrent remote update causes a lease failure and never loses the remote commit.
- A lost response after Forge acceptance reconciles to the accepted push instead of duplicating it.
- The result includes the accepted commit OID and the Forge WAL-backed push receipt.
- Browser and API tests show the same publication state and receipts.
mix precommit passes.
Dependencies
- #61 provides the shared chat tool runtime and authority boundary.
- #62 provides the file mutation tools and workspace snapshots.
- Pull-request publication remains separate and depends on #1.
References
lib/openagents/tools/repo_commit_push.ex
lib/openagents/tools/repository.ex
test/openagents/tools/repository_mutation_tools_test.exs
docs/scv-planning.md
Context
Issues #61, #62, and #63 give a chat an isolated repository workspace and the tools to read, change, and test it. Those changes need a durable publication path.
OpenAgents already has
OpenAgents.Tools.RepoCommitPush. It stages all changes in a coding job checkout, creates a commit, and pushes only to that job's fixedopenagents/job-<id>branch on the owned Forge. The Forge records the push in its write-ahead log, and the tool returns the commit and branch receipts.The current implementation is tied to one configured repository and a coding job context. It is not yet a repository-generic chat tool.
Outcome
Add a public model tool named
publish_changesthat commits an approved chat workspace and pushes it to a server-assigned branch on the selected OpenAgents Forge repository. Keep the existing low-levelrepo_commit_pushbehavior behind a shared publication service.Publishing a branch must never update the default branch, an operator branch, a GitHub mirror, or a model-supplied ref.
Tool contract
Accept:
message: The commit message.expected_workspace_digest: The optional digest that the model or client last observed.Derive the repository, remote, source commit, and destination branch from the authenticated conversation workspace. Do not accept those values from the model.
Return:
Publication behavior
openagents/chat/<opaque-run-id>. Do not put prompts, user input, or secrets in branch names.expected_workspace_digestbefore staging files.nothing_to_publishresult.Authority and policy
repository.write, the workspace's mutation receipts, and the repository's agent-publication policy.Chat and API behavior
Acceptance criteria
mix precommitpasses.Dependencies
References
lib/openagents/tools/repo_commit_push.exlib/openagents/tools/repository.extest/openagents/tools/repository_mutation_tools_test.exsdocs/scv-planning.md