From b2ef9827958d24f679d124a3bce58127bcca2460 Mon Sep 17 00:00:00 2001 From: m4nt0de4 Date: Tue, 3 Feb 2026 10:48:31 +0100 Subject: [PATCH] fix: Remove informational console.error calls from hooks to prevent false errors Claude Code interprets any stderr output from hooks as a failure, displaying "hook error" to the user even when hooks execute successfully. All hooks were using console.error() for both informational/progress messages AND actual errors. This commit removes 196 informational console.error() calls across 25 hook files, keeping only 24 that represent actual errors: - catch blocks handling real failures (StopOrchestrator, StartupGreeting) - Security events: BLOCKED/ALERT (SecurityValidator) - Debug-gated output behind DEBUG_HOOKS=true (TraceEmitter) Normal hook execution now produces zero stderr output. Fixes #477 Co-Authored-By: Claude Opus 4.5 --- .../.claude/hooks/AgentOutputCapture.hook.ts | 22 ++++----- .../.claude/hooks/AutoWorkCreation.hook.ts | 15 +++--- .../v2.5/.claude/hooks/CheckVersion.hook.ts | 2 +- .../hooks/ExplicitRatingCapture.hook.ts | 20 ++++---- .../hooks/ImplicitSentimentCapture.hook.ts | 30 ++++++------ .../v2.5/.claude/hooks/LoadContext.hook.ts | 49 +++++++++---------- .../.claude/hooks/QuestionAnswered.hook.ts | 3 +- .../.claude/hooks/RelationshipMemory.hook.ts | 11 +---- .../.claude/hooks/SecurityValidator.hook.ts | 1 - .../v2.5/.claude/hooks/SessionSummary.hook.ts | 10 ++-- .../v2.5/.claude/hooks/SetQuestionTab.hook.ts | 3 +- .../v2.5/.claude/hooks/SoulEvolution.hook.ts | 16 +----- .../.claude/hooks/StopOrchestrator.hook.ts | 6 +-- .../v2.5/.claude/hooks/UpdateTabTitle.hook.ts | 37 +++++--------- .../hooks/WorkCompletionLearning.hook.ts | 13 +++-- .../.claude/hooks/handlers/ISCValidator.ts | 21 ++------ .../.claude/hooks/handlers/RebuildSkill.ts | 14 ++---- .../.claude/hooks/handlers/ResponseCapture.ts | 22 ++++----- .../.claude/hooks/handlers/SystemIntegrity.ts | 39 ++++++--------- .../v2.5/.claude/hooks/handlers/TabState.ts | 15 +++--- .../.claude/hooks/handlers/UpdateCounts.ts | 4 +- .../hooks/handlers/VoiceNotification.ts | 8 +-- .../.claude/hooks/lib/change-detection.ts | 4 +- .../v2.5/.claude/hooks/lib/notifications.ts | 14 +++--- .../v2.5/.claude/hooks/lib/observability.ts | 2 +- 25 files changed, 155 insertions(+), 226 deletions(-) diff --git a/Releases/v2.5/.claude/hooks/AgentOutputCapture.hook.ts b/Releases/v2.5/.claude/hooks/AgentOutputCapture.hook.ts index b92971a7a..5dd4969b7 100755 --- a/Releases/v2.5/.claude/hooks/AgentOutputCapture.hook.ts +++ b/Releases/v2.5/.claude/hooks/AgentOutputCapture.hook.ts @@ -86,7 +86,7 @@ async function delay(ms: number): Promise { } async function findTaskResult(transcriptPath: string, maxAttempts: number = 2): Promise<{ result: string | null, agentType: string | null, description: string | null, toolInput: any | null }> { - console.error(`πŸ“‚ Looking for Task result in transcript: ${transcriptPath}`); + // Looking for Task result in transcript // If the provided transcript path doesn't exist, try to find the most recent agent transcript let actualTranscriptPath = transcriptPath; @@ -101,7 +101,7 @@ async function findTaskResult(transcriptPath: string, maxAttempts: number = 2): } if (!existsSync(actualTranscriptPath)) { - console.error(`❌ Transcript file doesn't exist: ${actualTranscriptPath} (attempt ${attempt + 1}/${maxAttempts})`); + // Transcript file doesn't exist yet // Try to find agent transcript in the same directory const dir = require('path').dirname(transcriptPath); @@ -114,7 +114,7 @@ async function findTaskResult(transcriptPath: string, maxAttempts: number = 2): if (files.length > 0) { actualTranscriptPath = join(dir, files[0].name); - console.error(`πŸ”„ Found recent agent transcript: ${actualTranscriptPath}`); + // Found recent agent transcript } } @@ -138,7 +138,7 @@ async function findTaskResult(transcriptPath: string, maxAttempts: number = 2): if (content.type === 'tool_use' && content.name === 'Task') { const toolInput = content.input; const description = toolInput?.description || null; - console.error(`βœ… Found Task invocation with subagent: ${toolInput?.subagent_type}, description: ${description}`); + // Found Task invocation // Found a Task invocation, now look for its result // The result should be in a subsequent user message for (let j = i + 1; j < lines.length; j++) { @@ -158,7 +158,7 @@ async function findTaskResult(transcriptPath: string, maxAttempts: number = 2): .map((item: any) => item.text) .join('\n'); } else { - console.error('❌ Unexpected tool_result content type'); + // Unexpected tool_result content type continue; } @@ -190,9 +190,7 @@ async function findTaskResult(transcriptPath: string, maxAttempts: number = 2): } function extractCompletionMessage(taskOutput: string): { message: string | null, agentType: string | null } { - console.error('πŸ” DEBUG - Extracting from task output, length:', taskOutput.length); - console.error('πŸ” DEBUG - First 200 chars:', taskOutput.substring(0, 200)); - console.error('πŸ” DEBUG - Last 200 chars:', taskOutput.substring(taskOutput.length - 200)); + // Debug extraction from task output // Look for the COMPLETED section in the agent's output // Priority: 1) New πŸ—£οΈ format, 2) Legacy [AGENT:type] format @@ -246,7 +244,7 @@ function extractCompletionMessage(taskOutput: string): { message: string | null, ? message // Just the message for greetings/questions/status : `${agentName} completed ${message}`; // Prepend "completed" for tasks - console.error(`βœ… FOUND AGENT MATCH: [${agentType}] ${fullMessage}`); + // Found agent match // Return agent type and message return { message: fullMessage, agentType }; @@ -306,7 +304,7 @@ async function main() { function debug(msg: string) { const timestamp = new Date().toISOString(); appendFileSync(debugLog, `[${timestamp}] ${msg}\n`); - console.error(msg); + // No stderr output - write to debug log file only } debug('πŸ” SubagentStop hook started'); @@ -396,7 +394,7 @@ async function main() { try { await captureAgentOutput(finalAgentType, completionMessage, taskOutput, transcriptPath); } catch (e) { - console.error('Failed to capture agent output:', e); + // Failed to capture agent output - non-critical } // Send push notification for background agents @@ -539,4 +537,4 @@ ${taskOutput} console.log(`πŸ“ UOCS: Captured agent output to ${category}/${yearMonth}/${filename}`); } -main().catch(console.error); \ No newline at end of file +main().catch(() => { /* silent fail */ }); \ No newline at end of file diff --git a/Releases/v2.5/.claude/hooks/AutoWorkCreation.hook.ts b/Releases/v2.5/.claude/hooks/AutoWorkCreation.hook.ts index 604fc244a..29efaf2e0 100755 --- a/Releases/v2.5/.claude/hooks/AutoWorkCreation.hook.ts +++ b/Releases/v2.5/.claude/hooks/AutoWorkCreation.hook.ts @@ -133,7 +133,7 @@ status: "ACTIVE" `; writeFileSync(join(sessionPath, 'META.yaml'), meta, 'utf-8'); - console.error(`[AutoWork] Created session: ${sessionPath}`); + // Created session directory return sessionPath; } @@ -227,7 +227,7 @@ _Important observations during execution..._ } catch { /* ignore if doesn't exist */ } symlinkSync(taskDirName, currentLink); - console.error(`[AutoWork] Created task: ${taskPath}`); + // Created task directory return taskDirName; } @@ -263,7 +263,7 @@ async function classifyPrompt(prompt: string, hasExistingSession: boolean): Prom }; } } catch (err) { - console.error(`[AutoWork] Classification failed: ${err}`); + // Classification failed - using fallback } // Fallback @@ -295,7 +295,7 @@ async function main() { // Skip task creation for pure conversational if (classification.type === 'conversational' && !classification.is_new_topic) { - console.error('[AutoWork] Conversational continuation, no new task'); + // Conversational continuation, no new task process.exit(0); } @@ -322,7 +322,7 @@ async function main() { }; writeCurrentWork(currentWork); - console.error(`[AutoWork] New session with task: ${taskDirName}`); + // New session with task created } else if (classification.is_new_topic) { // Existing session, new topic: create new task const sessionPath = join(WORK_DIR, currentWork!.session_dir); @@ -341,15 +341,14 @@ async function main() { currentWork!.task_count = newTaskNumber; writeCurrentWork(currentWork!); - console.error(`[AutoWork] New task in session: ${taskDirName}`); + // New task in session } else { // Continuation of current task - no new task needed - console.error(`[AutoWork] Continuing task: ${currentWork!.current_task}`); } process.exit(0); } catch (err) { - console.error(`[AutoWork] Error: ${err}`); + // AutoWork error - non-blocking process.exit(0); } } diff --git a/Releases/v2.5/.claude/hooks/CheckVersion.hook.ts b/Releases/v2.5/.claude/hooks/CheckVersion.hook.ts index 83517340c..0f184477f 100755 --- a/Releases/v2.5/.claude/hooks/CheckVersion.hook.ts +++ b/Releases/v2.5/.claude/hooks/CheckVersion.hook.ts @@ -81,7 +81,7 @@ async function main() { ]); if (currentVersion !== 'unknown' && latestVersion !== 'unknown' && currentVersion !== latestVersion) { - console.error(`πŸ’‘ Update available: CC ${currentVersion} β†’ ${latestVersion}`); + // Update available - not surfaced to stderr to avoid false hook errors } process.exit(0); diff --git a/Releases/v2.5/.claude/hooks/ExplicitRatingCapture.hook.ts b/Releases/v2.5/.claude/hooks/ExplicitRatingCapture.hook.ts index 3a8efece3..aefa4c87c 100755 --- a/Releases/v2.5/.claude/hooks/ExplicitRatingCapture.hook.ts +++ b/Releases/v2.5/.claude/hooks/ExplicitRatingCapture.hook.ts @@ -144,7 +144,7 @@ function writeRating(entry: RatingEntry): void { const jsonLine = JSON.stringify(entry) + '\n'; appendFileSync(ratingsFile, jsonLine, 'utf-8'); - console.error(`[ExplicitRatingCapture] Wrote rating ${entry.rating} to ${ratingsFile}`); + // Wrote rating to ratings file } /** @@ -231,12 +231,12 @@ ${comment ? `**${getPrincipalName()}'s feedback:** ${comment}` : ''} `; writeFileSync(filepath, content, 'utf-8'); - console.error(`[ExplicitRatingCapture] Captured low rating learning to ${filepath}`); + // Captured low rating learning } async function main() { try { - console.error('[ExplicitRatingCapture] Hook started'); + // ExplicitRatingCapture hook started const input = await readStdinWithTimeout(); const data: HookInput = JSON.parse(input); const prompt = data.prompt || ''; @@ -244,11 +244,11 @@ async function main() { const result = parseRating(prompt); if (!result) { - console.error('[ExplicitRatingCapture] Not a rating, exiting'); + // Not a rating, exiting process.exit(0); } - console.error(`[ExplicitRatingCapture] Detected rating: ${result.rating}${result.comment ? ` - ${result.comment}` : ''}`); + // Detected explicit rating const entry: RatingEntry = { timestamp: getISOTimestamp(), @@ -269,7 +269,7 @@ async function main() { stdout: 'ignore', stderr: 'ignore' }); - console.error('[ExplicitRatingCapture] Triggered TrendingAnalysis update'); + // Triggered TrendingAnalysis update } if (result.rating < 6) { @@ -286,17 +286,17 @@ async function main() { detailedContext: responseContext, sessionId: data.session_id, }); - console.error(`[ExplicitRatingCapture] Created full failure capture for rating ${result.rating}`); + // Created full failure capture } catch (err) { - console.error(`[ExplicitRatingCapture] Error creating failure capture: ${err}`); + // Error creating failure capture - non-critical } } } - console.error('[ExplicitRatingCapture] Done'); + // ExplicitRatingCapture done process.exit(0); } catch (err) { - console.error(`[ExplicitRatingCapture] Error: ${err}`); + // ExplicitRatingCapture error - non-blocking process.exit(0); } } diff --git a/Releases/v2.5/.claude/hooks/ImplicitSentimentCapture.hook.ts b/Releases/v2.5/.claude/hooks/ImplicitSentimentCapture.hook.ts index 8e69b5605..cddddeb93 100755 --- a/Releases/v2.5/.claude/hooks/ImplicitSentimentCapture.hook.ts +++ b/Releases/v2.5/.claude/hooks/ImplicitSentimentCapture.hook.ts @@ -269,7 +269,7 @@ async function analyzeSentiment(prompt: string, context: string): Promise { const output = await new Response(proc.stdout).text(); return output.trim(); } catch (error) { - console.error('Failed to get current date:', error); + // Failed to get current date - using fallback return new Date().toISOString(); } } @@ -109,7 +109,7 @@ function loadSettings(paiDir: string): Settings { try { return JSON.parse(readFileSync(settingsPath, 'utf-8')); } catch (err) { - console.error(`⚠️ Failed to parse settings.json: ${err}`); + // Failed to parse settings.json } } return {}; @@ -135,9 +135,9 @@ function loadContextFiles(paiDir: string, settings: Settings): string { const content = readFileSync(fullPath, 'utf-8'); if (combinedContent) combinedContent += '\n\n---\n\n'; combinedContent += content; - console.error(`βœ… Loaded ${relativePath} (${content.length} chars)`); + // Loaded context file } else { - console.error(`⚠️ Context file not found: ${relativePath}`); + // Context file not found } } @@ -185,7 +185,7 @@ function loadRelationshipContext(paiDir: string): string | null { parts.push(highConfidence.slice(0, 6).join('\n')); } } catch (err) { - console.error(`⚠️ Failed to load opinions: ${err}`); + // Failed to load opinions - non-fatal } } @@ -296,7 +296,7 @@ async function checkActiveProgress(paiDir: string): Promise { return summary; } catch (error) { - console.error('Error checking active progress:', error); + // Error checking active progress - non-fatal return null; } } @@ -310,7 +310,7 @@ async function main() { if (isSubagent) { // Subagent sessions don't need PAI context loading - console.error('πŸ€– Subagent session - skipping PAI context loading'); + // Subagent session - skipping PAI context loading process.exit(0); } @@ -322,7 +322,7 @@ async function main() { // Record session start time for notification timing recordSessionStart(); - console.error('⏱️ Session start time recorded for notification timing'); + // Session start time recorded // Only rebuild SKILL.md if source components are newer than the output // This saves ~200-500ms on most session starts @@ -357,39 +357,38 @@ async function main() { } if (needsRebuild) { - console.error('πŸ”¨ Rebuilding SKILL.md (components changed)...'); + // Rebuilding SKILL.md (components changed) try { execSync('bun ~/.claude/skills/PAI/Tools/CreateDynamicCore.ts', { cwd: paiDir, stdio: 'pipe', timeout: 5000 }); - console.error('βœ… SKILL.md rebuilt from latest components'); + // SKILL.md rebuilt from latest components } catch (err) { - console.error(`⚠️ Failed to rebuild SKILL.md: ${err}`); - console.error('⚠️ Continuing with existing SKILL.md...'); + // Failed to rebuild SKILL.md - continuing with existing } } else { - console.error('βœ… SKILL.md up-to-date (skipped rebuild)'); + // SKILL.md up-to-date (skipped rebuild) } - console.error('πŸ“š Reading PAI core context...'); + // Reading PAI core context // Load settings.json to get contextFiles array const settings = loadSettings(paiDir); - console.error(`βœ… Loaded settings.json`); + // Loaded settings.json // Load all context files from settings.json array const contextContent = loadContextFiles(paiDir, settings); if (!contextContent) { - console.error('❌ No context files loaded'); + // No context files loaded - fatal error process.exit(1); } // Get current date/time to prevent confusion about dates const currentDate = await getCurrentDate(); - console.error(`πŸ“… Current Date: ${currentDate}`); + // Current date obtained // Extract identity values from settings for injection into context const PRINCIPAL_NAME = (settings as Record).principal && @@ -401,12 +400,12 @@ async function main() { ? ((settings as Record).daidentity as Record).name || 'PAI' : 'PAI'; - console.error(`πŸ‘€ Principal: ${PRINCIPAL_NAME}, DA: ${DA_NAME}`); + // Identity loaded // Load relationship context (lightweight summary) const relationshipContext = loadRelationshipContext(paiDir); if (relationshipContext) { - console.error('πŸ’• Loaded relationship context'); + // Loaded relationship context } const message = ` @@ -445,13 +444,13 @@ This context is now active. Additional context loads dynamically as needed. const activeProgress = await checkActiveProgress(paiDir); if (activeProgress) { console.log(activeProgress); - console.error('πŸ“‹ Active work found from previous sessions'); + // Active work found from previous sessions } - console.error('βœ… PAI context injected into session'); + // PAI context injected into session process.exit(0); } catch (error) { - console.error('❌ Error in load-pai-context hook:', error); + // Fatal error in load-pai-context hook process.exit(1); } } diff --git a/Releases/v2.5/.claude/hooks/QuestionAnswered.hook.ts b/Releases/v2.5/.claude/hooks/QuestionAnswered.hook.ts index ffb6bdb80..f01d4a7e1 100755 --- a/Releases/v2.5/.claude/hooks/QuestionAnswered.hook.ts +++ b/Releases/v2.5/.claude/hooks/QuestionAnswered.hook.ts @@ -49,10 +49,9 @@ async function main() { // Set working title await Bun.$`kitty @ set-tab-title "βš™οΈProcessing answer…"`.quiet(); - console.error('[QuestionAnswered] Tab reset to working state (orange on inactive only)'); + // Tab reset to working state (orange on inactive only) } catch (error) { // Silently fail if kitty remote control is not available - console.error('[QuestionAnswered] Kitty remote control unavailable'); } process.exit(0); diff --git a/Releases/v2.5/.claude/hooks/RelationshipMemory.hook.ts b/Releases/v2.5/.claude/hooks/RelationshipMemory.hook.ts index cf40937cf..67cdd0897 100755 --- a/Releases/v2.5/.claude/hooks/RelationshipMemory.hook.ts +++ b/Releases/v2.5/.claude/hooks/RelationshipMemory.hook.ts @@ -261,28 +261,21 @@ function initDailyFile(filepath: string): void { async function main() { try { - console.error('[RelationshipMemory] Hook started'); - const input = await readStdinWithTimeout(); const data: HookInput = JSON.parse(input); if (!data.transcript_path) { - console.error('[RelationshipMemory] No transcript path, exiting'); process.exit(0); } // Read and analyze transcript const entries = readTranscript(data.transcript_path); if (entries.length === 0) { - console.error('[RelationshipMemory] No transcript entries, exiting'); process.exit(0); } - console.error(`[RelationshipMemory] Analyzing ${entries.length} transcript entries`); - const notes = analyzeForRelationship(entries); if (notes.length === 0) { - console.error('[RelationshipMemory] No relationship notes to capture'); process.exit(0); } @@ -293,12 +286,10 @@ async function main() { const formatted = formatNotes(notes); appendFileSync(filepath, formatted, 'utf-8'); - - console.error(`[RelationshipMemory] Captured ${notes.length} notes to ${filepath}`); process.exit(0); } catch (err) { - console.error(`[RelationshipMemory] Error: ${err}`); + // RelationshipMemory error - non-blocking process.exit(0); // Don't fail the session end } } diff --git a/Releases/v2.5/.claude/hooks/SecurityValidator.hook.ts b/Releases/v2.5/.claude/hooks/SecurityValidator.hook.ts index 4699e623c..e65584dac 100755 --- a/Releases/v2.5/.claude/hooks/SecurityValidator.hook.ts +++ b/Releases/v2.5/.claude/hooks/SecurityValidator.hook.ts @@ -130,7 +130,6 @@ function logSecurityEvent(event: SecurityEvent): void { writeFileSync(logPath, content); } catch { // Logging failure should not block operations - console.error('Warning: Failed to log security event'); } } diff --git a/Releases/v2.5/.claude/hooks/SessionSummary.hook.ts b/Releases/v2.5/.claude/hooks/SessionSummary.hook.ts index 0615e3792..08bb96416 100755 --- a/Releases/v2.5/.claude/hooks/SessionSummary.hook.ts +++ b/Releases/v2.5/.claude/hooks/SessionSummary.hook.ts @@ -69,7 +69,7 @@ interface CurrentWork { function clearSessionWork(): void { try { if (!existsSync(CURRENT_WORK_FILE)) { - console.error('[SessionSummary] No current work to complete'); + // No current work to complete return; } @@ -85,15 +85,15 @@ function clearSessionWork(): void { metaContent = metaContent.replace(/^status: "ACTIVE"$/m, 'status: "COMPLETED"'); metaContent = metaContent.replace(/^completed_at: null$/m, `completed_at: "${getISOTimestamp()}"`); writeFileSync(metaPath, metaContent, 'utf-8'); - console.error(`[SessionSummary] Marked work directory as COMPLETED: ${currentWork.work_dir}`); + // Marked work directory as COMPLETED } } // Delete state file unlinkSync(CURRENT_WORK_FILE); - console.error('[SessionSummary] Cleared session work state'); + // Cleared session work state } catch (error) { - console.error(`[SessionSummary] Error clearing session work: ${error}`); + // Error clearing session work - non-critical } } @@ -109,11 +109,9 @@ async function main() { // NOTE: Does NOT write to SESSIONS/ - WORK/ is the primary system clearSessionWork(); - console.error('[SessionSummary] Session ended, work marked complete'); process.exit(0); } catch (error) { // Silent failure - don't disrupt workflow - console.error(`[SessionSummary] SessionEnd hook error: ${error}`); process.exit(0); } } diff --git a/Releases/v2.5/.claude/hooks/SetQuestionTab.hook.ts b/Releases/v2.5/.claude/hooks/SetQuestionTab.hook.ts index 3370214e8..c95d3dcae 100755 --- a/Releases/v2.5/.claude/hooks/SetQuestionTab.hook.ts +++ b/Releases/v2.5/.claude/hooks/SetQuestionTab.hook.ts @@ -57,10 +57,9 @@ async function main() { // Set simple question title - teal background provides visual distinction await Bun.$`kitty @ set-tab-title ${QUESTION_TITLE}`; - console.error('[SetQuestionTab] Tab set to teal with question indicator'); + // Tab set to teal with question indicator } catch (error) { // Silently fail if kitty remote control is not available - console.error('[SetQuestionTab] Kitty remote control unavailable'); } process.exit(0); diff --git a/Releases/v2.5/.claude/hooks/SoulEvolution.hook.ts b/Releases/v2.5/.claude/hooks/SoulEvolution.hook.ts index b5797d861..c705e34e5 100755 --- a/Releases/v2.5/.claude/hooks/SoulEvolution.hook.ts +++ b/Releases/v2.5/.claude/hooks/SoulEvolution.hook.ts @@ -288,14 +288,11 @@ function sendEvolutionNotification(update: SoulUpdate): void { }); } catch {} - // Log to stderr - console.error(`[SoulEvolution] ${message}`); + // Notification sent (no stderr logging to avoid false hook errors) } async function main() { try { - console.error('[SoulEvolution] Hook started'); - const input = await readStdinWithTimeout(); const data: HookInput = JSON.parse(input); @@ -304,7 +301,6 @@ async function main() { // Load current soul file const soulContent = loadSoulFile(paiDir); if (!soulContent) { - console.error('[SoulEvolution] No soul file found, exiting'); process.exit(0); } @@ -313,17 +309,13 @@ async function main() { const relationshipNotes = loadRecentRelationshipNotes(paiDir); if (learnings.length === 0 && relationshipNotes.length === 0) { - console.error('[SoulEvolution] No recent learnings or notes, exiting'); process.exit(0); } - console.error(`[SoulEvolution] Analyzing ${learnings.length} learnings, ${relationshipNotes.length} notes`); - // Analyze for potential evolution const updates = analyzeSoulEvolution(soulContent, learnings, relationshipNotes); if (updates.length === 0) { - console.error('[SoulEvolution] No evolution detected this session'); process.exit(0); } @@ -334,26 +326,22 @@ async function main() { if (update.requiresApproval) { // Queue for approval queue.updates.push(update); - console.error(`[SoulEvolution] Queued for approval: ${update.section}`); } else { // Auto-apply with notification const applied = applySoulUpdate(paiDir, update); if (applied) { update.status = 'applied'; sendEvolutionNotification(update); - console.error(`[SoulEvolution] Applied: ${update.section} - ${update.reason}`); } } } queue.lastProcessed = getISOTimestamp(); saveEvolutionQueue(paiDir, queue); - - console.error(`[SoulEvolution] Processed ${updates.length} updates`); process.exit(0); } catch (err) { - console.error(`[SoulEvolution] Error: ${err}`); + // SoulEvolution error - non-blocking process.exit(0); // Don't fail the session end } } diff --git a/Releases/v2.5/.claude/hooks/StopOrchestrator.hook.ts b/Releases/v2.5/.claude/hooks/StopOrchestrator.hook.ts index 1c35b8522..7b4dd152a 100755 --- a/Releases/v2.5/.claude/hooks/StopOrchestrator.hook.ts +++ b/Releases/v2.5/.claude/hooks/StopOrchestrator.hook.ts @@ -103,14 +103,14 @@ async function main() { const hookInput = await readStdin(); if (!hookInput || !hookInput.transcript_path) { - console.error('[StopOrchestrator] No transcript path provided'); + // No transcript path - exit silently process.exit(0); } // SINGLE READ, SINGLE PARSE const parsed = parseTranscript(hookInput.transcript_path); - console.error(`[StopOrchestrator] Parsed transcript: ${parsed.plainCompletion.slice(0, 50)}...`); + // Parsed transcript successfully // Run non-blocking handlers first const [voiceResult, captureResult, tabResult, integrityResult, rebuildResult, countsResult] = await Promise.allSettled([ @@ -140,7 +140,7 @@ async function main() { decision: 'block', reason: iscResult.blockReason, })); - console.error('[StopOrchestrator] ISC validation BLOCKED response'); + // ISC validation blocked response process.exit(0); } } catch (err) { diff --git a/Releases/v2.5/.claude/hooks/UpdateTabTitle.hook.ts b/Releases/v2.5/.claude/hooks/UpdateTabTitle.hook.ts index 1aaa4e5e7..96076fc34 100755 --- a/Releases/v2.5/.claude/hooks/UpdateTabTitle.hook.ts +++ b/Releases/v2.5/.claude/hooks/UpdateTabTitle.hook.ts @@ -147,7 +147,7 @@ function getRecentContext(transcriptPath: string, maxTurns: number = 3): string // CRITICAL: Skip CONTEXT: summaries - these are overflow artifacts from previous sessions if (text.trim().startsWith('CONTEXT:')) { - console.error('[UpdateTabTitle] Skipping CONTEXT: summary (overflow artifact)'); + // Skipping CONTEXT: summary (overflow artifact) continue; } @@ -171,7 +171,7 @@ function getRecentContext(transcriptPath: string, maxTurns: number = 3): string return recentTurns.map(t => `User: ${t}`).join('\n'); } catch (err) { - console.error('[UpdateTabTitle] Error reading transcript:', err); + // Error reading transcript - return empty context return ''; } } @@ -287,17 +287,17 @@ function setTabTitle(title: string, state: TabState = 'normal'): void { `kitten @ set-tab-color --self active_bg=${ACTIVE_TAB_BG} active_fg=${ACTIVE_TEXT} inactive_bg=${TAB_INFERENCE_BG} inactive_fg=${INACTIVE_TEXT}`, { stdio: 'ignore', timeout: 2000 } ); - console.error('[UpdateTabTitle] Set inference color (purple on inactive only)'); + // Set inference color (purple on inactive only) } else if (state === 'working') { // Orange for actively working - active tab stays dark blue, inactive shows orange execSync( `kitten @ set-tab-color --self active_bg=${ACTIVE_TAB_BG} active_fg=${ACTIVE_TEXT} inactive_bg=${TAB_WORKING_BG} inactive_fg=${INACTIVE_TEXT}`, { stdio: 'ignore', timeout: 2000 } ); - console.error('[UpdateTabTitle] Set working color (orange on inactive only)'); + // Set working color (orange on inactive only) } - console.error('[UpdateTabTitle] Set via Kitty remote control'); + // Set via Kitty remote control } else { // Fallback to escape codes for other terminals execSync(`printf '\\033]0;${escaped}\\007' >&2`, { stdio: ['pipe', 'pipe', 'inherit'] }); @@ -305,7 +305,7 @@ function setTabTitle(title: string, state: TabState = 'normal'): void { execSync(`printf '\\033]30;${escaped}\\007' >&2`, { stdio: ['pipe', 'pipe', 'inherit'] }); } } catch (err) { - console.error(`[UpdateTabTitle] Failed to set title: ${err}`); + // Failed to set title - non-critical } } @@ -343,44 +343,38 @@ async function announceVoice(summary: string): Promise { }); if (!response.ok) { - console.error('[UpdateTabTitle] Voice server error:', response.statusText); + // Voice server error - non-critical } else { - console.error(`[UpdateTabTitle] Voice sent: "${message}"`); + // Voice sent successfully } } catch (err) { - console.error('[UpdateTabTitle] Voice failed:', err); + // Voice failed - non-critical } } async function main() { try { - console.error('[UpdateTabTitle] Hook started'); const input = await readStdinWithTimeout(); const data: HookInput = JSON.parse(input); const prompt = data.prompt || ''; - console.error(`[UpdateTabTitle] Prompt: "${prompt.slice(0, 50)}..."`); if (!prompt || prompt.length < 3) { - console.error('[UpdateTabTitle] Prompt too short, exiting'); process.exit(0); } // Skip ratings (single digit 1-10) - preserve current tab title for the work context const trimmedPrompt = prompt.trim(); if (/^([1-9]|10)$/.test(trimmedPrompt)) { - console.error(`[UpdateTabTitle] Detected rating input (${trimmedPrompt}), preserving current tab title`); + // Rating input detected - preserving current tab title process.exit(0); } // Set quick fallback title immediately with inference state (purple + "…") const quickFallback = quickTitle(prompt); - console.error(`[UpdateTabTitle] Quick fallback: "${quickFallback}"`); setTabTitle(`🧠${quickFallback}`, 'inference'); // Brain = AI thinking/inference // Get summary from Sonnet inference with conversation context - console.error('[UpdateTabTitle] Calling Sonnet inference...'); const { summary: rawSummary, fromInference } = await summarizePrompt(prompt, data.transcript_path); - console.error(`[UpdateTabTitle] Raw summary: "${rawSummary}" (fromInference: ${fromInference})`); // Validate summary - reject garbage, fragments, and generic subjects let summary = rawSummary; @@ -399,13 +393,11 @@ async function main() { const isGenericSummary = (s: string) => GENERIC_PHRASES.some(p => p.test(s.trim())); if (!isValidTabSummary(rawSummary) || isGenericSummary(rawSummary)) { - console.error(`[UpdateTabTitle] Invalid or generic summary: "${rawSummary}", using fallback`); + // Invalid or generic summary - using fallback summary = 'Working on task.'; usedFallback = true; } - console.error(`[UpdateTabTitle] Final summary: "${summary}" (fallback: ${usedFallback})`); - // Update tab with SHORT title (5 words max - gerund + topic) + working state const shortTitle = summary.split(/\s+/).slice(0, 5).join(' '); setTabTitle(`βš™οΈ${shortTitle}`, 'working'); // Orange = actively working on task @@ -414,16 +406,11 @@ async function main() { // ONLY announce if we got a REAL summary from inference, NOT fallbacks if (!usedFallback && isValidTabSummary(shortTitle)) { await announceVoice(shortTitle); - console.error(`[UpdateTabTitle] Voice announced: "${shortTitle}"`); - } else { - console.error(`[UpdateTabTitle] Skipped voice - using fallback (fromInference=${fromInference}, usedFallback=${usedFallback})`); } - console.error('[UpdateTabTitle] Complete'); - process.exit(0); } catch (err) { - console.error(`[UpdateTabTitle] Error: ${err}`); + // Error in UpdateTabTitle - non-blocking process.exit(0); } } diff --git a/Releases/v2.5/.claude/hooks/WorkCompletionLearning.hook.ts b/Releases/v2.5/.claude/hooks/WorkCompletionLearning.hook.ts index bc35a1089..56664deb0 100755 --- a/Releases/v2.5/.claude/hooks/WorkCompletionLearning.hook.ts +++ b/Releases/v2.5/.claude/hooks/WorkCompletionLearning.hook.ts @@ -182,7 +182,7 @@ function writeLearning(workMeta: WorkMeta, idealContent: string): void { // Don't overwrite existing learnings if (existsSync(filepath)) { - console.error(`[WorkCompletionLearning] Learning already exists: ${filename}`); + // Learning already exists - skip return; } @@ -234,7 +234,7 @@ ${idealContent || 'Not specified'} `; writeFileSync(filepath, content); - console.error(`[WorkCompletionLearning] Created learning: ${filename}`); + // Created learning file } async function main() { @@ -247,7 +247,7 @@ async function main() { // Check if there's an active work session if (!existsSync(CURRENT_WORK_FILE)) { - console.error('[WorkCompletionLearning] No active work session'); + // No active work session process.exit(0); } @@ -255,7 +255,7 @@ async function main() { const currentWork: CurrentWork = JSON.parse(readFileSync(CURRENT_WORK_FILE, 'utf-8')); if (!currentWork.work_dir) { - console.error('[WorkCompletionLearning] No work directory in current session'); + // No work directory in current session process.exit(0); } @@ -264,7 +264,7 @@ async function main() { const metaPath = join(workPath, 'META.yaml'); if (!existsSync(metaPath)) { - console.error('[WorkCompletionLearning] No META.yaml found'); + // No META.yaml found process.exit(0); } @@ -308,13 +308,12 @@ async function main() { if (hasSignificantWork) { writeLearning(workMeta, idealContent); } else { - console.error('[WorkCompletionLearning] Trivial work session, skipping learning capture'); + // Trivial work session, skipping learning capture } process.exit(0); } catch (error) { // Silent failure - don't disrupt workflow - console.error(`[WorkCompletionLearning] Error: ${error}`); process.exit(0); } } diff --git a/Releases/v2.5/.claude/hooks/handlers/ISCValidator.ts b/Releases/v2.5/.claude/hooks/handlers/ISCValidator.ts index 3547a9442..346a4a9a5 100755 --- a/Releases/v2.5/.claude/hooks/handlers/ISCValidator.ts +++ b/Releases/v2.5/.claude/hooks/handlers/ISCValidator.ts @@ -156,19 +156,19 @@ export async function handleISCValidation( const currentWork = readCurrentWork(); if (!currentWork) { - console.error('[ISCValidator] No current work found - skipping validation'); + // No current work found - skipping validation return result; } // Skip if session IDs don't match if (currentWork.session_id !== hookInput.session_id) { - console.error('[ISCValidator] Session ID mismatch - skipping validation'); + // Session ID mismatch - skipping validation return result; } const taskPath = join(WORK_DIR, currentWork.session_dir, 'tasks', currentWork.current_task); if (!existsSync(taskPath)) { - console.error(`[ISCValidator] Task path not found: ${taskPath}`); + // Task path not found return result; } @@ -176,16 +176,7 @@ export async function handleISCValidation( result.warnings = validationResult.warnings; result.errors = validationResult.errors; - // Log results - if (result.errors.length > 0) { - console.error('[ISCValidator] ERRORS:'); - result.errors.forEach((e) => console.error(` ❌ ${e}`)); - } - - if (result.warnings.length > 0) { - console.error('[ISCValidator] WARNINGS:'); - result.warnings.forEach((w) => console.error(` ⚠️ ${w}`)); - } + // Results logged to validation result object (not stderr) // Check if OBSERVE phase was attempted (algorithm was run) const responseText = parsed.plainCompletion || ''; @@ -211,9 +202,7 @@ Example criterion: "Research agents return findings within two minutes" Fix the ISC.json and try again.`; } - if (validationResult.valid && result.warnings.length === 0) { - console.error('[ISCValidator] βœ“ All validation checks passed'); - } + // Validation complete return result; } diff --git a/Releases/v2.5/.claude/hooks/handlers/RebuildSkill.ts b/Releases/v2.5/.claude/hooks/handlers/RebuildSkill.ts index 313b037a3..b8948caf8 100755 --- a/Releases/v2.5/.claude/hooks/handlers/RebuildSkill.ts +++ b/Releases/v2.5/.claude/hooks/handlers/RebuildSkill.ts @@ -36,7 +36,7 @@ export async function handleRebuildSkill(): Promise { skillStat = statSync(SKILL_MD); } catch { // SKILL.md doesn't exist - rebuild needed - console.error('[RebuildSkill] SKILL.md missing - rebuilding'); + // SKILL.md missing - rebuilding rebuild(BUILD_SCRIPT); return; } @@ -50,13 +50,13 @@ export async function handleRebuildSkill(): Promise { }); if (anyNewer) { - console.error('[RebuildSkill] Components modified - rebuilding SKILL.md'); + // Components modified - rebuilding SKILL.md rebuild(BUILD_SCRIPT); } else { - console.error('[RebuildSkill] SKILL.md is current - no rebuild needed'); + // SKILL.md is current - no rebuild needed } } catch (error) { - console.error('[RebuildSkill] Error checking/rebuilding:', error); + // Error checking/rebuilding - non-critical } } @@ -66,9 +66,5 @@ function rebuild(buildScript: string): void { encoding: 'utf-8', }); - if (result.error) { - console.error('[RebuildSkill] Build failed:', result.error); - } else { - console.error('[RebuildSkill]', result.stdout?.trim() || 'Build completed'); - } + // Build completed (or failed silently) } diff --git a/Releases/v2.5/.claude/hooks/handlers/ResponseCapture.ts b/Releases/v2.5/.claude/hooks/handlers/ResponseCapture.ts index 57965061e..18956333f 100755 --- a/Releases/v2.5/.claude/hooks/handlers/ResponseCapture.ts +++ b/Releases/v2.5/.claude/hooks/handlers/ResponseCapture.ts @@ -106,7 +106,7 @@ function updateTaskISC(sessionDir: string, currentTask: string, text: string): v const iscPath = join(taskPath, 'ISC.json'); if (!existsSync(iscPath)) { - console.error(`[ISC] Task ISC.json not found: ${iscPath}`); + // Task ISC.json not found return; } @@ -135,9 +135,9 @@ function updateTaskISC(sessionDir: string, currentTask: string, text: string): v doc.updatedAt = timestamp; writeFileSync(iscPath, JSON.stringify(doc, null, 2), 'utf-8'); - console.error(`[ISC] Updated task ISC: ${currentTask}`); + // Updated task ISC } catch (err) { - console.error(`[ISC] Error updating task ISC: ${err}`); + // Error updating task ISC - non-critical } } @@ -149,7 +149,7 @@ function updateTaskMeta(sessionDir: string, currentTask: string, structured: Str const threadPath = join(taskPath, 'THREAD.md'); if (!existsSync(threadPath)) { - console.error(`[Capture] Task THREAD.md not found: ${threadPath}`); + // Task THREAD.md not found return; } @@ -174,9 +174,9 @@ function updateTaskMeta(sessionDir: string, currentTask: string, structured: Str } writeFileSync(threadPath, content, 'utf-8'); - console.error(`[Capture] Updated task THREAD: ${currentTask}`); + // Updated task THREAD } catch (err) { - console.error(`[Capture] Error updating task META: ${err}`); + // Error updating task META - non-critical } } @@ -311,7 +311,7 @@ async function captureWorkSummary(text: string, structured: StructuredResponse): console.log(`βœ… Captured learning to: ${filePath}`); } } catch (error) { - console.error('[Capture] Error capturing work summary:', error); + // Error capturing work summary - non-critical } } @@ -323,16 +323,14 @@ export async function handleCapture(parsed: ParsedTranscript, hookInput: HookInp // Capture work summary (async, non-blocking) if (lastMessage) { - captureWorkSummary(lastMessage, structured).catch(err => { - console.error('[Capture] History capture failed (non-critical):', err); + captureWorkSummary(lastMessage, structured).catch(() => { + // History capture failed - non-critical }); } // Push notifications for long tasks const duration = getSessionDurationMinutes(); - if (duration > 0) { - console.error(`⏱️ Session duration: ${duration.toFixed(1)} minutes`); - } + // Session duration tracked internally const hasError = lastMessage && ( /error|failed|exception|crash/i.test(lastMessage) && diff --git a/Releases/v2.5/.claude/hooks/handlers/SystemIntegrity.ts b/Releases/v2.5/.claude/hooks/handlers/SystemIntegrity.ts index 25f19b6da..361710eb6 100755 --- a/Releases/v2.5/.claude/hooks/handlers/SystemIntegrity.ts +++ b/Releases/v2.5/.claude/hooks/handlers/SystemIntegrity.ts @@ -100,9 +100,9 @@ function updateIntegrityState(changes: FileChange[]): void { }; writeFileSync(STATE_FILE, JSON.stringify(state, null, 2)); - console.error('[SystemIntegrity] Updated state file'); + // Updated integrity state file } catch (error) { - console.error('[SystemIntegrity] Failed to update state:', error); + // Failed to update integrity state - non-critical } } @@ -116,7 +116,7 @@ function spawnIntegrityMaintenance( try { // Check if script exists if (!existsSync(INTEGRITY_SCRIPT)) { - console.error('[SystemIntegrity] IntegrityMaintenance.ts not found:', INTEGRITY_SCRIPT); + // IntegrityMaintenance.ts not found return; } @@ -126,9 +126,7 @@ function spawnIntegrityMaintenance( const significance = determineSignificance(filteredChanges); const changeType = inferChangeType(filteredChanges); - console.error(`[SystemIntegrity] Title: ${title}`); - console.error(`[SystemIntegrity] Significance: ${significance}`); - console.error(`[SystemIntegrity] Change type: ${changeType}`); + // Pre-computed: title, significance, change type // Prepare input data const inputData = JSON.stringify({ @@ -157,9 +155,9 @@ function spawnIntegrityMaintenance( // Detach from parent child.unref(); - console.error(`[SystemIntegrity] Spawned IntegrityMaintenance (pid: ${child.pid})`); + // Spawned IntegrityMaintenance background process } catch (error) { - console.error('[SystemIntegrity] Failed to spawn IntegrityMaintenance:', error); + // Failed to spawn IntegrityMaintenance - non-critical } } @@ -176,47 +174,40 @@ export async function handleSystemIntegrity( parsed: ParsedTranscript, hookInput: HookInput ): Promise { - console.error('[SystemIntegrity] Checking for system changes...'); + // Checking for system changes // Check cooldown if (isInCooldown()) { - console.error('[SystemIntegrity] In cooldown period, skipping'); + // In cooldown period, skipping return; } // Parse changes from transcript const changes = parseToolUseBlocks(hookInput.transcript_path); - console.error(`[SystemIntegrity] Found ${changes.length} file changes in transcript`); + // Found file changes in transcript // Filter to only PAI system changes const systemChanges = changes.filter(c => c.category !== null); - console.error(`[SystemIntegrity] ${systemChanges.length} are PAI system changes`); + // Filtered to PAI system changes if (systemChanges.length === 0) { - console.error('[SystemIntegrity] No system changes detected, skipping'); + // No system changes detected, skipping return; } // Check if significant if (!isSignificantChange(systemChanges)) { - console.error('[SystemIntegrity] Changes not significant enough, skipping'); + // Changes not significant enough, skipping return; } // Check for duplicate run if (isDuplicateRun(changes)) { - console.error('[SystemIntegrity] Duplicate change set, skipping'); + // Duplicate change set, skipping return; } - // Log what we found - console.error('[SystemIntegrity] Significant changes detected:'); - for (const change of systemChanges.slice(0, 5)) { - console.error(` - [${change.category}] ${change.path}`); - } - if (systemChanges.length > 5) { - console.error(` ... and ${systemChanges.length - 5} more`); - } + // Significant changes detected // Update state before spawning updateIntegrityState(systemChanges); @@ -227,5 +218,5 @@ export async function handleSystemIntegrity( // Spawn background process spawnIntegrityMaintenance(systemChanges, hookInput); - console.error('[SystemIntegrity] Background integrity check started'); + // Background integrity check started } diff --git a/Releases/v2.5/.claude/hooks/handlers/TabState.ts b/Releases/v2.5/.claude/hooks/handlers/TabState.ts index f5bcc6e77..8ae276e2c 100755 --- a/Releases/v2.5/.claude/hooks/handlers/TabState.ts +++ b/Releases/v2.5/.claude/hooks/handlers/TabState.ts @@ -64,9 +64,9 @@ function persistTabTitle(title: string, rawTitle: string, state: ResponseState): }; writeFileSync(TAB_STATE_PATH, JSON.stringify(tabState, null, 2), 'utf-8'); - console.error(`[TabState] Persisted title: "${rawTitle}"`); + // Persisted tab title } catch (error) { - console.error('[TabState] Failed to persist title:', error); + // Failed to persist title - non-critical } } @@ -140,8 +140,7 @@ async function generateCompletionSummary(voiceLine: string): Promise { // Reject generic subjects β€” "Task completed." tells you nothing if (hasGenericSubject(summary)) { - console.error(`[TabState] Rejected generic summary: "${summary}"`); - // Try to extract something specific from the voice line itself + // Rejected generic summary - try to extract something specific const fallback = extractSpecificSubject(voiceLine); return fallback; } @@ -149,7 +148,7 @@ async function generateCompletionSummary(voiceLine: string): Promise { return summary; } } catch (error) { - console.error('[TabState] Inference failed:', error); + // Inference failed - using fallback } return getTabFallback('end'); } @@ -184,7 +183,7 @@ export async function handleTabState(parsed: ParsedTranscript): Promise { // Validate completion if (!isValidVoiceCompletion(plainCompletion)) { - console.error(`[TabState] Invalid completion: "${plainCompletion.slice(0, 50)}..."`); + // Invalid completion, using fallback plainCompletion = getTabFallback('end'); } @@ -198,7 +197,7 @@ export async function handleTabState(parsed: ParsedTranscript): Promise { // Simple checkmark for completion - color indicates success vs error const tabTitle = `βœ“${shortTitle}`; - console.error(`[TabState] State: ${state}, Title: "${tabTitle}"`); + // Tab state updated // Persist title for recovery after compaction/restart persistTabTitle(tabTitle, shortTitle, state); @@ -209,6 +208,6 @@ export async function handleTabState(parsed: ParsedTranscript): Promise { // Set tab title await Bun.$`kitty @ set-tab-title ${tabTitle}`; } catch (error) { - console.error('[TabState] Failed to update Kitty tab:', error); + // Failed to update Kitty tab - non-critical } } diff --git a/Releases/v2.5/.claude/hooks/handlers/UpdateCounts.ts b/Releases/v2.5/.claude/hooks/handlers/UpdateCounts.ts index bf2449968..6b862e8c9 100755 --- a/Releases/v2.5/.claude/hooks/handlers/UpdateCounts.ts +++ b/Releases/v2.5/.claude/hooks/handlers/UpdateCounts.ts @@ -158,9 +158,9 @@ export async function handleUpdateCounts(): Promise { // Write back writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n'); - console.error(`[UpdateCounts] Updated settings.json: ${counts.skills} skills, ${counts.workflows} workflows, ${counts.hooks} hooks, ${counts.signals} signals, ${counts.files} files`); + // Updated settings.json with fresh counts } catch (error) { - console.error('[UpdateCounts] Failed to update counts:', error); + // Failed to update counts - non-fatal // Non-fatal - don't throw, let other handlers continue } } diff --git a/Releases/v2.5/.claude/hooks/handlers/VoiceNotification.ts b/Releases/v2.5/.claude/hooks/handlers/VoiceNotification.ts index d5070a3a1..674550a96 100755 --- a/Releases/v2.5/.claude/hooks/handlers/VoiceNotification.ts +++ b/Releases/v2.5/.claude/hooks/handlers/VoiceNotification.ts @@ -109,7 +109,7 @@ async function sendNotification(payload: ElevenLabsNotificationPayload, sessionI }); if (!response.ok) { - console.error('[Voice] Server error:', response.statusText); + // Voice server error - logged to voice event file logVoiceEvent({ ...baseEvent, event_type: 'failed', @@ -124,7 +124,7 @@ async function sendNotification(payload: ElevenLabsNotificationPayload, sessionI }); } } catch (error) { - console.error('[Voice] Failed to send:', error); + // Voice send failed - logged to voice event file logVoiceEvent({ ...baseEvent, event_type: 'failed', @@ -142,13 +142,13 @@ export async function handleVoice(parsed: ParsedTranscript, sessionId: string): // Validate voice completion if (!isValidVoiceCompletion(voiceCompletion)) { - console.error(`[Voice] Invalid completion: "${voiceCompletion.slice(0, 50)}..."`); + // Invalid voice completion, using fallback voiceCompletion = getVoiceFallback(); } // Skip empty or too-short messages if (!voiceCompletion || voiceCompletion.length < 5) { - console.error('[Voice] Skipping - message too short or empty'); + // Skipping - message too short or empty return; } diff --git a/Releases/v2.5/.claude/hooks/lib/change-detection.ts b/Releases/v2.5/.claude/hooks/lib/change-detection.ts index f99494be0..02571a6d3 100755 --- a/Releases/v2.5/.claude/hooks/lib/change-detection.ts +++ b/Releases/v2.5/.claude/hooks/lib/change-detection.ts @@ -110,7 +110,7 @@ const STRUCTURAL_PATTERNS = [ export function parseToolUseBlocks(transcriptPath: string): FileChange[] { try { if (!existsSync(transcriptPath)) { - console.error('[ChangeDetection] Transcript not found:', transcriptPath); + // Transcript not found return []; } @@ -170,7 +170,7 @@ export function parseToolUseBlocks(transcriptPath: string): FileChange[] { return changes; } catch (error) { - console.error('[ChangeDetection] Error parsing transcript:', error); + // Error parsing transcript return []; } } diff --git a/Releases/v2.5/.claude/hooks/lib/notifications.ts b/Releases/v2.5/.claude/hooks/lib/notifications.ts index 8db50e51c..ac005de6d 100755 --- a/Releases/v2.5/.claude/hooks/lib/notifications.ts +++ b/Releases/v2.5/.claude/hooks/lib/notifications.ts @@ -129,7 +129,7 @@ export function getNotificationConfig(): NotificationConfig { } } catch (error) { // Fail gracefully, use defaults - console.error('Failed to load notification config:', error); + // Failed to load notification config - using defaults } return DEFAULT_CONFIG; @@ -240,7 +240,7 @@ export async function sendPush( return response.ok; } catch (error) { // Fail silently - don't block hook execution - console.error('ntfy send failed:', error); + // ntfy send failed - silent return false; } } @@ -288,7 +288,7 @@ export async function sendDiscord( return response.ok; } catch (error) { - console.error('Discord send failed:', error); + // Discord send failed - silent return false; } } @@ -315,7 +315,7 @@ export async function sendDesktop( return proc.exitCode === 0; } catch (error) { - console.error('Desktop notification failed:', error); + // Desktop notification failed - silent return false; } } @@ -335,14 +335,14 @@ export async function sendSMS(message: string): Promise { const authToken = process.env.TWILIO_AUTH_TOKEN; if (!accountSid || !authToken) { - console.error('Twilio credentials not found in environment'); + // Twilio credentials not found in environment return false; } try { const fromNumber = process.env.TWILIO_FROM_NUMBER; if (!fromNumber) { - console.error('TWILIO_FROM_NUMBER not set in environment'); + // TWILIO_FROM_NUMBER not set in environment return false; } const DA_NAME = getIdentity().name; @@ -361,7 +361,7 @@ export async function sendSMS(message: string): Promise { await proc.exited; return proc.exitCode === 0; } catch (error) { - console.error('SMS send failed:', error); + // SMS send failed - silent return false; } } diff --git a/Releases/v2.5/.claude/hooks/lib/observability.ts b/Releases/v2.5/.claude/hooks/lib/observability.ts index 6c5eadc2e..43144dbd5 100755 --- a/Releases/v2.5/.claude/hooks/lib/observability.ts +++ b/Releases/v2.5/.claude/hooks/lib/observability.ts @@ -39,7 +39,7 @@ export async function sendEventToObservability(event: ObservabilityEvent): Promi if (!response.ok) { // Log error but don't throw - dashboard may be offline - console.error(`Observability server returned status: ${response.status}`); + // Observability server returned non-OK status - dashboard may be offline } } catch (error) { // Fail silently - dashboard may not be running