// Part 1 of 15 of the operator console app script. // // Label imports and the in-memory client state every other part reads. // // Load order is significant: these are classic (non-module) scripts sharing one // global scope, and index.html must keep them in the order listed above/below. // Splitting is a pure line-range extraction of the former single app.js. const { riskLabels, decisionLabels, providerLabels, sourceLabels, providerStatusLabels, candidateStatusLabels, evidenceStatusLabels, knowledgeStatusLabels, provenanceLabels, knowledgeTypeLabels, } = window.OperatorLabels; const retiredProviderIds = new Set(); const operatorSearchProviders = [ { id: "naver", label: providerLabels.naver }, { id: "google_search", label: providerLabels.google_search }, ]; const submissions = []; const providers = []; const knowledgeEntries = []; const searchCoverage = {}; let suggestedQueryRunSummary = null; // { caseId, message } — 현재 케이스의 마지막 추천 쿼리 실행 결과 const knowledgeFilters = { query: "", type: "all", status: "all", active: "all" }; let editingKnowledgeEntryId = ""; let activeRerunAddedIds = new Set(); // 현재 렌더 중인 케이스의 lastRerunDiff.addedEvidenceIds const DEFAULT_COVERAGE_THRESHOLDS = Object.freeze({ coverageGoodRate: 70, coverageWarnRate: 40, queryGoodRate: 70, queryWarnRate: 40, }); const coverageThresholds = { ...DEFAULT_COVERAGE_THRESHOLDS }; const collectionCandidates = []; const corrections = []; const auditEvents = []; const decisionMemoPresets = []; const state = { currentView: "queue", workbenchTab: "evidence", knowledgeTab: "collect", currentCollectionQuery: "", currentCollectionProvider: "", selectedCaseId: submissions[0]?.id || "", apiError: "", submissionQueue: null, importStatus: { tone: "idle", message: "로컬 제출 저장소 변경 대기 중", }, filters: { risk: "all", source: "all", decision: "all", sort: "risk", query: "", }, }; const viewNames = new Set(["queue", "workbench", "knowledge", "providers", "stats", "audit"]); // Bearer token for a server started with COPYRIGHTER_AUTH_TOKEN. Held in memory // only (never localStorage/sessionStorage): the first authenticated request makes // the server mint an HttpOnly session cookie, which is what subsequently // authorizes /media requests that cannot carry a header. let authToken = ""; let pendingAuthPrompt = null;