diff --git a/Packs/pai-hook-system/src/hooks/handlers/SystemIntegrity.ts b/Packs/pai-hook-system/src/hooks/handlers/SystemIntegrity.ts index 34d859ce7c..99d1e66efe 100755 --- a/Packs/pai-hook-system/src/hooks/handlers/SystemIntegrity.ts +++ b/Packs/pai-hook-system/src/hooks/handlers/SystemIntegrity.ts @@ -30,6 +30,7 @@ import { determineSignificance, inferChangeType, generateDescriptiveTitle, + readIntegrityState, type FileChange, } from '../lib/change-detection'; import type { ParsedTranscript } from '../../skills/CORE/Tools/TranscriptParser'; @@ -71,7 +72,7 @@ async function notifyIntegrityStart(): Promise { /** * Update the integrity state file. */ -function updateIntegrityState(changes: FileChange[]): void { +function updateIntegrityState(changes: FileChange[], lastParsedLine: number): void { try { if (!existsSync(STATE_DIR)) { mkdirSync(STATE_DIR, { recursive: true }); @@ -81,10 +82,11 @@ function updateIntegrityState(changes: FileChange[]): void { last_run: new Date().toISOString(), last_changes_hash: hashChanges(changes), cooldown_until: getCooldownEndTime(), + last_parsed_line: lastParsedLine, }; writeFileSync(STATE_FILE, JSON.stringify(state, null, 2)); - console.error('[SystemIntegrity] Updated state file'); + console.error('[SystemIntegrity] Updated state file (parsed up to line ' + lastParsedLine + ')'); } catch (error) { console.error('[SystemIntegrity] Failed to update state:', error); } @@ -168,9 +170,14 @@ export async function handleSystemIntegrity( return; } - // Parse changes from transcript - const changes = parseToolUseBlocks(hookInput.transcript_path); - console.error(`[SystemIntegrity] Found ${changes.length} file changes in transcript`); + // Get last parsed line from state for incremental parsing + const state = readIntegrityState(); + const startLine = state?.last_parsed_line || 0; + console.error(`[SystemIntegrity] Incremental parsing from line ${startLine}`); + + // Parse changes from transcript (only new lines since last check) + const { changes, lastLine } = parseToolUseBlocks(hookInput.transcript_path, startLine); + console.error(`[SystemIntegrity] Found ${changes.length} file changes in transcript (lines ${startLine}-${lastLine})`); // Filter to only PAI system changes const systemChanges = changes.filter(c => c.category !== null); @@ -202,8 +209,8 @@ export async function handleSystemIntegrity( console.error(` ... and ${systemChanges.length - 5} more`); } - // Update state before spawning - updateIntegrityState(systemChanges); + // Update state before spawning (including last parsed line for incremental parsing) + updateIntegrityState(systemChanges, lastLine); // Send voice notification (fire-and-forget) notifyIntegrityStart().catch(() => {}); diff --git a/Packs/pai-hook-system/src/hooks/lib/change-detection.ts b/Packs/pai-hook-system/src/hooks/lib/change-detection.ts index e22559360d..30a672a800 100755 --- a/Packs/pai-hook-system/src/hooks/lib/change-detection.ts +++ b/Packs/pai-hook-system/src/hooks/lib/change-detection.ts @@ -46,6 +46,7 @@ export interface IntegrityState { last_run: string; last_changes_hash: string; cooldown_until: string | null; + last_parsed_line?: number; } // ============================================================================ @@ -106,12 +107,19 @@ const STRUCTURAL_PATTERNS = [ /** * Parse tool_use blocks from a transcript that modify files. * Extracts Write, Edit, and MultiEdit operations. + * + * @param transcriptPath - Path to the transcript file + * @param startLine - Optional line number to start parsing from (0-indexed) + * @returns Object containing changes and the last line number parsed */ -export function parseToolUseBlocks(transcriptPath: string): FileChange[] { +export function parseToolUseBlocks( + transcriptPath: string, + startLine: number = 0 +): { changes: FileChange[]; lastLine: number } { try { if (!existsSync(transcriptPath)) { console.error('[ChangeDetection] Transcript not found:', transcriptPath); - return []; + return { changes: [], lastLine: 0 }; } const content = readFileSync(transcriptPath, 'utf-8'); @@ -119,7 +127,9 @@ export function parseToolUseBlocks(transcriptPath: string): FileChange[] { const changes: FileChange[] = []; const seenPaths = new Set(); - for (const line of lines) { + // Only parse lines after startLine + for (let i = startLine; i < lines.length; i++) { + const line = lines[i]; if (!line.trim()) continue; try { @@ -168,10 +178,10 @@ export function parseToolUseBlocks(transcriptPath: string): FileChange[] { } } - return changes; + return { changes, lastLine: lines.length }; } catch (error) { console.error('[ChangeDetection] Error parsing transcript:', error); - return []; + return { changes: [], lastLine: 0 }; } }