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

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