// SPDX-License-Identifier: EUPL-1.2 package agentic import ( "context" "testing" core "dappco.re/go/core" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestCommandsPlan_CmdPlanCheck_Good_CompletePlan(t *testing.T) { dir := t.TempDir() t.Setenv("CORE_WORKSPACE", dir) s := newTestPrep(t) _, created, err := s.planCreate(context.Background(), nil, PlanCreateInput{ Title: "Check Plan", Description: "Confirm the plan check command reports completion", Phases: []Phase{ { Name: "Setup", Tasks: []PlanTask{ {ID: "1", Title: "Review RFC", Status: "completed"}, }, }, }, }) require.NoError(t, err) plan, err := readPlan(PlansRoot(), created.ID) require.NoError(t, err) r := s.cmdPlanCheck(core.NewOptions(core.Option{Key: "_arg", Value: plan.Slug})) require.True(t, r.OK) output, ok := r.Value.(PlanCheckOutput) require.True(t, ok) assert.True(t, output.Success) assert.True(t, output.Complete) assert.Empty(t, output.Pending) assert.Equal(t, plan.Slug, output.Plan.Slug) } func TestCommandsPlan_CmdPlanCheck_Bad_MissingSlug(t *testing.T) { s := newTestPrep(t) r := s.cmdPlanCheck(core.NewOptions()) assert.False(t, r.OK) require.Error(t, r.Value.(error)) assert.Contains(t, r.Value.(error).Error(), "slug is required") } func TestCommandsPlan_CmdPlanCheck_Ugly_IncompletePhase(t *testing.T) { dir := t.TempDir() t.Setenv("CORE_WORKSPACE", dir) s := newTestPrep(t) _, created, err := s.planCreate(context.Background(), nil, PlanCreateInput{ Title: "Incomplete Plan", Description: "Leave one task pending", Phases: []Phase{ { Number: 1, Name: "Setup", Tasks: []PlanTask{ {ID: "1", Title: "Review RFC", Status: "completed"}, {ID: "2", Title: "Patch code", Status: "pending"}, }, }, }, }) require.NoError(t, err) plan, err := readPlan(PlansRoot(), created.ID) require.NoError(t, err) r := s.cmdPlanCheck(core.NewOptions( core.Option{Key: "slug", Value: plan.Slug}, core.Option{Key: "phase", Value: 1}, )) assert.False(t, r.OK) output, ok := r.Value.(PlanCheckOutput) require.True(t, ok) assert.False(t, output.Complete) assert.Equal(t, 1, output.Phase) assert.Equal(t, "Setup", output.PhaseName) assert.Equal(t, []string{"Patch code"}, output.Pending) } func TestCommandsPlan_CmdPlan_Good_RoutesCreate(t *testing.T) { dir := t.TempDir() t.Setenv("CORE_WORKSPACE", dir) s := newTestPrep(t) r := s.cmdPlan(core.NewOptions( core.Option{Key: "action", Value: "create"}, core.Option{Key: "slug", Value: "root-route-plan"}, core.Option{Key: "title", Value: "Root Route Plan"}, core.Option{Key: "objective", Value: "Exercise the root plan router"}, )) require.True(t, r.OK) output, ok := r.Value.(PlanCreateOutput) require.True(t, ok) assert.True(t, output.Success) assert.NotEmpty(t, output.ID) assert.NotEmpty(t, output.Path) } func TestCommandsPlan_CmdPlan_Good_RoutesStatus(t *testing.T) { dir := t.TempDir() t.Setenv("CORE_WORKSPACE", dir) s := newTestPrep(t) _, created, err := s.planCreate(context.Background(), nil, PlanCreateInput{ Title: "Status Route Plan", Description: "Exercise the root plan router status action", }) require.NoError(t, err) plan, err := readPlan(PlansRoot(), created.ID) require.NoError(t, err) r := s.cmdPlan(core.NewOptions( core.Option{Key: "action", Value: "status"}, core.Option{Key: "slug", Value: plan.Slug}, )) require.True(t, r.OK) output, ok := r.Value.(PlanCompatibilityGetOutput) require.True(t, ok) assert.True(t, output.Success) assert.Equal(t, plan.Slug, output.Plan.Slug) } func TestCommandsPlan_CmdPlan_Bad_UnknownAction(t *testing.T) { s := newTestPrep(t) r := s.cmdPlan(core.NewOptions( core.Option{Key: "action", Value: "does-not-exist"}, )) require.False(t, r.OK) require.Error(t, r.Value.(error)) assert.Contains(t, r.Value.(error).Error(), "unknown plan command") } 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) s := newTestPrep(t) _, created, err := s.planCreate(context.Background(), nil, PlanCreateInput{ Title: "Action Check Plan", Description: "Confirm the plan check action reports completion", Phases: []Phase{ { Name: "Setup", Tasks: []PlanTask{ {ID: "1", Title: "Review RFC", Status: "completed"}, }, }, }, }) require.NoError(t, err) plan, err := readPlan(PlansRoot(), created.ID) require.NoError(t, err) r := s.handlePlanCheck(context.Background(), core.NewOptions( core.Option{Key: "slug", Value: plan.Slug}, )) require.True(t, r.OK) output, ok := r.Value.(PlanCheckOutput) require.True(t, ok) assert.True(t, output.Success) assert.True(t, output.Complete) assert.Equal(t, plan.Slug, output.Plan.Slug) } func TestCommandsPlan_CmdPlanTemplates_Good(t *testing.T) { s := testPrepWithPlatformServer(t, nil, "") r := s.cmdPlanTemplates(core.NewOptions( core.Option{Key: "category", Value: "development"}, )) require.True(t, r.OK) output, ok := r.Value.(TemplateListOutput) require.True(t, ok) assert.True(t, output.Success) assert.NotZero(t, output.Total) } func TestCommandsPlan_CmdPlanTemplates_Ugly_NoMatchingCategory(t *testing.T) { s := testPrepWithPlatformServer(t, nil, "") r := s.cmdPlanTemplates(core.NewOptions( core.Option{Key: "category", Value: "does-not-exist"}, )) require.True(t, r.OK) output, ok := r.Value.(TemplateListOutput) require.True(t, ok) assert.True(t, output.Success) assert.Zero(t, output.Total) assert.Empty(t, output.Templates) } func TestCommandsPlan_RegisterPlanCommands_Good_SpecAliasRegistered(t *testing.T) { c := core.New(core.WithOption("name", "test")) s := &PrepSubsystem{ServiceRuntime: core.NewServiceRuntime(c, AgentOptions{})} s.registerPlanCommands() assert.Contains(t, c.Commands(), "agentic:plan") assert.Contains(t, c.Commands(), "plan") assert.Contains(t, c.Commands(), "agentic:plan/templates") assert.Contains(t, c.Commands(), "plan/templates") assert.Contains(t, c.Commands(), "agentic:plan/create") assert.Contains(t, c.Commands(), "agentic:plan/get") assert.Contains(t, c.Commands(), "plan/get") assert.Contains(t, c.Commands(), "agentic:plan/list") assert.Contains(t, c.Commands(), "agentic:plan/read") assert.Contains(t, c.Commands(), "plan/read") assert.Contains(t, c.Commands(), "agentic:plan/show") assert.Contains(t, c.Commands(), "plan/show") assert.Contains(t, c.Commands(), "agentic:plan/status") assert.Contains(t, c.Commands(), "plan/update") assert.Contains(t, c.Commands(), "agentic:plan/update") assert.Contains(t, c.Commands(), "plan/status") assert.Contains(t, c.Commands(), "plan/update_status") assert.Contains(t, c.Commands(), "agentic:plan/update_status") assert.Contains(t, c.Commands(), "agentic:plan/check") assert.Contains(t, c.Commands(), "plan/check") assert.Contains(t, c.Commands(), "agentic:plan/archive") assert.Contains(t, c.Commands(), "plan/archive") assert.Contains(t, c.Commands(), "agentic:plan/delete") assert.Contains(t, c.Commands(), "plan/delete") }