fix(ext+hub): v0.5.2 Idle→Resume 신호 소실 3중 버그 수정 — auth_fail 재연결 + pending_owners 보존 + step-probe 리셋

This commit is contained in:
Variet Worker
2026-03-21 10:51:02 +09:00
parent 94cbda6f3d
commit 5aad82c727
9 changed files with 59 additions and 15 deletions

View File

@@ -16,7 +16,7 @@ import * as path from 'path';
import * as os from 'os';
import * as cp from 'child_process';
import { WSBridgeClient, WSResponseData, WSCommandData } from './ws-client';
import { initStepProbe, BridgeContext, writePendingApproval, tryApprovalStrategies, writeRegistration, getApprovalContext, resetPendingState, handleDiffReviewResponse, getActiveSessionId as getStepProbeSessionId, getStepProbeContext } from './step-probe';
import { initStepProbe, BridgeContext, writePendingApproval, tryApprovalStrategies, writeRegistration, getApprovalContext, resetPendingState, resetPendingStateForReconnect, handleDiffReviewResponse, getActiveSessionId as getStepProbeSessionId, getStepProbeContext } from './step-probe';
import { startHttpBridge, getDeterministicPort, HttpBridgeContext } from './http-bridge';
import { setupApprovalObserver } from './html-patcher';
import { watchCommandsDir, handleWSCommand, disposeCommandsWatcher, CommandHandlerContext } from './command-handler';
@@ -433,6 +433,8 @@ export async function activate(context: vscode.ExtensionContext) {
logToFile(`[WS] Connected: ${connId} instance=#${instanceNum}`);
statusBar.text = '$(check) Bridge WS';
statusBar.tooltip = `Gravity Bridge: ${projectName} (WS #${instanceNum})`;
// Reset step-probe state so WAITING steps are re-detected after reconnect
resetPendingStateForReconnect();
},
onDisconnected: () => {
logToFile('[WS] Disconnected — using file fallback');

View File

@@ -85,6 +85,19 @@ export function resetPendingState(): void {
ctx.sawRunningAfterPending = false;
}
/**
* Reset step-probe state after WS reconnection.
* Without this, stallProbed=true + lastPendingStepIndex=N permanently block
* re-detection of WAITING steps whose pending was lost during disconnect.
*/
export function resetPendingStateForReconnect(): void {
ctx.lastPendingStepIndex = -1;
ctx.stallProbed = false;
ctx.sawRunningAfterPending = false;
recentPendingSteps.clear();
ctx.logToFile('[STEP-PROBE] Reset pending state for WS reconnect');
}
// handleDiffReviewResponse → moved to ./approval-handler.ts
/**

View File

@@ -359,14 +359,21 @@ export class WSBridgeClient {
case 'auth_fail': {
const reason = (msg as any).reason || 'Unknown';
this.logFn(`[WS] Auth failed: ${reason}`);
// Clear session token if it was rejected
// Clear session token if it was rejected (e.g. expired after 24h)
this.sessionToken = '';
// MUST set shouldReconnect=false BEFORE _cleanup(), because _cleanup()
// closes the WS → triggers close event → _onDisconnect() → _scheduleReconnect().
// Without this, auth failures cause infinite reconnect loops.
this.shouldReconnect = false;
this._cleanup();
this.handlers.onError?.(`Auth failed: ${reason}`);
if (this.registrationCode) {
// Token expired → retry with registration code on next reconnect
this.logFn('[WS] Retrying with registration code...');
this._cleanup();
this._scheduleReconnect();
} else {
// No registration code available → permanent failure
// MUST set shouldReconnect=false BEFORE _cleanup(), because _cleanup()
// closes the WS → triggers close event → _onDisconnect() → _scheduleReconnect().
this.shouldReconnect = false;
this._cleanup();
this.handlers.onError?.(`Auth failed: ${reason}`);
}
break;
}