Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions pkg/agentdrain/coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,6 @@ func (c *Coordinator) AnalyzeEvent(evt AgentEvent) (*MatchResult, *AnomalyReport
return m.AnalyzeEvent(evt)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removal of Stages() and MinerForStage() looks correct per the dead-code analysis. Consider adding a comment to AllClusters() clarifying it is now the primary iteration point for consumers that previously used Stages().

}

// Stages returns the list of stage names managed by this Coordinator.
func (c *Coordinator) Stages() []string {
c.mu.RLock()
defer c.mu.RUnlock()
stages := make([]string, 0, len(c.miners))
for s := range c.miners {
stages = append(stages, s)
}
return stages
}

// MinerForStage returns the Miner for the given stage, or false if not found.
func (c *Coordinator) MinerForStage(stage string) (*Miner, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
m, ok := c.miners[stage]
return m, ok
}

// AllClusters returns a map from stage name to the list of clusters in that miner.
func (c *Coordinator) AllClusters() map[string][]Cluster {
c.mu.RLock()
Expand Down
37 changes: 0 additions & 37 deletions pkg/agentdrain/miner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,32 +154,6 @@ func TestFlattenEvent(t *testing.T) {
}
}

func TestPreTrainTemplate(t *testing.T) {
cfg := DefaultConfig()
cfg.SimThreshold = 0.4
m, err := NewMiner(cfg)
if err != nil {
t.Fatalf("NewMiner: %v", err)
}

m.PreTrainTemplate("stage=tool_call tool=<*> latency_ms=<*>", 5)
if m.ClusterCount() != 1 {
t.Fatalf("PreTrainTemplate: expected 1 cluster, got %d", m.ClusterCount())
}

// A real line matching that pattern should hit the pre-trained cluster.
result, ok, err := m.Match("stage=tool_call tool=search latency_ms=<*>")
if err != nil {
t.Fatalf("Match: %v", err)
}
if !ok {
t.Error("Match: expected to find pre-trained cluster, got no match")
}
if result != nil && result.ClusterID == 0 {
t.Error("Match: expected valid cluster ID")
}
}

func TestSaveLoadJSON(t *testing.T) {
cfg := DefaultConfig()
m, err := NewMiner(cfg)
Expand Down Expand Up @@ -260,17 +234,6 @@ func TestStageRouting(t *testing.T) {
}
}

for _, stage := range stages {
m, ok := coord.MinerForStage(stage)
if !ok {
t.Errorf("MinerForStage(%q): not found", stage)
continue
}
if m.ClusterCount() == 0 {
t.Errorf("stage %q: expected at least one cluster", stage)
}
}

// Unknown stage should error.
_, err = coord.TrainEvent(AgentEvent{Stage: "unknown", Fields: map[string]string{}})
if err == nil {
Expand Down
58 changes: 0 additions & 58 deletions pkg/agentdrain/pretrain.go

This file was deleted.

19 changes: 0 additions & 19 deletions pkg/workflow/action_pins.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,25 +144,6 @@ func getActionPinsByRepo(repo string) []ActionPin {
return cachedActionPinsByRepo[repo]
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean removal of sortPinsByVersion. Confirm that GetActionPin (the only caller of the sort logic) still handles multi-version repos correctly after this change — the inline sort logic should cover the same cases.

}

// sortPinsByVersion sorts action pins by version in descending order (highest first).
// This function returns a new sorted slice without modifying the input.
// This is an immutable operation for better safety and clarity.
func sortPinsByVersion(pins []ActionPin) []ActionPin {
// Create a copy to avoid mutating the input
result := make([]ActionPin, len(pins))
copy(result, pins)

sort.Slice(result, func(i, j int) bool {
// Strip 'v' prefix for comparison
v1 := strings.TrimPrefix(result[i].Version, "v")
v2 := strings.TrimPrefix(result[j].Version, "v")
// Return true if v1 > v2 to get descending order
return compareVersions(v1, v2) > 0
})

return result
}

// GetActionPin returns the pinned action reference for a given action repository
// When multiple versions exist for the same repo, it returns the latest version by semver
// If no pin is found, it returns an empty string
Expand Down
98 changes: 0 additions & 98 deletions pkg/workflow/action_pins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -708,104 +708,6 @@ func TestGetActionPinWithData_AlreadySHA(t *testing.T) {
}
}

func TestSortPinsByVersion(t *testing.T) {
tests := []struct {
name string
input []ActionPin
expected []ActionPin
}{
{
name: "versions in ascending order",
input: []ActionPin{
{Repo: "actions/checkout", Version: "v1", SHA: "abc1"},
{Repo: "actions/checkout", Version: "v2", SHA: "abc2"},
{Repo: "actions/checkout", Version: "v3", SHA: "abc3"},
},
expected: []ActionPin{
{Repo: "actions/checkout", Version: "v3", SHA: "abc3"},
{Repo: "actions/checkout", Version: "v2", SHA: "abc2"},
{Repo: "actions/checkout", Version: "v1", SHA: "abc1"},
},
},
{
name: "versions already in descending order",
input: []ActionPin{
{Repo: "actions/checkout", Version: "v3", SHA: "abc3"},
{Repo: "actions/checkout", Version: "v2", SHA: "abc2"},
{Repo: "actions/checkout", Version: "v1", SHA: "abc1"},
},
expected: []ActionPin{
{Repo: "actions/checkout", Version: "v3", SHA: "abc3"},
{Repo: "actions/checkout", Version: "v2", SHA: "abc2"},
{Repo: "actions/checkout", Version: "v1", SHA: "abc1"},
},
},
{
name: "mixed version order with patch versions",
input: []ActionPin{
{Repo: "actions/checkout", Version: "v2.1.0", SHA: "abc210"},
{Repo: "actions/checkout", Version: "v3.0.0", SHA: "abc300"},
{Repo: "actions/checkout", Version: "v2.0.1", SHA: "abc201"},
{Repo: "actions/checkout", Version: "v1.0.0", SHA: "abc100"},
},
expected: []ActionPin{
{Repo: "actions/checkout", Version: "v3.0.0", SHA: "abc300"},
{Repo: "actions/checkout", Version: "v2.1.0", SHA: "abc210"},
{Repo: "actions/checkout", Version: "v2.0.1", SHA: "abc201"},
{Repo: "actions/checkout", Version: "v1.0.0", SHA: "abc100"},
},
},
{
name: "empty slice",
input: []ActionPin{},
expected: []ActionPin{},
},
{
name: "single element",
input: []ActionPin{
{Repo: "actions/checkout", Version: "v1", SHA: "abc1"},
},
expected: []ActionPin{
{Repo: "actions/checkout", Version: "v1", SHA: "abc1"},
},
},
{
name: "versions without v prefix",
input: []ActionPin{
{Repo: "actions/checkout", Version: "1.0.0", SHA: "abc100"},
{Repo: "actions/checkout", Version: "2.0.0", SHA: "abc200"},
{Repo: "actions/checkout", Version: "1.5.0", SHA: "abc150"},
},
expected: []ActionPin{
{Repo: "actions/checkout", Version: "2.0.0", SHA: "abc200"},
{Repo: "actions/checkout", Version: "1.5.0", SHA: "abc150"},
{Repo: "actions/checkout", Version: "1.0.0", SHA: "abc100"},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// sortPinsByVersion now returns a new sorted slice (immutable operation)
result := sortPinsByVersion(tt.input)

if len(result) != len(tt.expected) {
t.Errorf("sortPinsByVersion() length = %d, want %d", len(result), len(tt.expected))
return
}

for i := range result {
if result[i].Repo != tt.expected[i].Repo ||
result[i].Version != tt.expected[i].Version ||
result[i].SHA != tt.expected[i].SHA {
t.Errorf("sortPinsByVersion() at index %d = %+v, want %+v",
i, result[i], tt.expected[i])
}
}
})
}
}

func TestApplyActionPinsToTypedSteps(t *testing.T) {
// Create a minimal WorkflowData for testing
data := &WorkflowData{
Expand Down
Loading