fix: add truthful KTAP monitoring diagnostics

This commit is contained in:
2026-07-10 12:17:42 +09:00
parent fc932b27f6
commit 306d3a70a1
15 changed files with 764 additions and 33 deletions

View File

@@ -45,6 +45,12 @@
connectionState: "unavailable",
processDetected: false,
connected: false,
lastKtapConnectState: "not-attempted",
ktapConnectAttempted: false,
ktapConnectAccepted: false,
ktapHelloObserved: null,
networkMonitoringRecordExpected: false,
networkMonitoringCheckRequired: false,
commandAvailable: false,
liveTakeInAllowed: false,
nativeOutcomeUnknown: false,
@@ -419,9 +425,21 @@
"disposed": "Disposed",
"unavailable": "Unavailable"
};
elements.playoutConnectionState.textContent = connectionLabels[state.playout.connectionState] || "Unavailable";
const lastKtapLabels = {
"attempted": "마지막 KTAP 결과 미확인",
"accepted-unconfirmed": "마지막 KTAP 수락 · OnHello 미확인",
"failed": "마지막 KTAP 실패"
};
const currentConnectionLabel = connectionLabels[state.playout.connectionState] || "Unavailable";
elements.playoutConnectionState.textContent = dryRun
? "KTAP 미호출"
: (state.playout.connected && state.playout.lastKtapConnectState === "accepted-unconfirmed"
? "KTAP 수락 · OnHello 미확인"
: `${currentConnectionLabel}${lastKtapLabels[state.playout.lastKtapConnectState]
? ` · ${lastKtapLabels[state.playout.lastKtapConnectState]}`
: ""}`);
setStatusDot(elements.playoutConnectionDot, state.playout.connected
? "healthy"
? (state.playout.ktapHelloObserved === true ? "healthy" : "warn")
: (transitionalConnection ? "warn" : (bridgeReady ? "error" : "unconfigured")));
const safetyContainer = elements.playoutSafetyMode.closest(".playout-health-item");
@@ -461,15 +479,17 @@
} else if (dryRun) {
elements.playoutSummary.classList.add("dry-run");
elements.playoutSummaryBadge.textContent = "DRY RUN";
elements.playoutSummaryDetail.textContent = bridgeReady ? "안전 모드 · PROGRAM 출력 차단" : "브라우저 미리보기 전용";
elements.playoutSummaryDetail.textContent = bridgeReady ? "KTAP 미호출 · 모니터 기록 없음(정상)" : "브라우저 미리보기 전용";
} else if (state.playout.connected) {
elements.playoutSummary.classList.add("ready");
elements.playoutSummaryBadge.textContent = testMode
? (state.playout.liveTakeInAllowed ? "TEST READY" : "TEST LOCKED")
: (state.playout.liveTakeInAllowed ? "LIVE READY" : "CONNECTED");
elements.playoutSummaryDetail.textContent = testMode
? "테스트 전용 출력 · 안전 게이트 적용"
: (state.playout.processDetected ? "Tornado2 프로세스 · 엔진 연결됨" : "엔진 연결됨 · 프로세스 미감지");
elements.playoutSummaryDetail.textContent = state.playout.lastKtapConnectState === "accepted-unconfirmed"
? "KTAP 수락 · OnHello/[R]/[S] 확인 필요"
: (testMode
? "테스트 전용 출력 · 안전 게이트 적용"
: (state.playout.processDetected ? "Tornado2 프로세스 · 엔진 연결됨" : "엔진 연결됨 · 프로세스 미감지"));
} else {
elements.playoutSummary.classList.add("error");
elements.playoutSummaryBadge.textContent = bridgeReady ? "OFFLINE" : "PREVIEW";
@@ -614,6 +634,19 @@
state.playout.connectionState = playoutSafety.normalizeConnectionState(payload.connectionState);
state.playout.processDetected = payload.processDetected === true;
state.playout.connected = payload.connected === true;
state.playout.lastKtapConnectState = ["not-attempted", "attempted", "accepted-unconfirmed", "failed"]
.includes(payload.lastKtapConnectState) ? payload.lastKtapConnectState : "not-attempted";
state.playout.ktapConnectAttempted = payload.ktapConnectAttempted === true;
state.playout.ktapConnectAccepted = payload.ktapConnectAccepted === true
? true
: (payload.ktapConnectAccepted === false ? false : null);
state.playout.ktapHelloObserved = payload.ktapHelloObserved === true
? true
: (payload.ktapHelloObserved === false ? false : null);
state.playout.networkMonitoringRecordExpected = payload.networkMonitoringRecordExpected === true
? true
: (payload.networkMonitoringRecordExpected === false ? false : null);
state.playout.networkMonitoringCheckRequired = payload.networkMonitoringCheckRequired === true;
state.playout.commandAvailable = payload.commandAvailable === true;
state.playout.liveTakeInAllowed = payload.liveTakeInAllowed === true;
state.playout.nativeOutcomeUnknown = payload.outcomeUnknown === true ||
@@ -642,7 +675,7 @@
}
renderPlayout();
const signature = [state.playout.mode, state.playout.engineState, state.playout.connectionState, state.playout.processDetected, state.playout.connected, state.playout.commandAvailable, state.playout.liveTakeInAllowed, state.playout.nativeOutcomeUnknown].join("|");
const signature = [state.playout.mode, state.playout.engineState, state.playout.connectionState, state.playout.processDetected, state.playout.connected, state.playout.lastKtapConnectState, state.playout.commandAvailable, state.playout.liveTakeInAllowed, state.playout.nativeOutcomeUnknown].join("|");
if (signature !== state.playout.lastSignature) {
addLog(`Tornado 상태 · ${playoutDisplayState()} · ${state.playout.connected ? "연결" : "미연결"}`);
state.playout.lastSignature = signature;