feat(agentic): expose plan update CLI command
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
863f76fb71
commit
689b2e90e5
3 changed files with 92 additions and 0 deletions
|
|
@ -18,6 +18,8 @@ func (s *PrepSubsystem) registerPlanCommands() {
|
|||
c.Command("agentic:plan/read", core.Command{Description: "Read an implementation plan", Action: s.cmdPlanShow})
|
||||
c.Command("plan/read", core.Command{Description: "Read an implementation plan", Action: s.cmdPlanShow})
|
||||
c.Command("plan/show", core.Command{Description: "Show an implementation plan", Action: s.cmdPlanShow})
|
||||
c.Command("plan/update", core.Command{Description: "Update an implementation plan", Action: s.cmdPlanUpdate})
|
||||
c.Command("agentic:plan/update", core.Command{Description: "Update an implementation plan", Action: s.cmdPlanUpdate})
|
||||
c.Command("plan/status", core.Command{Description: "Read or update an implementation plan status", Action: s.cmdPlanStatus})
|
||||
c.Command("plan/check", core.Command{Description: "Check whether a plan or phase is complete", Action: s.cmdPlanCheck})
|
||||
c.Command("plan/archive", core.Command{Description: "Archive an implementation plan by slug or ID", Action: s.cmdPlanArchive})
|
||||
|
|
@ -174,6 +176,54 @@ func (s *PrepSubsystem) cmdPlanShow(options core.Options) core.Result {
|
|||
return core.Result{Value: output, OK: true}
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) cmdPlanUpdate(options core.Options) core.Result {
|
||||
ctx := s.commandContext()
|
||||
id := optionStringValue(options, "id", "_arg")
|
||||
slug := optionStringValue(options, "slug")
|
||||
hasChanges := options.Has("status") || options.Has("title") || options.Has("objective") || options.Has("description") || options.Has("notes") || options.Has("agent") || options.Has("context") || options.Has("phases")
|
||||
if id == "" && slug == "" {
|
||||
core.Print(nil, "usage: core-agent plan update <id-or-slug> [--status=ready] [--title=\"...\"] [--objective=\"...\"] [--description=\"...\"] [--notes=\"...\"] [--agent=codex] [--context='{\"repo\":\"go-io\"}'] [--phases='[...]']")
|
||||
return core.Result{Value: core.E("agentic.cmdPlanUpdate", "id or slug is required", nil), OK: false}
|
||||
}
|
||||
if !hasChanges {
|
||||
core.Print(nil, "usage: core-agent plan update <id-or-slug> [--status=ready] [--title=\"...\"] [--objective=\"...\"] [--description=\"...\"] [--notes=\"...\"] [--agent=codex] [--context='{\"repo\":\"go-io\"}'] [--phases='[...]']")
|
||||
return core.Result{Value: core.E("agentic.cmdPlanUpdate", "at least one update field is required", nil), OK: false}
|
||||
}
|
||||
|
||||
result := s.handlePlanUpdate(ctx, core.NewOptions(
|
||||
core.Option{Key: "id", Value: id},
|
||||
core.Option{Key: "slug", Value: slug},
|
||||
core.Option{Key: "status", Value: optionStringValue(options, "status")},
|
||||
core.Option{Key: "title", Value: optionStringValue(options, "title")},
|
||||
core.Option{Key: "objective", Value: optionStringValue(options, "objective")},
|
||||
core.Option{Key: "description", Value: optionStringValue(options, "description")},
|
||||
core.Option{Key: "context", Value: optionAnyMapValue(options, "context")},
|
||||
core.Option{Key: "phases", Value: planPhasesValue(options, "phases")},
|
||||
core.Option{Key: "notes", Value: optionStringValue(options, "notes")},
|
||||
core.Option{Key: "agent", Value: optionStringValue(options, "agent")},
|
||||
))
|
||||
if !result.OK {
|
||||
err := commandResultError("agentic.cmdPlanUpdate", result)
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
output, ok := result.Value.(PlanUpdateOutput)
|
||||
if !ok {
|
||||
err := core.E("agentic.cmdPlanUpdate", "invalid plan update output", nil)
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
core.Print(nil, "slug: %s", output.Plan.Slug)
|
||||
core.Print(nil, "title: %s", output.Plan.Title)
|
||||
core.Print(nil, "status: %s", output.Plan.Status)
|
||||
if output.Plan.Agent != "" {
|
||||
core.Print(nil, "agent: %s", output.Plan.Agent)
|
||||
}
|
||||
return core.Result{Value: output, OK: true}
|
||||
}
|
||||
|
||||
func (s *PrepSubsystem) cmdPlanStatus(options core.Options) core.Result {
|
||||
ctx := s.commandContext()
|
||||
slug := optionStringValue(options, "slug", "_arg")
|
||||
|
|
|
|||
|
|
@ -92,6 +92,44 @@ func TestCommandsPlan_CmdPlanCheck_Ugly_IncompletePhase(t *testing.T) {
|
|||
assert.Equal(t, []string{"Patch code"}, output.Pending)
|
||||
}
|
||||
|
||||
func TestCommandsPlan_CmdPlanUpdate_Good_StatusAndAgent(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", dir)
|
||||
|
||||
s := newTestPrep(t)
|
||||
_, created, err := s.planCreate(context.Background(), nil, PlanCreateInput{
|
||||
Title: "Update Command",
|
||||
Objective: "Verify the plan update command",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
r := s.cmdPlanUpdate(core.NewOptions(
|
||||
core.Option{Key: "_arg", Value: created.ID},
|
||||
core.Option{Key: "status", Value: "ready"},
|
||||
core.Option{Key: "agent", Value: "codex"},
|
||||
))
|
||||
require.True(t, r.OK)
|
||||
|
||||
output, ok := r.Value.(PlanUpdateOutput)
|
||||
require.True(t, ok)
|
||||
assert.True(t, output.Success)
|
||||
assert.Equal(t, created.ID, output.Plan.ID)
|
||||
assert.Equal(t, "ready", output.Plan.Status)
|
||||
assert.Equal(t, "codex", output.Plan.Agent)
|
||||
}
|
||||
|
||||
func TestCommandsPlan_CmdPlanUpdate_Bad_MissingFields(t *testing.T) {
|
||||
s := newTestPrep(t)
|
||||
|
||||
r := s.cmdPlanUpdate(core.NewOptions(
|
||||
core.Option{Key: "_arg", Value: "plan-123"},
|
||||
))
|
||||
|
||||
assert.False(t, r.OK)
|
||||
require.Error(t, r.Value.(error))
|
||||
assert.Contains(t, r.Value.(error).Error(), "at least one update field is required")
|
||||
}
|
||||
|
||||
func TestCommandsPlan_HandlePlanCheck_Good_CompletePlan(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
t.Setenv("CORE_WORKSPACE", dir)
|
||||
|
|
@ -139,4 +177,6 @@ func TestCommandsPlan_RegisterPlanCommands_Good_SpecAliasRegistered(t *testing.T
|
|||
assert.Contains(t, c.Commands(), "agentic:plan/read")
|
||||
assert.Contains(t, c.Commands(), "plan/read")
|
||||
assert.Contains(t, c.Commands(), "plan/show")
|
||||
assert.Contains(t, c.Commands(), "plan/update")
|
||||
assert.Contains(t, c.Commands(), "agentic:plan/update")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1416,6 +1416,8 @@ func TestCommands_RegisterCommands_Good_AllRegistered(t *testing.T) {
|
|||
assert.Contains(t, cmds, "plan/list")
|
||||
assert.Contains(t, cmds, "plan/read")
|
||||
assert.Contains(t, cmds, "plan/show")
|
||||
assert.Contains(t, cmds, "plan/update")
|
||||
assert.Contains(t, cmds, "agentic:plan/update")
|
||||
assert.Contains(t, cmds, "plan/status")
|
||||
assert.Contains(t, cmds, "plan/check")
|
||||
assert.Contains(t, cmds, "plan/archive")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue