agent/pkg/agentic/auto_pr.go
Snider a0dc9c32e7 refactor: migrate core/agent to Core primitives — reference implementation
Phase 1: go-io/go-log → core.Fs{}, core.E(), core.Error/Info/Warn
Phase 2: strings/fmt → core.Contains, core.Sprintf, core.Split etc
Phase 3: embed.FS → core.Mount/core.Embed, core.Extract
Phase 4: cmd/main.go → core.Command(), c.Cli().Run(), no cli package

All packages migrated:
- pkg/lib (Codex): core.Mount, core.Extract, Result returns, AX comments
- pkg/setup (Codex): core.Fs, core.E, fixed missing lib helpers
- pkg/brain (Codex): Core primitives, AX comments
- pkg/monitor (Codex): Core string/logging primitives
- pkg/agentic (Codex): 20 files, Core primitives throughout
- cmd/main.go: pure Core CLI, no fmt/log/filepath/strings/cli

Remaining stdlib: path/filepath (Core doesn't wrap OS paths),
fmt.Sscanf/strings.Map (no Core equivalent).

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-22 06:13:41 +00:00

98 lines
2.6 KiB
Go

// SPDX-License-Identifier: EUPL-1.2
package agentic
import (
"context"
"os/exec"
"time"
core "dappco.re/go/core"
)
// autoCreatePR pushes the agent's branch and creates a PR on Forge
// if the agent made any commits beyond the initial clone.
func (s *PrepSubsystem) autoCreatePR(wsDir string) {
st, err := readStatus(wsDir)
if err != nil || st.Branch == "" || st.Repo == "" {
return
}
srcDir := core.JoinPath(wsDir, "src")
// Detect default branch for this repo
base := DefaultBranch(srcDir)
// Check if there are commits on the branch beyond the default branch
diffCmd := exec.Command("git", "log", "--oneline", "origin/"+base+"..HEAD")
diffCmd.Dir = srcDir
out, err := diffCmd.Output()
if err != nil || len(core.Trim(string(out))) == 0 {
// No commits — nothing to PR
return
}
commitCount := len(core.Split(core.Trim(string(out)), "\n"))
// Get the repo's forge remote URL to extract org/repo
org := st.Org
if org == "" {
org = "core"
}
// Push the branch to forge
forgeRemote := core.Sprintf("ssh://git@forge.lthn.ai:2223/%s/%s.git", org, st.Repo)
pushCmd := exec.Command("git", "push", forgeRemote, st.Branch)
pushCmd.Dir = srcDir
if pushErr := pushCmd.Run(); pushErr != nil {
// Push failed — update status with error but don't block
if st2, err := readStatus(wsDir); err == nil {
st2.Question = core.Sprintf("PR push failed: %v", pushErr)
writeStatus(wsDir, st2)
}
return
}
// Create PR via Forge API
title := core.Sprintf("[agent/%s] %s", st.Agent, truncate(st.Task, 60))
body := s.buildAutoPRBody(st, commitCount)
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
prURL, _, err := s.forgeCreatePR(ctx, org, st.Repo, st.Branch, base, title, body)
if err != nil {
if st2, err := readStatus(wsDir); err == nil {
st2.Question = core.Sprintf("PR creation failed: %v", err)
writeStatus(wsDir, st2)
}
return
}
// Update status with PR URL
if st2, err := readStatus(wsDir); err == nil {
st2.PRURL = prURL
writeStatus(wsDir, st2)
}
}
func (s *PrepSubsystem) buildAutoPRBody(st *WorkspaceStatus, commits int) string {
b := core.NewBuilder()
b.WriteString("## Task\n\n")
b.WriteString(st.Task)
b.WriteString("\n\n")
b.WriteString(core.Sprintf("**Agent:** %s\n", st.Agent))
b.WriteString(core.Sprintf("**Commits:** %d\n", commits))
b.WriteString(core.Sprintf("**Branch:** `%s`\n", st.Branch))
b.WriteString("\n---\n")
b.WriteString("Auto-created by core-agent dispatch system.\n")
b.WriteString("Co-Authored-By: Virgil <virgil@lethean.io>\n")
return b.String()
}
func truncate(s string, max int) string {
if len(s) <= max {
return s
}
return s[:max] + "..."
}