refactor(backend): remove dead code and deprecated shims (#1965)

Delete unreachable/unused backend symbols confirmed by staticcheck U1000
and golang.org/x/tools/deadcode, plus deprecated back-compat aliases kept
alive only by their own tests.

Removed (unused):
- parseGitHubRepoURL, syncTaskStateForBulkWorkflowMove (task/service)
- resolvePrimaryRepoInfo (orchestrator/executor)
- resolveWorkflowAgentProfile, workflowDefaultAgentProfile wrappers (mcp/handlers)
- cleanupExitedContainer (runtime/lifecycle) + orphaned fmt import
- VscodeManager.setEnv (agentctl/server/process)
- repoRootDir const (cmd/preview)

Removed (deprecated shims):
- Canceller.CancelSessionAndNotify alias -> callers use DetachSessionAndNotify
- ScriptPlaceholder type alias (live scriptPlaceholders var kept)
- Placeholder{QueueRun,ClearDecisions,QueueRunForEachParticipant}Callback
  no-op structs and their self-referential test

No behavior change; build, vet, and affected-package tests pass.

Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
João Salavisa
2026-07-26 17:54:12 +01:00
committed by GitHub
parent 45974b513a
commit bb72d70586
13 changed files with 6 additions and 199 deletions
-1
View File
@@ -15,7 +15,6 @@ import (
// appsDir is the apps/ workspace root relative to the working directory (apps/backend/).
const appsDir = ".."
const repoRootDir = "../.."
// goDockerImage is used to cross-compile CGO binaries on non-linux/amd64 hosts.
const goDockerImage = "golang:1.26-bookworm"
@@ -3,7 +3,6 @@ package lifecycle
import (
"context"
"errors"
"fmt"
"sync"
"time"
@@ -231,55 +230,6 @@ func (m *Manager) StopAllAgents(ctx context.Context) error {
const stopReasonStaleExecutionCleanup = "stale execution cleanup"
// cleanupExitedContainer handles cleanup for a single exited container.
func (m *Manager) cleanupExitedContainer(ctx context.Context, containerID string) {
execution, tracked := m.executionStore.GetByContainerID(containerID)
if !tracked {
return
}
// Get the Docker executor's ContainerManager from the registry.
var containerMgr *ContainerManager
if m.executorRegistry != nil {
if backend, berr := m.executorRegistry.GetBackend(executor.NameDocker); berr == nil {
if dockerExec, ok := backend.(*DockerExecutor); ok {
containerMgr = dockerExec.ContainerMgr()
}
}
}
if containerMgr == nil {
m.logger.Warn("docker container manager unavailable, cannot clean up container",
zap.String("container_id", containerID))
return
}
// Get container info to get exit code
info, err := containerMgr.GetContainerInfo(ctx, containerID)
if err != nil {
m.logger.Warn("failed to get container info during cleanup",
zap.String("container_id", containerID),
zap.Error(err))
return
}
// Mark execution as completed
errorMsg := ""
if info.ExitCode != 0 {
errorMsg = fmt.Sprintf("container exited with code %d", info.ExitCode)
}
_ = m.MarkCompleted(execution.ID, info.ExitCode, errorMsg)
// Remove the container
if err := containerMgr.RemoveContainer(ctx, containerID, false); err != nil {
m.logger.Warn("failed to remove container during cleanup",
zap.String("container_id", containerID),
zap.Error(err))
}
// Remove the execution from tracking so new agents can be launched
m.RemoveExecution(execution.ID)
}
// CleanupStaleExecutionBySessionID cleans up a stale execution: stops the runtime
// instance, closes the client connection, and removes it from tracking.
//
@@ -93,15 +93,6 @@ func NewVscodeManager(
}
}
func (v *VscodeManager) setEnv(env map[string]string) {
v.mu.Lock()
defer v.mu.Unlock()
v.env = make(map[string]string, len(env))
for key, value := range env {
v.env[key] = value
}
}
// Start launches the code-server process asynchronously.
// It returns immediately after setting status to "installing" and spawns
// a background goroutine that resolves the binary, writes theme settings,
@@ -132,12 +132,6 @@ func (c *Canceller) DetachSessionAndNotify(ctx context.Context, sessionID string
return c.detachSessionBundles(ctx, sessionID)
}
// Deprecated: use DetachSessionAndNotify. This alias remains so older tests and
// integrations keep the pre-rename entrypoint while detach semantics settle.
func (c *Canceller) CancelSessionAndNotify(ctx context.Context, sessionID string) int {
return c.DetachSessionAndNotify(ctx, sessionID)
}
// ExpireSessionAndNotify cancels in-memory waiters and marks clarification
// messages expired so the overlay closes and history shows a timed-out entry.
// TODO: wire this into terminal teardown paths that should close the overlay
@@ -88,7 +88,7 @@ func TestCanceller_MarksDetachedOnDisconnect(t *testing.T) {
},
}}
cancelled := c.CancelSessionAndNotify(context.Background(), "s1")
cancelled := c.DetachSessionAndNotify(context.Background(), "s1")
if cancelled != 1 {
t.Fatalf("expected 1 cancelled, got %d", cancelled)
}
@@ -138,7 +138,7 @@ func TestCanceller_ExpireSessionAndNotify_MarksExpired(t *testing.T) {
func TestCanceller_NoMessagesToUpdate(t *testing.T) {
c, repo, _ := newTestCanceller(t, map[string][]*taskmodels.Message{})
if got := c.CancelSessionAndNotify(context.Background(), "nonexistent"); got != 0 {
if got := c.DetachSessionAndNotify(context.Background(), "nonexistent"); got != 0 {
t.Errorf("expected 0 cancelled, got %d", got)
}
if len(repo.updated) != 0 {
@@ -159,7 +159,7 @@ func TestCanceller_PublishesMessageUpdatedEvent(t *testing.T) {
Metadata: map[string]any{"status": "pending"},
}}
c.CancelSessionAndNotify(context.Background(), "s1")
c.DetachSessionAndNotify(context.Background(), "s1")
if len(eventBus.events) != 1 {
t.Fatalf("expected 1 event, got %d", len(eventBus.events))
@@ -179,7 +179,7 @@ func TestCanceller_MultiQuestion_MarksAllMessagesDetached(t *testing.T) {
{ID: "m3", TaskSessionID: "s1", Metadata: map[string]any{"status": "pending", "question_id": "q3"}},
}
cancelled := c.CancelSessionAndNotify(context.Background(), "s1")
cancelled := c.DetachSessionAndNotify(context.Background(), "s1")
if cancelled != 1 {
t.Fatalf("expected 1 cancelled bundle, got %d", cancelled)
}
@@ -233,7 +233,7 @@ func TestCanceller_Idempotent_SkipsAnsweredMessages(t *testing.T) {
{ID: "m2", TaskSessionID: "s1", Metadata: map[string]any{"status": "pending"}},
}
c.CancelSessionAndNotify(context.Background(), "s1")
c.DetachSessionAndNotify(context.Background(), "s1")
if len(repo.updated) != 1 {
t.Fatalf("expected 1 message update (only the pending one), got %d", len(repo.updated))
@@ -1023,11 +1023,6 @@ func (h *Handlers) mcpTaskAgentProfileDefault(ctx context.Context, explicitAgent
return usermodels.NormalizeMCPTaskAgentProfileDefault(settings.MCPTaskAgentProfileDefault), nil
}
func (h *Handlers) resolveWorkflowAgentProfile(ctx context.Context, workflowStepID, workflowID string) string {
profileID, _ := h.resolveWorkflowAgentProfileWithError(ctx, workflowStepID, workflowID)
return profileID
}
func (h *Handlers) resolveWorkflowAgentProfileWithError(ctx context.Context, workflowStepID, workflowID string) (string, error) {
profileID, resolvedWorkflowID := h.resolveWorkflowControllerAgentProfile(ctx, workflowStepID, workflowID)
if profileID != "" {
@@ -1075,11 +1070,6 @@ func (h *Handlers) resolveWorkflowStartStepAgentProfile(ctx context.Context, wor
return startStepAgentProfile(resp.Steps)
}
func (h *Handlers) workflowDefaultAgentProfile(ctx context.Context, workflowID string) string {
profileID, _ := h.workflowDefaultAgentProfileWithError(ctx, workflowID)
return profileID
}
func (h *Handlers) workflowDefaultAgentProfileWithError(ctx context.Context, workflowID string) (string, error) {
if workflowID == "" || h.taskSvc == nil {
return "", nil
@@ -70,22 +70,6 @@ type repoInfo struct {
Repository *models.Repository
}
// resolvePrimaryRepoInfo fetches and resolves the primary repository info for a task.
func (e *Executor) resolvePrimaryRepoInfo(ctx context.Context, taskID string) (*repoInfo, error) {
info := &repoInfo{}
primaryTaskRepo, err := e.repo.GetPrimaryTaskRepository(ctx, taskID)
if err != nil {
e.logger.Error("failed to get primary task repository",
zap.String("task_id", taskID),
zap.Error(err))
return nil, err
}
if primaryTaskRepo == nil {
return info, nil
}
return e.resolveTaskRepoInfo(ctx, primaryTaskRepo)
}
// resolveAllRepoInfo returns the resolved repository info for every repository
// linked to the task, ordered by Position. Returns a single-element slice for
// single-repo tasks and an empty slice for repo-less tasks (e.g. quick chat).
@@ -2,10 +2,5 @@ package handlers
import "github.com/kandev/kandev/internal/scriptengine"
// ScriptPlaceholder describes a template variable available in prepare/cleanup scripts.
//
// Deprecated: Use scriptengine.PlaceholderInfo directly.
type ScriptPlaceholder = scriptengine.PlaceholderInfo
// scriptPlaceholders is the registry of all available script template placeholders.
var scriptPlaceholders = scriptengine.DefaultPlaceholders
@@ -966,20 +966,6 @@ func (s *Service) probeProviderDefaultBranchIfMissing(
return probed
}
// parseGitHubRepoURL parses a GitHub repository URL into owner and name.
// Supports: https://github.com/owner/repo, github.com/owner/repo,
// https://github.com/owner/repo.git, with optional trailing slashes.
func parseGitHubRepoURL(rawURL string) (owner, name string, err error) {
provider, owner, name, _, parseErr := parseRemoteRepositoryURL(rawURL, "")
if parseErr != nil {
return "", "", parseErr
}
if provider != providerGitHub {
return "", "", fmt.Errorf("not a GitHub URL")
}
return owner, name, nil
}
// resolvePRNumber returns the GitHub PR number for a repository input. Prefers
// the explicit PRNumber field; falls back to parsing a /pull/<N> path out of
// GitHubURL when present. Returns 0 when no PR is identified.
@@ -466,31 +466,6 @@ func (s *Service) syncTaskStateForWorkflowMove(ctx context.Context, task *models
return nil
}
func (s *Service) syncTaskStateForBulkWorkflowMove(ctx context.Context, task *models.Task, oldStepID, targetStepID string, targetIsTerminal, sourceIsTerminal, sourceTerminalKnown bool) error {
if targetIsTerminal {
if !models.IsTerminalTaskState(task.State) {
task.State = v1.TaskStateCompleted
}
return nil
}
if oldStepID == targetStepID || task.State != v1.TaskStateCompleted {
return nil
}
oldTerminal := sourceIsTerminal
if !sourceTerminalKnown {
var err error
oldTerminal, err = s.terminalWorkflowStep(ctx, oldStepID)
if err != nil {
return err
}
}
if oldTerminal {
task.State = v1.TaskStateTODO
}
return nil
}
func (s *Service) pullNextTaskOnVacate(ctx context.Context, vacatedStepID, excludeTaskID string) {
vacatedStep := s.pullEnabledStep(ctx, vacatedStepID)
if vacatedStep == nil {
@@ -382,45 +382,9 @@ func queueRunForEachParticipantReason(in ActionInput) string {
return string(in.Trigger)
}
// PlaceholderQueueRunCallback is preserved as a typed alias for backward
// compatibility with the Phase 2 prep slice. New code should construct
// QueueRunCallback directly.
//
// Deprecated: Use QueueRunCallback.
type PlaceholderQueueRunCallback struct{}
// Execute returns ErrActionNotYetWired so accidental use is loud.
func (PlaceholderQueueRunCallback) Execute(_ context.Context, _ ActionInput) (ActionResult, error) {
return ActionResult{}, ErrActionNotYetWired
}
// PlaceholderClearDecisionsCallback is preserved for backward compatibility.
//
// Deprecated: Use ClearDecisionsCallback.
type PlaceholderClearDecisionsCallback struct{}
// Execute returns ErrActionNotYetWired so accidental use is loud.
func (PlaceholderClearDecisionsCallback) Execute(_ context.Context, _ ActionInput) (ActionResult, error) {
return ActionResult{}, ErrActionNotYetWired
}
// PlaceholderQueueRunForEachParticipantCallback is preserved for backward
// compatibility.
//
// Deprecated: Use QueueRunForEachParticipantCallback.
type PlaceholderQueueRunForEachParticipantCallback struct{}
// Execute returns ErrActionNotYetWired so accidental use is loud.
func (PlaceholderQueueRunForEachParticipantCallback) Execute(_ context.Context, _ ActionInput) (ActionResult, error) {
return ActionResult{}, ErrActionNotYetWired
}
// Compile-time interface assertions.
var (
_ ActionCallback = QueueRunCallback{}
_ ActionCallback = ClearDecisionsCallback{}
_ ActionCallback = QueueRunForEachParticipantCallback{}
_ ActionCallback = PlaceholderQueueRunCallback{}
_ ActionCallback = PlaceholderClearDecisionsCallback{}
_ ActionCallback = PlaceholderQueueRunForEachParticipantCallback{}
)
@@ -2,7 +2,6 @@ package engine
import (
"context"
"errors"
"testing"
wfmodels "github.com/kandev/kandev/internal/workflow/models"
@@ -90,25 +89,6 @@ func TestClearDecisionsAction_Construction(t *testing.T) {
}
}
func TestPhase2Placeholders_ReturnNotYetWired(t *testing.T) {
cases := []struct {
name string
cb ActionCallback
}{
{"queue_run", PlaceholderQueueRunCallback{}},
{"clear_decisions", PlaceholderClearDecisionsCallback{}},
{"queue_run_for_each_participant", PlaceholderQueueRunForEachParticipantCallback{}},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, err := tc.cb.Execute(context.Background(), ActionInput{})
if !errors.Is(err, ErrActionNotYetWired) {
t.Fatalf("expected ErrActionNotYetWired, got %v", err)
}
})
}
}
func TestPhase2Placeholders_NotRegisteredInDefaultRegistry(t *testing.T) {
// Empty MapRegistry must not resolve the new action kinds. This pins the
// invariant that the Phase 2 actions are declared but inert until the
@@ -150,8 +150,7 @@ type RunCodeReviewAction struct {
}
// QueueRunAction represents the Phase 2 "queue a run on a target task/agent"
// action. The action is declared but its callback is not yet wired into the
// engine; see PlaceholderQueueRunCallback.
// action. The callback is QueueRunCallback.
//
// Targets: "primary" | "participant_role:<role>" | "agent_profile_id:<id>" |
// "workspace.ceo_agent" (resolved at engine evaluation time, post-wire-up).