Skip to content

Branch ownership enforcement (S7) #382

Description

@vybe

Summary

Enforce the "working branches are per-instance-only" invariant to prevent silent data loss when two agents push to the same branch.

Context

Problem P5: Two Trinity agents can be configured to push to the same (repo, branch) tuple with no collision check. Force-pushes silently clobber each other — whoever pushed last wins.

Real incident: 2026-04-17, alpaca-vybe-live and alpaca-vybe-live-2 both pushed to trinity/alpaca-vybe-live/a702560e within 12 seconds. One agent's 50KB of state was silently overwritten.

Problem P7: generate_instance_id() is called at three sites with no cross-check:

  • src/backend/services/agent_service/crud.py:225
  • src/backend/routers/git.py:367
  • src/backend/services/git_service.py:405

Acceptance Criteria

Layer 0: Consolidate instance ID generation

  • Create single reserve_and_generate_instance_id(agent_name, github_repo) helper
  • Check git ls-remote to verify branch doesn't exist on remote
  • Retry up to 5x on collision
  • All three call sites use the new helper

Layer 1: Creation-time remote check

  • Covered by Layer 0

Layer 2: DB uniqueness constraint

  • Add partial UNIQUE index: UNIQUE(github_repo, working_branch) WHERE source_mode = 0
  • Migration tolerates existing duplicates (flag first, let operators resolve)
  • Pre-flight audit query to detect existing duplicates

Layer 3: Push-time guard

  • Replace git push --force with git push --force-with-lease=<ref>:<expected-sha>
  • Persist last remote SHA in .trinity/last-remote-sha/<branch> after fetch
  • Surface collision to operator queue with structured error

Observability

  • Fleet dashboard shows branch bindings tab
  • Duplicate bindings shown in red
  • One-click rebinding flow: "Assign fresh working branch"

Technical Notes

Files to modify:

  • src/backend/services/git_service.py — new reserve_and_generate_instance_id, check_remote_branch_exists
  • src/backend/db/schema.py, db/migrations.py — partial UNIQUE index
  • src/backend/routers/agents.py, routers/git.py, routers/agent_config.py — validate on create/update
  • docker/base-image/agent_server/routers/git.py — --force-with-lease, persist last-remote-sha
  • Frontend — fleet binding warnings

Migration note: Deploy validation as warnings first, fix known duplicates, then flip the constraint.

Part of Epic #381

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions