fix: enforce MEMORY.md header preservation and simplify /plan clear

Strengthen prompts to prevent LLM from overwriting the # Active Plan
header block. Include full header in Target Format template. Simplify
/plan clear to check ReadMemory instead of HasActivePlan so orphaned
MEMORY.md files can be cleared. Remove tg.expand() for default sizing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
dj-oyu 2026-02-22 11:28:56 +09:00
parent f93f17f8e9
commit fd2d5165a6
3 changed files with 28 additions and 14 deletions

View file

@ -82,20 +82,22 @@ Your workspace is at: %s
3. **Memory & Plans**
- Use memory/MEMORY.md for structured plans.
- NEVER remove or overwrite the header block (# Active Plan, > Task:, > Status:, > Phase:). The system parses these lines to track plan state.
- If Status is "interviewing": Ask clarifying questions.
After each answer, use edit_file to save findings to ## Context in memory/MEMORY.md.
When you have enough information, write ## Phase and ## Commands sections into MEMORY.md, then set Status to "executing".
When you have enough information, add ## Phase sections with "- [ ]" checkbox steps, and ## Commands section below the header. Then change > Status: to "executing".
- If Status is "executing": Work through the current Phase's steps.
Mark each [x] via edit_file. The system will auto-advance phases.
- Plan format:
Mark each "- [x]" via edit_file. The system will auto-advance phases.
- Plan format (header is written by the system do NOT delete it):
# Active Plan
> Task: <description>
> Status: interviewing | executing
> Phase: <current phase number>
## Phase 1: <title>
- [ ] Step 1
## Phase 2: <title>
- [ ] Step 2
## Phase 2: <title>
- [ ] Step 1
## Commands
build: <build command>
test: <test command>

View file

@ -772,7 +772,7 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
if agent.ContextBuilder.GetPlanStatus() == "interviewing" && agent.interviewStaleCount >= interviewStaleThreshold {
messages = append(messages, providers.Message{
Role: "user",
Content: "[System] You have been interviewing for several turns without updating memory/MEMORY.md. Please use edit_file now to save your findings to the ## Context section, or organize the plan into Phases if you have enough information.",
Content: "[System] You have been interviewing for several turns without updating memory/MEMORY.md. Please use edit_file now to save your findings to the ## Context section, or organize the plan into ## Phase sections with `- [ ]` checkbox steps if you have enough information.",
})
}
@ -968,7 +968,7 @@ func buildPlanReminder(planStatus string) (providers.Message, bool) {
case "interviewing":
content = "[System] You are interviewing the user to build a plan. " +
"Ask clarifying questions and save findings to ## Context in memory/MEMORY.md using edit_file. " +
"When you have enough information, write ## Phases and ## Commands sections."
"When you have enough information, write ## Phase sections with `- [ ]` checkbox steps, and ## Commands section."
case "review":
content = "[System] The plan is under review. " +
"Wait for the user to approve or request changes. Do not proceed with execution."
@ -2469,7 +2469,7 @@ func (al *AgentLoop) handlePlanCommand(args []string) (string, bool) {
sub := args[0]
switch sub {
case "clear":
if !agent.ContextBuilder.HasActivePlan() {
if agent.ContextBuilder.ReadMemory() == "" {
return "No active plan to clear.", true
}
if err := agent.ContextBuilder.ClearMemory(); err != nil {

View file

@ -449,23 +449,35 @@ func (ms *MemoryStore) GetInterviewContext() string {
sb.WriteString("- Tooling preferences (test framework, linter, formatter, CI)\n")
sb.WriteString("- Key commands the user already runs (build, test, deploy)\n")
sb.WriteString("\n### Rules\n")
sb.WriteString("- NEVER remove or overwrite the header block (`# Active Plan`, `> Task:`, `> Status:`, `> Phase:` lines). The system parses these to track state.\n")
sb.WriteString("- After each answer, use edit_file to append findings to the ## Context section of memory/MEMORY.md.\n")
sb.WriteString("- When you have enough information, use edit_file to write ## Phase, ## Commands, and ## Context sections into memory/MEMORY.md.\n")
sb.WriteString("- When you have enough information, use edit_file to add ## Phase, ## Commands, and ## Context sections BELOW the header block.\n")
sb.WriteString("- Each step MUST use checkbox syntax: `- [ ] description`. The system parses checkboxes to track progress.\n")
sb.WriteString("- Organize into 2-5 phases with 3-5 steps each.\n")
sb.WriteString("- After writing Phases, set Status to executing. The system will handle the rest.\n")
sb.WriteString("\n### Target Format\n")
sb.WriteString("```\n")
sb.WriteString("- After writing Phases, change `> Status: interviewing` to `> Status: executing` via edit_file.\n")
sb.WriteString("\n### Target Format (MANDATORY — system parses this exact structure)\n")
sb.WriteString("\n")
sb.WriteString("# Active Plan\n")
sb.WriteString("> Task: <description>\n")
sb.WriteString("> WorkDir: <path>\n")
sb.WriteString("> Status: interviewing\n")
sb.WriteString("> Phase: 1\n")
sb.WriteString("\n")
sb.WriteString("## Phase 1: <title>\n")
sb.WriteString("- [ ] Step\n")
sb.WriteString("- [ ] Step description\n")
sb.WriteString("- [ ] Step description\n")
sb.WriteString("\n")
sb.WriteString("## Phase 2: <title>\n")
sb.WriteString("- [ ] Step\n")
sb.WriteString("- [ ] Step description\n")
sb.WriteString("- [ ] Step description\n")
sb.WriteString("\n")
sb.WriteString("## Commands\n")
sb.WriteString("build: <project-specific build command>\n")
sb.WriteString("test: <project-specific test command>\n")
sb.WriteString("lint: <project-specific lint command>\n")
sb.WriteString("\n")
sb.WriteString("## Context\n")
sb.WriteString("<collected requirements, decisions, environment>\n")
sb.WriteString("```\n")
return sb.String()
}