Publish chat workspace changes to protected Forge branches #64

Closed AtlantisPleb opened this 1d ago 1 comment

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
  1. AtlantisPleb opened this issue 1d ago
  2. A AtlantisPleb Author 1d ago

    Implemented the approved chat workspace publication workflow in commit e98c9c5. The publish_changes tool now derives the repository, remote, and stable opaque branch on the server; stages the full workspace through an isolated Git index; creates deterministic commits; enforces membership, repository.write, and explicit approval; uses force-with-lease; reconciles uncertain pushes against the Forge WAL; and persists an idempotent publication ledger with exact receipts. Added architecture documentation, migration lineage, and focused tests. Verification: mix precommit passed with 2,157 backend tests, 15 excluded, and 17 frontend tests.

  3. closed this as completed 1d ago
Sign in with GitHub to comment on this issue.