fix(extension): diff_review 2-strategy deploy + 8s pending delay
- Deploy AcknowledgeCascadeCodeEdit RPC strategy (was in source but never compiled) - Add 8s setTimeout delay for diff_review pending (AI response arrives on Discord first) - Capture closure variables for delayed pending creation safety - known-issues: diff_review pending ordering fix
This commit is contained in:
@@ -556,3 +556,10 @@
|
||||
- **원인**: AG의 stacked code review는 VS Code의 `isDirty` 상태와 무관. AG 자체 diff 시스템으로 관리되며, 파일은 이미 디스크에 저장됨
|
||||
- **해결**: (1차) `AcknowledgeCascadeCodeEdit` RPC로 직접 protocol 수락 시도 → (2차 fallback) `openReviewChanges` 패널 열기 + 수정 파일 focus + `agentAcceptAllInFile` 실행
|
||||
- **주의**: diff_review pending에 `modified_files` (전체 경로)와 `edit_step_indices` (step 번호) 포함 필수. `agentAcceptAllInFile`은 diff 에디터가 포커스된 상태에서만 동작할 수 있음
|
||||
|
||||
### [2026-03-16] diff_review pending 순서 — AI 응답보다 먼저 Discord 도착
|
||||
- **증상**: Discord에 diff_review 승인 버튼이 먼저 표시되고, AI 응답 텍스트가 나중에 도착. 유저가 승인 클릭 후에야 마지막 대화 내용을 확인할 수 있음
|
||||
- **원인**: RUNNING→IDLE 전환 시 AI 응답 snapshot과 diff_review pending이 같은 poll tick에 생성. `pending_approval_scanner`(3초)가 `chat_snapshot_scanner`보다 먼저 fire하여 버튼이 먼저 Discord에 전달됨
|
||||
- **해결**: diff_review pending 생성을 `setTimeout(8000)`으로 지연. 변수는 closure로 캡처 (`capturedSessionId`, `capturedStepCount`, 파일 목록). tracking 배열은 즉시 리셋
|
||||
- **주의**: 8초는 snapshot_scanner + Collector + Gateway + Bot 전체 경로의 전파 시간을 고려한 값. 너무 짧으면 여전히 버튼이 먼저 도착
|
||||
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
| # | 시간 | 작업 | 커밋 | 상태 |
|
||||
|---|------|------|------|------|
|
||||
| 001 | 07:30~11:10 | 승인 상태 관리 근본 원인 분석 + v0.3.12 수정 (sawRunningAfterPending gate) + approval-flow.md 시스템 Flow 문서 + known-issues 2건 추가 | `2d9fe96` | ✅ |
|
||||
| 002 | 13:25~13:48 | DOM Observer 전체 분석 + step_type 매핑 버그 수정 (write→code_edit) + diff_review 핸들러 리팩토링 (AcknowledgeCascadeCodeEdit RPC + openReviewChanges fallback) + known-issues 3건 추가 | `d521dd5` | 🔧 |
|
||||
| 002 | 13:25~14:20 | diff_review 핸들러 2-strategy 리팩토링 + 배포 불일치 발견/수정 + pending 순서 8초 지연 + 1차 테스트 (버튼 OK, RPC 미배포→재배포) + known-issues 2건 | `` | 🔧 |
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# DOM Observer 분석 + diff_review 수정
|
||||
# DOM Observer 분석 + diff_review 수정 + 배포
|
||||
|
||||
- **시간**: 2026-03-16 13:25~13:48
|
||||
- **시간**: 2026-03-16 13:25~14:20
|
||||
- **Commit**: ``
|
||||
- **Vikunja**: 미정
|
||||
- **Vikunja**: #384 diff_review 원격 승인 테스트 → 진행중
|
||||
|
||||
## 분석 결과
|
||||
|
||||
@@ -22,8 +22,20 @@ extension.ts 3,166줄 전체를 5개 기능 영역으로 분류:
|
||||
1. `AcknowledgeCascadeCodeEdit` RPC (UI 조작 불필요)
|
||||
2. `openReviewChanges` + 파일 포커스 + `agentAcceptAllInFile` (fallback)
|
||||
- pending에 `modified_files`(전체경로)와 `edit_step_indices`(step 번호) 포함
|
||||
- diff_review pending 생성을 8초 지연 (AI 응답이 먼저 Discord 도착)
|
||||
|
||||
## 테스트 결과 (1차)
|
||||
- ✅ Discord에 Accept all / Reject all 버튼 표시 확인
|
||||
- ❌ AcknowledgeCascadeCodeEdit RPC 미실행 — 소스 수정 후 컴파일+배포 누락 발견
|
||||
- ❌ AI 응답이 승인 버튼보다 늦게 Discord에 도착
|
||||
|
||||
## 수정 및 배포
|
||||
- Extension 재컴파일+배포 (2-strategy diff_review 핸들러 포함)
|
||||
- diff_review pending 8초 지연 (`setTimeout`) 추가
|
||||
- known-issues 2건 추가 (isDirty 실패, pending 순서)
|
||||
|
||||
## 미완료
|
||||
- diff_review 실제 테스트 (AG 재시작 후 Accept all 버튼 동작 확인 필요)
|
||||
- `AcknowledgeCascadeCodeEdit` RPC가 stepIndices 없이도 전체 수락하는지 확인 필요
|
||||
- **AG 풀 재시작 후 2차 E2E 테스트** 필요
|
||||
- AcknowledgeCascadeCodeEdit RPC 성공 확인
|
||||
- AI 응답 → 승인 버튼 순서 확인
|
||||
- DOM Observer 제거 리팩토링 → diff_review 동작 확인 후 진행
|
||||
|
||||
@@ -2432,25 +2432,38 @@ 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(', ');
|
||||
logToFile(`[DIFF-REVIEW] IDLE with ${pendingModifiedFiles.length} modified files: ${fileList}`);
|
||||
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: activeSessionId,
|
||||
conversation_id: capturedSessionId,
|
||||
command: `코드 리뷰: ${fileList}`,
|
||||
description: `${pendingModifiedFiles.length}개 파일이 수정되었습니다`,
|
||||
description: `${fileCount}개 파일이 수정되었습니다`,
|
||||
step_type: 'diff_review',
|
||||
step_index: currentCount,
|
||||
step_index: capturedStepCount,
|
||||
source: 'diff_review_detect',
|
||||
buttons: [
|
||||
{ text: 'Accept all', index: 0 },
|
||||
{ text: 'Reject all', index: 1 },
|
||||
],
|
||||
modified_files: pendingModifiedFilePaths.slice(0, 20),
|
||||
edit_step_indices: pendingEditStepIndices.slice(0, 20),
|
||||
modified_files: capturedModFiles,
|
||||
edit_step_indices: capturedEditSteps,
|
||||
});
|
||||
pendingModifiedFiles = []; // reset after notification
|
||||
pendingModifiedFilePaths = [];
|
||||
pendingEditStepIndices = [];
|
||||
}, 8000);
|
||||
}
|
||||
wasRunning = isRunning;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2401,25 +2401,38 @@ 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(', ');
|
||||
logToFile(`[DIFF-REVIEW] IDLE with ${pendingModifiedFiles.length} modified files: ${fileList}`);
|
||||
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: activeSessionId,
|
||||
conversation_id: capturedSessionId,
|
||||
command: `코드 리뷰: ${fileList}`,
|
||||
description: `${pendingModifiedFiles.length}개 파일이 수정되었습니다`,
|
||||
description: `${fileCount}개 파일이 수정되었습니다`,
|
||||
step_type: 'diff_review',
|
||||
step_index: currentCount,
|
||||
step_index: capturedStepCount,
|
||||
source: 'diff_review_detect',
|
||||
buttons: [
|
||||
{ text: 'Accept all', index: 0 },
|
||||
{ text: 'Reject all', index: 1 },
|
||||
],
|
||||
modified_files: pendingModifiedFilePaths.slice(0, 20),
|
||||
edit_step_indices: pendingEditStepIndices.slice(0, 20),
|
||||
modified_files: capturedModFiles,
|
||||
edit_step_indices: capturedEditSteps,
|
||||
} as any);
|
||||
pendingModifiedFiles = []; // reset after notification
|
||||
pendingModifiedFilePaths = [];
|
||||
pendingEditStepIndices = [];
|
||||
}, 8000);
|
||||
}
|
||||
wasRunning = isRunning;
|
||||
} catch (e: any) {
|
||||
|
||||
Reference in New Issue
Block a user