fix: cross-project event flooding + pending accumulation + diff_review brain exclusion

Phase 1: Collector auto-cleanup of auto_resolved/expired pending files after Gateway forwarding
Phase 2: Watcher project filter (only MY sessions emit events) + Collector event forward filter
Phase 3: Extension diff_review excludes brain/ artifact files (task.md, implementation_plan.md)
This commit is contained in:
Variet Worker
2026-03-16 23:05:27 +09:00
parent 7ca0bc0f1f
commit e3f8fb93f7
3 changed files with 172 additions and 37 deletions

View File

@@ -2407,39 +2407,65 @@ function setupMonitor() {
// ── Diff review detection: if session just went IDLE and files were modified ──
if (wasRunning && !isRunning && pendingModifiedFiles.length > 0) {
const fileList = pendingModifiedFiles.slice(0, 5).join(', ');
const fileCount = pendingModifiedFiles.length;
// Capture variables for delayed closure (poll loop may change them)
const capturedSessionId = activeSessionId;
const capturedStepCount = currentCount;
const capturedModFiles = pendingModifiedFilePaths.slice(0, 20);
const capturedEditSteps = pendingEditStepIndices.slice(0, 20);
logToFile(`[DIFF-REVIEW] IDLE with ${fileCount} modified files: ${fileList}`);
// Reset tracking arrays immediately (so next session starts fresh)
pendingModifiedFiles = [];
pendingModifiedFilePaths = [];
pendingEditStepIndices = [];
// Delay diff_review pending by 8s so AI response snapshot arrives
// on Discord before the approval buttons (snapshot scanner needs time
// to relay the response text to Discord ahead of the approval embed)
setTimeout(() => {
logToFile(`[DIFF-REVIEW] deferred pending creation (8s) for: ${fileList}`);
writeChatSnapshot(`📝 **코드 리뷰 대기**\n\n수정된 파일: ${fileList}\n\nAG에서 Accept all / Reject all로 확인해주세요.`);
writePendingApproval({
conversation_id: capturedSessionId,
command: `코드 리뷰: ${fileList}`,
description: `${fileCount}개 파일이 수정되었습니다`,
step_type: 'diff_review',
step_index: capturedStepCount,
source: 'diff_review_detect',
buttons: [
{ text: 'Accept all', index: 0 },
{ text: 'Reject all', index: 1 },
],
modified_files: capturedModFiles,
edit_step_indices: capturedEditSteps,
});
}, 8000);
// Phase 3 FIX: Filter out brain/ artifact files (task.md, implementation_plan.md etc.)
// These are AG internal artifacts, NOT code changes needing user review.
const brainPathSegment = '.gemini/antigravity/brain/';
const codeOnlyFiles: string[] = [];
const codeOnlyPaths: string[] = [];
const codeOnlySteps: number[] = [];
for (let fi = 0; fi < pendingModifiedFilePaths.length; fi++) {
const normalized = pendingModifiedFilePaths[fi].replace(/\\/g, '/').toLowerCase();
if (!normalized.includes(brainPathSegment)) {
codeOnlyFiles.push(pendingModifiedFiles[fi]);
codeOnlyPaths.push(pendingModifiedFilePaths[fi]);
if (fi < pendingEditStepIndices.length) {
codeOnlySteps.push(pendingEditStepIndices[fi]);
}
} else {
logToFile(`[DIFF-REVIEW] skip brain artifact: ${pendingModifiedFiles[fi]}`);
}
}
if (codeOnlyFiles.length > 0) {
const fileList = codeOnlyFiles.slice(0, 5).join(', ');
const fileCount = codeOnlyFiles.length;
// Capture variables for delayed closure (poll loop may change them)
const capturedSessionId = activeSessionId;
const capturedStepCount = currentCount;
const capturedModFiles = codeOnlyPaths.slice(0, 20);
const capturedEditSteps = codeOnlySteps.slice(0, 20);
logToFile(`[DIFF-REVIEW] IDLE with ${fileCount} code files: ${fileList}`);
// Reset tracking arrays immediately (so next session starts fresh)
pendingModifiedFiles = [];
pendingModifiedFilePaths = [];
pendingEditStepIndices = [];
// Delay diff_review pending by 8s so AI response snapshot arrives
// on Discord before the approval buttons (snapshot scanner needs time
// to relay the response text to Discord ahead of the approval embed)
setTimeout(() => {
logToFile(`[DIFF-REVIEW] deferred pending creation (8s) for: ${fileList}`);
writeChatSnapshot(`📝 **코드 리뷰 대기**\n\n수정된 파일: ${fileList}\n\nAG에서 Accept all / Reject all로 확인해주세요.`);
writePendingApproval({
conversation_id: capturedSessionId,
command: `코드 리뷰: ${fileList}`,
description: `${fileCount}개 파일이 수정되었습니다`,
step_type: 'diff_review',
step_index: capturedStepCount,
source: 'diff_review_detect',
buttons: [
{ text: 'Accept all', index: 0 },
{ text: 'Reject all', index: 1 },
],
modified_files: capturedModFiles,
edit_step_indices: capturedEditSteps,
});
}, 8000);
} else {
logToFile(`[DIFF-REVIEW] all ${pendingModifiedFiles.length} modified files are brain artifacts — skip diff_review`);
pendingModifiedFiles = [];
pendingModifiedFilePaths = [];
pendingEditStepIndices = [];
}
}
wasRunning = isRunning;
} catch (e: any) {