feat(agentic): extend workspace dispatch contract

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 12:39:18 +00:00
parent cacb8977bf
commit c01a694455
2 changed files with 46 additions and 14 deletions

View file

@ -92,22 +92,12 @@ func (s *PrepSubsystem) cmdWorkspaceClean(options core.Options) core.Result {
// input := DispatchInput{Repo: "go-io", Task: "Fix the failing tests", Issue: 12}
func (s *PrepSubsystem) cmdWorkspaceDispatch(options core.Options) core.Result {
repo := options.String("_arg")
if repo == "" {
core.Print(nil, "usage: core-agent workspace dispatch <repo> --task=\"...\" --issue=N|--pr=N|--branch=X [--agent=codex]")
input := workspaceDispatchInputFromOptions(options)
if input.Repo == "" {
core.Print(nil, "usage: core-agent workspace dispatch <repo> --task=\"...\" --issue=N|--pr=N|--branch=X [--agent=codex] [--template=coding] [--plan-template=bug-fix] [--persona=code/reviewer] [--tag=v0.8.0] [--dry-run]")
return core.Result{Value: core.E("agentic.cmdWorkspaceDispatch", "repo is required", nil), OK: false}
}
input := DispatchInput{
Repo: repo,
Task: options.String("task"),
Agent: options.String("agent"),
Org: options.String("org"),
Template: options.String("template"),
Branch: options.String("branch"),
Issue: parseIntString(options.String("issue")),
PR: parseIntString(options.String("pr")),
}
_, out, err := s.dispatch(context.Background(), nil, input)
if err != nil {
core.Print(nil, "dispatch failed: %s", err.Error())
@ -117,7 +107,7 @@ func (s *PrepSubsystem) cmdWorkspaceDispatch(options core.Options) core.Result {
if agent == "" {
agent = "codex"
}
core.Print(nil, "dispatched %s to %s", agent, repo)
core.Print(nil, "dispatched %s to %s", agent, input.Repo)
if out.WorkspaceDir != "" {
core.Print(nil, " workspace: %s", out.WorkspaceDir)
}
@ -126,3 +116,13 @@ func (s *PrepSubsystem) cmdWorkspaceDispatch(options core.Options) core.Result {
}
return core.Result{OK: true}
}
func workspaceDispatchInputFromOptions(options core.Options) DispatchInput {
dispatchOptions := core.NewOptions(options.Items()...)
if dispatchOptions.String("repo") == "" {
if repo := optionStringValue(options, "_arg", "repo"); repo != "" {
dispatchOptions.Set("repo", repo)
}
}
return dispatchInputFromOptions(dispatchOptions)
}

View file

@ -157,3 +157,35 @@ func TestCommandsworkspace_CmdWorkspaceDispatch_Ugly_AllFieldsSet(t *testing.T)
// The test verifies the CLI correctly passes all fields through to dispatch.
assert.False(t, r.OK)
}
func TestCommandsworkspace_WorkspaceDispatchInputFromOptions_Good_MapsFullContract(t *testing.T) {
input := workspaceDispatchInputFromOptions(core.NewOptions(
core.Option{Key: "_arg", Value: "go-io"},
core.Option{Key: "task", Value: "ship the release"},
core.Option{Key: "agent", Value: "codex:gpt-5.4"},
core.Option{Key: "org", Value: "core"},
core.Option{Key: "template", Value: "coding"},
core.Option{Key: "plan_template", Value: "bug-fix"},
core.Option{Key: "variables", Value: map[string]any{"ISSUE": 42, "MODE": "deep"}},
core.Option{Key: "persona", Value: "code/reviewer"},
core.Option{Key: "issue", Value: "42"},
core.Option{Key: "pr", Value: 7},
core.Option{Key: "branch", Value: "feature/release"},
core.Option{Key: "tag", Value: "v0.8.0"},
core.Option{Key: "dry_run", Value: true},
))
assert.Equal(t, "go-io", input.Repo)
assert.Equal(t, "ship the release", input.Task)
assert.Equal(t, "codex:gpt-5.4", input.Agent)
assert.Equal(t, "core", input.Org)
assert.Equal(t, "coding", input.Template)
assert.Equal(t, "bug-fix", input.PlanTemplate)
assert.Equal(t, map[string]string{"ISSUE": "42", "MODE": "deep"}, input.Variables)
assert.Equal(t, "code/reviewer", input.Persona)
assert.Equal(t, 42, input.Issue)
assert.Equal(t, 7, input.PR)
assert.Equal(t, "feature/release", input.Branch)
assert.Equal(t, "v0.8.0", input.Tag)
assert.True(t, input.DryRun)
}