feat: Add summary skip logic to prevent duplicate and trivial summaries

Added "WHEN NOT TO SUMMARIZE" section to buildSummaryPrompt that instructs the SDK to skip creating summaries for:
- Work already covered in previous prompts (prevents duplicates)
- Conversational banter with no deliverables
- Trivial requests (questions, status checks)
- Meta-discussions about memory system without shipped changes

Implementation:
- src/sdk/prompts.ts: Added WHEN NOT TO SUMMARIZE section with <skip_summary> output format
- src/sdk/parser.ts: Added skip_summary detection before parsing full summary XML
- src/sdk/parser.ts: Fixed observation type validation to include all 6 types (bugfix, feature, refactor, change, discovery, decision)

This should eliminate the duplicate summaries like the three "restore 6 types" summaries we saw for session d9137878.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2025-10-22 00:07:30 -04:00
parent 63f930a433
commit 2952b7fb8d
3 changed files with 41 additions and 7 deletions
File diff suppressed because one or more lines are too long
+14 -2
View File
@@ -62,7 +62,7 @@ export function parseObservations(text: string, correlationId?: string): ParsedO
}
// Validate type
const validTypes = ['change', 'discovery', 'decision'];
const validTypes = ['bugfix', 'feature', 'refactor', 'change', 'discovery', 'decision'];
if (!validTypes.includes(type.trim())) {
logger.warn('PARSER', `Invalid observation type: ${type}, skipping`, { correlationId });
continue;
@@ -97,9 +97,21 @@ export function parseObservations(text: string, correlationId?: string): ParsedO
/**
* Parse summary XML block from SDK response
* Returns null if no valid summary found
* Returns null if no valid summary found or if summary was skipped
*/
export function parseSummary(text: string, sessionId?: number): ParsedSummary | null {
// Check for skip_summary first
const skipRegex = /<skip_summary\s+reason="([^"]+)"\s*\/>/;
const skipMatch = skipRegex.exec(text);
if (skipMatch) {
logger.info('PARSER', 'Summary skipped', {
sessionId,
reason: skipMatch[1]
});
return null;
}
// Match <summary>...</summary> block (non-greedy)
const summaryRegex = /<summary>([\s\S]*?)<\/summary>/;
const summaryMatch = summaryRegex.exec(text);
+11
View File
@@ -164,6 +164,17 @@ CRITICAL: Describe what was delivered to the project, NOT what the memory system
User's Original Request: ${session.user_prompt}
WHEN NOT TO SUMMARIZE
----------------------
Do NOT create a summary if:
- **Already summarized**: This work was covered in a previous prompt's summary (check if it's just continuation)
- **Conversational banter**: User is chatting, joking, or making casual comments with no deliverables
- **Trivial requests**: Simple questions, status checks, or explanations that don't result in shipped work
- **No meaningful observations**: All observations were skipped or there's nothing substantial to document
- **Meta-discussions about memory**: Talking about the memory system itself without shipping changes to it
If any of these apply, **output only**: <skip_summary reason="[brief reason]" />
✅ GOOD - Describes deliverables:
<request>Fix authentication timeout bug</request>
<request>Add three-tier verbosity system to session summaries</request>