feat(agentic): add plan archive CLI command

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 12:15:56 +00:00
parent c2e1263493
commit b7a102cc3a
2 changed files with 55 additions and 0 deletions

View file

@ -13,6 +13,7 @@ func (s *PrepSubsystem) registerPlanCommands() {
c.Command("plan/list", core.Command{Description: "List implementation plans", Action: s.cmdPlanList})
c.Command("plan/show", core.Command{Description: "Show an implementation plan", Action: s.cmdPlanShow})
c.Command("plan/status", core.Command{Description: "Read or update an implementation plan status", Action: s.cmdPlanStatus})
c.Command("plan/archive", core.Command{Description: "Archive an implementation plan by slug or ID", Action: s.cmdPlanArchive})
}
func (s *PrepSubsystem) cmdPlan(options core.Options) core.Result {
@ -163,3 +164,32 @@ func (s *PrepSubsystem) cmdPlanStatus(options core.Options) core.Result {
core.Print(nil, "status: %s", output.Plan.Status)
return core.Result{Value: output, OK: true}
}
func (s *PrepSubsystem) cmdPlanArchive(options core.Options) core.Result {
ctx := s.commandContext()
id := optionStringValue(options, "id", "slug", "_arg")
if id == "" {
core.Print(nil, "usage: core-agent plan archive <slug> [--reason=\"...\"]")
return core.Result{Value: core.E("agentic.cmdPlanArchive", "slug or id is required", nil), OK: false}
}
result := s.handlePlanArchive(ctx, core.NewOptions(
core.Option{Key: "slug", Value: id},
core.Option{Key: "reason", Value: optionStringValue(options, "reason")},
))
if !result.OK {
err := commandResultError("agentic.cmdPlanArchive", result)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
output, ok := result.Value.(PlanArchiveOutput)
if !ok {
err := core.E("agentic.cmdPlanArchive", "invalid plan archive output", nil)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
core.Print(nil, "archived: %s", output.Archived)
return core.Result{Value: output, OK: true}
}

View file

@ -937,6 +937,30 @@ func TestCommands_CmdPlanStatus_Good_GetAndSet(t *testing.T) {
assert.Equal(t, "ready", plan.Status)
}
func TestCommands_CmdPlanArchive_Good(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
_, created, err := s.planCreate(context.Background(), nil, PlanCreateInput{
Title: "Archive Plan",
Objective: "Exercise archive command",
})
require.NoError(t, err)
output := captureStdout(t, func() {
r := s.cmdPlanArchive(core.NewOptions(
core.Option{Key: "_arg", Value: created.ID},
))
assert.True(t, r.OK)
})
assert.Contains(t, output, "archived:")
plan, err := readPlan(PlansRoot(), created.ID)
require.NoError(t, err)
assert.Equal(t, "archived", plan.Status)
assert.False(t, plan.ArchivedAt.IsZero())
}
func TestCommands_CmdExtract_Good(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
target := core.JoinPath(t.TempDir(), "extract-test")
@ -1003,6 +1027,7 @@ func TestCommands_RegisterCommands_Good_AllRegistered(t *testing.T) {
assert.Contains(t, cmds, "plan/list")
assert.Contains(t, cmds, "plan/show")
assert.Contains(t, cmds, "plan/status")
assert.Contains(t, cmds, "plan/archive")
assert.Contains(t, cmds, "pr-manage")
assert.Contains(t, cmds, "task")
assert.Contains(t, cmds, "task/update")