fix: show correct phase (e.g. 4/4) on plan completion and preserve memory
When all plan steps were completed, the post-processing block was skipped
because "completed" status wasn't handled, leaving phase stuck at 1.
Additionally, ClearMemory() deleted MEMORY.md immediately, preventing
users from reviewing completed plans in the Mini App.
- Add SetPhase(n) to directly set phase number
- Handle "completed" status in post-processing condition
- Replace ClearMemory() with SetCurrentPhase(total) + SetPlanStatus("completed")
- Update TestAutoCompleteClears to verify new retention behavior
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4e52b1cb75
commit
57a75b281b
4 changed files with 40 additions and 13 deletions
|
|
@ -396,6 +396,11 @@ func (cb *ContextBuilder) AdvancePhase() error {
|
|||
return cb.memory.AdvancePhase()
|
||||
}
|
||||
|
||||
// SetCurrentPhase sets the current phase number to n.
|
||||
func (cb *ContextBuilder) SetCurrentPhase(n int) error {
|
||||
return cb.memory.SetPhase(n)
|
||||
}
|
||||
|
||||
// GetCurrentPhase returns the current phase number.
|
||||
func (cb *ContextBuilder) GetCurrentPhase() int {
|
||||
return cb.memory.GetCurrentPhase()
|
||||
|
|
|
|||
|
|
@ -833,7 +833,7 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
|
|||
|
||||
// 5a. Auto-advance plan phases after LLM iteration
|
||||
postStatus := agent.ContextBuilder.GetPlanStatus()
|
||||
if agent.ContextBuilder.HasActivePlan() && (postStatus == "executing" || postStatus == "review") {
|
||||
if agent.ContextBuilder.HasActivePlan() && (postStatus == "executing" || postStatus == "review" || postStatus == "completed") {
|
||||
// Intercept: if AI changed status to executing or review without user approval
|
||||
// (from interviewing or review), validate and hold at "review".
|
||||
if preStatus == "interviewing" || (preStatus == "review" && postStatus == "executing") {
|
||||
|
|
@ -862,7 +862,11 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
|
|||
logger.WarnCF("agent", "Reverted plan to interviewing: no phases defined",
|
||||
map[string]interface{}{"agent_id": agent.ID})
|
||||
} else if agent.ContextBuilder.IsPlanComplete() {
|
||||
_ = agent.ContextBuilder.ClearMemory()
|
||||
// Mark plan as completed (keep memory for review; user can /plan clear)
|
||||
total := agent.ContextBuilder.GetTotalPhases()
|
||||
_ = agent.ContextBuilder.SetCurrentPhase(total)
|
||||
if preStatus != "completed" {
|
||||
_ = agent.ContextBuilder.SetPlanStatus("completed")
|
||||
if !constants.IsInternalChannel(opts.Channel) {
|
||||
al.bus.PublishOutbound(bus.OutboundMessage{
|
||||
Channel: opts.Channel,
|
||||
|
|
@ -871,6 +875,7 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
|
|||
SkipPlaceholder: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if agent.ContextBuilder.IsCurrentPhaseComplete() {
|
||||
prev := agent.ContextBuilder.GetCurrentPhase()
|
||||
_ = agent.ContextBuilder.AdvancePhase()
|
||||
|
|
|
|||
|
|
@ -1317,7 +1317,7 @@ Test
|
|||
}
|
||||
}
|
||||
|
||||
// TestAutoCompleteClears verifies that plan is cleared when all phases are complete.
|
||||
// TestAutoCompleteClears verifies that plan is marked completed with correct phase when all phases are complete.
|
||||
func TestAutoCompleteClears(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "agent-auto-complete-*")
|
||||
if err != nil {
|
||||
|
|
@ -1369,9 +1369,15 @@ Test
|
|||
t.Fatalf("ProcessDirectWithChannel failed: %v", err)
|
||||
}
|
||||
|
||||
// Plan should be cleared
|
||||
if agent.ContextBuilder.HasActivePlan() {
|
||||
t.Error("expected plan to be cleared after completion")
|
||||
// Plan should be kept with status "completed" and phase set to total
|
||||
if !agent.ContextBuilder.HasActivePlan() {
|
||||
t.Error("expected plan to be retained after completion")
|
||||
}
|
||||
if status := agent.ContextBuilder.GetPlanStatus(); status != "completed" {
|
||||
t.Errorf("expected plan status 'completed', got %q", status)
|
||||
}
|
||||
if phase := agent.ContextBuilder.GetCurrentPhase(); phase != 1 {
|
||||
t.Errorf("expected phase 1 (total phases), got %d", phase)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -335,6 +335,17 @@ func (ms *MemoryStore) AdvancePhase() error {
|
|||
return ms.WriteLongTerm(content)
|
||||
}
|
||||
|
||||
// SetPhase sets the current phase number to n.
|
||||
func (ms *MemoryStore) SetPhase(n int) error {
|
||||
content := ms.ReadLongTerm()
|
||||
m := rePhase.FindString(content)
|
||||
if m == "" {
|
||||
return fmt.Errorf("no phase marker found")
|
||||
}
|
||||
content = strings.Replace(content, m, fmt.Sprintf("> Phase: %d", n), 1)
|
||||
return ms.WriteLongTerm(content)
|
||||
}
|
||||
|
||||
// MarkStep marks the nth step (1-based) in the given phase as done [x].
|
||||
func (ms *MemoryStore) MarkStep(phase, step int) error {
|
||||
content := ms.ReadLongTerm()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue