Skip to content

fix: gitops role handlers return structs instead of map[string]any - #7

Open
andrewwhitecdw wants to merge 2 commits into
mainfrom
bugfix/workspace-gitops-role-handlers-return-structs
Open

fix: gitops role handlers return structs instead of map[string]any#7
andrewwhitecdw wants to merge 2 commits into
mainfrom
bugfix/workspace-gitops-role-handlers-return-structs

Conversation

@andrewwhitecdw

Copy link
Copy Markdown
Owner

This PR addresses the following issue in go/internal/roles/gitops/workspace.go: gitops role handlers return structs instead of map[string]any.

Changes

  • go/internal/roles/gitops/workspace.go: gitops role handlers return structs instead of map[string]any.

Details

--- a/go/internal/roles/gitops/workspace.go
+++ b/go/internal/roles/gitops/workspace.go
@@ -2,6 +2,7 @@ package gitops
 
 import (
 	"context"
+	"encoding/json"
 	"fmt"
 
 	"github.com/Agent-Field/SWE-AF/go/internal/afx"
@@ -74,7 +75,12 @@ func RunGitInit(ctx context.Context, deps *Deps, input map[string]any) (any, err
 	if ok {
 		deps.App.Note(ctx, fmt.Sprintf("Git init complete: mode=%s, integration_branch=%s",
 			val.Mode, val.IntegrationBranch), "git_init", "complete")
-		return *val, nil
+		out, err := toMap(val)
+		if err != nil {
+			return nil, err
+		}
+		return out, nil
 	}
 
 	// Fallback: report failure.
-	return schemas.GitInitResult{
+	out, err := toMap(&schemas.GitInitResult{
 		Mode:              "unknown",
 		OriginalBranch:    "",
 		IntegrationBranch: "",
 		InitialCommitSHA:  "",
 		Success:           false,
 		ErrorMessage:      "Git init agent failed to produce a valid result.",
-	}, nil
+	})
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
 }
 
 // ---------------------------------------------------------------------------
@@ -144,7 +155,12 @@ func RunWorkspaceSetup(ctx context.Context, deps *Deps, input map[string]any) (an
 	if ok {
 		deps.App.Note(ctx, fmt.Sprintf("Workspace setup complete: %d worktrees created",
 			len(val.Workspaces)), "workspace_setup", "complete")
-		return *val, nil
+		out, err := toMap(val)
+		if err != nil {
+			return nil, err
+		}
+		return out, nil
 	}
 
-	return workspaceSetupResult{Workspaces: []schemas.WorkspaceInfo{}, Success: false}, nil
+	out, err := toMap(&workspaceSetupResult{Workspaces: []schemas.WorkspaceInfo{}, Success: false})
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
 }
 
 // ---------------------------------------------------------------------------
@@ -198,9 +214,32 @@ func RunWorkspaceCleanup(ctx context.Context, deps *Deps, input map[string]any)
 	if ok {
 		deps.App.Note(ctx, fmt.Sprintf("Workspace cleanup complete: %d cleaned",
 			len(val.Cleaned)), "workspace_cleanup", "complete")
-		return *val, nil
+		out, err := toMap(val)
+		if err != nil {
+			return nil, err
+		}
+		return out, nil
 	}
 
-	return workspaceCleanupResult{Success: false, Cleaned: []string{}}, nil
+	out, err := toMap(&workspaceCleanupResult{Success: false, Cleaned: []string{}})
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// ---------------------------------------------------------------------------
+// Helpers
+// ---------------------------------------------------------------------------
+
+// toMap serializes a typed result into a JSON-tagged map[string]any so role
+// handlers return dict-shaped payloads consistent with the planning package.
+func toMap(v any) (map[string]any, error) {
+	b, err := json.Marshal(v)
+	if err != nil {
+		return nil, err
+	}
+	var out map[string]any
+	if err := json.Unmarshal(b, &out); err != nil {
+		return nil, err
+	}
+	return out, nil
 }

Tests

  • go/internal/roles/gitops/workspace_test.go
--- /dev/null
+++ b/go/internal/roles/gitops/workspace_test.go
@@ -0,0 +1,20 @@
+package gitops
+
+import "testing"
+
+func TestToMapReturnsTaggedMap(t *testing.T) {
+	type sample struct {
+		Mode    string `json:"mode"`
+		Success bool   `json:"success"`
+	}
+	s := sample{Mode: "gitflow", Success: true}
+	m, err := toMap(&s)
+	if err != nil {
+		t.Fatalf("toMap error: %v", err)
+	}
+	if got, want := m["mode"], "gitflow"; got != want {
+		t.Fatalf("mode: got %v, want %v", got, want)
+	}
+	if got, want := m["success"], true; got != want {
+		t.Fatalf("success: got %v, want %v", got, want)
+	}
+}

AbirAbbas and others added 2 commits July 31, 2026 22:23
…ude/sonnet (Agent-Field#120)

Direct reasoner calls hard-coded ai_provider=claude and model=sonnet,
so on an OpenRouter-only deployment (the common cloud setup) every
direct role call tried the claude harness and failed instantly - even
though config.DefaultRuntime() already auto-selects open_code there and
the orchestrators already resolve properly. Resolve absent runtime and
model inputs at call time through the existing config cascade
(SWE_DEFAULT_RUNTIME, tier env vars, OpenRouter auto-default); explicit
input values are untouched. Adds config.DefaultRoleModel backed by
ResolveRuntimeModels/RoleToTier so coding and gitops roles pick their
tier-correct model.

Verified live on a Railway control plane where run_product_manager
failed in 500ms with the old defaults and succeeded via opencode with
provider overrides.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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