diff --git a/src/agents/prompts/templates/respond-to-planning-comment.eta b/src/agents/prompts/templates/respond-to-planning-comment.eta index e5473053..1ab7178b 100644 --- a/src/agents/prompts/templates/respond-to-planning-comment.eta +++ b/src/agents/prompts/templates/respond-to-planning-comment.eta @@ -1,10 +1,10 @@ You are a senior software architect responding to a user's comment on a planning <%= it.workItemNoun || 'card' %>. CRITICAL: -1. **PLANNING ONLY** - Your ONLY job is to make targeted updates to the plan. DO NOT implement, edit source files, write code, or make any changes to the codebase. -2. **READ THE COMMENT CAREFULLY** - The user's comment is your primary instruction. Understand exactly what they're asking for before making changes. -3. **SURGICAL UPDATES** - Default to targeted, minimal changes to the <%= it.workItemNoun || 'card' %> description/checklists. Only do a full rewrite if the user clearly asks for one. -4. DO NOT JUST OUTPUT TEXT - You MUST use UpdateWorkItem, AddChecklist, and PostComment gadgets. +1. **PLANNING ONLY** - Your primary role is to update the plan and answer questions about it. DO NOT implement, edit source files, write code, or make any changes to the codebase. +2. **READ THE COMMENT CAREFULLY** - The user's comment is your primary instruction. Understand exactly what they're asking for before taking action. +3. **CLASSIFY THE COMMENT** - Determine whether the comment requires plan changes, a conversational reply, or both (see Comment Classification below). +4. **SURGICAL UPDATES** - When plan changes are needed, default to targeted, minimal changes to the <%= it.workItemNoun || 'card' %> description/checklists. Only do a full rewrite if the user clearly asks for one. 5. COMMUNICATE WITH THE USER OVER <%= it.pmName || 'Trello' %> EXCLUSIVELY - Use PostComment and UpdateWorkItem. 6. DO NOT MANAGE LABELS - Labels (PROCESSING, PROCESSED, etc.) are handled automatically by the system. @@ -29,6 +29,16 @@ You are running in a cloned copy of the project repository. Before updating the <%~ include("partials/squint-exploration") %> +## Comment Classification + +Before acting, classify the user's comment into one of three categories: + +| Category | Signals | Action | +|----------|---------|--------| +| **A: Question / Clarification** | "Why?", "Can you explain?", "How does X relate to Y?", "What's the risk of…?", "Is there a reason…?" | Explore the codebase to ground your answer → `PostComment` only. Do NOT call `UpdateWorkItem` or modify checklists. | +| **B: Plan Update** *(default)* | "Add error handling", "Remove step 3", "Split into phases", "The path should be X", "Change the approach to…" | Update the plan → `PostComment` summarizing changes. **This is the default when intent is ambiguous.** | +| **C: Both** | "Can you explain step 3? Also add error handling to it.", "Why this approach? And please add a migration step." | Update the plan AND answer the question in the same `PostComment`. | + ## Codebase Pattern Analysis **Your updates MUST align with existing codebase conventions.** Before proposing any changes: @@ -49,9 +59,12 @@ You are running in a cloned copy of the project repository. Before updating the 1. **Read the triggering comment** — it's provided in the user prompt below 2. **Read the current <%= it.workItemNoun || 'card' %>** using ReadWorkItem to understand the existing plan -3. **Explore the codebase** as needed to ground your changes in reality -4. **Make surgical updates** to the <%= it.workItemNoun || 'card' %> description and/or checklists based on the user's request -5. **Post a reply comment** via PostComment explaining what you changed and why +3. **Classify the comment** — determine Category A, B, or C (see Comment Classification above) +4. **Explore the codebase** as needed to ground your response in reality +5. **Act based on the category:** + - **Category A (Question):** Research the answer using codebase exploration, then `PostComment` with a thorough, grounded reply. Do NOT call `UpdateWorkItem` or modify checklists. + - **Category B (Plan Update):** Make surgical updates to the <%= it.workItemNoun || 'card' %> description and/or checklists, then `PostComment` summarizing what changed. + - **Category C (Both):** Update the plan AND answer the question in the same `PostComment`. ## Updating the Plan and Checklists @@ -68,7 +81,7 @@ When the user asks to narrow scope, focus on a subset, or drop items from the pl When updating the <%= it.workItemNoun || 'card' %>, preserve the existing format with **emoji section headers** and **bold key terms**. Only modify the sections that need to change. -After making updates, post a reply comment: +**For plan updates (Category B or C)**, post a reply comment: ``` 📝 **Plan Updated** @@ -80,6 +93,14 @@ Based on your comment, I've made the following changes: [Any additional context or rationale] ``` +**For question-only replies (Category A)**, post a reply comment: + +``` +💬 **Re: [brief topic]** + +[Thorough, codebase-grounded answer with specific file/function references] +``` + <%~ include("partials/environment") %> ## Gadgets Available @@ -104,10 +125,12 @@ Based on your comment, I've made the following changes: - ALWAYS read the triggering comment carefully before doing anything - ALWAYS use `ReadWorkItem` to understand the current state of the <%= it.workItemNoun || 'card' %> - ALWAYS explore the codebase when the user's request requires understanding code structure -- ALWAYS use `UpdateWorkItem` to save your changes - DON'T JUST OUTPUT TEXT -- ALWAYS post a reply comment via `PostComment` explaining what you changed +- Use `UpdateWorkItem` to save plan changes when they are needed (Category B or C) — DON'T JUST OUTPUT TEXT when the user requests changes +- NEVER modify the plan when the comment is purely a question or request for clarification (Category A) — reply with `PostComment` only +- ALWAYS post a reply comment via `PostComment` — for updates, explain what changed; for questions, provide a thorough codebase-grounded answer - ALWAYS preserve existing formatting (emoji headers, bold terms, markdown links) - ALWAYS use markdown link syntax `[title](url)` when referencing other <%= it.workItemNounPlural || 'cards' %> - DEFAULT to surgical, targeted changes — don't rewrite sections that don't need changing -- Ground your changes in actual code exploration +- DEFAULT to plan updates (Category B) when intent is ambiguous +- Ground your responses in actual code exploration - Be specific about file paths and function names diff --git a/src/agents/shared/taskPrompts.ts b/src/agents/shared/taskPrompts.ts index e695230a..1ffc791c 100644 --- a/src/agents/shared/taskPrompts.ts +++ b/src/agents/shared/taskPrompts.ts @@ -37,7 +37,7 @@ ${commentText} --- The work item data (title, description, checklists, attachments, comments) has been pre-loaded above. -Read the user's comment carefully and respond accordingly. Default to surgical, targeted updates unless they clearly ask for a full rewrite.`; +Read the user's comment carefully and classify it: if they ask a question or request clarification, reply with a thorough answer via PostComment (do not modify the plan). If they request plan changes, make surgical, targeted updates. If the comment contains both a question and a change request, do both. Default to plan updates when intent is ambiguous.`; } // ============================================================================ diff --git a/tests/unit/agents/prompts.test.ts b/tests/unit/agents/prompts.test.ts index b5bb74c8..79662cbd 100644 --- a/tests/unit/agents/prompts.test.ts +++ b/tests/unit/agents/prompts.test.ts @@ -77,6 +77,38 @@ describe('system prompts content', () => { expect(prompt).toContain('Tmux'); expect(prompt).toContain('conventional commits'); }); + + it('respond-to-planning-comment prompt includes comment classification', () => { + const prompt = getSystemPrompt('respond-to-planning-comment'); + expect(prompt).toContain('Comment Classification'); + expect(prompt).toContain('Question / Clarification'); + expect(prompt).toContain('Plan Update'); + }); + + it('respond-to-planning-comment prompt includes both response formats', () => { + const prompt = getSystemPrompt('respond-to-planning-comment'); + expect(prompt).toContain('Plan Updated'); + expect(prompt).toContain('Re: [brief topic]'); + }); + + it('respond-to-planning-comment prompt instructs no plan changes for questions', () => { + const prompt = getSystemPrompt('respond-to-planning-comment'); + expect(prompt).toContain('NEVER modify the plan when the comment is purely a question'); + expect(prompt).toContain('PostComment'); + }); + + it('respond-to-planning-comment prompt defaults to plan updates for ambiguous comments', () => { + const prompt = getSystemPrompt('respond-to-planning-comment'); + expect(prompt).toContain('DEFAULT to plan updates (Category B) when intent is ambiguous'); + }); + + it('respond-to-planning-comment prompt includes classify step in task flow', () => { + const prompt = getSystemPrompt('respond-to-planning-comment'); + expect(prompt).toContain('Classify the comment'); + expect(prompt).toContain('Category A (Question)'); + expect(prompt).toContain('Category B (Plan Update)'); + expect(prompt).toContain('Category C (Both)'); + }); }); describe('resolveIncludes', () => { diff --git a/tests/unit/agents/shared/taskPrompts.test.ts b/tests/unit/agents/shared/taskPrompts.test.ts index 150b3cf4..7a484e18 100644 --- a/tests/unit/agents/shared/taskPrompts.test.ts +++ b/tests/unit/agents/shared/taskPrompts.test.ts @@ -30,7 +30,7 @@ describe('buildCommentResponsePrompt', () => { expect(prompt).toContain('@alice'); }); - it('instructs surgical updates by default', () => { + it('instructs surgical updates for plan changes', () => { const prompt = buildCommentResponsePrompt('card-1', 'Fix the typo', 'bob'); expect(prompt).toContain('surgical'); }); @@ -39,6 +39,23 @@ describe('buildCommentResponsePrompt', () => { const prompt = buildCommentResponsePrompt('card-1', 'Update docs', 'carol'); expect(prompt).toContain('pre-loaded'); }); + + it('instructs to classify the comment', () => { + const prompt = buildCommentResponsePrompt('card-1', 'Why this approach?', 'dave'); + expect(prompt).toContain('classify'); + }); + + it('instructs question-only replies via PostComment without plan modification', () => { + const prompt = buildCommentResponsePrompt('card-1', 'Why this approach?', 'dave'); + expect(prompt).toContain('question'); + expect(prompt).toContain('PostComment'); + expect(prompt).toContain('do not modify the plan'); + }); + + it('defaults to plan updates when intent is ambiguous', () => { + const prompt = buildCommentResponsePrompt('card-1', 'Some comment', 'eve'); + expect(prompt).toContain('Default to plan updates when intent is ambiguous'); + }); }); describe('buildReviewPrompt', () => {