diff --git a/pkg/agentci/clotho.go b/pkg/agentci/clotho.go index f8b25b3..998d502 100644 --- a/pkg/agentci/clotho.go +++ b/pkg/agentci/clotho.go @@ -61,6 +61,25 @@ func (s *Spinner) GetVerifierModel(agentName string) string { return agent.VerifyModel } +// FindByForgejoUser resolves a Forgejo username to the agent config key and config. +// This decouples agent naming (mythological roles) from Forgejo identity. +func (s *Spinner) FindByForgejoUser(forgejoUser string) (string, AgentConfig, bool) { + if forgejoUser == "" { + return "", AgentConfig{}, false + } + // Direct match on config key first. + if agent, ok := s.Agents[forgejoUser]; ok { + return forgejoUser, agent, true + } + // Search by ForgejoUser field. + for name, agent := range s.Agents { + if agent.ForgejoUser != "" && agent.ForgejoUser == forgejoUser { + return name, agent, true + } + } + return "", AgentConfig{}, false +} + // Weave compares primary and verifier outputs. Returns true if they converge. // This is a placeholder for future semantic diff logic. func (s *Spinner) Weave(ctx context.Context, primaryOutput, signedOutput []byte) (bool, error) { diff --git a/pkg/jobrunner/handlers/dispatch.go b/pkg/jobrunner/handlers/dispatch.go index de2ae7d..f33a28e 100644 --- a/pkg/jobrunner/handlers/dispatch.go +++ b/pkg/jobrunner/handlers/dispatch.go @@ -68,12 +68,12 @@ func (h *DispatchHandler) Name() string { } // Match returns true for signals where a child issue needs coding (no PR yet) -// and the assignee is a known agent. +// and the assignee is a known agent (by config key or Forgejo username). func (h *DispatchHandler) Match(signal *jobrunner.PipelineSignal) bool { if !signal.NeedsCoding { return false } - _, ok := h.spinner.Agents[signal.Assignee] + _, _, ok := h.spinner.FindByForgejoUser(signal.Assignee) return ok } @@ -81,7 +81,7 @@ func (h *DispatchHandler) Match(signal *jobrunner.PipelineSignal) bool { func (h *DispatchHandler) Execute(ctx context.Context, signal *jobrunner.PipelineSignal) (*jobrunner.ActionResult, error) { start := time.Now() - agent, ok := h.spinner.Agents[signal.Assignee] + agentName, agent, ok := h.spinner.FindByForgejoUser(signal.Assignee) if !ok { return nil, fmt.Errorf("unknown agent: %s", signal.Assignee) } @@ -133,10 +133,10 @@ func (h *DispatchHandler) Execute(ctx context.Context, signal *jobrunner.Pipelin } // Clotho planning — determine execution mode. - runMode := h.spinner.DeterminePlan(signal, signal.Assignee) + runMode := h.spinner.DeterminePlan(signal, agentName) verifyModel := "" if runMode == agentci.ModeDual { - verifyModel = h.spinner.GetVerifierModel(signal.Assignee) + verifyModel = h.spinner.GetVerifierModel(agentName) } // Build ticket.