Skip to content

Conversation

@JoshuaSkootsky
Copy link

@JoshuaSkootsky JoshuaSkootsky commented Jan 12, 2026

I saw Drover and thought to add OpenCode as an alternative to Claude Code

Testing out the OpenCode I ran into some bugs with empty git repos that I wanted to add to Drover

[edit] possibly you good people at Drover handled these issues over the weekend!

Add Support for Empty Git Repositories with Telemetry

Summary

Enable Drover to work with empty Git repositories by automatically initializing a main branch when needed, and adds comprehensive telemetry to track empty repo scenarios for observability.

Problem

Drover previously failed when encountering empty Git repositories with the error:

  • fatal: refusing to merge unrelated histories

  • No visibility into how frequently empty repos were encountered

  • Workflow would break on first run against new/empty repositories

Solution

  1. Empty Repository Handling (internal/git/worktree.go)
  • Added EnsureMainBranch() method that detects empty repos and creates an initial commit on the target branch

  • Modified MergeToMain() to use git reset --hard strategy when encountering unrelated histories

  • Both operations are now idempotent and safe to call multiple times

  1. Telemetry Integration (pkg/telemetry/tracer.go)
  • Added SpanGitEnsureMain = "drover.git.ensure_main" for branch initialization tracking

  • Added SpanGitWorktreeMerge = "drover.git.worktree_merge" for merge operations

  • Added StartGitSpan() helper function for consistent git operation tracing

  1. Context Propagation
  • Updated EnsureMainBranch(ctx context.Context) and MergeToMain(ctx context.Context, taskID string) to accept context

  • Updated all 7 callers across workflow orchestrators to pass context through

  • Enables full distributed tracing from workflow → git operations

Key Changes

// New telemetry spans with attributes:
SpanGitEnsureMain:
  - git.branch: target branch name
  
SpanGitWorktreeMerge:
  - task.id: task identifier
  - repo.had_commits: boolean tracking empty repo scenarios

Testing

  • ✅ All 15 git package tests pass

  • ✅ 9/9 core orchestrator tests pass (6 DBOS tests require PostgreSQL)

  • ✅ Verified empty repo workflow: git init → EnsureMainBranch() → MergeToMain() succeeds

  • ✅ Verified non-empty repo workflow remains unchanged

Impact

  • Operational: Drover now works seamlessly with both empty and populated repositories

  • Observability: You can now query metrics on empty repo frequency:

    -- Example: % of merges that encountered empty repos
    SELECT (SUM(CASE WHEN attrs['repo.had_commits'] = 'false' THEN 1 ELSE 0 END) * 100.0 / COUNT(*))
    FROM spans WHERE name = 'drover.git.worktree_merge'

  • Debugging: Full trace visibility into git operations with error correlation

JoshuaSkootsky and others added 3 commits January 12, 2026 11:19
- Added OpenCodeExecutor with run command support
- Added factory pattern for agent type selection
- Added CLI flags for --agent-type and --opencode-model
- Added configuration for OpenCode model and server URL
- Added comprehensive test coverage
- Updated telemetry with AgentTypeOpenCode constant

Co-Authored-By: MiniMax M2.1  <noreply@minimax.io>
- Fix unexported field access in test by using Path() method
- Add EnsureMainBranch() to handle empty repos by creating main branch with initial commit
- Fix MergeToMain() to handle unrelated histories error by using reset --hard strategy
- Add comprehensive tests for empty repo scenarios
- Update Create() to check for empty repo before calling EnsureMainBranch
- Add SpanGitEnsureMain and SpanGitWorktreeMerge span constants
- Add StartGitSpan helper function for git operations
- Add context parameter to EnsureMainBranch and MergeToMain
- Track repo.had_commits and task.id attributes for empty repo detection
@petehanssens petehanssens self-requested a review January 13, 2026 12:54
@petehanssens
Copy link
Contributor

PR #4 Review: OpenCode Agent Support

Thanks so much for putting this together @JoshuaSkootsky

Summary

This PR adds OpenCode agent support with a new executor factory pattern. However, there are several merge conflicts and architectural inconsistencies that need to be resolved.

Key Changes in PR

  1. New OpenCode Executor: Adds internal/executor/opencode.go with OpenCodeExecutor implementation
  2. New Factory Pattern: Adds internal/executor/factory.go with AgentExecutor interface and NewAgentExecutor() factory
  3. Config Refactoring: Changes AgentType from string to typed constants (AgentTypeClaudeCode, AgentTypeOpenCode)
  4. Git Worktree Updates: Adds context parameter to MergeToMain() and adds EnsureMainBranch() method
  5. CLI Flags: Adds --agent-type, --opencode-model, --opencode-url flags

Merge Conflicts Identified

1. MergeToMain Signature Change ⚠️ CRITICAL

Conflict: PR changes MergeToMain(taskID string) to MergeToMain(ctx context.Context, taskID string)

Current calls that need updating:

  • internal/workflow/orchestrator.go:282 - o.git.MergeToMain(task.ID)
  • internal/workflow/orchestrator.go:380 - o.git.MergeToMain(subTask.ID)
  • internal/workflow/dbos_workflow.go:567 - o.git.MergeToMain(taskID)

Resolution: All call sites need to pass context.Context. The orchestrator already has context available.

2. Executor Interface Mismatch ⚠️ CRITICAL

Conflict: PR introduces new AgentExecutor interface, but current codebase uses:

  • executor.Agent interface (in agent.go)
  • executor.Executor struct (old Claude executor)

Current state:

  • dbos_workflow.go uses executor.Executor (line 7, 27)
  • orchestrator.go uses executor.Agent interface (line 70)

PR wants:

  • dbos_workflow.go to use executor.AgentExecutor interface
  • Factory method executor.NewAgentExecutor(cfg) instead of executor.NewExecutor()

Resolution: Need to decide:

  • Option A: Migrate everything to new AgentExecutor interface (breaking change)
  • Option B: Keep both interfaces and bridge them
  • Option C: Refactor PR to use existing Agent interface

3. Config AgentType Incompatibility ⚠️ HIGH

Conflict:

  • Current: AgentType string with values "claude", "codex", "amp", "opencode"
  • PR: AgentType AgentType (typed) with constants AgentTypeClaudeCode ("claude-code"), AgentTypeOpenCode ("opencode")

Issues:

  • Value mismatch: "claude" vs "claude-code"
  • Type mismatch: string vs AgentType
  • Current code expects cfg.AgentType == "claude" but PR uses cfg.AgentType == config.AgentTypeClaudeCode

Files affected:

  • internal/config/config.go - type definition
  • internal/workflow/dbos_workflow.go - agent type checks
  • internal/workflow/orchestrator.go - agent type checks
  • cmd/drover/commands.go - config usage

Resolution: Need to align on:

  • Keep string-based for backward compatibility, OR
  • Migrate all code to typed constants (breaking change)

4. OpenCode Implementation Duplication ⚠️ MEDIUM

Conflict:

  • Current: internal/executor/opencode_agent.go with OpenCodeAgent struct
  • PR: internal/executor/opencode.go with OpenCodeExecutor struct

Differences:

  • OpenCodeAgent uses simple opencode run <prompt> command
  • OpenCodeExecutor uses JSON event parsing and supports --model and --url flags
  • Different interfaces: Agent vs AgentExecutor

Resolution:

  • Decide which implementation to keep
  • If keeping PR version, remove opencode_agent.go
  • If keeping current, update PR to use existing implementation

5. Factory Pattern Conflict ⚠️ MEDIUM

Conflict:

  • Current: executor.NewAgent(cfg *AgentConfig) returns Agent interface
  • PR: executor.NewAgentExecutor(cfg *config.Config) returns AgentExecutor interface

Resolution: Need unified factory approach or clear separation of concerns.

6. Missing CheckOpenCodeInstalled Function ⚠️ LOW

PR references: executor.CheckOpenCodeInstalled(cfg.OpenCodePath) in dbos_workflow.go:44
Current: No such function exists (only CheckClaudeInstalled)

Resolution: Need to add this function or use existing OpenCodeAgent.CheckInstalled() method.

Additional Issues

7. Config Field Additions

PR adds new config fields that don't exist in current codebase:

  • OpenCodePath string
  • OpenCodeModel string
  • OpenCodeURL string
  • MergeTargetBranch string

These need to be added to current Config struct.

8. Worktree Create Logic Changes

PR significantly changes Create() method to handle empty repos with EnsureMainBranch(). Current implementation uses -b flag to create branch upfront. Need to reconcile approaches.

9. CLI Flag Integration

PR adds flags but current runCmd() doesn't have the agent configuration logic. Need to integrate the PR's flag handling code.

Recommended Resolution Strategy

Phase 1: Resolve Critical Conflicts

  1. Update MergeToMain calls: Add context parameter to all 3 call sites
  2. Decide on executor interface: Choose between Agent and AgentExecutor (recommend migrating to AgentExecutor for consistency)
  3. Resolve AgentType: Migrate to typed constants for type safety

Phase 2: Resolve Implementation Conflicts

  1. Choose OpenCode implementation: Keep PR's more feature-rich version, remove opencode_agent.go
  2. Add missing functions: Implement CheckOpenCodeInstalled() helper
  3. Update factory: Migrate all code to use NewAgentExecutor()

Phase 3: Integration

  1. Add config fields: Add new OpenCode config fields to Config struct
  2. Integrate CLI flags: Add agent selection flags to runCmd()
  3. Update worktree logic: Merge PR's empty repo handling with current branch creation logic

Testing Considerations

  • Verify backward compatibility with existing "claude" agent type
  • Test OpenCode executor with various model formats
  • Test empty repository handling
  • Verify context propagation in git operations

Questions for PR Author

  1. Why introduce AgentExecutor interface instead of extending Agent?
  2. Why change "claude" to "claude-code"? (breaking change)
  3. Should we keep both OpenCode implementations or consolidate?
  4. What's the migration path for existing users with AgentType="claude"?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants