From 12d418a4264222f74877145b1296e9129fc6ee03 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Fri, 18 Sep 2026 04:01:40 +0800 Subject: [PATCH 1/3] fix(console): sharpen operator copy and ops typography Align workspace descriptions with the three operator questions and replace Inter defaults with IBM Plex Sans / Source Serif 4 without changing permission semantics. Co-authored-by: Cursor --- tests/strategy_switch_worker_validation.mjs | 4 ++-- web/strategy-switch-console/app.css | 21 ++++++++++++++++++--- web/strategy-switch-console/app.js | 12 ++++++------ web/strategy-switch-console/app_css.js | 2 +- web/strategy-switch-console/app_js.js | 2 +- web/strategy-switch-console/index.html | 7 +++++-- web/strategy-switch-console/page_asset.js | 2 +- 7 files changed, 34 insertions(+), 16 deletions(-) diff --git a/tests/strategy_switch_worker_validation.mjs b/tests/strategy_switch_worker_validation.mjs index 9f8b5d0..4d5d98f 100644 --- a/tests/strategy_switch_worker_validation.mjs +++ b/tests/strategy_switch_worker_validation.mjs @@ -147,8 +147,8 @@ assert.ok(indexHtml.includes('switchSurface.classList.toggle("summary-hidden", ! assert.equal(indexHtml.match(/Generated by inject_platform_config\.py/g)?.length, 1); assert.ok(indexHtml.includes('')); assert.ok(indexHtml.includes('')); -assert.ok(indexHtml.includes('/app.js?v=console-clarity-v1')); -assert.ok(indexHtml.includes('/app.css?v=console-clarity-v1')); +assert.ok(indexHtml.includes('/app.js?v=console-clarity-v2')); +assert.ok(indexHtml.includes('/app.css?v=console-clarity-v2')); assert.equal(indexHtml.includes(' @@ -450,6 +453,6 @@

自动化任务

- + diff --git a/web/strategy-switch-console/page_asset.js b/web/strategy-switch-console/page_asset.js index 24ff6c6..2d4f18b 100644 --- a/web/strategy-switch-console/page_asset.js +++ b/web/strategy-switch-console/page_asset.js @@ -1,2 +1,2 @@ // Generated by python/scripts/sync_strategy_switch_page_asset.py; do not edit by hand. -export const PAGE_HTML = "\n\n\n \n \n \n QuantStrategyLab 控制台\n \n \n\n\n\n\n\n
\n
\n Q\n

QuantStrategyLab

\n

管理控制台

\n
\n \n
\n \n \n \n \n
\n
\n\n
\n
\n 初始化控制台\n

读取策略配置

\n

正在读取登录状态、账号配置和当前状态。

\n
\n
\n
\n\n
\n
\n Q\n

管理你的量化平台

\n

配置策略,关注运行,处理重要决策。

\n 登录\n
\n
\n\n
\n

\n
\n

运行总览

\n
\n
\n\n
\n
\n
\n
\n

需要你决定

\n

只有材料完整且仍需你确认的事项会出现在这里。

\n
\n
\n 等待登录\n
\n
\n
\n \n
\n 登录后查看待处理事项。\n \n
\n
\n \n \n \n
\n
\n

账户

\n
\n
\n \n \n \n \n
\n \n
\n
\n
账户配置策略运行情况最近检查账户操作
\n
\n \n

状态来自实际读回;保存配置不代表已经运行或成交。

\n
\n \n\n
\n \n \n \n\n \n \n
\n\n \n \n\n\n"; +export const PAGE_HTML = "\n\n\n \n \n \n QuantStrategyLab 控制台\n \n \n \n \n \n\n\n\n\n\n
\n
\n Q\n

QuantStrategyLab

\n

管理控制台

\n
\n \n
\n \n \n \n \n
\n
\n\n
\n
\n 初始化控制台\n

读取策略配置

\n

正在读取登录状态、账号配置和当前状态。

\n
\n
\n
\n\n
\n
\n Q\n

管理你的量化平台

\n

配置策略,关注运行,处理重要决策。

\n 登录\n
\n
\n\n
\n

\n
\n

运行总览

\n
\n
\n\n
\n
\n
\n
\n

需要你决定

\n

只有材料完整且仍需你确认的事项会出现在这里。

\n
\n
\n 等待登录\n
\n
\n
\n \n
\n 登录后查看待处理事项。\n \n
\n
\n \n \n \n
\n
\n

账户

\n
\n
\n \n \n \n \n
\n \n
\n
\n
账户配置策略运行情况最近检查账户操作
\n
\n \n

状态来自实际读回;保存配置不代表已经运行或成交。

\n
\n \n\n
\n \n \n \n\n \n \n
\n\n \n \n\n\n"; From 73d26d2c1a837a64f867823e8743db11d3a57415 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Fri, 18 Sep 2026 04:13:06 +0800 Subject: [PATCH 2/3] fix(console): prioritize research receipts Co-authored-by: Cursor --- .../scripts/execution_evidence_projection.py | 6 +++ .../test_execution_evidence_projection.py | 23 +++++++++ tests/console_runtime_state_validation.mjs | 12 +++-- tests/strategy_switch_worker_validation.mjs | 50 +++++++++++++++++++ web/strategy-switch-console/app.js | 40 ++++++--------- web/strategy-switch-console/app_js.js | 2 +- web/strategy-switch-console/index.html | 21 ++++---- web/strategy-switch-console/page_asset.js | 2 +- web/strategy-switch-console/worker.js | 6 ++- 9 files changed, 118 insertions(+), 44 deletions(-) diff --git a/python/scripts/execution_evidence_projection.py b/python/scripts/execution_evidence_projection.py index c12cb0c..611a017 100644 --- a/python/scripts/execution_evidence_projection.py +++ b/python/scripts/execution_evidence_projection.py @@ -50,6 +50,8 @@ { "not_due", "no_action", + "no_signal", + "no_rebalance", "risk_blocked", "submitted", "broker_acknowledged", @@ -72,6 +74,8 @@ _EXECUTION_RECEIPT_OUTCOME_CONFIRMATIONS = { "not_due": frozenset({"not_applicable"}), "no_action": frozenset({"not_applicable"}), + "no_signal": frozenset({"not_applicable"}), + "no_rebalance": frozenset({"not_applicable"}), "risk_blocked": frozenset({"not_applicable"}), "submitted": frozenset({"not_observed"}), "broker_acknowledged": frozenset({"acknowledged"}), @@ -298,6 +302,8 @@ def _execution_evidence_from_receipt( if receipt is None: return "pending", "target_execution_evidence_missing" outcome = receipt["outcome"] + if outcome in {"no_signal", "no_rebalance"}: + return "not_applicable", "target_execution_receipt_observed" if outcome == "reconciliation_required": return "unavailable", "target_execution_reconciliation_required" if outcome == "failed": diff --git a/python/tests/test_execution_evidence_projection.py b/python/tests/test_execution_evidence_projection.py index e30c567..5d2ebd8 100644 --- a/python/tests/test_execution_evidence_projection.py +++ b/python/tests/test_execution_evidence_projection.py @@ -52,6 +52,8 @@ def _execution_receipt(self, *, outcome: str = "filled") -> dict[str, str]: "filled": "filled", "failed": "not_observed", "reconciliation_required": "reconciliation_required", + "no_signal": "not_applicable", + "no_rebalance": "not_applicable", }[outcome] observed_at = "2026-08-25T16:00:00Z" return { @@ -143,6 +145,27 @@ def test_projects_a_matching_minimal_execution_receipt_without_order_details(sel for forbidden in ("receipt_id", "must-not-be-projected", "account_ids", "api_token", "gs://"): self.assertNotIn(forbidden, serialized) + def test_accepts_non_action_receipts_without_granting_execution_authority(self): + for outcome in ("no_signal", "no_rebalance"): + with self.subTest(outcome=outcome): + report = self._report() + report["execution_receipt"] = self._execution_receipt(outcome=outcome) + + snapshot = projection.build_execution_evidence_source_snapshot( + [report], + source_id="runtime-reports", + now=datetime(2026, 8, 25, 16, 5, tzinfo=UTC), + ) + + deployment = snapshot["deployments"][0] + self.assertEqual(deployment["evidence"]["target_execution"], "not_applicable") + self.assertEqual(deployment["recommendation"], { + "code": "parked", + "reason_code": "target_execution_receipt_observed", + }) + self.assertEqual(deployment["execution_receipt"]["outcome"], outcome) + self.assertEqual(deployment["execution_receipt"]["broker_confirmation"], "not_applicable") + def test_rejects_a_tampered_execution_receipt_without_claiming_execution(self): report = self._report() receipt = self._execution_receipt() diff --git a/tests/console_runtime_state_validation.mjs b/tests/console_runtime_state_validation.mjs index 678aefc..699a444 100644 --- a/tests/console_runtime_state_validation.mjs +++ b/tests/console_runtime_state_validation.mjs @@ -333,14 +333,18 @@ test('buildInputs keeps untouched policy layers current and serializes only touc assert.equal(touched.min_reserved_cash_usd, '100'); }); -test('account settings copy removes guesswork and keeps the two research views', () => { +test('account settings copy removes guesswork and prioritizes research candidates', () => { const html = readFileSync(new URL('../web/strategy-switch-console/index.html', import.meta.url), 'utf8'); const app = readFileSync(new URL('../web/strategy-switch-console/app.js', import.meta.url), 'utf8'); assert.ok(html.includes('id="mode-display"')); assert.ok(html.includes('id="execution-mode-select"')); assert.equal(html.includes('data-mode="live"'), false); - assert.ok(html.includes('data-research-internal-view="monitoring"')); - assert.ok(html.includes('data-research-internal-view="research"')); + assert.equal(html.includes('research-internal-tabs'), false); + assert.equal(html.includes('data-research-internal-view'), false); + assert.ok(html.includes('id="monitoring-diagnostics" hidden')); + assert.ok(html.indexOf('id="promotion-decision-panel"') < html.indexOf('id="monitoring-diagnostics"')); + assert.equal(app.includes('researchInternalView'), false); + assert.ok(app.includes('if (state.view === "research") void refreshResearchWorkspace()')); assert.equal(html.includes('需要启停或调整策略时展开'), false); assert.equal(html.includes('插件、收入层和期权的选择不授予运行许可'), false); assert.equal(app.includes('target {target} · service {service} · market {domains}'), false); @@ -750,7 +754,7 @@ test('account details keep saved, deployed and application state separate', () = const app = readFileSync(new URL('../web/strategy-switch-console/app.js', import.meta.url), 'utf8'); assert.ok(html.includes('data-i18n="overviewRuntime"')); assert.ok(html.includes('data-i18n="latestReadback"')); - assert.ok(html.indexOf('data-research-internal-view="monitoring"') < html.indexOf('id="promotion-decision-panel"')); + assert.ok(html.indexOf('id="promotion-decision-panel"') < html.indexOf('id="monitoring-diagnostics"')); assert.ok(html.includes('class="account-facts"')); assert.ok(app.includes('["deployedSwitch", accountDeploymentText(platform, account)]')); assert.ok(app.includes('["applicationStatus", application]')); diff --git a/tests/strategy_switch_worker_validation.mjs b/tests/strategy_switch_worker_validation.mjs index 4d5d98f..9dccd56 100644 --- a/tests/strategy_switch_worker_validation.mjs +++ b/tests/strategy_switch_worker_validation.mjs @@ -3446,6 +3446,56 @@ assert.deepEqual(receiptDeployment.deployment.execution_receipt, { observed_at: executionReceiptObservedAt, }); +for (const outcome of ["no_signal", "no_rebalance"]) { + const nonActionPayload = { + ...executionReceiptEvidenceSourcePayload, + source_id: `longbridge.execution_receipt.${outcome}`, + deployments: [{ + ...executionReceiptEvidenceSourcePayload.deployments[0], + deployment_id: `soxl_soxx_trend_income.${outcome}.longbridge.paper`, + strategy: { + ...executionReceiptEvidenceSourcePayload.deployments[0].strategy, + candidate_id: `soxl_soxx_trend_income.${outcome}`, + }, + evidence: { + ...executionReceiptEvidenceSourcePayload.deployments[0].evidence, + target_execution: "not_applicable", + }, + execution_receipt: { + outcome, + broker_confirmation: "not_applicable", + observed_at: executionReceiptObservedAt, + }, + }], + }; + const syncResponse = await worker.fetch( + new Request("https://switch.example/api/internal/sync-execution-evidence-source", { + method: "POST", + headers: { Authorization: `Bearer ${executionEvidenceSyncValue}`, "Content-Type": "application/json" }, + body: JSON.stringify(nonActionPayload), + }), + executionEvidenceEnv, + ); + assert.equal(syncResponse.status, 200); +} +const nonActionEvidenceRead = await worker.fetch( + new Request("https://switch.example/api/execution-evidence", { headers: executionEvidenceCookieHeaders }), + executionEvidenceEnv, +); +const nonActionEvidencePayload = await nonActionEvidenceRead.json(); +for (const outcome of ["no_signal", "no_rebalance"]) { + const deployment = nonActionEvidencePayload.deployments.find( + (entry) => entry.deployment.deployment_id === `soxl_soxx_trend_income.${outcome}.longbridge.paper`, + ); + assert.equal(deployment.deployment.evidence.target_execution, "not_applicable"); + assert.equal(deployment.deployment.recommendation.code, "parked"); + assert.deepEqual(deployment.deployment.execution_receipt, { + outcome, + broker_confirmation: "not_applicable", + observed_at: executionReceiptObservedAt, + }); +} + const runtimeTargetLifecycleSourcePayload = { schema_version: "qsl_runtime_target_lifecycle_source_snapshot.v1", source_id: "longbridge.sg", diff --git a/web/strategy-switch-console/app.js b/web/strategy-switch-console/app.js index 8be75e1..ccd4382 100644 --- a/web/strategy-switch-console/app.js +++ b/web/strategy-switch-console/app.js @@ -1412,7 +1412,6 @@ const state = { view: "overview", - researchInternalView: "monitoring", overviewFilter: "all", overviewSearch: "", lastRefreshAt: null, @@ -6421,14 +6420,7 @@ el("platform-strip-label").hidden = view !== "accounts"; el("platform-strip-label").textContent = t("activePlatform"); el("health-view").hidden = view !== "research"; - document.querySelectorAll?.("[data-research-panel]")?.forEach((panel) => { - panel.hidden = panel.dataset.researchPanel !== state.researchInternalView; - }); - document.querySelectorAll?.("[data-research-internal-view]")?.forEach((button) => { - const active = button.dataset.researchInternalView === state.researchInternalView; - button.classList?.toggle("active", active); - button.setAttribute?.("aria-selected", String(active)); - }); + el("monitoring-diagnostics").hidden = view !== "research"; el("workspace-title").textContent = t(`${view}Nav`); el("workspace-description").textContent = t(`${view}Description`); document.querySelector(".workspace-nav").hidden = !state.appReady || !state.auth.allowed; @@ -7102,9 +7094,23 @@ "); } + function refreshResearchWorkspace() { + return Promise.allSettled([ + refreshHealth(), + refreshReconciliationRecovery(), + refreshM0Research(), + refreshAdaptiveSelection(), + refreshExecutionEvidence(), + refreshResearchTasks(), + refreshResearchPromotionTickets(), + refreshRuntimeTargetLifecycle(), + ]); + } + document.querySelectorAll("[data-workspace]").forEach(button => button.addEventListener("click", () => { state.view = button.dataset.workspace; render(); + if (state.view === "research") void refreshResearchWorkspace(); el("workspace-title").focus({ preventScroll: true }); window.scrollTo({ top: 0 }); })); @@ -7124,22 +7130,6 @@ renderOverview(); el("overview-search").focus(); }); - document.querySelectorAll("[data-research-internal-view]").forEach((button) => button.addEventListener("click", () => { - state.researchInternalView = button.dataset.researchInternalView === "research" ? "research" : "monitoring"; - renderWorkspace(); - if (state.researchInternalView === "research") { - refreshHealth(); - refreshReconciliationRecovery(); - refreshM0Research(); - refreshAdaptiveSelection(); - refreshExecutionEvidence(); - refreshResearchTasks(); - refreshResearchPromotionTickets(); - } else { - refreshRuntimeTargetLifecycle(); - } - })); - document.querySelectorAll("[data-health-filter]").forEach((button) => button.addEventListener("click", () => { document.querySelectorAll("[data-health-filter]").forEach((node) => node.classList.remove("active")); button.classList.add("active"); diff --git a/web/strategy-switch-console/app_js.js b/web/strategy-switch-console/app_js.js index d7959ea..e614e67 100644 --- a/web/strategy-switch-console/app_js.js +++ b/web/strategy-switch-console/app_js.js @@ -1,2 +1,2 @@ // Generated by python/scripts/sync_strategy_switch_page_asset.py; do not edit by hand. -export const APP_JS = "\n\n function requiredInjected(name, value, fallback) {\n if (value !== undefined && value !== null) return value;\n console.error(`[strategy-switch-console] missing injected config: ${name}`);\n return fallback;\n }\n\n let platformMeta = window.__PLATFORM_META__ || {};\n const platformRepositories = window.__PLATFORM_REPOSITORIES__ || {};\n // Alias for backward compatibility\n const defaultRepositories = platformRepositories;\n\n const defaultAccountOptions = requiredInjected(\"__DEFAULT_ACCOUNT_OPTIONS__\", window.__DEFAULT_ACCOUNT_OPTIONS__, {});\n\n const domainLabels = window.__DOMAIN_LABELS__ || {\n cn_equity: { zh: \"A股\", en: \"CN A-share\" },\n crypto: { zh: \"加密\", en: \"Crypto\" },\n hk_equity: { zh: \"港股\", en: \"HK Equity\" },\n us_equity: { zh: \"美股\", en: \"US Equity\" },\n };\n\n const platformConfig = requiredInjected(\"__PLATFORM_CONFIG__\", window.__PLATFORM_CONFIG__, {});\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n const reservePolicyModes = [\"none\", \"ratio\", \"floor\", \"max\"];\n const incomeLayerModes = [\"enabled\", \"disabled\"];\n const optionOverlayModes = [\"enabled\", \"disabled\"];\n const cashOnlyExecutionModes = [\"enabled\", \"disabled\"];\n const runtimeTargetModes = [\"current\", \"enabled\", \"disabled\"];\n const pluginModes = [\"none\"];\n const dcaModes = [\"fixed\", \"smart\"];\n const runtimeTargetEnabledVariable = \"RUNTIME_TARGET_ENABLED\";\n const incomeLayerEnabledVariable = \"INCOME_LAYER_ENABLED\";\n const incomeLayerStartUsdVariable = \"INCOME_LAYER_START_USD\";\n const incomeLayerMaxRatioVariable = \"INCOME_LAYER_MAX_RATIO\";\n const dcaProfileDefaults = requiredInjected(\"__DCA_PROFILE_DEFAULTS__\", window.__DCA_PROFILE_DEFAULTS__, {});\n const APP_BOOT_TIMEOUT_MS = 15000;\n const platformMinReservedCashVariables = requiredInjected(\"__PLATFORM_MIN_RESERVED_CASH_VARIABLES__\", window.__PLATFORM_MIN_RESERVED_CASH_VARIABLES__, {});\n const platformReservedCashRatioVariables = requiredInjected(\"__PLATFORM_RESERVED_CASH_RATIO_VARIABLES__\", window.__PLATFORM_RESERVED_CASH_RATIO_VARIABLES__, {});\n\n const defaultStrategyProfiles = requiredInjected(\"__DEFAULT_STRATEGY_PROFILES__\", window.__DEFAULT_STRATEGY_PROFILES__, []);\n\n const localStrategyLabels = {\n tqqq_growth_income: { zh: \"纳斯达克增长收益\", en: \"NASDAQ Growth Income\" },\n soxl_soxx_trend_income: { zh: \"半导体趋势收益\", en: \"Semiconductor Trend Income\" },\n nasdaq_sp500_smart_dca: { zh: \"纳指标普定投\", en: \"NASDAQ/S&P 500 DCA\" },\n ibit_smart_dca: { zh: \"IBIT比特币定投\", en: \"IBIT Bitcoin DCA\" },\n global_etf_rotation: { zh: \"全球ETF轮动\", en: \"Global ETF Rotation\" },\n russell_top50_leader_rotation: { zh: \"罗素Top50领涨\", en: \"Russell Top50 Leaders\" },\n hk_global_etf_tactical_rotation: { zh: \"港股ETF战术轮动\", en: \"HK ETF Tactical Rotation\" },\n hk_low_vol_dividend_quality_snapshot: { zh: \"港股红利质量\", en: \"HK Dividend Quality\" },\n cn_industry_etf_rotation: { zh: \"A股行业ETF轮动\", en: \"CN Industry ETF Rotation\" },\n cn_dividend_quality_snapshot: { zh: \"A股红利质量\", en: \"CN Dividend Quality\" },\n us_equity_combo: { zh: \"美股核心组合\", en: \"US Core Combo\" },\n us_equity_combo_leveraged: { zh: \"美股加速组合\", en: \"US Alpha Combo\" },\n hk_equity_combo: { zh: \"港股恒生组合\", en: \"HK Core Combo\" },\n cn_industry_etf_rotation_aggressive: { zh: \"A股ETF轮动\", en: \"CN ETF Rotation\" },\n cn_stock_momentum_rotation: { zh: \"A股个股动量\", en: \"CN Stock Momentum\" },\n cn_equity_combo: { zh: \"A股进取组合\", en: \"CN Alpha Combo\" },\n crypto_btc_dca: { zh: \"BTC定投\", en: \"BTC DCA\" },\n crypto_trend_rotation: { zh: \"山寨趋势轮动\", en: \"Altcoin Trend\" },\n crypto_equity_combo: { zh: \"加密动量组合\", en: \"Crypto Core Combo\" },\n };\n\n const fallbackIncomeLayerDefaults = requiredInjected(\"__INCOME_LAYER_DEFAULTS__\", window.__INCOME_LAYER_DEFAULTS__, {});\n let incomeLayerDefaults = {};\n const fallbackOptionOverlayDefaults = requiredInjected(\"__OPTION_OVERLAY_DEFAULTS__\", window.__OPTION_OVERLAY_DEFAULTS__, {});\n let optionOverlayDefaults = {};\n\n const strategyDomains = [\"us_equity\", \"hk_equity\", \"cn_equity\", \"crypto\"];\n let strategyOptions = [];\n let strategyLabels = {};\n let strategyCatalog = {};\n\n\n const copy = {\n zh: {\n appTitle: \"QuantStrategyLab\",\n appSubtitle: \"管理控制台\",\n workspaceNavigation: \"管理页面\",\n overviewNav: \"运行总览\",\n accountsNav: \"账户管理\",\n researchNav: \"研究与确认\",\n overviewDescription: \"先看有没有必须你确认的事,再扫账户是否异常;改配置放到账户管理。\",\n accountsDescription: \"先看读回状态;要改开关或策略时再展开设置。提交只记意图,不等于成交。\",\n researchDescription: \"只处理有材料的候选与晋级确认;接受意图不等于实盘授权。\",\n accountsTitle: \"账户\",\n accountFilters: \"筛选账户\",\n filterAll: \"全部\",\n filterNormal: \"正常\",\n filterPaused: \"暂停\",\n filterAbnormal: \"异常\",\n searchAccounts: \"搜索账户或策略\",\n overviewRuntime: \"运行情况\",\n latestReadback: \"最近检查\",\n accountActions: \"账户操作\",\n viewAccount: \"查看\",\n viewAccountLabel: \"查看 {account}\",\n overviewEvidenceNote: \"状态来自最近检查;保存配置不代表策略已经运行或有成交。\",\n clearFilters: \"清除筛选\",\n viewUnverified: \"查看待核实账户\",\n overviewUnverifiedTitle: \"实际运行状态尚未完整读回\",\n overviewUnverifiedDescription: \"启用配置不代表策略已开始运行。\",\n overviewAttentionTitle: \"有账户需要核对\",\n overviewAttentionDescription: \"有账户的配置还没同步,或最近检查需要查看。请打开对应账户。\",\n overviewReadTitle: \"配置与最近检查一致\",\n overviewReadDescription: \"开关已经同步;策略运行和成交请以运行报告为准。\",\n overviewLoadingTitle: \"正在读取账户状态\",\n overviewLoadingDescription: \"配置和运行读回将分别显示,请稍候。\",\n overviewUnavailableTitle: \"暂时未读到账户配置\",\n overviewUnavailableDescription: \"请刷新重试。读不到的状态会显示为异常,并标明原因。\",\n overviewEmptyTitle: \"没有匹配的账户\",\n overviewEmptyDescription: \"试试其他关键词,或清除当前筛选。\",\n overviewNoAccountsTitle: \"暂无可显示的账户\",\n overviewNoAccountsDescription: \"当前没有可显示的账户配置。\",\n accountResults: \"{count} / {total} 个账户\",\n pageRefreshed: \"本页刷新 {time}\",\n pageNotRefreshed: \"等待读取\",\n savedState: \"配置:{state}\",\n overviewActualUnknown: \"实际待核实\",\n overviewRuntimeNormal: \"正常\",\n overviewRuntimePaused: \"暂停\",\n overviewRuntimeAbnormal: \"异常\",\n overviewRuntimeReasonPending: \"检查未完成\",\n overviewRuntimeReasonMissing: \"尚未收到运行检查\",\n accountRuntimeSummary: \"运行状态摘要\",\n monitoringViewReason: \"查看原因\",\n accountDiagnosisButton: \"AI诊断\",\n accountDiagnosisSubmitting: \"诊断中…\",\n accountDiagnosisQueuedButton: \"排队中…\",\n accountDiagnosisRunningButton: \"诊断中…\",\n accountDiagnosisRecheckingButton: \"复查中…\",\n accountDiagnosisQueued: \"已排队等待诊断\",\n accountDiagnosisDispatchUnknown: \"提交结果未确认,请稍后重新检查\",\n accountDiagnosisRunning: \"正在诊断\",\n accountDiagnosisRechecking: \"正在复查\",\n accountDiagnosisSuccess: \"检查正常\",\n accountDiagnosisNeedsReview: \"仍需处理:{summary}\",\n accountDiagnosisRecheckUnknown: \"复查结果未确认,请重新检查状态\",\n accountDiagnosisRecheckUnavailable: \"复查资料还不完整,请重新检查状态\",\n accountDiagnosisFailed: \"诊断未完成:{reason}\",\n accountDiagnosisUnavailable: \"暂时无法诊断,请先完成状态检查\",\n overviewRuntimeReasonStale: \"检查已过期({age})\",\n overviewRuntimeReasonConfig: \"配置未同步\",\n overviewRuntimeReasonSwitch: \"开关未同步\",\n overviewRuntimeReasonStrategy: \"策略未同步\",\n overviewRuntimeReasonSchedule: \"调度未同步\",\n overviewRuntimeReasonAttention: \"最近检查发现问题\",\n viewResearch: \"前往研究页\",\n researchPendingCount: \"研究页有 {count} 条可审候选\",\n researchIntro: \"研究候选与当前运行分开管理。\",\n monitoringDiagnosticsView: \"监控诊断\",\n researchCandidatesView: \"研究候选\",\n accountDetailAction: \"下一步\",\n loginTitle: \"管理你的量化平台\",\n loginDescription: \"配置策略,关注运行,处理重要决策。\",\n loginUnavailable: \"暂时无法确认登录状态,请重新登录。\",\n loginDenied: \"当前账号没有访问权限,请切换账号。\",\n languageToggle: \"切换语言\",\n consoleNavigation: \"管理台导航\",\n dataFreshness: \"数据更新时间\",\n decisionSummary: \"待办摘要\",\n healthSummary: \"策略健康摘要\",\n healthFilters: \"筛选策略健康状态\",\n controlPlaneView: \"待办确认\",\n healthView: \"运行概览\",\n switchView: \"平台设置\",\n refreshStatus: \"刷新状态\",\n refreshingStatus: \"读取中…\",\n configTruthNote: \"配置值不代表云端实际状态。\",\n configuredSwitch: \"配置开关\",\n observedRuntime: \"最近运行检查\",\n deployedSwitch: \"实际开关\",\n schedulerState: \"自动调度\",\n applicationStatus: \"应用状态\",\n configuredStrategy: \"配置策略\",\n scheduleEnabled: \"已启用\",\n schedulePaused: \"已暂停\",\n scheduleMixed: \"部分暂停\",\n scheduleMissing: \"未找到任务\",\n scheduleUnknown: \"状态未知\",\n scheduleNotApplicable: \"不适用\",\n runtimeStateUnknown: \"状态未知\",\n deploymentUnverified: \"实际状态未知\",\n strategyNotApplied: \"策略尚未应用\",\n settingsNotApplied: \"开关尚未应用\",\n switchesApplied: \"开关已同步\",\n scheduleNotApplied: \"调度尚未同步\",\n monitoringConfigMismatch: \"配置与检查不一致\",\n runtimeUnverified: \"暂无记录\",\n monitoringUnlinked: \"待关联\",\n monitoringTime: \"记录时间\",\n monitoringDetails: \"监测详情\",\n promotionIntentPlatform: \"建议使用的平台\",\n platformManagement: \"决策与账户\",\n strategySettings: \"策略设置\",\n strategySettingsHint: \"\",\n accountNextStep: \"下一步\",\n recheckRuntimeStatus: \"重新检查状态\",\n accountScrollHint: \"左右滑动查看实际状态与下一步\",\n awaitDeploymentReadback: \"等待有效读回\",\n noSwitchAction: \"开关无需处理\",\n reviewAccountSettings: \"复核设置\",\n advancedSelectionNotice: \"\",\n advancedDetails: \"高级详情\",\n monitoringSummaryHint: \"仅展示已配置账户的记录;监测通过不代表已成交。\",\n instanceList: \"账户实例\",\n configDetails: \"配置详情\",\n openSystemStatus: \"查看高级详情\",\n noConfiguredAccounts: \"登录并读取配置后显示账户实例。\",\n\n controlPlaneEyebrow: \"待处理事项\",\n controlPlaneTitle: \"需要你决定\",\n controlPlaneSubtitle: \"这里显示仍需要你决定的事项。\",\n controlPlaneProgressTitle: \"观察进度\",\n controlPlaneProgressSubtitle: \"自动观察的最新记录,无需操作。\",\n controlPlaneMixedTitle: \"研究进度与待办\",\n controlPlaneMixedSubtitle: \"自动观察与需要确认的事项。\",\n controlCandidateTotal: \"监控对象\",\n controlDeferred: \"待复核\",\n controlParked: \"暂停中\",\n controlOwnerDecision: \"待处理\",\n controlQueueEyebrow: \"优先处理\",\n controlQueueHint: \"有风险或需要确认时才出现\",\n controlCandidateBoard: \"需要你处理\",\n controlProgressBoard: \"观察中的策略\",\n controlMixedBoard: \"研究进度与待办\",\n controlDataReady: \"已更新\",\n controlDataStale: \"更新延迟\",\n controlDataUnavailable: \"暂时无法读取\",\n controlAttentionResearchOnly: \"暂无待处理事项\",\n controlAttentionRequired: \"需要关注\",\n controlAttentionUnavailable: \"等待数据\",\n controlLoginNotice: \"登录后查看待处理事项和运行状态。\",\n controlStaleNotice: \"有些研究数据还没更新,暂时无法确认新的事项。\",\n controlUnavailableNotice: \"暂时无法读取最新状态,请稍后刷新。\",\n controlUpstreamNotice: \"有些研究数据还没准备好,暂时无法确认新的事项。\",\n controlAttentionNotice: \"有 {count} 项需要你确认。\",\n controlNormalNotice: \"目前没有需要你决定的事项。\",\n controlNormalSummary: \"暂无需要你决定的事项。你可以查看账户和研究进度。\",\n controlStaleSummary: \"数据更新后再看待办。\",\n controlUnavailableSummary: \"暂时读不到最新数据,无法确认新的事项。\",\n controlLoginSummary: \"登录后查看你的待办和系统概览。\",\n controlAttentionSummary: \"请查看下方事项并记录你的决定。\",\n decisionBackgroundSummary: \"系统进度与历史记录\",\n controlEmptyCandidates: \"当前没有待处理事项。\",\n controlNoRecommendation: \"暂未给出处理建议。\",\n controlItemMeta: \"{kind} · {domain} · 最近更新:{freshness}\",\n parkedResearchResultFallback: \"验证结果已保留,尚未进入模拟观察。\",\n parkedResearchResultSource: \"查看验证来源\",\n parkedResearchResultsTitle: \"研究记录\",\n parkedResearchResultTitle: \"SOXL 研究验证\",\n parkedResearchResultStatus: \"尚未模拟观察\",\n forwardObservationProgress: \"观察进度 {completed} / {required} 个交易日 · 最近观察 {session} · 不下单\",\n forwardObservationActive: \"继续观察\",\n forwardObservationPaused: \"保持暂停\",\n forwardObservationComplete: \"观察完成,等待复核\",\n controlNext: \"处理建议\",\n controlStatus: \"当前状态\",\n ownerDecisionTitle: \"请选择下一步\",\n ownerDecisionAdminOnly: \"请由管理员确认。\",\n ownerDecisionReady: \"数据已准备好。这里记录决定,不会直接启用交易。\",\n ownerDecisionRecorded: \"已保存:{decision}\",\n ownerDecisionApprove: \"接受建议\",\n ownerDecisionPark: \"保持暂停\",\n ownerDecisionRetire: \"停止跟踪\",\n ownerDecisionConfirm: \"确认保存此项决定?\",\n ownerDecisionSubmitting: \"正在保存…\",\n ownerDecisionSuccess: \"决定已保存。\",\n ownerDecisionFailed: \"无法保存决定\",\n reconciliationRecoveryBoard: \"恢复前确认\",\n reconciliationRecoveryLoginNotice: \"登录后查看需要恢复或复核的事项。\",\n reconciliationRecoveryStaleNotice: \"恢复信息更新延迟,请等待下一次检查。\",\n reconciliationRecoveryUnavailableNotice: \"暂时没有可用的恢复信息。\",\n reconciliationRecoveryUpstreamNotice: \"部分恢复信息暂不可用,请先查看阻断原因。\",\n reconciliationRecoveryEmpty: \"当前没有需要恢复的事项。\",\n reconciliationRecoveryTitle: \"{platform} 恢复检查\",\n reconciliationRecoveryMeta: \"{strategy}\",\n reconciliationRecoveryReason: \"这个账户已完成恢复前核对。请决定是否记录恢复意向。\",\n reconciliationRecoveryImpact: \"记录后,系统会重新核验当前状态;不会立即开始交易,也不会解除风险停用。\",\n reconciliationRecoveryTechnicalDetails: \"查看检查依据\",\n reconciliationRecoveryDetail: \"状态:{state} · 样本:{samples} · 复核:{review} · 最近更新:{lastObserved}\",\n reconciliationRecoveryBlocked: \"仍需处理:{blockers}\",\n reconciliationRecoveryReady: \"核对已完成,等待你记录恢复决定。\",\n reconciliationRecoveryAdminOnly: \"请由管理员确认。\",\n reconciliationRecoveryConfirmed: \"恢复确认已保存。\",\n reconciliationRecoveryConfirm: \"记录恢复决定\",\n reconciliationRecoveryConfirmPrompt: \"记录这项恢复决定?保存后仍需运行端重新核验,交易开关和熔断保持独立。\",\n reconciliationRecoverySubmitting: \"正在保存…\",\n reconciliationRecoverySuccess: \"恢复决定已记录,等待运行端重新核验。\",\n reconciliationRecoveryFailed: \"无法保存恢复决定\",\n reconciliationRecoveryNoOrder: \"这里仅记录决定,不会直接恢复交易。\",\n binancePrivateScopeBoard: \"Binance 私密资产清单\",\n binancePrivateScopeAccount: \"Binance 当前采集账户\",\n binancePrivateScopePrivateIdentity: \"私密账户摘要不在页面显示。\",\n binancePrivateScopeEmpty: \"empty:当前没有可显示的有效清单。\",\n binancePrivateScopeUnavailable: \"暂时无法读取私密清单。\",\n binancePrivateScopeObservedAt: \"观测时间:{time}\",\n binancePrivateScopeHistoricalWarning: \"历史差异尚未核清;清单仅供人工核对,不授予下单或处置权限。\",\n binancePrivateScopeAsset: \"资产\",\n binancePrivateScopeFree: \"可用\",\n binancePrivateScopeLocked: \"锁定\",\n executionEvidenceBoard: \"执行与成交记录\",\n executionEvidenceLoginNotice: \"登录后查看执行和成交记录。\",\n executionEvidenceStaleNotice: \"执行记录更新延迟,请结合最新平台状态判断。\",\n executionEvidenceUnavailableNotice: \"暂时没有可用的执行记录。\",\n executionEvidenceUpstreamNotice: \"部分执行记录暂不可用,请稍后重试。\",\n executionEvidenceEmpty: \"当前没有可展示的执行记录。\",\n executionEvidenceMeta: \"{platform} · 当前通道:{environment} · 来源:{source}\",\n executionEvidenceDetail: \"策略:{strategy} · 数据:{data} · 执行:{execution} · 观察:{shadow} · 模拟:{paper}\",\n executionEvidenceReceipt: \"执行回执:{outcome} · 券商确认:{confirmation}\",\n executionEvidenceReceiptMissing: \"执行回执:未采集\",\n executionEvidenceReceiptNotDue: \"未到应交易窗口\",\n executionEvidenceReceiptNoAction: \"策略未产生订单\",\n executionEvidenceReceiptRiskBlocked: \"已被风控拦截\",\n executionEvidenceReceiptSubmitted: \"已提交,尚未确认\",\n executionEvidenceReceiptAcknowledged: \"券商已确认\",\n executionEvidenceReceiptPartiallyFilled: \"部分成交\",\n executionEvidenceReceiptFilled: \"已成交\",\n executionEvidenceReceiptReconciliation: \"需要对账\",\n executionEvidenceReceiptFailed: \"执行失败,需复核\",\n executionEvidenceConfirmationNotApplicable: \"不适用\",\n executionEvidenceConfirmationNotObserved: \"未观察到确认\",\n executionEvidenceConfirmationAcknowledged: \"已确认\",\n executionEvidenceConfirmationPartiallyFilled: \"部分成交\",\n executionEvidenceConfirmationFilled: \"已成交\",\n executionEvidenceConfirmationReconciliation: \"需对账\",\n executionEvidenceNoOrder: \"查看当前执行和成交结果。\",\n executionEvidenceNext: \"处理建议\",\n runtimeTargetLifecycleBoard: \"平台运行状态\",\n runtimeTargetLifecycleLoginNotice: \"登录后查看平台运行状态。\",\n runtimeTargetLifecycleStaleNotice: \"平台状态更新延迟,请先检查运行情况。\",\n runtimeTargetLifecycleUnavailableNotice: \"暂时没有可用的平台状态。\",\n runtimeTargetLifecycleUpstreamNotice: \"部分平台状态暂不可用,请先核对。\",\n runtimeTargetLifecycleEmpty: \"当前没有可展示的平台状态。\",\n runtimeTargetLifecycleMeta: \"{platform} · {state} · 通道:{mode}\",\n runtimeTargetLifecycleDetail: \"运行监测:{guard} · 执行心跳:{heartbeat}\",\n runtimeTargetLifecycleObservation: \"本次执行:{observation} · 成交证据:{evidence}\",\n runtimeTargetLifecycleNoOrder: \"查看当前平台运行情况。\",\n runtimeTargetLifecycleNext: \"当前建议\",\n runtimeTargetLifecycleStateEnabled: \"已启用\",\n runtimeTargetLifecycleStateDisabled: \"已停用\",\n runtimeTargetLifecycleCheckPass: \"通过\",\n runtimeTargetLifecycleCheckAttention: \"需处理\",\n runtimeTargetLifecycleCheckNotDue: \"未到检查时间\",\n runtimeTargetLifecycleCheckNotApplicable: \"不适用\",\n runtimeTargetLifecycleCheckUnavailable: \"不可用\",\n runtimeTargetLifecycleObservationNotDue: \"未到应交易窗口\",\n runtimeTargetLifecycleObservationMonitoringOnly: \"最近检查通过\",\n runtimeTargetLifecycleObservationNotApplicable: \"检查时已停用\",\n runtimeTargetLifecycleObservationAttention: \"运行检查异常\",\n runtimeTargetLifecycleObservationUnavailable: \"不可用\",\n runtimeTargetLifecycleOrderEvidenceNotCollected: \"未采集订单/成交回执\",\n runtimeTargetLifecycleDispositionEnabled: \"持续监控\",\n runtimeTargetLifecycleDispositionDisabled: \"无执行验证\",\n runtimeTargetLifecycleDispositionParked: \"已暂停\",\n runtimeTargetLifecycleReasonNone: \"监测正常\",\n runtimeTargetLifecycleReasonDisabled: \"按配置停用,仍持续验证\",\n runtimeTargetLifecycleReasonRuntimeGuard: \"运行监测需要复核\",\n runtimeTargetLifecycleReasonHeartbeat: \"执行心跳需要复核\",\n runtimeTargetLifecycleReasonUnavailable: \"监测数据不可用\",\n m0ResearchBoard: \"外部研究记录\",\n m0ResearchLoginNotice: \"登录后查看外部研究记录。\",\n m0ResearchStaleNotice: \"外部研究更新延迟,仅供历史参考。\",\n m0ResearchUnavailableNotice: \"暂时没有可用的外部研究记录。\",\n m0ResearchUpstreamNotice: \"部分外部研究暂不可用,请稍后重试。\",\n m0ResearchEmpty: \"当前没有可展示的外部研究记录。\",\n m0ResearchMore: \"显示前 {count} 条研究观察。\",\n m0ResearchMeta: \"{kind} · 查看于:{viewed}\",\n m0ResearchStateFreshness: \"状态:{state} · 新鲜度:{freshness}\",\n m0ResearchHorizons: \"主要观察期:{primary} · 适用观察期:{suitable}\",\n m0ResearchEvidence: \"置信:{confidence} · 风格:{style} · 资料摘要:{digest}\",\n m0ResearchConsistency: \"当前周期分歧:{conflict} · 历史失效漂移:{drift}\",\n m0ResearchNoOrder: \"外部研究不影响当前策略运行。\",\n adaptiveSelectionBoard: \"系统建议\",\n adaptiveSelectionLoginNotice: \"登录后查看系统建议。\",\n adaptiveSelectionStaleNotice: \"建议更新延迟,仅供历史参考。\",\n adaptiveSelectionUnavailableNotice: \"暂时没有可用的系统建议。\",\n adaptiveSelectionUpstreamNotice: \"部分建议暂不可用,请稍后重试。\",\n adaptiveSelectionEmpty: \"当前没有可展示的系统建议。\",\n adaptiveSelectionMeta: \"{source} · {domain} · 市场截至 {asOf}\",\n adaptiveSelectionRecommended: \"建议观察\",\n adaptiveSelectionNoCandidate: \"暂无合适建议\",\n adaptiveSelectionReason: \"原因:{reasons}\",\n adaptiveSelectionNoOrder: \"查看系统的当前建议。\",\n adaptiveSelectionScoreLabel: \"研究次数\",\n researchTaskBoard: \"自动化任务\",\n researchTaskLoginNotice: \"登录后查看自动化任务。\",\n researchTaskStaleNotice: \"任务信息更新延迟,仅供历史参考。\",\n researchTaskUnavailableNotice: \"暂时没有可用的自动化任务。\",\n researchTaskUpstreamNotice: \"部分任务信息暂不可用,请稍后重试。\",\n researchTaskEmpty: \"当前没有可展示的自动化任务。\",\n researchTaskMeta: \"{type} · {domain} · 创建于:{created}\",\n researchTaskLimits: \"研究预算:最多 {runs} 次 / {seconds} 秒\",\n researchTaskNoOrder: \"查看当前自动化任务。\",\n healthEyebrow: \"系统状态\",\n healthTitle: \"监测与诊断\",\n healthSubtitle: \"账户、配置与监测记录,一处查看。\",\n healthTotal: \"策略总数\",\n healthHealthy: \"健康\",\n healthWatch: \"观察\",\n healthReview: \"需要复核\",\n healthCritical: \"严重\",\n healthBoard: \"策略健康\",\n healthFilterAttention: \"需要关注\",\n healthFilterAll: \"全部策略\",\n healthDataReady: \"已更新\",\n healthDataStale: \"更新延迟\",\n healthDataUnavailable: \"暂时无法读取\",\n healthComputedAt: \"更新于:{time}\",\n healthLoginNotice: \"登录后查看策略健康度和运行情况。\",\n healthStaleNotice: \"状态更新延迟;系统会继续检查。\",\n healthUnavailableNotice: \"暂时无法读取策略状态,请稍后刷新。\",\n healthUpstreamNotice: \"部分策略状态暂不可用,请稍后重试。\",\n healthNormalNotice: \"当前没有需要关注的运行问题。\",\n healthAttentionNotice: \"有 {critical} 项严重、{review} 项需要复核、{watch} 项观察;系统正在持续监测。\",\n healthEmpty: \"当前分类下没有策略。\",\n healthStatusHealthy: \"健康\",\n healthStatusWatch: \"观察\",\n healthStatusReview: \"需要复核\",\n healthStatusCritical: \"严重\",\n healthStatusUnknown: \"未知\",\n healthCardMeta: \"{status} · {domain}\",\n healthDecisionFallbackLabel: \"系统正在继续观察。\",\n healthDecisionFallbackReason: \"没有需要你处理的异常。\",\n healthRecommendationHealthy: \"系统正在正常运行。\",\n healthRecommendationWatch: \"系统正在继续观察。\",\n healthRecommendationReview: \"请查看诊断详情,等待系统复核完成。\",\n healthRecommendationCritical: \"请查看诊断详情,并暂缓相关变更。\",\n healthDetail: \"数据截至:{date}\",\n healthScoreLabel: \"健康度\",\n diagnosticDetails: \"查看诊断详情\",\n diagnosticDetailsHint: \"仅在排查问题或查看研究记录时使用。\",\n researchTaskNoOrderBadge: \"未产生订单\",\n recoveryConfirmedStatus: \"已确认\",\n recoveryReadyStatus: \"可确认\",\n recoveryBlockedStatus: \"仍受阻\",\n commonUnknown: \"未知\",\n commonNotMarked: \"未标记\",\n bootKicker: \"初始化控制台\",\n bootTitle: \"读取策略配置\",\n bootMessage: \"正在读取登录状态、账号配置和当前状态。\",\n bootStrategy: \"正在读取策略目录。\",\n bootSession: \"正在验证登录状态。\",\n bootConfig: \"正在读取账号配置和当前状态。\",\n bootTimeout: \"加载超时,已切换到公开预览(登录后可重试)。\",\n bootPublic: \"公开预览已就绪。\",\n login: \"登录\",\n logout: \"退出\",\n signedInAs: \"已登录 {login}\",\n planEyebrow: \"策略设置\",\n planTitle: \"平台设置\",\n planSubtitle: \"按账户实例管理,互不影响。\",\n planAdvancedSummary: \"高级设置\",\n planAdvancedHint: \"运行状态、插件、现金、收入层和定投通常沿用当前配置;需要改动时再展开。\",\n planScopeTitle: \"选择范围\",\n planScopeSubtitle: \"平台、账号、策略与目标环境\",\n planRuntimeTitle: \"运行保护\",\n planRuntimeSubtitle: \"停用、插件和附加层都受同一计划约束\",\n planOverlayTitle: \"策略附加层\",\n planOverlaySubtitle: \"仅使用策略已定义的默认边界\",\n planCashSubtitle: \"现金预留优先于融资;两者不能同时覆盖\",\n activePlatform: \"目标平台\",\n account: \"账户\",\n strategy: \"策略\",\n mode: \"运行方式\",\n live: \"实盘交易\",\n paper: \"模拟交易\",\n dryRun: \"无下单检查\",\n modeUnknown: \"账户类型待确认\",\n executionModeSetting: \"执行方式设置\",\n executionModeLive: \"执行交易\",\n executionModeDryRun: \"仅检查,不下单\",\n executionModeSettingMeta: \"仅修改现有执行设置;不下单检查不会写入交易订单。\",\n promotionConfirmTitle: \"确认研究候选\",\n promotionDecisionEyebrow: \"待决策\",\n promotionTargetPlatform: \"目标平台\",\n promotionBrokerEnvironment: \"券商环境\",\n promotionAccount: \"具体账户\",\n promotionExecutionMode: \"目标执行模式\",\n promotionExecutionModeReadonly: \"账户环境:{mode}\",\n promotionNoOrderCannotConfirm: \"当前账户是不下单演练;不能把它记录成券商 paper 或实盘意向。\",\n promotionRiskProfile: \"风险档\",\n promotionConfirmMeta: \"接受建议只记录研究决定,不会启用交易或替换当前策略。\",\n promotionTargetSummary: \"建议平台:{platform};当前账户:{account}。\",\n promotionClickEffect: \"点击后:只记录人工决定;{mode}账户不会因此启用交易或下单。\",\n promotionResearchSummary: \"研究简述\",\n promotionResearchSummaryMissing: \"尚未提供收益对比/策略说明。{strategy};{observation}\",\n promotionResearchSummaryMissingParts: \"未提供:{items}\",\n promotionStrategyDescription: \"策略说明:{description}\",\n promotionPluginsUnknown: \"插件:未提供\",\n promotionPluginsNone: \"插件:无\",\n promotionPlugins: \"插件:{description}\",\n promotionComparison: \"回测:{startDate}—{endDate};候选扣费后年化 {candidateCagr};候选最大回撤 {candidateDrawdown};基准扣费后年化 {baselineCagr};基准最大回撤 {baselineDrawdown}\",\n promotionLimitations: \"不足:{limitations}\",\n promotionAiExplanation: \"AI说明(仅供参考):{text}\",\n promotionTargetUnavailable: \"有研究候选待确认,但当前没有可见目标平台。\",\n promotionRiskDetails: \"风险档与账户资料\",\n promotionRiskScaleMeta: \"按控制回撤、兼顾收益与回撤、更看重收益的顺序,晋级仓位缩放为 0.50 / 0.75 / 1.00,仅适用于新晋级或数据变更;组合相对无杠杆基准的回撤上限倍数为 1.00 / 1.25 / 1.50。两者含义不同,不会据此调整现有实盘。\",\n promotionPaperUnavailable: \"该平台无券商 paper/sim,已禁用 paper\",\n promotionTicket: \"待确认候选\",\n promotionAccept: \"接受建议\",\n promotionReject: \"拒绝\",\n promotionTicketEmpty: \"当前没有待确认的研究候选。\",\n promotionTicketLoginRequired: \"请先登录(需权限账号)后再刷新\",\n promotionTicketLoadFailed: \"研究候选队列暂不可用,请刷新记录;不能据此判断没有待办。\",\n promotionAdminOnly: \"需管理员才能确认/拒绝\",\n promotionTicketSuggested: \"候选建议风险档:{profile}\",\n promotionUnnamedRecord: \"未命名策略记录 {number}\",\n promotionFlowRecord: \"流程检查记录 · 来源待核实\",\n promotionOldRecord: \"旧记录\",\n promotionParameterProposal: \"参数调整建议\",\n promotionUnverifiedCount: \"{count} 条旧记录 · 材料待核实\",\n promotionUnverifiedHint: \"这是一条旧研究记录,缺少观察材料类型,尚不能认定为已验证的策略。暂不需要接受或拒绝;补齐来源后再评估。\",\n promotionOriginalRecord: \"查看原始名称与材料\",\n promotionDecisionHint: \"先查看研究结果、风险和来源,再决定是否接受建议。\",\n promotionTicketEvidenceKind: \"观察类型:{kind}\",\n promotionTicketParams: \"建议参数:{params}\",\n promotionTicketNotification: \"说明:{body}\",\n promotionObservationReported: \"记录上报观察通过,尚不代表完整验证通过。\",\n promotionObservationFailed: \"记录上报观察未通过。\",\n promotionObservationMissing: \"记录未提供观察结果。\",\n promotionEvidenceSourceMissing: \"来源还没写清楚:记录没有观察类型,请先查看来源。\",\n promotionEvidenceNeedsReview: \"已注明观察类型,但来源和完整检查还需要查看。\",\n promotionDecisionSaved: \"已记录晋级意图(未授予实盘权限)\",\n promotionDecisionFailed: \"晋级确认失败\",\n promotionApplicationTitle: \"账户检查\",\n promotionApplicationHint: \"合格候选可部署到已确认的模拟账户;部署后保持暂停,启用是独立步骤。\",\n promotionApplicationCandidate: \"研究候选\",\n promotionApplicationAccount: \"目标账户\",\n promotionApplicationReady: \"账户和策略检查通过;系统没有提交变更。\",\n promotionApplicationBlocked: \"当前还不能使用:{reasons}。系统没有提交变更。\",\n promotionApplicationOpen: \"在账户设置中查看\",\n promotionApplicationDeploy: \"部署到模拟账户\",\n promotionApplicationQueued: \"已提交部署申请;账户会保持暂停。\",\n promotionApplicationDispatchUnknown: \"提交结果尚未确认,暂不重复提交。\",\n promotionApplicationClaimed: \"部署处理中;账户会保持暂停。\",\n promotionApplicationApplied: \"已部署并核对版本,当前暂停。\",\n promotionApplicationRejected: \"部署未通过:{reason}\",\n promotionApplicationUncertain: \"部署结果待确认,请查看最近检查。\",\n promotionApplicationEmpty: \"没有可准备的研究候选。\",\n promotionApplicationBlockActivation: \"账户应用尚未接通\",\n promotionApplicationBlockParams: \"缺少可运行的策略参数\",\n promotionApplicationBlockStrategy: \"缺少同名可运行的策略版本\",\n promotionApplicationBlockAccount: \"没有匹配的已配置账户\",\n promotionApplicationBlockEvidence: \"研究材料尚未核实\",\n promotionApplicationBlockBrokerEnvironment: \"券商环境未明确或不受支持\",\n promotionApplicationBlockPreflight: \"账户或策略检查未通过\",\n riskCapitalPreservation: \"优先控制回撤\",\n riskBalancedCompounding: \"兼顾收益与回撤\",\n riskGrowthCompounding: \"更看重收益\",\n riskEnvelopeTitle: \"账户风险信封\",\n riskEnvelopePreference: \"风险偏好\",\n riskEnvelopeCapitalBand: \"资金档\",\n riskEnvelopeStatus: \"状态灯\",\n riskEnvelopeDetailsSummary: \"详情\",\n riskEnvelopeMeta: \"只读展示;不授予实盘、不自动升档。\",\n riskEnvelopeAwaitingEquity: \"待对账权益注入\",\n riskEnvelopeUnset: \"未设定\",\n promotionModeLive: \"实盘交易\",\n promotionModePaper: \"模拟交易\",\n liveModeUnavailable: \"本次切换暂不具备实盘资格。现有账户状态请看上方。\",\n runtimeTargetMode: \"平台开关\",\n runtimeStopConfirm: \"将为当前账号提交停用。只保存并核对停用配置,不应用表单其他修改;平台是否已停止仍未知。不撤单、不平仓,不能保证在途请求结束。继续?\",\n runtimeStopPending: \"停用请求已提交。配置保存结果请查看任务;平台应用未请求,实际运行状态未知,请勿重复提交。\",\n runtimeStopReadyNote: \"已选择停用:主操作只提交严格停用配置,不要求策略重新上架,也不应用其他表单修改。\",\n runtimeSectionTitle: \"运行与插件\",\n runtimeTargetCurrent: \"\",\n runtimeTargetEnabled: \"启用\",\n runtimeTargetDisabled: \"禁用\",\n runtimeTargetModeMeta: \"保存后,系统会检查是否生效。\",\n pluginMode: \"插件状态\",\n pluginModeNone: \"不挂载旧插件\",\n pluginModeMeta: \"当前候选未绑定插件;旧插件不会自动挂载。\",\n incomeLayerMode: \"收入层状态\",\n incomeLayerSectionTitle: \"收入层\",\n incomeLayerCurrent: \"沿用当前配置\",\n incomeLayerEnabled: \"开启收入层\",\n incomeLayerDisabled: \"关闭收入层\",\n incomeLayerNotSupported: \"该策略未定义收入层\",\n incomeLayerStartUsd: \"收入层起始金额\",\n incomeLayerMaxRatio: \"收入层最高比例\",\n incomeLayerModeMeta: \"仅对已定义收入层的美股策略生效。\",\n incomeLayerDefaultMeta: \"策略默认:起始 {start},最高 {ratio}。\",\n incomeLayerAllocationMeta: \"默认分配:{allocations}。\",\n incomeLayerStartMeta: \"总资产达到该金额后启用收入层。\",\n incomeLayerRatioMeta: \"例如 0.55 表示最高 55%。\",\n optionOverlayMode: \"期权层状态\",\n optionOverlaySectionTitle: \"期权层\",\n optionOverlayCurrent: \"沿用当前配置\",\n optionOverlayEnabled: \"启用期权层\",\n optionOverlayDisabled: \"关闭期权层\",\n optionOverlayNotSupported: \"该策略未定义期权层\",\n optionOverlayModeMeta: \"启用时使用策略默认的最佳 recipe 和预算,不在这里手动调比例。\",\n optionOverlayDefaultMeta: \"{defaults}\",\n optionOverlayFamilyGrowth: \"增长\",\n optionOverlayFamilyIncome: \"收入\",\n optionOverlayBudgetRatio: \"预算 {ratio}\",\n optionOverlayRiskRatio: \"风险 {ratio}\",\n cashOnlyExecutionMode: \"允许融资\",\n cashOnlyExecutionCurrent: \"沿用当前配置\",\n cashOnlyExecutionYes: \"是\",\n cashOnlyExecutionNo: \"否\",\n cashOnlyExecutionModeMeta: \"选「否」时只按真实现金下单,不会动用 margin 购买力。\",\n cashOnlyExecutionValueYes: \"是\",\n cashOnlyExecutionValueNo: \"否\",\n currentCashOnlyExecution: \"当前允许融资\",\n pendingCashOnlyExecution: \"待提交允许融资\",\n executionCashPolicyTitle: \"资本边界\",\n executionCashPolicyNote: \"允许融资与预留现金覆盖不能同时生效;选「是」会清空预留覆盖,设预留覆盖会强制「否」。\",\n executionCashMarginBlocksReserve: \"已选允许融资;提交时会清空预留现金覆盖。\",\n executionCashReserveBlocksMargin: \"已设预留现金覆盖;提交时会强制不允许融资。\",\n qmtPlatformCashNote: \"A 股 QMT 不使用 margin / 平台预留现金;现金约束在策略参数 execution_cash_reserve_ratio 内配置。\",\n qmtDryRunOnlyNote: \"当前平台仅支持模拟运行。\",\n binancePlatformNote: \"Binance 平台不使用券商级收入层与期权层;相关功能由策略内部实现。\",\n invalidExecutionCashPolicyNote: \"允许融资与预留现金覆盖冲突,请只保留一种约束。\",\n dcaMode: \"定投模式\",\n dcaSectionTitle: \"定投\",\n dcaModeFixed: \"定额定投\",\n dcaModeSmart: \"智能定投\",\n dcaBaseInvestmentUsd: \"定投基准金额\",\n dcaModeMeta: \"仅定投策略可配置。\",\n dcaDefaultMeta: \"默认:{mode},基准金额 {amount}。\",\n dcaNotSupported: \"该策略不是定投策略\",\n dcaPlatformNotSupported: \"当前平台不支持定投策略\",\n currentDca: \"当前定投设置\",\n pendingDca: \"待提交定投设置\",\n dcaText: \"{mode},基准金额 {amount}\",\n minReservedCash: \"最小预留现金 ({currency})\",\n reservedCashRatio: \"预留现金比例\",\n reservedCashMode: \"预留现金策略\",\n reservePolicyCurrent: \"沿用当前配置\",\n reservePolicyNone: \"不设置平台预留现金\",\n reservePolicyRatio: \"仅按比例\",\n reservePolicyFloor: \"仅按固定金额\",\n reservePolicyMax: \"固定金额和比例取较大值\",\n reservedCashModeMeta: \"选择是否沿用、清空或覆盖平台预留现金。\",\n reservedCashNone: \"不设置\",\n reservedCashDefault: \"未配置(平台默认:0 {currency} / 0%)\",\n reservedCashMeta: \"固定金额下限,可单独设置或与比例取较大值。\",\n reservedCashRatioMeta: \"例如 0.03 表示 3%。\",\n summary: \"当前配置\",\n summaryCurrent: \"已保存的配置\",\n summaryPending: \"待提交变更\",\n copySummary: \"复制状态\",\n loginToRun: \"登录后提交计划\",\n loadingConfig: \"读取配置中\",\n configureAccounts: \"暂不能提交\",\n runSwitch: \"保存设置\",\n noChanges: \"无变更\",\n readonlyNote: \"登录后可保存设置。\",\n publicReadonly: \"登录后查看账号配置。\",\n loadingConfigNote: \"正在读取账号配置和当前状态。\",\n missingConfigNote: \"账号配置未加载,暂时不能执行。\",\n readyNote: \"请核对上方改动后保存。\",\n invalidStrategyNote: \"本次策略切换不满足所选运行方式的条件,暂不能提交。现有账户状态请看上方。\",\n binanceResume: \"恢复当前实盘目标\",\n binanceResumeHint: \"恢复当前实盘目标只保存启用开关,保留现有策略和资金配置。运行端仍会核验恢复记录。\",\n binanceResumeModeHint: \"恢复原目标请用上方恢复按钮;下方表单用于切换策略。\",\n binanceResumeConfirm: \"确认恢复当前 Binance 实盘目标?只保存启用开关,保留现有策略和资金配置;此表单中未保存的修改不会提交。运行端通过恢复与风险检查后才会执行。\",\n binanceResumePending: \"恢复请求已提交。请查看处理结果并刷新配置;实际恢复以平台运行记录为准。\",\n binanceResumeUnknown: \"提交结果未确认。请先查看已有处理记录,再刷新页面,避免重复提交。\",\n invalidReservePolicyNote: \"请为当前预留现金策略填写有效金额或比例。\",\n invalidIncomeLayerNote: \"请填写有效的收入层起始金额和最高比例。\",\n invalidOptionOverlayNote: \"当前策略未定义可启用的期权层。\",\n invalidDcaNote: \"请填写有效的定投模式和基准金额。\",\n noAccount: \"没有账号选项\",\n noStrategy: \"没有支持的策略\",\n repository: \"平台仓库\",\n selectedAccount: \"账号\",\n selectedMarket: \"市场\",\n currentRuntimeTarget: \"配置开关\",\n pendingRuntimeTarget: \"待提交账号状态\",\n reservedCashPolicy: \"当前预留现金\",\n currentIncomeLayer: \"当前收入层\",\n pendingIncomeLayer: \"待提交收入层\",\n currentOptionOverlay: \"当前期权层\",\n pendingOptionOverlay: \"待提交期权层\",\n pendingReservedCashPolicy: \"待提交预留现金\",\n pendingMode: \"待提交模式\",\n currentPluginMode: \"当前插件范围\",\n pendingPluginMode: \"待提交插件范围\",\n unchanged: \"不变\",\n copied: \"已复制状态\",\n dispatching: \"正在触发工作流...\",\n dispatched: \"已触发工作流\",\n dispatchFailed: \"触发失败\",\n targetMeta: \"\",\n strategyMeta: \"支持市场:{domains}\",\n strategyLifecycleMeta: \"当前门槛 {stage}\",\n strategyBlockedCountMeta: \"{count} 个策略未达 live 门槛\",\n strategyDefaultBlockedMeta: \"默认策略 {profile} 已阻断:{reason}\",\n usEquity: \"美股\",\n hkEquity: \"港股\",\n cnEquity: \"A股\",\n cryptoEquity: \"加密\",\n currentStrategy: \"当前策略\",\n nextStrategy: \"切换策略\",\n notRead: \"暂未读取\",\n runtimeTargetOn: \"启用\",\n runtimeTargetOff: \"禁用\",\n incomeLayerDefault: \"开启,{start}起 {ratio}\",\n incomeLayerOff: \"关闭\",\n incomeLayerOn: \"开启,起始 {start},最高 {ratio}\",\n optionOverlayOff: \"关闭\",\n optionOverlayOn: \"开启\",\n optionOverlayDefaultSimple: \"开启\",\n optionOverlayDefault: \"开启,{detail}\",\n cashOnlyExecutionDefault: \"仅用现金\",\n notConfigured: \"未设置\",\n strategyDefault: \"使用策略默认\",\n },\n en: {\n appTitle: \"QuantStrategyLab\",\n appSubtitle: \"Management console\",\n workspaceNavigation: \"Management pages\",\n overviewNav: \"Overview\",\n accountsNav: \"Accounts\",\n researchNav: \"Research & decisions\",\n overviewDescription: \"Check decisions first, then scan account anomalies. Change settings under Accounts.\",\n accountsDescription: \"Review readback first. Expand settings only when changing. Submit records intent, not a fill.\",\n researchDescription: \"Handle candidates with complete material only. Accepting intent is not live authority.\",\n accountsTitle: \"Accounts\",\n accountFilters: \"Filter accounts\",\n filterAll: \"All\",\n filterNormal: \"Normal\",\n filterPaused: \"Paused\",\n filterAbnormal: \"Needs attention\",\n searchAccounts: \"Search accounts or strategies\",\n overviewRuntime: \"Runtime state\",\n latestReadback: \"Latest check\",\n accountActions: \"Account actions\",\n viewAccount: \"View\",\n viewAccountLabel: \"View {account}\",\n overviewEvidenceNote: \"Status comes from the latest check. Saved settings do not prove execution or fills.\",\n clearFilters: \"Clear filters\",\n viewUnverified: \"View accounts to check\",\n overviewUnverifiedTitle: \"Actual runtime state is not fully verified\",\n overviewUnverifiedDescription: \"An enabled setting does not prove the strategy has started.\",\n overviewAttentionTitle: \"Some accounts need a closer look\",\n overviewAttentionDescription: \"An account is out of sync, or its latest check needs review. Open the affected account.\",\n overviewReadTitle: \"Settings agree with the latest check\",\n overviewReadDescription: \"The switch is synchronized. Use runtime reports for strategy execution and fills.\",\n overviewLoadingTitle: \"Reading account state\",\n overviewLoadingDescription: \"Settings and runtime readback will appear separately. Please wait.\",\n overviewUnavailableTitle: \"Account settings could not be read\",\n overviewUnavailableDescription: \"Refresh to try again. Missing state is shown as needing attention with a reason.\",\n overviewEmptyTitle: \"No matching accounts\",\n overviewEmptyDescription: \"Try another search, or clear your filters.\",\n overviewNoAccountsTitle: \"No accounts to display\",\n overviewNoAccountsDescription: \"No visible account configuration is available.\",\n accountResults: \"{count} of {total} accounts\",\n pageRefreshed: \"Page refreshed {time}\",\n pageNotRefreshed: \"Waiting for data\",\n savedState: \"Setting: {state}\",\n overviewActualUnknown: \"Unverified\",\n overviewRuntimeNormal: \"Normal\",\n overviewRuntimePaused: \"Paused\",\n overviewRuntimeAbnormal: \"Needs attention\",\n overviewRuntimeReasonPending: \"Status needs confirmation\",\n overviewRuntimeReasonMissing: \"No runtime check received\",\n overviewRuntimeReasonStale: \"Check is out of date ({age})\",\n overviewRuntimeReasonConfig: \"Settings not synchronized\",\n overviewRuntimeReasonSwitch: \"Switch not synchronized\",\n overviewRuntimeReasonStrategy: \"Strategy not synchronized\",\n overviewRuntimeReasonSchedule: \"Scheduling not synchronized\",\n overviewRuntimeReasonAttention: \"The latest check found a problem\",\n accountDiagnosisButton: \"AI diagnose\",\n accountDiagnosisSubmitting: \"Diagnosing…\",\n accountDiagnosisQueuedButton: \"Queued…\",\n accountDiagnosisRunningButton: \"Diagnosing…\",\n accountDiagnosisRecheckingButton: \"Rechecking…\",\n accountDiagnosisQueued: \"Queued for diagnosis\",\n accountDiagnosisDispatchUnknown: \"Submission not confirmed; check again shortly\",\n accountDiagnosisRunning: \"Diagnosis in progress\",\n accountDiagnosisRechecking: \"Rechecking\",\n accountDiagnosisSuccess: \"Check passed\",\n accountDiagnosisNeedsReview: \"Still needs attention: {summary}\",\n accountDiagnosisRecheckUnknown: \"Recheck result not confirmed; check status again\",\n accountDiagnosisRecheckUnavailable: \"The recheck data is incomplete; check status again\",\n accountDiagnosisFailed: \"Diagnosis did not complete: {reason}\",\n accountDiagnosisUnavailable: \"Diagnosis is unavailable until a current status check exists\",\n viewResearch: \"Go to research\",\n researchPendingCount: \"{count} reviewable candidate(s) in Research\",\n researchIntro: \"Research candidates are separate from current runtime.\",\n monitoringDiagnosticsView: \"Monitoring\",\n researchCandidatesView: \"Research candidates\",\n accountDetailAction: \"Next step\",\n loginTitle: \"Your trading workspace\",\n loginDescription: \"Configure strategies. Monitor operations. Make key decisions.\",\n loginUnavailable: \"Unable to verify your session. Please sign in again.\",\n loginDenied: \"This account does not have access. Please switch accounts.\",\n languageToggle: \"Change language\",\n consoleNavigation: \"Console navigation\",\n dataFreshness: \"Data freshness\",\n decisionSummary: \"Decision summary\",\n healthSummary: \"Strategy health summary\",\n healthFilters: \"Filter strategy health\",\n controlPlaneView: \"Decisions\",\n healthView: \"Runtime overview\",\n switchView: \"Platforms\",\n refreshStatus: \"Refresh status\",\n refreshingStatus: \"Reading…\",\n configTruthNote: \"Saved configuration is not observed runtime state.\",\n configuredSwitch: \"Configured switch\",\n observedRuntime: \"Latest runtime check\",\n deployedSwitch: \"Deployed switch\",\n schedulerState: \"Scheduling\",\n applicationStatus: \"Applied status\",\n configuredStrategy: \"Configured strategy\",\n scheduleEnabled: \"Enabled\",\n schedulePaused: \"Paused\",\n scheduleMixed: \"Partially paused\",\n scheduleMissing: \"No bound jobs\",\n scheduleUnknown: \"Unknown\",\n scheduleNotApplicable: \"Not applicable\",\n runtimeStateUnknown: \"Unknown\",\n deploymentUnverified: \"Actual state unknown\",\n strategyNotApplied: \"Strategy not applied\",\n settingsNotApplied: \"Switch not applied\",\n switchesApplied: \"Switches synchronized\",\n scheduleNotApplied: \"Scheduling not synchronized\",\n monitoringConfigMismatch: \"Configuration differs from last check\",\n runtimeUnverified: \"No record\",\n monitoringUnlinked: \"Not linked\",\n monitoringTime: \"Recorded at\",\n monitoringDetails: \"Monitoring details\",\n promotionIntentPlatform: \"Suggested platform\",\n platformManagement: \"Decisions and accounts\",\n strategySettings: \"Strategy settings\",\n strategySettingsHint: \"\",\n accountNextStep: \"Next step\",\n recheckRuntimeStatus: \"Recheck status\",\n accountScrollHint: \"Scroll horizontally for actual status and next step\",\n awaitDeploymentReadback: \"Await verified readback\",\n noSwitchAction: \"No switch action needed\",\n reviewAccountSettings: \"Review settings\",\n advancedSelectionNotice: \"\",\n advancedDetails: \"Advanced details\",\n monitoringSummaryHint: \"Records for configured accounts only. Monitoring success does not imply a fill.\",\n instanceList: \"Account instances\",\n configDetails: \"Configuration details\",\n openSystemStatus: \"View advanced details\",\n noConfiguredAccounts: \"Sign in and load configuration to view account instances.\",\n\n controlPlaneEyebrow: \"To do\",\n controlPlaneTitle: \"Decisions for you\",\n controlPlaneSubtitle: \"This is where items that still need your decision appear.\",\n controlPlaneProgressTitle: \"Observation progress\",\n controlPlaneProgressSubtitle: \"Latest automated observation. No action is needed.\",\n controlPlaneMixedTitle: \"Research progress & tasks\",\n controlPlaneMixedSubtitle: \"Automated observations and items needing your confirmation.\",\n controlCandidateTotal: \"Monitored items\",\n controlDeferred: \"To review\",\n controlParked: \"Paused\",\n controlOwnerDecision: \"To do\",\n controlQueueEyebrow: \"Priority\",\n controlQueueHint: \"Only appears when action is needed\",\n controlCandidateBoard: \"Needs your attention\",\n controlProgressBoard: \"Strategies under observation\",\n controlMixedBoard: \"Research progress & tasks\",\n controlDataReady: \"Up to date\",\n controlDataStale: \"Update delayed\",\n controlDataUnavailable: \"Unavailable\",\n controlAttentionResearchOnly: \"Nothing to do\",\n controlAttentionRequired: \"Needs attention\",\n controlAttentionUnavailable: \"Waiting for data\",\n controlLoginNotice: \"Sign in to see your to-do items and runtime status.\",\n controlStaleNotice: \"Some research data has not been updated, so new items cannot be confirmed yet.\",\n controlUnavailableNotice: \"The latest status is temporarily unavailable. Please refresh later.\",\n controlUpstreamNotice: \"Some research data is not ready, so new items cannot be confirmed yet.\",\n controlAttentionNotice: \"{count} item(s) need your decision.\",\n controlNormalNotice: \"There is nothing you need to decide right now.\",\n controlNormalSummary: \"There is nothing you need to decide right now. You can review account and research progress.\",\n controlStaleSummary: \"Check the to-do items after the data is updated.\",\n controlUnavailableSummary: \"The latest data could not be read, so new items cannot be confirmed.\",\n controlLoginSummary: \"Sign in to see your tasks and system overview.\",\n controlAttentionSummary: \"Review the items below and record your decision.\",\n decisionBackgroundSummary: \"System progress and decision history\",\n controlEmptyCandidates: \"There is nothing to handle right now.\",\n controlNoRecommendation: \"No action is recommended yet.\",\n controlItemMeta: \"{kind} · {domain} · updated {freshness}\",\n parkedResearchResultFallback: \"The validation result is retained and has not entered simulated observation.\",\n parkedResearchResultSource: \"View validation source\",\n parkedResearchResultsTitle: \"Research records\",\n parkedResearchResultTitle: \"SOXL research validation\",\n parkedResearchResultStatus: \"Not in simulated observation\",\n forwardObservationProgress: \"No-order observation progress: {completed} / {required} trading days · last observed {session}\",\n forwardObservationActive: \"Keep monitoring\",\n forwardObservationPaused: \"Keep paused\",\n forwardObservationComplete: \"Observation complete — review\",\n controlNext: \"Recommended action\",\n controlStatus: \"Current status\",\n ownerDecisionTitle: \"Choose the next step\",\n ownerDecisionAdminOnly: \"An administrator needs to confirm this.\",\n ownerDecisionReady: \"The data is ready. This records a decision; it does not enable trading.\",\n ownerDecisionRecorded: \"Saved: {decision}\",\n ownerDecisionApprove: \"Accept suggestion\",\n ownerDecisionPark: \"Keep parked\",\n ownerDecisionRetire: \"Stop tracking\",\n ownerDecisionConfirm: \"Save this decision?\",\n ownerDecisionSubmitting: \"Saving…\",\n ownerDecisionSuccess: \"Decision saved.\",\n ownerDecisionFailed: \"Could not save the decision\",\n reconciliationRecoveryBoard: \"Recovery decision\",\n reconciliationRecoveryLoginNotice: \"Sign in to see recovery and review items.\",\n reconciliationRecoveryStaleNotice: \"Recovery information is delayed. Wait for the next check.\",\n reconciliationRecoveryUnavailableNotice: \"Recovery information is temporarily unavailable.\",\n reconciliationRecoveryUpstreamNotice: \"Some recovery information is unavailable. Review the blockers first.\",\n reconciliationRecoveryEmpty: \"There are no recovery items right now.\",\n reconciliationRecoveryTitle: \"{platform} recovery check\",\n reconciliationRecoveryMeta: \"{strategy}\",\n reconciliationRecoveryReason: \"This account has completed its recovery checks. Decide whether to record recovery intent.\",\n reconciliationRecoveryImpact: \"After it is recorded, the system checks current state again. Trading does not start immediately, and risk stops stay in place.\",\n reconciliationRecoveryTechnicalDetails: \"View check evidence\",\n reconciliationRecoveryDetail: \"status: {state} · samples: {samples} · review: {review} · updated: {lastObserved}\",\n reconciliationRecoveryBlocked: \"Still needed: {blockers}\",\n reconciliationRecoveryReady: \"Checks are complete. Record your recovery decision.\",\n reconciliationRecoveryAdminOnly: \"An administrator needs to confirm this.\",\n reconciliationRecoveryConfirmed: \"Recovery confirmation saved.\",\n reconciliationRecoveryConfirm: \"Record recovery decision\",\n reconciliationRecoveryConfirmPrompt: \"Record this recovery decision? The runtime must still re-check current state; trading switches and circuit breakers remain independent.\",\n reconciliationRecoverySubmitting: \"Saving…\",\n reconciliationRecoverySuccess: \"Recovery decision recorded. Waiting for the runtime to re-check current state.\",\n reconciliationRecoveryFailed: \"Could not save the recovery decision\",\n reconciliationRecoveryNoOrder: \"This records a decision; it does not resume trading directly.\",\n binancePrivateScopeBoard: \"Private Binance asset list\",\n binancePrivateScopeAccount: \"Current collected Binance account\",\n binancePrivateScopePrivateIdentity: \"The private account digest is not displayed.\",\n binancePrivateScopeEmpty: \"empty: There is no current valid list to display.\",\n binancePrivateScopeUnavailable: \"not_available: The private list cannot be read right now.\",\n binancePrivateScopeObservedAt: \"Observed at: {time}\",\n binancePrivateScopeHistoricalWarning: \"Historical differences remain unresolved. This list is for manual comparison only and grants no order or remediation authority.\",\n binancePrivateScopeAsset: \"Asset\",\n binancePrivateScopeFree: \"Free\",\n binancePrivateScopeLocked: \"Locked\",\n executionEvidenceBoard: \"Execution and fills\",\n executionEvidenceLoginNotice: \"Sign in to see execution and fill records.\",\n executionEvidenceStaleNotice: \"Execution records are delayed. Check the latest platform status as well.\",\n executionEvidenceUnavailableNotice: \"Execution records are temporarily unavailable.\",\n executionEvidenceUpstreamNotice: \"Some execution records are unavailable. Please retry later.\",\n executionEvidenceEmpty: \"There are no execution records to display.\",\n executionEvidenceMeta: \"{platform} · current lane: {environment} · source: {source}\",\n executionEvidenceDetail: \"strategy: {strategy} · data: {data} · execution: {execution} · observe: {shadow} · simulated: {paper}\",\n executionEvidenceReceipt: \"execution receipt: {outcome} · broker confirmation: {confirmation}\",\n executionEvidenceReceiptMissing: \"execution receipt: not collected\",\n executionEvidenceReceiptNotDue: \"not in a due window\",\n executionEvidenceReceiptNoAction: \"strategy produced no order\",\n executionEvidenceReceiptRiskBlocked: \"blocked by risk controls\",\n executionEvidenceReceiptSubmitted: \"submitted; not yet confirmed\",\n executionEvidenceReceiptAcknowledged: \"broker acknowledged\",\n executionEvidenceReceiptPartiallyFilled: \"partially filled\",\n executionEvidenceReceiptFilled: \"filled\",\n executionEvidenceReceiptReconciliation: \"reconciliation required\",\n executionEvidenceReceiptFailed: \"execution failed; review required\",\n executionEvidenceConfirmationNotApplicable: \"not applicable\",\n executionEvidenceConfirmationNotObserved: \"not observed\",\n executionEvidenceConfirmationAcknowledged: \"acknowledged\",\n executionEvidenceConfirmationPartiallyFilled: \"partially filled\",\n executionEvidenceConfirmationFilled: \"filled\",\n executionEvidenceConfirmationReconciliation: \"reconciliation required\",\n executionEvidenceNoOrder: \"View the current execution and fill results.\",\n executionEvidenceNext: \"Recommended action\",\n runtimeTargetLifecycleBoard: \"Platform status\",\n runtimeTargetLifecycleLoginNotice: \"Sign in to see platform status.\",\n runtimeTargetLifecycleStaleNotice: \"Platform status is delayed. Check runtime first.\",\n runtimeTargetLifecycleUnavailableNotice: \"Platform status is temporarily unavailable.\",\n runtimeTargetLifecycleUpstreamNotice: \"Some platform status is unavailable. Please review it first.\",\n runtimeTargetLifecycleEmpty: \"There is no platform status to display.\",\n runtimeTargetLifecycleMeta: \"{platform} · {state} · lane: {mode}\",\n runtimeTargetLifecycleDetail: \"runtime guard: {guard} · execution heartbeat: {heartbeat}\",\n runtimeTargetLifecycleObservation: \"execution: {observation} · order/fill evidence: {evidence}\",\n runtimeTargetLifecycleNoOrder: \"View the current platform runtime status.\",\n runtimeTargetLifecycleNext: \"Current recommendation\",\n runtimeTargetLifecycleStateEnabled: \"enabled\",\n runtimeTargetLifecycleStateDisabled: \"disabled\",\n runtimeTargetLifecycleCheckPass: \"pass\",\n runtimeTargetLifecycleCheckAttention: \"attention\",\n runtimeTargetLifecycleCheckNotDue: \"not due\",\n runtimeTargetLifecycleCheckNotApplicable: \"not applicable\",\n runtimeTargetLifecycleCheckUnavailable: \"unavailable\",\n runtimeTargetLifecycleObservationNotDue: \"not in a due window\",\n runtimeTargetLifecycleObservationMonitoringOnly: \"latest check passed\",\n runtimeTargetLifecycleObservationNotApplicable: \"Disabled record\",\n runtimeTargetLifecycleObservationAttention: \"needs review\",\n runtimeTargetLifecycleObservationUnavailable: \"unavailable\",\n runtimeTargetLifecycleOrderEvidenceNotCollected: \"not collected\",\n runtimeTargetLifecycleDispositionEnabled: \"continue monitoring\",\n runtimeTargetLifecycleDispositionDisabled: \"disabled validation\",\n runtimeTargetLifecycleDispositionParked: \"parked\",\n runtimeTargetLifecycleReasonNone: \"monitoring normal\",\n runtimeTargetLifecycleReasonDisabled: \"intentionally disabled; validation continues\",\n runtimeTargetLifecycleReasonRuntimeGuard: \"runtime guard needs review\",\n runtimeTargetLifecycleReasonHeartbeat: \"execution heartbeat needs review\",\n runtimeTargetLifecycleReasonUnavailable: \"monitoring data unavailable\",\n m0ResearchBoard: \"External research records\",\n m0ResearchLoginNotice: \"Sign in to see external research records.\",\n m0ResearchStaleNotice: \"External research is delayed and is provided for historical context only.\",\n m0ResearchUnavailableNotice: \"External research records are temporarily unavailable.\",\n m0ResearchUpstreamNotice: \"Some external research records are unavailable. Please retry later.\",\n m0ResearchEmpty: \"There are no external research records to display.\",\n m0ResearchMore: \"Showing the first {count} research observations.\",\n m0ResearchMeta: \"{kind} · viewed {viewed}\",\n m0ResearchStateFreshness: \"State: {state} · freshness: {freshness}\",\n m0ResearchHorizons: \"Primary horizon: {primary} · suitable horizons: {suitable}\",\n m0ResearchEvidence: \"Confidence: {confidence} · style: {style} · source digest: {digest}\",\n m0ResearchConsistency: \"Current horizon conflict: {conflict} · historical stale drift: {drift}\",\n m0ResearchNoOrder: \"External research does not affect current strategy operation.\",\n adaptiveSelectionBoard: \"System suggestions\",\n adaptiveSelectionLoginNotice: \"Sign in to see system suggestions.\",\n adaptiveSelectionStaleNotice: \"Suggestions are delayed and are provided for historical context only.\",\n adaptiveSelectionUnavailableNotice: \"System suggestions are temporarily unavailable.\",\n adaptiveSelectionUpstreamNotice: \"Some suggestions are unavailable. Please retry later.\",\n adaptiveSelectionEmpty: \"There are no system suggestions to display.\",\n adaptiveSelectionMeta: \"{source} · {domain} · market as of {asOf}\",\n adaptiveSelectionRecommended: \"Observe suggestion\",\n adaptiveSelectionNoCandidate: \"No suitable suggestion yet\",\n adaptiveSelectionReason: \"Reasons: {reasons}\",\n adaptiveSelectionNoOrder: \"View the system's current suggestions.\",\n adaptiveSelectionScoreLabel: \"Research runs\",\n researchTaskBoard: \"Automation tasks\",\n researchTaskLoginNotice: \"Sign in to see automation tasks.\",\n researchTaskStaleNotice: \"Task information is delayed and is provided for historical context only.\",\n researchTaskUnavailableNotice: \"Automation tasks are temporarily unavailable.\",\n researchTaskUpstreamNotice: \"Some task information is unavailable. Please retry later.\",\n researchTaskEmpty: \"There are no automation tasks to display.\",\n researchTaskMeta: \"{type} · {domain} · created {created}\",\n researchTaskLimits: \"Research budget: up to {runs} run(s) / {seconds}s\",\n researchTaskNoOrder: \"View the current automation tasks.\",\n healthEyebrow: \"System status\",\n healthTitle: \"Runtime overview\",\n healthSubtitle: \"Platform runtime records first; expand strategy and research details as needed.\",\n healthTotal: \"Strategies\",\n healthHealthy: \"Healthy\",\n healthWatch: \"Watch\",\n healthReview: \"Review\",\n healthCritical: \"Critical\",\n healthBoard: \"Strategy health\",\n healthFilterAttention: \"Needs attention\",\n healthFilterAll: \"All strategies\",\n healthDataReady: \"Up to date\",\n healthDataStale: \"Update delayed\",\n healthDataUnavailable: \"Unavailable\",\n healthComputedAt: \"Updated: {time}\",\n healthLoginNotice: \"Sign in to see strategy health and runtime status.\",\n healthStaleNotice: \"Status is delayed; monitoring continues.\",\n healthUnavailableNotice: \"Strategy status is temporarily unavailable. Refresh later.\",\n healthUpstreamNotice: \"Some strategy status is unavailable. Retry later.\",\n healthNormalNotice: \"There are no runtime issues that need attention.\",\n healthAttentionNotice: \"{critical} critical, {review} to review, and {watch} under observation. Monitoring continues.\",\n healthEmpty: \"There are no strategies in this category.\",\n healthStatusHealthy: \"Healthy\",\n healthStatusWatch: \"Watch\",\n healthStatusReview: \"Review\",\n healthStatusCritical: \"Critical\",\n healthStatusUnknown: \"Unknown\",\n healthCardMeta: \"{status} · {domain}\",\n healthDecisionFallbackLabel: \"The system is continuing to monitor.\",\n healthDecisionFallbackReason: \"There is no exception for you to handle.\",\n healthRecommendationHealthy: \"The system is running normally.\",\n healthRecommendationWatch: \"The system is continuing to monitor.\",\n healthRecommendationReview: \"View diagnostic details while the system completes its review.\",\n healthRecommendationCritical: \"View diagnostic details and hold related changes for now.\",\n healthDetail: \"Data as of: {date}\",\n healthScoreLabel: \"Health\",\n diagnosticDetails: \"View diagnostic details\",\n diagnosticDetailsHint: \"Use this only to investigate an issue or review research records.\",\n researchTaskNoOrderBadge: \"NO ORDER\",\n recoveryConfirmedStatus: \"Confirmed\",\n recoveryReadyStatus: \"Ready to confirm\",\n recoveryBlockedStatus: \"Blocked\",\n commonUnknown: \"Unknown\",\n commonNotMarked: \"Not marked\",\n bootKicker: \"Starting console\",\n bootTitle: \"Loading strategy config\",\n bootMessage: \"Reading session, account config, and current state.\",\n bootStrategy: \"Reading strategy catalog.\",\n bootSession: \"Checking sign-in status.\",\n bootConfig: \"Reading account config and current state.\",\n bootTimeout: \"Loading timed out; switched to public preview. Retry after signing in.\",\n bootPublic: \"Public preview is ready.\",\n login: \"Sign in\",\n logout: \"Sign out\",\n signedInAs: \"Signed in as {login}\",\n planEyebrow: \"Strategy settings\",\n planTitle: \"Platform settings\",\n planSubtitle: \"Choose a platform, account, strategy, and environment; review this change before saving.\",\n planAdvancedSummary: \"Advanced settings\",\n planAdvancedHint: \"Runtime, plugins, cash, overlays, and DCA normally retain their current setup. Expand only when changing one.\",\n planScopeTitle: \"Choose scope\",\n planScopeSubtitle: \"Platform, account, strategy, and target environment\",\n planRuntimeTitle: \"Runtime protection\",\n planRuntimeSubtitle: \"Disable state, plugins, and overlays share one plan boundary\",\n planOverlayTitle: \"Strategy overlays\",\n planOverlaySubtitle: \"Only strategy-defined default guardrails are available\",\n planCashSubtitle: \"Cash reserve takes precedence over margin; they cannot override together\",\n activePlatform: \"Target platform\",\n account: \"Target account\",\n strategy: \"Strategy\",\n mode: \"Runtime mode\",\n live: \"Live trading\",\n paper: \"Paper trading\",\n dryRun: \"No-order check\",\n modeUnknown: \"Account type to be confirmed\",\n executionModeSetting: \"Execution setting\",\n executionModeLive: \"Execute trades\",\n executionModeDryRun: \"Check only, no orders\",\n executionModeSettingMeta: \"Changes the existing execution setting; no-order checks do not write trade orders.\",\n promotionConfirmTitle: \"Review research candidate\",\n promotionDecisionEyebrow: \"Decisions\",\n promotionTargetPlatform: \"Target platform\",\n promotionBrokerEnvironment: \"Broker environment\",\n promotionAccount: \"Specific account\",\n promotionExecutionMode: \"Target execution mode\",\n promotionExecutionModeReadonly: \"Account environment: {mode}\",\n promotionNoOrderCannotConfirm: \"This account is in no-order simulation; it cannot be recorded as broker paper or live intent.\",\n promotionRiskProfile: \"Risk profile\",\n promotionConfirmMeta: \"Accepting records your research decision. It does not enable trading or replace the current strategy.\",\n promotionTargetSummary: \"Suggested platform: {platform}; current account: {account}.\",\n promotionClickEffect: \"After clicking: this only records a human decision; the {mode} account will not be enabled or place orders because of it.\",\n promotionResearchSummary: \"Research summary\",\n promotionResearchSummaryMissing: \"Return comparison / strategy explanation not provided. {strategy}; {observation}\",\n promotionResearchSummaryMissingParts: \"Not provided: {items}\",\n promotionStrategyDescription: \"Strategy: {description}\",\n promotionPluginsUnknown: \"Plugins: not provided\",\n promotionPluginsNone: \"Plugins: none\",\n promotionPlugins: \"Plugins: {description}\",\n promotionComparison: \"Backtest: {startDate}—{endDate}; candidate after-cost CAGR {candidateCagr}; candidate max drawdown {candidateDrawdown}; baseline after-cost CAGR {baselineCagr}; baseline max drawdown {baselineDrawdown}\",\n promotionLimitations: \"Limitations: {limitations}\",\n promotionAiExplanation: \"AI explanation (advisory): {text}\",\n promotionTargetUnavailable: \"Research candidates await confirmation, but no target platform is visible.\",\n promotionRiskDetails: \"Risk profiles and account context\",\n promotionRiskScaleMeta: \"For drawdown control, balanced and growth-focused profiles, promotion size scales are 0.50 / 0.75 / 1.00 for new promotions or data changes only. Portfolio drawdown caps relative to the unlevered benchmark are 1.00 / 1.25 / 1.50. These have different meanings and do not change existing live settings.\",\n promotionPaperUnavailable: \"Broker paper/sim unavailable on this platform; paper disabled\",\n promotionTicket: \"Pending candidate\",\n promotionAccept: \"Accept suggestion\",\n promotionReject: \"Reject\",\n promotionTicketEmpty: \"No research candidates awaiting confirmation.\",\n promotionTicketLoginRequired: \"Sign in with an authorized account, then refresh\",\n promotionTicketLoadFailed: \"Research candidate queue unavailable. Refresh records; this does not mean there are no pending decisions.\",\n promotionAdminOnly: \"An administrator must confirm or reject\",\n promotionTicketSuggested: \"Candidate suggested risk profile: {profile}\",\n promotionUnnamedRecord: \"Unnamed strategy record {number}\",\n promotionFlowRecord: \"Workflow check record · source unverified\",\n promotionOldRecord: \"Older record\",\n promotionParameterProposal: \"Parameter proposal\",\n promotionUnverifiedCount: \"{count} older record(s) · evidence unverified\",\n promotionUnverifiedHint: \"This older research record does not identify its observation evidence. It is not a verified strategy. No acceptance or rejection is needed now; review it after its source is established.\",\n promotionOriginalRecord: \"View original name and evidence\",\n promotionDecisionHint: \"Review the research result, risk and source before accepting the suggestion.\",\n promotionTicketEvidenceKind: \"Observation type: {kind}\",\n promotionTicketParams: \"Suggested parameters: {params}\",\n promotionTicketNotification: \"Note: {body}\",\n promotionObservationReported: \"The record reports a passed observation; this does not establish complete validation.\",\n promotionObservationFailed: \"The record reports a failed observation.\",\n promotionObservationMissing: \"The record provides no observation outcome.\",\n promotionEvidenceSourceMissing: \"The source is unclear: no observation type is recorded. Check the source first.\",\n promotionEvidenceNeedsReview: \"An observation type is recorded, but its source and complete checks still need review.\",\n promotionDecisionSaved: \"Promotion intent recorded (no live authority granted)\",\n promotionDecisionFailed: \"Promotion confirmation failed\",\n promotionApplicationTitle: \"Account check\",\n promotionApplicationHint: \"A qualified candidate can be deployed to the confirmed paper account; it stays paused after deployment. Enabling it is a separate step.\",\n promotionApplicationCandidate: \"Research candidate\",\n promotionApplicationAccount: \"Target account\",\n promotionApplicationReady: \"Account and strategy checks passed; no change was submitted.\",\n promotionApplicationBlocked: \"This cannot be used yet: {reasons}. No change was submitted.\",\n promotionApplicationOpen: \"Review in account settings\",\n promotionApplicationDeploy: \"Deploy to paper account\",\n promotionApplicationQueued: \"Deployment request submitted; the account will remain paused.\",\n promotionApplicationDispatchUnknown: \"The submission result is unconfirmed; no duplicate submission will be made.\",\n promotionApplicationClaimed: \"Deployment is in progress; the account will remain paused.\",\n promotionApplicationApplied: \"The candidate was deployed and its version was checked; the account is paused.\",\n promotionApplicationRejected: \"Deployment was rejected: {reason}\",\n promotionApplicationUncertain: \"Deployment result is unconfirmed. Check the latest status.\",\n promotionApplicationEmpty: \"No research candidate is available for preparation.\",\n promotionApplicationBlockActivation: \"account application is not connected\",\n promotionApplicationBlockParams: \"runnable strategy parameters are missing\",\n promotionApplicationBlockStrategy: \"a same-name runnable strategy version is missing\",\n promotionApplicationBlockAccount: \"no configured account matches\",\n promotionApplicationBlockEvidence: \"research evidence is not verified\",\n promotionApplicationBlockBrokerEnvironment: \"broker environment is missing or unsupported\",\n promotionApplicationBlockPreflight: \"account or strategy preflight failed\",\n riskCapitalPreservation: \"Drawdown control\",\n riskBalancedCompounding: \"Balanced return and drawdown\",\n riskGrowthCompounding: \"Growth focused\",\n riskEnvelopeTitle: \"Account risk envelope\",\n riskEnvelopePreference: \"Risk preference\",\n riskEnvelopeCapitalBand: \"Capital band\",\n riskEnvelopeStatus: \"Status lamp\",\n riskEnvelopeDetailsSummary: \"Details\",\n riskEnvelopeMeta: \"Read-only; does not grant live authority or auto step-up.\",\n riskEnvelopeAwaitingEquity: \"Awaiting reconciled equity\",\n riskEnvelopeUnset: \"Unset\",\n promotionModeLive: \"Live trading\",\n promotionModePaper: \"Simulated trading\",\n liveModeUnavailable: \"This selection is not eligible for a new live switch. See the current account state above.\",\n runtimeTargetMode: \"Account status\",\n runtimeStopConfirm: \"Submit disable for this account. Only the disable setting is saved and verified; other form edits are ignored. Whether the platform has stopped remains unknown. No cancellation or liquidation; in-flight work may continue. Continue?\",\n runtimeStopPending: \"Disable requested. Inspect the task for the configuration save result. Platform application was not requested; actual runtime state is unknown. Do not submit again.\",\n runtimeStopReadyNote: \"Disable selected: the main action submits a strict stop-only configuration save. Strategy re-listing is not required and other form edits are not applied.\",\n runtimeSectionTitle: \"Runtime and plugins\",\n runtimeTargetCurrent: \"\",\n runtimeTargetEnabled: \"Enabled\",\n runtimeTargetDisabled: \"Disabled\",\n runtimeTargetModeMeta: \"Select a change, then use the main action below. Saving a disable setting does not prove the platform stopped; actual state requires readback.\",\n pluginMode: \"Plugin status\",\n pluginModeNone: \"Do not mount legacy plugins\",\n pluginModeMeta: \"The current candidate has no bound plugin; legacy plugins are not auto-mounted.\",\n incomeLayerMode: \"Income layer\",\n incomeLayerSectionTitle: \"Income layer\",\n incomeLayerCurrent: \"Keep current config\",\n incomeLayerEnabled: \"Enable income layer\",\n incomeLayerDisabled: \"Disable income layer\",\n incomeLayerNotSupported: \"No income layer for this strategy\",\n incomeLayerStartUsd: \"Income layer start amount\",\n incomeLayerMaxRatio: \"Income layer max ratio\",\n incomeLayerModeMeta: \"Only applies to US equity strategies with an income layer.\",\n incomeLayerDefaultMeta: \"Strategy default: starts at {start}, max {ratio}.\",\n incomeLayerAllocationMeta: \"Default allocation: {allocations}.\",\n incomeLayerStartMeta: \"Income layer activates after total assets reach this amount.\",\n incomeLayerRatioMeta: \"Use 0.55 for a 55% cap.\",\n optionOverlayMode: \"Option layer\",\n optionOverlaySectionTitle: \"Option layer\",\n optionOverlayCurrent: \"Keep current config\",\n optionOverlayEnabled: \"Enable option layer\",\n optionOverlayDisabled: \"Disable option layer\",\n optionOverlayNotSupported: \"No option layer for this strategy\",\n optionOverlayModeMeta: \"Enabled mode uses the strategy's default recipe and budget; ratios are not edited here.\",\n optionOverlayDefaultMeta: \"{defaults}\",\n optionOverlayFamilyGrowth: \"Growth\",\n optionOverlayFamilyIncome: \"Income\",\n optionOverlayBudgetRatio: \"budget {ratio}\",\n optionOverlayRiskRatio: \"risk {ratio}\",\n cashOnlyExecutionMode: \"Allow margin\",\n cashOnlyExecutionCurrent: \"Keep current config\",\n cashOnlyExecutionYes: \"Yes\",\n cashOnlyExecutionNo: \"No\",\n cashOnlyExecutionModeMeta: \"Choose No to use available cash only and avoid margin buying power.\",\n cashOnlyExecutionValueYes: \"Yes\",\n cashOnlyExecutionValueNo: \"No\",\n currentCashOnlyExecution: \"Current allow margin\",\n pendingCashOnlyExecution: \"Pending allow margin\",\n executionCashPolicyTitle: \"Capital boundary\",\n executionCashPolicyNote: \"Allow margin and reserve-cash overrides cannot both apply. Yes clears reserve overrides; reserve overrides force No.\",\n executionCashMarginBlocksReserve: \"Allow margin is selected; submitting will clear reserve-cash overrides.\",\n executionCashReserveBlocksMargin: \"Reserve-cash override is active; submitting will force allow margin to No.\",\n qmtPlatformCashNote: \"QMT A-share does not use margin or platform reserve cash; cash constraints live in strategy execution_cash_reserve_ratio.\",\n qmtDryRunOnlyNote: \"This platform supports no-order dry runs only; no live execution route is configured.\",\n binancePlatformNote: \"Binance does not use broker-level income/option layers; features are implemented inside strategies.\",\n invalidExecutionCashPolicyNote: \"Allow margin and reserve-cash overrides conflict. Keep only one constraint.\",\n dcaMode: \"DCA mode\",\n dcaSectionTitle: \"DCA\",\n dcaModeFixed: \"Fixed DCA\",\n dcaModeSmart: \"Smart DCA\",\n dcaBaseInvestmentUsd: \"Base DCA amount\",\n dcaModeMeta: \"Only DCA strategies can use this.\",\n dcaDefaultMeta: \"Default: {mode}, base amount {amount}.\",\n dcaNotSupported: \"This is not a DCA strategy\",\n dcaPlatformNotSupported: \"DCA not supported on this platform\",\n currentDca: \"Current DCA settings\",\n pendingDca: \"Pending DCA settings\",\n dcaText: \"{mode}, base amount {amount}\",\n minReservedCash: \"Minimum reserved cash ({currency})\",\n reservedCashRatio: \"Reserved cash ratio\",\n reservedCashMode: \"Reserved cash policy\",\n reservePolicyCurrent: \"Keep current config\",\n reservePolicyNone: \"No platform reserve\",\n reservePolicyRatio: \"Ratio only\",\n reservePolicyFloor: \"Fixed amount only\",\n reservePolicyMax: \"Max of amount and ratio\",\n reservedCashModeMeta: \"Choose whether to keep, clear, or override platform reserved cash.\",\n reservedCashNone: \"None\",\n reservedCashDefault: \"Not configured (platform default: 0 {currency} / 0%)\",\n reservedCashMeta: \"Fixed cash floor. Use alone or with a ratio.\",\n reservedCashRatioMeta: \"Use 0.03 for 3%.\",\n summary: \"Current configuration\",\n summaryCurrent: \"Saved configuration\",\n summaryPending: \"Pending change\",\n copySummary: \"Copy state\",\n loginToRun: \"Sign in to submit a plan\",\n loadingConfig: \"Loading config\",\n configureAccounts: \"Configure accounts\",\n runSwitch: \"Save settings\",\n noChanges: \"No changes\",\n readonlyNote: \"Sign in to save settings.\",\n publicReadonly: \"Sign in to view account config.\",\n loadingConfigNote: \"Reading account config and current state.\",\n missingConfigNote: \"Account config is not loaded, so switching is disabled.\",\n readyNote: \"Review the changes above, then save.\",\n invalidStrategyNote: \"This strategy switch does not meet the requirements for the selected execution mode. See the current account state above.\",\n binanceResume: \"Resume current live target\",\n binanceResumeHint: \"Restore only the enable setting, preserving the current strategy and cash configuration. The runtime still verifies the recovery record.\",\n binanceResumeModeHint: \"Use the resume button above for the existing target; the form below switches strategies.\",\n binanceResumeConfirm: \"Resume the current Binance live target? Only the enable setting will be saved. Current strategy and cash settings are retained; unsaved form edits will not be submitted. Execution still requires runtime recovery and risk checks.\",\n binanceResumePending: \"Resume requested. Check the result and refresh configuration; actual recovery requires platform runtime evidence.\",\n binanceResumeUnknown: \"Submission is unconfirmed. Check the existing run before refreshing and retrying.\",\n invalidReservePolicyNote: \"Enter a valid amount or ratio for the selected reserved-cash policy.\",\n invalidIncomeLayerNote: \"Enter a valid income layer start amount and max ratio.\",\n invalidOptionOverlayNote: \"This strategy does not define an option layer to enable.\",\n invalidDcaNote: \"Enter a valid DCA mode and base amount.\",\n noAccount: \"No accounts\",\n noStrategy: \"No supported strategies\",\n repository: \"Repository\",\n selectedAccount: \"Account\",\n selectedMarket: \"Market\",\n currentRuntimeTarget: \"Current account status\",\n pendingRuntimeTarget: \"Pending account status\",\n reservedCashPolicy: \"Current reserved cash\",\n currentIncomeLayer: \"Current income layer\",\n pendingIncomeLayer: \"Pending income layer\",\n currentOptionOverlay: \"Current option layer\",\n pendingOptionOverlay: \"Pending option layer\",\n pendingReservedCashPolicy: \"Pending reserved cash\",\n pendingMode: \"Pending mode\",\n currentPluginMode: \"Current plugin scope\",\n pendingPluginMode: \"Pending plugin scope\",\n unchanged: \"Unchanged\",\n copied: \"State copied\",\n dispatching: \"Dispatching workflow...\",\n dispatched: \"Workflow dispatched\",\n dispatchFailed: \"Dispatch failed\",\n targetMeta: \"\",\n strategyMeta: \"Markets: {domains}\",\n strategyLifecycleMeta: \"current gate {stage}\",\n strategyBlockedCountMeta: \"{count} strategies are blocked from live\",\n strategyDefaultBlockedMeta: \"Default strategy {profile} is blocked: {reason}\",\n usEquity: \"US equity\",\n hkEquity: \"HK equity\",\n cnEquity: \"CN A-share\",\n cryptoEquity: \"Crypto\",\n currentStrategy: \"Current strategy\",\n nextStrategy: \"Switch strategy\",\n notRead: \"Not read yet\",\n runtimeTargetOn: \"Enabled\",\n runtimeTargetOff: \"Disabled\",\n incomeLayerDefault: \"Enabled, {start} start, {ratio} max\",\n incomeLayerOff: \"Disabled\",\n incomeLayerOn: \"Enabled, starts at {start}, max {ratio}\",\n optionOverlayOff: \"Disabled\",\n optionOverlayOn: \"Enabled\",\n optionOverlayDefaultSimple: \"Strategy default: enabled\",\n optionOverlayDefault: \"Enabled, {detail}\",\n cashOnlyExecutionDefault: \"Cash only\",\n notConfigured: \"Not set\",\n strategyDefault: \"Use strategy default\",\n },\n };\n\n const storedLang = localStorage.getItem(\"qsl-switch-lang\");\n const initialLang = storedLang === \"zh\" || storedLang === \"en\"\n ? storedLang\n : ((navigator.language || \"\").toLowerCase().startsWith(\"zh\") ? \"zh\" : \"en\");\n const clone = (value) => JSON.parse(JSON.stringify(value));\n const runtimeStopLock = { pending: false };\n const binanceResumeLock = { pending: false, messageKey: \"\" };\n let binancePrivateScopeRequestGeneration = 0;\n const defaultReserveForm = () => ({\n reservePolicyMode: \"current\",\n minReservedCashUsd: \"\",\n reservedCashRatio: \"\",\n reservedCashTouched: false,\n incomeLayerMode: \"current\",\n incomeLayerStartUsd: \"\",\n incomeLayerMaxRatio: \"\",\n incomeLayerTouched: false,\n optionOverlayMode: \"current\",\n optionOverlayTouched: false,\n cashOnlyExecutionMode: \"current\",\n cashOnlyExecutionTouched: false,\n runtimeTargetMode: \"current\",\n runtimeTargetTouched: false,\n dcaMode: \"fixed\",\n dcaBaseInvestmentUsd: \"\",\n dcaTouched: false,\n strategyTouched: false,\n executionModeTouched: false,\n pluginModeTouched: false,\n });\n\n const state = {\n view: \"overview\",\n researchInternalView: \"monitoring\",\n overviewFilter: \"all\",\n overviewSearch: \"\",\n lastRefreshAt: null,\n refreshing: false,\n selected: Object.keys(platformMeta)[0] || \"\",\n lang: initialLang,\n appReady: false,\n bootMessageKey: \"bootMessage\",\n auth: { available: false, allowed: false, admin: false, login: null },\n accountOptions: clone(defaultAccountOptions),\n currentStrategies: {},\n health: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { strategy_count: 0, healthy: 0, watch: 0, review: 0, critical: 0 },\n strategies: [],\n },\n filter: \"attention\",\n },\n controlPlane: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { candidate_count: 0, deferred: 0, parked: 0, owner_decision_required: 0 },\n attention: { status: \"unavailable\", reason_codes: [\"control_plane_source_unavailable\"] },\n candidates: [],\n policy: { p4_p5_automation: \"not_configured\", p6_owner_decision_required: true },\n errors: [],\n },\n },\n ownerDecisions: {\n data_status: \"unavailable\",\n candidates: [],\n errors: [],\n },\n reconciliationRecovery: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { recovery_count: 0, awaiting_human_confirmation: 0, blocked: 0, confirmed: 0 },\n recoveries: [],\n policy: { human_confirmation_required: true, current_evidence_required: true, no_order: true, execution_authority_granted: false },\n errors: [],\n },\n submittingRecoveryId: null,\n },\n binancePrivateScope: {\n status: \"not_available\",\n report: null,\n },\n m0Research: {\n payload: {\n data_status: \"unavailable\",\n viewed_at: null,\n summary: {\n subject_count: 0,\n observation_count: 0,\n fresh_observation_count: 0,\n stale_observation_count: 0,\n unknown_observation_count: 0,\n horizon_conflict_count: 0,\n historical_stale_horizon_drift_count: 0,\n },\n subjects: [],\n policy: { authority: \"research_only\", no_order: true, permitted_next_step: \"research_validation_only\" },\n errors: [],\n },\n },\n adaptiveSelection: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { source_count: 0, decision_count: 0, candidate_count: 0, recommended_count: 0, rejected_candidate_count: 0 },\n selections: [],\n policy: { authority: \"shadow_only\", no_order: true, execution_authority_granted: false },\n errors: [],\n },\n },\n executionEvidence: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { deployment_count: 0, autonomous_shadow: 0, autonomous_paper: 0, owner_canary_decision: 0, parked: 0 },\n deployments: [],\n policy: { execution_evidence_read_only: true, p6_owner_decision_required: true, limited_live_canary_active: false },\n errors: [],\n },\n },\n runtimeTargetLifecycle: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { target_count: 0, enabled: 0, disabled: 0, attention: 0 },\n targets: [],\n policy: { lifecycle_status_read_only: true, no_order: true },\n errors: [],\n },\n },\n accountDiagnosis: {\n tasks: {},\n loading: {},\n submitting: {},\n },\n researchTasks: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { task_count: 0 },\n tasks: [],\n policy: { research_only: true, no_order: true, size_zero_required: true, p4_p5_p6_authorized: false },\n errors: [],\n },\n },\n researchPromotion: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n tickets: [],\n applications: [],\n summary: { ticket_count: 0, awaiting_human: 0 },\n policy: { live_authority_granted: false, no_order: true },\n errors: [],\n },\n selectedTicketId: \"\",\n selectedApplicationTicketId: \"\",\n selectedApplicationPlatform: \"\",\n selectedApplicationEnvironment: \"\",\n selectedApplicationAccountKey: \"\",\n },\n configSource: \"default\",\n repositories: clone(defaultRepositories),\n forms: Object.fromEntries(Object.keys(platformMeta).map((platform) => [platform, {\n accountKey: defaultAccountOptions[platform]?.[0]?.key || \"preview\",\n strategy: \"\",\n executionMode: \"\",\n pluginMode: \"none\",\n ...defaultReserveForm(),\n }])),\n };\n\n const el = (id) => document.getElementById(id);\n const t = (key) => copy[state.lang][key] || copy.en[key] || key;\n const locale = () => (state.lang === \"zh\" ? \"zh-CN\" : \"en-US\");\n\n function formatDateTime(value) {\n if (!value) return \"—\";\n const parsed = value instanceof Date ? value : new Date(value);\n if (Number.isNaN(parsed.getTime())) return \"—\";\n return new Intl.DateTimeFormat(locale(), {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n }).format(parsed);\n }\n\n function formatAsOfDate(value) {\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n const parsed = new Date(`${value}T00:00:00.000Z`);\n return new Intl.DateTimeFormat(locale(), {\n dateStyle: \"medium\",\n timeZone: \"UTC\",\n }).format(parsed);\n }\n return formatDateTime(value);\n }\n\n function localizedExternalText(value, fallback) {\n const text = typeof value === \"string\" ? value.trim() : \"\";\n if (!text) return fallback;\n const hasChinese = /[\\u3400-\\u9fff]/.test(text);\n const hasLatinWords = /[A-Za-z]{3,}/.test(text);\n if ((state.lang === \"en\" && hasChinese) || (state.lang === \"zh\" && hasLatinWords && !hasChinese)) {\n return fallback;\n }\n return text;\n }\n let toastTimer = null;\n\n function showToast(message, { duration = 4000 } = {}) {\n const node = el(\"toast\");\n if (toastTimer) {\n window.clearTimeout(toastTimer);\n toastTimer = null;\n }\n node.textContent = message || \"\";\n if (message && duration > 0) {\n toastTimer = window.setTimeout(() => {\n node.textContent = \"\";\n toastTimer = null;\n }, duration);\n }\n }\n\n async function fetchWithTimeout(url, init = {}, timeoutMs = APP_BOOT_TIMEOUT_MS) {\n const controller = new AbortController();\n const timeoutId = window.setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } catch (error) {\n if (error?.name === \"AbortError\") {\n throw new Error(\"request timeout\");\n }\n throw error;\n } finally {\n window.clearTimeout(timeoutId);\n }\n }\n\n async function requestJson(url, init = {}, timeoutMs = APP_BOOT_TIMEOUT_MS) {\n const response = await fetchWithTimeout(url, { ...init, cache: \"no-store\" }, timeoutMs);\n if (!response.ok) throw new Error(\"request failed\");\n return response.json();\n }\n\n function isRequestTimeoutError(error) {\n return String(error?.message || \"\").toLowerCase() === \"request timeout\";\n }\n\n function optionsFor(platform) {\n return state.accountOptions[platform] && state.accountOptions[platform].length\n ? state.accountOptions[platform]\n : defaultAccountOptions[platform];\n }\n\n function selectedAccount(platform = state.selected) {\n const options = optionsFor(platform);\n const form = state.forms[platform];\n return options.find((option) => option.key === form.accountKey) || options[0];\n }\n\n function accountDisplayLabel(account) {\n const selectors = String(account?.account_selector || \"\")\n .split(/[\\s,;|]+/)\n .map(value => value.trim())\n .filter(value => /^U\\d+$/i.test(value))\n .map(value => value.toUpperCase());\n const accountIds = [...new Set(selectors)];\n return accountIds.length\n ? accountIds.join(\" / \")\n : String(account?.label || account?.target_name || account?.key || \"\");\n }\n\n function hasPrivateConfig() {\n return Boolean(state.auth.allowed && state.configSource === \"private\");\n }\n\n function cleanStrategyProfile(value) {\n const profile = String(value || \"\").trim();\n return /^[a-z0-9._=-]{1,120}$/.test(profile) ? profile : \"\";\n }\n\n function cleanStrategyDomain(value) {\n const domain = String(value || \"\").trim();\n return strategyDomains.includes(domain) ? domain : \"\";\n }\n\n function domainLabel(domain) {\n const entry = domainLabels[domain];\n if (entry) return state.lang === \"zh\" ? entry.zh : entry.en;\n return domain;\n }\n\n function platformSupportsMarginPolicy(platform = state.selected) {\n return platformConfig[platform]?.margin_policy ?? true;\n }\n\n function platformSupportsReservedCashPolicy(platform = state.selected) {\n return platformConfig[platform]?.reserved_cash ?? true;\n }\n\n function platformDryRunOnly(platform = state.selected) {\n return platformConfig[platform]?.dry_run_only ?? false;\n }\n\n function supportedExecutionModesForPlatform(platform = state.selected) {\n const modes = platformConfig[platform]?.supported_execution_modes;\n return Array.isArray(modes) ? modes.filter((mode) => mode === \"live\" || mode === \"dry_run\") : [];\n }\n\n function allowMarginExplicitlySelected(form) {\n return normalizeCashOnlyExecutionMode(form?.cashOnlyExecutionMode) === \"disabled\";\n }\n\n function reserveCashOverrideActive(form) {\n const mode = normalizeReservePolicyMode(form?.reservePolicyMode);\n return mode === \"ratio\" || mode === \"floor\" || mode === \"max\";\n }\n\n function executionCashPolicyConflict(form) {\n return allowMarginExplicitlySelected(form) && reserveCashOverrideActive(form);\n }\n\n function reconcileExecutionCashPolicy(form, changed) {\n if (!form) return;\n if (changed === \"margin\" && allowMarginExplicitlySelected(form)) {\n if (form.reservePolicyMode !== \"none\" && (form.minReservedCashUsd || form.reservedCashRatio)) {\n form._prevReserve = {\n mode: form.reservePolicyMode,\n floor: form.minReservedCashUsd,\n ratio: form.reservedCashRatio,\n };\n }\n form.reservePolicyMode = \"none\";\n form.reservedCashTouched = true;\n } else if (changed === \"reserve\" && reserveCashOverrideActive(form)) {\n form.cashOnlyExecutionMode = \"enabled\";\n form.cashOnlyExecutionTouched = true;\n }\n }\n\n function restoreReserveAfterMarginDisabled(form) {\n if (!form || allowMarginExplicitlySelected(form) || !form._prevReserve) return;\n form.reservePolicyMode = form._prevReserve.mode;\n form.minReservedCashUsd = form._prevReserve.floor;\n form.reservedCashRatio = form._prevReserve.ratio;\n form.reservedCashTouched = true;\n delete form._prevReserve;\n }\n\n function strategyDomain(profile) {\n return strategyCatalog[profile]?.domain || \"\";\n }\n\n function selectedCashCurrency(platform = state.selected, account = selectedAccount(platform)) {\n const configured = String(account?.cash_currency || \"\").trim().toUpperCase();\n if (configured === \"USD\" || configured === \"HKD\" || configured === \"CNY\") return configured;\n const domain = strategyDomain(state.forms[platform]?.strategy);\n if (domain === \"hk_equity\") return \"HKD\";\n if (domain === \"cn_equity\") return \"CNY\";\n return \"USD\";\n }\n\n function applyStrategyProfiles(rawProfiles) {\n const profiles = Array.isArray(rawProfiles) && rawProfiles.length\n ? rawProfiles\n : defaultStrategyProfiles;\n const nextOptions = [];\n const nextLabels = {};\n const nextCatalog = {};\n const nextIncomeLayerDefaults = {};\n const nextOptionOverlayDefaults = {};\n for (const item of profiles) {\n const profile = cleanStrategyProfile(item?.profile || item?.strategy_profile);\n if (!profile || nextOptions.includes(profile)) continue;\n const domain = cleanStrategyDomain(item?.domain || \"us_equity\");\n if (!domain) continue;\n nextOptions.push(profile);\n nextLabels[profile] = strategyLabelSet(profile, item);\n nextCatalog[profile] = {\n profile,\n label: nextLabels[profile].en || nextLabels[profile].zh || profile,\n label_en: nextLabels[profile].en || \"\",\n label_zh: nextLabels[profile].zh || \"\",\n domain,\n runtime_enabled: cleanOptionalBoolean(item?.runtime_enabled ?? false) === true,\n };\n const lifecycleStage = normalizeLifecycleStage(item?.lifecycle_stage ?? item?.lifecycleStage);\n if (lifecycleStage) nextCatalog[profile].lifecycle_stage = lifecycleStage;\n const allowedExecutionModes = normalizeAllowedExecutionModes(item?.allowed_execution_modes);\n if (allowedExecutionModes.length) nextCatalog[profile].allowed_execution_modes = allowedExecutionModes;\n const canSwitchLive = cleanOptionalBoolean(item?.can_switch_live);\n if (canSwitchLive !== null) nextCatalog[profile].can_switch_live = canSwitchLive;\n const blockedLiveReason = cleanDisplayText(item?.blocked_live_reason);\n if (blockedLiveReason) nextCatalog[profile].blocked_live_reason = blockedLiveReason;\n const latestEvidenceStatus = cleanDisplayText(item?.latest_evidence_status);\n if (latestEvidenceStatus) nextCatalog[profile].latest_evidence_status = latestEvidenceStatus;\n const pluginGateStatus = cleanDisplayText(item?.plugin_gate_status);\n if (pluginGateStatus) nextCatalog[profile].plugin_gate_status = pluginGateStatus;\n const dcaDefaults = dcaProfileDefaults[profile] || null;\n if (dcaDefaults || item?.dca_enabled === true) {\n nextCatalog[profile].dca_enabled = true;\n nextCatalog[profile].dca_default_mode = normalizeDcaMode(\n item?.dca_default_mode || item?.default_dca_mode || dcaDefaults?.defaultMode || \"fixed\",\n );\n nextCatalog[profile].dca_default_base_investment_usd = cleanDisplayPositiveNumber(\n item?.dca_default_base_investment_usd ||\n item?.default_dca_base_investment_usd ||\n dcaDefaults?.defaultBaseInvestmentUsd ||\n \"1000\",\n ) || \"1000\";\n }\n const profileIncomeDefaults = incomeLayerDefaultsFromProfileItem(item);\n const incomeDefaults = profileIncomeDefaults === false\n ? null\n : (profileIncomeDefaults || fallbackIncomeLayerDefaults[profile] || null);\n if (incomeDefaults) {\n nextIncomeLayerDefaults[profile] = incomeDefaults;\n nextCatalog[profile].income_layer_enabled = true;\n nextCatalog[profile].income_layer_start_usd = String(incomeDefaults.startUsd);\n nextCatalog[profile].income_layer_max_ratio = incomeDefaults.maxRatio;\n nextCatalog[profile].income_layer_allocations = incomeDefaults.allocations;\n }\n const profileOptionDefaults = optionOverlayDefaultsFromProfileItem(item);\n const optionDefaults = profileOptionDefaults === false\n ? null\n : (profileOptionDefaults || fallbackOptionOverlayDefaults[profile] || null);\n if (optionDefaults) {\n nextOptionOverlayDefaults[profile] = optionDefaults;\n nextCatalog[profile].option_overlay_enabled = true;\n nextCatalog[profile].option_overlay_live_gate = optionDefaults.liveGate || \"\";\n nextCatalog[profile].option_overlay_live_status = optionDefaults.liveStatus || \"\";\n }\n }\n if (!nextOptions.length && profiles !== defaultStrategyProfiles) return applyStrategyProfiles(defaultStrategyProfiles);\n strategyOptions = nextOptions;\n strategyLabels = nextLabels;\n strategyCatalog = nextCatalog;\n incomeLayerDefaults = nextIncomeLayerDefaults;\n optionOverlayDefaults = nextOptionOverlayDefaults;\n }\n\n function incomeLayerDefaultsFromProfileItem(item) {\n const enabled = cleanOptionalBoolean(item?.income_layer_enabled);\n const hasConfig = enabled !== null ||\n item?.income_layer_start_usd !== undefined ||\n item?.income_layer_max_ratio !== undefined ||\n item?.income_layer_allocations !== undefined;\n if (!hasConfig) return null;\n if (enabled === false) return false;\n const startUsd = cleanDisplayNumber(item?.income_layer_start_usd);\n const maxRatio = cleanDisplayRatio(item?.income_layer_max_ratio);\n const allocations = cleanIncomeLayerAllocations(item?.income_layer_allocations);\n if (!startUsd || !maxRatio || !allocations) return null;\n return { startUsd, maxRatio, allocations };\n }\n\n function cleanIncomeLayerAllocations(value) {\n if (!value || Array.isArray(value) || typeof value !== \"object\") return null;\n const allocations = {};\n let total = 0;\n for (const [rawSymbol, rawRatio] of Object.entries(value)) {\n const symbol = String(rawSymbol || \"\").trim().toUpperCase();\n const ratio = cleanDisplayPositiveNumber(rawRatio);\n if (!/^[A-Z0-9.-]{1,12}$/.test(symbol) || !ratio) continue;\n allocations[symbol] = Number(ratio);\n total += Number(ratio);\n }\n return total > 0 && Object.keys(allocations).length ? allocations : null;\n }\n\n function optionOverlayDefaultsFromProfileItem(item) {\n const enabled = cleanOptionalBoolean(item?.option_overlay_enabled);\n const hasConfig = enabled !== null ||\n item?.option_growth_overlay_enabled !== undefined ||\n item?.option_income_overlay_enabled !== undefined ||\n item?.option_overlay_live_gate !== undefined ||\n item?.option_overlay_live_status !== undefined;\n if (!hasConfig) return null;\n if (enabled === false) return false;\n const families = [\n optionOverlayFamilyDefaultsFromProfileItem(item, \"growth\"),\n optionOverlayFamilyDefaultsFromProfileItem(item, \"income\"),\n ].filter(Boolean);\n if (!families.length) return null;\n return {\n liveGate: String(item?.option_overlay_live_gate || \"promotion_required\"),\n liveStatus: String(item?.option_overlay_live_status || \"research_only\"),\n families,\n };\n }\n\n function optionOverlayFamilyDefaultsFromProfileItem(item, family) {\n const prefix = `option_${family}_overlay`;\n const enabled = cleanOptionalBoolean(item?.[`${prefix}_enabled`]);\n if (enabled !== true) return null;\n const recipe = cleanStrategyProfile(item?.[`${prefix}_recipe`]);\n const startUsd = cleanDisplayNumber(item?.[`${prefix}_start_usd`]);\n const ratioField = family === \"growth\"\n ? \"option_growth_overlay_nav_budget_ratio\"\n : \"option_income_overlay_nav_risk_ratio\";\n const ratio = cleanDisplayRatio(item?.[ratioField]);\n if (!recipe || !startUsd || !ratio) return null;\n return {\n family,\n recipe,\n startUsd,\n ratio,\n ratioKind: family === \"growth\" ? \"budget\" : \"risk\",\n };\n }\n\n function supportedDomainsForAccount(platform, account) {\n if (Array.isArray(account?.supported_domains) && account.supported_domains.length) {\n const cleaned = account.supported_domains.map(cleanStrategyDomain).filter(Boolean);\n if (cleaned.length) return [...new Set(cleaned)];\n }\n return inferSupportedDomains(platform, account);\n }\n\n function inferSupportedDomains(platform, account) {\n void account;\n const configured = typeof platformConfig !== \"undefined\" ? platformConfig[platform]?.supported_domains : null;\n if (Array.isArray(configured) && configured.length) return [...configured];\n if (platform === \"qmt\") return [\"cn_equity\"];\n if (platform === \"binance\") return [\"crypto\"];\n if (platform === \"longbridge\" || platform === \"ibkr\") return [\"us_equity\", \"hk_equity\"];\n return [\"us_equity\"];\n }\n\n function supportedDomainLabel(platform, account) {\n return supportedDomainsForAccount(platform, account).map(domainLabel).join(\" / \");\n }\n\n function platformSupportsDca(platform = state.selected) {\n return platformConfig[platform]?.dca ?? false;\n }\n\n function strategyCatalogEntry(profile) {\n return strategyCatalog[cleanStrategyProfile(profile)] || {};\n }\n\n function normalizeLifecycleStage(value) {\n const text = String(value || \"\").trim().toLowerCase();\n if (!text || text.length > 40 || !/^[a-z0-9._-]+$/.test(text)) return \"\";\n if ([\"research_backtest_only\", \"ai_monitored_candidate\"].includes(text)) return \"research_active\";\n if (text === \"shadow_candidate\") return \"shadow_active\";\n return text;\n }\n\n function normalizeAllowedExecutionModes(value) {\n const items = Array.isArray(value)\n ? value\n : String(value || \"\").split(/[,\\s/|]+/);\n const modes = [];\n for (const item of items) {\n const mode = String(item || \"\").trim().toLowerCase();\n if (!mode || mode.length > 32 || !/^[a-z0-9._-]+$/.test(mode)) continue;\n if (!modes.includes(mode)) modes.push(mode);\n }\n return modes;\n }\n\n function cleanDisplayText(value) {\n const text = String(value ?? \"\").trim();\n if (!text || text.length > 120 || /[<>]/.test(text)) return \"\";\n return text;\n }\n\n function strategyCanSwitchLive(entry) {\n if (!entry || typeof entry !== \"object\") return false;\n if (entry.runtime_enabled !== true) return false;\n const allowedModes = normalizeAllowedExecutionModes(entry.allowed_execution_modes);\n if (!allowedModes.includes(\"live\")) return false;\n if (cleanOptionalBoolean(entry.can_switch_live) !== true) return false;\n const lifecycleStage = normalizeLifecycleStage(entry.lifecycle_stage);\n if (![\"live_enabled\", \"runtime_enabled\"].includes(lifecycleStage)) return false;\n const blockedReason = cleanDisplayText(entry.blocked_live_reason);\n if (blockedReason) return false;\n const evidenceStatus = cleanDisplayText(entry.latest_evidence_status);\n if (evidenceStatus && [\"research_only\", \"blocked\", \"pending\"].includes(evidenceStatus.toLowerCase())) return false;\n const pluginGateStatus = cleanDisplayText(entry.plugin_gate_status);\n if (pluginGateStatus && [\"blocked\", \"locked\", \"disabled\"].includes(pluginGateStatus.toLowerCase())) return false;\n return true;\n }\n\n function strategyDisplayMetaText(platform, account, profile) {\n void profile;\n return t(\"strategyMeta\").replace(\"{domains}\", supportedDomainLabel(platform, account));\n }\n\n function strategyActionNoteText(platform = state.selected, account = selectedAccount(platform)) {\n if (platform === \"binance\" && binanceResumeDigest()) return t(\"binanceResumeModeHint\");\n const profile = state.forms[platform]?.strategy || \"\";\n const meta = strategyDisplayMetaText(platform, account, profile);\n return meta ? `${t(\"invalidStrategyNote\")}\\n${meta}` : t(\"invalidStrategyNote\");\n }\n\n function strategyChoiceLabel(profile, platform = state.selected, account = selectedAccount(platform), executionMode = state.forms[platform]?.executionMode) {\n const label = strategyLabel(profile);\n const entry = strategyCatalogEntry(profile);\n const domain = entry.domain ? domainLabel(entry.domain) : \"\";\n if (!entry.profile) return label;\n if (normalizeExecutionMode(executionMode, false) === \"live\" && !strategyCanSwitchLive(entry)) {\n return domain ? `${label}(${domain})` : label;\n }\n if (entry.runtime_enabled === false) {\n return domain ? `${label}(${domain})` : label;\n }\n return label;\n }\n\n function strategyAllowedForAccount(platform, account, profile, executionMode = state.forms[platform]?.executionMode) {\n const cleanProfile = cleanStrategyProfile(profile);\n const catalogEntry = strategyCatalogEntry(cleanProfile);\n if (!catalogEntry.profile) return false;\n if (dcaConfigForStrategy(cleanProfile) && !platformSupportsDca(platform)) return false;\n if (!supportedDomainsForAccount(platform, account).includes(catalogEntry.domain)) return false;\n const mode = normalizeExecutionMode(executionMode, false);\n if (!supportedExecutionModesForPlatform(platform).includes(mode)) return false;\n if (mode === \"live\") return strategyCanSwitchLive(catalogEntry);\n const allowedModes = normalizeAllowedExecutionModes(catalogEntry.allowed_execution_modes);\n if (allowedModes.length && !allowedModes.includes(mode)) return false;\n return true;\n }\n\n function strategyCompatibleWithAccount(platform, account, profile) {\n const entry = strategyCatalogEntry(profile);\n return Boolean(entry.profile)\n && (!dcaConfigForStrategy(profile) || platformSupportsDca(platform))\n && supportedDomainsForAccount(platform, account).includes(entry.domain);\n }\n\n function strategyChoicesForAccount(platform = state.selected, account = selectedAccount(platform)) {\n // Browsing is not execution approval; submission retains its existing checks.\n return strategyOptions.filter(profile => strategyCompatibleWithAccount(platform, account, profile));\n }\n\n function hasLiveStrategyOption(platform = state.selected, account = selectedAccount(platform)) {\n return strategyOptions.some((profile) => strategyAllowedForAccount(platform, account, profile, \"live\"));\n }\n\n function strategyLabel(profile) {\n const labels = strategyLabels[profile] || localStrategyLabels[profile];\n if (!labels) return profile;\n return state.lang === \"zh\"\n ? (labels.zh || labels.en || profile)\n : (labels.en || labels.zh || profile);\n }\n\n function strategyLabelSet(profile, item) {\n const local = localStrategyLabels[profile] || {};\n const label = String(item?.label || item?.display_name || \"\").trim();\n const labelEn = String(item?.label_en || item?.display_name_en || \"\").trim();\n const labelZh = String(item?.label_zh || item?.display_name_zh || \"\").trim();\n return {\n zh: labelZh || local.zh || label || local.en || profile,\n en: labelEn || label || local.en || labelZh || local.zh || profile,\n };\n }\n\n function modeLabel(mode) {\n if (mode === \"dry_run\") return t(\"dryRun\");\n if (mode === \"paper\") return t(\"paper\");\n if (mode === \"live\") return t(\"live\");\n return t(\"modeUnknown\");\n }\n\n function normalizePluginMode(value) {\n return pluginModes.includes(value) ? value : \"none\";\n }\n\n function pluginModeLabel(mode) {\n void mode;\n return t(\"pluginModeNone\");\n }\n\n function dcaConfigForStrategy(profile) {\n const cleanProfile = cleanStrategyProfile(profile);\n const catalog = strategyCatalog[cleanProfile] || {};\n if (catalog.dca_enabled === true) {\n return {\n defaultMode: normalizeDcaMode(catalog.dca_default_mode || \"fixed\"),\n defaultBaseInvestmentUsd: cleanDisplayPositiveNumber(catalog.dca_default_base_investment_usd) || \"1000\",\n };\n }\n return dcaProfileDefaults[cleanProfile] || null;\n }\n\n function dcaSupported(profile) {\n return Boolean(dcaConfigForStrategy(profile));\n }\n\n function normalizeDcaMode(value) {\n const mode = String(value || \"\").trim().toLowerCase();\n if (mode === \"smart_dca\") return \"smart\";\n if (mode === \"fixed_dca\" || mode === \"ordinary\" || mode === \"ordinary_dca\") return \"fixed\";\n return dcaModes.includes(mode) ? mode : \"fixed\";\n }\n\n function dcaModeLabel(mode) {\n return normalizeDcaMode(mode) === \"smart\" ? t(\"dcaModeSmart\") : t(\"dcaModeFixed\");\n }\n\n function normalizeRuntimeTargetMode(value) {\n return runtimeTargetModes.includes(value) ? value : \"current\";\n }\n\n function runtimeTargetModeLabel(mode) {\n if (mode === \"enabled\") return t(\"runtimeTargetEnabled\");\n if (mode === \"disabled\") return t(\"runtimeTargetDisabled\");\n return \"\";\n }\n\n function runtimeTargetEnabledForAccount(platform, account) {\n return cleanOptionalBoolean(currentEntryForAccount(platform, account)?.runtime_target_enabled);\n }\n\n function runtimeTargetStateForAccount(platform = state.selected, account = selectedAccount(platform)) {\n const entry = currentEntryForAccount(platform, account);\n if (!entry) return { known: false, enabled: null };\n const configured = cleanOptionalBoolean(entry.runtime_target_enabled);\n return { known: configured !== null, enabled: configured };\n }\n\n function runtimeTargetText(enabled) {\n return enabled ? t(\"runtimeTargetOn\") : t(\"runtimeTargetOff\");\n }\n\n function runtimeTargetTone(enabled) {\n return enabled ? \"enabled\" : \"disabled\";\n }\n\n function currentRuntimeTargetText(platform = state.selected, account = selectedAccount(platform)) {\n const target = runtimeTargetStateForAccount(platform, account);\n if (!target.known) return t(\"notRead\");\n return runtimeTargetText(target.enabled);\n }\n\n function currentRuntimeTargetTone(platform = state.selected, account = selectedAccount(platform)) {\n const target = runtimeTargetStateForAccount(platform, account);\n if (!target.known) return \"neutral\";\n return runtimeTargetTone(target.enabled);\n }\n\n function incomeLayerDefaultForStrategy(profile) {\n return incomeLayerDefaults[cleanStrategyProfile(profile)] || null;\n }\n\n function incomeLayerSupported(profile) {\n return Boolean(incomeLayerDefaultForStrategy(profile));\n }\n\n function normalizeIncomeLayerMode(value) {\n return incomeLayerModes.includes(value) ? value : \"current\";\n }\n\n function incomeLayerModeLabel(mode) {\n if (mode === \"enabled\") return t(\"incomeLayerEnabled\");\n if (mode === \"disabled\") return t(\"incomeLayerDisabled\");\n return \"\";\n }\n\n function optionOverlayDefaultForStrategy(profile) {\n return optionOverlayDefaults[cleanStrategyProfile(profile)] || null;\n }\n\n function optionOverlaySupported(profile) {\n return Boolean(optionOverlayDefaultForStrategy(profile));\n }\n\n function normalizeOptionOverlayMode(value) {\n return optionOverlayModes.includes(value) ? value : \"current\";\n }\n\n function optionOverlayModeLabel(mode) {\n if (mode === \"enabled\") return t(\"optionOverlayEnabled\");\n if (mode === \"disabled\") return t(\"optionOverlayDisabled\");\n return \"\";\n }\n\n function optionOverlayText(enabled) {\n return enabled ? t(\"optionOverlayOn\") : t(\"optionOverlayOff\");\n }\n\n function normalizeCashOnlyExecutionMode(value) {\n return cashOnlyExecutionModes.includes(value) ? value : \"current\";\n }\n\n function cashOnlyExecutionModeLabel(mode) {\n if (mode === \"enabled\") return t(\"cashOnlyExecutionNo\");\n if (mode === \"disabled\") return t(\"cashOnlyExecutionYes\");\n return \"\";\n }\n\n function cashOnlyExecutionText(enabled) {\n if (enabled === null) return t(\"notRead\");\n return enabled ? t(\"cashOnlyExecutionValueNo\") : t(\"cashOnlyExecutionValueYes\");\n }\n\n function platformCashOnlyExecutionDefault() {\n return true;\n }\n\n function effectiveCashOnlyExecutionForAccount(platform, account) {\n return currentCashOnlyExecutionForAccount(platform, account);\n }\n\n function currentCashOnlyExecutionForAccount(platform, account) {\n const entry = accountReadbackEntry(platform, account);\n if (entry) {\n const val = cleanOptionalBoolean(entry.cash_only_execution);\n if (val !== null) return val;\n }\n return null;\n }\n\n function currentCashOnlyExecutionText(platform = state.selected, account = selectedAccount(platform)) {\n if (!platformSupportsMarginPolicy(platform)) return t(\"notRead\");\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return t(\"notRead\");\n const configured = cleanOptionalBoolean(entry.cash_only_execution);\n if (configured === null) return t(\"notConfigured\");\n return cashOnlyExecutionText(configured);\n }\n\n function currentOptionOverlayForAccount(platform, account) {\n return cleanOptionalBoolean(accountReadbackEntry(platform, account)?.option_overlay_enabled);\n }\n\n function effectiveOptionOverlayForAccount(platform, account, profile = state.forms[platform]?.strategy) {\n const configured = currentOptionOverlayForAccount(platform, account);\n return configured === null ? null : configured;\n }\n\n function optionOverlayDefaultSummaryDetail(defaults) {\n if (!defaults?.families?.length) return \"\";\n return defaults.families.map((item) => {\n const family = item.family === \"income\" ? t(\"optionOverlayFamilyIncome\") : t(\"optionOverlayFamilyGrowth\");\n const ratioText = item.ratioKind === \"risk\"\n ? t(\"optionOverlayRiskRatio\").replace(\"{ratio}\", formatRatioPercent(item.ratio))\n : t(\"optionOverlayBudgetRatio\").replace(\"{ratio}\", formatRatioPercent(item.ratio));\n return `${family} ${ratioText}`;\n }).join(\" / \");\n }\n\n function optionOverlayDefaultText(profile) {\n const defaults = optionOverlayDefaultForStrategy(profile);\n if (!defaults) return t(\"optionOverlayNotSupported\");\n const detail = optionOverlayDefaultSummaryDetail(defaults);\n return detail ? t(\"optionOverlayDefault\").replace(\"{detail}\", detail) : t(\"optionOverlayDefaultSimple\");\n }\n\n function currentOptionOverlayText(platform = state.selected, account = selectedAccount(platform), profile = state.forms[platform]?.strategy) {\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return t(\"notRead\");\n const configured = cleanOptionalBoolean(entry.option_overlay_enabled);\n if (!optionOverlaySupported(profile)) {\n return configured === null ? t(\"optionOverlayNotSupported\") : optionOverlayText(configured);\n }\n if (configured === null) return t(\"strategyDefault\");\n return optionOverlayText(configured);\n }\n\n function currentIncomeLayerForAccount(platform, account) {\n return incomeLayerFromEntry(currentEntryForAccount(platform, account));\n }\n\n function incomeLayerFromEntry(entry) {\n return {\n enabled: cleanOptionalBoolean(entry?.income_layer_enabled),\n startUsd: cleanDisplayNumber(entry?.income_layer_start_usd),\n maxRatio: cleanDisplayRatio(entry?.income_layer_max_ratio),\n };\n }\n\n function incomeLayerFieldsConfigured(entry) {\n const current = incomeLayerFromEntry(entry);\n return current.enabled !== null || Boolean(current.startUsd || current.maxRatio);\n }\n\n function effectiveIncomeLayerForAccount(platform, account, profile = state.forms[platform]?.strategy) {\n const defaults = incomeLayerDefaultForStrategy(profile);\n if (!defaults) return null;\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return null;\n const current = incomeLayerFromEntry(entry);\n if (!incomeLayerFieldsConfigured(entry)) {\n return {\n enabled: true,\n startUsd: String(defaults.startUsd),\n maxRatio: defaults.maxRatio,\n };\n }\n return {\n enabled: current.enabled ?? true,\n startUsd: current.startUsd || String(defaults.startUsd),\n maxRatio: current.maxRatio || defaults.maxRatio,\n };\n }\n\n function currentDcaForAccount(platform, account, profile = state.forms[platform]?.strategy) {\n const defaults = dcaConfigForStrategy(profile);\n if (!defaults) return { supported: false, mode: \"\", baseInvestmentUsd: \"\" };\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return { supported: true, mode: \"\", baseInvestmentUsd: \"\" };\n return {\n supported: true,\n mode: normalizeDcaMode(entry.dca_mode),\n baseInvestmentUsd: cleanDisplayPositiveNumber(entry.dca_base_investment_usd),\n };\n }\n\n function normalizeAccountLookupKey(value) {\n return String(value || \"\").trim().toLowerCase();\n }\n\n function collectAccountLookupCandidates(keys) {\n const candidates = new Set();\n for (const rawKey of keys) {\n const key = normalizeAccountLookupKey(rawKey);\n if (!key) continue;\n\n candidates.add(key);\n\n const compact = key.replace(/[^a-z0-9]+/g, \"\");\n if (compact) candidates.add(compact);\n\n const parts = key.split(/[^a-z0-9]+/).filter(Boolean);\n if (parts.length > 1) candidates.add(parts[parts.length - 1]);\n }\n return [...candidates];\n }\n\n function resolveCurrentEntryByKey(byPlatform, keys) {\n const candidates = new Set(collectAccountLookupCandidates(keys));\n if (!candidates.size) return null;\n\n for (const key of keys) {\n const entry = byPlatform[key];\n if (currentEntryHasState(entry)) return entry;\n }\n\n for (const [rawKey, entry] of Object.entries(byPlatform)) {\n if (!currentEntryHasState(entry)) continue;\n const rawCandidates = collectAccountLookupCandidates([rawKey]);\n const hasMatch = rawCandidates.some((candidate) => candidates.has(candidate));\n if (hasMatch) return entry;\n }\n\n return null;\n }\n\n function currentEntryForAccount(platform, account) {\n const byPlatform = state.currentStrategies[platform] || {};\n const keys = [account?.key, account?.target_name, account?.label]\n .filter(Boolean)\n .map((value) => String(value));\n const entry = resolveCurrentEntryByKey(byPlatform, keys);\n if (entry) return entry;\n // Account options describe routing. They are not a readback of the\n // runtime configuration, so leave all runtime values unknown until the\n // authoritative current-strategies snapshot supplies them.\n return {\n strategy_profile: \"\",\n source: \"account_defaults\",\n runtime_target_enabled: null,\n };\n }\n\n function currentEntryHasState(entry) {\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) return false;\n return Boolean(\n cleanStrategyProfile(entry.strategy_profile) ||\n cleanDisplayNumber(entry.min_reserved_cash_usd ?? entry.reserved_cash_floor_usd) ||\n cleanDisplayRatio(entry.reserved_cash_ratio) ||\n cleanOptionalBoolean(entry.income_layer_enabled) !== null ||\n cleanDisplayNumber(entry.income_layer_start_usd) ||\n cleanDisplayRatio(entry.income_layer_max_ratio) ||\n cleanOptionalBoolean(entry.option_overlay_enabled) !== null ||\n cleanOptionalBoolean(entry.cash_only_execution) !== null ||\n cleanOptionalBoolean(entry.runtime_target_enabled) !== null ||\n normalizeDcaMode(entry.dca_mode || \"\") !== \"fixed\" ||\n cleanDisplayPositiveNumber(entry.dca_base_investment_usd) ||\n normalizeExecutionEnvironment(entry.execution_environment) ||\n normalizeExecutionMode(entry.execution_mode, entry.dry_run_only),\n );\n }\n\n function accountReadbackEntry(platform, account) {\n const entry = currentEntryForAccount(platform, account);\n return entry?.source === \"account_defaults\" ? null : entry;\n }\n\n function currentStrategyForAccount(platform, account) {\n const entry = accountReadbackEntry(platform, account);\n return cleanStrategyProfile(entry?.strategy_profile) || \"\";\n }\n\n function currentReservePolicyForAccount(platform, account) {\n const entry = currentEntryForAccount(platform, account);\n return reservePolicyFromEntry(entry);\n }\n\n function currentPluginModeForAccount(platform, account) {\n void platform;\n return normalizePluginMode(account?.plugin_mode);\n }\n\n function reservePolicyFromEntry(entry) {\n return {\n minReservedCashUsd: cleanDisplayNumber(entry?.min_reserved_cash_usd ?? entry?.reserved_cash_floor_usd),\n reservedCashRatio: cleanDisplayRatio(entry?.reserved_cash_ratio),\n };\n }\n\n function cleanDisplayNumber(value) {\n const text = String(value ?? \"\").trim();\n if (!text || text.length > 32 || !/^(?:\\d+|\\d*\\.\\d+)$/.test(text)) return \"\";\n const numeric = Number(text);\n if (!Number.isFinite(numeric) || numeric < 0) return \"\";\n return text;\n }\n\n function cleanDisplayRatio(value) {\n const text = cleanDisplayNumber(value);\n if (!text) return \"\";\n const numeric = Number(text);\n return numeric >= 0 && numeric <= 1 ? text : \"\";\n }\n\n function cleanDisplayPositiveNumber(value) {\n const text = cleanDisplayNumber(value);\n return text && Number(text) > 0 ? text : \"\";\n }\n\n\n const PROMOTION_RISK_PROFILES = [\n \"CAPITAL_PRESERVATION\",\n \"BALANCED_COMPOUNDING\",\n \"GROWTH_COMPOUNDING\",\n ];\n const DEFAULT_PROMOTION_RISK_PROFILE = \"CAPITAL_PRESERVATION\";\n\n function promotionRiskProfileLabel(profile) {\n if (profile === \"CAPITAL_PRESERVATION\") return t(\"riskCapitalPreservation\");\n if (profile === \"BALANCED_COMPOUNDING\") return t(\"riskBalancedCompounding\");\n if (profile === \"GROWTH_COMPOUNDING\") return t(\"riskGrowthCompounding\");\n return profile;\n }\n\n function buildPromotionConfirmation({\n targetPlatform,\n executionMode,\n riskProfile,\n paperSupported,\n suggestedRiskProfile,\n }) {\n const platform = String(targetPlatform || \"\").trim();\n const mode = String(executionMode || \"\").trim().toLowerCase();\n const profile = String(riskProfile || DEFAULT_PROMOTION_RISK_PROFILE).trim().toUpperCase();\n const suggested = String(\n suggestedRiskProfile || DEFAULT_PROMOTION_RISK_PROFILE,\n ).trim().toUpperCase();\n if (!platform) throw new Error(\"target_platform required\");\n if (mode !== \"live\" && mode !== \"paper\") throw new Error(\"execution_mode must be live or paper\");\n if (!PROMOTION_RISK_PROFILES.includes(profile)) throw new Error(\"invalid risk_profile\");\n if (!PROMOTION_RISK_PROFILES.includes(suggested)) throw new Error(\"invalid suggested_risk_profile\");\n if (mode === \"paper\" && !paperSupported) {\n throw new Error(\"paper unavailable; synthetic matching is not supported\");\n }\n // Exact QPK PromotionConfirmation.to_dict() fields only.\n return {\n target_platform: platform,\n execution_mode: mode,\n risk_profile: profile,\n };\n }\n\n\n function buildDesignPreviewRiskEnvelopeView(riskPreference) {\n const profile = String(riskPreference || \"\").trim().toUpperCase();\n const labels = {\n CAPITAL_PRESERVATION: { zh: \"保全\", en: \"Preserve\" },\n BALANCED_COMPOUNDING: { zh: \"均衡\", en: \"Balance\" },\n GROWTH_COMPOUNDING: { zh: \"增长\", en: \"Growth\" },\n };\n const scales = {\n CAPITAL_PRESERVATION: { composer_mdd_multiple: 1.0, promotion_size_scale: 0.5 },\n BALANCED_COMPOUNDING: { composer_mdd_multiple: 1.25, promotion_size_scale: 0.75 },\n GROWTH_COMPOUNDING: { composer_mdd_multiple: 1.5, promotion_size_scale: 1.0 },\n };\n const known = Object.prototype.hasOwnProperty.call(labels, profile);\n return {\n schema: \"qsl.risk_envelope_view.v1\",\n source: \"design_preview\",\n preference: known\n ? { id: profile, label_zh: labels[profile].zh, label_en: labels[profile].en }\n : { id: \"unknown\", label_zh: \"未设定\", label_en: \"Unset\" },\n capital_band: {\n id: \"unknown\",\n label_zh: \"待对账权益注入\",\n label_en: \"Awaiting reconciled equity\",\n },\n status: {\n id: \"unknown\",\n label_zh: \"待对账权益注入\",\n label_en: \"Awaiting reconciled equity\",\n },\n scales: {\n composer_mdd_multiple: known ? scales[profile].composer_mdd_multiple : null,\n promotion_size_scale: known ? scales[profile].promotion_size_scale : null,\n capital_scale: null,\n vol_scale: null,\n dd_scale: null,\n },\n detail: {\n dual_scale_note_zh:\n \"双口径:Composer 相对无杠杆基准 MDD 天花板为 1.00 / 1.25 / 1.50;晋级仓位缩放为 0.50 / 0.75 / 1.00(仅新晋级/材料变更)。资金信封 combined_scale = capital_scale × vol_scale × dd_scale(各因子 ≤1),由系统按权益/波动/回撤计算,禁止自动升档。\",\n dual_scale_note_en:\n \"Dual scale: Composer unlevered-benchmark MDD caps are 1.00 / 1.25 / 1.50; promotion size scales are 0.50 / 0.75 / 1.00 (new promotion / material change only). Envelope combined_scale = capital_scale × vol_scale × dd_scale (each ≤1), system-computed from equity/vol/drawdown; auto step-up is forbidden.\",\n },\n live_authority_granted: false,\n };\n }\n\n function renderRiskEnvelopePanel() {\n const preferenceEl = el(\"risk-envelope-preference\");\n const bandEl = el(\"risk-envelope-capital-band\");\n const statusEl = el(\"risk-envelope-status\");\n const detailsEl = el(\"risk-envelope-details\");\n const panel = el(\"risk-envelope-panel\");\n if (!preferenceEl || !bandEl || !statusEl || !detailsEl) return;\n const ticket = selectedPromotionTicket();\n const riskSelect = el(\"promotion-risk-profile-select\");\n const selectedProfile = String(riskSelect?.value || ticket?.suggested_risk_profile || DEFAULT_PROMOTION_RISK_PROFILE).trim().toUpperCase();\n const view = ticket?.risk_envelope_view && typeof ticket.risk_envelope_view === \"object\"\n ? {\n ...ticket.risk_envelope_view,\n preference: {\n ...(ticket.risk_envelope_view.preference || {}),\n ...(buildDesignPreviewRiskEnvelopeView(selectedProfile).preference || {}),\n },\n scales: {\n ...(ticket.risk_envelope_view.scales || {}),\n ...(buildDesignPreviewRiskEnvelopeView(selectedProfile).scales || {}),\n },\n }\n : buildDesignPreviewRiskEnvelopeView(selectedProfile);\n const zh = state.lang !== \"en\";\n preferenceEl.textContent = zh\n ? (view.preference?.label_zh || t(\"riskEnvelopeUnset\"))\n : (view.preference?.label_en || t(\"riskEnvelopeUnset\"));\n bandEl.textContent = zh\n ? (view.capital_band?.label_zh || t(\"riskEnvelopeAwaitingEquity\"))\n : (view.capital_band?.label_en || t(\"riskEnvelopeAwaitingEquity\"));\n const statusId = String(view.status?.id || \"unknown\");\n statusEl.textContent = zh\n ? (view.status?.label_zh || t(\"riskEnvelopeAwaitingEquity\"))\n : (view.status?.label_en || t(\"riskEnvelopeAwaitingEquity\"));\n statusEl.dataset.status = statusId;\n if (panel) panel.dataset.status = statusId;\n const scales = view.scales || {};\n const note = zh ? (view.detail?.dual_scale_note_zh || \"\") : (view.detail?.dual_scale_note_en || \"\");\n const scaleLines = [\n `Composer MDD ×${scales.composer_mdd_multiple ?? \"—\"}`,\n `promo size ×${scales.promotion_size_scale ?? \"—\"}`,\n `capital_scale=${scales.capital_scale ?? \"null\"}`,\n `vol_scale=${scales.vol_scale ?? \"null\"}`,\n `dd_scale=${scales.dd_scale ?? \"null\"}`,\n `source=${view.source || \"design_preview\"}`,\n `live_authority_granted=${view.live_authority_granted === true}`,\n ];\n detailsEl.textContent = `${note}\\n${scaleLines.join(\" · \")}`;\n }\n\n function selectedPromotionTicket() {\n const tickets = state.researchPromotion?.payload?.tickets || [];\n const selectedId = state.researchPromotion?.selectedTicketId || \"\";\n return tickets.find((ticket) => ticket.ticket_id === selectedId) || null;\n }\n\n function promotionTicketNeedsSourceCheck(ticket) {\n return !String(ticket?.shadow_evidence_kind || \"\").trim();\n }\n\n function reviewablePromotionTickets(payload) {\n if (payload?.data_status !== \"ready\" || payload?.errors?.length) return [];\n return (payload.tickets || []).filter((ticket) =>\n ticket.state === \"awaiting_human\" && !promotionTicketNeedsSourceCheck(ticket));\n }\n\n function promotionTicketDisplayName(ticket, index = 0) {\n const profile = String(ticket?.strategy_profile || \"\");\n if (profile === \"synthetic-profile\") return t(\"promotionUnnamedRecord\").replace(\"{number}\", String(index + 1));\n if (profile === \"smoke\") return t(\"promotionFlowRecord\");\n const label = profile === \"soxl_soxx_trend_income\" ? `SOXL · ${strategyLabel(profile)}` : strategyLabel(profile || \"?\");\n return `${label} · ${t(promotionTicketNeedsSourceCheck(ticket) ? \"promotionOldRecord\" : \"promotionParameterProposal\")}`;\n }\n\n function renderUnverifiedPromotionRecords(tickets) {\n const section = el(\"promotion-unverified-records\");\n const list = el(\"promotion-unverified-list\");\n if (!section || !list) return;\n section.hidden = !tickets.length;\n el(\"promotion-unverified-summary\").textContent = t(\"promotionUnverifiedCount\").replace(\"{count}\", String(tickets.length));\n list.replaceChildren();\n tickets.forEach((ticket, index) => {\n const card = document.createElement(\"article\");\n card.className = \"promotion-old-record\";\n const title = document.createElement(\"h4\");\n title.textContent = promotionTicketDisplayName(ticket, index);\n const hint = document.createElement(\"p\");\n hint.textContent = t(\"promotionUnverifiedHint\");\n const details = document.createElement(\"details\");\n const summary = document.createElement(\"summary\");\n summary.textContent = t(\"promotionOriginalRecord\");\n const evidence = document.createElement(\"p\");\n evidence.textContent = `${ticket.strategy_profile || \"?\"} · ${promotionTicketDetailMessage(ticket)}`;\n details.append(summary, evidence);\n card.append(title, hint, details);\n list.appendChild(card);\n });\n }\n\n function promotionTicketQueueMessage() {\n if (!state.auth?.allowed) return t(\"promotionTicketLoginRequired\");\n const payload = state.researchPromotion?.payload || {};\n if (payload.data_status === \"login_required\") return t(\"promotionTicketLoginRequired\");\n if (\n payload.data_status !== \"ready\"\n || (Array.isArray(payload.errors) && payload.errors.length > 0)\n ) {\n return t(\"promotionTicketLoadFailed\");\n }\n return t(\"promotionTicketEmpty\");\n }\n\n function promotionTicketEvidenceMessage(ticket) {\n const outcome = ticket?.shadow_passed === true\n ? \"promotionObservationReported\"\n : ticket?.shadow_passed === false ? \"promotionObservationFailed\" : \"promotionObservationMissing\";\n const provenance = String(ticket?.shadow_evidence_kind || \"\").trim()\n ? \"promotionEvidenceNeedsReview\" : \"promotionEvidenceSourceMissing\";\n return `${t(outcome)} ${t(provenance)}`;\n }\n\n function promotionSummaryCanonical(value) {\n if (value === null) return \"null\";\n if (typeof value === \"string\" || typeof value === \"boolean\") return JSON.stringify(value);\n if (typeof value === \"number\") return Number.isFinite(value) ? JSON.stringify(value) : \"\";\n if (Array.isArray(value)) return `[${value.map(promotionSummaryCanonical).join(\",\")}]`;\n if (!value || typeof value !== \"object\") return \"\";\n return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${promotionSummaryCanonical(value[key])}`).join(\",\")}}`;\n }\n\n function promotionResearchSummaryForDisplay(ticket) {\n const summary = ticket?.research_summary;\n if (!summary || typeof summary !== \"object\" || Array.isArray(summary)) return null;\n const identity = summary.identity;\n if (!identity || identity.strategy_profile !== ticket.strategy_profile || identity.domain !== ticket.domain\n || promotionSummaryCanonical(identity.proposed_params) !== promotionSummaryCanonical(ticket.proposed_params || {})) {\n return null;\n }\n return summary;\n }\n\n function formatPromotionPercent(value) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return \"\";\n return `${(value * 100).toFixed(2)}%`;\n }\n\n function promotionResearchSummaryMessage(ticket) {\n const summary = promotionResearchSummaryForDisplay(ticket);\n const strategy = strategyLabel(ticket?.strategy_profile || \"\") || t(\"commonUnknown\");\n const observation = promotionTicketEvidenceMessage(ticket);\n if (!summary) {\n return t(\"promotionResearchSummaryMissing\")\n .replace(\"{strategy}\", strategy)\n .replace(\"{observation}\", observation);\n }\n const lines = [t(\"promotionResearchSummary\")];\n const missing = [];\n const description = String(summary.strategy_description || \"\").trim();\n if (description) lines.push(t(\"promotionStrategyDescription\").replace(\"{description}\", description));\n else missing.push(state.lang === \"zh\" ? \"策略说明\" : \"strategy explanation\");\n if (summary.plugins === null) {\n lines.push(t(\"promotionPluginsUnknown\"));\n } else if (Array.isArray(summary.plugins) && summary.plugins.length === 0) {\n lines.push(t(\"promotionPluginsNone\"));\n } else if (Array.isArray(summary.plugins)) {\n const descriptions = summary.plugins.map((plugin) => String(plugin?.description || \"\").trim()).filter(Boolean);\n lines.push(descriptions.length\n ? t(\"promotionPlugins\").replace(\"{description}\", descriptions.join(\"、\"))\n : t(\"promotionPluginsUnknown\"));\n }\n const comparison = summary.comparison;\n const candidate = comparison?.candidate;\n const baseline = comparison?.baseline;\n const candidateCagr = formatPromotionPercent(candidate?.cagr);\n const candidateDrawdown = formatPromotionPercent(candidate?.max_drawdown);\n const baselineCagr = formatPromotionPercent(baseline?.cagr);\n const baselineDrawdown = formatPromotionPercent(baseline?.max_drawdown);\n const startDate = String(comparison?.start_date || \"\").trim();\n const endDate = String(comparison?.end_date || \"\").trim();\n if (comparison?.status === \"comparable\" && startDate && endDate\n && candidateCagr && candidateDrawdown && baselineCagr && baselineDrawdown) {\n lines.push(t(\"promotionComparison\")\n .replace(\"{startDate}\", startDate)\n .replace(\"{endDate}\", endDate)\n .replace(\"{candidateCagr}\", candidateCagr)\n .replace(\"{candidateDrawdown}\", candidateDrawdown)\n .replace(\"{baselineCagr}\", baselineCagr)\n .replace(\"{baselineDrawdown}\", baselineDrawdown));\n } else {\n missing.push(state.lang === \"zh\" ? \"收益对比\" : \"return comparison\");\n }\n const limitations = Array.isArray(summary.limitations)\n ? summary.limitations.map((item) => String(item || \"\").trim()).filter(Boolean)\n : [];\n if (limitations.length) lines.push(t(\"promotionLimitations\").replace(\"{limitations}\", limitations.join(\";\")));\n else missing.push(state.lang === \"zh\" ? \"不足\" : \"limitations\");\n const ai = summary.ai_explanation;\n if (ai?.status === \"available\" && ai.provider === \"codex\" && String(ai.text || \"\").trim()) {\n lines.push(t(\"promotionAiExplanation\").replace(\"{text}\", String(ai.text).trim()));\n }\n if (missing.length) lines.push(t(\"promotionResearchSummaryMissingParts\").replace(\"{items}\", missing.join(state.lang === \"zh\" ? \"、\" : \", \")));\n return lines.join(\" · \");\n }\n\n function promotionClickEffectMessage(account) {\n const mode = account?.broker_environment === \"paper\"\n ? t(\"promotionModePaper\")\n : account?.broker_environment === \"live\" ? t(\"promotionModeLive\") : t(\"commonUnknown\");\n return t(\"promotionClickEffect\").replace(\"{mode}\", mode);\n }\n\n function promotionTicketDetailMessage(ticket) {\n if (!ticket) return \"\";\n const evidenceKind = String(ticket.shadow_evidence_kind || \"\").trim() || t(\"commonUnknown\");\n const params = JSON.stringify(ticket.proposed_params || {});\n const detail = [\n `${ticket.ticket_id} · ${formatDateTime(ticket.created_at)}`,\n t(\"promotionTicketEvidenceKind\").replace(\"{kind}\", evidenceKind),\n promotionTicketEvidenceMessage(ticket),\n t(\"promotionTicketParams\").replace(\"{params}\", params),\n ];\n const notification = String(ticket.notification_body || \"\").trim();\n if (notification) {\n detail.push(t(\"promotionTicketNotification\").replace(\"{body}\", notification));\n }\n return detail.join(\" · \");\n }\n\n function promotionApplications() {\n const payload = state.researchPromotion?.payload || {};\n if (payload.data_status !== \"ready\" || payload.errors?.length) return [];\n return Array.isArray(payload.applications) ? payload.applications : [];\n }\n\n function selectedPromotionApplication() {\n const applications = promotionApplications();\n const selectedId = state.researchPromotion.selectedApplicationTicketId || \"\";\n return applications.find((item) => item.ticket_id === selectedId) || applications[0] || null;\n }\n\n function selectedPromotionApplicationAccount(application = selectedPromotionApplication()) {\n const accounts = application?.application_preparation?.account_options || [];\n const selectedKey = state.researchPromotion.selectedApplicationAccountKey || \"\";\n const platform = state.researchPromotion.selectedApplicationPlatform || \"\";\n const environment = state.researchPromotion.selectedApplicationEnvironment || \"\";\n return accounts.find((item) => `${item.platform}/${item.key}` === selectedKey)\n || accounts.find((item) => (!platform || item.platform === platform) && (!environment || item.broker_environment === environment))\n || accounts[0]\n || null;\n }\n\n function promotionApplicationBlockerLabel(code) {\n if (code === \"activation_not_connected\") return t(\"promotionApplicationBlockActivation\");\n if (code === \"candidate_params_unbound\") return t(\"promotionApplicationBlockParams\");\n if (code === \"strategy_not_configured\") return t(\"promotionApplicationBlockStrategy\");\n if (code === \"configured_account_missing\") return t(\"promotionApplicationBlockAccount\");\n if (code === \"research_evidence_unverified\") return t(\"promotionApplicationBlockEvidence\");\n if (code === \"broker_environment_unknown\" || code === \"broker_environment_unsupported\") return t(\"promotionApplicationBlockBrokerEnvironment\");\n return t(\"promotionApplicationBlockPreflight\");\n }\n\n function promotionApplicationReasonLabel(code) {\n const labels = {\n readback_mismatch: state.lang === \"zh\" ? \"版本核对不一致\" : \"version readback did not match\",\n workflow_rejected: state.lang === \"zh\" ? \"部署未通过\" : \"deployment was rejected\",\n workflow_uncertain: state.lang === \"zh\" ? \"部署结果待确认\" : \"deployment result is unconfirmed\",\n account_changed: state.lang === \"zh\" ? \"账户配置已变化\" : \"account configuration changed\",\n qualification_changed: state.lang === \"zh\" ? \"候选资格已变化\" : \"candidate qualification changed\",\n };\n return labels[String(code || \"\")] || (state.lang === \"zh\" ? \"状态待确认\" : \"status is unconfirmed\");\n }\n\n function renderPromotionSelectionControls(application = selectedPromotionApplication()) {\n const platformSelect = el(\"promotion-target-platform-select\");\n const environmentSelect = el(\"promotion-broker-environment-select\");\n const accountSelect = el(\"promotion-selected-account-select\");\n if (!platformSelect || !environmentSelect || !accountSelect) return null;\n const accounts = application?.application_preparation?.account_options || [];\n const platforms = [...new Set(accounts.map((item) => item.platform))];\n const previousPlatform = state.researchPromotion.selectedApplicationPlatform;\n const platform = platforms.includes(previousPlatform) ? previousPlatform : (platforms[0] || \"\");\n state.researchPromotion.selectedApplicationPlatform = platform;\n platformSelect.replaceChildren();\n for (const value of platforms) {\n platformSelect.append(new Option(platformMeta[value]?.label || value, value, false, value === platform));\n }\n if (!platforms.length) platformSelect.append(new Option(t(\"promotionApplicationBlockAccount\"), \"\", true, true));\n const platformAccounts = accounts.filter((item) => item.platform === platform);\n const environments = [...new Set(platformAccounts.map((item) => item.broker_environment).filter(Boolean))];\n const previousEnvironment = state.researchPromotion.selectedApplicationEnvironment;\n const environment = environments.includes(previousEnvironment) ? previousEnvironment : (environments[0] || \"\");\n state.researchPromotion.selectedApplicationEnvironment = environment;\n environmentSelect.replaceChildren();\n for (const value of environments) {\n environmentSelect.append(new Option(value === \"paper\" ? t(\"promotionModePaper\") : t(\"promotionModeLive\"), value, false, value === environment));\n }\n if (!environments.length) environmentSelect.append(new Option(t(\"commonUnknown\"), \"\", true, true));\n const filteredAccounts = platformAccounts.filter((item) => item.broker_environment === environment);\n const previousKey = state.researchPromotion.selectedApplicationAccountKey;\n const selectedKey = filteredAccounts.some((item) => `${item.platform}/${item.key}` === previousKey)\n ? previousKey : (filteredAccounts[0] ? `${filteredAccounts[0].platform}/${filteredAccounts[0].key}` : \"\");\n state.researchPromotion.selectedApplicationAccountKey = selectedKey;\n accountSelect.replaceChildren();\n for (const account of filteredAccounts) {\n accountSelect.append(new Option(`${account.label} · ${account.key}`, `${account.platform}/${account.key}`, false, `${account.platform}/${account.key}` === selectedKey));\n }\n if (!filteredAccounts.length) accountSelect.append(new Option(t(\"promotionApplicationBlockAccount\"), \"\", true, true));\n const selected = filteredAccounts.find((item) => `${item.platform}/${item.key}` === selectedKey) || null;\n const modeReadonly = el(\"promotion-execution-mode-readonly\");\n if (modeReadonly) {\n const modeLabel = selected?.broker_environment === \"paper\" ? t(\"promotionModePaper\") : selected?.broker_environment === \"live\" ? t(\"promotionModeLive\") : t(\"commonUnknown\");\n modeReadonly.textContent = selected ? t(\"promotionExecutionModeReadonly\").replace(\"{mode}\", modeLabel) : \"\";\n }\n return selected;\n }\n\n function renderPromotionApplicationPreparation() {\n const applications = promotionApplications();\n const block = el(\"promotion-application-block\");\n const status = el(\"promotion-application-status\");\n const progress = el(\"promotion-application-progress\");\n const deployButton = el(\"promotion-application-deploy\");\n const openButton = el(\"promotion-application-open\");\n if (!block || !status || !openButton || !deployButton) return;\n block.hidden = !applications.length;\n if (!applications.length) {\n status.textContent = t(\"promotionApplicationEmpty\");\n if (progress) progress.textContent = \"\";\n deployButton.hidden = true;\n deployButton.disabled = true;\n openButton.disabled = true;\n return;\n }\n const application = selectedPromotionApplication();\n const account = selectedPromotionApplicationAccount(application);\n const blockers = [\n ...(application?.application_preparation?.blocker_codes || []),\n ...(account?.blocker_codes || []),\n ];\n const uniqueBlockers = [...new Set(blockers)];\n const preflightReady = application?.application_preparation?.preflight_status === \"ready\"\n && account?.preflight_status === \"ready\";\n status.textContent = preflightReady\n ? t(\"promotionApplicationReady\")\n : t(\"promotionApplicationBlocked\").replace(\n \"{reasons}\",\n uniqueBlockers.map(promotionApplicationBlockerLabel).join(\"、\"),\n );\n openButton.disabled = !preflightReady;\n const storedApplication = application?.application || null;\n const previewReady = Boolean(application?.application_preparation?.preview_request)\n && preflightReady && account?.platform === \"longbridge\" && account?.broker_environment === \"paper\";\n const canRetryRejected = storedApplication?.status === \"rejected\";\n deployButton.hidden = !previewReady || Boolean(storedApplication && !canRetryRejected);\n deployButton.disabled = !previewReady || Boolean(storedApplication && !canRetryRejected);\n if (progress) {\n if (!storedApplication) progress.textContent = previewReady ? \"\" : \"\";\n else if (storedApplication.status === \"approved\" && storedApplication.dispatch_state === \"unknown\") progress.textContent = t(\"promotionApplicationDispatchUnknown\");\n else if (storedApplication.status === \"approved\") progress.textContent = t(\"promotionApplicationQueued\");\n else if (storedApplication.status === \"claimed\") progress.textContent = t(\"promotionApplicationClaimed\");\n else if (storedApplication.status === \"applied_paused\") progress.textContent = t(\"promotionApplicationApplied\");\n else if (storedApplication.status === \"rejected\") progress.textContent = t(\"promotionApplicationRejected\").replace(\"{reason}\", promotionApplicationReasonLabel(storedApplication.reason_code));\n else progress.textContent = t(\"promotionApplicationUncertain\");\n }\n }\n\n async function submitV7PaperApplication() {\n const application = selectedPromotionApplication();\n const account = selectedPromotionApplicationAccount(application);\n const ticketId = application?.ticket_id || \"\";\n if (!ticketId || !account || application?.application_preparation?.preflight_status !== \"ready\"\n || !application?.application_preparation?.preview_request || account.platform !== \"longbridge\"\n || account.broker_environment !== \"paper\") return;\n const button = el(\"promotion-application-deploy\");\n if (button) button.disabled = true;\n try {\n const instanceState = await requestJson(\"/api/admin/runtime-instances\");\n const response = await fetch(\"/api/research-promotion-applications\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ticket_id: ticketId,\n selected_account: { platform: account.platform, key: account.key },\n expected_revision: Number(instanceState.revision),\n }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"promotionApplicationUncertain\"));\n await refreshResearchPromotionTickets();\n } catch (error) {\n // A dispatch response can be unknown after the server has persisted it.\n // Refresh first so the rendered application state decides whether the\n // button remains disabled; never turn a possibly submitted request back\n // into an apparent retry.\n try { await refreshResearchPromotionTickets(); } catch { /* keep the button disabled until a later refresh */ }\n showToast(error.message || t(\"promotionApplicationUncertain\"), { duration: 9000 });\n if (button) button.disabled = true;\n }\n }\n\n function promotionConfirmationExecutionMode(platform = state.selected) {\n void platform;\n const brokerEnvironment = selectedPromotionApplicationAccount()?.broker_environment;\n return brokerEnvironment || \"\";\n }\n\n function renderPromotionConfirmControls() {\n const platform = state.selected;\n const platformVisible = platformMeta[platform]?.console_visible !== false;\n const payload = state.researchPromotion?.payload || {};\n const queueReady = payload.data_status === \"ready\" && !(payload.errors || []).length;\n const pendingTickets = state.auth?.allowed && queueReady\n ? (payload.tickets || []).filter((ticket) => ticket.state === \"awaiting_human\")\n : [];\n const tickets = state.auth?.allowed ? reviewablePromotionTickets(payload) : [];\n const applications = state.auth?.allowed ? promotionApplications() : [];\n renderUnverifiedPromotionRecords(pendingTickets.filter(promotionTicketNeedsSourceCheck));\n const panel = el(\"promotion-decision-panel\");\n if (panel) panel.hidden = !tickets.length || !platformVisible;\n const notice = el(\"promotion-queue-notice\");\n if (notice) {\n notice.hidden = !state.auth?.allowed || (tickets.length > 0 && platformVisible);\n notice.textContent = tickets.length && !platformVisible ? t(\"promotionTargetUnavailable\") : promotionTicketQueueMessage();\n }\n const confirmationBlock = el(\"promotion-confirm-block\");\n if (confirmationBlock) confirmationBlock.hidden = !tickets.length;\n const targetSummary = el(\"promotion-target-summary\");\n if (targetSummary) {\n targetSummary.textContent = t(\"promotionTargetSummary\")\n .replace(\"{platform}\", platformMeta[platform]?.label || t(\"commonUnknown\"))\n .replace(\"{account}\", selectedAccount(platform)?.label || t(\"commonUnknown\"));\n }\n const ticketSelect = el(\"promotion-ticket-select\");\n const modeReadonly = el(\"promotion-execution-mode-readonly\");\n const riskSelect = el(\"promotion-risk-profile-select\");\n const meta = el(\"promotion-confirm-meta\");\n const ticketMeta = el(\"promotion-ticket-meta\");\n const acceptButton = el(\"promotion-accept-button\");\n const rejectButton = el(\"promotion-reject-button\");\n if (!modeReadonly || !riskSelect) return;\n if (ticketSelect) {\n const previousTicket = state.researchPromotion.selectedTicketId || ticketSelect.value || \"\";\n ticketSelect.replaceChildren();\n if (!tickets.length) {\n ticketSelect.append(new Option(promotionTicketQueueMessage(), \"\", true, true));\n state.researchPromotion.selectedTicketId = \"\";\n } else {\n const selectedId = tickets.some((ticket) => ticket.ticket_id === previousTicket)\n ? previousTicket\n : tickets[0].ticket_id;\n state.researchPromotion.selectedTicketId = selectedId;\n for (const ticket of tickets) {\n const label = `${promotionTicketDisplayName(ticket)} · ${formatDateTime(ticket.created_at)}`;\n ticketSelect.append(new Option(label, ticket.ticket_id, false, ticket.ticket_id === selectedId));\n }\n }\n }\n const ticket = selectedPromotionTicket();\n const selectedPromotionAccount = typeof renderPromotionSelectionControls === \"function\"\n ? renderPromotionSelectionControls(selectedPromotionApplication())\n : null;\n const selectedPlatformVisible = selectedPromotionAccount\n ? platformMeta[selectedPromotionAccount.platform]?.console_visible !== false\n : platformVisible;\n if (targetSummary) {\n targetSummary.textContent = t(\"promotionTargetSummary\")\n .replace(\"{platform}\", platformMeta[selectedPromotionAccount?.platform || platform]?.label || t(\"commonUnknown\"))\n .replace(\"{account}\", selectedPromotionAccount?.label || selectedAccount(platform)?.label || t(\"commonUnknown\"));\n }\n const ticketDetail = el(\"promotion-ticket-detail\");\n if (ticketDetail) ticketDetail.textContent = promotionTicketDetailMessage(ticket);\n const researchSummary = el(\"promotion-research-summary\");\n if (researchSummary) researchSummary.textContent = promotionResearchSummaryMessage(ticket);\n const clickEffect = el(\"promotion-click-effect\");\n if (clickEffect) clickEffect.textContent = promotionClickEffectMessage(selectedPromotionAccount);\n const suggested = PROMOTION_RISK_PROFILES.includes(ticket?.suggested_risk_profile)\n ? ticket.suggested_risk_profile\n : DEFAULT_PROMOTION_RISK_PROFILE;\n const previousRisk = riskSelect.value || suggested;\n const promotionMode = promotionConfirmationExecutionMode(platform);\n riskSelect.replaceChildren();\n // Prefill from ticket suggestion unless the operator already chose another valid profile.\n const selectedRisk = PROMOTION_RISK_PROFILES.includes(previousRisk) && previousRisk\n ? (ticket && !riskSelect.dataset.touched ? suggested : previousRisk)\n : suggested;\n if (ticket && !riskSelect.dataset.touched) {\n // Prefer ticket suggestion on first bind / ticket change.\n }\n const riskToSelect = ticket && riskSelect.dataset.ticketId !== (ticket?.ticket_id || \"\")\n ? suggested\n : (PROMOTION_RISK_PROFILES.includes(previousRisk) ? previousRisk : suggested);\n for (const profile of PROMOTION_RISK_PROFILES) {\n riskSelect.append(new Option(promotionRiskProfileLabel(profile), profile, false, profile === riskToSelect));\n }\n riskSelect.dataset.ticketId = ticket?.ticket_id || \"\";\n if (meta) {\n meta.textContent = promotionMode ? t(\"promotionConfirmMeta\") : `${t(\"promotionConfirmMeta\")} ${t(\"promotionNoOrderCannotConfirm\")}`;\n }\n if (ticketMeta) {\n if (ticket) {\n const decisionMeta = state.auth?.admin\n ? t(\"promotionTicketSuggested\").replace(\"{profile}\", promotionRiskProfileLabel(suggested))\n : t(\"promotionAdminOnly\");\n ticketMeta.textContent = `${decisionMeta} ${promotionTicketEvidenceMessage(ticket)}`;\n } else {\n ticketMeta.textContent = promotionTicketQueueMessage();\n }\n }\n const canDecide = Boolean(\n ticket\n && state.auth?.admin\n && selectedPlatformVisible\n && promotionMode\n && selectedPromotionAccount\n && selectedPromotionAccount.broker_environment === promotionMode\n );\n if (acceptButton) acceptButton.disabled = !canDecide;\n if (rejectButton) rejectButton.disabled = !Boolean(ticket && state.auth?.admin);\n renderRiskEnvelopePanel();\n renderPromotionApplicationPreparation();\n }\n\n async function refreshResearchPromotionTickets() {\n if (!state.auth?.allowed) {\n state.researchPromotion.payload = {\n data_status: \"login_required\",\n computed_at: null,\n tickets: [],\n applications: [],\n summary: { ticket_count: 0, awaiting_human: 0 },\n policy: { live_authority_granted: false, no_order: true },\n errors: [],\n };\n renderPromotionConfirmControls();\n return;\n }\n try {\n const payload = await requestJson(\"/api/research-promotion-tickets\");\n state.researchPromotion.payload = {\n data_status: payload?.data_status || \"ready\",\n computed_at: payload?.computed_at || null,\n tickets: Array.isArray(payload?.tickets) ? payload.tickets : [],\n applications: Array.isArray(payload?.applications) ? payload.applications : [],\n summary: payload?.summary || { ticket_count: 0, awaiting_human: 0 },\n policy: {\n live_authority_granted: false,\n no_order: true,\n ...(payload?.policy || {}),\n },\n errors: Array.isArray(payload?.errors) ? payload.errors : [],\n };\n } catch {\n state.researchPromotion.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n tickets: [],\n applications: [],\n summary: { ticket_count: 0, awaiting_human: 0 },\n policy: { live_authority_granted: false, no_order: true },\n errors: [\"research_promotion_request_failed\"],\n };\n }\n renderPromotionConfirmControls();\n renderOverview();\n }\n\n async function submitResearchPromotionDecision(decision) {\n const ticket = selectedPromotionTicket();\n if (!ticket) {\n showToast(t(\"promotionTicketEmpty\"));\n return;\n }\n const application = selectedPromotionApplication();\n const selected = selectedPromotionApplicationAccount(application);\n const platform = selected?.platform || \"\";\n const executionMode = selected?.broker_environment || \"\";\n const riskSelect = el(\"promotion-risk-profile-select\");\n try {\n const confirmation = decision === \"accept\"\n ? buildPromotionConfirmation({\n targetPlatform: platform,\n executionMode,\n riskProfile: riskSelect?.value || ticket.suggested_risk_profile,\n paperSupported: executionMode !== \"paper\" || platform === \"longbridge\",\n suggestedRiskProfile: ticket.suggested_risk_profile,\n })\n : null;\n const payload = await requestJson(\"/api/research-promotion-decisions\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ticket_id: ticket.ticket_id,\n decision,\n confirmation,\n ...(decision === \"accept\" ? { selected_account: { platform: selected?.platform || \"\", key: selected?.key || \"\" } } : {}),\n expected_proposed_params: ticket.proposed_params || {},\n expected_strategy_profile: ticket.strategy_profile,\n expected_domain: ticket.domain,\n }),\n });\n if (payload?.live_authority_granted) {\n throw new Error(\"server attempted to grant live authority\");\n }\n showToast(t(\"promotionDecisionSaved\"));\n await refreshResearchPromotionTickets();\n } catch (error) {\n showToast(`${t(\"promotionDecisionFailed\")}: ${error.message || error}`);\n }\n }\n\n el(\"promotion-ticket-select\")?.addEventListener(\"change\", (event) => {\n state.researchPromotion.selectedTicketId = String(event.target.value || \"\");\n state.researchPromotion.selectedApplicationTicketId = state.researchPromotion.selectedTicketId;\n state.researchPromotion.selectedApplicationPlatform = \"\";\n state.researchPromotion.selectedApplicationEnvironment = \"\";\n state.researchPromotion.selectedApplicationAccountKey = \"\";\n const riskSelect = el(\"promotion-risk-profile-select\");\n if (riskSelect) delete riskSelect.dataset.ticketId;\n renderPromotionConfirmControls();\n });\n el(\"promotion-target-platform-select\")?.addEventListener(\"change\", (event) => {\n state.researchPromotion.selectedApplicationPlatform = String(event.target.value || \"\");\n state.researchPromotion.selectedApplicationEnvironment = \"\";\n state.researchPromotion.selectedApplicationAccountKey = \"\";\n renderPromotionConfirmControls();\n });\n el(\"promotion-broker-environment-select\")?.addEventListener(\"change\", (event) => {\n state.researchPromotion.selectedApplicationEnvironment = String(event.target.value || \"\");\n state.researchPromotion.selectedApplicationAccountKey = \"\";\n renderPromotionConfirmControls();\n });\n el(\"promotion-selected-account-select\")?.addEventListener(\"change\", (event) => {\n state.researchPromotion.selectedApplicationAccountKey = String(event.target.value || \"\");\n renderPromotionConfirmControls();\n });\n el(\"promotion-risk-profile-select\")?.addEventListener(\"change\", () => {\n const riskSelect = el(\"promotion-risk-profile-select\");\n if (riskSelect) riskSelect.dataset.touched = \"1\";\n renderRiskEnvelopePanel();\n });\n el(\"promotion-application-open\")?.addEventListener(\"click\", openSelectedPromotionApplicationAccount);\n el(\"promotion-application-deploy\")?.addEventListener(\"click\", () => {\n submitV7PaperApplication();\n });\n el(\"promotion-accept-button\")?.addEventListener(\"click\", () => {\n submitResearchPromotionDecision(\"accept\");\n });\n el(\"promotion-reject-button\")?.addEventListener(\"click\", () => {\n submitResearchPromotionDecision(\"reject\");\n });\n\n function openSelectedPromotionApplicationAccount() {\n const application = selectedPromotionApplication();\n const account = selectedPromotionApplicationAccount(application);\n if (\n application?.application_preparation?.preflight_status !== \"ready\"\n || account?.preflight_status !== \"ready\"\n ) return;\n openAccountSettings(account.platform, account, true);\n }\n\n function normalizeExecutionMode(value, dryRunOnly) {\n const mode = String(value || \"\").trim().toLowerCase();\n if (mode === \"live\") return \"live\";\n if (mode === \"paper\" || mode === \"dry_run\" || mode === \"dry-run\") return \"dry_run\";\n if (dryRunOnly === true || dryRunOnly === \"true\" || dryRunOnly === \"1\" || dryRunOnly === 1) return \"dry_run\";\n if (dryRunOnly === false || dryRunOnly === \"false\" || dryRunOnly === \"0\" || dryRunOnly === 0) return \"live\";\n return \"\";\n }\n\n function cleanOptionalBoolean(value) {\n if (value === true || value === 1) return true;\n if (value === false || value === 0) return false;\n if (typeof value === \"string\") {\n const text = value.trim().toLowerCase();\n if (text === \"true\" || text === \"1\") return true;\n if (text === \"false\" || text === \"0\") return false;\n }\n return null;\n }\n\n function normalizeExecutionEnvironment(value) {\n const environment = String(value || \"\").trim().toLowerCase();\n return environment === \"live\" || environment === \"paper\" || environment === \"shadow\" ? environment : \"\";\n }\n\n function executionEnvironmentFromEntry(entry) {\n if (!entry || entry.source === \"account_defaults\") return \"\";\n const explicit = normalizeExecutionEnvironment(entry.execution_environment);\n if (explicit) return explicit;\n const rawMode = String(entry.execution_mode_raw || entry.execution_mode || \"\").trim().toLowerCase();\n if (rawMode === \"paper\") return cleanOptionalBoolean(entry.dry_run_only) === false ? \"paper\" : \"\";\n if (rawMode === \"live\") return \"live\";\n return \"\";\n }\n\n function configuredAccountEnvironment(account) {\n return normalizeExecutionEnvironment(account?.broker_environment || account?.execution_environment);\n }\n\n function executionEnvironmentForAccount(platform, account) {\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return \"\";\n const dryRunOnly = cleanOptionalBoolean(entry.dry_run_only);\n const rawMode = String(entry.execution_mode_raw || entry.execution_mode || \"\").trim().toLowerCase();\n if (dryRunOnly === true || rawMode === \"dry_run\" || rawMode === \"dry-run\") return \"dry_run\";\n if (rawMode === \"paper\" && dryRunOnly === null) return \"dry_run\";\n if (dryRunOnly === null) return \"\";\n const configured = configuredAccountEnvironment(account);\n if (configured === \"live\" || configured === \"paper\") return configured;\n const explicit = executionEnvironmentFromEntry(entry);\n if (explicit === \"live\" || explicit === \"paper\") return explicit;\n if (normalizeExecutionMode(entry?.execution_mode, entry?.dry_run_only) === \"live\") return \"live\";\n return \"\";\n }\n\n function executionModeForDispatch(entry) {\n if (!entry) return \"\";\n const dryRunOnly = cleanOptionalBoolean(entry?.dry_run_only);\n if (dryRunOnly === true) return \"dry_run\";\n const rawMode = String(entry?.execution_mode_raw || entry?.execution_mode || \"\").trim().toLowerCase();\n const environment = normalizeExecutionEnvironment(entry?.execution_environment);\n if (rawMode === \"dry_run\" || rawMode === \"dry-run\") return \"dry_run\";\n if (dryRunOnly === null) return rawMode === \"paper\" || environment === \"paper\" ? \"dry_run\" : \"\";\n if (rawMode === \"paper\" || environment === \"paper\") return \"live\";\n return normalizeExecutionMode(entry?.execution_mode, entry?.dry_run_only);\n }\n\n function defaultExecutionModeForAccount(platform, account) {\n if (platformDryRunOnly(platform)) return \"dry_run\";\n const entry = accountReadbackEntry(platform, account);\n return executionModeForDispatch(entry);\n }\n\n function defaultStrategyForAccount(platform, account) {\n const currentProfile = currentStrategyForAccount(platform, account);\n if (currentProfile) return currentProfile;\n return \"\";\n }\n\n function syncStrategyForAccount(platform) {\n const account = selectedAccount(platform);\n if (!account) return;\n const form = state.forms[platform];\n if (!form.strategyTouched) form.strategy = defaultStrategyForAccount(platform, account);\n if (!form.executionModeTouched) form.executionMode = defaultExecutionModeForAccount(platform, account);\n if (!form.pluginModeTouched) form.pluginMode = currentPluginModeForAccount(platform, account);\n syncRuntimeTargetForAccount(platform);\n syncReservePolicyForAccount(platform);\n syncIncomeLayerForAccount(platform);\n syncOptionOverlayForAccount(platform);\n syncCashOnlyExecutionForAccount(platform);\n reconcileExecutionCashPolicy(state.forms[platform], \"margin\");\n syncDcaForAccount(platform);\n }\n\n function syncRuntimeTargetForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.runtimeTargetTouched) return;\n form.runtimeTargetMode = \"current\";\n }\n\n function syncReservePolicyForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.reservedCashTouched) return;\n const entry = accountReadbackEntry(platform, selectedAccount(platform));\n if (!entry) {\n form.reservePolicyMode = \"current\";\n form.minReservedCashUsd = \"\";\n form.reservedCashRatio = \"\";\n return;\n }\n const policy = currentReservePolicyForAccount(platform, selectedAccount(platform));\n const hasFloor = Boolean(policy.minReservedCashUsd);\n const hasRatio = Boolean(policy.reservedCashRatio);\n if (hasFloor && hasRatio) form.reservePolicyMode = \"max\";\n else if (hasFloor) form.reservePolicyMode = \"floor\";\n else if (hasRatio) form.reservePolicyMode = \"ratio\";\n else form.reservePolicyMode = \"none\";\n form.minReservedCashUsd = policy.minReservedCashUsd;\n form.reservedCashRatio = policy.reservedCashRatio;\n }\n\n function syncIncomeLayerForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.incomeLayerTouched) return;\n const current = currentIncomeLayerForAccount(platform, selectedAccount(platform));\n const entry = accountReadbackEntry(platform, selectedAccount(platform));\n if (entry && incomeLayerFieldsConfigured(entry)) {\n form.incomeLayerMode = current.enabled === false ? \"disabled\" : \"enabled\";\n } else {\n form.incomeLayerMode = \"current\";\n form.incomeLayerStartUsd = \"\";\n form.incomeLayerMaxRatio = \"\";\n }\n if (entry && incomeLayerFieldsConfigured(entry)) {\n form.incomeLayerStartUsd = current.startUsd;\n form.incomeLayerMaxRatio = current.maxRatio;\n }\n }\n\n function syncOptionOverlayForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.optionOverlayTouched) return;\n const configured = normalizeOptionOverlayMode(selectedAccount(platform)?.option_overlay_mode);\n if (configured !== \"current\") {\n form.optionOverlayMode = configured;\n return;\n }\n const entry = accountReadbackEntry(platform, selectedAccount(platform));\n const rawValue = cleanOptionalBoolean(entry?.option_overlay_enabled);\n if (rawValue !== null) {\n form.optionOverlayMode = rawValue ? \"enabled\" : \"disabled\";\n return;\n }\n form.optionOverlayMode = \"current\";\n }\n\n function syncCashOnlyExecutionForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.cashOnlyExecutionTouched) return;\n const configured = normalizeCashOnlyExecutionMode(selectedAccount(platform)?.cash_only_execution_mode);\n if (configured !== \"current\") {\n form.cashOnlyExecutionMode = configured;\n return;\n }\n const entry = accountReadbackEntry(platform, selectedAccount(platform));\n const rawValue = cleanOptionalBoolean(entry?.cash_only_execution);\n if (rawValue !== null) {\n form.cashOnlyExecutionMode = rawValue ? \"enabled\" : \"disabled\";\n return;\n }\n form.cashOnlyExecutionMode = \"current\";\n }\n\n function syncDcaForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.dcaTouched) return;\n const current = currentDcaForAccount(platform, selectedAccount(platform), form.strategy);\n form.dcaMode = current.supported && current.mode ? current.mode : \"fixed\";\n form.dcaBaseInvestmentUsd = current.supported ? current.baseInvestmentUsd : \"\";\n }\n\n function ensureAccountSelection(platform) {\n const options = optionsFor(platform);\n if (!options.length) return;\n if (!options.some((option) => option.key === state.forms[platform].accountKey)) {\n state.forms[platform].accountKey = options[0].key;\n state.forms[platform].runtimeTargetTouched = false;\n state.forms[platform].reservedCashTouched = false;\n state.forms[platform].incomeLayerTouched = false;\n state.forms[platform].optionOverlayTouched = false;\n state.forms[platform].cashOnlyExecutionTouched = false;\n state.forms[platform].dcaTouched = false;\n state.forms[platform].executionModeTouched = false;\n state.forms[platform].pluginModeTouched = false;\n state.forms[platform].strategy = defaultStrategyForAccount(platform, options[0]);\n state.forms[platform].pluginMode = currentPluginModeForAccount(platform, options[0]);\n syncRuntimeTargetForAccount(platform);\n syncReservePolicyForAccount(platform);\n syncIncomeLayerForAccount(platform);\n syncOptionOverlayForAccount(platform);\n syncCashOnlyExecutionForAccount(platform);\n syncDcaForAccount(platform);\n }\n }\n\n function derivedService(platform, targetName) {\n if (platform === \"longbridge\") return `longbridge-quant-${targetName.toLowerCase()}-service`;\n if (platform === \"ibkr\") return `interactive-brokers-${targetName.toLowerCase()}-service`;\n if (platform === \"schwab\") return \"charles-schwab-quant-service\";\n if (platformConfig[platform]?.service_name) return platformConfig[platform].service_name;\n if (platform === \"qmt\") return \"qmt-quant-service\";\n return \"\";\n }\n\n function accountMetaText() {\n return \"\";\n }\n\n function hasRunnableStrategySelection(platform = state.selected) {\n const form = state.forms[platform];\n const account = selectedAccount(platform);\n return Boolean(form?.strategy && account && strategyAllowedForAccount(platform, account, form.strategy, form.executionMode));\n }\n\n function hasValidReservePolicy(platform = state.selected) {\n if (!platformSupportsReservedCashPolicy(platform)) return true;\n const form = state.forms[platform];\n const mode = normalizeReservePolicyMode(form?.reservePolicyMode);\n if (mode === \"current\" || mode === \"none\") return true;\n return Boolean(reservePolicyOverrideForForm(form, platform));\n }\n\n function hasValidExecutionCashPolicy(platform = state.selected) {\n if (!platformSupportsMarginPolicy(platform) && !platformSupportsReservedCashPolicy(platform)) return true;\n const form = state.forms[platform];\n return !executionCashPolicyConflict(form) && hasValidReservePolicy(platform);\n }\n\n function hasValidIncomeLayerPolicy(platform = state.selected) {\n const form = state.forms[platform];\n if (!incomeLayerSupported(form?.strategy)) return true;\n const mode = normalizeIncomeLayerMode(form?.incomeLayerMode);\n if (mode === \"current\" || mode === \"disabled\") return true;\n const defaults = incomeLayerDefaultForStrategy(form?.strategy);\n const startUsd = cleanDisplayNumber(form?.incomeLayerStartUsd || defaults?.startUsd);\n const maxRatio = cleanDisplayRatio(form?.incomeLayerMaxRatio || defaults?.maxRatio);\n return Boolean(startUsd && maxRatio);\n }\n\n function hasValidOptionOverlayPolicy(platform = state.selected) {\n const form = state.forms[platform];\n const mode = normalizeOptionOverlayMode(form?.optionOverlayMode);\n return mode !== \"enabled\" || optionOverlaySupported(form?.strategy);\n }\n\n function hasValidDcaPolicy(platform = state.selected) {\n const form = state.forms[platform];\n if (!dcaSupported(form?.strategy) || !platformSupportsDca(platform)) return true;\n return Boolean(dcaModes.includes(normalizeDcaMode(form?.dcaMode)) && cleanDisplayPositiveNumber(form?.dcaBaseInvestmentUsd));\n }\n\n function hasValidStrategySelection(platform = state.selected) {\n return hasRunnableStrategySelection(platform) &&\n hasValidExecutionCashPolicy(platform) &&\n hasValidIncomeLayerPolicy(platform) &&\n hasValidOptionOverlayPolicy(platform) &&\n hasValidDcaPolicy(platform);\n }\n\n function normalizeReservePolicyMode(value) {\n return reservePolicyModes.includes(value) ? value : \"current\";\n }\n\n function reservePolicyOverrideForForm(form, platform = state.selected) {\n if (!platformSupportsReservedCashPolicy(platform)) return null;\n const mode = normalizeReservePolicyMode(form?.reservePolicyMode);\n const floor = cleanDisplayNumber(form?.minReservedCashUsd);\n const ratio = cleanDisplayRatio(form?.reservedCashRatio);\n const extraVariables = {};\n if (mode === \"current\") return null;\n if (mode === \"none\") {\n extraVariables[platformMinReservedCashVariables[platform]] = \"\";\n extraVariables[platformReservedCashRatioVariables[platform]] = \"\";\n return { inputs: {}, extraVariables };\n }\n if (mode === \"ratio\") {\n if (!ratio) return null;\n extraVariables[platformMinReservedCashVariables[platform]] = \"\";\n return { inputs: { reserved_cash_ratio: ratio }, extraVariables };\n }\n if (mode === \"floor\") {\n if (!floor) return null;\n extraVariables[platformReservedCashRatioVariables[platform]] = \"\";\n return { inputs: { min_reserved_cash_usd: floor }, extraVariables };\n }\n if (mode === \"max\") {\n if (!floor || !ratio) return null;\n return { inputs: { min_reserved_cash_usd: floor, reserved_cash_ratio: ratio }, extraVariables };\n }\n return null;\n }\n\n function runtimeTargetOverrideForForm(form) {\n const mode = normalizeRuntimeTargetMode(form?.runtimeTargetMode);\n if (mode === \"current\") return null;\n return {\n inputs: { runtime_target_enabled_mode: mode },\n extraVariables: { [runtimeTargetEnabledVariable]: mode === \"enabled\" ? \"true\" : \"false\" },\n };\n }\n\n function incomeLayerOverrideForForm(form) {\n const defaults = incomeLayerDefaultForStrategy(form?.strategy);\n if (!defaults) return null;\n const mode = normalizeIncomeLayerMode(form?.incomeLayerMode);\n if (mode === \"current\") return null;\n const extraVariables = {};\n if (mode === \"disabled\") {\n extraVariables[incomeLayerEnabledVariable] = \"false\";\n extraVariables[incomeLayerStartUsdVariable] = \"\";\n extraVariables[incomeLayerMaxRatioVariable] = \"\";\n return { inputs: { income_layer_mode: mode }, extraVariables };\n }\n const startUsd = cleanDisplayNumber(form?.incomeLayerStartUsd || defaults.startUsd);\n const maxRatio = cleanDisplayRatio(form?.incomeLayerMaxRatio || defaults.maxRatio);\n if (!startUsd || !maxRatio) return null;\n extraVariables[incomeLayerEnabledVariable] = \"true\";\n extraVariables[incomeLayerStartUsdVariable] = startUsd;\n extraVariables[incomeLayerMaxRatioVariable] = maxRatio;\n return { inputs: { income_layer_mode: mode, income_layer_start_usd: startUsd, income_layer_max_ratio: maxRatio }, extraVariables };\n }\n\n function optionOverlayOverrideForForm(form) {\n const mode = normalizeOptionOverlayMode(form?.optionOverlayMode);\n if (mode === \"current\") return null;\n if (mode === \"enabled\" && !optionOverlaySupported(form?.strategy)) return null;\n return { inputs: { option_overlay_mode: mode } };\n }\n\n function cashOnlyExecutionOverrideForForm(form, platform = state.selected) {\n if (!platformSupportsMarginPolicy(platform)) return null;\n const mode = normalizeCashOnlyExecutionMode(form?.cashOnlyExecutionMode);\n if (mode === \"current\") return null;\n return { inputs: { cash_only_execution_mode: mode } };\n }\n\n function dcaOverrideForForm(form) {\n if (!form?.dcaTouched || !dcaSupported(form?.strategy) || !platformSupportsDca(state.selected)) return null;\n const mode = normalizeDcaMode(form?.dcaMode);\n const baseInvestmentUsd = cleanDisplayPositiveNumber(form?.dcaBaseInvestmentUsd);\n if (!baseInvestmentUsd) return null;\n return { inputs: { dca_mode: mode, dca_base_investment_usd: baseInvestmentUsd } };\n }\n\n function mergeExtraVariables(inputs, extraVariables) {\n if (!extraVariables || !Object.keys(extraVariables).length) return;\n const merged = inputs.extra_variables_json ? JSON.parse(inputs.extra_variables_json) : {};\n Object.assign(merged, extraVariables);\n inputs.extra_variables_json = JSON.stringify(merged);\n }\n\n function buildInputs(platform = state.selected) {\n const form = state.forms[platform];\n const account = selectedAccount(platform);\n const targetName = account.target_name || account.key;\n const inputs = {\n platform,\n target_name: targetName,\n strategy_profile: form.strategy,\n execution_mode: form.executionMode,\n variable_scope: account.variable_scope || \"default\",\n plugin_mode: form.pluginModeTouched ? normalizePluginMode(form.pluginMode) : \"current\",\n service_targets_mode: \"auto\",\n apply: \"true\",\n trigger_platform_sync: \"true\",\n confirm_apply: \"APPLY_AND_SYNC\",\n platform_sync_workflow: \"sync-cloud-run-env.yml\",\n };\n for (const field of [\n \"github_environment\",\n \"deployment_selector\",\n \"account_selector\",\n \"account_scope\",\n \"service_name\",\n ]) {\n if (account[field]) inputs[field] = account[field];\n }\n const reserveTouched = Boolean(form.reservedCashTouched);\n const reserveOverride = reserveTouched && platformSupportsReservedCashPolicy(platform)\n ? reservePolicyOverrideForForm(form, platform)\n : null;\n if (platformSupportsReservedCashPolicy(platform)) {\n inputs.reserved_cash_policy_mode = reserveTouched ? normalizeReservePolicyMode(form.reservePolicyMode) : \"current\";\n if (reserveTouched && reserveOverride) {\n Object.assign(inputs, reserveOverride.inputs);\n mergeExtraVariables(inputs, reserveOverride.extraVariables);\n }\n }\n const runtimeTargetOverride = runtimeTargetOverrideForForm(form);\n inputs.runtime_target_enabled_mode = normalizeRuntimeTargetMode(form.runtimeTargetMode);\n if (runtimeTargetOverride) {\n Object.assign(inputs, runtimeTargetOverride.inputs);\n mergeExtraVariables(inputs, runtimeTargetOverride.extraVariables);\n }\n const incomeTouched = Boolean(form.incomeLayerTouched);\n const incomeOverride = incomeTouched ? incomeLayerOverrideForForm(form) : null;\n inputs.income_layer_mode = incomeTouched ? normalizeIncomeLayerMode(form.incomeLayerMode) : \"current\";\n if (incomeTouched && incomeOverride) {\n Object.assign(inputs, incomeOverride.inputs);\n mergeExtraVariables(inputs, incomeOverride.extraVariables);\n }\n const optionOverlayTouched = Boolean(form.optionOverlayTouched);\n const optionOverlayOverride = optionOverlayTouched ? optionOverlayOverrideForForm(form) : null;\n inputs.option_overlay_mode = optionOverlayTouched ? normalizeOptionOverlayMode(form.optionOverlayMode) : \"current\";\n if (optionOverlayTouched && optionOverlayOverride) {\n Object.assign(inputs, optionOverlayOverride.inputs);\n }\n const cashOnlyTouched = Boolean(form.cashOnlyExecutionTouched);\n const cashOnlyOverride = cashOnlyTouched ? cashOnlyExecutionOverrideForForm(form, platform) : null;\n if (platformSupportsMarginPolicy(platform)) {\n inputs.cash_only_execution_mode = cashOnlyTouched ? normalizeCashOnlyExecutionMode(form.cashOnlyExecutionMode) : \"current\";\n if (cashOnlyTouched && cashOnlyOverride) {\n Object.assign(inputs, cashOnlyOverride.inputs);\n }\n }\n const dcaOverride = dcaOverrideForForm(form);\n if (dcaOverride) {\n Object.assign(inputs, dcaOverride.inputs);\n }\n return inputs;\n }\n\n function reservedCashPolicyText(inputs, platform = state.selected, account = selectedAccount(platform), fallback = t(\"unchanged\")) {\n if (inputs?.reserved_cash_policy_mode === \"none\") return t(\"reservedCashNone\");\n const floor = cleanDisplayNumber(inputs?.min_reserved_cash_usd);\n const ratio = cleanDisplayRatio(inputs?.reserved_cash_ratio);\n const currency = selectedCashCurrency(platform, account);\n const hasEffectiveFloor = Boolean(floor && !(ratio && Number(floor) === 0));\n if (!hasEffectiveFloor && !ratio) return fallback;\n if (hasEffectiveFloor && ratio) return `max(${floor} ${currency}, ${formatRatioPercent(ratio)})`;\n if (hasEffectiveFloor) return `${floor} ${currency}`;\n return formatRatioPercent(ratio);\n }\n\n function platformReservedCashDefaultText(platform = state.selected, account = selectedAccount(platform)) {\n return t(\"reservedCashDefault\").replace(\"{currency}\", selectedCashCurrency(platform, account));\n }\n\n function currentReservedCashPolicyText(platform = state.selected, account = selectedAccount(platform)) {\n const entry = currentEntryForAccount(platform, account);\n const policy = currentReservePolicyForAccount(platform, account);\n return reservedCashPolicyText(\n {\n min_reserved_cash_usd: policy.minReservedCashUsd,\n reserved_cash_ratio: policy.reservedCashRatio,\n },\n platform,\n account,\n entry ? platformReservedCashDefaultText(platform, account) : t(\"notRead\"),\n );\n }\n\n function pendingReservedCashPolicyText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n return reservedCashPolicyText(pendingReservePolicy(inputs, platform, account).inputs, platform, account, t(\"unchanged\"));\n }\n\n function pendingReservePolicy(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const mode = normalizeReservePolicyMode(inputs.reserved_cash_policy_mode);\n if (mode === \"current\") return { changed: false, inputs: {} };\n const current = currentReservePolicyForAccount(platform, account);\n const currentFloor = cleanDisplayNumber(current.minReservedCashUsd);\n const currentRatio = cleanDisplayRatio(current.reservedCashRatio);\n const next = {\n min_reserved_cash_usd: cleanDisplayNumber(inputs.min_reserved_cash_usd),\n reserved_cash_ratio: cleanDisplayRatio(inputs.reserved_cash_ratio),\n };\n if (mode === \"none\") {\n next.reserved_cash_policy_mode = \"none\";\n }\n const entry = currentEntryForAccount(platform, account);\n const changed = Boolean(entry && (\n next.min_reserved_cash_usd !== currentFloor ||\n next.reserved_cash_ratio !== currentRatio ||\n (mode === \"none\" && (currentFloor || currentRatio))\n ));\n return { changed, inputs: next };\n }\n\n function currentIncomeLayerText(platform = state.selected, account = selectedAccount(platform), profile = state.forms[platform]?.strategy) {\n const defaults = incomeLayerDefaultForStrategy(profile);\n if (!defaults) return t(\"incomeLayerNotSupported\");\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return t(\"notRead\");\n const current = incomeLayerFromEntry(entry);\n if (!incomeLayerFieldsConfigured(entry)) {\n return t(\"strategyDefault\");\n }\n const enabled = current.enabled ?? true;\n const startUsd = current.startUsd || String(defaults.startUsd);\n const ratio = current.maxRatio || defaults.maxRatio;\n return enabled\n ? t(\"incomeLayerOn\")\n .replace(\"{start}\", formatUsd(startUsd))\n .replace(\"{ratio}\", formatRatioPercent(ratio))\n : t(\"incomeLayerOff\");\n }\n\n function pendingIncomeLayerText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingIncomeLayer(inputs, platform, account);\n if (!pending.supported) return t(\"incomeLayerNotSupported\");\n if (!pending.changed) return t(\"unchanged\");\n if (pending.inputs.income_layer_enabled === false) return t(\"incomeLayerOff\");\n return t(\"incomeLayerOn\")\n .replace(\"{start}\", formatUsd(pending.inputs.income_layer_start_usd))\n .replace(\"{ratio}\", formatRatioPercent(pending.inputs.income_layer_max_ratio));\n }\n\n function pendingOptionOverlayText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingOptionOverlay(inputs, platform, account);\n if (!pending.supported && pending.inputs.option_overlay_enabled !== false) return t(\"optionOverlayNotSupported\");\n if (!pending.changed) return t(\"unchanged\");\n return optionOverlayText(pending.inputs.option_overlay_enabled);\n }\n\n function pendingCashOnlyExecutionText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingCashOnlyExecution(inputs, platform, account);\n if (!pending.changed) return t(\"unchanged\");\n return cashOnlyExecutionText(pending.inputs.cash_only_execution);\n }\n\n function pendingRuntimeTargetText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingRuntimeTarget(inputs, platform, account);\n if (!pending.changed) return t(\"unchanged\");\n return runtimeTargetText(pending.inputs.runtime_target_enabled);\n }\n\n function pendingRuntimeTargetTone(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingRuntimeTarget(inputs, platform, account);\n if (!pending.changed) return \"neutral\";\n return runtimeTargetTone(pending.inputs.runtime_target_enabled);\n }\n\n function currentDcaText(platform = state.selected, account = selectedAccount(platform), profile = state.forms[platform]?.strategy) {\n const current = currentDcaForAccount(platform, account, profile);\n if (!current.supported) return t(\"dcaNotSupported\");\n return t(\"dcaText\")\n .replace(\"{mode}\", dcaModeLabel(current.mode))\n .replace(\"{amount}\", formatUsd(current.baseInvestmentUsd));\n }\n\n function pendingDcaText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingDca(inputs, platform, account);\n if (!pending.supported) return t(\"dcaNotSupported\");\n if (!pending.changed) return t(\"unchanged\");\n return t(\"dcaText\")\n .replace(\"{mode}\", dcaModeLabel(pending.inputs.dca_mode))\n .replace(\"{amount}\", formatUsd(pending.inputs.dca_base_investment_usd));\n }\n\n function pendingRuntimeTarget(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const mode = normalizeRuntimeTargetMode(inputs.runtime_target_enabled_mode);\n if (mode === \"current\") {\n return {\n changed: false,\n inputs: { runtime_target_enabled: runtimeTargetEnabledForAccount(platform, account) },\n };\n }\n const current = runtimeTargetEnabledForAccount(platform, account);\n const currentEnabled = current;\n const nextEnabled = mode === \"enabled\";\n const entry = accountReadbackEntry(platform, account);\n return {\n changed: Boolean(entry && currentEnabled !== nextEnabled),\n inputs: { runtime_target_enabled: nextEnabled },\n };\n }\n\n function pendingIncomeLayer(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const profile = cleanStrategyProfile(inputs.strategy_profile || state.forms[platform]?.strategy);\n const defaults = incomeLayerDefaultForStrategy(profile);\n if (!defaults) return { supported: false, changed: false, inputs: {} };\n const mode = normalizeIncomeLayerMode(inputs.income_layer_mode);\n const entry = accountReadbackEntry(platform, account);\n const rawCurrent = currentIncomeLayerForAccount(platform, account);\n const effective = effectiveIncomeLayerForAccount(platform, account, profile);\n const currentEnabled = effective?.enabled ?? true;\n const currentStartUsd = effective?.startUsd ?? String(defaults.startUsd);\n const currentRatio = effective?.maxRatio ?? defaults.maxRatio;\n if (mode === \"current\") {\n return {\n supported: true,\n changed: false,\n inputs: {\n income_layer_enabled: rawCurrent.enabled,\n income_layer_start_usd: rawCurrent.startUsd,\n income_layer_max_ratio: rawCurrent.maxRatio,\n },\n };\n }\n if (mode === \"disabled\") {\n if (!entry) {\n return {\n supported: true,\n changed: false,\n inputs: {\n income_layer_enabled: false,\n income_layer_start_usd: \"\",\n income_layer_max_ratio: \"\",\n },\n };\n }\n return {\n supported: true,\n changed: currentEnabled !== false || Boolean(rawCurrent.startUsd || rawCurrent.maxRatio),\n inputs: {\n income_layer_enabled: false,\n income_layer_start_usd: \"\",\n income_layer_max_ratio: \"\",\n },\n };\n }\n const nextStartUsd = cleanDisplayNumber(inputs.income_layer_start_usd || defaults.startUsd);\n const nextRatio = cleanDisplayRatio(inputs.income_layer_max_ratio || defaults.maxRatio);\n return {\n supported: true,\n changed: Boolean(entry && (currentEnabled !== true || nextStartUsd !== currentStartUsd || nextRatio !== currentRatio)),\n inputs: {\n income_layer_enabled: true,\n income_layer_start_usd: nextStartUsd,\n income_layer_max_ratio: nextRatio,\n },\n };\n }\n\n function pendingOptionOverlay(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const profile = cleanStrategyProfile(inputs.strategy_profile || state.forms[platform]?.strategy);\n const supported = optionOverlaySupported(profile);\n const mode = normalizeOptionOverlayMode(inputs.option_overlay_mode);\n const current = effectiveOptionOverlayForAccount(platform, account, profile);\n if (mode === \"current\") {\n return {\n supported,\n changed: false,\n inputs: { option_overlay_enabled: currentOptionOverlayForAccount(platform, account) },\n };\n }\n if (mode === \"enabled\") {\n return {\n supported,\n changed: supported && current !== null && current !== true,\n inputs: { option_overlay_enabled: true },\n };\n }\n return {\n supported,\n changed: current === true,\n inputs: { option_overlay_enabled: false },\n };\n }\n\n function pendingCashOnlyExecution(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const mode = normalizeCashOnlyExecutionMode(inputs.cash_only_execution_mode);\n if (!platformSupportsMarginPolicy(platform) || mode === \"current\") {\n return { changed: false, inputs: {} };\n }\n const current = effectiveCashOnlyExecutionForAccount(platform, account);\n const nextEnabled = mode === \"enabled\";\n const entry = accountReadbackEntry(platform, account);\n return {\n changed: Boolean(entry && current !== null && current !== nextEnabled),\n inputs: { cash_only_execution: nextEnabled },\n };\n }\n\n function pendingDca(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const profile = cleanStrategyProfile(inputs.strategy_profile || state.forms[platform]?.strategy);\n const defaults = dcaConfigForStrategy(profile);\n if (!defaults) return { supported: false, changed: false, inputs: {} };\n const current = currentDcaForAccount(platform, account, profile);\n const nextMode = normalizeDcaMode(inputs.dca_mode || defaults.defaultMode);\n const nextBase = cleanDisplayPositiveNumber(inputs.dca_base_investment_usd || defaults.defaultBaseInvestmentUsd);\n return {\n supported: true,\n changed: Boolean(current.mode !== nextMode || current.baseInvestmentUsd !== nextBase),\n inputs: {\n dca_mode: nextMode,\n dca_base_investment_usd: nextBase,\n },\n };\n }\n\n function pendingChangeState(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const currentProfile = currentStrategyForAccount(platform, account);\n const nextProfile = cleanStrategyProfile(inputs.strategy_profile);\n const currentEntry = currentEntryForAccount(platform, account);\n const currentMode = executionModeForDispatch(currentEntry);\n const currentPluginMode = currentPluginModeForAccount(platform, account);\n const nextPluginMode = normalizePluginMode(inputs.plugin_mode);\n const runtimeTarget = pendingRuntimeTarget(inputs, platform, account);\n const reserve = pendingReservePolicy(inputs, platform, account);\n const income = pendingIncomeLayer(inputs, platform, account);\n const optionOverlay = pendingOptionOverlay(inputs, platform, account);\n const cashOnly = pendingCashOnlyExecution(inputs, platform, account);\n const dca = pendingDca(inputs, platform, account);\n return {\n currentProfile,\n nextProfile,\n currentMode,\n currentPluginMode,\n nextPluginMode,\n strategyChanged: Boolean(nextProfile && ((state.forms[platform]?.strategyTouched) || (currentProfile && currentProfile !== nextProfile))),\n modeChanged: Boolean(inputs.execution_mode && currentMode && currentMode !== inputs.execution_mode),\n pluginModeChanged: Boolean(state.forms[platform]?.pluginModeTouched && nextPluginMode && currentPluginMode !== nextPluginMode),\n runtimeTargetChanged: runtimeTarget.changed,\n reserveCashChanged: reserve.changed,\n incomeLayerChanged: income.changed,\n optionOverlayChanged: optionOverlay.changed,\n cashOnlyChanged: cashOnly.changed,\n dcaChanged: dca.changed,\n runtimeTarget,\n reserve,\n income,\n optionOverlay,\n cashOnly,\n dca,\n };\n }\n\n function hasPendingChanges(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const changes = pendingChangeState(inputs, platform, account);\n return Boolean(\n changes.strategyChanged ||\n changes.modeChanged ||\n changes.pluginModeChanged ||\n changes.runtimeTargetChanged ||\n changes.reserveCashChanged ||\n changes.incomeLayerChanged ||\n changes.optionOverlayChanged ||\n changes.cashOnlyChanged ||\n changes.dcaChanged\n );\n }\n\n function formatRatioPercent(value) {\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) return String(value);\n return `${(numeric * 100).toFixed(2).replace(/\\.?0+$/, \"\")}%`;\n }\n\n function formatUsd(value) {\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) return String(value);\n return `$${numeric.toLocaleString(\"en-US\", { maximumFractionDigits: 0 })}`;\n }\n\n function incomeLayerAllocationText(defaults) {\n if (!defaults?.allocations) return \"\";\n return Object.entries(defaults.allocations)\n .map(([symbol, ratio]) => `${symbol} ${formatRatioPercent(ratio)}`)\n .join(\" / \");\n }\n\n function incomeLayerDefaultMetaText(defaults) {\n if (!defaults) return t(\"incomeLayerModeMeta\");\n return t(\"incomeLayerDefaultMeta\")\n .replace(\"{start}\", formatUsd(defaults.startUsd))\n .replace(\"{ratio}\", formatRatioPercent(defaults.maxRatio));\n }\n\n function optionOverlayDefaultMetaText(defaults) {\n if (!defaults?.families?.length) return t(\"optionOverlayModeMeta\");\n const familyText = defaults.families.map((item) => {\n const family = item.family === \"income\" ? t(\"optionOverlayFamilyIncome\") : t(\"optionOverlayFamilyGrowth\");\n const ratioText = item.ratioKind === \"risk\"\n ? t(\"optionOverlayRiskRatio\").replace(\"{ratio}\", formatRatioPercent(item.ratio))\n : t(\"optionOverlayBudgetRatio\").replace(\"{ratio}\", formatRatioPercent(item.ratio));\n return `${family}: ${item.recipe}, ${formatUsd(item.startUsd)}, ${ratioText}`;\n }).join(\" / \");\n return t(\"optionOverlayDefaultMeta\").replace(\"{defaults}\", familyText);\n }\n\n function summaryRows(inputs) {\n const account = selectedAccount();\n const changes = pendingChangeState(inputs, state.selected, account);\n const currentStrategyText = changes.currentProfile ? strategyLabel(changes.currentProfile) : t(\"notRead\");\n const rows = [\n [t(\"repository\"), state.repositories[state.selected] || defaultRepositories[state.selected]],\n [t(\"selectedAccount\"), accountDisplayLabel(account)],\n [t(\"currentStrategy\"), currentStrategyText],\n [t(\"selectedMarket\"), supportedDomainLabel(state.selected, account)],\n [\n t(\"currentRuntimeTarget\"),\n currentRuntimeTargetText(state.selected, account),\n \"\",\n currentRuntimeTargetTone(state.selected, account),\n ],\n [t(\"currentPluginMode\"), pluginModeLabel(changes.currentPluginMode)],\n [t(\"reservedCashPolicy\"), currentReservedCashPolicyText(state.selected, account)],\n ];\n if (platformSupportsMarginPolicy(state.selected)) {\n rows.push([t(\"currentCashOnlyExecution\"), currentCashOnlyExecutionText(state.selected, account)]);\n }\n if (incomeLayerSupported(inputs.strategy_profile)) {\n rows.push([t(\"currentIncomeLayer\"), currentIncomeLayerText(state.selected, account, inputs.strategy_profile)]);\n }\n if (optionOverlaySupported(inputs.strategy_profile) || changes.optionOverlayChanged) {\n rows.push([t(\"currentOptionOverlay\"), currentOptionOverlayText(state.selected, account, inputs.strategy_profile)]);\n }\n if (dcaSupported(inputs.strategy_profile)) {\n rows.push([t(\"currentDca\"), currentDcaText(state.selected, account, inputs.strategy_profile)]);\n }\n if (changes.reserveCashChanged) {\n rows.push([t(\"pendingReservedCashPolicy\"), pendingReservedCashPolicyText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.incomeLayerChanged) {\n rows.push([t(\"pendingIncomeLayer\"), pendingIncomeLayerText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.optionOverlayChanged) {\n rows.push([t(\"pendingOptionOverlay\"), pendingOptionOverlayText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.cashOnlyChanged) {\n rows.push([t(\"pendingCashOnlyExecution\"), pendingCashOnlyExecutionText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.dcaChanged) {\n rows.push([t(\"pendingDca\"), pendingDcaText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.modeChanged) {\n rows.push([t(\"pendingMode\"), modeLabel(inputs.execution_mode), \"pending\"]);\n }\n if (changes.pluginModeChanged) {\n rows.push([t(\"pendingPluginMode\"), pluginModeLabel(changes.nextPluginMode), \"pending\"]);\n }\n if (changes.runtimeTargetChanged) {\n rows.push([\n t(\"pendingRuntimeTarget\"),\n pendingRuntimeTargetText(inputs, state.selected, account),\n \"pending\",\n pendingRuntimeTargetTone(inputs, state.selected, account),\n ]);\n }\n if (changes.strategyChanged && changes.nextProfile) {\n rows.push([t(\"nextStrategy\"), strategyLabel(changes.nextProfile), \"pending\"]);\n }\n return rows;\n }\n\n function applyLanguage() {\n document.documentElement.lang = state.lang === \"zh\" ? \"zh-CN\" : \"en\";\n document.querySelectorAll(\"[data-i18n]\").forEach((node) => {\n node.textContent = t(node.dataset.i18n);\n });\n document.querySelectorAll(\"[data-i18n-aria-label]\").forEach((node) => {\n node.setAttribute(\"aria-label\", t(node.dataset.i18nAriaLabel));\n });\n document.querySelectorAll(\"[data-i18n-placeholder]\").forEach((node) => {\n node.placeholder = t(node.dataset.i18nPlaceholder);\n });\n el(\"lang-button\").textContent = state.lang === \"zh\" ? \"EN\" : \"中\";\n }\n\n function renderPlatforms() {\n const strip = el(\"platform-strip\");\n strip.replaceChildren();\n const showPrivateConfig = hasPrivateConfig();\n const visiblePlatforms = Object.keys(platformMeta).filter((platform) => platformMeta[platform].console_visible !== false);\n if (!visiblePlatforms.includes(state.selected) && visiblePlatforms.length) state.selected = visiblePlatforms[0];\n el(\"switch-view\").hidden = !visiblePlatforms.length;\n for (const platform of visiblePlatforms) {\n ensureAccountSelection(platform);\n const meta = platformMeta[platform];\n const form = state.forms[platform];\n const account = selectedAccount(platform);\n const button = document.createElement(\"button\");\n button.className = \"platform-button\";\n button.type = \"button\";\n button.dataset.platform = platform;\n button.classList.toggle(\"active\", platform === state.selected);\n button.setAttribute(\"aria-pressed\", String(platform === state.selected));\n const mark = document.createElement(\"span\");\n mark.className = \"mark\";\n mark.textContent = meta.code;\n const copyNode = document.createElement(\"span\");\n copyNode.className = \"platform-copy\";\n const labelNode = document.createElement(\"strong\");\n labelNode.textContent = meta.label;\n copyNode.append(labelNode);\n if (showPrivateConfig) {\n const accountNode = document.createElement(\"span\");\n accountNode.textContent = accountDisplayLabel(account);\n const strategyNode = document.createElement(\"small\");\n strategyNode.textContent = strategyLabel(form.strategy);\n copyNode.append(accountNode, strategyNode);\n }\n button.append(mark, copyNode);\n strip.appendChild(button);\n }\n }\n\n function accountMonitoringRecord(platform, account) {\n if (!state.auth.allowed || !account?.runtime_status_target_id) return null;\n const id = account.runtime_status_target_id;\n if (optionsFor(platform).filter(item => item.runtime_status_target_id === id).length !== 1) return null;\n const matches = state.runtimeTargetLifecycle.payload.targets.filter(entry =>\n entry.target?.target?.platform === platform && entry.target?.target_id === id);\n return matches.length === 1 ? matches[0] : null;\n }\n\n function accountMonitoringText(platform, account) {\n const record = accountMonitoringRecord(platform, account);\n if (!record) return t(account?.runtime_status_target_id ? \"runtimeUnverified\" : \"monitoringUnlinked\");\n if (record.freshness?.data_status !== \"ready\") return t(\"controlDataStale\");\n const configured = runtimeTargetStateForAccount(platform, account);\n const recorded = record.target?.target?.configured_state;\n if (configured.known && [\"enabled\", \"disabled\"].includes(recorded)\n && configured.enabled !== (recorded === \"enabled\")) return t(\"monitoringConfigMismatch\");\n return runtimeTargetLifecycleObservationLabel(record.execution_observation?.code);\n }\n\n function accountDiagnosisKey(platform, account) {\n return `${platform}:${account?.key || \"\"}`;\n }\n\n function accountDiagnosisEligible(platform, account) {\n const targetId = String(account?.runtime_status_target_id || \"\");\n return state.auth.allowed\n && ((platform === \"binance\" && targetId === \"binance.crypto_live_pool_rotation\")\n || (platform === \"longbridge\" && [\"longbridge.paper\", \"longbridge.hk\", \"longbridge.sg\"].includes(targetId)));\n }\n\n function accountDiagnosisTask(platform, account) {\n return state.accountDiagnosis.tasks[accountDiagnosisKey(platform, account)] || null;\n }\n\n function accountDiagnosisStatusAvailable(platform, account) {\n const record = accountMonitoringRecord(platform, account);\n return [\"ready\", \"stale\"].includes(record?.freshness?.data_status);\n }\n\n function accountDiagnosisStatusText(task) {\n if (!task) return \"\";\n if (task.status === \"queued\" && task.dispatch_state === \"unknown\") return t(\"accountDiagnosisDispatchUnknown\");\n if (task.status === \"queued\") return t(\"accountDiagnosisQueued\");\n if (task.status === \"running\") return t(\"accountDiagnosisRunning\");\n if (task.status === \"succeeded\" && task.recheck_status === \"sent\") return t(\"accountDiagnosisRechecking\");\n if (task.status === \"succeeded\" && task.recheck_status === \"attention\") {\n const reason = task.summary || t(\"accountDiagnosisUnavailable\");\n return t(\"accountDiagnosisNeedsReview\").replace(\"{summary}\", reason);\n }\n if (task.status === \"succeeded\" && task.recheck_status === \"passed\") return t(\"accountDiagnosisSuccess\");\n if (task.status === \"succeeded\" && task.recheck_status === \"unavailable\") return t(\"accountDiagnosisRecheckUnavailable\");\n if (task.status === \"succeeded\") return t(\"accountDiagnosisRecheckUnknown\");\n if (task.status === \"failed\" || task.status === \"unknown\") {\n const reason = task.summary || task.reason_code || t(\"accountDiagnosisUnavailable\");\n return t(\"accountDiagnosisFailed\").replace(\"{reason}\", reason);\n }\n return \"\";\n }\n\n function accountDiagnosisTrigger(platform, account) {\n const record = accountMonitoringRecord(platform, account);\n const deployment = record?.target?.deployment;\n const monitoring = record?.target?.monitoring || {};\n const configuredState = record?.target?.target?.configured_state;\n const confirmedAttention = record?.freshness?.data_status === \"ready\"\n && ((configuredState !== \"disabled\" && deployment?.runtime_enabled === false)\n || (configuredState === \"enabled\" && deployment?.scheduler_state === \"paused\")\n || monitoring.runtime_guard === \"attention\"\n || monitoring.execution_heartbeat === \"attention\");\n return confirmedAttention ? \"incident\" : \"manual_check\";\n }\n\n function renderAccountDiagnosisAction() {\n const action = el(\"account-diagnosis-action\");\n const button = el(\"account-diagnosis-button\");\n const status = el(\"account-diagnosis-status\");\n if (!action || !button || !status) return;\n const platform = state.selected;\n const account = selectedAccount(platform);\n const eligible = accountDiagnosisEligible(platform, account);\n const task = eligible ? accountDiagnosisTask(platform, account) : null;\n const statusAvailable = accountDiagnosisStatusAvailable(platform, account);\n const key = accountDiagnosisKey(platform, account);\n const submitting = Boolean(state.accountDiagnosis.submitting[key]);\n const busy = submitting || [\"queued\", \"running\"].includes(task?.status)\n || (task?.status === \"succeeded\" && task?.recheck_status === \"sent\");\n action.hidden = !eligible;\n button.disabled = !eligible || !statusAvailable\n || submitting\n || [\"queued\", \"running\"].includes(task?.status)\n || (task?.status === \"succeeded\" && task?.recheck_status === \"sent\");\n button.textContent = submitting ? t(\"accountDiagnosisSubmitting\")\n : task?.status === \"queued\" ? t(\"accountDiagnosisQueuedButton\")\n : task?.status === \"running\" ? t(\"accountDiagnosisRunningButton\")\n : task?.status === \"succeeded\" && task?.recheck_status === \"sent\"\n ? t(\"accountDiagnosisRecheckingButton\") : t(\"accountDiagnosisButton\");\n button.classList.toggle(\"is-busy\", busy);\n if (busy) button.setAttribute(\"aria-busy\", \"true\");\n else button.removeAttribute(\"aria-busy\");\n status.textContent = task && !busy ? accountDiagnosisStatusText(task)\n : eligible && !statusAvailable ? t(\"accountDiagnosisUnavailable\") : \"\";\n }\n\n function accountDeploymentObservation(platform, account) {\n const record = accountMonitoringRecord(platform, account);\n return (record?.deployment_freshness || record?.freshness)?.data_status === \"ready\" ? record.target?.deployment || null : null;\n }\n\n function accountDeploymentText(platform, account) {\n const observed = accountDeploymentObservation(platform, account);\n // Ready observation with null switch is \"unknown\", not the same as missing readback.\n if (!observed) return t(\"notRead\");\n if (typeof observed.runtime_enabled !== \"boolean\") return t(\"runtimeStateUnknown\");\n return t(observed.runtime_enabled ? \"runtimeTargetLifecycleStateEnabled\" : \"runtimeTargetLifecycleStateDisabled\");\n }\n\n function accountSchedulerText(platform, account) {\n const observed = accountDeploymentObservation(platform, account);\n if (!observed) return t(\"notRead\");\n return t({enabled:\"scheduleEnabled\", paused:\"schedulePaused\", mixed:\"scheduleMixed\",\n missing:\"scheduleMissing\", unknown:\"scheduleUnknown\",\n not_applicable:\"scheduleNotApplicable\"}[observed.scheduler_state] || \"notRead\");\n }\n\n function accountApplicationText(platform, account) {\n const observed = accountDeploymentObservation(platform, account);\n const configured = runtimeTargetStateForAccount(platform, account);\n if (!configured.known || typeof observed?.runtime_enabled !== \"boolean\") return t(\"deploymentUnverified\");\n const profile = currentStrategyForAccount(platform, account);\n if (observed.strategy_profile && profile && observed.strategy_profile !== profile) return t(\"strategyNotApplied\");\n if (observed.runtime_enabled !== configured.enabled) return t(\"settingsNotApplied\");\n if (!configured.enabled && observed.scheduler_state === \"paused\") return t(\"switchesApplied\");\n if (configured.enabled && observed.scheduler_state === \"enabled\") return t(\"switchesApplied\");\n if (!observed.scheduler_state || observed.scheduler_state === \"unknown\") return t(\"deploymentUnverified\");\n return t(\"scheduleNotApplied\");\n }\n\n function runtimeOverviewStatus(saved, applicationApplied, record, configurationReason = \"\") {\n const ready = record?.freshness?.data_status === \"ready\";\n const code = record?.execution_observation?.code;\n const healthy = code === \"monitoring_only\"\n || code === \"not_due\"\n || (code === \"not_applicable\" && saved.known && saved.enabled === false);\n if (applicationApplied && ready && healthy) {\n return { status: saved.known && saved.enabled === false ? \"paused\" : \"normal\", reason: \"\" };\n }\n return {\n status: \"abnormal\",\n reason: !record ? \"missing\"\n : record.freshness?.data_status === \"stale\" ? \"stale\"\n : code === \"attention\" ? \"attention\"\n : (typeof configurationReason === \"string\" ? configurationReason : configurationReason ? \"config\" : \"\") || \"pending\",\n };\n }\n\n function accountNextStep(platform, account) {\n const status = accountApplicationText(platform, account);\n if (status === t(\"deploymentUnverified\")) return { label: t(\"recheckRuntimeStatus\"), openSettings: false };\n if (status === t(\"switchesApplied\")) return { label: t(\"noSwitchAction\"), openSettings: false };\n return { label: t(\"reviewAccountSettings\"), openSettings: true };\n }\n\n function openAccountSettings(platform, account, edit = true) {\n state.view = \"accounts\";\n state.selected = platform;\n render();\n const select = el(\"account-select\");\n select.value = account.key;\n select.dispatchEvent(new Event(\"change\"));\n const settings = el(\"strategy-settings\");\n settings.open = edit;\n (edit ? settings : el(\"workspace-title\")).scrollIntoView({ block: \"start\" });\n select.focus({ preventScroll: true });\n }\n\n function accountMonitoringAge(record) {\n const age = (record?.deployment_freshness || record?.freshness)?.age_seconds;\n if (typeof age !== \"number\" || !Number.isFinite(age) || age < 0) return \"—\";\n const unit = age >= 86400 ? \"day\" : age >= 3600 ? \"hour\" : \"minute\";\n const seconds = unit === \"day\" ? 86400 : unit === \"hour\" ? 3600 : 60;\n return new Intl.RelativeTimeFormat(state.lang, { numeric: \"auto\" }).format(-Math.floor(age / seconds), unit);\n }\n\n function accountObservationAge(record) {\n const age = record?.freshness?.age_seconds;\n if (typeof age !== \"number\" || !Number.isFinite(age) || age < 0) return \"—\";\n const unit = age >= 86400 ? \"day\" : age >= 3600 ? \"hour\" : \"minute\";\n const seconds = unit === \"day\" ? 86400 : unit === \"hour\" ? 3600 : 60;\n return new Intl.RelativeTimeFormat(state.lang, { numeric: \"auto\" }).format(-Math.floor(age / seconds), unit);\n }\n\n function runtimeStatusDisplayText(platform, account) {\n const saved = runtimeTargetStateForAccount(platform, account);\n const record = accountMonitoringRecord(platform, account);\n const application = accountApplicationText(platform, account);\n const configurationMismatch = [\"settingsNotApplied\", \"strategyNotApplied\", \"scheduleNotApplied\"]\n .map(key => t(key)).includes(application) || accountMonitoringText(platform, account) === t(\"monitoringConfigMismatch\");\n const configurationReason = application === t(\"strategyNotApplied\") ? \"strategy\"\n : application === t(\"scheduleNotApplied\") ? \"schedule\"\n : application === t(\"settingsNotApplied\") || configurationMismatch ? \"switch\" : \"\";\n const status = runtimeOverviewStatus(saved, application === t(\"switchesApplied\"), record,\n configurationReason);\n const statusReasonText = reason => {\n const reasonKey = reason === \"missing\" ? \"overviewRuntimeReasonMissing\"\n : reason === \"stale\" ? \"overviewRuntimeReasonStale\"\n : reason === \"switch\" ? \"overviewRuntimeReasonSwitch\"\n : reason === \"strategy\" ? \"overviewRuntimeReasonStrategy\"\n : reason === \"schedule\" ? \"overviewRuntimeReasonSchedule\"\n : reason === \"config\" ? \"overviewRuntimeReasonConfig\"\n : reason === \"attention\" ? \"overviewRuntimeReasonAttention\" : \"overviewRuntimeReasonPending\";\n return t(reasonKey).replace(\"{age}\", accountObservationAge(record));\n };\n const statusKey = status.status === \"normal\" ? \"overviewRuntimeNormal\" : status.status === \"paused\" ? \"overviewRuntimePaused\" : \"overviewRuntimeAbnormal\";\n if (status.status !== \"abnormal\") return t(statusKey);\n return `${t(statusKey)} · ${statusReasonText(status.reason)}`;\n }\n\n function renderMonitoringOverview() {\n const body = el(\"monitoring-overview-body\");\n body.replaceChildren();\n if (!hasPrivateConfig()) return;\n for (const platform of Object.keys(platformMeta).filter(p => platformMeta[p].console_visible !== false)) {\n for (const account of optionsFor(platform)) {\n const record = accountMonitoringRecord(platform, account);\n const row = document.createElement(\"tr\");\n for (const value of [platformMeta[platform].label, accountDisplayLabel(account),\n runtimeStatusDisplayText(platform, account), accountObservationAge(record)]) {\n const cell = document.createElement(\"td\");\n cell.textContent = value;\n row.append(cell);\n }\n const action = document.createElement(\"td\");\n const button = document.createElement(\"button\");\n button.className = \"btn\";\n button.type = \"button\";\n button.textContent = runtimeStatusDisplayText(platform, account).startsWith(t(\"overviewRuntimeAbnormal\"))\n ? t(\"monitoringViewReason\") : t(\"switchView\");\n button.addEventListener(\"click\", () => {\n openAccountSettings(platform, account, false);\n });\n action.append(button);\n const statusText = runtimeStatusDisplayText(platform, account);\n if (accountDiagnosisEligible(platform, account) && statusText.startsWith(t(\"overviewRuntimeAbnormal\"))) {\n const diagnosisButton = document.createElement(\"button\");\n diagnosisButton.className = \"btn\";\n diagnosisButton.type = \"button\";\n diagnosisButton.dataset.accountDiagnosis = \"true\";\n diagnosisButton.dataset.platform = platform;\n diagnosisButton.dataset.accountKey = account.key;\n diagnosisButton.textContent = t(\"accountDiagnosisButton\");\n const task = accountDiagnosisTask(platform, account);\n diagnosisButton.disabled = !accountDiagnosisStatusAvailable(platform, account)\n || Boolean(state.accountDiagnosis.submitting[accountDiagnosisKey(platform, account)])\n || [\"queued\", \"running\"].includes(task?.status)\n || (task?.status === \"succeeded\" && task?.recheck_status === \"sent\");\n action.append(diagnosisButton);\n }\n row.append(action);\n body.append(row);\n }\n }\n }\n\n function renderAccountOverview() {\n const body = el(\"account-overview-body\");\n const details = el(\"account-runtime-details\");\n const detailsBody = el(\"account-runtime-details-body\");\n body.replaceChildren();\n detailsBody.replaceChildren();\n el(\"account-overview\").hidden = !hasPrivateConfig();\n details.hidden = !hasPrivateConfig();\n if (!hasPrivateConfig()) {\n if (typeof renderAccountDiagnosisAction === \"function\") renderAccountDiagnosisAction();\n return;\n }\n const platform = state.selected;\n const account = selectedAccount(platform);\n const record = accountMonitoringRecord(platform, account);\n const monitoring = accountMonitoringText(platform, account);\n const observationAge = accountObservationAge(record);\n const application = accountApplicationText(platform, account);\n const saved = runtimeTargetStateForAccount(platform, account);\n const observed = (record?.deployment_freshness || record?.freshness)?.data_status === \"ready\"\n ? record.target?.deployment || null : null;\n const configurationMismatch = [\"settingsNotApplied\", \"strategyNotApplied\", \"scheduleNotApplied\"]\n .map(key => t(key)).includes(application) || monitoring === t(\"monitoringConfigMismatch\");\n const configurationReason = application === t(\"strategyNotApplied\") ? \"strategy\"\n : application === t(\"scheduleNotApplied\") ? \"schedule\"\n : application === t(\"settingsNotApplied\") || configurationMismatch ? \"switch\" : \"\";\n const runtimeStatus = runtimeOverviewStatus(saved, application === t(\"switchesApplied\"), record,\n configurationReason);\n const statusReasonText = reason => {\n const reasonKey = reason === \"missing\" ? \"overviewRuntimeReasonMissing\"\n : reason === \"stale\" ? \"overviewRuntimeReasonStale\"\n : reason === \"switch\" ? \"overviewRuntimeReasonSwitch\"\n : reason === \"strategy\" ? \"overviewRuntimeReasonStrategy\"\n : reason === \"schedule\" ? \"overviewRuntimeReasonSchedule\"\n : reason === \"config\" ? \"overviewRuntimeReasonConfig\"\n : reason === \"attention\" ? \"overviewRuntimeReasonAttention\" : \"overviewRuntimeReasonPending\";\n return t(reasonKey).replace(\"{age}\", accountObservationAge(record));\n };\n const observationCode = record?.execution_observation?.code;\n const profile = currentStrategyForAccount(platform, account);\n const monitoringNeedsAttention = !record\n || record.freshness?.data_status !== \"ready\"\n || [\"attention\", \"unavailable\"].includes(observationCode)\n || monitoring === t(\"monitoringConfigMismatch\");\n const needsAttention = application !== t(\"switchesApplied\") || monitoringNeedsAttention;\n const nextStep = application !== t(\"switchesApplied\")\n ? accountNextStep(platform, account).label\n : runtimeStatus.status === \"abnormal\" ? t(\"recheckRuntimeStatus\")\n : t(\"openSystemStatus\");\n const runtimeSummary = runtimeStatus.status === \"abnormal\"\n ? statusReasonText(runtimeStatus.reason)\n : !observed || !saved.known\n ? t(\"overviewRuntimeReasonPending\")\n : application === t(\"switchesApplied\") && !saved.enabled && observed.scheduler_state === \"paused\"\n ? `${t(\"overviewRuntimePaused\")},未发现运行故障。`\n : application === t(\"switchesApplied\") && saved.enabled && observed.scheduler_state === \"enabled\"\n ? \"配置已应用,自动调度正常。\"\n : application === t(\"strategyNotApplied\") ? t(\"strategyNotApplied\")\n : application === t(\"settingsNotApplied\") ? t(\"settingsNotApplied\")\n : application === t(\"scheduleNotApplied\") ? t(\"scheduleNotApplied\")\n : observed.scheduler_state === \"missing\" ? t(\"scheduleMissing\")\n : t(\"overviewRuntimeReasonPending\");\n const facts = [\n [\"overviewRuntime\", `${t(runtimeStatus.status === \"normal\" ? \"overviewRuntimeNormal\" : runtimeStatus.status === \"paused\" ? \"overviewRuntimePaused\" : \"overviewRuntimeAbnormal\")}${runtimeStatus.status === \"abnormal\" ? ` · ${statusReasonText(runtimeStatus.reason)}` : \"\"}`],\n [\"configuredStrategy\", profile ? strategyLabel(profile) : t(\"notRead\")],\n [\"latestReadback\", observationAge === \"—\" ? t(\"runtimeUnverified\") : observationAge],\n ...(needsAttention ? [[\"accountDetailAction\", nextStep]] : []),\n ];\n const detailSummary = details.querySelector?.(\"summary\");\n if (detailSummary) detailSummary.textContent = `${t(\"accountRuntimeSummary\")}:${runtimeSummary}`;\n const detailFacts = [\n [\"deployedSwitch\", accountDeploymentText(platform, account)],\n [\"schedulerState\", accountSchedulerText(platform, account)],\n [\"applicationStatus\", application],\n ];\n for (const [target, rows] of [[body, facts], [detailsBody, detailFacts]]) {\n for (const [label, value] of rows) {\n const pair = document.createElement(\"div\");\n const term = document.createElement(\"dt\");\n term.textContent = t(label);\n const detail = document.createElement(\"dd\");\n detail.textContent = value;\n pair.append(term, detail);\n target.append(pair);\n }\n }\n if (typeof renderAccountDiagnosisAction === \"function\") renderAccountDiagnosisAction();\n }\n\n function renderCurrentValueSelect(select, modes, selected, known, label, placeholder = t(\"notRead\")) {\n select.replaceChildren();\n if (!known) {\n const option = new Option(placeholder, \"\", true, true);\n option.disabled = true;\n select.append(option);\n select.disabled = true;\n return;\n }\n select.disabled = false;\n for (const mode of modes) {\n select.append(new Option(label(mode), mode, false, mode === selected));\n }\n }\n\n function renderControls() {\n renderPromotionConfirmControls();\n\n const platform = state.selected;\n const meta = platformMeta[platform];\n const form = state.forms[platform];\n const accounts = optionsFor(platform);\n const account = selectedAccount(platform);\n const choices = strategyChoicesForAccount(platform, account, form.executionMode);\n const currentStrategy = currentStrategyForAccount(platform, account);\n const currentStrategyBlocked = Boolean(\n currentStrategy &&\n !strategyAllowedForAccount(platform, account, currentStrategy, form.executionMode),\n );\n const accountSelect = el(\"account-select\");\n const strategySelect = el(\"strategy-select\");\n const runtimeTargetEnabledSelect = el(\"runtime-target-enabled-select\");\n const executionModeSelect = el(\"execution-mode-select\");\n const pluginModeSelect = el(\"plugin-mode-select\");\n const incomeLayerModeSelect = el(\"income-layer-mode-select\");\n const incomeLayerStartUsdInput = el(\"income-layer-start-usd-input\");\n const incomeLayerMaxRatioInput = el(\"income-layer-max-ratio-input\");\n const optionOverlayModeSelect = el(\"option-overlay-mode-select\");\n const cashOnlyExecutionModeSelect = el(\"cash-only-execution-mode-select\");\n const dcaModeSelect = el(\"dca-mode-select\");\n const dcaBaseInvestmentUsdInput = el(\"dca-base-investment-usd-input\");\n const reservePolicyModeSelect = el(\"reserve-policy-mode-select\");\n const minReservedCashInput = el(\"min-reserved-cash-input\");\n const reservedCashRatioInput = el(\"reserved-cash-ratio-input\");\n const showPrivateControls = hasPrivateConfig();\n\n el(\"switch-panel\").style.setProperty(\"--platform-color\", meta.accent);\n el(\"platform-title\").textContent = meta.label;\n el(\"quick-form\").hidden = !showPrivateControls;\n el(\"run-area\").hidden = !showPrivateControls;\n el(\"public-note\").hidden = showPrivateControls;\n el(\"public-note\").textContent = state.auth.allowed ? t(\"missingConfigNote\") : t(\"publicReadonly\");\n\n if (!showPrivateControls) {\n accountSelect.replaceChildren();\n strategySelect.replaceChildren();\n runtimeTargetEnabledSelect.replaceChildren();\n executionModeSelect.replaceChildren();\n pluginModeSelect.replaceChildren();\n incomeLayerModeSelect.replaceChildren();\n optionOverlayModeSelect.replaceChildren();\n cashOnlyExecutionModeSelect.replaceChildren();\n dcaModeSelect.replaceChildren();\n reservePolicyModeSelect.replaceChildren();\n incomeLayerStartUsdInput.value = \"\";\n incomeLayerMaxRatioInput.value = \"\";\n dcaBaseInvestmentUsdInput.value = \"\";\n minReservedCashInput.value = \"\";\n reservedCashRatioInput.value = \"\";\n el(\"account-meta\").textContent = \"\";\n el(\"strategy-meta\").textContent = \"\";\n el(\"income-layer-mode-meta\").textContent = \"\";\n el(\"income-layer-start-meta\").textContent = \"\";\n el(\"income-layer-ratio-meta\").textContent = \"\";\n el(\"option-overlay-mode-meta\").textContent = \"\";\n el(\"cash-only-execution-mode-meta\").textContent = \"\";\n el(\"dca-mode-meta\").textContent = \"\";\n el(\"dca-base-meta\").textContent = \"\";\n return;\n }\n\n accountSelect.replaceChildren();\n if (accounts.length) {\n for (const account of accounts) {\n accountSelect.append(new Option(accountDisplayLabel(account), account.key, false, account.key === form.accountKey));\n }\n } else {\n accountSelect.append(new Option(t(\"noAccount\"), \"\"));\n }\n el(\"account-meta\").textContent = accounts.length ? accountMetaText(platform) : \"\";\n\n const strategyKnown = Boolean(form.strategy || form.strategyTouched);\n strategySelect.disabled = !choices.length || !strategyKnown;\n strategySelect.replaceChildren();\n if (currentStrategyBlocked && !choices.includes(currentStrategy)) {\n const blockedOption = new Option(\n strategyChoiceLabel(currentStrategy, platform, account, form.executionMode),\n currentStrategy,\n true,\n currentStrategy === form.strategy,\n );\n blockedOption.disabled = true;\n strategySelect.append(blockedOption);\n }\n if (choices.length) {\n for (const strategy of choices) {\n strategySelect.append(\n new Option(strategyChoiceLabel(strategy, platform, account, form.executionMode), strategy, false, strategy === form.strategy),\n );\n }\n } else {\n const option = new Option(strategyKnown ? t(\"noStrategy\") : t(\"notRead\"), \"\", true, true);\n option.disabled = true;\n strategySelect.append(option);\n }\n el(\"strategy-meta\").textContent = account\n ? strategyDisplayMetaText(platform, account, form.strategy)\n : \"\";\n const runtimeTarget = runtimeTargetStateForAccount(platform, account);\n const runtimeTargetSelected = form.runtimeTargetTouched\n ? normalizeRuntimeTargetMode(form.runtimeTargetMode)\n : (runtimeTarget.known ? (runtimeTarget.enabled ? \"enabled\" : \"disabled\") : \"\");\n renderCurrentValueSelect(\n runtimeTargetEnabledSelect,\n [\"enabled\", \"disabled\"],\n runtimeTargetSelected,\n runtimeTarget.known || form.runtimeTargetTouched,\n runtimeTargetModeLabel,\n );\n pluginModeSelect.replaceChildren();\n pluginModeSelect.disabled = false;\n for (const mode of pluginModes) {\n pluginModeSelect.append(new Option(pluginModeLabel(mode), mode, false, mode === normalizePluginMode(form.pluginMode)));\n }\n const incomeDefaults = incomeLayerDefaultForStrategy(form.strategy);\n el(\"income-layer-section\").hidden = false;\n el(\"option-overlay-section\").hidden = false;\n incomeLayerModeSelect.replaceChildren();\n if (incomeDefaults) {\n const readback = accountReadbackEntry(platform, account);\n const currentIncome = currentIncomeLayerForAccount(platform, account);\n const incomeKnown = Boolean(readback && incomeLayerFieldsConfigured(readback));\n const incomeSelected = form.incomeLayerTouched\n ? normalizeIncomeLayerMode(form.incomeLayerMode)\n : (incomeKnown ? (currentIncome.enabled === false ? \"disabled\" : \"enabled\") : \"\");\n renderCurrentValueSelect(\n incomeLayerModeSelect,\n incomeLayerModes,\n incomeSelected,\n incomeKnown || form.incomeLayerTouched,\n incomeLayerModeLabel,\n readback ? t(\"strategyDefault\") : t(\"notRead\"),\n );\n el(\"income-layer-mode-meta\").textContent = incomeKnown\n ? incomeLayerDefaultMetaText(incomeDefaults)\n : (readback ? t(\"strategyDefault\") : t(\"notRead\"));\n el(\"income-layer-start-meta\").textContent = t(\"incomeLayerStartMeta\");\n el(\"income-layer-ratio-meta\").textContent = t(\"incomeLayerAllocationMeta\").replace(\n \"{allocations}\",\n incomeLayerAllocationText(incomeDefaults),\n );\n } else {\n incomeLayerModeSelect.disabled = true;\n incomeLayerModeSelect.append(new Option(t(\"incomeLayerNotSupported\"), \"current\"));\n el(\"income-layer-mode-meta\").textContent = t(\"incomeLayerModeMeta\");\n el(\"income-layer-start-meta\").textContent = t(\"incomeLayerStartMeta\");\n el(\"income-layer-ratio-meta\").textContent = t(\"incomeLayerRatioMeta\");\n }\n const supportsMargin = platformSupportsMarginPolicy(platform);\n const supportsReserve = platformSupportsReservedCashPolicy(platform);\n if (supportsMargin) syncCashOnlyExecutionForAccount(platform);\n reconcileExecutionCashPolicy(form, \"margin\");\n const executionCashPolicyGrid = el(\"execution-cash-policy-grid\");\n const qmtPlatformCashNote = el(\"qmt-platform-cash-note\");\n const executionCashPolicyNote = el(\"execution-cash-policy-note\");\n executionCashPolicyGrid.hidden = !supportsMargin && !supportsReserve;\n qmtPlatformCashNote.hidden = supportsMargin || supportsReserve || platform !== \"qmt\";\n executionCashPolicyNote.hidden = !supportsMargin || !supportsReserve;\n\n const marginBlocksReserve = supportsMargin && supportsReserve && allowMarginExplicitlySelected(form);\n const reserveBlocksMargin = supportsMargin && supportsReserve && reserveCashOverrideActive(form);\n\n if (supportsReserve) {\n const reserveReadback = accountReadbackEntry(platform, account);\n const reserveKnown = Boolean(reserveReadback);\n const reservePolicy = currentReservePolicyForAccount(platform, account);\n const currentReserveMode = reservePolicy.minReservedCashUsd && reservePolicy.reservedCashRatio\n ? \"max\" : reservePolicy.minReservedCashUsd ? \"floor\" : reservePolicy.reservedCashRatio ? \"ratio\" : \"none\";\n const reserveSelected = form.reservedCashTouched ? normalizeReservePolicyMode(form.reservePolicyMode) : (reserveKnown ? currentReserveMode : \"\");\n renderCurrentValueSelect(\n reservePolicyModeSelect,\n reservePolicyModes,\n reserveSelected,\n reserveKnown || form.reservedCashTouched,\n mode => t(`reservePolicy${mode[0].toUpperCase()}${mode.slice(1)}`),\n );\n const reserveMode = normalizeReservePolicyMode(form.reservePolicyMode);\n el(\"min-reserved-cash-label\").textContent = t(\"minReservedCash\").replace(\n \"{currency}\",\n selectedCashCurrency(platform, account),\n );\n reservePolicyModeSelect.disabled = false;\n minReservedCashInput.disabled = reserveMode === \"current\" || reserveMode === \"none\" || reserveMode === \"ratio\";\n reservedCashRatioInput.disabled = reserveMode === \"current\" || reserveMode === \"none\" || reserveMode === \"floor\";\n minReservedCashInput.value = reserveMode === \"ratio\" || reserveMode === \"none\" ? \"\" : form.minReservedCashUsd;\n reservedCashRatioInput.value = reserveMode === \"floor\" || reserveMode === \"none\" ? \"\" : form.reservedCashRatio;\n el(\"reserve-policy-block\").classList.toggle(\"policy-block-muted\", marginBlocksReserve);\n el(\"min-reserve-block\").classList.toggle(\"policy-block-muted\", marginBlocksReserve);\n el(\"reserve-ratio-block\").classList.toggle(\"policy-block-muted\", marginBlocksReserve);\n el(\"reserve-policy-mode-meta\").textContent = marginBlocksReserve\n ? t(\"executionCashMarginBlocksReserve\")\n : t(\"reservedCashModeMeta\");\n } else {\n reservePolicyModeSelect.replaceChildren();\n minReservedCashInput.value = \"\";\n reservedCashRatioInput.value = \"\";\n }\n const incomeMode = normalizeIncomeLayerMode(form.incomeLayerMode);\n const incomeLayerInputsDisabled = !incomeDefaults || incomeMode === \"disabled\";\n incomeLayerStartUsdInput.disabled = incomeLayerInputsDisabled;\n incomeLayerMaxRatioInput.disabled = incomeLayerInputsDisabled;\n if (incomeDefaults && incomeMode !== \"disabled\" && !cleanDisplayNumber(form.incomeLayerStartUsd)) {\n form.incomeLayerStartUsd = String(incomeDefaults.startUsd);\n }\n if (incomeDefaults && incomeMode !== \"disabled\" && !cleanDisplayRatio(form.incomeLayerMaxRatio)) {\n form.incomeLayerMaxRatio = incomeDefaults.maxRatio;\n }\n incomeLayerStartUsdInput.value = incomeDefaults && incomeMode !== \"disabled\" ? form.incomeLayerStartUsd : \"\";\n incomeLayerMaxRatioInput.value = incomeDefaults && incomeMode !== \"disabled\" ? form.incomeLayerMaxRatio : \"\";\n\n const optionDefaults = optionOverlayDefaultForStrategy(form.strategy);\n optionOverlayModeSelect.replaceChildren();\n if (optionDefaults) {\n const optionReadback = accountReadbackEntry(platform, account);\n const optionValue = cleanOptionalBoolean(optionReadback?.option_overlay_enabled);\n const optionKnown = optionValue !== null;\n const optionSelected = form.optionOverlayTouched\n ? normalizeOptionOverlayMode(form.optionOverlayMode)\n : (optionKnown ? (optionValue ? \"enabled\" : \"disabled\") : \"\");\n renderCurrentValueSelect(\n optionOverlayModeSelect,\n optionOverlayModes,\n optionSelected,\n optionKnown || form.optionOverlayTouched,\n optionOverlayModeLabel,\n optionReadback ? t(\"strategyDefault\") : t(\"notRead\"),\n );\n el(\"option-overlay-mode-meta\").textContent = optionKnown\n ? optionOverlayDefaultMetaText(optionDefaults)\n : (optionReadback ? t(\"strategyDefault\") : t(\"notRead\"));\n } else {\n optionOverlayModeSelect.disabled = true;\n optionOverlayModeSelect.append(new Option(t(\"optionOverlayNotSupported\"), \"current\"));\n el(\"option-overlay-mode-meta\").textContent = t(\"optionOverlayModeMeta\");\n }\n\n if (supportsMargin) {\n const cashReadback = accountReadbackEntry(platform, account);\n const cashValue = cleanOptionalBoolean(cashReadback?.cash_only_execution);\n const cashKnown = cashValue !== null;\n const cashSelected = form.cashOnlyExecutionTouched\n ? normalizeCashOnlyExecutionMode(form.cashOnlyExecutionMode)\n : (cashKnown ? (cashValue ? \"enabled\" : \"disabled\") : \"\");\n renderCurrentValueSelect(\n cashOnlyExecutionModeSelect,\n cashOnlyExecutionModes,\n cashSelected,\n cashKnown || form.cashOnlyExecutionTouched,\n mode => mode === \"enabled\" ? t(\"cashOnlyExecutionNo\") : t(\"cashOnlyExecutionYes\"),\n cashReadback ? t(\"notConfigured\") : t(\"notRead\"),\n );\n el(\"cash-only-policy-block\").classList.toggle(\"policy-block-muted\", reserveBlocksMargin);\n el(\"cash-only-execution-mode-meta\").textContent = reserveBlocksMargin\n ? t(\"executionCashReserveBlocksMargin\")\n : t(\"cashOnlyExecutionModeMeta\");\n } else {\n cashOnlyExecutionModeSelect.replaceChildren();\n el(\"cash-only-execution-mode-meta\").textContent = \"\";\n }\n\n const dcaDefaults = dcaConfigForStrategy(form.strategy);\n dcaModeSelect.replaceChildren();\n const dcaAllowed = Boolean(dcaDefaults) && platformSupportsDca(platform);\n if (dcaAllowed) {\n const dcaReadback = accountReadbackEntry(platform, account);\n const dcaCurrent = currentDcaForAccount(platform, account, form.strategy);\n const dcaKnown = Boolean(dcaReadback && dcaCurrent.mode && dcaCurrent.baseInvestmentUsd);\n const dcaSelected = form.dcaTouched ? normalizeDcaMode(form.dcaMode) : (dcaKnown ? dcaCurrent.mode : \"\");\n renderCurrentValueSelect(dcaModeSelect, dcaModes, dcaSelected, dcaKnown || form.dcaTouched, dcaModeLabel);\n dcaBaseInvestmentUsdInput.disabled = !dcaKnown && !form.dcaTouched;\n dcaBaseInvestmentUsdInput.value = dcaKnown || form.dcaTouched ? form.dcaBaseInvestmentUsd : \"\";\n el(\"dca-mode-meta\").textContent = dcaKnown\n ? t(\"dcaDefaultMeta\")\n .replace(\"{mode}\", dcaModeLabel(dcaDefaults.defaultMode))\n .replace(\"{amount}\", formatUsd(dcaDefaults.defaultBaseInvestmentUsd))\n : t(\"notRead\");\n el(\"dca-base-meta\").textContent = t(\"dcaModeMeta\");\n } else {\n dcaModeSelect.disabled = true;\n dcaModeSelect.append(new Option(\n dcaDefaults && !platformSupportsDca(platform) ? t(\"dcaPlatformNotSupported\") : t(\"dcaNotSupported\"),\n \"fixed\",\n ));\n dcaBaseInvestmentUsdInput.disabled = true;\n dcaBaseInvestmentUsdInput.value = \"\";\n el(\"dca-mode-meta\").textContent = t(\"dcaModeMeta\");\n el(\"dca-base-meta\").textContent = t(\"dcaModeMeta\");\n }\n\n const supportedModes = supportedExecutionModesForPlatform(platform);\n const liveModeAvailable = supportedModes.includes(\"live\") && hasLiveStrategyOption(platform, account);\n const executionModeKnown = Boolean(form.executionMode || form.executionModeTouched);\n renderCurrentValueSelect(\n executionModeSelect,\n supportedModes,\n form.executionMode,\n executionModeKnown,\n mode => mode === \"live\" ? t(\"executionModeLive\") : t(\"executionModeDryRun\"),\n );\n for (const option of executionModeSelect.options) {\n option.disabled = option.value === \"live\" && !liveModeAvailable;\n }\n const displayedMode = executionEnvironmentForAccount(platform, account);\n el(\"mode-display\").textContent = modeLabel(displayedMode);\n el(\"mode-meta\").textContent = !executionModeKnown\n ? t(\"notRead\")\n : (!supportedModes.includes(\"live\")\n ? t(\"qmtDryRunOnlyNote\")\n : (!liveModeAvailable ? t(binanceResumeDigest() ? \"binanceResumeModeHint\" : \"liveModeUnavailable\") : \"\"));\n }\n\n function renderSummary() {\n const showSummary = hasPrivateConfig();\n const summaryPanel = document.querySelector(\".summary-panel\");\n const switchSurface = document.querySelector(\".switch-surface\");\n summaryPanel.hidden = !showSummary;\n switchSurface.classList.toggle(\"summary-hidden\", !showSummary);\n if (!showSummary) return;\n\n const inputs = buildInputs();\n const list = el(\"summary-list\");\n list.replaceChildren();\n document.querySelector(\".summary-head h2\").textContent = t(\"summary\");\n const currentHeading = document.createElement(\"p\");\n currentHeading.className = \"summary-section-title\";\n currentHeading.textContent = t(\"summaryCurrent\");\n list.appendChild(currentHeading);\n const detail = document.createElement(\"details\");\n detail.className = \"summary-details\";\n const detailLabel = document.createElement(\"summary\");\n detailLabel.textContent = t(\"configDetails\");\n detail.append(detailLabel);\n const primaryLabels = new Set([t(\"selectedAccount\"), t(\"currentStrategy\"), t(\"currentRuntimeTarget\")]);\n let pendingSectionInserted = false;\n for (const [label, value, rowClass, valueTone] of summaryRows(inputs)) {\n if (!pendingSectionInserted && rowClass === \"pending\") {\n const pendingHeading = document.createElement(\"p\");\n pendingHeading.className = \"summary-section-title\";\n pendingHeading.textContent = t(\"summaryPending\");\n list.appendChild(pendingHeading);\n pendingSectionInserted = true;\n }\n const row = document.createElement(\"div\");\n row.className = \"summary-row\";\n row.setAttribute(\"role\", \"listitem\");\n if (rowClass) row.classList.add(rowClass);\n const labelNode = document.createElement(\"div\");\n labelNode.className = \"summary-label\";\n labelNode.textContent = label;\n const valueNode = document.createElement(\"div\");\n valueNode.className = \"summary-value\";\n if (valueTone) {\n const badge = document.createElement(\"span\");\n badge.className = `summary-status ${valueTone}`;\n badge.textContent = value;\n valueNode.appendChild(badge);\n } else {\n valueNode.textContent = value;\n }\n row.append(labelNode, valueNode);\n if (rowClass === \"pending\" || primaryLabels.has(label)) list.appendChild(row);\n else detail.appendChild(row);\n }\n list.appendChild(detail);\n\n const account = selectedAccount();\n const currentMode = executionEnvironmentForAccount(state.selected, account);\n el(\"mode-pill\").textContent = currentMode ? modeLabel(currentMode) : t(\"notRead\");\n }\n\n function renderAuth() {\n const status = el(\"auth-status\");\n const loginLink = el(\"login-link\");\n const logoutButton = el(\"logout-button\");\n const signedIn = Boolean(state.auth.allowed && state.auth.login);\n\n status.hidden = !signedIn;\n status.textContent = signedIn ? t(\"signedInAs\").replace(\"{login}\", state.auth.login) : \"\";\n loginLink.hidden = signedIn;\n loginLink.href = \"/login\";\n loginLink.textContent = t(\"login\");\n logoutButton.hidden = !signedIn;\n logoutButton.textContent = t(\"logout\");\n\n const dispatch = el(\"dispatch-button\");\n const hasPrivateAccounts = state.configSource === \"private\";\n const loadingConfig = state.configSource === \"loading\";\n const stopOnlySelection = normalizeRuntimeTargetMode(state.forms[state.selected]?.runtimeTargetMode) === \"disabled\"\n && Boolean(selectedAccount(state.selected)?.target_name);\n const hasRunnableStrategy = hasRunnableStrategySelection();\n const hasValidReserve = hasValidExecutionCashPolicy();\n const hasValidIncomeLayer = hasValidIncomeLayerPolicy();\n const hasValidOptionOverlay = hasValidOptionOverlayPolicy();\n const hasValidDca = hasValidDcaPolicy();\n const hasValidStrategy = hasRunnableStrategy &&\n hasValidReserve &&\n hasValidIncomeLayer &&\n hasValidOptionOverlay &&\n hasValidDca;\n const hasPendingChange = hasPrivateAccounts && hasValidStrategy && hasPendingChanges(buildInputs());\n if (stopOnlySelection) {\n dispatch.disabled = !state.auth.allowed || loadingConfig || !hasPrivateAccounts || runtimeStopLock.pending;\n dispatch.textContent = state.auth.allowed\n ? (loadingConfig ? t(\"loadingConfig\") : (hasPrivateAccounts ? t(\"runSwitch\") : t(\"configureAccounts\")))\n : t(\"loginToRun\");\n } else {\n dispatch.disabled = !state.auth.allowed || loadingConfig || !hasPrivateAccounts || !hasValidStrategy || !hasPendingChange;\n dispatch.textContent = state.auth.allowed\n ? (loadingConfig\n ? t(\"loadingConfig\")\n : (hasPrivateAccounts ? (hasValidStrategy ? (hasPendingChange ? t(\"runSwitch\") : t(\"noChanges\")) : t(\"configureAccounts\")) : t(\"configureAccounts\")))\n : t(\"loginToRun\");\n }\n const note = el(\"action-note\");\n if (stopOnlySelection && state.auth.allowed && !loadingConfig && hasPrivateAccounts) {\n note.textContent = t(\"runtimeStopReadyNote\");\n note.classList.toggle(\"warning\", false);\n } else {\n note.textContent = state.auth.allowed\n ? (loadingConfig\n ? t(\"loadingConfigNote\")\n : (hasPrivateAccounts\n ? (hasRunnableStrategy\n ? (hasValidReserve\n ? (hasValidIncomeLayer\n ? (hasValidOptionOverlay\n ? (hasValidDca ? (hasPendingChange ? t(\"readyNote\") : \"\") : t(\"invalidDcaNote\"))\n : t(\"invalidOptionOverlayNote\"))\n : t(\"invalidIncomeLayerNote\"))\n : (executionCashPolicyConflict(state.forms[state.selected])\n ? t(\"invalidExecutionCashPolicyNote\")\n : t(\"invalidReservePolicyNote\")))\n : strategyActionNoteText())\n : t(\"missingConfigNote\")))\n : t(\"readonlyNote\");\n note.classList.toggle(\n \"warning\",\n state.auth.allowed && !loadingConfig && (!hasPrivateAccounts || !hasValidStrategy),\n );\n }\n }\n\n function renderAppVisibility() {\n document.body.classList.toggle(\"app-loading\", !state.appReady);\n el(\"boot-message\").textContent = t(state.bootMessageKey);\n el(\"app-shell\").hidden = !state.appReady || !state.auth.allowed;\n el(\"login-screen\").hidden = !state.appReady || state.auth.allowed;\n el(\"login-message\").textContent = t(!state.auth.available\n ? \"loginUnavailable\" : state.auth.login ? \"loginDenied\" : \"loginDescription\");\n el(\"login-link\").hidden = true;\n }\n\n function normalizeControlPlanePayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid control plane payload\");\n const candidates = Array.isArray(payload.candidates) ? payload.candidates : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n attention: payload.attention && typeof payload.attention === \"object\" && !Array.isArray(payload.attention)\n ? {\n status: [\"research_only\", \"attention_required\", \"unavailable\"].includes(payload.attention.status)\n ? payload.attention.status\n : \"unavailable\",\n reason_codes: Array.isArray(payload.attention.reason_codes) ? payload.attention.reason_codes : [],\n }\n : { status: \"unavailable\", reason_codes: [\"control_plane_attention_missing\"] },\n candidates: candidates.filter((item) => item && typeof item === \"object\" && item.lifecycle && typeof item.lifecycle === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function normalizeOwnerDecisionQueue(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid owner decision queue\");\n const candidates = Array.isArray(payload.candidates) ? payload.candidates : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n candidates: candidates.filter((entry) => entry && typeof entry === \"object\"\n && entry.candidate && typeof entry.candidate === \"object\"\n && typeof entry.candidate_evidence_sha256 === \"string\"),\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function ownerDecisionEntry(candidateId) {\n return state.ownerDecisions.candidates.find((entry) => entry.candidate?.candidate_id === candidateId) || null;\n }\n\n function ownerDecisionLabel(decision) {\n return {\n approve_limited_live_canary: t(\"ownerDecisionApprove\"),\n keep_parked: t(\"ownerDecisionPark\"),\n retire_candidate: t(\"ownerDecisionRetire\"),\n }[decision] || String(decision || \"—\");\n }\n\n const operatorLabels = {\n kind: {\n individual: { zh: \"策略\", en: \"Strategy\" },\n portfolio: { zh: \"组合\", en: \"Portfolio\" },\n plugin: { zh: \"插件\", en: \"Plugin\" },\n },\n status: {\n research: { zh: \"观察中\", en: \"Monitoring\" },\n evidence_pending: { zh: \"待复核\", en: \"To review\" },\n verified: { zh: \"正常\", en: \"Normal\" },\n deferred: { zh: \"待复核\", en: \"To review\" },\n parked: { zh: \"已暂停\", en: \"Paused\" },\n paper: { zh: \"测试中\", en: \"Testing\" },\n shadow: { zh: \"观察中\", en: \"Monitoring\" },\n owner_decision_required: { zh: \"等待处理\", en: \"Needs attention\" },\n },\n action: {\n keep_research: { zh: \"继续观察\", en: \"Keep monitoring\" },\n defer: { zh: \"稍后复核\", en: \"Review later\" },\n park: { zh: \"保持暂停\", en: \"Keep paused\" },\n auto_paper_evaluation: { zh: \"继续测试\", en: \"Continue testing\" },\n auto_shadow_evaluation: { zh: \"继续观察\", en: \"Keep monitoring\" },\n owner_live_decision: { zh: \"需要确认\", en: \"Confirmation needed\" },\n none: { zh: \"暂无操作\", en: \"No action\" },\n },\n freshness: {\n fresh: { zh: \"最新\", en: \"Current\" },\n stale: { zh: \"更新延迟\", en: \"Delayed\" },\n unavailable: { zh: \"暂不可用\", en: \"Unavailable\" },\n unknown: { zh: \"暂不可用\", en: \"Unavailable\" },\n },\n };\n\n function operatorLabel(group, value) {\n const label = operatorLabels[group]?.[value];\n return label ? (state.lang === \"zh\" ? label.zh : label.en) : \"—\";\n }\n\n function controlPlaneDataStatusText(status) {\n return status === \"ready\"\n ? t(\"controlDataReady\")\n : (status === \"stale\" ? t(\"controlDataStale\") : t(\"controlDataUnavailable\"));\n }\n\n function controlPlaneAttentionText(attention) {\n const status = attention?.status || \"unavailable\";\n if (status === \"research_only\") return t(\"controlAttentionResearchOnly\");\n if (status === \"attention_required\") return t(\"controlAttentionRequired\");\n return t(\"controlAttentionUnavailable\");\n }\n\n function candidateNeedsOperatorAction(item) {\n const decision = ownerDecisionEntry(item?.candidate_id);\n return state.controlPlane.payload.data_status === \"ready\"\n && state.ownerDecisions.data_status === \"ready\"\n && item?.freshness?.status === \"fresh\"\n && item?.lifecycle?.stage === \"P6\"\n && item.lifecycle.status === \"owner_decision_required\"\n && item?.recommendation?.code === \"owner_live_decision\"\n && Boolean(decision)\n && !decision.intent;\n }\n\n function isParkedResearchResult(item) {\n return item?.source_id === \"aiaudit.soxl_manual_validation\"\n && item?.lifecycle?.stage === \"P3\"\n && item.lifecycle.status === \"parked\"\n && item?.recommendation?.code === \"park\";\n }\n\n function candidateIsControlPlaneVisible(item) {\n return candidateNeedsOperatorAction(item);\n }\n\n function candidateIsDecisionBackgroundVisible(item) {\n return Boolean(item?.forward_observation)\n || Boolean(ownerDecisionEntry(item?.candidate_id)?.intent)\n || item?.lifecycle?.status === \"owner_decision_required\"\n || item?.recommendation?.code === \"owner_live_decision\";\n }\n\n function parkedResearchResultSourceUrl(item) {\n if (!isParkedResearchResult(item)) return \"\";\n const runId = String(item?.evidence?.p3_evidence_id || \"\").trim();\n return /^\\d{6,20}$/.test(runId)\n ? `https://github.com/QuantStrategyLab/AIAuditBridge/actions/runs/${runId}`\n : \"\";\n }\n\n function parkedResearchResultReason(item) {\n const reason = String(item?.recommendation?.reason || \"\").trim();\n return reason || t(\"parkedResearchResultFallback\");\n }\n\n function renderParkedResearchResults() {\n const board = el(\"parked-research-results\");\n const list = el(\"parked-research-results-list\");\n const results = state.controlPlane.payload.candidates.filter(isParkedResearchResult);\n board.hidden = !state.auth.allowed || !results.length;\n list.replaceChildren();\n for (const item of results) {\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"parkedResearchResultsTitle\");\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = t(\"parkedResearchResultTitle\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = parkedResearchResultReason(item);\n main.append(meta, title, reason);\n const sourceUrl = parkedResearchResultSourceUrl(item);\n if (sourceUrl) {\n const source = document.createElement(\"a\");\n source.className = \"health-card__meta\";\n source.href = sourceUrl;\n source.target = \"_blank\";\n source.rel = \"noreferrer\";\n source.textContent = t(\"parkedResearchResultSource\");\n main.appendChild(source);\n }\n const status = document.createElement(\"div\");\n status.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"parkedResearchResultsTitle\");\n const stage = document.createElement(\"strong\");\n stage.textContent = t(\"parkedResearchResultStatus\");\n status.append(label, stage);\n card.append(main, status);\n list.appendChild(card);\n }\n }\n\n function forwardObservationDisplayText(observation) {\n if (!observation || typeof observation !== \"object\") return \"\";\n return t(\"forwardObservationProgress\")\n .replace(\"{completed}\", String(observation.observations_completed ?? \"—\"))\n .replace(\"{required}\", String(observation.required_trading_sessions ?? \"—\"))\n .replace(\"{session}\", String(observation.last_observed_session || \"—\"));\n }\n\n function forwardObservationActionText(observation) {\n if (observation?.state === \"FORWARD_COMPLETE_HUMAN_REVIEW\") return t(\"forwardObservationComplete\");\n if (observation?.state === \"FORWARD_ACTIVE\") return t(\"forwardObservationActive\");\n return t(\"forwardObservationPaused\");\n }\n\n function renderControlPlaneHeading({ hasActionable, hasForwardObservation }) {\n const title = el(\"control-plane-view-title\");\n const subtitle = title?.nextElementSibling;\n const board = el(\"control-queue-title\");\n if (hasActionable && hasForwardObservation) {\n title.textContent = t(\"controlPlaneMixedTitle\");\n subtitle.textContent = t(\"controlPlaneMixedSubtitle\");\n board.textContent = t(\"controlMixedBoard\");\n } else if (hasForwardObservation) {\n title.textContent = t(\"controlPlaneProgressTitle\");\n subtitle.textContent = t(\"controlPlaneProgressSubtitle\");\n board.textContent = t(\"controlProgressBoard\");\n } else {\n title.textContent = t(\"controlPlaneTitle\");\n subtitle.textContent = t(\"controlPlaneSubtitle\");\n board.textContent = t(\"controlCandidateBoard\");\n }\n }\n\n function controlPlaneSourceCondition(payload, ownerDecisions, recoveryPayload) {\n const sources = [payload, ownerDecisions, recoveryPayload];\n const unavailable = sources.some((source) => source?.data_status === \"unavailable\");\n const stale = !unavailable && sources.some((source) => source?.data_status === \"stale\");\n const needsReview = sources.some((source) => Boolean(source?.errors?.length));\n return {\n status: unavailable ? \"unavailable\" : (stale || needsReview ? \"stale\" : \"ready\"),\n unavailable,\n stale,\n needsReview,\n };\n }\n\n function renderControlPlane() {\n const payload = state.controlPlane.payload;\n const pendingRecoveries = state.reconciliationRecovery.payload.recoveries.filter(recoveryNeedsOperatorAction);\n const actionableCandidates = payload.candidates.filter(candidateNeedsOperatorAction);\n const backgroundCandidates = payload.candidates.filter((item) =>\n !candidateNeedsOperatorAction(item) && candidateIsDecisionBackgroundVisible(item));\n const actionableCount = actionableCandidates.length + pendingRecoveries.length;\n const sourceCondition = controlPlaneSourceCondition(\n payload,\n state.ownerDecisions,\n state.reconciliationRecovery.payload,\n );\n const decisionStatus = actionableCount ? \"ready\" : sourceCondition.status;\n el(\"control-plane-status\").textContent = controlPlaneDataStatusText(decisionStatus);\n\n const notice = el(\"control-plane-notice\");\n const statePanel = notice.closest(\".decision-state\");\n renderControlPlaneHeading({ hasActionable: actionableCount > 0, hasForwardObservation: false });\n el(\"control-plane-view\").hidden = !state.auth.allowed;\n const queue = el(\"control-plane-queue\");\n queue.hidden = !actionableCandidates.length;\n statePanel.classList.toggle(\"is-attention\", actionableCount > 0);\n statePanel.classList.toggle(\"is-stale\", !actionableCount && decisionStatus === \"stale\");\n statePanel.classList.toggle(\"is-unavailable\", !state.auth.allowed || (!actionableCount && sourceCondition.unavailable));\n const stateMark = statePanel.querySelector(\".decision-state__mark\");\n stateMark.textContent = !state.auth.allowed || (!actionableCount && sourceCondition.unavailable)\n ? \"i\"\n : ((actionableCount > 0 || decisionStatus === \"stale\") ? \"!\" : \"✓\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"controlLoginNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlLoginSummary\");\n } else if (actionableCount > 0) {\n notice.textContent = t(\"controlAttentionNotice\")\n .replace(\"{count}\", String(actionableCount));\n el(\"control-plane-summary\").textContent = t(\"controlAttentionSummary\");\n } else if (sourceCondition.unavailable) {\n notice.textContent = t(\"controlUnavailableNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlUnavailableSummary\");\n } else if (sourceCondition.stale) {\n notice.textContent = t(\"controlStaleNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlStaleSummary\");\n } else if (sourceCondition.needsReview) {\n notice.textContent = t(\"controlUpstreamNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlStaleSummary\");\n } else {\n notice.textContent = t(\"controlNormalNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlNormalSummary\");\n }\n\n const list = el(\"control-plane-list\");\n list.replaceChildren();\n for (const item of actionableCandidates) {\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = `${operatorLabel(\"kind\", item.candidate_kind)} · ${domainLabel(item.domain || \"\")}`;\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = String(item.candidate_id || \"unknown\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = item.forward_observation\n ? forwardObservationActionText(item.forward_observation)\n : (isParkedResearchResult(item) ? parkedResearchResultReason(item) : t(\"controlAttentionSummary\"));\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"controlItemMeta\")\n .replace(\"{kind}\", operatorLabel(\"status\", item.lifecycle?.status))\n .replace(\"{domain}\", domainLabel(item.domain || \"\"))\n .replace(\"{freshness}\", operatorLabel(\"freshness\", item.freshness?.status || \"unknown\"));\n main.append(meta, title, reason, detail);\n if (item.forward_observation) {\n const observation = document.createElement(\"div\");\n observation.className = \"health-card__meta\";\n observation.textContent = forwardObservationDisplayText(item.forward_observation);\n main.appendChild(observation);\n }\n const parkedResultUrl = parkedResearchResultSourceUrl(item);\n if (parkedResultUrl) {\n const source = document.createElement(\"a\");\n source.className = \"health-card__meta\";\n source.href = parkedResultUrl;\n source.target = \"_blank\";\n source.rel = \"noreferrer\";\n source.textContent = t(\"parkedResearchResultSource\");\n main.appendChild(source);\n }\n const stateBlock = document.createElement(\"div\");\n stateBlock.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"controlNext\");\n const stage = document.createElement(\"strong\");\n stage.textContent = item.forward_observation\n ? forwardObservationActionText(item.forward_observation)\n : operatorLabel(\"action\", item.recommendation?.code || \"none\");\n const recommendation = document.createElement(\"small\");\n recommendation.textContent = `${t(\"controlStatus\")}:${operatorLabel(\"status\", item.lifecycle?.status)}`;\n stateBlock.append(label, stage, recommendation);\n const ownerEntry = ownerDecisionEntry(item.candidate_id);\n if (ownerEntry) {\n const ownerDecision = document.createElement(\"div\");\n ownerDecision.className = \"owner-decision\";\n const ownerTitle = document.createElement(\"strong\");\n ownerTitle.textContent = t(\"ownerDecisionTitle\");\n const ownerDetail = document.createElement(\"small\");\n if (ownerEntry.intent) {\n ownerDetail.textContent = t(\"ownerDecisionRecorded\")\n .replace(\"{decision}\", ownerDecisionLabel(ownerEntry.intent.decision));\n } else if (!state.auth.admin) {\n ownerDetail.textContent = t(\"ownerDecisionAdminOnly\");\n } else {\n ownerDetail.textContent = t(\"ownerDecisionReady\");\n }\n ownerDecision.append(ownerTitle, ownerDetail);\n if (!ownerEntry.intent && state.auth.admin) {\n const actions = document.createElement(\"div\");\n actions.className = \"owner-decision__actions\";\n const submitting = state.ownerDecisions.submittingCandidateId === item.candidate_id;\n for (const [decision, labelKey] of [\n [\"approve_limited_live_canary\", \"ownerDecisionApprove\"],\n [\"keep_parked\", \"ownerDecisionPark\"],\n [\"retire_candidate\", \"ownerDecisionRetire\"],\n ]) {\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"owner-decision__button\";\n button.dataset.ownerDecision = decision;\n button.dataset.candidateId = item.candidate_id;\n button.dataset.candidateEvidenceSha256 = ownerEntry.candidate_evidence_sha256;\n button.disabled = submitting;\n button.textContent = submitting ? t(\"ownerDecisionSubmitting\") : t(labelKey);\n actions.appendChild(button);\n }\n ownerDecision.appendChild(actions);\n }\n main.appendChild(ownerDecision);\n }\n card.append(main, stateBlock);\n list.appendChild(card);\n }\n\n const progressList = el(\"control-plane-progress-list\");\n progressList.replaceChildren();\n for (const item of backgroundCandidates) {\n const card = document.createElement(\"article\");\n card.className = \"health-card is-background\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = String(item.candidate_id || \"unknown\");\n const detail = document.createElement(\"p\");\n detail.className = \"health-card__reason\";\n const recordedDecision = ownerDecisionEntry(item.candidate_id)?.intent?.decision;\n detail.textContent = item.forward_observation\n ? forwardObservationDisplayText(item.forward_observation)\n : (recordedDecision\n ? t(\"ownerDecisionRecorded\").replace(\"{decision}\", ownerDecisionLabel(recordedDecision))\n : t(\"controlStaleSummary\"));\n main.append(title, detail);\n card.appendChild(main);\n progressList.appendChild(card);\n }\n el(\"decision-background\").hidden = !backgroundCandidates.length\n && !state.reconciliationRecovery.payload.recoveries.some((entry) => !recoveryNeedsOperatorAction(entry));\n }\n\n function normalizeReconciliationRecoveryPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new Error(\"invalid reconciliation recovery payload\");\n }\n const recoveries = Array.isArray(payload.recoveries) ? payload.recoveries : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n recoveries: recoveries.filter((entry) => entry && typeof entry === \"object\"\n && entry.recovery && typeof entry.recovery === \"object\"\n && entry.recovery.dual_review && typeof entry.recovery.dual_review === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function recoveryNeedsOperatorAction(entry) {\n const recovery = entry?.recovery || {};\n return state.reconciliationRecovery.payload.data_status === \"ready\"\n && entry?.freshness?.data_status === \"ready\"\n && !entry?.confirmation\n && recovery.readiness === \"awaiting_human_confirmation\"\n && Array.isArray(recovery.blocker_codes)\n && recovery.blocker_codes.length === 0\n && Boolean(recovery.candidate_sha256)\n && recovery.dual_review?.evidence_binding_sha256 === recovery.candidate_sha256;\n }\n\n function recoveryConfirmationAvailableToCurrentUser(entry) {\n return recoveryNeedsOperatorAction(entry) && state.auth.admin;\n }\n\n function renderReconciliationRecovery() {\n const payload = state.reconciliationRecovery.payload;\n const pending = payload.recoveries.filter(recoveryNeedsOperatorAction);\n const history = payload.recoveries.filter((entry) => !recoveryNeedsOperatorAction(entry));\n el(\"reconciliation-recovery-board\").hidden = !state.auth.allowed || !pending.length;\n const notice = el(\"reconciliation-recovery-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"reconciliationRecoveryLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"reconciliationRecoveryStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"reconciliationRecoveryUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"reconciliationRecoveryUpstreamNotice\").replace(\"{count}\", payload.errors.length);\n } else {\n notice.textContent = t(\"reconciliationRecoveryNoOrder\");\n }\n const list = el(\"reconciliation-recovery-list\");\n list.replaceChildren();\n const historyList = el(\"reconciliation-recovery-history-list\");\n historyList.replaceChildren();\n const renderEntry = (entry, target) => {\n const recovery = entry.recovery || {};\n const card = document.createElement(\"article\");\n card.className = `health-card${recoveryNeedsOperatorAction(entry) ? \"\" : \" is-background\"}`;\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"reconciliationRecoveryMeta\")\n .replace(\"{strategy}\", strategyLabel(recovery.strategy_profile || \"unknown\"));\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n const platformKey = String(recovery.platform || \"\").toLowerCase();\n const platformLabel = platformMeta[platformKey]?.label || recovery.platform || t(\"commonUnknown\");\n title.textContent = t(\"reconciliationRecoveryTitle\").replace(\"{platform}\", platformLabel);\n const detail = document.createElement(\"p\");\n detail.className = \"health-card__reason\";\n const ready = recoveryNeedsOperatorAction(entry);\n detail.textContent = entry.confirmation\n ? t(\"reconciliationRecoveryConfirmed\")\n : (ready ? t(\"reconciliationRecoveryReason\") : t(\"reconciliationRecoveryBlocked\")\n .replace(\"{blockers}\", (recovery.blocker_codes || []).join(\", \") || recovery.readiness || \"unknown\"));\n const impact = document.createElement(\"p\");\n impact.className = \"health-card__meta decision-impact\";\n impact.textContent = t(\"reconciliationRecoveryImpact\");\n const technical = document.createElement(\"details\");\n technical.className = \"decision-technical-details\";\n const technicalSummary = document.createElement(\"summary\");\n technicalSummary.textContent = t(\"reconciliationRecoveryTechnicalDetails\");\n const technicalBody = document.createElement(\"p\");\n technicalBody.textContent = `${recovery.recovery_id || \"unknown\"} · ${t(\"reconciliationRecoveryDetail\")\n .replace(\"{state}\", recovery.reconciliation_state || \"unknown\")\n .replace(\"{samples}\", String(recovery.evidence_sample_count || 0))\n .replace(\"{review}\", recovery.dual_review?.outcome || \"unknown\")\n .replace(\"{lastObserved}\", recovery.last_observed_at || \"—\")}`;\n technical.append(technicalSummary, technicalBody);\n const status = document.createElement(\"div\");\n status.className = \"health-card__meta\";\n if (entry.confirmation) {\n status.textContent = t(\"reconciliationRecoveryConfirmed\");\n } else if (!ready) {\n status.textContent = t(\"reconciliationRecoveryBlocked\")\n .replace(\"{blockers}\", (recovery.blocker_codes || []).join(\", \") || recovery.readiness || \"unknown\");\n } else if (!state.auth.admin) {\n status.textContent = t(\"reconciliationRecoveryAdminOnly\");\n }\n main.append(meta, title, detail, impact);\n if (status.textContent) main.appendChild(status);\n main.appendChild(technical);\n if (recoveryConfirmationAvailableToCurrentUser(entry)) {\n const actions = document.createElement(\"div\");\n actions.className = \"owner-decision__actions\";\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"owner-decision__button\";\n button.dataset.reconciliationRecoveryConfirm = \"true\";\n button.dataset.recoveryId = recovery.recovery_id || \"\";\n button.dataset.candidateSha256 = recovery.candidate_sha256 || \"\";\n button.dataset.dualReviewBindingSha256 = recovery.dual_review?.evidence_binding_sha256 || \"\";\n const submitting = state.reconciliationRecovery.submittingRecoveryId === recovery.recovery_id;\n button.disabled = submitting;\n button.textContent = submitting ? t(\"reconciliationRecoverySubmitting\") : t(\"reconciliationRecoveryConfirm\");\n actions.appendChild(button);\n main.appendChild(actions);\n }\n const stateBlock = document.createElement(\"div\");\n stateBlock.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"controlNext\");\n const stateText = document.createElement(\"strong\");\n stateText.textContent = entry.confirmation\n ? t(\"recoveryConfirmedStatus\")\n : (ready ? t(\"recoveryReadyStatus\") : t(\"recoveryBlockedStatus\"));\n const freshness = document.createElement(\"small\");\n freshness.textContent = controlPlaneDataStatusText(entry.freshness?.data_status);\n stateBlock.append(label, stateText, freshness);\n card.append(main, stateBlock);\n target.appendChild(card);\n };\n for (const entry of pending) renderEntry(entry, list);\n for (const entry of history) renderEntry(entry, historyList);\n if (!pending.length && !history.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"reconciliationRecoveryEmpty\");\n historyList.appendChild(empty);\n }\n el(\"decision-background\").hidden = !history.length\n && !state.controlPlane.payload.candidates.some((item) =>\n !candidateNeedsOperatorAction(item) && candidateIsDecisionBackgroundVisible(item));\n }\n\n function clearBinancePrivateScope(status = \"not_available\") {\n binancePrivateScopeRequestGeneration += 1;\n state.binancePrivateScope = { status, report: null };\n el(\"binance-private-scope-list\")?.replaceChildren();\n }\n\n function normalizeBinancePrivateScopePayload(payload) {\n if (!payload || payload.ok !== true || !(\"report\" in payload)) {\n throw new Error(\"invalid Binance private scope payload\");\n }\n if (payload.report === null) return null;\n const report = payload.report;\n if (!report || typeof report !== \"object\" || Array.isArray(report) || report.platform !== \"binance\" || !Array.isArray(report.assets)) {\n throw new Error(\"invalid Binance private scope report\");\n }\n return {\n observed_at: String(report.observed_at || \"\"),\n assets: report.assets.map((item) => {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n throw new Error(\"invalid Binance private scope asset\");\n }\n return {\n asset: String(item.asset || \"\"),\n free: String(item.free || \"\"),\n locked: String(item.locked || \"\"),\n };\n }),\n };\n }\n\n function binancePrivateScopeShouldShow(currentState) {\n return Boolean(\n currentState?.auth?.allowed\n && currentState?.auth?.admin\n && currentState.selected === \"binance\"\n && currentState.binancePrivateScope?.report,\n );\n }\n\n function renderBinancePrivateScope() {\n const board = el(\"binance-private-scope-board\");\n const { status, report } = state.binancePrivateScope;\n board.hidden = !binancePrivateScopeShouldShow(state);\n const list = el(\"binance-private-scope-list\");\n list.replaceChildren();\n if (board.hidden) return;\n const notice = el(\"binance-private-scope-notice\");\n if (status === \"not_available\") {\n notice.textContent = t(\"binancePrivateScopeUnavailable\");\n return;\n }\n if (!report) {\n notice.textContent = t(\"binancePrivateScopeEmpty\");\n return;\n }\n notice.textContent = t(\"binancePrivateScopeObservedAt\").replace(\"{time}\", report.observed_at || \"—\");\n const account = document.createElement(\"p\");\n account.className = \"binance-private-scope__account\";\n account.textContent = `${t(\"binancePrivateScopeAccount\")} · ${t(\"binancePrivateScopePrivateIdentity\")}`;\n const warning = document.createElement(\"p\");\n warning.className = \"binance-private-scope__warning\";\n warning.textContent = t(\"binancePrivateScopeHistoricalWarning\");\n list.append(account, warning);\n if (!report.assets.length) return;\n const tableWrap = document.createElement(\"div\");\n tableWrap.className = \"binance-private-scope__table-wrap\";\n const table = document.createElement(\"table\");\n table.className = \"binance-private-scope__table\";\n const head = document.createElement(\"thead\");\n const headRow = document.createElement(\"tr\");\n for (const label of [\"binancePrivateScopeAsset\", \"binancePrivateScopeFree\", \"binancePrivateScopeLocked\"]) {\n const cell = document.createElement(\"th\");\n cell.scope = \"col\";\n cell.textContent = t(label);\n headRow.appendChild(cell);\n }\n head.appendChild(headRow);\n const body = document.createElement(\"tbody\");\n for (const asset of report.assets) {\n const row = document.createElement(\"tr\");\n for (const value of [asset.asset, asset.free, asset.locked]) {\n const cell = document.createElement(\"td\");\n cell.textContent = value;\n row.appendChild(cell);\n }\n body.appendChild(row);\n }\n table.append(head, body);\n tableWrap.appendChild(table);\n list.appendChild(tableWrap);\n }\n\n const M0_RESEARCH_DISPLAY_LIMIT = 100;\n\n const m0ResearchLabels = {\n subject: {\n asset_idea: { zh: \"资产观察\", en: \"Asset idea\" },\n theme_context: { zh: \"主题背景\", en: \"Theme context\" },\n strategy_hypothesis: { zh: \"研究假设\", en: \"Research hypothesis\" },\n risk_context: { zh: \"风险背景\", en: \"Risk context\" },\n },\n state: {\n candidate: { zh: \"待验证\", en: \"Candidate\" },\n source_verification_required: { zh: \"等待来源核验\", en: \"Source verification required\" },\n deferred: { zh: \"暂缓\", en: \"Deferred\" },\n context_only: { zh: \"仅作背景\", en: \"Context only\" },\n },\n freshness: {\n fresh: { zh: \"有效\", en: \"Fresh\" },\n stale: { zh: \"已过期\", en: \"Stale\" },\n unknown: { zh: \"未知\", en: \"Unknown\" },\n },\n horizon: {\n short: { zh: \"短期\", en: \"Short\" },\n medium: { zh: \"中期\", en: \"Medium\" },\n long: { zh: \"长期\", en: \"Long\" },\n not_applicable: { zh: \"不适用\", en: \"Not applicable\" },\n },\n confidence: {\n high: { zh: \"高\", en: \"High\" },\n medium: { zh: \"中\", en: \"Medium\" },\n low: { zh: \"低\", en: \"Low\" },\n mixed: { zh: \"混合\", en: \"Mixed\" },\n no_event: { zh: \"无事件\", en: \"No event\" },\n unknown: { zh: \"未知\", en: \"Unknown\" },\n },\n style: {\n event_driven: { zh: \"事件驱动\", en: \"Event driven\" },\n long_horizon_growth: { zh: \"长期成长\", en: \"Long-horizon growth\" },\n value_quality: { zh: \"价值质量\", en: \"Value quality\" },\n macro_context: { zh: \"宏观背景\", en: \"Macro context\" },\n mixed_research: { zh: \"综合研究\", en: \"Mixed research\" },\n },\n conflict: {\n none: { zh: \"无\", en: \"None\" },\n conflict: { zh: \"存在\", en: \"Present\" },\n unavailable: { zh: \"不可用\", en: \"Unavailable\" },\n },\n drift: {\n none: { zh: \"无\", en: \"None\" },\n drift: { zh: \"存在\", en: \"Present\" },\n unavailable: { zh: \"不可用\", en: \"Unavailable\" },\n },\n };\n\n function m0ResearchLabel(group, value) {\n const entry = m0ResearchLabels[group]?.[value];\n return entry ? (state.lang === \"zh\" ? entry.zh : entry.en) : \"—\";\n }\n\n function m0ResearchTimestamp(value) {\n return formatDateTime(value);\n }\n\n function m0ResearchHorizons(values) {\n if (!Array.isArray(values) || !values.length) return \"—\";\n const labels = values.map((value) => m0ResearchLabel(\"horizon\", value)).filter((value) => value !== \"—\");\n return labels.length ? labels.join(\" / \") : \"—\";\n }\n\n function m0ResearchEntries(subjects) {\n if (!Array.isArray(subjects)) return [];\n const entries = [];\n for (const item of subjects) {\n if (!item || typeof item !== \"object\" || !item.subject || typeof item.subject !== \"object\") continue;\n if (!Array.isArray(item.observations)) continue;\n for (const observation of item.observations) {\n if (!observation || typeof observation !== \"object\" || !observation.research_context) continue;\n entries.push({\n subject: item.subject,\n observation,\n horizonConflict: item.horizon_conflict,\n historicalStaleHorizonDrift: item.historical_stale_horizon_drift,\n });\n }\n }\n return entries;\n }\n\n function normalizeM0ResearchPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid M0 research payload\");\n const subjects = Array.isArray(payload.subjects) ? payload.subjects : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n viewed_at: typeof payload.viewed_at === \"string\" ? payload.viewed_at : null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n subjects: subjects.filter((item) => item && typeof item === \"object\"\n && item.subject && typeof item.subject === \"object\" && Array.isArray(item.observations)),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function renderM0Research() {\n const payload = state.m0Research.payload;\n const entries = m0ResearchEntries(payload.subjects);\n const shownEntries = entries.slice(0, M0_RESEARCH_DISPLAY_LIMIT);\n const notice = el(\"m0-research-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"m0ResearchLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"m0ResearchStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"m0ResearchUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"m0ResearchUpstreamNotice\").replace(\"{count}\", String(payload.errors.length));\n } else {\n const more = entries.length > M0_RESEARCH_DISPLAY_LIMIT\n ? ` ${t(\"m0ResearchMore\").replace(\"{count}\", String(M0_RESEARCH_DISPLAY_LIMIT))}`\n : \"\";\n notice.textContent = `${t(\"m0ResearchNoOrder\")}${more}`;\n }\n\n const list = el(\"m0-research-list\");\n list.replaceChildren();\n if (!shownEntries.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"m0ResearchEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const entry of shownEntries) {\n const subject = entry.subject || {};\n const observation = entry.observation || {};\n const context = observation.research_context || {};\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"m0ResearchMeta\")\n .replace(\"{kind}\", m0ResearchLabel(\"subject\", subject.kind))\n .replace(\"{viewed}\", m0ResearchTimestamp(payload.viewed_at));\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = typeof subject.identifier === \"string\" ? subject.identifier : \"—\";\n const stateFreshness = document.createElement(\"p\");\n stateFreshness.className = \"health-card__reason\";\n stateFreshness.textContent = t(\"m0ResearchStateFreshness\")\n .replace(\"{state}\", m0ResearchLabel(\"state\", context.state))\n .replace(\"{freshness}\", m0ResearchLabel(\"freshness\", observation.freshness?.status));\n const horizons = document.createElement(\"div\");\n horizons.className = \"health-card__meta\";\n horizons.textContent = t(\"m0ResearchHorizons\")\n .replace(\"{primary}\", m0ResearchLabel(\"horizon\", context.primary_horizon))\n .replace(\"{suitable}\", m0ResearchHorizons(context.suitable_horizons));\n const evidence = document.createElement(\"div\");\n evidence.className = \"health-card__meta\";\n evidence.textContent = t(\"m0ResearchEvidence\")\n .replace(\"{confidence}\", m0ResearchLabel(\"confidence\", context.source_confidence))\n .replace(\"{style}\", m0ResearchLabel(\"style\", context.source_style))\n .replace(\"{digest}\", `${shortResearchDigest(observation.source_report_digest)} / ${shortResearchDigest(observation.source_entry_digest)}`);\n const consistency = document.createElement(\"div\");\n consistency.className = \"health-card__meta\";\n consistency.textContent = t(\"m0ResearchConsistency\")\n .replace(\"{conflict}\", m0ResearchLabel(\"conflict\", entry.horizonConflict?.status))\n .replace(\"{drift}\", m0ResearchLabel(\"drift\", entry.historicalStaleHorizonDrift?.status));\n main.append(meta, title, stateFreshness, horizons, evidence, consistency);\n const status = document.createElement(\"div\");\n status.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = state.lang === \"zh\" ? \"研究\" : \"Research\";\n const freshness = document.createElement(\"strong\");\n freshness.textContent = m0ResearchLabel(\"freshness\", observation.freshness?.status);\n const stateLabel = document.createElement(\"small\");\n stateLabel.textContent = m0ResearchLabel(\"state\", context.state);\n status.append(label, freshness, stateLabel);\n card.append(main, status);\n list.appendChild(card);\n }\n }\n\n function normalizeAdaptiveSelectionPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid adaptive selection payload\");\n const selections = Array.isArray(payload.selections) ? payload.selections : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n selections: selections.filter((item) => item && typeof item === \"object\"\n && typeof item.source_id === \"string\" && item.decision && typeof item.decision === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function renderAdaptiveSelection() {\n const payload = state.adaptiveSelection.payload;\n const notice = el(\"adaptive-selection-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"adaptiveSelectionLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"adaptiveSelectionStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"adaptiveSelectionUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"adaptiveSelectionUpstreamNotice\").replace(\"{count}\", String(payload.errors.length));\n } else {\n notice.textContent = localizedExternalText(payload.policy?.notice, t(\"adaptiveSelectionNoOrder\"));\n }\n\n const list = el(\"adaptive-selection-list\");\n list.replaceChildren();\n if (!payload.selections.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"adaptiveSelectionEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const entry of payload.selections) {\n const decision = entry.decision || {};\n const context = decision.market_context || {};\n const recommended = decision.candidates?.find((item) => item.accepted\n && item.strategy_profile === decision.recommended_strategy_profile) || null;\n const rejected = (decision.candidates || []).filter((item) => !item.accepted);\n const reasons = (recommended?.reasons?.length ? recommended.reasons : rejected.flatMap((item) => item.reasons || []))\n .slice(0, 3)\n .join(\", \");\n\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"adaptiveSelectionMeta\")\n .replace(\"{source}\", entry.source_id || \"unknown\")\n .replace(\"{domain}\", domainLabel(context.domain || \"\"))\n .replace(\"{asOf}\", context.as_of || \"—\");\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = recommended\n ? `${t(\"adaptiveSelectionRecommended\")} · ${recommended.strategy_profile}`\n : t(\"adaptiveSelectionNoCandidate\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = reasons\n ? t(\"adaptiveSelectionReason\").replace(\"{reasons}\", localizedExternalText(reasons, t(\"adaptiveSelectionNoOrder\")))\n : t(\"adaptiveSelectionNoOrder\");\n main.append(meta, title, reason);\n const status = document.createElement(\"div\");\n status.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"adaptiveSelectionScoreLabel\");\n const score = document.createElement(\"strong\");\n score.textContent = typeof recommended?.score === \"number\" ? recommended.score.toFixed(3) : \"—\";\n const freshness = document.createElement(\"small\");\n freshness.textContent = controlPlaneDataStatusText(entry.freshness?.data_status);\n status.append(label, score, freshness);\n card.append(main, status);\n list.appendChild(card);\n }\n }\n\n function normalizeExecutionEvidencePayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid execution evidence payload\");\n const deployments = Array.isArray(payload.deployments) ? payload.deployments : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n deployments: deployments.filter((item) => item && typeof item === \"object\" && item.deployment && typeof item.deployment === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function executionEvidenceReceiptOutcomeLabel(value) {\n return {\n not_due: t(\"executionEvidenceReceiptNotDue\"),\n no_action: t(\"executionEvidenceReceiptNoAction\"),\n risk_blocked: t(\"executionEvidenceReceiptRiskBlocked\"),\n submitted: t(\"executionEvidenceReceiptSubmitted\"),\n broker_acknowledged: t(\"executionEvidenceReceiptAcknowledged\"),\n partially_filled: t(\"executionEvidenceReceiptPartiallyFilled\"),\n filled: t(\"executionEvidenceReceiptFilled\"),\n reconciliation_required: t(\"executionEvidenceReceiptReconciliation\"),\n failed: t(\"executionEvidenceReceiptFailed\"),\n }[value] || t(\"executionEvidenceReceiptMissing\");\n }\n\n function executionEvidenceReceiptConfirmationLabel(value) {\n return {\n not_applicable: t(\"executionEvidenceConfirmationNotApplicable\"),\n not_observed: t(\"executionEvidenceConfirmationNotObserved\"),\n acknowledged: t(\"executionEvidenceConfirmationAcknowledged\"),\n partially_filled: t(\"executionEvidenceConfirmationPartiallyFilled\"),\n filled: t(\"executionEvidenceConfirmationFilled\"),\n reconciliation_required: t(\"executionEvidenceConfirmationReconciliation\"),\n }[value] || t(\"executionEvidenceConfirmationNotObserved\");\n }\n\n function renderExecutionEvidence() {\n const payload = state.executionEvidence.payload;\n const notice = el(\"execution-evidence-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"executionEvidenceLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"executionEvidenceStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"executionEvidenceUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"executionEvidenceUpstreamNotice\").replace(\"{count}\", payload.errors.length);\n } else {\n notice.textContent = localizedExternalText(payload.policy?.notice, t(\"executionEvidenceNoOrder\"));\n }\n\n const list = el(\"execution-evidence-list\");\n list.replaceChildren();\n if (!payload.deployments.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"executionEvidenceEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const entry of payload.deployments) {\n const deployment = entry.deployment || {};\n const strategy = deployment.strategy || {};\n const target = deployment.target || {};\n const capabilities = deployment.capabilities || {};\n const evidence = deployment.evidence || {};\n const executionReceipt = deployment.execution_receipt || null;\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"executionEvidenceMeta\")\n .replace(\"{platform}\", target.platform || \"unknown\")\n .replace(\"{environment}\", target.environment || \"unknown\")\n .replace(\"{source}\", entry.source_id || \"unknown\");\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = String(strategy.candidate_id || deployment.deployment_id || \"unknown\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = localizedExternalText(deployment.recommendation?.reason_code, t(\"executionEvidenceNoOrder\"));\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"executionEvidenceDetail\")\n .replace(\"{strategy}\", evidence.strategy || \"unknown\")\n .replace(\"{data}\", evidence.target_data || \"unknown\")\n .replace(\"{execution}\", evidence.target_execution || \"unknown\")\n .replace(\"{shadow}\", capabilities.shadow || \"unknown\")\n .replace(\"{paper}\", capabilities.paper || \"unknown\");\n const receiptDetail = document.createElement(\"div\");\n receiptDetail.className = \"health-card__meta\";\n receiptDetail.textContent = executionReceipt\n ? t(\"executionEvidenceReceipt\")\n .replace(\"{outcome}\", executionEvidenceReceiptOutcomeLabel(executionReceipt.outcome))\n .replace(\"{confirmation}\", executionEvidenceReceiptConfirmationLabel(executionReceipt.broker_confirmation))\n : t(\"executionEvidenceReceiptMissing\");\n main.append(meta, title, reason, detail, receiptDetail);\n const stateBlock = document.createElement(\"div\");\n stateBlock.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"executionEvidenceNext\");\n const recommendation = document.createElement(\"strong\");\n recommendation.textContent = operatorLabel(\"action\", deployment.recommendation?.code || \"park\");\n const freshness = document.createElement(\"small\");\n freshness.textContent = controlPlaneDataStatusText(entry.freshness?.data_status);\n stateBlock.append(label, recommendation, freshness);\n card.append(main, stateBlock);\n list.appendChild(card);\n }\n }\n\n function normalizeRuntimeTargetLifecyclePayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new Error(\"invalid runtime target lifecycle payload\");\n }\n const targets = Array.isArray(payload.targets) ? payload.targets : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n targets: targets.filter((entry) => entry && typeof entry === \"object\"\n && entry.target && typeof entry.target === \"object\"\n && entry.target.target && typeof entry.target.target === \"object\"\n && entry.target.monitoring && typeof entry.target.monitoring === \"object\"\n && entry.target.disposition && typeof entry.target.disposition === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function runtimeTargetLifecycleCheckLabel(value) {\n return {\n pass: t(\"runtimeTargetLifecycleCheckPass\"),\n attention: t(\"runtimeTargetLifecycleCheckAttention\"),\n not_due: t(\"runtimeTargetLifecycleCheckNotDue\"),\n not_applicable: t(\"runtimeTargetLifecycleCheckNotApplicable\"),\n unavailable: t(\"runtimeTargetLifecycleCheckUnavailable\"),\n }[value] || t(\"runtimeTargetLifecycleCheckUnavailable\");\n }\n\n function runtimeTargetLifecycleStateLabel(value) {\n return value === \"enabled\"\n ? t(\"runtimeTargetLifecycleStateEnabled\")\n : t(\"runtimeTargetLifecycleStateDisabled\");\n }\n\n function runtimeTargetLifecycleObservationLabel(value) {\n return {\n not_due: t(\"runtimeTargetLifecycleObservationNotDue\"),\n monitoring_only: t(\"runtimeTargetLifecycleObservationMonitoringOnly\"),\n not_applicable: t(\"runtimeTargetLifecycleObservationNotApplicable\"),\n attention: t(\"runtimeTargetLifecycleObservationAttention\"),\n unavailable: t(\"runtimeTargetLifecycleObservationUnavailable\"),\n }[value] || t(\"runtimeTargetLifecycleObservationUnavailable\");\n }\n\n function runtimeTargetLifecycleOrderEvidenceLabel(value) {\n return {\n not_collected: t(\"runtimeTargetLifecycleOrderEvidenceNotCollected\"),\n }[value] || t(\"runtimeTargetLifecycleOrderEvidenceNotCollected\");\n }\n\n function runtimeTargetLifecycleDispositionLabel(value) {\n return {\n continue_enabled_monitoring: t(\"runtimeTargetLifecycleDispositionEnabled\"),\n continue_disabled_validation: t(\"runtimeTargetLifecycleDispositionDisabled\"),\n parked: t(\"runtimeTargetLifecycleDispositionParked\"),\n }[value] || t(\"runtimeTargetLifecycleDispositionParked\");\n }\n\n function runtimeTargetLifecycleReasonLabel(value) {\n return {\n none: t(\"runtimeTargetLifecycleReasonNone\"),\n target_intentionally_disabled: t(\"runtimeTargetLifecycleReasonDisabled\"),\n runtime_guard_attention: t(\"runtimeTargetLifecycleReasonRuntimeGuard\"),\n execution_heartbeat_attention: t(\"runtimeTargetLifecycleReasonHeartbeat\"),\n monitoring_unavailable: t(\"runtimeTargetLifecycleReasonUnavailable\"),\n }[value] || t(\"runtimeTargetLifecycleReasonUnavailable\");\n }\n\n function renderRuntimeTargetLifecycle() {\n const payload = state.runtimeTargetLifecycle.payload;\n renderMonitoringOverview();\n renderOverview();\n const notice = el(\"runtime-target-lifecycle-notice\");\n notice.hidden = false;\n if (state.runtimeTargetLifecycle.loading) {\n notice.textContent = t(\"refreshingStatus\");\n } else if (!state.auth.allowed) {\n notice.textContent = t(\"runtimeTargetLifecycleLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"runtimeTargetLifecycleStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"runtimeTargetLifecycleUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"runtimeTargetLifecycleUpstreamNotice\").replace(\"{count}\", String(payload.errors.length));\n } else {\n notice.textContent = \"\";\n notice.hidden = true;\n }\n\n const list = el(\"runtime-target-lifecycle-list\");\n list.replaceChildren();\n if (!payload.targets.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"runtimeTargetLifecycleEmpty\");\n list.appendChild(empty);\n return;\n }\n\n const targets = payload.targets.filter(entry => {\n const platform = entry.target?.target?.platform;\n return platformMeta[platform]?.console_visible !== false && platformMeta[platform]\n && optionsFor(platform).some(account => account.runtime_status_target_id === entry.target.target_id);\n }).sort((left, right) => {\n const leftParked = left.target?.disposition?.code === \"parked\" ? 0 : 1;\n const rightParked = right.target?.disposition?.code === \"parked\" ? 0 : 1;\n if (leftParked !== rightParked) return leftParked - rightParked;\n return String(left.target?.target_id || \"\").localeCompare(String(right.target?.target_id || \"\"));\n });\n for (const entry of targets) {\n const target = entry.target || {};\n const configuration = target.target || {};\n const monitoring = target.monitoring || {};\n const disposition = target.disposition || {};\n const executionObservation = entry.execution_observation || {};\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"runtimeTargetLifecycleMeta\")\n .replace(\"{platform}\", configuration.platform || \"unknown\")\n .replace(\"{state}\", runtimeTargetLifecycleStateLabel(configuration.configured_state))\n .replace(\"{mode}\", configuration.execution_mode || \"unknown\");\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = optionsFor(configuration.platform).find(account => account.runtime_status_target_id === target.target_id)?.label || t(\"runtimeUnverified\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = runtimeTargetLifecycleReasonLabel(disposition.reason_code);\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"runtimeTargetLifecycleDetail\")\n .replace(\"{guard}\", runtimeTargetLifecycleCheckLabel(monitoring.runtime_guard))\n .replace(\"{heartbeat}\", runtimeTargetLifecycleCheckLabel(monitoring.execution_heartbeat));\n const observation = document.createElement(\"div\");\n observation.className = \"health-card__meta\";\n observation.textContent = t(\"runtimeTargetLifecycleObservation\")\n .replace(\"{observation}\", runtimeTargetLifecycleObservationLabel(executionObservation.code))\n .replace(\"{evidence}\", runtimeTargetLifecycleOrderEvidenceLabel(executionObservation.order_or_fill_evidence));\n main.append(meta, title, reason, detail, observation);\n\n const stateBlock = document.createElement(\"div\");\n stateBlock.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"runtimeTargetLifecycleNext\");\n const current = document.createElement(\"strong\");\n current.textContent = runtimeTargetLifecycleDispositionLabel(disposition.code);\n const freshness = document.createElement(\"small\");\n freshness.textContent = entry.freshness?.data_status || \"unknown\";\n stateBlock.append(label, current, freshness);\n card.append(main, stateBlock);\n list.appendChild(card);\n }\n }\n\n function normalizeResearchTaskPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid research task payload\");\n const tasks = Array.isArray(payload.tasks) ? payload.tasks : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n tasks: tasks.filter((item) => item && typeof item === \"object\" && item.task && typeof item.task === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function shortResearchDigest(value) {\n const text = String(value || \"\");\n return /^[0-9a-f]{64}$/.test(text) ? `${text.slice(0, 10)}…` : \"—\";\n }\n\n function renderResearchTasks() {\n const payload = state.researchTasks.payload;\n const board = el(\"research-task-board\");\n const hasValidReport = state.auth.allowed && payload.data_status === \"ready\" && payload.tasks.length > 0;\n if (board) board.hidden = !hasValidReport;\n const notice = el(\"research-task-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"researchTaskLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"researchTaskStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"researchTaskUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"researchTaskUpstreamNotice\").replace(\"{count}\", payload.errors.length);\n } else {\n notice.textContent = localizedExternalText(payload.policy?.notice, t(\"researchTaskNoOrder\"));\n }\n\n const list = el(\"research-task-list\");\n list.replaceChildren();\n if (!payload.tasks.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"researchTaskEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const entry of payload.tasks) {\n const task = entry.task || {};\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"researchTaskMeta\")\n .replace(\"{type}\", task.task_type || \"research\")\n .replace(\"{domain}\", domainLabel(task.target?.domain || \"\"))\n .replace(\"{created}\", formatDateTime(task.created_at));\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = `${task.target?.candidate_id || \"unknown\"} · ${task.task_id || \"unknown\"}`;\n const hypothesis = document.createElement(\"p\");\n hypothesis.className = \"health-card__reason\";\n hypothesis.textContent = localizedExternalText(task.experiment?.hypothesis, t(\"researchTaskNoOrder\"));\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"researchTaskLimits\")\n .replace(\"{runs}\", String(task.experiment?.max_runs || \"—\"))\n .replace(\"{seconds}\", String(task.experiment?.max_wall_seconds || \"—\"))\n .replace(\"{p1}\", shortResearchDigest(task.evidence?.p1_input_digest))\n .replace(\"{p2}\", shortResearchDigest(task.evidence?.p2_config_digest))\n .replace(\"{p3}\", shortResearchDigest(task.evidence?.p3_evidence_id));\n main.append(meta, title, hypothesis, detail);\n const status = document.createElement(\"div\");\n status.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"researchTaskNoOrderBadge\");\n const count = document.createElement(\"strong\");\n count.textContent = String(task.experiment?.max_runs || \"—\");\n const source = document.createElement(\"small\");\n source.textContent = controlPlaneDataStatusText(entry.freshness?.data_status);\n status.append(label, count, source);\n card.append(main, status);\n list.appendChild(card);\n }\n }\n\n function healthStatusLabel(status) {\n return {\n healthy: t(\"healthStatusHealthy\"),\n watch: t(\"healthStatusWatch\"),\n review: t(\"healthStatusReview\"),\n critical: t(\"healthStatusCritical\"),\n }[status] || t(\"healthStatusUnknown\");\n }\n\n function healthRecommendationText(status) {\n return {\n healthy: t(\"healthRecommendationHealthy\"),\n watch: t(\"healthRecommendationWatch\"),\n review: t(\"healthRecommendationReview\"),\n critical: t(\"healthRecommendationCritical\"),\n }[status] || t(\"healthDecisionFallbackReason\");\n }\n\n function normalizeHealthPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid health payload\");\n const strategies = Array.isArray(payload.strategies) ? payload.strategies : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n strategies: strategies.filter((item) => item && typeof item === \"object\" && [\"healthy\", \"watch\", \"review\", \"critical\"].includes(item.status)),\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function renderHealth() {\n const payload = state.health.payload;\n const board = el(\"health-summary-board\");\n if (board) board.hidden = !state.auth.allowed || payload.data_status === \"unavailable\" || !payload.strategies.length;\n const summary = payload.summary || {};\n const healthCount = (status) => Math.max(\n Number(summary[status]) || 0,\n payload.strategies.filter((item) => item.status === status).length,\n );\n const criticalCount = healthCount(\"critical\");\n const reviewCount = healthCount(\"review\");\n const watchCount = healthCount(\"watch\");\n const hasAttention = criticalCount + reviewCount + watchCount > 0;\n const summaryAvailable = state.auth.allowed && payload.data_status !== \"unavailable\";\n const summaryCount = (value) => (summaryAvailable ? String(Number(value) || 0) : \"—\");\n const statusText = payload.data_status === \"ready\"\n ? t(\"healthDataReady\")\n : (payload.data_status === \"stale\" ? t(\"healthDataStale\") : t(\"healthDataUnavailable\"));\n el(\"health-status\").textContent = statusText;\n el(\"health-computed-at\").textContent = payload.computed_at\n ? t(\"healthComputedAt\").replace(\"{time}\", formatDateTime(payload.computed_at))\n : t(\"healthComputedAt\").replace(\"{time}\", \"—\");\n el(\"health-count-total\").textContent = summaryCount(summary.strategy_count);\n el(\"health-count-healthy\").textContent = summaryCount(summary.healthy);\n el(\"health-count-watch\").textContent = summaryCount(summary.watch);\n el(\"health-count-review\").textContent = summaryCount(summary.review);\n el(\"health-count-critical\").textContent = summaryCount(summary.critical);\n\n const notice = el(\"health-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"healthLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"healthStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"healthUnavailableNotice\");\n } else if (hasAttention) {\n notice.textContent = t(\"healthAttentionNotice\")\n .replace(\"{critical}\", String(criticalCount))\n .replace(\"{review}\", String(reviewCount))\n .replace(\"{watch}\", String(watchCount));\n } else if (payload.errors?.length) {\n notice.textContent = t(\"healthUpstreamNotice\");\n } else {\n notice.textContent = t(\"healthNormalNotice\");\n }\n\n const list = el(\"health-list\");\n list.replaceChildren();\n const strategies = payload.strategies.filter((item) => state.health.filter === \"all\" || item.status !== \"healthy\");\n if (!strategies.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"healthEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const item of strategies) {\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"healthCardMeta\")\n .replace(\"{status}\", healthStatusLabel(item.status))\n .replace(\"{domain}\", domainLabel(item.domain || \"\"));\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = strategyLabel(item.profile) || t(\"commonUnknown\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = healthRecommendationText(item.status);\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"healthDetail\")\n .replace(\"{date}\", formatAsOfDate(item.as_of));\n main.append(meta, title, reason, detail);\n const scoreBlock = document.createElement(\"div\");\n scoreBlock.className = \"health-card__score\";\n const scoreLabel = document.createElement(\"small\");\n scoreLabel.textContent = t(\"healthScoreLabel\");\n const score = document.createElement(\"strong\");\n score.textContent = typeof item.score === \"number\" ? item.score.toFixed(1) : \"—\";\n const decision = document.createElement(\"small\");\n decision.textContent = healthStatusLabel(item.status);\n scoreBlock.append(scoreLabel, score, decision);\n card.append(main, scoreBlock);\n list.appendChild(card);\n }\n }\n\n function overviewAccounts() {\n if (!hasPrivateConfig()) return [];\n const rows = [];\n for (const platform of Object.keys(platformMeta).filter(key => platformMeta[key].console_visible !== false)) {\n for (const account of optionsFor(platform)) {\n const saved = runtimeTargetStateForAccount(platform, account);\n const record = accountMonitoringRecord(platform, account);\n const application = accountApplicationText(platform, account);\n const unknown = application === t(\"deploymentUnverified\");\n const runtimeAttention = record?.freshness?.data_status === \"ready\"\n && record.execution_observation?.code === \"attention\";\n const configurationMismatch = [\"settingsNotApplied\", \"strategyNotApplied\", \"scheduleNotApplied\"]\n .map(key => t(key)).includes(application) || accountMonitoringText(platform, account) === t(\"monitoringConfigMismatch\");\n const configurationReason = application === t(\"strategyNotApplied\") ? \"strategy\"\n : application === t(\"scheduleNotApplied\") ? \"schedule\"\n : application === t(\"settingsNotApplied\") || configurationMismatch ? \"switch\" : \"\";\n const runtimeSummary = runtimeOverviewStatus(saved, application === t(\"switchesApplied\"), record, configurationReason);\n const profile = currentStrategyForAccount(platform, account);\n rows.push({\n platform, platformLabel: platformMeta[platform].label, account,\n strategy: profile ? strategyLabel(profile) : t(\"notRead\"),\n configured: saved.known ? (saved.enabled ? \"enabled\" : \"disabled\") : \"unknown\",\n application, unknown, runtimeAttention,\n runtimeStatus: runtimeSummary.status, runtimeReason: runtimeSummary.reason,\n attention: runtimeSummary.status === \"abnormal\",\n observation: accountMonitoringText(platform, account),\n age: accountObservationAge(record),\n });\n }\n }\n return rows;\n }\n\n function filterOverviewAccounts(rows, filter, search) {\n const query = String(search || \"\").trim().toLocaleLowerCase();\n return rows.filter(row => {\n const inScope = [\"normal\", \"paused\", \"abnormal\"].includes(filter)\n ? row.runtimeStatus === filter : true;\n return inScope && (!query || [row.platformLabel, accountDisplayLabel(row.account), row.account.label, row.strategy]\n .some(value => String(value || \"\").toLocaleLowerCase().includes(query)));\n });\n }\n\n function renderOverview() {\n const rows = overviewAccounts();\n const available = hasPrivateConfig();\n const counts = Object.fromEntries([\"normal\", \"paused\", \"abnormal\"]\n .map(status => [status, rows.filter(row => row.runtimeStatus === status).length]));\n\n const filtered = filterOverviewAccounts(rows, state.overviewFilter, state.overviewSearch);\n el(\"overview-result-count\").textContent = available\n ? t(\"accountResults\").replace(\"{count}\", filtered.length).replace(\"{total}\", rows.length) : \"—\";\n document.querySelectorAll(\"[data-overview-filter]\").forEach(button => {\n button.setAttribute(\"aria-pressed\", String(button.dataset.overviewFilter === state.overviewFilter));\n button.disabled = !available;\n const count = button.querySelector(\"[data-overview-count]\");\n if (count) count.textContent = available ? `(${counts[button.dataset.overviewFilter] || 0})` : \"\";\n });\n el(\"overview-search\").disabled = !available;\n const body = el(\"overview-accounts-body\");\n body.replaceChildren();\n for (const row of filtered) {\n const tr = document.createElement(\"tr\");\n const accountCell = document.createElement(\"td\");\n accountCell.className = \"overview-account\";\n const mark = document.createElement(\"span\");\n mark.className = \"account-mark\";\n mark.setAttribute(\"aria-hidden\", \"true\");\n mark.textContent = platformMeta[row.platform].code;\n const identity = document.createElement(\"span\");\n const name = document.createElement(\"strong\");\n name.textContent = accountDisplayLabel(row.account);\n const platform = document.createElement(\"small\");\n platform.textContent = row.platformLabel;\n identity.append(name, platform);\n accountCell.append(mark, identity);\n const strategyCell = document.createElement(\"td\");\n strategyCell.className = \"overview-strategy\";\n strategyCell.textContent = row.strategy;\n const runtimeCell = document.createElement(\"td\");\n runtimeCell.className = \"overview-runtime\";\n const actual = document.createElement(\"span\");\n actual.className = `runtime-badge ${row.runtimeStatus === \"abnormal\" ? \"attention\" : row.runtimeStatus === \"paused\" ? \"unverified\" : \"applied\"}`;\n const statusKey = row.runtimeStatus === \"normal\" ? \"overviewRuntimeNormal\"\n : row.runtimeStatus === \"paused\" ? \"overviewRuntimePaused\" : \"overviewRuntimeAbnormal\";\n const reasonKey = row.runtimeReason === \"missing\" ? \"overviewRuntimeReasonMissing\"\n : row.runtimeReason === \"stale\" ? \"overviewRuntimeReasonStale\"\n : row.runtimeReason === \"switch\" ? \"overviewRuntimeReasonSwitch\"\n : row.runtimeReason === \"strategy\" ? \"overviewRuntimeReasonStrategy\"\n : row.runtimeReason === \"schedule\" ? \"overviewRuntimeReasonSchedule\"\n : row.runtimeReason === \"config\" ? \"overviewRuntimeReasonConfig\"\n : row.runtimeReason === \"attention\" ? \"overviewRuntimeReasonAttention\" : \"overviewRuntimeReasonPending\";\n actual.textContent = `${t(statusKey)}${row.runtimeStatus === \"abnormal\" ? ` · ${t(reasonKey).replace(\"{age}\", row.age)}` : \"\"}`;\n const saved = document.createElement(\"small\");\n saved.textContent = t(\"savedState\").replace(\"{state}\", t({\n enabled: \"runtimeTargetLifecycleStateEnabled\", disabled: \"runtimeTargetLifecycleStateDisabled\",\n unknown: \"runtimeStateUnknown\",\n }[row.configured]));\n runtimeCell.append(actual, saved);\n const readbackCell = document.createElement(\"td\");\n readbackCell.className = \"overview-readback\";\n const age = document.createElement(\"span\");\n age.textContent = row.age;\n const observation = document.createElement(\"small\");\n observation.textContent = row.observation;\n const mobileLabel = document.createElement(\"span\");\n mobileLabel.className = \"mobile-readback-label\";\n mobileLabel.textContent = `${t(\"latestReadback\")}:`;\n readbackCell.append(mobileLabel, age, observation);\n const actionCell = document.createElement(\"td\");\n actionCell.className = \"overview-action\";\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"btn\";\n button.textContent = t(\"viewAccount\");\n button.setAttribute(\"aria-label\", t(\"viewAccountLabel\").replace(\"{account}\", `${row.platformLabel} ${accountDisplayLabel(row.account)}`));\n button.addEventListener(\"click\", () => openAccountSettings(row.platform, row.account, false));\n actionCell.append(button);\n tr.append(accountCell, strategyCell, runtimeCell, readbackCell, actionCell);\n body.append(tr);\n }\n el(\"overview-empty\").hidden = filtered.length > 0;\n const emptyKey = !available ? (state.configSource === \"loading\" ? \"overviewLoading\" : \"overviewUnavailable\")\n : rows.length ? \"overviewEmpty\" : \"overviewNoAccounts\";\n el(\"overview-empty-title\").textContent = t(`${emptyKey}Title`);\n el(\"overview-empty-description\").textContent = t(`${emptyKey}Description`);\n el(\"overview-reset\").hidden = !available || !rows.length;\n el(\"monitoring-computed-at\").textContent = state.lastRefreshAt\n ? t(\"pageRefreshed\").replace(\"{time}\", new Intl.DateTimeFormat(locale(), {hour: \"2-digit\", minute: \"2-digit\"}).format(new Date(state.lastRefreshAt)))\n : t(\"pageNotRefreshed\");\n const queue = state.researchPromotion.payload;\n const pending = reviewablePromotionTickets(queue).length;\n el(\"overview-research-link\").hidden = !state.auth.allowed || pending === 0;\n el(\"overview-research-summary\").textContent = pending\n ? t(\"researchPendingCount\").replace(\"{count}\", pending)\n : \"\";\n }\n\n function renderWorkspace() {\n el(\"refresh-status-button\").disabled = state.refreshing;\n el(\"refresh-status-button\").textContent = t(state.refreshing ? \"refreshingStatus\" : \"refreshStatus\");\n const view = [\"overview\", \"accounts\", \"research\"].includes(state.view) ? state.view : \"overview\";\n for (const name of [\"overview\", \"accounts\", \"research\"]) el(`${name}-view`).hidden = view !== name;\n el(\"platform-strip\").hidden = view !== \"accounts\";\n el(\"platform-strip-label\").hidden = view !== \"accounts\";\n el(\"platform-strip-label\").textContent = t(\"activePlatform\");\n el(\"health-view\").hidden = view !== \"research\";\n document.querySelectorAll?.(\"[data-research-panel]\")?.forEach((panel) => {\n panel.hidden = panel.dataset.researchPanel !== state.researchInternalView;\n });\n document.querySelectorAll?.(\"[data-research-internal-view]\")?.forEach((button) => {\n const active = button.dataset.researchInternalView === state.researchInternalView;\n button.classList?.toggle(\"active\", active);\n button.setAttribute?.(\"aria-selected\", String(active));\n });\n el(\"workspace-title\").textContent = t(`${view}Nav`);\n el(\"workspace-description\").textContent = t(`${view}Description`);\n document.querySelector(\".workspace-nav\").hidden = !state.appReady || !state.auth.allowed;\n document.querySelectorAll(\".workspace-nav [data-workspace]\").forEach(button => {\n if (button.dataset.workspace === view) button.setAttribute(\"aria-current\", \"page\");\n else button.removeAttribute(\"aria-current\");\n });\n }\n\n function renderConsoleView() {\n el(\"switch-view\").hidden = false;\n el(\"health-view\").hidden = true;\n el(\"control-plane-view\").hidden = !state.auth.allowed;\n }\n\n function render() {\n applyLanguage();\n renderConsoleView();\n renderControlPlane();\n renderReconciliationRecovery();\n renderParkedResearchResults();\n renderBinancePrivateScope();\n renderM0Research();\n renderAdaptiveSelection();\n renderExecutionEvidence();\n renderRuntimeTargetLifecycle();\n renderResearchTasks();\n renderHealth();\n renderPlatforms();\n renderControls();\n renderBinanceResume();\n renderAccountOverview();\n renderSummary();\n renderAuth();\n renderAppVisibility();\n renderWorkspace();\n renderOverview();\n }\n\n async function refreshSession() {\n state.bootMessageKey = \"bootSession\";\n render();\n try {\n const session = await requestJson(\"/api/session\");\n state.auth = {\n available: true,\n allowed: Boolean(session.allowed),\n admin: Boolean(session.admin),\n login: session.login || null,\n };\n } catch {\n state.auth = { available: false, allowed: false, admin: false, login: null };\n }\n if (state.auth.allowed) {\n await refreshControlPlane();\n await refreshOwnerDecisions();\n await refreshConfig();\n await refreshRuntimeTargetLifecycle();\n await refreshAccountDiagnosis();\n refreshReconciliationRecovery();\n if (state.auth.allowed && state.auth.admin) refreshBinancePrivateScope();\n else clearBinancePrivateScope();\n await refreshResearchPromotionTickets();\n } else {\n clearBinancePrivateScope();\n state.bootMessageKey = \"bootPublic\";\n state.appReady = true;\n render();\n }\n }\n\n async function refreshHealth() {\n if (!state.auth.allowed) {\n renderHealth();\n return;\n }\n try {\n state.health.payload = normalizeHealthPayload(await requestJson(\"/api/strategy-health\"));\n } catch {\n state.health.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { strategy_count: 0, healthy: 0, watch: 0, review: 0, critical: 0 },\n strategies: [],\n errors: [\"health_request_failed\"],\n };\n }\n renderHealth();\n }\n\n async function refreshControlPlane() {\n if (!state.auth.allowed) {\n renderControlPlane();\n return;\n }\n try {\n state.controlPlane.payload = normalizeControlPlanePayload(await requestJson(\"/api/control-plane\"));\n } catch {\n state.controlPlane.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { candidate_count: 0, deferred: 0, parked: 0, owner_decision_required: 0 },\n attention: { status: \"unavailable\", reason_codes: [\"control_plane_request_failed\"] },\n candidates: [],\n policy: { p4_p5_automation: \"not_configured\", p6_owner_decision_required: true },\n errors: [\"control_plane_request_failed\"],\n };\n }\n renderControlPlane();\n }\n\n async function refreshOwnerDecisions() {\n if (!state.auth.allowed) {\n state.ownerDecisions = { data_status: \"unavailable\", candidates: [], errors: [] };\n renderControlPlane();\n return;\n }\n try {\n state.ownerDecisions = normalizeOwnerDecisionQueue(await requestJson(\"/api/owner-decisions\"));\n } catch {\n state.ownerDecisions = {\n data_status: \"unavailable\",\n candidates: [],\n errors: [\"owner_decision_queue_request_failed\"],\n };\n }\n renderControlPlane();\n }\n\n async function refreshReconciliationRecovery() {\n if (!state.auth.allowed) {\n renderControlPlane();\n renderReconciliationRecovery();\n return;\n }\n try {\n state.reconciliationRecovery.payload = normalizeReconciliationRecoveryPayload(\n await requestJson(\"/api/reconciliation-recovery\"),\n );\n } catch {\n state.reconciliationRecovery.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { recovery_count: 0, awaiting_human_confirmation: 0, blocked: 0, confirmed: 0 },\n recoveries: [],\n policy: { human_confirmation_required: true, current_evidence_required: true, no_order: true, execution_authority_granted: false },\n errors: [\"reconciliation_recovery_request_failed\"],\n };\n }\n renderControlPlane();\n renderReconciliationRecovery();\n }\n\n async function refreshBinancePrivateScope() {\n if (!state.auth.allowed || !state.auth.admin) {\n clearBinancePrivateScope();\n renderBinancePrivateScope();\n return;\n }\n const requestGeneration = ++binancePrivateScopeRequestGeneration;\n try {\n const report = normalizeBinancePrivateScopePayload(\n await requestJson(\"/api/binance-private-scope\"),\n );\n if (requestGeneration !== binancePrivateScopeRequestGeneration || !state.auth.allowed || !state.auth.admin) return;\n state.binancePrivateScope = {\n status: report ? \"available\" : \"empty\",\n report,\n };\n } catch {\n if (requestGeneration !== binancePrivateScopeRequestGeneration) return;\n clearBinancePrivateScope();\n }\n renderBinancePrivateScope();\n }\n\n async function refreshM0Research() {\n if (!state.auth.allowed) {\n renderM0Research();\n return;\n }\n try {\n state.m0Research.payload = normalizeM0ResearchPayload(await requestJson(\"/api/m0-research\"));\n } catch {\n state.m0Research.payload = {\n data_status: \"unavailable\",\n viewed_at: null,\n summary: {\n subject_count: 0,\n observation_count: 0,\n fresh_observation_count: 0,\n stale_observation_count: 0,\n unknown_observation_count: 0,\n horizon_conflict_count: 0,\n historical_stale_horizon_drift_count: 0,\n },\n subjects: [],\n policy: { authority: \"research_only\", no_order: true, permitted_next_step: \"research_validation_only\" },\n errors: [\"m0_research_request_failed\"],\n };\n }\n renderM0Research();\n }\n\n async function refreshAdaptiveSelection() {\n if (!state.auth.allowed) {\n renderAdaptiveSelection();\n return;\n }\n try {\n state.adaptiveSelection.payload = normalizeAdaptiveSelectionPayload(await requestJson(\"/api/adaptive-selection\"));\n } catch {\n state.adaptiveSelection.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { source_count: 0, decision_count: 0, candidate_count: 0, recommended_count: 0, rejected_candidate_count: 0 },\n selections: [],\n policy: { authority: \"shadow_only\", no_order: true, execution_authority_granted: false },\n errors: [\"adaptive_selection_request_failed\"],\n };\n }\n renderAdaptiveSelection();\n }\n\n async function recordOwnerDecision(button) {\n if (!state.auth.admin) return;\n const candidateId = String(button.dataset.candidateId || \"\");\n const candidateEvidenceSha256 = String(button.dataset.candidateEvidenceSha256 || \"\");\n const decision = String(button.dataset.ownerDecision || \"\");\n if (!candidateId || !candidateEvidenceSha256 || !decision) return;\n if (!window.confirm(t(\"ownerDecisionConfirm\"))) return;\n state.ownerDecisions.submittingCandidateId = candidateId;\n renderControlPlane();\n try {\n const response = await fetch(\"/api/owner-decisions\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n candidate_id: candidateId,\n decision,\n candidate_evidence_sha256: candidateEvidenceSha256,\n }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"ownerDecisionFailed\"));\n showToast(t(\"ownerDecisionSuccess\"), { duration: 7000 });\n await refreshControlPlane();\n await refreshOwnerDecisions();\n } catch (error) {\n showToast(`${t(\"ownerDecisionFailed\")}: ${error.message}`, { duration: 12000 });\n } finally {\n delete state.ownerDecisions.submittingCandidateId;\n renderControlPlane();\n }\n }\n\n async function recordReconciliationRecoveryConfirmation(button) {\n if (!state.auth.admin) return;\n const recoveryId = String(button.dataset.recoveryId || \"\");\n const candidateSha256 = String(button.dataset.candidateSha256 || \"\");\n const dualReviewBindingSha256 = String(button.dataset.dualReviewBindingSha256 || \"\");\n if (!recoveryId || !candidateSha256 || !dualReviewBindingSha256) return;\n if (!window.confirm(t(\"reconciliationRecoveryConfirmPrompt\"))) return;\n state.reconciliationRecovery.submittingRecoveryId = recoveryId;\n renderReconciliationRecovery();\n try {\n const response = await fetch(\"/api/reconciliation-recovery-confirmations\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n recovery_id: recoveryId,\n candidate_sha256: candidateSha256,\n dual_review_binding_sha256: dualReviewBindingSha256,\n }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"reconciliationRecoveryFailed\"));\n showToast(t(\"reconciliationRecoverySuccess\"), { duration: 9000 });\n await refreshReconciliationRecovery();\n } catch (error) {\n showToast(`${t(\"reconciliationRecoveryFailed\")}: ${error.message}`, { duration: 12000 });\n } finally {\n state.reconciliationRecovery.submittingRecoveryId = null;\n renderReconciliationRecovery();\n }\n }\n\n async function refreshExecutionEvidence() {\n if (!state.auth.allowed) {\n renderExecutionEvidence();\n return;\n }\n try {\n state.executionEvidence.payload = normalizeExecutionEvidencePayload(await requestJson(\"/api/execution-evidence\"));\n } catch {\n state.executionEvidence.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { deployment_count: 0, autonomous_shadow: 0, autonomous_paper: 0, owner_canary_decision: 0, parked: 0 },\n deployments: [],\n policy: { execution_evidence_read_only: true, p6_owner_decision_required: true, limited_live_canary_active: false },\n errors: [\"execution_evidence_request_failed\"],\n };\n }\n renderExecutionEvidence();\n }\n\n async function refreshRuntimeTargetLifecycle() {\n if (!state.auth.allowed) {\n renderRuntimeTargetLifecycle();\n return;\n }\n state.runtimeTargetLifecycle.loading = true;\n renderRuntimeTargetLifecycle();\n try {\n state.runtimeTargetLifecycle.payload = normalizeRuntimeTargetLifecyclePayload(\n await requestJson(\"/api/runtime-target-lifecycle\"),\n );\n } catch {\n state.runtimeTargetLifecycle.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { target_count: 0, enabled: 0, disabled: 0, attention: 0 },\n targets: [],\n policy: { lifecycle_status_read_only: true, no_order: true },\n errors: [\"runtime_target_lifecycle_request_failed\"],\n };\n }\n state.runtimeTargetLifecycle.loading = false;\n renderRuntimeTargetLifecycle();\n renderAccountOverview();\n }\n\n async function refreshAccountDiagnosis(platform, account) {\n const targets = platform && account\n ? [[platform, account]]\n : Object.keys(platformMeta).flatMap(itemPlatform => optionsFor(itemPlatform)\n .filter(item => accountDiagnosisEligible(itemPlatform, item))\n .map(item => [itemPlatform, item]));\n await Promise.all(targets.map(async ([itemPlatform, item]) => {\n const diagnosisKey = accountDiagnosisKey(itemPlatform, item);\n state.accountDiagnosis.loading[diagnosisKey] = true;\n try {\n const payload = await requestJson(`/api/account-diagnosis?platform=${encodeURIComponent(itemPlatform)}&key=${encodeURIComponent(item.key)}`);\n state.accountDiagnosis.tasks[diagnosisKey] = payload.task || null;\n } catch {\n state.accountDiagnosis.tasks[diagnosisKey] = null;\n } finally {\n delete state.accountDiagnosis.loading[diagnosisKey];\n }\n }));\n renderAccountDiagnosisAction();\n renderMonitoringOverview();\n }\n\n async function dispatchAccountDiagnosis(button) {\n const platform = String(button.dataset.platform || state.selected);\n const account = optionsFor(platform).find(item => item.key === button.dataset.accountKey) || selectedAccount(platform);\n if (!accountDiagnosisEligible(platform, account)) return;\n const diagnosisKey = accountDiagnosisKey(platform, account);\n if (state.accountDiagnosis.submitting[diagnosisKey]) return;\n const trigger = button.dataset.diagnosisTrigger || accountDiagnosisTrigger(platform, account);\n state.accountDiagnosis.submitting[diagnosisKey] = true;\n renderAccountDiagnosisAction();\n renderMonitoringOverview();\n try {\n const response = await fetch(\"/api/account-diagnosis\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform, key: account.key, trigger }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"accountDiagnosisUnavailable\"));\n state.accountDiagnosis.tasks[diagnosisKey] = payload.task || null;\n } catch (error) {\n showToast(error.message || t(\"accountDiagnosisUnavailable\"), { duration: 9000 });\n } finally {\n delete state.accountDiagnosis.submitting[diagnosisKey];\n renderAccountDiagnosisAction();\n renderMonitoringOverview();\n }\n }\n\n async function refreshResearchTasks() {\n if (!state.auth.allowed) {\n renderResearchTasks();\n return;\n }\n try {\n state.researchTasks.payload = normalizeResearchTaskPayload(await requestJson(\"/api/research-tasks\"));\n } catch {\n state.researchTasks.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { task_count: 0 },\n tasks: [],\n policy: { research_only: true, no_order: true, size_zero_required: true, p4_p5_p6_authorized: false },\n errors: [\"research_task_request_failed\"],\n };\n }\n renderResearchTasks();\n }\n\n async function refreshStrategyProfiles() {\n state.bootMessageKey = \"bootStrategy\";\n render();\n try {\n const payload = await requestJson(\"/api/strategy-profiles\");\n applyStrategyProfiles(payload.strategyProfiles || []);\n if (payload.platformMeta) platformMeta = payload.platformMeta;\n for (const platform of Object.keys(platformMeta)) syncStrategyForAccount(platform);\n render();\n } catch {\n applyStrategyProfiles(defaultStrategyProfiles);\n for (const platform of Object.keys(platformMeta)) syncStrategyForAccount(platform);\n }\n }\n\n async function refreshConfig() {\n if (!state.auth.available || !state.auth.allowed) return;\n state.configSource = \"loading\";\n state.bootMessageKey = \"bootConfig\";\n render();\n try {\n const payload = await requestJson(\"/api/config\");\n if (payload.accountOptions) {\n applyStrategyProfiles(payload.strategyProfiles || []);\n state.accountOptions = normalizeAccountOptions(payload.accountOptions);\n if (payload.platformMeta) platformMeta = payload.platformMeta;\n state.repositories = normalizePlatformRepositories(payload.platformRepositories || {});\n state.currentStrategies = normalizeCurrentStrategies(payload.currentStrategies || {});\n state.configSource = \"private\";\n for (const platform of Object.keys(platformMeta)) {\n ensureAccountSelection(platform);\n syncStrategyForAccount(platform);\n }\n } else {\n state.configSource = \"default\";\n state.currentStrategies = {};\n }\n } catch (error) {\n state.configSource = \"default\";\n state.currentStrategies = {};\n if (isRequestTimeoutError(error)) {\n state.bootMessageKey = \"bootTimeout\";\n } else {\n state.bootMessageKey = \"bootPublic\";\n }\n } finally {\n state.lastRefreshAt = new Date().toISOString();\n state.appReady = true;\n render();\n }\n }\n\n function normalizeAccountOptions(raw) {\n const normalized = clone(defaultAccountOptions);\n for (const platform of Object.keys(platformMeta)) {\n if (!Array.isArray(raw[platform]) || !raw[platform].length) continue;\n normalized[platform] = raw[platform].map((item, index) => ({\n key: String(item.key || item.target_name || index),\n label: String(item.label || item.target_name || item.key || platform),\n target_name: String(item.target_name || item.key || \"\"),\n account_selector: item.account_selector ? String(item.account_selector) : \"\",\n broker_environment: normalizeExecutionEnvironment(item.broker_environment),\n execution_environment: normalizeExecutionEnvironment(item.execution_environment),\n deployment_selector: item.deployment_selector ? String(item.deployment_selector) : \"\",\n account_scope: item.account_scope ? String(item.account_scope) : \"\",\n service_name: item.service_name ? String(item.service_name) : \"\",\n runtime_status_target_id: String(item.runtime_status_target_id || \"\"),\n cash_currency: item.cash_currency || item.market_currency || item.trading_currency\n ? String(item.cash_currency || item.market_currency || item.trading_currency).trim().toUpperCase()\n : \"\",\n default_execution_mode: normalizeExecutionMode(item.default_execution_mode) || \"\",\n supported_domains: normalizeSupportedDomains(platform, item),\n github_environment: item.github_environment ? String(item.github_environment) : \"\",\n variable_scope: item.variable_scope ? String(item.variable_scope) : \"\",\n plugin_mode: item.plugin_mode ? String(item.plugin_mode) : \"\",\n option_overlay_mode: item.option_overlay_mode ? normalizeOptionOverlayMode(item.option_overlay_mode) : \"\",\n cash_only_execution_mode: item.cash_only_execution_mode\n ? normalizeCashOnlyExecutionMode(item.cash_only_execution_mode)\n : \"\",\n dca_mode: item.dca_mode ? normalizeDcaMode(item.dca_mode) : \"\",\n dca_base_investment_usd: cleanDisplayPositiveNumber(item.dca_base_investment_usd),\n }));\n }\n return normalized;\n }\n\n function normalizeSupportedDomains(platform, item) {\n const raw = Array.isArray(item?.supported_domains)\n ? item.supported_domains\n : String(item?.supported_domains || \"\").split(/[\\s,;]+/);\n const cleaned = raw.map(cleanStrategyDomain).filter(Boolean);\n if (cleaned.length) return [...new Set(cleaned)];\n return inferSupportedDomains(platform, item || {});\n }\n\n function normalizeCurrentStrategies(raw) {\n const normalized = {};\n for (const platform of Object.keys(platformMeta)) {\n if (!raw[platform] || typeof raw[platform] !== \"object\" || Array.isArray(raw[platform])) continue;\n normalized[platform] = {};\n for (const [key, entry] of Object.entries(raw[platform])) {\n const profile = cleanStrategyProfile(entry?.strategy_profile);\n const minReservedCashUsd = cleanDisplayNumber(entry?.min_reserved_cash_usd ?? entry?.reserved_cash_floor_usd);\n const reservedCashRatio = cleanDisplayRatio(entry?.reserved_cash_ratio);\n const incomeLayerEnabled = cleanOptionalBoolean(entry?.income_layer_enabled);\n const incomeLayerStartUsd = cleanDisplayNumber(entry?.income_layer_start_usd);\n const incomeLayerMaxRatio = cleanDisplayRatio(entry?.income_layer_max_ratio);\n const optionOverlayEnabled = cleanOptionalBoolean(entry?.option_overlay_enabled);\n const cashOnlyExecution = cleanOptionalBoolean(entry?.cash_only_execution);\n const runtimeTargetEnabled = cleanOptionalBoolean(entry?.runtime_target_enabled);\n const dcaMode = entry?.dca_mode ? normalizeDcaMode(entry.dca_mode) : \"\";\n const dcaBaseInvestmentUsd = cleanDisplayPositiveNumber(entry?.dca_base_investment_usd);\n const executionModeRaw = String(entry?.execution_mode || \"\").trim().toLowerCase();\n const executionEnvironment = normalizeExecutionEnvironment(entry?.execution_environment);\n const executionMode = normalizeExecutionMode(executionModeRaw, entry?.dry_run_only);\n const dryRunOnly = cleanOptionalBoolean(entry?.dry_run_only);\n if (\n !profile &&\n !minReservedCashUsd &&\n !reservedCashRatio &&\n incomeLayerEnabled === null &&\n !incomeLayerStartUsd &&\n !incomeLayerMaxRatio &&\n optionOverlayEnabled === null &&\n cashOnlyExecution === null &&\n runtimeTargetEnabled === null &&\n !dcaMode &&\n !dcaBaseInvestmentUsd &&\n !executionMode &&\n !executionEnvironment\n ) continue;\n normalized[platform][String(key)] = {\n strategy_profile: profile,\n execution_mode: executionMode,\n execution_mode_raw: executionModeRaw,\n execution_environment: executionEnvironment,\n dry_run_only: dryRunOnly,\n min_reserved_cash_usd: minReservedCashUsd,\n reserved_cash_ratio: reservedCashRatio,\n income_layer_enabled: incomeLayerEnabled,\n income_layer_start_usd: incomeLayerStartUsd,\n income_layer_max_ratio: incomeLayerMaxRatio,\n option_overlay_enabled: optionOverlayEnabled,\n cash_only_execution: cashOnlyExecution,\n runtime_target_enabled: runtimeTargetEnabled,\n binance_resume_target_sha256: /^[a-f0-9]{64}$/.test(entry?.binance_resume_target_sha256 || \"\")\n ? entry.binance_resume_target_sha256 : \"\",\n dca_mode: dcaMode,\n dca_base_investment_usd: dcaBaseInvestmentUsd,\n source: entry?.source ? String(entry.source) : \"\",\n };\n }\n if (!Object.keys(normalized[platform]).length) delete normalized[platform];\n }\n return normalized;\n }\n\n function normalizePlatformRepositories(raw) {\n const normalized = clone(defaultRepositories);\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return normalized;\n for (const platform of Object.keys(platformMeta)) {\n const repository = String(raw[platform] || \"\").trim();\n if (/^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/.test(repository)) {\n normalized[platform] = repository;\n }\n }\n return normalized;\n }\n\n function binanceResumeDigest() {\n if (!state.auth.allowed || state.configSource !== \"private\" || state.selected !== \"binance\") return \"\";\n const entry = currentEntryForAccount(\"binance\", selectedAccount(\"binance\"));\n return entry?.runtime_target_enabled === false ? entry.binance_resume_target_sha256 || \"\" : \"\";\n }\n\n function renderBinanceResume() {\n const visible = Boolean(binanceResumeDigest());\n el(\"binance-resume-panel\").hidden = !visible;\n el(\"binance-resume-button\").disabled = !visible || binanceResumeLock.pending;\n el(\"binance-resume-status\").textContent = binanceResumeLock.messageKey ? t(binanceResumeLock.messageKey) : \"\";\n }\n\n async function dispatchBinanceResume() {\n if (binanceResumeLock.pending || !state.auth.allowed || state.selected !== \"binance\") return;\n const digest = binanceResumeDigest();\n const account = selectedAccount(\"binance\");\n if (!digest || !account?.target_name || !window.confirm(t(\"binanceResumeConfirm\"))) return;\n binanceResumeLock.pending = true;\n binanceResumeLock.messageKey = \"dispatching\";\n render();\n try {\n const response = await fetch(\"/api/runtime-resume\", {\n method: \"POST\", headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform: \"binance\", target_name: account.target_name,\n runtime_target_sha256: digest, confirm: \"RESUME_EXISTING\" }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(\"resume submission unverified\");\n binanceResumeLock.messageKey = \"binanceResumePending\";\n if (payload.actions_url) window.open(payload.actions_url, \"_blank\", \"noopener,noreferrer\");\n } catch {\n binanceResumeLock.messageKey = \"binanceResumeUnknown\";\n }\n // Keep the lock after success or an uncertain write. Refresh only after\n // inspecting the existing workflow; no automatic retry or trading call.\n render();\n showToast(t(binanceResumeLock.messageKey), { duration: 12000 });\n }\n\n async function dispatchRuntimeStop() {\n if (runtimeStopLock.pending || !state.auth.allowed || !window.confirm(t(\"runtimeStopConfirm\"))) return;\n const account = selectedAccount(state.selected);\n if (!account?.target_name) return;\n runtimeStopLock.pending = true;\n const dispatch = el(\"dispatch-button\");\n if (dispatch) dispatch.disabled = true;\n showToast(t(\"dispatching\"), { duration: 0 });\n try {\n const response = await fetch(\"/api/runtime-stop\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform: state.selected, target_name: account.target_name, confirm: \"STOP_ONLY\" }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"dispatchFailed\"));\n showToast(t(\"runtimeStopPending\"), { duration: 12000 });\n if (payload.actions_url) window.open(payload.actions_url, \"_blank\", \"noopener,noreferrer\");\n } catch (error) {\n showToast(`${t(\"dispatchFailed\")}: ${error.message}`, { duration: 12000 });\n }\n // A timeout does not prove GitHub rejected the request. Keep the main\n // control locked until the operator reloads after checking the existing run.\n }\n\n async function dispatchSwitch() {\n if (!state.auth.allowed) return;\n if (normalizeRuntimeTargetMode(state.forms[state.selected]?.runtimeTargetMode) === \"disabled\") {\n return dispatchRuntimeStop();\n }\n showToast(t(\"dispatching\"), { duration: 0 });\n try {\n const response = await fetch(\"/api/switch\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(buildInputs()),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"dispatchFailed\"));\n showToast(t(\"dispatched\"), { duration: 4000 });\n if (payload.actions_url) window.open(payload.actions_url, \"_blank\", \"noopener,noreferrer\");\n await refreshConfig();\n } catch (error) {\n showToast(`${t(\"dispatchFailed\")}: ${error.message}`, { duration: 12000 });\n }\n }\n\n async function handleLogout() {\n state.auth = { available: true, allowed: false, admin: false, login: null };\n clearBinancePrivateScope();\n renderBinancePrivateScope();\n await fetch(\"/api/logout\", { method: \"POST\" });\n window.location.reload();\n }\n\n function summaryText() {\n const inputs = buildInputs();\n return summaryRows(inputs).map(([label, value]) => `${label}: ${value}`).join(\"\\\n\");\n }\n\n document.querySelectorAll(\"[data-workspace]\").forEach(button => button.addEventListener(\"click\", () => {\n state.view = button.dataset.workspace;\n render();\n el(\"workspace-title\").focus({ preventScroll: true });\n window.scrollTo({ top: 0 });\n }));\n\n document.querySelectorAll(\"[data-overview-filter]\").forEach(button => button.addEventListener(\"click\", () => {\n state.overviewFilter = button.dataset.overviewFilter;\n renderOverview();\n }));\n el(\"overview-search\").addEventListener(\"input\", () => {\n state.overviewSearch = el(\"overview-search\").value;\n renderOverview();\n });\n el(\"overview-reset\").addEventListener(\"click\", () => {\n state.overviewFilter = \"all\";\n state.overviewSearch = \"\";\n el(\"overview-search\").value = \"\";\n renderOverview();\n el(\"overview-search\").focus();\n });\n document.querySelectorAll(\"[data-research-internal-view]\").forEach((button) => button.addEventListener(\"click\", () => {\n state.researchInternalView = button.dataset.researchInternalView === \"research\" ? \"research\" : \"monitoring\";\n renderWorkspace();\n if (state.researchInternalView === \"research\") {\n refreshHealth();\n refreshReconciliationRecovery();\n refreshM0Research();\n refreshAdaptiveSelection();\n refreshExecutionEvidence();\n refreshResearchTasks();\n refreshResearchPromotionTickets();\n } else {\n refreshRuntimeTargetLifecycle();\n }\n }));\n\n document.querySelectorAll(\"[data-health-filter]\").forEach((button) => button.addEventListener(\"click\", () => {\n document.querySelectorAll(\"[data-health-filter]\").forEach((node) => node.classList.remove(\"active\"));\n button.classList.add(\"active\");\n state.health.filter = button.dataset.healthFilter;\n renderHealth();\n }));\n\n el(\"control-plane-list\").addEventListener(\"click\", (event) => {\n const button = event.target.closest(\"[data-owner-decision]\");\n if (!button || button.disabled) return;\n recordOwnerDecision(button);\n });\n\n el(\"reconciliation-recovery-list\").addEventListener(\"click\", (event) => {\n const button = event.target.closest(\"[data-reconciliation-recovery-confirm]\");\n if (!button || button.disabled) return;\n recordReconciliationRecoveryConfirmation(button);\n });\n\n el(\"account-diagnosis-button\").addEventListener(\"click\", event => {\n dispatchAccountDiagnosis(event.currentTarget);\n });\n el(\"monitoring-overview-body\").addEventListener(\"click\", event => {\n const button = event.target.closest(\"[data-account-diagnosis]\");\n if (!button || button.disabled) return;\n dispatchAccountDiagnosis(button);\n });\n\n el(\"platform-strip\").addEventListener(\"click\", (event) => {\n const button = event.target.closest(\"[data-platform]\");\n if (!button) return;\n state.selected = button.dataset.platform;\n state.forms[state.selected].strategyTouched = false;\n render();\n });\n\n el(\"refresh-status-button\").addEventListener(\"click\", async () => {\n if (!state.auth.allowed) return;\n const button = el(\"refresh-status-button\");\n state.refreshing = true;\n button.disabled = true;\n button.textContent = t(\"refreshingStatus\");\n try {\n await Promise.all([\n refreshConfig(),\n refreshRuntimeTargetLifecycle(),\n refreshReconciliationRecovery(),\n refreshBinancePrivateScope(),\n refreshResearchPromotionTickets(),\n refreshControlPlane(),\n refreshOwnerDecisions(),\n ]);\n await refreshAccountDiagnosis();\n } finally {\n state.refreshing = false;\n state.lastRefreshAt = new Date().toISOString();\n render();\n button.disabled = false;\n button.textContent = t(\"refreshStatus\");\n }\n });\n\n el(\"account-select\").addEventListener(\"change\", () => {\n state.forms[state.selected].accountKey = el(\"account-select\").value;\n state.forms[state.selected].runtimeTargetTouched = false;\n state.forms[state.selected].reservedCashTouched = false;\n state.forms[state.selected].incomeLayerTouched = false;\n state.forms[state.selected].optionOverlayTouched = false;\n state.forms[state.selected].cashOnlyExecutionTouched = false;\n state.forms[state.selected].dcaTouched = false;\n state.forms[state.selected].strategyTouched = false;\n state.forms[state.selected].executionModeTouched = false;\n state.forms[state.selected].pluginModeTouched = false;\n syncStrategyForAccount(state.selected);\n render();\n refreshAccountDiagnosis();\n });\n\n el(\"strategy-select\").addEventListener(\"change\", () => {\n state.forms[state.selected].strategy = el(\"strategy-select\").value;\n state.forms[state.selected].strategyTouched = true;\n state.forms[state.selected].incomeLayerTouched = false;\n state.forms[state.selected].optionOverlayTouched = false;\n state.forms[state.selected].dcaTouched = false;\n syncIncomeLayerForAccount(state.selected);\n syncOptionOverlayForAccount(state.selected);\n syncDcaForAccount(state.selected);\n render();\n });\n\n el(\"execution-mode-select\").addEventListener(\"change\", () => {\n const mode = el(\"execution-mode-select\").value;\n if (!supportedExecutionModesForPlatform(state.selected).includes(mode)) return;\n state.forms[state.selected].executionMode = mode;\n state.forms[state.selected].executionModeTouched = true;\n render();\n });\n\n el(\"plugin-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.pluginMode = normalizePluginMode(el(\"plugin-mode-select\").value);\n form.pluginModeTouched = true;\n render();\n });\n\n el(\"runtime-target-enabled-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.runtimeTargetMode = normalizeRuntimeTargetMode(el(\"runtime-target-enabled-select\").value);\n form.runtimeTargetTouched = form.runtimeTargetMode !== \"current\";\n render();\n });\n\n el(\"income-layer-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.incomeLayerMode = normalizeIncomeLayerMode(el(\"income-layer-mode-select\").value);\n form.incomeLayerTouched = form.incomeLayerMode !== \"current\";\n if (form.incomeLayerMode === \"current\") {\n form.incomeLayerTouched = false;\n syncIncomeLayerForAccount(state.selected);\n }\n render();\n });\n\n el(\"income-layer-start-usd-input\").addEventListener(\"input\", () => {\n const form = state.forms[state.selected];\n form.incomeLayerTouched = true;\n form.incomeLayerMode = \"enabled\";\n form.incomeLayerStartUsd = el(\"income-layer-start-usd-input\").value.trim();\n render();\n });\n\n el(\"income-layer-max-ratio-input\").addEventListener(\"input\", () => {\n const form = state.forms[state.selected];\n form.incomeLayerTouched = true;\n form.incomeLayerMode = \"enabled\";\n form.incomeLayerMaxRatio = el(\"income-layer-max-ratio-input\").value.trim();\n render();\n });\n\n el(\"option-overlay-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.optionOverlayMode = normalizeOptionOverlayMode(el(\"option-overlay-mode-select\").value);\n form.optionOverlayTouched = form.optionOverlayMode !== \"current\";\n render();\n });\n\n el(\"cash-only-execution-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.cashOnlyExecutionMode = normalizeCashOnlyExecutionMode(el(\"cash-only-execution-mode-select\").value);\n form.cashOnlyExecutionTouched = form.cashOnlyExecutionMode !== \"current\";\n if (allowMarginExplicitlySelected(form)) reconcileExecutionCashPolicy(form, \"margin\");\n else restoreReserveAfterMarginDisabled(form);\n render();\n });\n\n el(\"dca-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.dcaTouched = true;\n form.dcaMode = normalizeDcaMode(el(\"dca-mode-select\").value);\n render();\n });\n\n el(\"dca-base-investment-usd-input\").addEventListener(\"input\", () => {\n const form = state.forms[state.selected];\n form.dcaTouched = true;\n form.dcaBaseInvestmentUsd = el(\"dca-base-investment-usd-input\").value.trim();\n render();\n });\n\n el(\"reserve-policy-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.reservePolicyMode = normalizeReservePolicyMode(el(\"reserve-policy-mode-select\").value);\n form.reservedCashTouched = form.reservePolicyMode !== \"current\";\n if (form.reservePolicyMode === \"current\") syncReservePolicyForAccount(state.selected);\n reconcileExecutionCashPolicy(form, \"reserve\");\n render();\n });\n\n el(\"min-reserved-cash-input\").addEventListener(\"input\", () => {\n state.forms[state.selected].reservedCashTouched = true;\n state.forms[state.selected].minReservedCashUsd = el(\"min-reserved-cash-input\").value.trim();\n render();\n });\n\n el(\"reserved-cash-ratio-input\").addEventListener(\"input\", () => {\n state.forms[state.selected].reservedCashTouched = true;\n state.forms[state.selected].reservedCashRatio = el(\"reserved-cash-ratio-input\").value.trim();\n render();\n });\n\n el(\"copy-button\").addEventListener(\"click\", async () => {\n try {\n await navigator.clipboard.writeText(summaryText());\n showToast(t(\"copied\"), { duration: 3000 });\n } catch {\n showToast(summaryText(), { duration: 0 });\n }\n });\n\n el(\"dispatch-button\").addEventListener(\"click\", dispatchSwitch);\n el(\"binance-resume-button\").addEventListener(\"click\", dispatchBinanceResume);\n el(\"logout-button\").addEventListener(\"click\", handleLogout);\n el(\"lang-button\").addEventListener(\"click\", () => {\n state.lang = state.lang === \"zh\" ? \"en\" : \"zh\";\n localStorage.setItem(\"qsl-switch-lang\", state.lang);\n render();\n });\n\n applyStrategyProfiles(defaultStrategyProfiles);\n for (const platform of Object.keys(platformMeta)) syncStrategyForAccount(platform);\n render();\n boot();\n\n async function boot() {\n try {\n await refreshStrategyProfiles();\n await refreshSession();\n } catch {\n state.auth = { available: false, allowed: false, admin: false, login: null };\n clearBinancePrivateScope();\n state.configSource = \"default\";\n state.currentStrategies = {};\n state.bootMessageKey = \"bootTimeout\";\n state.appReady = true;\n render();\n }\n }\n"; +export const APP_JS = "\n\n function requiredInjected(name, value, fallback) {\n if (value !== undefined && value !== null) return value;\n console.error(`[strategy-switch-console] missing injected config: ${name}`);\n return fallback;\n }\n\n let platformMeta = window.__PLATFORM_META__ || {};\n const platformRepositories = window.__PLATFORM_REPOSITORIES__ || {};\n // Alias for backward compatibility\n const defaultRepositories = platformRepositories;\n\n const defaultAccountOptions = requiredInjected(\"__DEFAULT_ACCOUNT_OPTIONS__\", window.__DEFAULT_ACCOUNT_OPTIONS__, {});\n\n const domainLabels = window.__DOMAIN_LABELS__ || {\n cn_equity: { zh: \"A股\", en: \"CN A-share\" },\n crypto: { zh: \"加密\", en: \"Crypto\" },\n hk_equity: { zh: \"港股\", en: \"HK Equity\" },\n us_equity: { zh: \"美股\", en: \"US Equity\" },\n };\n\n const platformConfig = requiredInjected(\"__PLATFORM_CONFIG__\", window.__PLATFORM_CONFIG__, {});\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n const reservePolicyModes = [\"none\", \"ratio\", \"floor\", \"max\"];\n const incomeLayerModes = [\"enabled\", \"disabled\"];\n const optionOverlayModes = [\"enabled\", \"disabled\"];\n const cashOnlyExecutionModes = [\"enabled\", \"disabled\"];\n const runtimeTargetModes = [\"current\", \"enabled\", \"disabled\"];\n const pluginModes = [\"none\"];\n const dcaModes = [\"fixed\", \"smart\"];\n const runtimeTargetEnabledVariable = \"RUNTIME_TARGET_ENABLED\";\n const incomeLayerEnabledVariable = \"INCOME_LAYER_ENABLED\";\n const incomeLayerStartUsdVariable = \"INCOME_LAYER_START_USD\";\n const incomeLayerMaxRatioVariable = \"INCOME_LAYER_MAX_RATIO\";\n const dcaProfileDefaults = requiredInjected(\"__DCA_PROFILE_DEFAULTS__\", window.__DCA_PROFILE_DEFAULTS__, {});\n const APP_BOOT_TIMEOUT_MS = 15000;\n const platformMinReservedCashVariables = requiredInjected(\"__PLATFORM_MIN_RESERVED_CASH_VARIABLES__\", window.__PLATFORM_MIN_RESERVED_CASH_VARIABLES__, {});\n const platformReservedCashRatioVariables = requiredInjected(\"__PLATFORM_RESERVED_CASH_RATIO_VARIABLES__\", window.__PLATFORM_RESERVED_CASH_RATIO_VARIABLES__, {});\n\n const defaultStrategyProfiles = requiredInjected(\"__DEFAULT_STRATEGY_PROFILES__\", window.__DEFAULT_STRATEGY_PROFILES__, []);\n\n const localStrategyLabels = {\n tqqq_growth_income: { zh: \"纳斯达克增长收益\", en: \"NASDAQ Growth Income\" },\n soxl_soxx_trend_income: { zh: \"半导体趋势收益\", en: \"Semiconductor Trend Income\" },\n nasdaq_sp500_smart_dca: { zh: \"纳指标普定投\", en: \"NASDAQ/S&P 500 DCA\" },\n ibit_smart_dca: { zh: \"IBIT比特币定投\", en: \"IBIT Bitcoin DCA\" },\n global_etf_rotation: { zh: \"全球ETF轮动\", en: \"Global ETF Rotation\" },\n russell_top50_leader_rotation: { zh: \"罗素Top50领涨\", en: \"Russell Top50 Leaders\" },\n hk_global_etf_tactical_rotation: { zh: \"港股ETF战术轮动\", en: \"HK ETF Tactical Rotation\" },\n hk_low_vol_dividend_quality_snapshot: { zh: \"港股红利质量\", en: \"HK Dividend Quality\" },\n cn_industry_etf_rotation: { zh: \"A股行业ETF轮动\", en: \"CN Industry ETF Rotation\" },\n cn_dividend_quality_snapshot: { zh: \"A股红利质量\", en: \"CN Dividend Quality\" },\n us_equity_combo: { zh: \"美股核心组合\", en: \"US Core Combo\" },\n us_equity_combo_leveraged: { zh: \"美股加速组合\", en: \"US Alpha Combo\" },\n hk_equity_combo: { zh: \"港股恒生组合\", en: \"HK Core Combo\" },\n cn_industry_etf_rotation_aggressive: { zh: \"A股ETF轮动\", en: \"CN ETF Rotation\" },\n cn_stock_momentum_rotation: { zh: \"A股个股动量\", en: \"CN Stock Momentum\" },\n cn_equity_combo: { zh: \"A股进取组合\", en: \"CN Alpha Combo\" },\n crypto_btc_dca: { zh: \"BTC定投\", en: \"BTC DCA\" },\n crypto_trend_rotation: { zh: \"山寨趋势轮动\", en: \"Altcoin Trend\" },\n crypto_equity_combo: { zh: \"加密动量组合\", en: \"Crypto Core Combo\" },\n };\n\n const fallbackIncomeLayerDefaults = requiredInjected(\"__INCOME_LAYER_DEFAULTS__\", window.__INCOME_LAYER_DEFAULTS__, {});\n let incomeLayerDefaults = {};\n const fallbackOptionOverlayDefaults = requiredInjected(\"__OPTION_OVERLAY_DEFAULTS__\", window.__OPTION_OVERLAY_DEFAULTS__, {});\n let optionOverlayDefaults = {};\n\n const strategyDomains = [\"us_equity\", \"hk_equity\", \"cn_equity\", \"crypto\"];\n let strategyOptions = [];\n let strategyLabels = {};\n let strategyCatalog = {};\n\n\n const copy = {\n zh: {\n appTitle: \"QuantStrategyLab\",\n appSubtitle: \"管理控制台\",\n workspaceNavigation: \"管理页面\",\n overviewNav: \"运行总览\",\n accountsNav: \"账户管理\",\n researchNav: \"研究与确认\",\n overviewDescription: \"先看有没有必须你确认的事,再扫账户是否异常;改配置放到账户管理。\",\n accountsDescription: \"先看读回状态;要改开关或策略时再展开设置。提交只记意图,不等于成交。\",\n researchDescription: \"只处理有材料的候选与晋级确认;接受意图不等于实盘授权。\",\n accountsTitle: \"账户\",\n accountFilters: \"筛选账户\",\n filterAll: \"全部\",\n filterNormal: \"正常\",\n filterPaused: \"暂停\",\n filterAbnormal: \"异常\",\n searchAccounts: \"搜索账户或策略\",\n overviewRuntime: \"运行情况\",\n latestReadback: \"最近检查\",\n accountActions: \"账户操作\",\n viewAccount: \"查看\",\n viewAccountLabel: \"查看 {account}\",\n overviewEvidenceNote: \"状态来自最近检查;保存配置不代表策略已经运行或有成交。\",\n clearFilters: \"清除筛选\",\n viewUnverified: \"查看待核实账户\",\n overviewUnverifiedTitle: \"实际运行状态尚未完整读回\",\n overviewUnverifiedDescription: \"启用配置不代表策略已开始运行。\",\n overviewAttentionTitle: \"有账户需要核对\",\n overviewAttentionDescription: \"有账户的配置还没同步,或最近检查需要查看。请打开对应账户。\",\n overviewReadTitle: \"配置与最近检查一致\",\n overviewReadDescription: \"开关已经同步;策略运行和成交请以运行报告为准。\",\n overviewLoadingTitle: \"正在读取账户状态\",\n overviewLoadingDescription: \"配置和运行读回将分别显示,请稍候。\",\n overviewUnavailableTitle: \"暂时未读到账户配置\",\n overviewUnavailableDescription: \"请刷新重试。读不到的状态会显示为异常,并标明原因。\",\n overviewEmptyTitle: \"没有匹配的账户\",\n overviewEmptyDescription: \"试试其他关键词,或清除当前筛选。\",\n overviewNoAccountsTitle: \"暂无可显示的账户\",\n overviewNoAccountsDescription: \"当前没有可显示的账户配置。\",\n accountResults: \"{count} / {total} 个账户\",\n pageRefreshed: \"本页刷新 {time}\",\n pageNotRefreshed: \"等待读取\",\n savedState: \"配置:{state}\",\n overviewActualUnknown: \"实际待核实\",\n overviewRuntimeNormal: \"正常\",\n overviewRuntimePaused: \"暂停\",\n overviewRuntimeAbnormal: \"异常\",\n overviewRuntimeReasonPending: \"检查未完成\",\n overviewRuntimeReasonMissing: \"尚未收到运行检查\",\n accountRuntimeSummary: \"运行状态摘要\",\n monitoringViewReason: \"查看原因\",\n accountDiagnosisButton: \"AI诊断\",\n accountDiagnosisSubmitting: \"诊断中…\",\n accountDiagnosisQueuedButton: \"排队中…\",\n accountDiagnosisRunningButton: \"诊断中…\",\n accountDiagnosisRecheckingButton: \"复查中…\",\n accountDiagnosisQueued: \"已排队等待诊断\",\n accountDiagnosisDispatchUnknown: \"提交结果未确认,请稍后重新检查\",\n accountDiagnosisRunning: \"正在诊断\",\n accountDiagnosisRechecking: \"正在复查\",\n accountDiagnosisSuccess: \"检查正常\",\n accountDiagnosisNeedsReview: \"仍需处理:{summary}\",\n accountDiagnosisRecheckUnknown: \"复查结果未确认,请重新检查状态\",\n accountDiagnosisRecheckUnavailable: \"复查资料还不完整,请重新检查状态\",\n accountDiagnosisFailed: \"诊断未完成:{reason}\",\n accountDiagnosisUnavailable: \"暂时无法诊断,请先完成状态检查\",\n overviewRuntimeReasonStale: \"检查已过期({age})\",\n overviewRuntimeReasonConfig: \"配置未同步\",\n overviewRuntimeReasonSwitch: \"开关未同步\",\n overviewRuntimeReasonStrategy: \"策略未同步\",\n overviewRuntimeReasonSchedule: \"调度未同步\",\n overviewRuntimeReasonAttention: \"最近检查发现问题\",\n viewResearch: \"前往研究页\",\n researchPendingCount: \"研究页有 {count} 条可审候选\",\n researchIntro: \"研究候选与当前运行分开管理。\",\n monitoringDiagnosticsView: \"监控诊断\",\n researchCandidatesView: \"研究候选\",\n accountDetailAction: \"下一步\",\n loginTitle: \"管理你的量化平台\",\n loginDescription: \"配置策略,关注运行,处理重要决策。\",\n loginUnavailable: \"暂时无法确认登录状态,请重新登录。\",\n loginDenied: \"当前账号没有访问权限,请切换账号。\",\n languageToggle: \"切换语言\",\n consoleNavigation: \"管理台导航\",\n dataFreshness: \"数据更新时间\",\n decisionSummary: \"待办摘要\",\n healthSummary: \"策略健康摘要\",\n healthFilters: \"筛选策略健康状态\",\n controlPlaneView: \"待办确认\",\n healthView: \"运行概览\",\n switchView: \"平台设置\",\n refreshStatus: \"刷新状态\",\n refreshingStatus: \"读取中…\",\n configTruthNote: \"配置值不代表云端实际状态。\",\n configuredSwitch: \"配置开关\",\n observedRuntime: \"最近运行检查\",\n deployedSwitch: \"实际开关\",\n schedulerState: \"自动调度\",\n applicationStatus: \"应用状态\",\n configuredStrategy: \"配置策略\",\n scheduleEnabled: \"已启用\",\n schedulePaused: \"已暂停\",\n scheduleMixed: \"部分暂停\",\n scheduleMissing: \"未找到任务\",\n scheduleUnknown: \"状态未知\",\n scheduleNotApplicable: \"不适用\",\n runtimeStateUnknown: \"状态未知\",\n deploymentUnverified: \"实际状态未知\",\n strategyNotApplied: \"策略尚未应用\",\n settingsNotApplied: \"开关尚未应用\",\n switchesApplied: \"开关已同步\",\n scheduleNotApplied: \"调度尚未同步\",\n monitoringConfigMismatch: \"配置与检查不一致\",\n runtimeUnverified: \"暂无记录\",\n monitoringUnlinked: \"待关联\",\n monitoringTime: \"记录时间\",\n monitoringDetails: \"监测详情\",\n promotionIntentPlatform: \"建议使用的平台\",\n platformManagement: \"决策与账户\",\n strategySettings: \"策略设置\",\n strategySettingsHint: \"\",\n accountNextStep: \"下一步\",\n recheckRuntimeStatus: \"重新检查状态\",\n accountScrollHint: \"左右滑动查看实际状态与下一步\",\n awaitDeploymentReadback: \"等待有效读回\",\n noSwitchAction: \"开关无需处理\",\n reviewAccountSettings: \"复核设置\",\n advancedSelectionNotice: \"\",\n advancedDetails: \"高级详情\",\n monitoringSummaryHint: \"仅展示已配置账户的记录;监测通过不代表已成交。\",\n instanceList: \"账户实例\",\n configDetails: \"配置详情\",\n openSystemStatus: \"查看高级详情\",\n noConfiguredAccounts: \"登录并读取配置后显示账户实例。\",\n\n controlPlaneEyebrow: \"待处理事项\",\n controlPlaneTitle: \"需要你决定\",\n controlPlaneSubtitle: \"这里显示仍需要你决定的事项。\",\n controlPlaneProgressTitle: \"观察进度\",\n controlPlaneProgressSubtitle: \"自动观察的最新记录,无需操作。\",\n controlPlaneMixedTitle: \"研究进度与待办\",\n controlPlaneMixedSubtitle: \"自动观察与需要确认的事项。\",\n controlCandidateTotal: \"监控对象\",\n controlDeferred: \"待复核\",\n controlParked: \"暂停中\",\n controlOwnerDecision: \"待处理\",\n controlQueueEyebrow: \"优先处理\",\n controlQueueHint: \"有风险或需要确认时才出现\",\n controlCandidateBoard: \"需要你处理\",\n controlProgressBoard: \"观察中的策略\",\n controlMixedBoard: \"研究进度与待办\",\n controlDataReady: \"已更新\",\n controlDataStale: \"更新延迟\",\n controlDataUnavailable: \"暂时无法读取\",\n controlAttentionResearchOnly: \"暂无待处理事项\",\n controlAttentionRequired: \"需要关注\",\n controlAttentionUnavailable: \"等待数据\",\n controlLoginNotice: \"登录后查看待处理事项和运行状态。\",\n controlStaleNotice: \"有些研究数据还没更新,暂时无法确认新的事项。\",\n controlUnavailableNotice: \"暂时无法读取最新状态,请稍后刷新。\",\n controlUpstreamNotice: \"有些研究数据还没准备好,暂时无法确认新的事项。\",\n controlAttentionNotice: \"有 {count} 项需要你确认。\",\n controlNormalNotice: \"目前没有需要你决定的事项。\",\n controlNormalSummary: \"暂无需要你决定的事项。你可以查看账户和研究进度。\",\n controlStaleSummary: \"数据更新后再看待办。\",\n controlUnavailableSummary: \"暂时读不到最新数据,无法确认新的事项。\",\n controlLoginSummary: \"登录后查看你的待办和系统概览。\",\n controlAttentionSummary: \"请查看下方事项并记录你的决定。\",\n decisionBackgroundSummary: \"系统进度与历史记录\",\n controlEmptyCandidates: \"当前没有待处理事项。\",\n controlNoRecommendation: \"暂未给出处理建议。\",\n controlItemMeta: \"{kind} · {domain} · 最近更新:{freshness}\",\n parkedResearchResultFallback: \"验证结果已保留,尚未进入模拟观察。\",\n parkedResearchResultSource: \"查看验证来源\",\n parkedResearchResultsTitle: \"研究记录\",\n parkedResearchResultTitle: \"SOXL 研究验证\",\n parkedResearchResultStatus: \"尚未模拟观察\",\n forwardObservationProgress: \"观察进度 {completed} / {required} 个交易日 · 最近观察 {session} · 不下单\",\n forwardObservationActive: \"继续观察\",\n forwardObservationPaused: \"保持暂停\",\n forwardObservationComplete: \"观察完成,等待复核\",\n controlNext: \"处理建议\",\n controlStatus: \"当前状态\",\n ownerDecisionTitle: \"请选择下一步\",\n ownerDecisionAdminOnly: \"请由管理员确认。\",\n ownerDecisionReady: \"数据已准备好。这里记录决定,不会直接启用交易。\",\n ownerDecisionRecorded: \"已保存:{decision}\",\n ownerDecisionApprove: \"接受建议\",\n ownerDecisionPark: \"保持暂停\",\n ownerDecisionRetire: \"停止跟踪\",\n ownerDecisionConfirm: \"确认保存此项决定?\",\n ownerDecisionSubmitting: \"正在保存…\",\n ownerDecisionSuccess: \"决定已保存。\",\n ownerDecisionFailed: \"无法保存决定\",\n reconciliationRecoveryBoard: \"恢复前确认\",\n reconciliationRecoveryLoginNotice: \"登录后查看需要恢复或复核的事项。\",\n reconciliationRecoveryStaleNotice: \"恢复信息更新延迟,请等待下一次检查。\",\n reconciliationRecoveryUnavailableNotice: \"暂时没有可用的恢复信息。\",\n reconciliationRecoveryUpstreamNotice: \"部分恢复信息暂不可用,请先查看阻断原因。\",\n reconciliationRecoveryEmpty: \"当前没有需要恢复的事项。\",\n reconciliationRecoveryTitle: \"{platform} 恢复检查\",\n reconciliationRecoveryMeta: \"{strategy}\",\n reconciliationRecoveryReason: \"这个账户已完成恢复前核对。请决定是否记录恢复意向。\",\n reconciliationRecoveryImpact: \"记录后,系统会重新核验当前状态;不会立即开始交易,也不会解除风险停用。\",\n reconciliationRecoveryTechnicalDetails: \"查看检查依据\",\n reconciliationRecoveryDetail: \"状态:{state} · 样本:{samples} · 复核:{review} · 最近更新:{lastObserved}\",\n reconciliationRecoveryBlocked: \"仍需处理:{blockers}\",\n reconciliationRecoveryReady: \"核对已完成,等待你记录恢复决定。\",\n reconciliationRecoveryAdminOnly: \"请由管理员确认。\",\n reconciliationRecoveryConfirmed: \"恢复确认已保存。\",\n reconciliationRecoveryConfirm: \"记录恢复决定\",\n reconciliationRecoveryConfirmPrompt: \"记录这项恢复决定?保存后仍需运行端重新核验,交易开关和熔断保持独立。\",\n reconciliationRecoverySubmitting: \"正在保存…\",\n reconciliationRecoverySuccess: \"恢复决定已记录,等待运行端重新核验。\",\n reconciliationRecoveryFailed: \"无法保存恢复决定\",\n reconciliationRecoveryNoOrder: \"这里仅记录决定,不会直接恢复交易。\",\n binancePrivateScopeBoard: \"Binance 私密资产清单\",\n binancePrivateScopeAccount: \"Binance 当前采集账户\",\n binancePrivateScopePrivateIdentity: \"私密账户摘要不在页面显示。\",\n binancePrivateScopeEmpty: \"empty:当前没有可显示的有效清单。\",\n binancePrivateScopeUnavailable: \"暂时无法读取私密清单。\",\n binancePrivateScopeObservedAt: \"观测时间:{time}\",\n binancePrivateScopeHistoricalWarning: \"历史差异尚未核清;清单仅供人工核对,不授予下单或处置权限。\",\n binancePrivateScopeAsset: \"资产\",\n binancePrivateScopeFree: \"可用\",\n binancePrivateScopeLocked: \"锁定\",\n executionEvidenceBoard: \"执行与成交记录\",\n executionEvidenceLoginNotice: \"登录后查看执行和成交记录。\",\n executionEvidenceStaleNotice: \"执行记录更新延迟,请结合最新平台状态判断。\",\n executionEvidenceUnavailableNotice: \"暂时没有可用的执行记录。\",\n executionEvidenceUpstreamNotice: \"部分执行记录暂不可用,请稍后重试。\",\n executionEvidenceEmpty: \"当前没有可展示的执行记录。\",\n executionEvidenceMeta: \"{platform} · 当前通道:{environment} · 来源:{source}\",\n executionEvidenceDetail: \"策略:{strategy} · 数据:{data} · 执行:{execution} · 观察:{shadow} · 模拟:{paper}\",\n executionEvidenceReceipt: \"执行回执:{outcome} · 券商确认:{confirmation}\",\n executionEvidenceReceiptMissing: \"执行回执:未采集\",\n executionEvidenceReceiptNotDue: \"未到应交易窗口\",\n executionEvidenceReceiptNoAction: \"策略未产生订单\",\n executionEvidenceReceiptRiskBlocked: \"已被风控拦截\",\n executionEvidenceReceiptSubmitted: \"已提交,尚未确认\",\n executionEvidenceReceiptAcknowledged: \"券商已确认\",\n executionEvidenceReceiptPartiallyFilled: \"部分成交\",\n executionEvidenceReceiptFilled: \"已成交\",\n executionEvidenceReceiptReconciliation: \"需要对账\",\n executionEvidenceReceiptFailed: \"执行失败,需复核\",\n executionEvidenceConfirmationNotApplicable: \"不适用\",\n executionEvidenceConfirmationNotObserved: \"未观察到确认\",\n executionEvidenceConfirmationAcknowledged: \"已确认\",\n executionEvidenceConfirmationPartiallyFilled: \"部分成交\",\n executionEvidenceConfirmationFilled: \"已成交\",\n executionEvidenceConfirmationReconciliation: \"需对账\",\n executionEvidenceNoOrder: \"查看当前执行和成交结果。\",\n executionEvidenceNext: \"处理建议\",\n runtimeTargetLifecycleBoard: \"平台运行状态\",\n runtimeTargetLifecycleLoginNotice: \"登录后查看平台运行状态。\",\n runtimeTargetLifecycleStaleNotice: \"平台状态更新延迟,请先检查运行情况。\",\n runtimeTargetLifecycleUnavailableNotice: \"暂时没有可用的平台状态。\",\n runtimeTargetLifecycleUpstreamNotice: \"部分平台状态暂不可用,请先核对。\",\n runtimeTargetLifecycleEmpty: \"当前没有可展示的平台状态。\",\n runtimeTargetLifecycleMeta: \"{platform} · {state} · 通道:{mode}\",\n runtimeTargetLifecycleDetail: \"运行监测:{guard} · 执行心跳:{heartbeat}\",\n runtimeTargetLifecycleObservation: \"本次执行:{observation} · 成交证据:{evidence}\",\n runtimeTargetLifecycleNoOrder: \"查看当前平台运行情况。\",\n runtimeTargetLifecycleNext: \"当前建议\",\n runtimeTargetLifecycleStateEnabled: \"已启用\",\n runtimeTargetLifecycleStateDisabled: \"已停用\",\n runtimeTargetLifecycleCheckPass: \"通过\",\n runtimeTargetLifecycleCheckAttention: \"需处理\",\n runtimeTargetLifecycleCheckNotDue: \"未到检查时间\",\n runtimeTargetLifecycleCheckNotApplicable: \"不适用\",\n runtimeTargetLifecycleCheckUnavailable: \"不可用\",\n runtimeTargetLifecycleObservationNotDue: \"未到应交易窗口\",\n runtimeTargetLifecycleObservationMonitoringOnly: \"最近检查通过\",\n runtimeTargetLifecycleObservationNotApplicable: \"检查时已停用\",\n runtimeTargetLifecycleObservationAttention: \"运行检查异常\",\n runtimeTargetLifecycleObservationUnavailable: \"不可用\",\n runtimeTargetLifecycleOrderEvidenceNotCollected: \"未采集订单/成交回执\",\n runtimeTargetLifecycleDispositionEnabled: \"持续监控\",\n runtimeTargetLifecycleDispositionDisabled: \"无执行验证\",\n runtimeTargetLifecycleDispositionParked: \"已暂停\",\n runtimeTargetLifecycleReasonNone: \"监测正常\",\n runtimeTargetLifecycleReasonDisabled: \"按配置停用,仍持续验证\",\n runtimeTargetLifecycleReasonRuntimeGuard: \"运行监测需要复核\",\n runtimeTargetLifecycleReasonHeartbeat: \"执行心跳需要复核\",\n runtimeTargetLifecycleReasonUnavailable: \"监测数据不可用\",\n m0ResearchBoard: \"外部研究记录\",\n m0ResearchLoginNotice: \"登录后查看外部研究记录。\",\n m0ResearchStaleNotice: \"外部研究更新延迟,仅供历史参考。\",\n m0ResearchUnavailableNotice: \"暂时没有可用的外部研究记录。\",\n m0ResearchUpstreamNotice: \"部分外部研究暂不可用,请稍后重试。\",\n m0ResearchEmpty: \"当前没有可展示的外部研究记录。\",\n m0ResearchMore: \"显示前 {count} 条研究观察。\",\n m0ResearchMeta: \"{kind} · 查看于:{viewed}\",\n m0ResearchStateFreshness: \"状态:{state} · 新鲜度:{freshness}\",\n m0ResearchHorizons: \"主要观察期:{primary} · 适用观察期:{suitable}\",\n m0ResearchEvidence: \"置信:{confidence} · 风格:{style} · 资料摘要:{digest}\",\n m0ResearchConsistency: \"当前周期分歧:{conflict} · 历史失效漂移:{drift}\",\n m0ResearchNoOrder: \"外部研究不影响当前策略运行。\",\n adaptiveSelectionBoard: \"系统建议\",\n adaptiveSelectionLoginNotice: \"登录后查看系统建议。\",\n adaptiveSelectionStaleNotice: \"建议更新延迟,仅供历史参考。\",\n adaptiveSelectionUnavailableNotice: \"暂时没有可用的系统建议。\",\n adaptiveSelectionUpstreamNotice: \"部分建议暂不可用,请稍后重试。\",\n adaptiveSelectionEmpty: \"当前没有可展示的系统建议。\",\n adaptiveSelectionMeta: \"{source} · {domain} · 市场截至 {asOf}\",\n adaptiveSelectionRecommended: \"建议观察\",\n adaptiveSelectionNoCandidate: \"暂无合适建议\",\n adaptiveSelectionReason: \"原因:{reasons}\",\n adaptiveSelectionNoOrder: \"查看系统的当前建议。\",\n adaptiveSelectionScoreLabel: \"研究次数\",\n researchTaskBoard: \"自动化任务\",\n researchTaskLoginNotice: \"登录后查看自动化任务。\",\n researchTaskStaleNotice: \"任务信息更新延迟,仅供历史参考。\",\n researchTaskUnavailableNotice: \"暂时没有可用的自动化任务。\",\n researchTaskUpstreamNotice: \"部分任务信息暂不可用,请稍后重试。\",\n researchTaskEmpty: \"当前没有可展示的自动化任务。\",\n researchTaskMeta: \"{type} · {domain} · 创建于:{created}\",\n researchTaskLimits: \"研究预算:最多 {runs} 次 / {seconds} 秒\",\n researchTaskNoOrder: \"查看当前自动化任务。\",\n healthEyebrow: \"系统状态\",\n healthTitle: \"监测与诊断\",\n healthSubtitle: \"账户、配置与监测记录,一处查看。\",\n healthTotal: \"策略总数\",\n healthHealthy: \"健康\",\n healthWatch: \"观察\",\n healthReview: \"需要复核\",\n healthCritical: \"严重\",\n healthBoard: \"策略健康\",\n healthFilterAttention: \"需要关注\",\n healthFilterAll: \"全部策略\",\n healthDataReady: \"已更新\",\n healthDataStale: \"更新延迟\",\n healthDataUnavailable: \"暂时无法读取\",\n healthComputedAt: \"更新于:{time}\",\n healthLoginNotice: \"登录后查看策略健康度和运行情况。\",\n healthStaleNotice: \"状态更新延迟;系统会继续检查。\",\n healthUnavailableNotice: \"暂时无法读取策略状态,请稍后刷新。\",\n healthUpstreamNotice: \"部分策略状态暂不可用,请稍后重试。\",\n healthNormalNotice: \"当前没有需要关注的运行问题。\",\n healthAttentionNotice: \"有 {critical} 项严重、{review} 项需要复核、{watch} 项观察;系统正在持续监测。\",\n healthEmpty: \"当前分类下没有策略。\",\n healthStatusHealthy: \"健康\",\n healthStatusWatch: \"观察\",\n healthStatusReview: \"需要复核\",\n healthStatusCritical: \"严重\",\n healthStatusUnknown: \"未知\",\n healthCardMeta: \"{status} · {domain}\",\n healthDecisionFallbackLabel: \"系统正在继续观察。\",\n healthDecisionFallbackReason: \"没有需要你处理的异常。\",\n healthRecommendationHealthy: \"系统正在正常运行。\",\n healthRecommendationWatch: \"系统正在继续观察。\",\n healthRecommendationReview: \"请查看诊断详情,等待系统复核完成。\",\n healthRecommendationCritical: \"请查看诊断详情,并暂缓相关变更。\",\n healthDetail: \"数据截至:{date}\",\n healthScoreLabel: \"健康度\",\n diagnosticDetails: \"查看诊断详情\",\n diagnosticDetailsHint: \"仅在排查问题或查看研究记录时使用。\",\n researchTaskNoOrderBadge: \"未产生订单\",\n recoveryConfirmedStatus: \"已确认\",\n recoveryReadyStatus: \"可确认\",\n recoveryBlockedStatus: \"仍受阻\",\n commonUnknown: \"未知\",\n commonNotMarked: \"未标记\",\n bootKicker: \"初始化控制台\",\n bootTitle: \"读取策略配置\",\n bootMessage: \"正在读取登录状态、账号配置和当前状态。\",\n bootStrategy: \"正在读取策略目录。\",\n bootSession: \"正在验证登录状态。\",\n bootConfig: \"正在读取账号配置和当前状态。\",\n bootTimeout: \"加载超时,已切换到公开预览(登录后可重试)。\",\n bootPublic: \"公开预览已就绪。\",\n login: \"登录\",\n logout: \"退出\",\n signedInAs: \"已登录 {login}\",\n planEyebrow: \"策略设置\",\n planTitle: \"平台设置\",\n planSubtitle: \"按账户实例管理,互不影响。\",\n planAdvancedSummary: \"高级设置\",\n planAdvancedHint: \"运行状态、插件、现金、收入层和定投通常沿用当前配置;需要改动时再展开。\",\n planScopeTitle: \"选择范围\",\n planScopeSubtitle: \"平台、账号、策略与目标环境\",\n planRuntimeTitle: \"运行保护\",\n planRuntimeSubtitle: \"停用、插件和附加层都受同一计划约束\",\n planOverlayTitle: \"策略附加层\",\n planOverlaySubtitle: \"仅使用策略已定义的默认边界\",\n planCashSubtitle: \"现金预留优先于融资;两者不能同时覆盖\",\n activePlatform: \"目标平台\",\n account: \"账户\",\n strategy: \"策略\",\n mode: \"运行方式\",\n live: \"实盘交易\",\n paper: \"模拟交易\",\n dryRun: \"无下单检查\",\n modeUnknown: \"账户类型待确认\",\n executionModeSetting: \"执行方式设置\",\n executionModeLive: \"执行交易\",\n executionModeDryRun: \"仅检查,不下单\",\n executionModeSettingMeta: \"仅修改现有执行设置;不下单检查不会写入交易订单。\",\n promotionConfirmTitle: \"确认研究候选\",\n promotionDecisionEyebrow: \"待决策\",\n promotionTargetPlatform: \"目标平台\",\n promotionBrokerEnvironment: \"券商环境\",\n promotionAccount: \"具体账户\",\n promotionExecutionMode: \"目标执行模式\",\n promotionExecutionModeReadonly: \"账户环境:{mode}\",\n promotionNoOrderCannotConfirm: \"当前账户是不下单演练;不能把它记录成券商 paper 或实盘意向。\",\n promotionRiskProfile: \"风险档\",\n promotionConfirmMeta: \"接受建议只记录研究决定,不会启用交易或替换当前策略。\",\n promotionTargetSummary: \"建议平台:{platform};当前账户:{account}。\",\n promotionClickEffect: \"点击后:只记录人工决定;{mode}账户不会因此启用交易或下单。\",\n promotionResearchSummary: \"研究简述\",\n promotionResearchSummaryMissing: \"尚未提供收益对比/策略说明。{strategy};{observation}\",\n promotionResearchSummaryMissingParts: \"未提供:{items}\",\n promotionStrategyDescription: \"策略说明:{description}\",\n promotionPluginsUnknown: \"插件:未提供\",\n promotionPluginsNone: \"插件:无\",\n promotionPlugins: \"插件:{description}\",\n promotionComparison: \"回测:{startDate}—{endDate};候选扣费后年化 {candidateCagr};候选最大回撤 {candidateDrawdown};基准扣费后年化 {baselineCagr};基准最大回撤 {baselineDrawdown}\",\n promotionLimitations: \"不足:{limitations}\",\n promotionAiExplanation: \"AI说明(仅供参考):{text}\",\n promotionTargetUnavailable: \"有研究候选待确认,但当前没有可见目标平台。\",\n promotionRiskDetails: \"风险档与账户资料\",\n promotionRiskScaleMeta: \"按控制回撤、兼顾收益与回撤、更看重收益的顺序,晋级仓位缩放为 0.50 / 0.75 / 1.00,仅适用于新晋级或数据变更;组合相对无杠杆基准的回撤上限倍数为 1.00 / 1.25 / 1.50。两者含义不同,不会据此调整现有实盘。\",\n promotionPaperUnavailable: \"该平台无券商 paper/sim,已禁用 paper\",\n promotionTicket: \"待确认候选\",\n promotionAccept: \"接受建议\",\n promotionReject: \"拒绝\",\n promotionTicketEmpty: \"当前没有待确认的研究候选。\",\n promotionTicketLoginRequired: \"请先登录(需权限账号)后再刷新\",\n promotionTicketLoadFailed: \"研究候选队列暂不可用,请刷新记录;不能据此判断没有待办。\",\n promotionAdminOnly: \"需管理员才能确认/拒绝\",\n promotionTicketSuggested: \"候选建议风险档:{profile}\",\n promotionUnnamedRecord: \"未命名策略记录 {number}\",\n promotionFlowRecord: \"流程检查记录 · 来源待核实\",\n promotionOldRecord: \"旧记录\",\n promotionParameterProposal: \"参数调整建议\",\n promotionUnverifiedCount: \"{count} 条旧记录 · 材料待核实\",\n promotionUnverifiedHint: \"这是一条旧研究记录,缺少观察材料类型,尚不能认定为已验证的策略。暂不需要接受或拒绝;补齐来源后再评估。\",\n promotionOriginalRecord: \"查看原始名称与材料\",\n promotionDecisionHint: \"先查看研究结果、风险和来源,再决定是否接受建议。\",\n promotionTicketEvidenceKind: \"观察类型:{kind}\",\n promotionTicketParams: \"建议参数:{params}\",\n promotionTicketNotification: \"说明:{body}\",\n promotionObservationReported: \"记录上报观察通过,尚不代表完整验证通过。\",\n promotionObservationFailed: \"记录上报观察未通过。\",\n promotionObservationMissing: \"记录未提供观察结果。\",\n promotionEvidenceSourceMissing: \"来源还没写清楚:记录没有观察类型,请先查看来源。\",\n promotionEvidenceNeedsReview: \"已注明观察类型,但来源和完整检查还需要查看。\",\n promotionDecisionSaved: \"已记录晋级意图(未授予实盘权限)\",\n promotionDecisionFailed: \"晋级确认失败\",\n promotionApplicationTitle: \"账户检查\",\n promotionApplicationHint: \"合格候选可部署到已确认的模拟账户;部署后保持暂停,启用是独立步骤。\",\n promotionApplicationCandidate: \"研究候选\",\n promotionApplicationAccount: \"目标账户\",\n promotionApplicationReady: \"账户和策略检查通过;系统没有提交变更。\",\n promotionApplicationBlocked: \"当前还不能使用:{reasons}。系统没有提交变更。\",\n promotionApplicationOpen: \"在账户设置中查看\",\n promotionApplicationDeploy: \"部署到模拟账户\",\n promotionApplicationQueued: \"已提交部署申请;账户会保持暂停。\",\n promotionApplicationDispatchUnknown: \"提交结果尚未确认,暂不重复提交。\",\n promotionApplicationClaimed: \"部署处理中;账户会保持暂停。\",\n promotionApplicationApplied: \"已部署并核对版本,当前暂停。\",\n promotionApplicationRejected: \"部署未通过:{reason}\",\n promotionApplicationUncertain: \"部署结果待确认,请查看最近检查。\",\n promotionApplicationEmpty: \"没有可准备的研究候选。\",\n promotionApplicationBlockActivation: \"账户应用尚未接通\",\n promotionApplicationBlockParams: \"缺少可运行的策略参数\",\n promotionApplicationBlockStrategy: \"缺少同名可运行的策略版本\",\n promotionApplicationBlockAccount: \"没有匹配的已配置账户\",\n promotionApplicationBlockEvidence: \"研究材料尚未核实\",\n promotionApplicationBlockBrokerEnvironment: \"券商环境未明确或不受支持\",\n promotionApplicationBlockPreflight: \"账户或策略检查未通过\",\n riskCapitalPreservation: \"优先控制回撤\",\n riskBalancedCompounding: \"兼顾收益与回撤\",\n riskGrowthCompounding: \"更看重收益\",\n riskEnvelopeTitle: \"账户风险信封\",\n riskEnvelopePreference: \"风险偏好\",\n riskEnvelopeCapitalBand: \"资金档\",\n riskEnvelopeStatus: \"状态灯\",\n riskEnvelopeDetailsSummary: \"详情\",\n riskEnvelopeMeta: \"只读展示;不授予实盘、不自动升档。\",\n riskEnvelopeAwaitingEquity: \"待对账权益注入\",\n riskEnvelopeUnset: \"未设定\",\n promotionModeLive: \"实盘交易\",\n promotionModePaper: \"模拟交易\",\n liveModeUnavailable: \"本次切换暂不具备实盘资格。现有账户状态请看上方。\",\n runtimeTargetMode: \"平台开关\",\n runtimeStopConfirm: \"将为当前账号提交停用。只保存并核对停用配置,不应用表单其他修改;平台是否已停止仍未知。不撤单、不平仓,不能保证在途请求结束。继续?\",\n runtimeStopPending: \"停用请求已提交。配置保存结果请查看任务;平台应用未请求,实际运行状态未知,请勿重复提交。\",\n runtimeStopReadyNote: \"已选择停用:主操作只提交严格停用配置,不要求策略重新上架,也不应用其他表单修改。\",\n runtimeSectionTitle: \"运行与插件\",\n runtimeTargetCurrent: \"\",\n runtimeTargetEnabled: \"启用\",\n runtimeTargetDisabled: \"禁用\",\n runtimeTargetModeMeta: \"保存后,系统会检查是否生效。\",\n pluginMode: \"插件状态\",\n pluginModeNone: \"不挂载旧插件\",\n pluginModeMeta: \"当前候选未绑定插件;旧插件不会自动挂载。\",\n incomeLayerMode: \"收入层状态\",\n incomeLayerSectionTitle: \"收入层\",\n incomeLayerCurrent: \"沿用当前配置\",\n incomeLayerEnabled: \"开启收入层\",\n incomeLayerDisabled: \"关闭收入层\",\n incomeLayerNotSupported: \"该策略未定义收入层\",\n incomeLayerStartUsd: \"收入层起始金额\",\n incomeLayerMaxRatio: \"收入层最高比例\",\n incomeLayerModeMeta: \"仅对已定义收入层的美股策略生效。\",\n incomeLayerDefaultMeta: \"策略默认:起始 {start},最高 {ratio}。\",\n incomeLayerAllocationMeta: \"默认分配:{allocations}。\",\n incomeLayerStartMeta: \"总资产达到该金额后启用收入层。\",\n incomeLayerRatioMeta: \"例如 0.55 表示最高 55%。\",\n optionOverlayMode: \"期权层状态\",\n optionOverlaySectionTitle: \"期权层\",\n optionOverlayCurrent: \"沿用当前配置\",\n optionOverlayEnabled: \"启用期权层\",\n optionOverlayDisabled: \"关闭期权层\",\n optionOverlayNotSupported: \"该策略未定义期权层\",\n optionOverlayModeMeta: \"启用时使用策略默认的最佳 recipe 和预算,不在这里手动调比例。\",\n optionOverlayDefaultMeta: \"{defaults}\",\n optionOverlayFamilyGrowth: \"增长\",\n optionOverlayFamilyIncome: \"收入\",\n optionOverlayBudgetRatio: \"预算 {ratio}\",\n optionOverlayRiskRatio: \"风险 {ratio}\",\n cashOnlyExecutionMode: \"允许融资\",\n cashOnlyExecutionCurrent: \"沿用当前配置\",\n cashOnlyExecutionYes: \"是\",\n cashOnlyExecutionNo: \"否\",\n cashOnlyExecutionModeMeta: \"选「否」时只按真实现金下单,不会动用 margin 购买力。\",\n cashOnlyExecutionValueYes: \"是\",\n cashOnlyExecutionValueNo: \"否\",\n currentCashOnlyExecution: \"当前允许融资\",\n pendingCashOnlyExecution: \"待提交允许融资\",\n executionCashPolicyTitle: \"资本边界\",\n executionCashPolicyNote: \"允许融资与预留现金覆盖不能同时生效;选「是」会清空预留覆盖,设预留覆盖会强制「否」。\",\n executionCashMarginBlocksReserve: \"已选允许融资;提交时会清空预留现金覆盖。\",\n executionCashReserveBlocksMargin: \"已设预留现金覆盖;提交时会强制不允许融资。\",\n qmtPlatformCashNote: \"A 股 QMT 不使用 margin / 平台预留现金;现金约束在策略参数 execution_cash_reserve_ratio 内配置。\",\n qmtDryRunOnlyNote: \"当前平台仅支持模拟运行。\",\n binancePlatformNote: \"Binance 平台不使用券商级收入层与期权层;相关功能由策略内部实现。\",\n invalidExecutionCashPolicyNote: \"允许融资与预留现金覆盖冲突,请只保留一种约束。\",\n dcaMode: \"定投模式\",\n dcaSectionTitle: \"定投\",\n dcaModeFixed: \"定额定投\",\n dcaModeSmart: \"智能定投\",\n dcaBaseInvestmentUsd: \"定投基准金额\",\n dcaModeMeta: \"仅定投策略可配置。\",\n dcaDefaultMeta: \"默认:{mode},基准金额 {amount}。\",\n dcaNotSupported: \"该策略不是定投策略\",\n dcaPlatformNotSupported: \"当前平台不支持定投策略\",\n currentDca: \"当前定投设置\",\n pendingDca: \"待提交定投设置\",\n dcaText: \"{mode},基准金额 {amount}\",\n minReservedCash: \"最小预留现金 ({currency})\",\n reservedCashRatio: \"预留现金比例\",\n reservedCashMode: \"预留现金策略\",\n reservePolicyCurrent: \"沿用当前配置\",\n reservePolicyNone: \"不设置平台预留现金\",\n reservePolicyRatio: \"仅按比例\",\n reservePolicyFloor: \"仅按固定金额\",\n reservePolicyMax: \"固定金额和比例取较大值\",\n reservedCashModeMeta: \"选择是否沿用、清空或覆盖平台预留现金。\",\n reservedCashNone: \"不设置\",\n reservedCashDefault: \"未配置(平台默认:0 {currency} / 0%)\",\n reservedCashMeta: \"固定金额下限,可单独设置或与比例取较大值。\",\n reservedCashRatioMeta: \"例如 0.03 表示 3%。\",\n summary: \"当前配置\",\n summaryCurrent: \"已保存的配置\",\n summaryPending: \"待提交变更\",\n copySummary: \"复制状态\",\n loginToRun: \"登录后提交计划\",\n loadingConfig: \"读取配置中\",\n configureAccounts: \"暂不能提交\",\n runSwitch: \"保存设置\",\n noChanges: \"无变更\",\n readonlyNote: \"登录后可保存设置。\",\n publicReadonly: \"登录后查看账号配置。\",\n loadingConfigNote: \"正在读取账号配置和当前状态。\",\n missingConfigNote: \"账号配置未加载,暂时不能执行。\",\n readyNote: \"请核对上方改动后保存。\",\n invalidStrategyNote: \"本次策略切换不满足所选运行方式的条件,暂不能提交。现有账户状态请看上方。\",\n binanceResume: \"恢复当前实盘目标\",\n binanceResumeHint: \"恢复当前实盘目标只保存启用开关,保留现有策略和资金配置。运行端仍会核验恢复记录。\",\n binanceResumeModeHint: \"恢复原目标请用上方恢复按钮;下方表单用于切换策略。\",\n binanceResumeConfirm: \"确认恢复当前 Binance 实盘目标?只保存启用开关,保留现有策略和资金配置;此表单中未保存的修改不会提交。运行端通过恢复与风险检查后才会执行。\",\n binanceResumePending: \"恢复请求已提交。请查看处理结果并刷新配置;实际恢复以平台运行记录为准。\",\n binanceResumeUnknown: \"提交结果未确认。请先查看已有处理记录,再刷新页面,避免重复提交。\",\n invalidReservePolicyNote: \"请为当前预留现金策略填写有效金额或比例。\",\n invalidIncomeLayerNote: \"请填写有效的收入层起始金额和最高比例。\",\n invalidOptionOverlayNote: \"当前策略未定义可启用的期权层。\",\n invalidDcaNote: \"请填写有效的定投模式和基准金额。\",\n noAccount: \"没有账号选项\",\n noStrategy: \"没有支持的策略\",\n repository: \"平台仓库\",\n selectedAccount: \"账号\",\n selectedMarket: \"市场\",\n currentRuntimeTarget: \"配置开关\",\n pendingRuntimeTarget: \"待提交账号状态\",\n reservedCashPolicy: \"当前预留现金\",\n currentIncomeLayer: \"当前收入层\",\n pendingIncomeLayer: \"待提交收入层\",\n currentOptionOverlay: \"当前期权层\",\n pendingOptionOverlay: \"待提交期权层\",\n pendingReservedCashPolicy: \"待提交预留现金\",\n pendingMode: \"待提交模式\",\n currentPluginMode: \"当前插件范围\",\n pendingPluginMode: \"待提交插件范围\",\n unchanged: \"不变\",\n copied: \"已复制状态\",\n dispatching: \"正在触发工作流...\",\n dispatched: \"已触发工作流\",\n dispatchFailed: \"触发失败\",\n targetMeta: \"\",\n strategyMeta: \"支持市场:{domains}\",\n strategyLifecycleMeta: \"当前门槛 {stage}\",\n strategyBlockedCountMeta: \"{count} 个策略未达 live 门槛\",\n strategyDefaultBlockedMeta: \"默认策略 {profile} 已阻断:{reason}\",\n usEquity: \"美股\",\n hkEquity: \"港股\",\n cnEquity: \"A股\",\n cryptoEquity: \"加密\",\n currentStrategy: \"当前策略\",\n nextStrategy: \"切换策略\",\n notRead: \"暂未读取\",\n runtimeTargetOn: \"启用\",\n runtimeTargetOff: \"禁用\",\n incomeLayerDefault: \"开启,{start}起 {ratio}\",\n incomeLayerOff: \"关闭\",\n incomeLayerOn: \"开启,起始 {start},最高 {ratio}\",\n optionOverlayOff: \"关闭\",\n optionOverlayOn: \"开启\",\n optionOverlayDefaultSimple: \"开启\",\n optionOverlayDefault: \"开启,{detail}\",\n cashOnlyExecutionDefault: \"仅用现金\",\n notConfigured: \"未设置\",\n strategyDefault: \"使用策略默认\",\n },\n en: {\n appTitle: \"QuantStrategyLab\",\n appSubtitle: \"Management console\",\n workspaceNavigation: \"Management pages\",\n overviewNav: \"Overview\",\n accountsNav: \"Accounts\",\n researchNav: \"Research & decisions\",\n overviewDescription: \"Check decisions first, then scan account anomalies. Change settings under Accounts.\",\n accountsDescription: \"Review readback first. Expand settings only when changing. Submit records intent, not a fill.\",\n researchDescription: \"Handle candidates with complete material only. Accepting intent is not live authority.\",\n accountsTitle: \"Accounts\",\n accountFilters: \"Filter accounts\",\n filterAll: \"All\",\n filterNormal: \"Normal\",\n filterPaused: \"Paused\",\n filterAbnormal: \"Needs attention\",\n searchAccounts: \"Search accounts or strategies\",\n overviewRuntime: \"Runtime state\",\n latestReadback: \"Latest check\",\n accountActions: \"Account actions\",\n viewAccount: \"View\",\n viewAccountLabel: \"View {account}\",\n overviewEvidenceNote: \"Status comes from the latest check. Saved settings do not prove execution or fills.\",\n clearFilters: \"Clear filters\",\n viewUnverified: \"View accounts to check\",\n overviewUnverifiedTitle: \"Actual runtime state is not fully verified\",\n overviewUnverifiedDescription: \"An enabled setting does not prove the strategy has started.\",\n overviewAttentionTitle: \"Some accounts need a closer look\",\n overviewAttentionDescription: \"An account is out of sync, or its latest check needs review. Open the affected account.\",\n overviewReadTitle: \"Settings agree with the latest check\",\n overviewReadDescription: \"The switch is synchronized. Use runtime reports for strategy execution and fills.\",\n overviewLoadingTitle: \"Reading account state\",\n overviewLoadingDescription: \"Settings and runtime readback will appear separately. Please wait.\",\n overviewUnavailableTitle: \"Account settings could not be read\",\n overviewUnavailableDescription: \"Refresh to try again. Missing state is shown as needing attention with a reason.\",\n overviewEmptyTitle: \"No matching accounts\",\n overviewEmptyDescription: \"Try another search, or clear your filters.\",\n overviewNoAccountsTitle: \"No accounts to display\",\n overviewNoAccountsDescription: \"No visible account configuration is available.\",\n accountResults: \"{count} of {total} accounts\",\n pageRefreshed: \"Page refreshed {time}\",\n pageNotRefreshed: \"Waiting for data\",\n savedState: \"Setting: {state}\",\n overviewActualUnknown: \"Unverified\",\n overviewRuntimeNormal: \"Normal\",\n overviewRuntimePaused: \"Paused\",\n overviewRuntimeAbnormal: \"Needs attention\",\n overviewRuntimeReasonPending: \"Status needs confirmation\",\n overviewRuntimeReasonMissing: \"No runtime check received\",\n overviewRuntimeReasonStale: \"Check is out of date ({age})\",\n overviewRuntimeReasonConfig: \"Settings not synchronized\",\n overviewRuntimeReasonSwitch: \"Switch not synchronized\",\n overviewRuntimeReasonStrategy: \"Strategy not synchronized\",\n overviewRuntimeReasonSchedule: \"Scheduling not synchronized\",\n overviewRuntimeReasonAttention: \"The latest check found a problem\",\n accountDiagnosisButton: \"AI diagnose\",\n accountDiagnosisSubmitting: \"Diagnosing…\",\n accountDiagnosisQueuedButton: \"Queued…\",\n accountDiagnosisRunningButton: \"Diagnosing…\",\n accountDiagnosisRecheckingButton: \"Rechecking…\",\n accountDiagnosisQueued: \"Queued for diagnosis\",\n accountDiagnosisDispatchUnknown: \"Submission not confirmed; check again shortly\",\n accountDiagnosisRunning: \"Diagnosis in progress\",\n accountDiagnosisRechecking: \"Rechecking\",\n accountDiagnosisSuccess: \"Check passed\",\n accountDiagnosisNeedsReview: \"Still needs attention: {summary}\",\n accountDiagnosisRecheckUnknown: \"Recheck result not confirmed; check status again\",\n accountDiagnosisRecheckUnavailable: \"The recheck data is incomplete; check status again\",\n accountDiagnosisFailed: \"Diagnosis did not complete: {reason}\",\n accountDiagnosisUnavailable: \"Diagnosis is unavailable until a current status check exists\",\n viewResearch: \"Go to research\",\n researchPendingCount: \"{count} reviewable candidate(s) in Research\",\n researchIntro: \"Research candidates are separate from current runtime.\",\n monitoringDiagnosticsView: \"Monitoring\",\n researchCandidatesView: \"Research candidates\",\n accountDetailAction: \"Next step\",\n loginTitle: \"Your trading workspace\",\n loginDescription: \"Configure strategies. Monitor operations. Make key decisions.\",\n loginUnavailable: \"Unable to verify your session. Please sign in again.\",\n loginDenied: \"This account does not have access. Please switch accounts.\",\n languageToggle: \"Change language\",\n consoleNavigation: \"Console navigation\",\n dataFreshness: \"Data freshness\",\n decisionSummary: \"Decision summary\",\n healthSummary: \"Strategy health summary\",\n healthFilters: \"Filter strategy health\",\n controlPlaneView: \"Decisions\",\n healthView: \"Runtime overview\",\n switchView: \"Platforms\",\n refreshStatus: \"Refresh status\",\n refreshingStatus: \"Reading…\",\n configTruthNote: \"Saved configuration is not observed runtime state.\",\n configuredSwitch: \"Configured switch\",\n observedRuntime: \"Latest runtime check\",\n deployedSwitch: \"Deployed switch\",\n schedulerState: \"Scheduling\",\n applicationStatus: \"Applied status\",\n configuredStrategy: \"Configured strategy\",\n scheduleEnabled: \"Enabled\",\n schedulePaused: \"Paused\",\n scheduleMixed: \"Partially paused\",\n scheduleMissing: \"No bound jobs\",\n scheduleUnknown: \"Unknown\",\n scheduleNotApplicable: \"Not applicable\",\n runtimeStateUnknown: \"Unknown\",\n deploymentUnverified: \"Actual state unknown\",\n strategyNotApplied: \"Strategy not applied\",\n settingsNotApplied: \"Switch not applied\",\n switchesApplied: \"Switches synchronized\",\n scheduleNotApplied: \"Scheduling not synchronized\",\n monitoringConfigMismatch: \"Configuration differs from last check\",\n runtimeUnverified: \"No record\",\n monitoringUnlinked: \"Not linked\",\n monitoringTime: \"Recorded at\",\n monitoringDetails: \"Monitoring details\",\n promotionIntentPlatform: \"Suggested platform\",\n platformManagement: \"Decisions and accounts\",\n strategySettings: \"Strategy settings\",\n strategySettingsHint: \"\",\n accountNextStep: \"Next step\",\n recheckRuntimeStatus: \"Recheck status\",\n accountScrollHint: \"Scroll horizontally for actual status and next step\",\n awaitDeploymentReadback: \"Await verified readback\",\n noSwitchAction: \"No switch action needed\",\n reviewAccountSettings: \"Review settings\",\n advancedSelectionNotice: \"\",\n advancedDetails: \"Advanced details\",\n monitoringSummaryHint: \"Records for configured accounts only. Monitoring success does not imply a fill.\",\n instanceList: \"Account instances\",\n configDetails: \"Configuration details\",\n openSystemStatus: \"View advanced details\",\n noConfiguredAccounts: \"Sign in and load configuration to view account instances.\",\n\n controlPlaneEyebrow: \"To do\",\n controlPlaneTitle: \"Decisions for you\",\n controlPlaneSubtitle: \"This is where items that still need your decision appear.\",\n controlPlaneProgressTitle: \"Observation progress\",\n controlPlaneProgressSubtitle: \"Latest automated observation. No action is needed.\",\n controlPlaneMixedTitle: \"Research progress & tasks\",\n controlPlaneMixedSubtitle: \"Automated observations and items needing your confirmation.\",\n controlCandidateTotal: \"Monitored items\",\n controlDeferred: \"To review\",\n controlParked: \"Paused\",\n controlOwnerDecision: \"To do\",\n controlQueueEyebrow: \"Priority\",\n controlQueueHint: \"Only appears when action is needed\",\n controlCandidateBoard: \"Needs your attention\",\n controlProgressBoard: \"Strategies under observation\",\n controlMixedBoard: \"Research progress & tasks\",\n controlDataReady: \"Up to date\",\n controlDataStale: \"Update delayed\",\n controlDataUnavailable: \"Unavailable\",\n controlAttentionResearchOnly: \"Nothing to do\",\n controlAttentionRequired: \"Needs attention\",\n controlAttentionUnavailable: \"Waiting for data\",\n controlLoginNotice: \"Sign in to see your to-do items and runtime status.\",\n controlStaleNotice: \"Some research data has not been updated, so new items cannot be confirmed yet.\",\n controlUnavailableNotice: \"The latest status is temporarily unavailable. Please refresh later.\",\n controlUpstreamNotice: \"Some research data is not ready, so new items cannot be confirmed yet.\",\n controlAttentionNotice: \"{count} item(s) need your decision.\",\n controlNormalNotice: \"There is nothing you need to decide right now.\",\n controlNormalSummary: \"There is nothing you need to decide right now. You can review account and research progress.\",\n controlStaleSummary: \"Check the to-do items after the data is updated.\",\n controlUnavailableSummary: \"The latest data could not be read, so new items cannot be confirmed.\",\n controlLoginSummary: \"Sign in to see your tasks and system overview.\",\n controlAttentionSummary: \"Review the items below and record your decision.\",\n decisionBackgroundSummary: \"System progress and decision history\",\n controlEmptyCandidates: \"There is nothing to handle right now.\",\n controlNoRecommendation: \"No action is recommended yet.\",\n controlItemMeta: \"{kind} · {domain} · updated {freshness}\",\n parkedResearchResultFallback: \"The validation result is retained and has not entered simulated observation.\",\n parkedResearchResultSource: \"View validation source\",\n parkedResearchResultsTitle: \"Research records\",\n parkedResearchResultTitle: \"SOXL research validation\",\n parkedResearchResultStatus: \"Not in simulated observation\",\n forwardObservationProgress: \"No-order observation progress: {completed} / {required} trading days · last observed {session}\",\n forwardObservationActive: \"Keep monitoring\",\n forwardObservationPaused: \"Keep paused\",\n forwardObservationComplete: \"Observation complete — review\",\n controlNext: \"Recommended action\",\n controlStatus: \"Current status\",\n ownerDecisionTitle: \"Choose the next step\",\n ownerDecisionAdminOnly: \"An administrator needs to confirm this.\",\n ownerDecisionReady: \"The data is ready. This records a decision; it does not enable trading.\",\n ownerDecisionRecorded: \"Saved: {decision}\",\n ownerDecisionApprove: \"Accept suggestion\",\n ownerDecisionPark: \"Keep parked\",\n ownerDecisionRetire: \"Stop tracking\",\n ownerDecisionConfirm: \"Save this decision?\",\n ownerDecisionSubmitting: \"Saving…\",\n ownerDecisionSuccess: \"Decision saved.\",\n ownerDecisionFailed: \"Could not save the decision\",\n reconciliationRecoveryBoard: \"Recovery decision\",\n reconciliationRecoveryLoginNotice: \"Sign in to see recovery and review items.\",\n reconciliationRecoveryStaleNotice: \"Recovery information is delayed. Wait for the next check.\",\n reconciliationRecoveryUnavailableNotice: \"Recovery information is temporarily unavailable.\",\n reconciliationRecoveryUpstreamNotice: \"Some recovery information is unavailable. Review the blockers first.\",\n reconciliationRecoveryEmpty: \"There are no recovery items right now.\",\n reconciliationRecoveryTitle: \"{platform} recovery check\",\n reconciliationRecoveryMeta: \"{strategy}\",\n reconciliationRecoveryReason: \"This account has completed its recovery checks. Decide whether to record recovery intent.\",\n reconciliationRecoveryImpact: \"After it is recorded, the system checks current state again. Trading does not start immediately, and risk stops stay in place.\",\n reconciliationRecoveryTechnicalDetails: \"View check evidence\",\n reconciliationRecoveryDetail: \"status: {state} · samples: {samples} · review: {review} · updated: {lastObserved}\",\n reconciliationRecoveryBlocked: \"Still needed: {blockers}\",\n reconciliationRecoveryReady: \"Checks are complete. Record your recovery decision.\",\n reconciliationRecoveryAdminOnly: \"An administrator needs to confirm this.\",\n reconciliationRecoveryConfirmed: \"Recovery confirmation saved.\",\n reconciliationRecoveryConfirm: \"Record recovery decision\",\n reconciliationRecoveryConfirmPrompt: \"Record this recovery decision? The runtime must still re-check current state; trading switches and circuit breakers remain independent.\",\n reconciliationRecoverySubmitting: \"Saving…\",\n reconciliationRecoverySuccess: \"Recovery decision recorded. Waiting for the runtime to re-check current state.\",\n reconciliationRecoveryFailed: \"Could not save the recovery decision\",\n reconciliationRecoveryNoOrder: \"This records a decision; it does not resume trading directly.\",\n binancePrivateScopeBoard: \"Private Binance asset list\",\n binancePrivateScopeAccount: \"Current collected Binance account\",\n binancePrivateScopePrivateIdentity: \"The private account digest is not displayed.\",\n binancePrivateScopeEmpty: \"empty: There is no current valid list to display.\",\n binancePrivateScopeUnavailable: \"not_available: The private list cannot be read right now.\",\n binancePrivateScopeObservedAt: \"Observed at: {time}\",\n binancePrivateScopeHistoricalWarning: \"Historical differences remain unresolved. This list is for manual comparison only and grants no order or remediation authority.\",\n binancePrivateScopeAsset: \"Asset\",\n binancePrivateScopeFree: \"Free\",\n binancePrivateScopeLocked: \"Locked\",\n executionEvidenceBoard: \"Execution and fills\",\n executionEvidenceLoginNotice: \"Sign in to see execution and fill records.\",\n executionEvidenceStaleNotice: \"Execution records are delayed. Check the latest platform status as well.\",\n executionEvidenceUnavailableNotice: \"Execution records are temporarily unavailable.\",\n executionEvidenceUpstreamNotice: \"Some execution records are unavailable. Please retry later.\",\n executionEvidenceEmpty: \"There are no execution records to display.\",\n executionEvidenceMeta: \"{platform} · current lane: {environment} · source: {source}\",\n executionEvidenceDetail: \"strategy: {strategy} · data: {data} · execution: {execution} · observe: {shadow} · simulated: {paper}\",\n executionEvidenceReceipt: \"execution receipt: {outcome} · broker confirmation: {confirmation}\",\n executionEvidenceReceiptMissing: \"execution receipt: not collected\",\n executionEvidenceReceiptNotDue: \"not in a due window\",\n executionEvidenceReceiptNoAction: \"strategy produced no order\",\n executionEvidenceReceiptRiskBlocked: \"blocked by risk controls\",\n executionEvidenceReceiptSubmitted: \"submitted; not yet confirmed\",\n executionEvidenceReceiptAcknowledged: \"broker acknowledged\",\n executionEvidenceReceiptPartiallyFilled: \"partially filled\",\n executionEvidenceReceiptFilled: \"filled\",\n executionEvidenceReceiptReconciliation: \"reconciliation required\",\n executionEvidenceReceiptFailed: \"execution failed; review required\",\n executionEvidenceConfirmationNotApplicable: \"not applicable\",\n executionEvidenceConfirmationNotObserved: \"not observed\",\n executionEvidenceConfirmationAcknowledged: \"acknowledged\",\n executionEvidenceConfirmationPartiallyFilled: \"partially filled\",\n executionEvidenceConfirmationFilled: \"filled\",\n executionEvidenceConfirmationReconciliation: \"reconciliation required\",\n executionEvidenceNoOrder: \"View the current execution and fill results.\",\n executionEvidenceNext: \"Recommended action\",\n runtimeTargetLifecycleBoard: \"Platform status\",\n runtimeTargetLifecycleLoginNotice: \"Sign in to see platform status.\",\n runtimeTargetLifecycleStaleNotice: \"Platform status is delayed. Check runtime first.\",\n runtimeTargetLifecycleUnavailableNotice: \"Platform status is temporarily unavailable.\",\n runtimeTargetLifecycleUpstreamNotice: \"Some platform status is unavailable. Please review it first.\",\n runtimeTargetLifecycleEmpty: \"There is no platform status to display.\",\n runtimeTargetLifecycleMeta: \"{platform} · {state} · lane: {mode}\",\n runtimeTargetLifecycleDetail: \"runtime guard: {guard} · execution heartbeat: {heartbeat}\",\n runtimeTargetLifecycleObservation: \"execution: {observation} · order/fill evidence: {evidence}\",\n runtimeTargetLifecycleNoOrder: \"View the current platform runtime status.\",\n runtimeTargetLifecycleNext: \"Current recommendation\",\n runtimeTargetLifecycleStateEnabled: \"enabled\",\n runtimeTargetLifecycleStateDisabled: \"disabled\",\n runtimeTargetLifecycleCheckPass: \"pass\",\n runtimeTargetLifecycleCheckAttention: \"attention\",\n runtimeTargetLifecycleCheckNotDue: \"not due\",\n runtimeTargetLifecycleCheckNotApplicable: \"not applicable\",\n runtimeTargetLifecycleCheckUnavailable: \"unavailable\",\n runtimeTargetLifecycleObservationNotDue: \"not in a due window\",\n runtimeTargetLifecycleObservationMonitoringOnly: \"latest check passed\",\n runtimeTargetLifecycleObservationNotApplicable: \"Disabled record\",\n runtimeTargetLifecycleObservationAttention: \"needs review\",\n runtimeTargetLifecycleObservationUnavailable: \"unavailable\",\n runtimeTargetLifecycleOrderEvidenceNotCollected: \"not collected\",\n runtimeTargetLifecycleDispositionEnabled: \"continue monitoring\",\n runtimeTargetLifecycleDispositionDisabled: \"disabled validation\",\n runtimeTargetLifecycleDispositionParked: \"parked\",\n runtimeTargetLifecycleReasonNone: \"monitoring normal\",\n runtimeTargetLifecycleReasonDisabled: \"intentionally disabled; validation continues\",\n runtimeTargetLifecycleReasonRuntimeGuard: \"runtime guard needs review\",\n runtimeTargetLifecycleReasonHeartbeat: \"execution heartbeat needs review\",\n runtimeTargetLifecycleReasonUnavailable: \"monitoring data unavailable\",\n m0ResearchBoard: \"External research records\",\n m0ResearchLoginNotice: \"Sign in to see external research records.\",\n m0ResearchStaleNotice: \"External research is delayed and is provided for historical context only.\",\n m0ResearchUnavailableNotice: \"External research records are temporarily unavailable.\",\n m0ResearchUpstreamNotice: \"Some external research records are unavailable. Please retry later.\",\n m0ResearchEmpty: \"There are no external research records to display.\",\n m0ResearchMore: \"Showing the first {count} research observations.\",\n m0ResearchMeta: \"{kind} · viewed {viewed}\",\n m0ResearchStateFreshness: \"State: {state} · freshness: {freshness}\",\n m0ResearchHorizons: \"Primary horizon: {primary} · suitable horizons: {suitable}\",\n m0ResearchEvidence: \"Confidence: {confidence} · style: {style} · source digest: {digest}\",\n m0ResearchConsistency: \"Current horizon conflict: {conflict} · historical stale drift: {drift}\",\n m0ResearchNoOrder: \"External research does not affect current strategy operation.\",\n adaptiveSelectionBoard: \"System suggestions\",\n adaptiveSelectionLoginNotice: \"Sign in to see system suggestions.\",\n adaptiveSelectionStaleNotice: \"Suggestions are delayed and are provided for historical context only.\",\n adaptiveSelectionUnavailableNotice: \"System suggestions are temporarily unavailable.\",\n adaptiveSelectionUpstreamNotice: \"Some suggestions are unavailable. Please retry later.\",\n adaptiveSelectionEmpty: \"There are no system suggestions to display.\",\n adaptiveSelectionMeta: \"{source} · {domain} · market as of {asOf}\",\n adaptiveSelectionRecommended: \"Observe suggestion\",\n adaptiveSelectionNoCandidate: \"No suitable suggestion yet\",\n adaptiveSelectionReason: \"Reasons: {reasons}\",\n adaptiveSelectionNoOrder: \"View the system's current suggestions.\",\n adaptiveSelectionScoreLabel: \"Research runs\",\n researchTaskBoard: \"Automation tasks\",\n researchTaskLoginNotice: \"Sign in to see automation tasks.\",\n researchTaskStaleNotice: \"Task information is delayed and is provided for historical context only.\",\n researchTaskUnavailableNotice: \"Automation tasks are temporarily unavailable.\",\n researchTaskUpstreamNotice: \"Some task information is unavailable. Please retry later.\",\n researchTaskEmpty: \"There are no automation tasks to display.\",\n researchTaskMeta: \"{type} · {domain} · created {created}\",\n researchTaskLimits: \"Research budget: up to {runs} run(s) / {seconds}s\",\n researchTaskNoOrder: \"View the current automation tasks.\",\n healthEyebrow: \"System status\",\n healthTitle: \"Runtime overview\",\n healthSubtitle: \"Platform runtime records first; expand strategy and research details as needed.\",\n healthTotal: \"Strategies\",\n healthHealthy: \"Healthy\",\n healthWatch: \"Watch\",\n healthReview: \"Review\",\n healthCritical: \"Critical\",\n healthBoard: \"Strategy health\",\n healthFilterAttention: \"Needs attention\",\n healthFilterAll: \"All strategies\",\n healthDataReady: \"Up to date\",\n healthDataStale: \"Update delayed\",\n healthDataUnavailable: \"Unavailable\",\n healthComputedAt: \"Updated: {time}\",\n healthLoginNotice: \"Sign in to see strategy health and runtime status.\",\n healthStaleNotice: \"Status is delayed; monitoring continues.\",\n healthUnavailableNotice: \"Strategy status is temporarily unavailable. Refresh later.\",\n healthUpstreamNotice: \"Some strategy status is unavailable. Retry later.\",\n healthNormalNotice: \"There are no runtime issues that need attention.\",\n healthAttentionNotice: \"{critical} critical, {review} to review, and {watch} under observation. Monitoring continues.\",\n healthEmpty: \"There are no strategies in this category.\",\n healthStatusHealthy: \"Healthy\",\n healthStatusWatch: \"Watch\",\n healthStatusReview: \"Review\",\n healthStatusCritical: \"Critical\",\n healthStatusUnknown: \"Unknown\",\n healthCardMeta: \"{status} · {domain}\",\n healthDecisionFallbackLabel: \"The system is continuing to monitor.\",\n healthDecisionFallbackReason: \"There is no exception for you to handle.\",\n healthRecommendationHealthy: \"The system is running normally.\",\n healthRecommendationWatch: \"The system is continuing to monitor.\",\n healthRecommendationReview: \"View diagnostic details while the system completes its review.\",\n healthRecommendationCritical: \"View diagnostic details and hold related changes for now.\",\n healthDetail: \"Data as of: {date}\",\n healthScoreLabel: \"Health\",\n diagnosticDetails: \"View diagnostic details\",\n diagnosticDetailsHint: \"Use this only to investigate an issue or review research records.\",\n researchTaskNoOrderBadge: \"NO ORDER\",\n recoveryConfirmedStatus: \"Confirmed\",\n recoveryReadyStatus: \"Ready to confirm\",\n recoveryBlockedStatus: \"Blocked\",\n commonUnknown: \"Unknown\",\n commonNotMarked: \"Not marked\",\n bootKicker: \"Starting console\",\n bootTitle: \"Loading strategy config\",\n bootMessage: \"Reading session, account config, and current state.\",\n bootStrategy: \"Reading strategy catalog.\",\n bootSession: \"Checking sign-in status.\",\n bootConfig: \"Reading account config and current state.\",\n bootTimeout: \"Loading timed out; switched to public preview. Retry after signing in.\",\n bootPublic: \"Public preview is ready.\",\n login: \"Sign in\",\n logout: \"Sign out\",\n signedInAs: \"Signed in as {login}\",\n planEyebrow: \"Strategy settings\",\n planTitle: \"Platform settings\",\n planSubtitle: \"Choose a platform, account, strategy, and environment; review this change before saving.\",\n planAdvancedSummary: \"Advanced settings\",\n planAdvancedHint: \"Runtime, plugins, cash, overlays, and DCA normally retain their current setup. Expand only when changing one.\",\n planScopeTitle: \"Choose scope\",\n planScopeSubtitle: \"Platform, account, strategy, and target environment\",\n planRuntimeTitle: \"Runtime protection\",\n planRuntimeSubtitle: \"Disable state, plugins, and overlays share one plan boundary\",\n planOverlayTitle: \"Strategy overlays\",\n planOverlaySubtitle: \"Only strategy-defined default guardrails are available\",\n planCashSubtitle: \"Cash reserve takes precedence over margin; they cannot override together\",\n activePlatform: \"Target platform\",\n account: \"Target account\",\n strategy: \"Strategy\",\n mode: \"Runtime mode\",\n live: \"Live trading\",\n paper: \"Paper trading\",\n dryRun: \"No-order check\",\n modeUnknown: \"Account type to be confirmed\",\n executionModeSetting: \"Execution setting\",\n executionModeLive: \"Execute trades\",\n executionModeDryRun: \"Check only, no orders\",\n executionModeSettingMeta: \"Changes the existing execution setting; no-order checks do not write trade orders.\",\n promotionConfirmTitle: \"Review research candidate\",\n promotionDecisionEyebrow: \"Decisions\",\n promotionTargetPlatform: \"Target platform\",\n promotionBrokerEnvironment: \"Broker environment\",\n promotionAccount: \"Specific account\",\n promotionExecutionMode: \"Target execution mode\",\n promotionExecutionModeReadonly: \"Account environment: {mode}\",\n promotionNoOrderCannotConfirm: \"This account is in no-order simulation; it cannot be recorded as broker paper or live intent.\",\n promotionRiskProfile: \"Risk profile\",\n promotionConfirmMeta: \"Accepting records your research decision. It does not enable trading or replace the current strategy.\",\n promotionTargetSummary: \"Suggested platform: {platform}; current account: {account}.\",\n promotionClickEffect: \"After clicking: this only records a human decision; the {mode} account will not be enabled or place orders because of it.\",\n promotionResearchSummary: \"Research summary\",\n promotionResearchSummaryMissing: \"Return comparison / strategy explanation not provided. {strategy}; {observation}\",\n promotionResearchSummaryMissingParts: \"Not provided: {items}\",\n promotionStrategyDescription: \"Strategy: {description}\",\n promotionPluginsUnknown: \"Plugins: not provided\",\n promotionPluginsNone: \"Plugins: none\",\n promotionPlugins: \"Plugins: {description}\",\n promotionComparison: \"Backtest: {startDate}—{endDate}; candidate after-cost CAGR {candidateCagr}; candidate max drawdown {candidateDrawdown}; baseline after-cost CAGR {baselineCagr}; baseline max drawdown {baselineDrawdown}\",\n promotionLimitations: \"Limitations: {limitations}\",\n promotionAiExplanation: \"AI explanation (advisory): {text}\",\n promotionTargetUnavailable: \"Research candidates await confirmation, but no target platform is visible.\",\n promotionRiskDetails: \"Risk profiles and account context\",\n promotionRiskScaleMeta: \"For drawdown control, balanced and growth-focused profiles, promotion size scales are 0.50 / 0.75 / 1.00 for new promotions or data changes only. Portfolio drawdown caps relative to the unlevered benchmark are 1.00 / 1.25 / 1.50. These have different meanings and do not change existing live settings.\",\n promotionPaperUnavailable: \"Broker paper/sim unavailable on this platform; paper disabled\",\n promotionTicket: \"Pending candidate\",\n promotionAccept: \"Accept suggestion\",\n promotionReject: \"Reject\",\n promotionTicketEmpty: \"No research candidates awaiting confirmation.\",\n promotionTicketLoginRequired: \"Sign in with an authorized account, then refresh\",\n promotionTicketLoadFailed: \"Research candidate queue unavailable. Refresh records; this does not mean there are no pending decisions.\",\n promotionAdminOnly: \"An administrator must confirm or reject\",\n promotionTicketSuggested: \"Candidate suggested risk profile: {profile}\",\n promotionUnnamedRecord: \"Unnamed strategy record {number}\",\n promotionFlowRecord: \"Workflow check record · source unverified\",\n promotionOldRecord: \"Older record\",\n promotionParameterProposal: \"Parameter proposal\",\n promotionUnverifiedCount: \"{count} older record(s) · evidence unverified\",\n promotionUnverifiedHint: \"This older research record does not identify its observation evidence. It is not a verified strategy. No acceptance or rejection is needed now; review it after its source is established.\",\n promotionOriginalRecord: \"View original name and evidence\",\n promotionDecisionHint: \"Review the research result, risk and source before accepting the suggestion.\",\n promotionTicketEvidenceKind: \"Observation type: {kind}\",\n promotionTicketParams: \"Suggested parameters: {params}\",\n promotionTicketNotification: \"Note: {body}\",\n promotionObservationReported: \"The record reports a passed observation; this does not establish complete validation.\",\n promotionObservationFailed: \"The record reports a failed observation.\",\n promotionObservationMissing: \"The record provides no observation outcome.\",\n promotionEvidenceSourceMissing: \"The source is unclear: no observation type is recorded. Check the source first.\",\n promotionEvidenceNeedsReview: \"An observation type is recorded, but its source and complete checks still need review.\",\n promotionDecisionSaved: \"Promotion intent recorded (no live authority granted)\",\n promotionDecisionFailed: \"Promotion confirmation failed\",\n promotionApplicationTitle: \"Account check\",\n promotionApplicationHint: \"A qualified candidate can be deployed to the confirmed paper account; it stays paused after deployment. Enabling it is a separate step.\",\n promotionApplicationCandidate: \"Research candidate\",\n promotionApplicationAccount: \"Target account\",\n promotionApplicationReady: \"Account and strategy checks passed; no change was submitted.\",\n promotionApplicationBlocked: \"This cannot be used yet: {reasons}. No change was submitted.\",\n promotionApplicationOpen: \"Review in account settings\",\n promotionApplicationDeploy: \"Deploy to paper account\",\n promotionApplicationQueued: \"Deployment request submitted; the account will remain paused.\",\n promotionApplicationDispatchUnknown: \"The submission result is unconfirmed; no duplicate submission will be made.\",\n promotionApplicationClaimed: \"Deployment is in progress; the account will remain paused.\",\n promotionApplicationApplied: \"The candidate was deployed and its version was checked; the account is paused.\",\n promotionApplicationRejected: \"Deployment was rejected: {reason}\",\n promotionApplicationUncertain: \"Deployment result is unconfirmed. Check the latest status.\",\n promotionApplicationEmpty: \"No research candidate is available for preparation.\",\n promotionApplicationBlockActivation: \"account application is not connected\",\n promotionApplicationBlockParams: \"runnable strategy parameters are missing\",\n promotionApplicationBlockStrategy: \"a same-name runnable strategy version is missing\",\n promotionApplicationBlockAccount: \"no configured account matches\",\n promotionApplicationBlockEvidence: \"research evidence is not verified\",\n promotionApplicationBlockBrokerEnvironment: \"broker environment is missing or unsupported\",\n promotionApplicationBlockPreflight: \"account or strategy preflight failed\",\n riskCapitalPreservation: \"Drawdown control\",\n riskBalancedCompounding: \"Balanced return and drawdown\",\n riskGrowthCompounding: \"Growth focused\",\n riskEnvelopeTitle: \"Account risk envelope\",\n riskEnvelopePreference: \"Risk preference\",\n riskEnvelopeCapitalBand: \"Capital band\",\n riskEnvelopeStatus: \"Status lamp\",\n riskEnvelopeDetailsSummary: \"Details\",\n riskEnvelopeMeta: \"Read-only; does not grant live authority or auto step-up.\",\n riskEnvelopeAwaitingEquity: \"Awaiting reconciled equity\",\n riskEnvelopeUnset: \"Unset\",\n promotionModeLive: \"Live trading\",\n promotionModePaper: \"Simulated trading\",\n liveModeUnavailable: \"This selection is not eligible for a new live switch. See the current account state above.\",\n runtimeTargetMode: \"Account status\",\n runtimeStopConfirm: \"Submit disable for this account. Only the disable setting is saved and verified; other form edits are ignored. Whether the platform has stopped remains unknown. No cancellation or liquidation; in-flight work may continue. Continue?\",\n runtimeStopPending: \"Disable requested. Inspect the task for the configuration save result. Platform application was not requested; actual runtime state is unknown. Do not submit again.\",\n runtimeStopReadyNote: \"Disable selected: the main action submits a strict stop-only configuration save. Strategy re-listing is not required and other form edits are not applied.\",\n runtimeSectionTitle: \"Runtime and plugins\",\n runtimeTargetCurrent: \"\",\n runtimeTargetEnabled: \"Enabled\",\n runtimeTargetDisabled: \"Disabled\",\n runtimeTargetModeMeta: \"Select a change, then use the main action below. Saving a disable setting does not prove the platform stopped; actual state requires readback.\",\n pluginMode: \"Plugin status\",\n pluginModeNone: \"Do not mount legacy plugins\",\n pluginModeMeta: \"The current candidate has no bound plugin; legacy plugins are not auto-mounted.\",\n incomeLayerMode: \"Income layer\",\n incomeLayerSectionTitle: \"Income layer\",\n incomeLayerCurrent: \"Keep current config\",\n incomeLayerEnabled: \"Enable income layer\",\n incomeLayerDisabled: \"Disable income layer\",\n incomeLayerNotSupported: \"No income layer for this strategy\",\n incomeLayerStartUsd: \"Income layer start amount\",\n incomeLayerMaxRatio: \"Income layer max ratio\",\n incomeLayerModeMeta: \"Only applies to US equity strategies with an income layer.\",\n incomeLayerDefaultMeta: \"Strategy default: starts at {start}, max {ratio}.\",\n incomeLayerAllocationMeta: \"Default allocation: {allocations}.\",\n incomeLayerStartMeta: \"Income layer activates after total assets reach this amount.\",\n incomeLayerRatioMeta: \"Use 0.55 for a 55% cap.\",\n optionOverlayMode: \"Option layer\",\n optionOverlaySectionTitle: \"Option layer\",\n optionOverlayCurrent: \"Keep current config\",\n optionOverlayEnabled: \"Enable option layer\",\n optionOverlayDisabled: \"Disable option layer\",\n optionOverlayNotSupported: \"No option layer for this strategy\",\n optionOverlayModeMeta: \"Enabled mode uses the strategy's default recipe and budget; ratios are not edited here.\",\n optionOverlayDefaultMeta: \"{defaults}\",\n optionOverlayFamilyGrowth: \"Growth\",\n optionOverlayFamilyIncome: \"Income\",\n optionOverlayBudgetRatio: \"budget {ratio}\",\n optionOverlayRiskRatio: \"risk {ratio}\",\n cashOnlyExecutionMode: \"Allow margin\",\n cashOnlyExecutionCurrent: \"Keep current config\",\n cashOnlyExecutionYes: \"Yes\",\n cashOnlyExecutionNo: \"No\",\n cashOnlyExecutionModeMeta: \"Choose No to use available cash only and avoid margin buying power.\",\n cashOnlyExecutionValueYes: \"Yes\",\n cashOnlyExecutionValueNo: \"No\",\n currentCashOnlyExecution: \"Current allow margin\",\n pendingCashOnlyExecution: \"Pending allow margin\",\n executionCashPolicyTitle: \"Capital boundary\",\n executionCashPolicyNote: \"Allow margin and reserve-cash overrides cannot both apply. Yes clears reserve overrides; reserve overrides force No.\",\n executionCashMarginBlocksReserve: \"Allow margin is selected; submitting will clear reserve-cash overrides.\",\n executionCashReserveBlocksMargin: \"Reserve-cash override is active; submitting will force allow margin to No.\",\n qmtPlatformCashNote: \"QMT A-share does not use margin or platform reserve cash; cash constraints live in strategy execution_cash_reserve_ratio.\",\n qmtDryRunOnlyNote: \"This platform supports no-order dry runs only; no live execution route is configured.\",\n binancePlatformNote: \"Binance does not use broker-level income/option layers; features are implemented inside strategies.\",\n invalidExecutionCashPolicyNote: \"Allow margin and reserve-cash overrides conflict. Keep only one constraint.\",\n dcaMode: \"DCA mode\",\n dcaSectionTitle: \"DCA\",\n dcaModeFixed: \"Fixed DCA\",\n dcaModeSmart: \"Smart DCA\",\n dcaBaseInvestmentUsd: \"Base DCA amount\",\n dcaModeMeta: \"Only DCA strategies can use this.\",\n dcaDefaultMeta: \"Default: {mode}, base amount {amount}.\",\n dcaNotSupported: \"This is not a DCA strategy\",\n dcaPlatformNotSupported: \"DCA not supported on this platform\",\n currentDca: \"Current DCA settings\",\n pendingDca: \"Pending DCA settings\",\n dcaText: \"{mode}, base amount {amount}\",\n minReservedCash: \"Minimum reserved cash ({currency})\",\n reservedCashRatio: \"Reserved cash ratio\",\n reservedCashMode: \"Reserved cash policy\",\n reservePolicyCurrent: \"Keep current config\",\n reservePolicyNone: \"No platform reserve\",\n reservePolicyRatio: \"Ratio only\",\n reservePolicyFloor: \"Fixed amount only\",\n reservePolicyMax: \"Max of amount and ratio\",\n reservedCashModeMeta: \"Choose whether to keep, clear, or override platform reserved cash.\",\n reservedCashNone: \"None\",\n reservedCashDefault: \"Not configured (platform default: 0 {currency} / 0%)\",\n reservedCashMeta: \"Fixed cash floor. Use alone or with a ratio.\",\n reservedCashRatioMeta: \"Use 0.03 for 3%.\",\n summary: \"Current configuration\",\n summaryCurrent: \"Saved configuration\",\n summaryPending: \"Pending change\",\n copySummary: \"Copy state\",\n loginToRun: \"Sign in to submit a plan\",\n loadingConfig: \"Loading config\",\n configureAccounts: \"Configure accounts\",\n runSwitch: \"Save settings\",\n noChanges: \"No changes\",\n readonlyNote: \"Sign in to save settings.\",\n publicReadonly: \"Sign in to view account config.\",\n loadingConfigNote: \"Reading account config and current state.\",\n missingConfigNote: \"Account config is not loaded, so switching is disabled.\",\n readyNote: \"Review the changes above, then save.\",\n invalidStrategyNote: \"This strategy switch does not meet the requirements for the selected execution mode. See the current account state above.\",\n binanceResume: \"Resume current live target\",\n binanceResumeHint: \"Restore only the enable setting, preserving the current strategy and cash configuration. The runtime still verifies the recovery record.\",\n binanceResumeModeHint: \"Use the resume button above for the existing target; the form below switches strategies.\",\n binanceResumeConfirm: \"Resume the current Binance live target? Only the enable setting will be saved. Current strategy and cash settings are retained; unsaved form edits will not be submitted. Execution still requires runtime recovery and risk checks.\",\n binanceResumePending: \"Resume requested. Check the result and refresh configuration; actual recovery requires platform runtime evidence.\",\n binanceResumeUnknown: \"Submission is unconfirmed. Check the existing run before refreshing and retrying.\",\n invalidReservePolicyNote: \"Enter a valid amount or ratio for the selected reserved-cash policy.\",\n invalidIncomeLayerNote: \"Enter a valid income layer start amount and max ratio.\",\n invalidOptionOverlayNote: \"This strategy does not define an option layer to enable.\",\n invalidDcaNote: \"Enter a valid DCA mode and base amount.\",\n noAccount: \"No accounts\",\n noStrategy: \"No supported strategies\",\n repository: \"Repository\",\n selectedAccount: \"Account\",\n selectedMarket: \"Market\",\n currentRuntimeTarget: \"Current account status\",\n pendingRuntimeTarget: \"Pending account status\",\n reservedCashPolicy: \"Current reserved cash\",\n currentIncomeLayer: \"Current income layer\",\n pendingIncomeLayer: \"Pending income layer\",\n currentOptionOverlay: \"Current option layer\",\n pendingOptionOverlay: \"Pending option layer\",\n pendingReservedCashPolicy: \"Pending reserved cash\",\n pendingMode: \"Pending mode\",\n currentPluginMode: \"Current plugin scope\",\n pendingPluginMode: \"Pending plugin scope\",\n unchanged: \"Unchanged\",\n copied: \"State copied\",\n dispatching: \"Dispatching workflow...\",\n dispatched: \"Workflow dispatched\",\n dispatchFailed: \"Dispatch failed\",\n targetMeta: \"\",\n strategyMeta: \"Markets: {domains}\",\n strategyLifecycleMeta: \"current gate {stage}\",\n strategyBlockedCountMeta: \"{count} strategies are blocked from live\",\n strategyDefaultBlockedMeta: \"Default strategy {profile} is blocked: {reason}\",\n usEquity: \"US equity\",\n hkEquity: \"HK equity\",\n cnEquity: \"CN A-share\",\n cryptoEquity: \"Crypto\",\n currentStrategy: \"Current strategy\",\n nextStrategy: \"Switch strategy\",\n notRead: \"Not read yet\",\n runtimeTargetOn: \"Enabled\",\n runtimeTargetOff: \"Disabled\",\n incomeLayerDefault: \"Enabled, {start} start, {ratio} max\",\n incomeLayerOff: \"Disabled\",\n incomeLayerOn: \"Enabled, starts at {start}, max {ratio}\",\n optionOverlayOff: \"Disabled\",\n optionOverlayOn: \"Enabled\",\n optionOverlayDefaultSimple: \"Strategy default: enabled\",\n optionOverlayDefault: \"Enabled, {detail}\",\n cashOnlyExecutionDefault: \"Cash only\",\n notConfigured: \"Not set\",\n strategyDefault: \"Use strategy default\",\n },\n };\n\n const storedLang = localStorage.getItem(\"qsl-switch-lang\");\n const initialLang = storedLang === \"zh\" || storedLang === \"en\"\n ? storedLang\n : ((navigator.language || \"\").toLowerCase().startsWith(\"zh\") ? \"zh\" : \"en\");\n const clone = (value) => JSON.parse(JSON.stringify(value));\n const runtimeStopLock = { pending: false };\n const binanceResumeLock = { pending: false, messageKey: \"\" };\n let binancePrivateScopeRequestGeneration = 0;\n const defaultReserveForm = () => ({\n reservePolicyMode: \"current\",\n minReservedCashUsd: \"\",\n reservedCashRatio: \"\",\n reservedCashTouched: false,\n incomeLayerMode: \"current\",\n incomeLayerStartUsd: \"\",\n incomeLayerMaxRatio: \"\",\n incomeLayerTouched: false,\n optionOverlayMode: \"current\",\n optionOverlayTouched: false,\n cashOnlyExecutionMode: \"current\",\n cashOnlyExecutionTouched: false,\n runtimeTargetMode: \"current\",\n runtimeTargetTouched: false,\n dcaMode: \"fixed\",\n dcaBaseInvestmentUsd: \"\",\n dcaTouched: false,\n strategyTouched: false,\n executionModeTouched: false,\n pluginModeTouched: false,\n });\n\n const state = {\n view: \"overview\",\n overviewFilter: \"all\",\n overviewSearch: \"\",\n lastRefreshAt: null,\n refreshing: false,\n selected: Object.keys(platformMeta)[0] || \"\",\n lang: initialLang,\n appReady: false,\n bootMessageKey: \"bootMessage\",\n auth: { available: false, allowed: false, admin: false, login: null },\n accountOptions: clone(defaultAccountOptions),\n currentStrategies: {},\n health: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { strategy_count: 0, healthy: 0, watch: 0, review: 0, critical: 0 },\n strategies: [],\n },\n filter: \"attention\",\n },\n controlPlane: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { candidate_count: 0, deferred: 0, parked: 0, owner_decision_required: 0 },\n attention: { status: \"unavailable\", reason_codes: [\"control_plane_source_unavailable\"] },\n candidates: [],\n policy: { p4_p5_automation: \"not_configured\", p6_owner_decision_required: true },\n errors: [],\n },\n },\n ownerDecisions: {\n data_status: \"unavailable\",\n candidates: [],\n errors: [],\n },\n reconciliationRecovery: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { recovery_count: 0, awaiting_human_confirmation: 0, blocked: 0, confirmed: 0 },\n recoveries: [],\n policy: { human_confirmation_required: true, current_evidence_required: true, no_order: true, execution_authority_granted: false },\n errors: [],\n },\n submittingRecoveryId: null,\n },\n binancePrivateScope: {\n status: \"not_available\",\n report: null,\n },\n m0Research: {\n payload: {\n data_status: \"unavailable\",\n viewed_at: null,\n summary: {\n subject_count: 0,\n observation_count: 0,\n fresh_observation_count: 0,\n stale_observation_count: 0,\n unknown_observation_count: 0,\n horizon_conflict_count: 0,\n historical_stale_horizon_drift_count: 0,\n },\n subjects: [],\n policy: { authority: \"research_only\", no_order: true, permitted_next_step: \"research_validation_only\" },\n errors: [],\n },\n },\n adaptiveSelection: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { source_count: 0, decision_count: 0, candidate_count: 0, recommended_count: 0, rejected_candidate_count: 0 },\n selections: [],\n policy: { authority: \"shadow_only\", no_order: true, execution_authority_granted: false },\n errors: [],\n },\n },\n executionEvidence: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { deployment_count: 0, autonomous_shadow: 0, autonomous_paper: 0, owner_canary_decision: 0, parked: 0 },\n deployments: [],\n policy: { execution_evidence_read_only: true, p6_owner_decision_required: true, limited_live_canary_active: false },\n errors: [],\n },\n },\n runtimeTargetLifecycle: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { target_count: 0, enabled: 0, disabled: 0, attention: 0 },\n targets: [],\n policy: { lifecycle_status_read_only: true, no_order: true },\n errors: [],\n },\n },\n accountDiagnosis: {\n tasks: {},\n loading: {},\n submitting: {},\n },\n researchTasks: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { task_count: 0 },\n tasks: [],\n policy: { research_only: true, no_order: true, size_zero_required: true, p4_p5_p6_authorized: false },\n errors: [],\n },\n },\n researchPromotion: {\n payload: {\n data_status: \"unavailable\",\n computed_at: null,\n tickets: [],\n applications: [],\n summary: { ticket_count: 0, awaiting_human: 0 },\n policy: { live_authority_granted: false, no_order: true },\n errors: [],\n },\n selectedTicketId: \"\",\n selectedApplicationTicketId: \"\",\n selectedApplicationPlatform: \"\",\n selectedApplicationEnvironment: \"\",\n selectedApplicationAccountKey: \"\",\n },\n configSource: \"default\",\n repositories: clone(defaultRepositories),\n forms: Object.fromEntries(Object.keys(platformMeta).map((platform) => [platform, {\n accountKey: defaultAccountOptions[platform]?.[0]?.key || \"preview\",\n strategy: \"\",\n executionMode: \"\",\n pluginMode: \"none\",\n ...defaultReserveForm(),\n }])),\n };\n\n const el = (id) => document.getElementById(id);\n const t = (key) => copy[state.lang][key] || copy.en[key] || key;\n const locale = () => (state.lang === \"zh\" ? \"zh-CN\" : \"en-US\");\n\n function formatDateTime(value) {\n if (!value) return \"—\";\n const parsed = value instanceof Date ? value : new Date(value);\n if (Number.isNaN(parsed.getTime())) return \"—\";\n return new Intl.DateTimeFormat(locale(), {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n }).format(parsed);\n }\n\n function formatAsOfDate(value) {\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n const parsed = new Date(`${value}T00:00:00.000Z`);\n return new Intl.DateTimeFormat(locale(), {\n dateStyle: \"medium\",\n timeZone: \"UTC\",\n }).format(parsed);\n }\n return formatDateTime(value);\n }\n\n function localizedExternalText(value, fallback) {\n const text = typeof value === \"string\" ? value.trim() : \"\";\n if (!text) return fallback;\n const hasChinese = /[\\u3400-\\u9fff]/.test(text);\n const hasLatinWords = /[A-Za-z]{3,}/.test(text);\n if ((state.lang === \"en\" && hasChinese) || (state.lang === \"zh\" && hasLatinWords && !hasChinese)) {\n return fallback;\n }\n return text;\n }\n let toastTimer = null;\n\n function showToast(message, { duration = 4000 } = {}) {\n const node = el(\"toast\");\n if (toastTimer) {\n window.clearTimeout(toastTimer);\n toastTimer = null;\n }\n node.textContent = message || \"\";\n if (message && duration > 0) {\n toastTimer = window.setTimeout(() => {\n node.textContent = \"\";\n toastTimer = null;\n }, duration);\n }\n }\n\n async function fetchWithTimeout(url, init = {}, timeoutMs = APP_BOOT_TIMEOUT_MS) {\n const controller = new AbortController();\n const timeoutId = window.setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } catch (error) {\n if (error?.name === \"AbortError\") {\n throw new Error(\"request timeout\");\n }\n throw error;\n } finally {\n window.clearTimeout(timeoutId);\n }\n }\n\n async function requestJson(url, init = {}, timeoutMs = APP_BOOT_TIMEOUT_MS) {\n const response = await fetchWithTimeout(url, { ...init, cache: \"no-store\" }, timeoutMs);\n if (!response.ok) throw new Error(\"request failed\");\n return response.json();\n }\n\n function isRequestTimeoutError(error) {\n return String(error?.message || \"\").toLowerCase() === \"request timeout\";\n }\n\n function optionsFor(platform) {\n return state.accountOptions[platform] && state.accountOptions[platform].length\n ? state.accountOptions[platform]\n : defaultAccountOptions[platform];\n }\n\n function selectedAccount(platform = state.selected) {\n const options = optionsFor(platform);\n const form = state.forms[platform];\n return options.find((option) => option.key === form.accountKey) || options[0];\n }\n\n function accountDisplayLabel(account) {\n const selectors = String(account?.account_selector || \"\")\n .split(/[\\s,;|]+/)\n .map(value => value.trim())\n .filter(value => /^U\\d+$/i.test(value))\n .map(value => value.toUpperCase());\n const accountIds = [...new Set(selectors)];\n return accountIds.length\n ? accountIds.join(\" / \")\n : String(account?.label || account?.target_name || account?.key || \"\");\n }\n\n function hasPrivateConfig() {\n return Boolean(state.auth.allowed && state.configSource === \"private\");\n }\n\n function cleanStrategyProfile(value) {\n const profile = String(value || \"\").trim();\n return /^[a-z0-9._=-]{1,120}$/.test(profile) ? profile : \"\";\n }\n\n function cleanStrategyDomain(value) {\n const domain = String(value || \"\").trim();\n return strategyDomains.includes(domain) ? domain : \"\";\n }\n\n function domainLabel(domain) {\n const entry = domainLabels[domain];\n if (entry) return state.lang === \"zh\" ? entry.zh : entry.en;\n return domain;\n }\n\n function platformSupportsMarginPolicy(platform = state.selected) {\n return platformConfig[platform]?.margin_policy ?? true;\n }\n\n function platformSupportsReservedCashPolicy(platform = state.selected) {\n return platformConfig[platform]?.reserved_cash ?? true;\n }\n\n function platformDryRunOnly(platform = state.selected) {\n return platformConfig[platform]?.dry_run_only ?? false;\n }\n\n function supportedExecutionModesForPlatform(platform = state.selected) {\n const modes = platformConfig[platform]?.supported_execution_modes;\n return Array.isArray(modes) ? modes.filter((mode) => mode === \"live\" || mode === \"dry_run\") : [];\n }\n\n function allowMarginExplicitlySelected(form) {\n return normalizeCashOnlyExecutionMode(form?.cashOnlyExecutionMode) === \"disabled\";\n }\n\n function reserveCashOverrideActive(form) {\n const mode = normalizeReservePolicyMode(form?.reservePolicyMode);\n return mode === \"ratio\" || mode === \"floor\" || mode === \"max\";\n }\n\n function executionCashPolicyConflict(form) {\n return allowMarginExplicitlySelected(form) && reserveCashOverrideActive(form);\n }\n\n function reconcileExecutionCashPolicy(form, changed) {\n if (!form) return;\n if (changed === \"margin\" && allowMarginExplicitlySelected(form)) {\n if (form.reservePolicyMode !== \"none\" && (form.minReservedCashUsd || form.reservedCashRatio)) {\n form._prevReserve = {\n mode: form.reservePolicyMode,\n floor: form.minReservedCashUsd,\n ratio: form.reservedCashRatio,\n };\n }\n form.reservePolicyMode = \"none\";\n form.reservedCashTouched = true;\n } else if (changed === \"reserve\" && reserveCashOverrideActive(form)) {\n form.cashOnlyExecutionMode = \"enabled\";\n form.cashOnlyExecutionTouched = true;\n }\n }\n\n function restoreReserveAfterMarginDisabled(form) {\n if (!form || allowMarginExplicitlySelected(form) || !form._prevReserve) return;\n form.reservePolicyMode = form._prevReserve.mode;\n form.minReservedCashUsd = form._prevReserve.floor;\n form.reservedCashRatio = form._prevReserve.ratio;\n form.reservedCashTouched = true;\n delete form._prevReserve;\n }\n\n function strategyDomain(profile) {\n return strategyCatalog[profile]?.domain || \"\";\n }\n\n function selectedCashCurrency(platform = state.selected, account = selectedAccount(platform)) {\n const configured = String(account?.cash_currency || \"\").trim().toUpperCase();\n if (configured === \"USD\" || configured === \"HKD\" || configured === \"CNY\") return configured;\n const domain = strategyDomain(state.forms[platform]?.strategy);\n if (domain === \"hk_equity\") return \"HKD\";\n if (domain === \"cn_equity\") return \"CNY\";\n return \"USD\";\n }\n\n function applyStrategyProfiles(rawProfiles) {\n const profiles = Array.isArray(rawProfiles) && rawProfiles.length\n ? rawProfiles\n : defaultStrategyProfiles;\n const nextOptions = [];\n const nextLabels = {};\n const nextCatalog = {};\n const nextIncomeLayerDefaults = {};\n const nextOptionOverlayDefaults = {};\n for (const item of profiles) {\n const profile = cleanStrategyProfile(item?.profile || item?.strategy_profile);\n if (!profile || nextOptions.includes(profile)) continue;\n const domain = cleanStrategyDomain(item?.domain || \"us_equity\");\n if (!domain) continue;\n nextOptions.push(profile);\n nextLabels[profile] = strategyLabelSet(profile, item);\n nextCatalog[profile] = {\n profile,\n label: nextLabels[profile].en || nextLabels[profile].zh || profile,\n label_en: nextLabels[profile].en || \"\",\n label_zh: nextLabels[profile].zh || \"\",\n domain,\n runtime_enabled: cleanOptionalBoolean(item?.runtime_enabled ?? false) === true,\n };\n const lifecycleStage = normalizeLifecycleStage(item?.lifecycle_stage ?? item?.lifecycleStage);\n if (lifecycleStage) nextCatalog[profile].lifecycle_stage = lifecycleStage;\n const allowedExecutionModes = normalizeAllowedExecutionModes(item?.allowed_execution_modes);\n if (allowedExecutionModes.length) nextCatalog[profile].allowed_execution_modes = allowedExecutionModes;\n const canSwitchLive = cleanOptionalBoolean(item?.can_switch_live);\n if (canSwitchLive !== null) nextCatalog[profile].can_switch_live = canSwitchLive;\n const blockedLiveReason = cleanDisplayText(item?.blocked_live_reason);\n if (blockedLiveReason) nextCatalog[profile].blocked_live_reason = blockedLiveReason;\n const latestEvidenceStatus = cleanDisplayText(item?.latest_evidence_status);\n if (latestEvidenceStatus) nextCatalog[profile].latest_evidence_status = latestEvidenceStatus;\n const pluginGateStatus = cleanDisplayText(item?.plugin_gate_status);\n if (pluginGateStatus) nextCatalog[profile].plugin_gate_status = pluginGateStatus;\n const dcaDefaults = dcaProfileDefaults[profile] || null;\n if (dcaDefaults || item?.dca_enabled === true) {\n nextCatalog[profile].dca_enabled = true;\n nextCatalog[profile].dca_default_mode = normalizeDcaMode(\n item?.dca_default_mode || item?.default_dca_mode || dcaDefaults?.defaultMode || \"fixed\",\n );\n nextCatalog[profile].dca_default_base_investment_usd = cleanDisplayPositiveNumber(\n item?.dca_default_base_investment_usd ||\n item?.default_dca_base_investment_usd ||\n dcaDefaults?.defaultBaseInvestmentUsd ||\n \"1000\",\n ) || \"1000\";\n }\n const profileIncomeDefaults = incomeLayerDefaultsFromProfileItem(item);\n const incomeDefaults = profileIncomeDefaults === false\n ? null\n : (profileIncomeDefaults || fallbackIncomeLayerDefaults[profile] || null);\n if (incomeDefaults) {\n nextIncomeLayerDefaults[profile] = incomeDefaults;\n nextCatalog[profile].income_layer_enabled = true;\n nextCatalog[profile].income_layer_start_usd = String(incomeDefaults.startUsd);\n nextCatalog[profile].income_layer_max_ratio = incomeDefaults.maxRatio;\n nextCatalog[profile].income_layer_allocations = incomeDefaults.allocations;\n }\n const profileOptionDefaults = optionOverlayDefaultsFromProfileItem(item);\n const optionDefaults = profileOptionDefaults === false\n ? null\n : (profileOptionDefaults || fallbackOptionOverlayDefaults[profile] || null);\n if (optionDefaults) {\n nextOptionOverlayDefaults[profile] = optionDefaults;\n nextCatalog[profile].option_overlay_enabled = true;\n nextCatalog[profile].option_overlay_live_gate = optionDefaults.liveGate || \"\";\n nextCatalog[profile].option_overlay_live_status = optionDefaults.liveStatus || \"\";\n }\n }\n if (!nextOptions.length && profiles !== defaultStrategyProfiles) return applyStrategyProfiles(defaultStrategyProfiles);\n strategyOptions = nextOptions;\n strategyLabels = nextLabels;\n strategyCatalog = nextCatalog;\n incomeLayerDefaults = nextIncomeLayerDefaults;\n optionOverlayDefaults = nextOptionOverlayDefaults;\n }\n\n function incomeLayerDefaultsFromProfileItem(item) {\n const enabled = cleanOptionalBoolean(item?.income_layer_enabled);\n const hasConfig = enabled !== null ||\n item?.income_layer_start_usd !== undefined ||\n item?.income_layer_max_ratio !== undefined ||\n item?.income_layer_allocations !== undefined;\n if (!hasConfig) return null;\n if (enabled === false) return false;\n const startUsd = cleanDisplayNumber(item?.income_layer_start_usd);\n const maxRatio = cleanDisplayRatio(item?.income_layer_max_ratio);\n const allocations = cleanIncomeLayerAllocations(item?.income_layer_allocations);\n if (!startUsd || !maxRatio || !allocations) return null;\n return { startUsd, maxRatio, allocations };\n }\n\n function cleanIncomeLayerAllocations(value) {\n if (!value || Array.isArray(value) || typeof value !== \"object\") return null;\n const allocations = {};\n let total = 0;\n for (const [rawSymbol, rawRatio] of Object.entries(value)) {\n const symbol = String(rawSymbol || \"\").trim().toUpperCase();\n const ratio = cleanDisplayPositiveNumber(rawRatio);\n if (!/^[A-Z0-9.-]{1,12}$/.test(symbol) || !ratio) continue;\n allocations[symbol] = Number(ratio);\n total += Number(ratio);\n }\n return total > 0 && Object.keys(allocations).length ? allocations : null;\n }\n\n function optionOverlayDefaultsFromProfileItem(item) {\n const enabled = cleanOptionalBoolean(item?.option_overlay_enabled);\n const hasConfig = enabled !== null ||\n item?.option_growth_overlay_enabled !== undefined ||\n item?.option_income_overlay_enabled !== undefined ||\n item?.option_overlay_live_gate !== undefined ||\n item?.option_overlay_live_status !== undefined;\n if (!hasConfig) return null;\n if (enabled === false) return false;\n const families = [\n optionOverlayFamilyDefaultsFromProfileItem(item, \"growth\"),\n optionOverlayFamilyDefaultsFromProfileItem(item, \"income\"),\n ].filter(Boolean);\n if (!families.length) return null;\n return {\n liveGate: String(item?.option_overlay_live_gate || \"promotion_required\"),\n liveStatus: String(item?.option_overlay_live_status || \"research_only\"),\n families,\n };\n }\n\n function optionOverlayFamilyDefaultsFromProfileItem(item, family) {\n const prefix = `option_${family}_overlay`;\n const enabled = cleanOptionalBoolean(item?.[`${prefix}_enabled`]);\n if (enabled !== true) return null;\n const recipe = cleanStrategyProfile(item?.[`${prefix}_recipe`]);\n const startUsd = cleanDisplayNumber(item?.[`${prefix}_start_usd`]);\n const ratioField = family === \"growth\"\n ? \"option_growth_overlay_nav_budget_ratio\"\n : \"option_income_overlay_nav_risk_ratio\";\n const ratio = cleanDisplayRatio(item?.[ratioField]);\n if (!recipe || !startUsd || !ratio) return null;\n return {\n family,\n recipe,\n startUsd,\n ratio,\n ratioKind: family === \"growth\" ? \"budget\" : \"risk\",\n };\n }\n\n function supportedDomainsForAccount(platform, account) {\n if (Array.isArray(account?.supported_domains) && account.supported_domains.length) {\n const cleaned = account.supported_domains.map(cleanStrategyDomain).filter(Boolean);\n if (cleaned.length) return [...new Set(cleaned)];\n }\n return inferSupportedDomains(platform, account);\n }\n\n function inferSupportedDomains(platform, account) {\n void account;\n const configured = typeof platformConfig !== \"undefined\" ? platformConfig[platform]?.supported_domains : null;\n if (Array.isArray(configured) && configured.length) return [...configured];\n if (platform === \"qmt\") return [\"cn_equity\"];\n if (platform === \"binance\") return [\"crypto\"];\n if (platform === \"longbridge\" || platform === \"ibkr\") return [\"us_equity\", \"hk_equity\"];\n return [\"us_equity\"];\n }\n\n function supportedDomainLabel(platform, account) {\n return supportedDomainsForAccount(platform, account).map(domainLabel).join(\" / \");\n }\n\n function platformSupportsDca(platform = state.selected) {\n return platformConfig[platform]?.dca ?? false;\n }\n\n function strategyCatalogEntry(profile) {\n return strategyCatalog[cleanStrategyProfile(profile)] || {};\n }\n\n function normalizeLifecycleStage(value) {\n const text = String(value || \"\").trim().toLowerCase();\n if (!text || text.length > 40 || !/^[a-z0-9._-]+$/.test(text)) return \"\";\n if ([\"research_backtest_only\", \"ai_monitored_candidate\"].includes(text)) return \"research_active\";\n if (text === \"shadow_candidate\") return \"shadow_active\";\n return text;\n }\n\n function normalizeAllowedExecutionModes(value) {\n const items = Array.isArray(value)\n ? value\n : String(value || \"\").split(/[,\\s/|]+/);\n const modes = [];\n for (const item of items) {\n const mode = String(item || \"\").trim().toLowerCase();\n if (!mode || mode.length > 32 || !/^[a-z0-9._-]+$/.test(mode)) continue;\n if (!modes.includes(mode)) modes.push(mode);\n }\n return modes;\n }\n\n function cleanDisplayText(value) {\n const text = String(value ?? \"\").trim();\n if (!text || text.length > 120 || /[<>]/.test(text)) return \"\";\n return text;\n }\n\n function strategyCanSwitchLive(entry) {\n if (!entry || typeof entry !== \"object\") return false;\n if (entry.runtime_enabled !== true) return false;\n const allowedModes = normalizeAllowedExecutionModes(entry.allowed_execution_modes);\n if (!allowedModes.includes(\"live\")) return false;\n if (cleanOptionalBoolean(entry.can_switch_live) !== true) return false;\n const lifecycleStage = normalizeLifecycleStage(entry.lifecycle_stage);\n if (![\"live_enabled\", \"runtime_enabled\"].includes(lifecycleStage)) return false;\n const blockedReason = cleanDisplayText(entry.blocked_live_reason);\n if (blockedReason) return false;\n const evidenceStatus = cleanDisplayText(entry.latest_evidence_status);\n if (evidenceStatus && [\"research_only\", \"blocked\", \"pending\"].includes(evidenceStatus.toLowerCase())) return false;\n const pluginGateStatus = cleanDisplayText(entry.plugin_gate_status);\n if (pluginGateStatus && [\"blocked\", \"locked\", \"disabled\"].includes(pluginGateStatus.toLowerCase())) return false;\n return true;\n }\n\n function strategyDisplayMetaText(platform, account, profile) {\n void profile;\n return t(\"strategyMeta\").replace(\"{domains}\", supportedDomainLabel(platform, account));\n }\n\n function strategyActionNoteText(platform = state.selected, account = selectedAccount(platform)) {\n if (platform === \"binance\" && binanceResumeDigest()) return t(\"binanceResumeModeHint\");\n const profile = state.forms[platform]?.strategy || \"\";\n const meta = strategyDisplayMetaText(platform, account, profile);\n return meta ? `${t(\"invalidStrategyNote\")}\\n${meta}` : t(\"invalidStrategyNote\");\n }\n\n function strategyChoiceLabel(profile, platform = state.selected, account = selectedAccount(platform), executionMode = state.forms[platform]?.executionMode) {\n const label = strategyLabel(profile);\n const entry = strategyCatalogEntry(profile);\n const domain = entry.domain ? domainLabel(entry.domain) : \"\";\n if (!entry.profile) return label;\n if (normalizeExecutionMode(executionMode, false) === \"live\" && !strategyCanSwitchLive(entry)) {\n return domain ? `${label}(${domain})` : label;\n }\n if (entry.runtime_enabled === false) {\n return domain ? `${label}(${domain})` : label;\n }\n return label;\n }\n\n function strategyAllowedForAccount(platform, account, profile, executionMode = state.forms[platform]?.executionMode) {\n const cleanProfile = cleanStrategyProfile(profile);\n const catalogEntry = strategyCatalogEntry(cleanProfile);\n if (!catalogEntry.profile) return false;\n if (dcaConfigForStrategy(cleanProfile) && !platformSupportsDca(platform)) return false;\n if (!supportedDomainsForAccount(platform, account).includes(catalogEntry.domain)) return false;\n const mode = normalizeExecutionMode(executionMode, false);\n if (!supportedExecutionModesForPlatform(platform).includes(mode)) return false;\n if (mode === \"live\") return strategyCanSwitchLive(catalogEntry);\n const allowedModes = normalizeAllowedExecutionModes(catalogEntry.allowed_execution_modes);\n if (allowedModes.length && !allowedModes.includes(mode)) return false;\n return true;\n }\n\n function strategyCompatibleWithAccount(platform, account, profile) {\n const entry = strategyCatalogEntry(profile);\n return Boolean(entry.profile)\n && (!dcaConfigForStrategy(profile) || platformSupportsDca(platform))\n && supportedDomainsForAccount(platform, account).includes(entry.domain);\n }\n\n function strategyChoicesForAccount(platform = state.selected, account = selectedAccount(platform)) {\n // Browsing is not execution approval; submission retains its existing checks.\n return strategyOptions.filter(profile => strategyCompatibleWithAccount(platform, account, profile));\n }\n\n function hasLiveStrategyOption(platform = state.selected, account = selectedAccount(platform)) {\n return strategyOptions.some((profile) => strategyAllowedForAccount(platform, account, profile, \"live\"));\n }\n\n function strategyLabel(profile) {\n const labels = strategyLabels[profile] || localStrategyLabels[profile];\n if (!labels) return profile;\n return state.lang === \"zh\"\n ? (labels.zh || labels.en || profile)\n : (labels.en || labels.zh || profile);\n }\n\n function strategyLabelSet(profile, item) {\n const local = localStrategyLabels[profile] || {};\n const label = String(item?.label || item?.display_name || \"\").trim();\n const labelEn = String(item?.label_en || item?.display_name_en || \"\").trim();\n const labelZh = String(item?.label_zh || item?.display_name_zh || \"\").trim();\n return {\n zh: labelZh || local.zh || label || local.en || profile,\n en: labelEn || label || local.en || labelZh || local.zh || profile,\n };\n }\n\n function modeLabel(mode) {\n if (mode === \"dry_run\") return t(\"dryRun\");\n if (mode === \"paper\") return t(\"paper\");\n if (mode === \"live\") return t(\"live\");\n return t(\"modeUnknown\");\n }\n\n function normalizePluginMode(value) {\n return pluginModes.includes(value) ? value : \"none\";\n }\n\n function pluginModeLabel(mode) {\n void mode;\n return t(\"pluginModeNone\");\n }\n\n function dcaConfigForStrategy(profile) {\n const cleanProfile = cleanStrategyProfile(profile);\n const catalog = strategyCatalog[cleanProfile] || {};\n if (catalog.dca_enabled === true) {\n return {\n defaultMode: normalizeDcaMode(catalog.dca_default_mode || \"fixed\"),\n defaultBaseInvestmentUsd: cleanDisplayPositiveNumber(catalog.dca_default_base_investment_usd) || \"1000\",\n };\n }\n return dcaProfileDefaults[cleanProfile] || null;\n }\n\n function dcaSupported(profile) {\n return Boolean(dcaConfigForStrategy(profile));\n }\n\n function normalizeDcaMode(value) {\n const mode = String(value || \"\").trim().toLowerCase();\n if (mode === \"smart_dca\") return \"smart\";\n if (mode === \"fixed_dca\" || mode === \"ordinary\" || mode === \"ordinary_dca\") return \"fixed\";\n return dcaModes.includes(mode) ? mode : \"fixed\";\n }\n\n function dcaModeLabel(mode) {\n return normalizeDcaMode(mode) === \"smart\" ? t(\"dcaModeSmart\") : t(\"dcaModeFixed\");\n }\n\n function normalizeRuntimeTargetMode(value) {\n return runtimeTargetModes.includes(value) ? value : \"current\";\n }\n\n function runtimeTargetModeLabel(mode) {\n if (mode === \"enabled\") return t(\"runtimeTargetEnabled\");\n if (mode === \"disabled\") return t(\"runtimeTargetDisabled\");\n return \"\";\n }\n\n function runtimeTargetEnabledForAccount(platform, account) {\n return cleanOptionalBoolean(currentEntryForAccount(platform, account)?.runtime_target_enabled);\n }\n\n function runtimeTargetStateForAccount(platform = state.selected, account = selectedAccount(platform)) {\n const entry = currentEntryForAccount(platform, account);\n if (!entry) return { known: false, enabled: null };\n const configured = cleanOptionalBoolean(entry.runtime_target_enabled);\n return { known: configured !== null, enabled: configured };\n }\n\n function runtimeTargetText(enabled) {\n return enabled ? t(\"runtimeTargetOn\") : t(\"runtimeTargetOff\");\n }\n\n function runtimeTargetTone(enabled) {\n return enabled ? \"enabled\" : \"disabled\";\n }\n\n function currentRuntimeTargetText(platform = state.selected, account = selectedAccount(platform)) {\n const target = runtimeTargetStateForAccount(platform, account);\n if (!target.known) return t(\"notRead\");\n return runtimeTargetText(target.enabled);\n }\n\n function currentRuntimeTargetTone(platform = state.selected, account = selectedAccount(platform)) {\n const target = runtimeTargetStateForAccount(platform, account);\n if (!target.known) return \"neutral\";\n return runtimeTargetTone(target.enabled);\n }\n\n function incomeLayerDefaultForStrategy(profile) {\n return incomeLayerDefaults[cleanStrategyProfile(profile)] || null;\n }\n\n function incomeLayerSupported(profile) {\n return Boolean(incomeLayerDefaultForStrategy(profile));\n }\n\n function normalizeIncomeLayerMode(value) {\n return incomeLayerModes.includes(value) ? value : \"current\";\n }\n\n function incomeLayerModeLabel(mode) {\n if (mode === \"enabled\") return t(\"incomeLayerEnabled\");\n if (mode === \"disabled\") return t(\"incomeLayerDisabled\");\n return \"\";\n }\n\n function optionOverlayDefaultForStrategy(profile) {\n return optionOverlayDefaults[cleanStrategyProfile(profile)] || null;\n }\n\n function optionOverlaySupported(profile) {\n return Boolean(optionOverlayDefaultForStrategy(profile));\n }\n\n function normalizeOptionOverlayMode(value) {\n return optionOverlayModes.includes(value) ? value : \"current\";\n }\n\n function optionOverlayModeLabel(mode) {\n if (mode === \"enabled\") return t(\"optionOverlayEnabled\");\n if (mode === \"disabled\") return t(\"optionOverlayDisabled\");\n return \"\";\n }\n\n function optionOverlayText(enabled) {\n return enabled ? t(\"optionOverlayOn\") : t(\"optionOverlayOff\");\n }\n\n function normalizeCashOnlyExecutionMode(value) {\n return cashOnlyExecutionModes.includes(value) ? value : \"current\";\n }\n\n function cashOnlyExecutionModeLabel(mode) {\n if (mode === \"enabled\") return t(\"cashOnlyExecutionNo\");\n if (mode === \"disabled\") return t(\"cashOnlyExecutionYes\");\n return \"\";\n }\n\n function cashOnlyExecutionText(enabled) {\n if (enabled === null) return t(\"notRead\");\n return enabled ? t(\"cashOnlyExecutionValueNo\") : t(\"cashOnlyExecutionValueYes\");\n }\n\n function platformCashOnlyExecutionDefault() {\n return true;\n }\n\n function effectiveCashOnlyExecutionForAccount(platform, account) {\n return currentCashOnlyExecutionForAccount(platform, account);\n }\n\n function currentCashOnlyExecutionForAccount(platform, account) {\n const entry = accountReadbackEntry(platform, account);\n if (entry) {\n const val = cleanOptionalBoolean(entry.cash_only_execution);\n if (val !== null) return val;\n }\n return null;\n }\n\n function currentCashOnlyExecutionText(platform = state.selected, account = selectedAccount(platform)) {\n if (!platformSupportsMarginPolicy(platform)) return t(\"notRead\");\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return t(\"notRead\");\n const configured = cleanOptionalBoolean(entry.cash_only_execution);\n if (configured === null) return t(\"notConfigured\");\n return cashOnlyExecutionText(configured);\n }\n\n function currentOptionOverlayForAccount(platform, account) {\n return cleanOptionalBoolean(accountReadbackEntry(platform, account)?.option_overlay_enabled);\n }\n\n function effectiveOptionOverlayForAccount(platform, account, profile = state.forms[platform]?.strategy) {\n const configured = currentOptionOverlayForAccount(platform, account);\n return configured === null ? null : configured;\n }\n\n function optionOverlayDefaultSummaryDetail(defaults) {\n if (!defaults?.families?.length) return \"\";\n return defaults.families.map((item) => {\n const family = item.family === \"income\" ? t(\"optionOverlayFamilyIncome\") : t(\"optionOverlayFamilyGrowth\");\n const ratioText = item.ratioKind === \"risk\"\n ? t(\"optionOverlayRiskRatio\").replace(\"{ratio}\", formatRatioPercent(item.ratio))\n : t(\"optionOverlayBudgetRatio\").replace(\"{ratio}\", formatRatioPercent(item.ratio));\n return `${family} ${ratioText}`;\n }).join(\" / \");\n }\n\n function optionOverlayDefaultText(profile) {\n const defaults = optionOverlayDefaultForStrategy(profile);\n if (!defaults) return t(\"optionOverlayNotSupported\");\n const detail = optionOverlayDefaultSummaryDetail(defaults);\n return detail ? t(\"optionOverlayDefault\").replace(\"{detail}\", detail) : t(\"optionOverlayDefaultSimple\");\n }\n\n function currentOptionOverlayText(platform = state.selected, account = selectedAccount(platform), profile = state.forms[platform]?.strategy) {\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return t(\"notRead\");\n const configured = cleanOptionalBoolean(entry.option_overlay_enabled);\n if (!optionOverlaySupported(profile)) {\n return configured === null ? t(\"optionOverlayNotSupported\") : optionOverlayText(configured);\n }\n if (configured === null) return t(\"strategyDefault\");\n return optionOverlayText(configured);\n }\n\n function currentIncomeLayerForAccount(platform, account) {\n return incomeLayerFromEntry(currentEntryForAccount(platform, account));\n }\n\n function incomeLayerFromEntry(entry) {\n return {\n enabled: cleanOptionalBoolean(entry?.income_layer_enabled),\n startUsd: cleanDisplayNumber(entry?.income_layer_start_usd),\n maxRatio: cleanDisplayRatio(entry?.income_layer_max_ratio),\n };\n }\n\n function incomeLayerFieldsConfigured(entry) {\n const current = incomeLayerFromEntry(entry);\n return current.enabled !== null || Boolean(current.startUsd || current.maxRatio);\n }\n\n function effectiveIncomeLayerForAccount(platform, account, profile = state.forms[platform]?.strategy) {\n const defaults = incomeLayerDefaultForStrategy(profile);\n if (!defaults) return null;\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return null;\n const current = incomeLayerFromEntry(entry);\n if (!incomeLayerFieldsConfigured(entry)) {\n return {\n enabled: true,\n startUsd: String(defaults.startUsd),\n maxRatio: defaults.maxRatio,\n };\n }\n return {\n enabled: current.enabled ?? true,\n startUsd: current.startUsd || String(defaults.startUsd),\n maxRatio: current.maxRatio || defaults.maxRatio,\n };\n }\n\n function currentDcaForAccount(platform, account, profile = state.forms[platform]?.strategy) {\n const defaults = dcaConfigForStrategy(profile);\n if (!defaults) return { supported: false, mode: \"\", baseInvestmentUsd: \"\" };\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return { supported: true, mode: \"\", baseInvestmentUsd: \"\" };\n return {\n supported: true,\n mode: normalizeDcaMode(entry.dca_mode),\n baseInvestmentUsd: cleanDisplayPositiveNumber(entry.dca_base_investment_usd),\n };\n }\n\n function normalizeAccountLookupKey(value) {\n return String(value || \"\").trim().toLowerCase();\n }\n\n function collectAccountLookupCandidates(keys) {\n const candidates = new Set();\n for (const rawKey of keys) {\n const key = normalizeAccountLookupKey(rawKey);\n if (!key) continue;\n\n candidates.add(key);\n\n const compact = key.replace(/[^a-z0-9]+/g, \"\");\n if (compact) candidates.add(compact);\n\n const parts = key.split(/[^a-z0-9]+/).filter(Boolean);\n if (parts.length > 1) candidates.add(parts[parts.length - 1]);\n }\n return [...candidates];\n }\n\n function resolveCurrentEntryByKey(byPlatform, keys) {\n const candidates = new Set(collectAccountLookupCandidates(keys));\n if (!candidates.size) return null;\n\n for (const key of keys) {\n const entry = byPlatform[key];\n if (currentEntryHasState(entry)) return entry;\n }\n\n for (const [rawKey, entry] of Object.entries(byPlatform)) {\n if (!currentEntryHasState(entry)) continue;\n const rawCandidates = collectAccountLookupCandidates([rawKey]);\n const hasMatch = rawCandidates.some((candidate) => candidates.has(candidate));\n if (hasMatch) return entry;\n }\n\n return null;\n }\n\n function currentEntryForAccount(platform, account) {\n const byPlatform = state.currentStrategies[platform] || {};\n const keys = [account?.key, account?.target_name, account?.label]\n .filter(Boolean)\n .map((value) => String(value));\n const entry = resolveCurrentEntryByKey(byPlatform, keys);\n if (entry) return entry;\n // Account options describe routing. They are not a readback of the\n // runtime configuration, so leave all runtime values unknown until the\n // authoritative current-strategies snapshot supplies them.\n return {\n strategy_profile: \"\",\n source: \"account_defaults\",\n runtime_target_enabled: null,\n };\n }\n\n function currentEntryHasState(entry) {\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) return false;\n return Boolean(\n cleanStrategyProfile(entry.strategy_profile) ||\n cleanDisplayNumber(entry.min_reserved_cash_usd ?? entry.reserved_cash_floor_usd) ||\n cleanDisplayRatio(entry.reserved_cash_ratio) ||\n cleanOptionalBoolean(entry.income_layer_enabled) !== null ||\n cleanDisplayNumber(entry.income_layer_start_usd) ||\n cleanDisplayRatio(entry.income_layer_max_ratio) ||\n cleanOptionalBoolean(entry.option_overlay_enabled) !== null ||\n cleanOptionalBoolean(entry.cash_only_execution) !== null ||\n cleanOptionalBoolean(entry.runtime_target_enabled) !== null ||\n normalizeDcaMode(entry.dca_mode || \"\") !== \"fixed\" ||\n cleanDisplayPositiveNumber(entry.dca_base_investment_usd) ||\n normalizeExecutionEnvironment(entry.execution_environment) ||\n normalizeExecutionMode(entry.execution_mode, entry.dry_run_only),\n );\n }\n\n function accountReadbackEntry(platform, account) {\n const entry = currentEntryForAccount(platform, account);\n return entry?.source === \"account_defaults\" ? null : entry;\n }\n\n function currentStrategyForAccount(platform, account) {\n const entry = accountReadbackEntry(platform, account);\n return cleanStrategyProfile(entry?.strategy_profile) || \"\";\n }\n\n function currentReservePolicyForAccount(platform, account) {\n const entry = currentEntryForAccount(platform, account);\n return reservePolicyFromEntry(entry);\n }\n\n function currentPluginModeForAccount(platform, account) {\n void platform;\n return normalizePluginMode(account?.plugin_mode);\n }\n\n function reservePolicyFromEntry(entry) {\n return {\n minReservedCashUsd: cleanDisplayNumber(entry?.min_reserved_cash_usd ?? entry?.reserved_cash_floor_usd),\n reservedCashRatio: cleanDisplayRatio(entry?.reserved_cash_ratio),\n };\n }\n\n function cleanDisplayNumber(value) {\n const text = String(value ?? \"\").trim();\n if (!text || text.length > 32 || !/^(?:\\d+|\\d*\\.\\d+)$/.test(text)) return \"\";\n const numeric = Number(text);\n if (!Number.isFinite(numeric) || numeric < 0) return \"\";\n return text;\n }\n\n function cleanDisplayRatio(value) {\n const text = cleanDisplayNumber(value);\n if (!text) return \"\";\n const numeric = Number(text);\n return numeric >= 0 && numeric <= 1 ? text : \"\";\n }\n\n function cleanDisplayPositiveNumber(value) {\n const text = cleanDisplayNumber(value);\n return text && Number(text) > 0 ? text : \"\";\n }\n\n\n const PROMOTION_RISK_PROFILES = [\n \"CAPITAL_PRESERVATION\",\n \"BALANCED_COMPOUNDING\",\n \"GROWTH_COMPOUNDING\",\n ];\n const DEFAULT_PROMOTION_RISK_PROFILE = \"CAPITAL_PRESERVATION\";\n\n function promotionRiskProfileLabel(profile) {\n if (profile === \"CAPITAL_PRESERVATION\") return t(\"riskCapitalPreservation\");\n if (profile === \"BALANCED_COMPOUNDING\") return t(\"riskBalancedCompounding\");\n if (profile === \"GROWTH_COMPOUNDING\") return t(\"riskGrowthCompounding\");\n return profile;\n }\n\n function buildPromotionConfirmation({\n targetPlatform,\n executionMode,\n riskProfile,\n paperSupported,\n suggestedRiskProfile,\n }) {\n const platform = String(targetPlatform || \"\").trim();\n const mode = String(executionMode || \"\").trim().toLowerCase();\n const profile = String(riskProfile || DEFAULT_PROMOTION_RISK_PROFILE).trim().toUpperCase();\n const suggested = String(\n suggestedRiskProfile || DEFAULT_PROMOTION_RISK_PROFILE,\n ).trim().toUpperCase();\n if (!platform) throw new Error(\"target_platform required\");\n if (mode !== \"live\" && mode !== \"paper\") throw new Error(\"execution_mode must be live or paper\");\n if (!PROMOTION_RISK_PROFILES.includes(profile)) throw new Error(\"invalid risk_profile\");\n if (!PROMOTION_RISK_PROFILES.includes(suggested)) throw new Error(\"invalid suggested_risk_profile\");\n if (mode === \"paper\" && !paperSupported) {\n throw new Error(\"paper unavailable; synthetic matching is not supported\");\n }\n // Exact QPK PromotionConfirmation.to_dict() fields only.\n return {\n target_platform: platform,\n execution_mode: mode,\n risk_profile: profile,\n };\n }\n\n\n function buildDesignPreviewRiskEnvelopeView(riskPreference) {\n const profile = String(riskPreference || \"\").trim().toUpperCase();\n const labels = {\n CAPITAL_PRESERVATION: { zh: \"保全\", en: \"Preserve\" },\n BALANCED_COMPOUNDING: { zh: \"均衡\", en: \"Balance\" },\n GROWTH_COMPOUNDING: { zh: \"增长\", en: \"Growth\" },\n };\n const scales = {\n CAPITAL_PRESERVATION: { composer_mdd_multiple: 1.0, promotion_size_scale: 0.5 },\n BALANCED_COMPOUNDING: { composer_mdd_multiple: 1.25, promotion_size_scale: 0.75 },\n GROWTH_COMPOUNDING: { composer_mdd_multiple: 1.5, promotion_size_scale: 1.0 },\n };\n const known = Object.prototype.hasOwnProperty.call(labels, profile);\n return {\n schema: \"qsl.risk_envelope_view.v1\",\n source: \"design_preview\",\n preference: known\n ? { id: profile, label_zh: labels[profile].zh, label_en: labels[profile].en }\n : { id: \"unknown\", label_zh: \"未设定\", label_en: \"Unset\" },\n capital_band: {\n id: \"unknown\",\n label_zh: \"待对账权益注入\",\n label_en: \"Awaiting reconciled equity\",\n },\n status: {\n id: \"unknown\",\n label_zh: \"待对账权益注入\",\n label_en: \"Awaiting reconciled equity\",\n },\n scales: {\n composer_mdd_multiple: known ? scales[profile].composer_mdd_multiple : null,\n promotion_size_scale: known ? scales[profile].promotion_size_scale : null,\n capital_scale: null,\n vol_scale: null,\n dd_scale: null,\n },\n detail: {\n dual_scale_note_zh:\n \"双口径:Composer 相对无杠杆基准 MDD 天花板为 1.00 / 1.25 / 1.50;晋级仓位缩放为 0.50 / 0.75 / 1.00(仅新晋级/材料变更)。资金信封 combined_scale = capital_scale × vol_scale × dd_scale(各因子 ≤1),由系统按权益/波动/回撤计算,禁止自动升档。\",\n dual_scale_note_en:\n \"Dual scale: Composer unlevered-benchmark MDD caps are 1.00 / 1.25 / 1.50; promotion size scales are 0.50 / 0.75 / 1.00 (new promotion / material change only). Envelope combined_scale = capital_scale × vol_scale × dd_scale (each ≤1), system-computed from equity/vol/drawdown; auto step-up is forbidden.\",\n },\n live_authority_granted: false,\n };\n }\n\n function renderRiskEnvelopePanel() {\n const preferenceEl = el(\"risk-envelope-preference\");\n const bandEl = el(\"risk-envelope-capital-band\");\n const statusEl = el(\"risk-envelope-status\");\n const detailsEl = el(\"risk-envelope-details\");\n const panel = el(\"risk-envelope-panel\");\n if (!preferenceEl || !bandEl || !statusEl || !detailsEl) return;\n const ticket = selectedPromotionTicket();\n const riskSelect = el(\"promotion-risk-profile-select\");\n const selectedProfile = String(riskSelect?.value || ticket?.suggested_risk_profile || DEFAULT_PROMOTION_RISK_PROFILE).trim().toUpperCase();\n const view = ticket?.risk_envelope_view && typeof ticket.risk_envelope_view === \"object\"\n ? {\n ...ticket.risk_envelope_view,\n preference: {\n ...(ticket.risk_envelope_view.preference || {}),\n ...(buildDesignPreviewRiskEnvelopeView(selectedProfile).preference || {}),\n },\n scales: {\n ...(ticket.risk_envelope_view.scales || {}),\n ...(buildDesignPreviewRiskEnvelopeView(selectedProfile).scales || {}),\n },\n }\n : buildDesignPreviewRiskEnvelopeView(selectedProfile);\n const zh = state.lang !== \"en\";\n preferenceEl.textContent = zh\n ? (view.preference?.label_zh || t(\"riskEnvelopeUnset\"))\n : (view.preference?.label_en || t(\"riskEnvelopeUnset\"));\n bandEl.textContent = zh\n ? (view.capital_band?.label_zh || t(\"riskEnvelopeAwaitingEquity\"))\n : (view.capital_band?.label_en || t(\"riskEnvelopeAwaitingEquity\"));\n const statusId = String(view.status?.id || \"unknown\");\n statusEl.textContent = zh\n ? (view.status?.label_zh || t(\"riskEnvelopeAwaitingEquity\"))\n : (view.status?.label_en || t(\"riskEnvelopeAwaitingEquity\"));\n statusEl.dataset.status = statusId;\n if (panel) panel.dataset.status = statusId;\n const scales = view.scales || {};\n const note = zh ? (view.detail?.dual_scale_note_zh || \"\") : (view.detail?.dual_scale_note_en || \"\");\n const scaleLines = [\n `Composer MDD ×${scales.composer_mdd_multiple ?? \"—\"}`,\n `promo size ×${scales.promotion_size_scale ?? \"—\"}`,\n `capital_scale=${scales.capital_scale ?? \"null\"}`,\n `vol_scale=${scales.vol_scale ?? \"null\"}`,\n `dd_scale=${scales.dd_scale ?? \"null\"}`,\n `source=${view.source || \"design_preview\"}`,\n `live_authority_granted=${view.live_authority_granted === true}`,\n ];\n detailsEl.textContent = `${note}\\n${scaleLines.join(\" · \")}`;\n }\n\n function selectedPromotionTicket() {\n const tickets = state.researchPromotion?.payload?.tickets || [];\n const selectedId = state.researchPromotion?.selectedTicketId || \"\";\n return tickets.find((ticket) => ticket.ticket_id === selectedId) || null;\n }\n\n function promotionTicketNeedsSourceCheck(ticket) {\n return !String(ticket?.shadow_evidence_kind || \"\").trim();\n }\n\n function reviewablePromotionTickets(payload) {\n if (payload?.data_status !== \"ready\" || payload?.errors?.length) return [];\n return (payload.tickets || []).filter((ticket) =>\n ticket.state === \"awaiting_human\" && !promotionTicketNeedsSourceCheck(ticket));\n }\n\n function promotionTicketDisplayName(ticket, index = 0) {\n const profile = String(ticket?.strategy_profile || \"\");\n if (profile === \"synthetic-profile\") return t(\"promotionUnnamedRecord\").replace(\"{number}\", String(index + 1));\n if (profile === \"smoke\") return t(\"promotionFlowRecord\");\n const label = profile === \"soxl_soxx_trend_income\" ? `SOXL · ${strategyLabel(profile)}` : strategyLabel(profile || \"?\");\n return `${label} · ${t(promotionTicketNeedsSourceCheck(ticket) ? \"promotionOldRecord\" : \"promotionParameterProposal\")}`;\n }\n\n function renderUnverifiedPromotionRecords(tickets) {\n const section = el(\"promotion-unverified-records\");\n const list = el(\"promotion-unverified-list\");\n if (!section || !list) return;\n section.hidden = !tickets.length;\n el(\"promotion-unverified-summary\").textContent = t(\"promotionUnverifiedCount\").replace(\"{count}\", String(tickets.length));\n list.replaceChildren();\n tickets.forEach((ticket, index) => {\n const card = document.createElement(\"article\");\n card.className = \"promotion-old-record\";\n const title = document.createElement(\"h4\");\n title.textContent = promotionTicketDisplayName(ticket, index);\n const hint = document.createElement(\"p\");\n hint.textContent = t(\"promotionUnverifiedHint\");\n const details = document.createElement(\"details\");\n const summary = document.createElement(\"summary\");\n summary.textContent = t(\"promotionOriginalRecord\");\n const evidence = document.createElement(\"p\");\n evidence.textContent = `${ticket.strategy_profile || \"?\"} · ${promotionTicketDetailMessage(ticket)}`;\n details.append(summary, evidence);\n card.append(title, hint, details);\n list.appendChild(card);\n });\n }\n\n function promotionTicketQueueMessage() {\n if (!state.auth?.allowed) return t(\"promotionTicketLoginRequired\");\n const payload = state.researchPromotion?.payload || {};\n if (payload.data_status === \"login_required\") return t(\"promotionTicketLoginRequired\");\n if (\n payload.data_status !== \"ready\"\n || (Array.isArray(payload.errors) && payload.errors.length > 0)\n ) {\n return t(\"promotionTicketLoadFailed\");\n }\n return t(\"promotionTicketEmpty\");\n }\n\n function promotionTicketEvidenceMessage(ticket) {\n const outcome = ticket?.shadow_passed === true\n ? \"promotionObservationReported\"\n : ticket?.shadow_passed === false ? \"promotionObservationFailed\" : \"promotionObservationMissing\";\n const provenance = String(ticket?.shadow_evidence_kind || \"\").trim()\n ? \"promotionEvidenceNeedsReview\" : \"promotionEvidenceSourceMissing\";\n return `${t(outcome)} ${t(provenance)}`;\n }\n\n function promotionSummaryCanonical(value) {\n if (value === null) return \"null\";\n if (typeof value === \"string\" || typeof value === \"boolean\") return JSON.stringify(value);\n if (typeof value === \"number\") return Number.isFinite(value) ? JSON.stringify(value) : \"\";\n if (Array.isArray(value)) return `[${value.map(promotionSummaryCanonical).join(\",\")}]`;\n if (!value || typeof value !== \"object\") return \"\";\n return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${promotionSummaryCanonical(value[key])}`).join(\",\")}}`;\n }\n\n function promotionResearchSummaryForDisplay(ticket) {\n const summary = ticket?.research_summary;\n if (!summary || typeof summary !== \"object\" || Array.isArray(summary)) return null;\n const identity = summary.identity;\n if (!identity || identity.strategy_profile !== ticket.strategy_profile || identity.domain !== ticket.domain\n || promotionSummaryCanonical(identity.proposed_params) !== promotionSummaryCanonical(ticket.proposed_params || {})) {\n return null;\n }\n return summary;\n }\n\n function formatPromotionPercent(value) {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return \"\";\n return `${(value * 100).toFixed(2)}%`;\n }\n\n function promotionResearchSummaryMessage(ticket) {\n const summary = promotionResearchSummaryForDisplay(ticket);\n const strategy = strategyLabel(ticket?.strategy_profile || \"\") || t(\"commonUnknown\");\n const observation = promotionTicketEvidenceMessage(ticket);\n if (!summary) {\n return t(\"promotionResearchSummaryMissing\")\n .replace(\"{strategy}\", strategy)\n .replace(\"{observation}\", observation);\n }\n const lines = [t(\"promotionResearchSummary\")];\n const missing = [];\n const description = String(summary.strategy_description || \"\").trim();\n if (description) lines.push(t(\"promotionStrategyDescription\").replace(\"{description}\", description));\n else missing.push(state.lang === \"zh\" ? \"策略说明\" : \"strategy explanation\");\n if (summary.plugins === null) {\n lines.push(t(\"promotionPluginsUnknown\"));\n } else if (Array.isArray(summary.plugins) && summary.plugins.length === 0) {\n lines.push(t(\"promotionPluginsNone\"));\n } else if (Array.isArray(summary.plugins)) {\n const descriptions = summary.plugins.map((plugin) => String(plugin?.description || \"\").trim()).filter(Boolean);\n lines.push(descriptions.length\n ? t(\"promotionPlugins\").replace(\"{description}\", descriptions.join(\"、\"))\n : t(\"promotionPluginsUnknown\"));\n }\n const comparison = summary.comparison;\n const candidate = comparison?.candidate;\n const baseline = comparison?.baseline;\n const candidateCagr = formatPromotionPercent(candidate?.cagr);\n const candidateDrawdown = formatPromotionPercent(candidate?.max_drawdown);\n const baselineCagr = formatPromotionPercent(baseline?.cagr);\n const baselineDrawdown = formatPromotionPercent(baseline?.max_drawdown);\n const startDate = String(comparison?.start_date || \"\").trim();\n const endDate = String(comparison?.end_date || \"\").trim();\n if (comparison?.status === \"comparable\" && startDate && endDate\n && candidateCagr && candidateDrawdown && baselineCagr && baselineDrawdown) {\n lines.push(t(\"promotionComparison\")\n .replace(\"{startDate}\", startDate)\n .replace(\"{endDate}\", endDate)\n .replace(\"{candidateCagr}\", candidateCagr)\n .replace(\"{candidateDrawdown}\", candidateDrawdown)\n .replace(\"{baselineCagr}\", baselineCagr)\n .replace(\"{baselineDrawdown}\", baselineDrawdown));\n } else {\n missing.push(state.lang === \"zh\" ? \"收益对比\" : \"return comparison\");\n }\n const limitations = Array.isArray(summary.limitations)\n ? summary.limitations.map((item) => String(item || \"\").trim()).filter(Boolean)\n : [];\n if (limitations.length) lines.push(t(\"promotionLimitations\").replace(\"{limitations}\", limitations.join(\";\")));\n else missing.push(state.lang === \"zh\" ? \"不足\" : \"limitations\");\n const ai = summary.ai_explanation;\n if (ai?.status === \"available\" && ai.provider === \"codex\" && String(ai.text || \"\").trim()) {\n lines.push(t(\"promotionAiExplanation\").replace(\"{text}\", String(ai.text).trim()));\n }\n if (missing.length) lines.push(t(\"promotionResearchSummaryMissingParts\").replace(\"{items}\", missing.join(state.lang === \"zh\" ? \"、\" : \", \")));\n return lines.join(\" · \");\n }\n\n function promotionClickEffectMessage(account) {\n const mode = account?.broker_environment === \"paper\"\n ? t(\"promotionModePaper\")\n : account?.broker_environment === \"live\" ? t(\"promotionModeLive\") : t(\"commonUnknown\");\n return t(\"promotionClickEffect\").replace(\"{mode}\", mode);\n }\n\n function promotionTicketDetailMessage(ticket) {\n if (!ticket) return \"\";\n const evidenceKind = String(ticket.shadow_evidence_kind || \"\").trim() || t(\"commonUnknown\");\n const params = JSON.stringify(ticket.proposed_params || {});\n const detail = [\n `${ticket.ticket_id} · ${formatDateTime(ticket.created_at)}`,\n t(\"promotionTicketEvidenceKind\").replace(\"{kind}\", evidenceKind),\n promotionTicketEvidenceMessage(ticket),\n t(\"promotionTicketParams\").replace(\"{params}\", params),\n ];\n const notification = String(ticket.notification_body || \"\").trim();\n if (notification) {\n detail.push(t(\"promotionTicketNotification\").replace(\"{body}\", notification));\n }\n return detail.join(\" · \");\n }\n\n function promotionApplications() {\n const payload = state.researchPromotion?.payload || {};\n if (payload.data_status !== \"ready\" || payload.errors?.length) return [];\n return Array.isArray(payload.applications) ? payload.applications : [];\n }\n\n function selectedPromotionApplication() {\n const applications = promotionApplications();\n const selectedId = state.researchPromotion.selectedApplicationTicketId || \"\";\n return applications.find((item) => item.ticket_id === selectedId) || applications[0] || null;\n }\n\n function selectedPromotionApplicationAccount(application = selectedPromotionApplication()) {\n const accounts = application?.application_preparation?.account_options || [];\n const selectedKey = state.researchPromotion.selectedApplicationAccountKey || \"\";\n const platform = state.researchPromotion.selectedApplicationPlatform || \"\";\n const environment = state.researchPromotion.selectedApplicationEnvironment || \"\";\n return accounts.find((item) => `${item.platform}/${item.key}` === selectedKey)\n || accounts.find((item) => (!platform || item.platform === platform) && (!environment || item.broker_environment === environment))\n || accounts[0]\n || null;\n }\n\n function promotionApplicationBlockerLabel(code) {\n if (code === \"activation_not_connected\") return t(\"promotionApplicationBlockActivation\");\n if (code === \"candidate_params_unbound\") return t(\"promotionApplicationBlockParams\");\n if (code === \"strategy_not_configured\") return t(\"promotionApplicationBlockStrategy\");\n if (code === \"configured_account_missing\") return t(\"promotionApplicationBlockAccount\");\n if (code === \"research_evidence_unverified\") return t(\"promotionApplicationBlockEvidence\");\n if (code === \"broker_environment_unknown\" || code === \"broker_environment_unsupported\") return t(\"promotionApplicationBlockBrokerEnvironment\");\n return t(\"promotionApplicationBlockPreflight\");\n }\n\n function promotionApplicationReasonLabel(code) {\n const labels = {\n readback_mismatch: state.lang === \"zh\" ? \"版本核对不一致\" : \"version readback did not match\",\n workflow_rejected: state.lang === \"zh\" ? \"部署未通过\" : \"deployment was rejected\",\n workflow_uncertain: state.lang === \"zh\" ? \"部署结果待确认\" : \"deployment result is unconfirmed\",\n account_changed: state.lang === \"zh\" ? \"账户配置已变化\" : \"account configuration changed\",\n qualification_changed: state.lang === \"zh\" ? \"候选资格已变化\" : \"candidate qualification changed\",\n };\n return labels[String(code || \"\")] || (state.lang === \"zh\" ? \"状态待确认\" : \"status is unconfirmed\");\n }\n\n function renderPromotionSelectionControls(application = selectedPromotionApplication()) {\n const platformSelect = el(\"promotion-target-platform-select\");\n const environmentSelect = el(\"promotion-broker-environment-select\");\n const accountSelect = el(\"promotion-selected-account-select\");\n if (!platformSelect || !environmentSelect || !accountSelect) return null;\n const accounts = application?.application_preparation?.account_options || [];\n const platforms = [...new Set(accounts.map((item) => item.platform))];\n const previousPlatform = state.researchPromotion.selectedApplicationPlatform;\n const platform = platforms.includes(previousPlatform) ? previousPlatform : (platforms[0] || \"\");\n state.researchPromotion.selectedApplicationPlatform = platform;\n platformSelect.replaceChildren();\n for (const value of platforms) {\n platformSelect.append(new Option(platformMeta[value]?.label || value, value, false, value === platform));\n }\n if (!platforms.length) platformSelect.append(new Option(t(\"promotionApplicationBlockAccount\"), \"\", true, true));\n const platformAccounts = accounts.filter((item) => item.platform === platform);\n const environments = [...new Set(platformAccounts.map((item) => item.broker_environment).filter(Boolean))];\n const previousEnvironment = state.researchPromotion.selectedApplicationEnvironment;\n const environment = environments.includes(previousEnvironment) ? previousEnvironment : (environments[0] || \"\");\n state.researchPromotion.selectedApplicationEnvironment = environment;\n environmentSelect.replaceChildren();\n for (const value of environments) {\n environmentSelect.append(new Option(value === \"paper\" ? t(\"promotionModePaper\") : t(\"promotionModeLive\"), value, false, value === environment));\n }\n if (!environments.length) environmentSelect.append(new Option(t(\"commonUnknown\"), \"\", true, true));\n const filteredAccounts = platformAccounts.filter((item) => item.broker_environment === environment);\n const previousKey = state.researchPromotion.selectedApplicationAccountKey;\n const selectedKey = filteredAccounts.some((item) => `${item.platform}/${item.key}` === previousKey)\n ? previousKey : (filteredAccounts[0] ? `${filteredAccounts[0].platform}/${filteredAccounts[0].key}` : \"\");\n state.researchPromotion.selectedApplicationAccountKey = selectedKey;\n accountSelect.replaceChildren();\n for (const account of filteredAccounts) {\n accountSelect.append(new Option(`${account.label} · ${account.key}`, `${account.platform}/${account.key}`, false, `${account.platform}/${account.key}` === selectedKey));\n }\n if (!filteredAccounts.length) accountSelect.append(new Option(t(\"promotionApplicationBlockAccount\"), \"\", true, true));\n const selected = filteredAccounts.find((item) => `${item.platform}/${item.key}` === selectedKey) || null;\n const modeReadonly = el(\"promotion-execution-mode-readonly\");\n if (modeReadonly) {\n const modeLabel = selected?.broker_environment === \"paper\" ? t(\"promotionModePaper\") : selected?.broker_environment === \"live\" ? t(\"promotionModeLive\") : t(\"commonUnknown\");\n modeReadonly.textContent = selected ? t(\"promotionExecutionModeReadonly\").replace(\"{mode}\", modeLabel) : \"\";\n }\n return selected;\n }\n\n function renderPromotionApplicationPreparation() {\n const applications = promotionApplications();\n const block = el(\"promotion-application-block\");\n const status = el(\"promotion-application-status\");\n const progress = el(\"promotion-application-progress\");\n const deployButton = el(\"promotion-application-deploy\");\n const openButton = el(\"promotion-application-open\");\n if (!block || !status || !openButton || !deployButton) return;\n block.hidden = !applications.length;\n if (!applications.length) {\n status.textContent = t(\"promotionApplicationEmpty\");\n if (progress) progress.textContent = \"\";\n deployButton.hidden = true;\n deployButton.disabled = true;\n openButton.disabled = true;\n return;\n }\n const application = selectedPromotionApplication();\n const account = selectedPromotionApplicationAccount(application);\n const blockers = [\n ...(application?.application_preparation?.blocker_codes || []),\n ...(account?.blocker_codes || []),\n ];\n const uniqueBlockers = [...new Set(blockers)];\n const preflightReady = application?.application_preparation?.preflight_status === \"ready\"\n && account?.preflight_status === \"ready\";\n status.textContent = preflightReady\n ? t(\"promotionApplicationReady\")\n : t(\"promotionApplicationBlocked\").replace(\n \"{reasons}\",\n uniqueBlockers.map(promotionApplicationBlockerLabel).join(\"、\"),\n );\n openButton.disabled = !preflightReady;\n const storedApplication = application?.application || null;\n const previewReady = Boolean(application?.application_preparation?.preview_request)\n && preflightReady && account?.platform === \"longbridge\" && account?.broker_environment === \"paper\";\n const canRetryRejected = storedApplication?.status === \"rejected\";\n deployButton.hidden = !previewReady || Boolean(storedApplication && !canRetryRejected);\n deployButton.disabled = !previewReady || Boolean(storedApplication && !canRetryRejected);\n if (progress) {\n if (!storedApplication) progress.textContent = previewReady ? \"\" : \"\";\n else if (storedApplication.status === \"approved\" && storedApplication.dispatch_state === \"unknown\") progress.textContent = t(\"promotionApplicationDispatchUnknown\");\n else if (storedApplication.status === \"approved\") progress.textContent = t(\"promotionApplicationQueued\");\n else if (storedApplication.status === \"claimed\") progress.textContent = t(\"promotionApplicationClaimed\");\n else if (storedApplication.status === \"applied_paused\") progress.textContent = t(\"promotionApplicationApplied\");\n else if (storedApplication.status === \"rejected\") progress.textContent = t(\"promotionApplicationRejected\").replace(\"{reason}\", promotionApplicationReasonLabel(storedApplication.reason_code));\n else progress.textContent = t(\"promotionApplicationUncertain\");\n }\n }\n\n async function submitV7PaperApplication() {\n const application = selectedPromotionApplication();\n const account = selectedPromotionApplicationAccount(application);\n const ticketId = application?.ticket_id || \"\";\n if (!ticketId || !account || application?.application_preparation?.preflight_status !== \"ready\"\n || !application?.application_preparation?.preview_request || account.platform !== \"longbridge\"\n || account.broker_environment !== \"paper\") return;\n const button = el(\"promotion-application-deploy\");\n if (button) button.disabled = true;\n try {\n const instanceState = await requestJson(\"/api/admin/runtime-instances\");\n const response = await fetch(\"/api/research-promotion-applications\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ticket_id: ticketId,\n selected_account: { platform: account.platform, key: account.key },\n expected_revision: Number(instanceState.revision),\n }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"promotionApplicationUncertain\"));\n await refreshResearchPromotionTickets();\n } catch (error) {\n // A dispatch response can be unknown after the server has persisted it.\n // Refresh first so the rendered application state decides whether the\n // button remains disabled; never turn a possibly submitted request back\n // into an apparent retry.\n try { await refreshResearchPromotionTickets(); } catch { /* keep the button disabled until a later refresh */ }\n showToast(error.message || t(\"promotionApplicationUncertain\"), { duration: 9000 });\n if (button) button.disabled = true;\n }\n }\n\n function promotionConfirmationExecutionMode(platform = state.selected) {\n void platform;\n const brokerEnvironment = selectedPromotionApplicationAccount()?.broker_environment;\n return brokerEnvironment || \"\";\n }\n\n function renderPromotionConfirmControls() {\n const platform = state.selected;\n const platformVisible = platformMeta[platform]?.console_visible !== false;\n const payload = state.researchPromotion?.payload || {};\n const queueReady = payload.data_status === \"ready\" && !(payload.errors || []).length;\n const pendingTickets = state.auth?.allowed && queueReady\n ? (payload.tickets || []).filter((ticket) => ticket.state === \"awaiting_human\")\n : [];\n const tickets = state.auth?.allowed ? reviewablePromotionTickets(payload) : [];\n const applications = state.auth?.allowed ? promotionApplications() : [];\n renderUnverifiedPromotionRecords(pendingTickets.filter(promotionTicketNeedsSourceCheck));\n const panel = el(\"promotion-decision-panel\");\n if (panel) panel.hidden = !tickets.length || !platformVisible;\n const notice = el(\"promotion-queue-notice\");\n if (notice) {\n notice.hidden = !state.auth?.allowed || (tickets.length > 0 && platformVisible);\n notice.textContent = tickets.length && !platformVisible ? t(\"promotionTargetUnavailable\") : promotionTicketQueueMessage();\n }\n const confirmationBlock = el(\"promotion-confirm-block\");\n if (confirmationBlock) confirmationBlock.hidden = !tickets.length;\n const targetSummary = el(\"promotion-target-summary\");\n if (targetSummary) {\n targetSummary.textContent = t(\"promotionTargetSummary\")\n .replace(\"{platform}\", platformMeta[platform]?.label || t(\"commonUnknown\"))\n .replace(\"{account}\", selectedAccount(platform)?.label || t(\"commonUnknown\"));\n }\n const ticketSelect = el(\"promotion-ticket-select\");\n const modeReadonly = el(\"promotion-execution-mode-readonly\");\n const riskSelect = el(\"promotion-risk-profile-select\");\n const meta = el(\"promotion-confirm-meta\");\n const ticketMeta = el(\"promotion-ticket-meta\");\n const acceptButton = el(\"promotion-accept-button\");\n const rejectButton = el(\"promotion-reject-button\");\n if (!modeReadonly || !riskSelect) return;\n if (ticketSelect) {\n const previousTicket = state.researchPromotion.selectedTicketId || ticketSelect.value || \"\";\n ticketSelect.replaceChildren();\n if (!tickets.length) {\n ticketSelect.append(new Option(promotionTicketQueueMessage(), \"\", true, true));\n state.researchPromotion.selectedTicketId = \"\";\n } else {\n const selectedId = tickets.some((ticket) => ticket.ticket_id === previousTicket)\n ? previousTicket\n : tickets[0].ticket_id;\n state.researchPromotion.selectedTicketId = selectedId;\n for (const ticket of tickets) {\n const label = `${promotionTicketDisplayName(ticket)} · ${formatDateTime(ticket.created_at)}`;\n ticketSelect.append(new Option(label, ticket.ticket_id, false, ticket.ticket_id === selectedId));\n }\n }\n }\n const ticket = selectedPromotionTicket();\n const selectedPromotionAccount = typeof renderPromotionSelectionControls === \"function\"\n ? renderPromotionSelectionControls(selectedPromotionApplication())\n : null;\n const selectedPlatformVisible = selectedPromotionAccount\n ? platformMeta[selectedPromotionAccount.platform]?.console_visible !== false\n : platformVisible;\n if (targetSummary) {\n targetSummary.textContent = t(\"promotionTargetSummary\")\n .replace(\"{platform}\", platformMeta[selectedPromotionAccount?.platform || platform]?.label || t(\"commonUnknown\"))\n .replace(\"{account}\", selectedPromotionAccount?.label || selectedAccount(platform)?.label || t(\"commonUnknown\"));\n }\n const ticketDetail = el(\"promotion-ticket-detail\");\n if (ticketDetail) ticketDetail.textContent = promotionTicketDetailMessage(ticket);\n const researchSummary = el(\"promotion-research-summary\");\n if (researchSummary) researchSummary.textContent = promotionResearchSummaryMessage(ticket);\n const clickEffect = el(\"promotion-click-effect\");\n if (clickEffect) clickEffect.textContent = promotionClickEffectMessage(selectedPromotionAccount);\n const suggested = PROMOTION_RISK_PROFILES.includes(ticket?.suggested_risk_profile)\n ? ticket.suggested_risk_profile\n : DEFAULT_PROMOTION_RISK_PROFILE;\n const previousRisk = riskSelect.value || suggested;\n const promotionMode = promotionConfirmationExecutionMode(platform);\n riskSelect.replaceChildren();\n // Prefill from ticket suggestion unless the operator already chose another valid profile.\n const selectedRisk = PROMOTION_RISK_PROFILES.includes(previousRisk) && previousRisk\n ? (ticket && !riskSelect.dataset.touched ? suggested : previousRisk)\n : suggested;\n if (ticket && !riskSelect.dataset.touched) {\n // Prefer ticket suggestion on first bind / ticket change.\n }\n const riskToSelect = ticket && riskSelect.dataset.ticketId !== (ticket?.ticket_id || \"\")\n ? suggested\n : (PROMOTION_RISK_PROFILES.includes(previousRisk) ? previousRisk : suggested);\n for (const profile of PROMOTION_RISK_PROFILES) {\n riskSelect.append(new Option(promotionRiskProfileLabel(profile), profile, false, profile === riskToSelect));\n }\n riskSelect.dataset.ticketId = ticket?.ticket_id || \"\";\n if (meta) {\n meta.textContent = promotionMode ? t(\"promotionConfirmMeta\") : `${t(\"promotionConfirmMeta\")} ${t(\"promotionNoOrderCannotConfirm\")}`;\n }\n if (ticketMeta) {\n if (ticket) {\n const decisionMeta = state.auth?.admin\n ? t(\"promotionTicketSuggested\").replace(\"{profile}\", promotionRiskProfileLabel(suggested))\n : t(\"promotionAdminOnly\");\n ticketMeta.textContent = `${decisionMeta} ${promotionTicketEvidenceMessage(ticket)}`;\n } else {\n ticketMeta.textContent = promotionTicketQueueMessage();\n }\n }\n const canDecide = Boolean(\n ticket\n && state.auth?.admin\n && selectedPlatformVisible\n && promotionMode\n && selectedPromotionAccount\n && selectedPromotionAccount.broker_environment === promotionMode\n );\n if (acceptButton) acceptButton.disabled = !canDecide;\n if (rejectButton) rejectButton.disabled = !Boolean(ticket && state.auth?.admin);\n renderRiskEnvelopePanel();\n renderPromotionApplicationPreparation();\n }\n\n async function refreshResearchPromotionTickets() {\n if (!state.auth?.allowed) {\n state.researchPromotion.payload = {\n data_status: \"login_required\",\n computed_at: null,\n tickets: [],\n applications: [],\n summary: { ticket_count: 0, awaiting_human: 0 },\n policy: { live_authority_granted: false, no_order: true },\n errors: [],\n };\n renderPromotionConfirmControls();\n return;\n }\n try {\n const payload = await requestJson(\"/api/research-promotion-tickets\");\n state.researchPromotion.payload = {\n data_status: payload?.data_status || \"ready\",\n computed_at: payload?.computed_at || null,\n tickets: Array.isArray(payload?.tickets) ? payload.tickets : [],\n applications: Array.isArray(payload?.applications) ? payload.applications : [],\n summary: payload?.summary || { ticket_count: 0, awaiting_human: 0 },\n policy: {\n live_authority_granted: false,\n no_order: true,\n ...(payload?.policy || {}),\n },\n errors: Array.isArray(payload?.errors) ? payload.errors : [],\n };\n } catch {\n state.researchPromotion.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n tickets: [],\n applications: [],\n summary: { ticket_count: 0, awaiting_human: 0 },\n policy: { live_authority_granted: false, no_order: true },\n errors: [\"research_promotion_request_failed\"],\n };\n }\n renderPromotionConfirmControls();\n renderOverview();\n }\n\n async function submitResearchPromotionDecision(decision) {\n const ticket = selectedPromotionTicket();\n if (!ticket) {\n showToast(t(\"promotionTicketEmpty\"));\n return;\n }\n const application = selectedPromotionApplication();\n const selected = selectedPromotionApplicationAccount(application);\n const platform = selected?.platform || \"\";\n const executionMode = selected?.broker_environment || \"\";\n const riskSelect = el(\"promotion-risk-profile-select\");\n try {\n const confirmation = decision === \"accept\"\n ? buildPromotionConfirmation({\n targetPlatform: platform,\n executionMode,\n riskProfile: riskSelect?.value || ticket.suggested_risk_profile,\n paperSupported: executionMode !== \"paper\" || platform === \"longbridge\",\n suggestedRiskProfile: ticket.suggested_risk_profile,\n })\n : null;\n const payload = await requestJson(\"/api/research-promotion-decisions\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n ticket_id: ticket.ticket_id,\n decision,\n confirmation,\n ...(decision === \"accept\" ? { selected_account: { platform: selected?.platform || \"\", key: selected?.key || \"\" } } : {}),\n expected_proposed_params: ticket.proposed_params || {},\n expected_strategy_profile: ticket.strategy_profile,\n expected_domain: ticket.domain,\n }),\n });\n if (payload?.live_authority_granted) {\n throw new Error(\"server attempted to grant live authority\");\n }\n showToast(t(\"promotionDecisionSaved\"));\n await refreshResearchPromotionTickets();\n } catch (error) {\n showToast(`${t(\"promotionDecisionFailed\")}: ${error.message || error}`);\n }\n }\n\n el(\"promotion-ticket-select\")?.addEventListener(\"change\", (event) => {\n state.researchPromotion.selectedTicketId = String(event.target.value || \"\");\n state.researchPromotion.selectedApplicationTicketId = state.researchPromotion.selectedTicketId;\n state.researchPromotion.selectedApplicationPlatform = \"\";\n state.researchPromotion.selectedApplicationEnvironment = \"\";\n state.researchPromotion.selectedApplicationAccountKey = \"\";\n const riskSelect = el(\"promotion-risk-profile-select\");\n if (riskSelect) delete riskSelect.dataset.ticketId;\n renderPromotionConfirmControls();\n });\n el(\"promotion-target-platform-select\")?.addEventListener(\"change\", (event) => {\n state.researchPromotion.selectedApplicationPlatform = String(event.target.value || \"\");\n state.researchPromotion.selectedApplicationEnvironment = \"\";\n state.researchPromotion.selectedApplicationAccountKey = \"\";\n renderPromotionConfirmControls();\n });\n el(\"promotion-broker-environment-select\")?.addEventListener(\"change\", (event) => {\n state.researchPromotion.selectedApplicationEnvironment = String(event.target.value || \"\");\n state.researchPromotion.selectedApplicationAccountKey = \"\";\n renderPromotionConfirmControls();\n });\n el(\"promotion-selected-account-select\")?.addEventListener(\"change\", (event) => {\n state.researchPromotion.selectedApplicationAccountKey = String(event.target.value || \"\");\n renderPromotionConfirmControls();\n });\n el(\"promotion-risk-profile-select\")?.addEventListener(\"change\", () => {\n const riskSelect = el(\"promotion-risk-profile-select\");\n if (riskSelect) riskSelect.dataset.touched = \"1\";\n renderRiskEnvelopePanel();\n });\n el(\"promotion-application-open\")?.addEventListener(\"click\", openSelectedPromotionApplicationAccount);\n el(\"promotion-application-deploy\")?.addEventListener(\"click\", () => {\n submitV7PaperApplication();\n });\n el(\"promotion-accept-button\")?.addEventListener(\"click\", () => {\n submitResearchPromotionDecision(\"accept\");\n });\n el(\"promotion-reject-button\")?.addEventListener(\"click\", () => {\n submitResearchPromotionDecision(\"reject\");\n });\n\n function openSelectedPromotionApplicationAccount() {\n const application = selectedPromotionApplication();\n const account = selectedPromotionApplicationAccount(application);\n if (\n application?.application_preparation?.preflight_status !== \"ready\"\n || account?.preflight_status !== \"ready\"\n ) return;\n openAccountSettings(account.platform, account, true);\n }\n\n function normalizeExecutionMode(value, dryRunOnly) {\n const mode = String(value || \"\").trim().toLowerCase();\n if (mode === \"live\") return \"live\";\n if (mode === \"paper\" || mode === \"dry_run\" || mode === \"dry-run\") return \"dry_run\";\n if (dryRunOnly === true || dryRunOnly === \"true\" || dryRunOnly === \"1\" || dryRunOnly === 1) return \"dry_run\";\n if (dryRunOnly === false || dryRunOnly === \"false\" || dryRunOnly === \"0\" || dryRunOnly === 0) return \"live\";\n return \"\";\n }\n\n function cleanOptionalBoolean(value) {\n if (value === true || value === 1) return true;\n if (value === false || value === 0) return false;\n if (typeof value === \"string\") {\n const text = value.trim().toLowerCase();\n if (text === \"true\" || text === \"1\") return true;\n if (text === \"false\" || text === \"0\") return false;\n }\n return null;\n }\n\n function normalizeExecutionEnvironment(value) {\n const environment = String(value || \"\").trim().toLowerCase();\n return environment === \"live\" || environment === \"paper\" || environment === \"shadow\" ? environment : \"\";\n }\n\n function executionEnvironmentFromEntry(entry) {\n if (!entry || entry.source === \"account_defaults\") return \"\";\n const explicit = normalizeExecutionEnvironment(entry.execution_environment);\n if (explicit) return explicit;\n const rawMode = String(entry.execution_mode_raw || entry.execution_mode || \"\").trim().toLowerCase();\n if (rawMode === \"paper\") return cleanOptionalBoolean(entry.dry_run_only) === false ? \"paper\" : \"\";\n if (rawMode === \"live\") return \"live\";\n return \"\";\n }\n\n function configuredAccountEnvironment(account) {\n return normalizeExecutionEnvironment(account?.broker_environment || account?.execution_environment);\n }\n\n function executionEnvironmentForAccount(platform, account) {\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return \"\";\n const dryRunOnly = cleanOptionalBoolean(entry.dry_run_only);\n const rawMode = String(entry.execution_mode_raw || entry.execution_mode || \"\").trim().toLowerCase();\n if (dryRunOnly === true || rawMode === \"dry_run\" || rawMode === \"dry-run\") return \"dry_run\";\n if (rawMode === \"paper\" && dryRunOnly === null) return \"dry_run\";\n if (dryRunOnly === null) return \"\";\n const configured = configuredAccountEnvironment(account);\n if (configured === \"live\" || configured === \"paper\") return configured;\n const explicit = executionEnvironmentFromEntry(entry);\n if (explicit === \"live\" || explicit === \"paper\") return explicit;\n if (normalizeExecutionMode(entry?.execution_mode, entry?.dry_run_only) === \"live\") return \"live\";\n return \"\";\n }\n\n function executionModeForDispatch(entry) {\n if (!entry) return \"\";\n const dryRunOnly = cleanOptionalBoolean(entry?.dry_run_only);\n if (dryRunOnly === true) return \"dry_run\";\n const rawMode = String(entry?.execution_mode_raw || entry?.execution_mode || \"\").trim().toLowerCase();\n const environment = normalizeExecutionEnvironment(entry?.execution_environment);\n if (rawMode === \"dry_run\" || rawMode === \"dry-run\") return \"dry_run\";\n if (dryRunOnly === null) return rawMode === \"paper\" || environment === \"paper\" ? \"dry_run\" : \"\";\n if (rawMode === \"paper\" || environment === \"paper\") return \"live\";\n return normalizeExecutionMode(entry?.execution_mode, entry?.dry_run_only);\n }\n\n function defaultExecutionModeForAccount(platform, account) {\n if (platformDryRunOnly(platform)) return \"dry_run\";\n const entry = accountReadbackEntry(platform, account);\n return executionModeForDispatch(entry);\n }\n\n function defaultStrategyForAccount(platform, account) {\n const currentProfile = currentStrategyForAccount(platform, account);\n if (currentProfile) return currentProfile;\n return \"\";\n }\n\n function syncStrategyForAccount(platform) {\n const account = selectedAccount(platform);\n if (!account) return;\n const form = state.forms[platform];\n if (!form.strategyTouched) form.strategy = defaultStrategyForAccount(platform, account);\n if (!form.executionModeTouched) form.executionMode = defaultExecutionModeForAccount(platform, account);\n if (!form.pluginModeTouched) form.pluginMode = currentPluginModeForAccount(platform, account);\n syncRuntimeTargetForAccount(platform);\n syncReservePolicyForAccount(platform);\n syncIncomeLayerForAccount(platform);\n syncOptionOverlayForAccount(platform);\n syncCashOnlyExecutionForAccount(platform);\n reconcileExecutionCashPolicy(state.forms[platform], \"margin\");\n syncDcaForAccount(platform);\n }\n\n function syncRuntimeTargetForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.runtimeTargetTouched) return;\n form.runtimeTargetMode = \"current\";\n }\n\n function syncReservePolicyForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.reservedCashTouched) return;\n const entry = accountReadbackEntry(platform, selectedAccount(platform));\n if (!entry) {\n form.reservePolicyMode = \"current\";\n form.minReservedCashUsd = \"\";\n form.reservedCashRatio = \"\";\n return;\n }\n const policy = currentReservePolicyForAccount(platform, selectedAccount(platform));\n const hasFloor = Boolean(policy.minReservedCashUsd);\n const hasRatio = Boolean(policy.reservedCashRatio);\n if (hasFloor && hasRatio) form.reservePolicyMode = \"max\";\n else if (hasFloor) form.reservePolicyMode = \"floor\";\n else if (hasRatio) form.reservePolicyMode = \"ratio\";\n else form.reservePolicyMode = \"none\";\n form.minReservedCashUsd = policy.minReservedCashUsd;\n form.reservedCashRatio = policy.reservedCashRatio;\n }\n\n function syncIncomeLayerForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.incomeLayerTouched) return;\n const current = currentIncomeLayerForAccount(platform, selectedAccount(platform));\n const entry = accountReadbackEntry(platform, selectedAccount(platform));\n if (entry && incomeLayerFieldsConfigured(entry)) {\n form.incomeLayerMode = current.enabled === false ? \"disabled\" : \"enabled\";\n } else {\n form.incomeLayerMode = \"current\";\n form.incomeLayerStartUsd = \"\";\n form.incomeLayerMaxRatio = \"\";\n }\n if (entry && incomeLayerFieldsConfigured(entry)) {\n form.incomeLayerStartUsd = current.startUsd;\n form.incomeLayerMaxRatio = current.maxRatio;\n }\n }\n\n function syncOptionOverlayForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.optionOverlayTouched) return;\n const configured = normalizeOptionOverlayMode(selectedAccount(platform)?.option_overlay_mode);\n if (configured !== \"current\") {\n form.optionOverlayMode = configured;\n return;\n }\n const entry = accountReadbackEntry(platform, selectedAccount(platform));\n const rawValue = cleanOptionalBoolean(entry?.option_overlay_enabled);\n if (rawValue !== null) {\n form.optionOverlayMode = rawValue ? \"enabled\" : \"disabled\";\n return;\n }\n form.optionOverlayMode = \"current\";\n }\n\n function syncCashOnlyExecutionForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.cashOnlyExecutionTouched) return;\n const configured = normalizeCashOnlyExecutionMode(selectedAccount(platform)?.cash_only_execution_mode);\n if (configured !== \"current\") {\n form.cashOnlyExecutionMode = configured;\n return;\n }\n const entry = accountReadbackEntry(platform, selectedAccount(platform));\n const rawValue = cleanOptionalBoolean(entry?.cash_only_execution);\n if (rawValue !== null) {\n form.cashOnlyExecutionMode = rawValue ? \"enabled\" : \"disabled\";\n return;\n }\n form.cashOnlyExecutionMode = \"current\";\n }\n\n function syncDcaForAccount(platform) {\n const form = state.forms[platform];\n if (!form || form.dcaTouched) return;\n const current = currentDcaForAccount(platform, selectedAccount(platform), form.strategy);\n form.dcaMode = current.supported && current.mode ? current.mode : \"fixed\";\n form.dcaBaseInvestmentUsd = current.supported ? current.baseInvestmentUsd : \"\";\n }\n\n function ensureAccountSelection(platform) {\n const options = optionsFor(platform);\n if (!options.length) return;\n if (!options.some((option) => option.key === state.forms[platform].accountKey)) {\n state.forms[platform].accountKey = options[0].key;\n state.forms[platform].runtimeTargetTouched = false;\n state.forms[platform].reservedCashTouched = false;\n state.forms[platform].incomeLayerTouched = false;\n state.forms[platform].optionOverlayTouched = false;\n state.forms[platform].cashOnlyExecutionTouched = false;\n state.forms[platform].dcaTouched = false;\n state.forms[platform].executionModeTouched = false;\n state.forms[platform].pluginModeTouched = false;\n state.forms[platform].strategy = defaultStrategyForAccount(platform, options[0]);\n state.forms[platform].pluginMode = currentPluginModeForAccount(platform, options[0]);\n syncRuntimeTargetForAccount(platform);\n syncReservePolicyForAccount(platform);\n syncIncomeLayerForAccount(platform);\n syncOptionOverlayForAccount(platform);\n syncCashOnlyExecutionForAccount(platform);\n syncDcaForAccount(platform);\n }\n }\n\n function derivedService(platform, targetName) {\n if (platform === \"longbridge\") return `longbridge-quant-${targetName.toLowerCase()}-service`;\n if (platform === \"ibkr\") return `interactive-brokers-${targetName.toLowerCase()}-service`;\n if (platform === \"schwab\") return \"charles-schwab-quant-service\";\n if (platformConfig[platform]?.service_name) return platformConfig[platform].service_name;\n if (platform === \"qmt\") return \"qmt-quant-service\";\n return \"\";\n }\n\n function accountMetaText() {\n return \"\";\n }\n\n function hasRunnableStrategySelection(platform = state.selected) {\n const form = state.forms[platform];\n const account = selectedAccount(platform);\n return Boolean(form?.strategy && account && strategyAllowedForAccount(platform, account, form.strategy, form.executionMode));\n }\n\n function hasValidReservePolicy(platform = state.selected) {\n if (!platformSupportsReservedCashPolicy(platform)) return true;\n const form = state.forms[platform];\n const mode = normalizeReservePolicyMode(form?.reservePolicyMode);\n if (mode === \"current\" || mode === \"none\") return true;\n return Boolean(reservePolicyOverrideForForm(form, platform));\n }\n\n function hasValidExecutionCashPolicy(platform = state.selected) {\n if (!platformSupportsMarginPolicy(platform) && !platformSupportsReservedCashPolicy(platform)) return true;\n const form = state.forms[platform];\n return !executionCashPolicyConflict(form) && hasValidReservePolicy(platform);\n }\n\n function hasValidIncomeLayerPolicy(platform = state.selected) {\n const form = state.forms[platform];\n if (!incomeLayerSupported(form?.strategy)) return true;\n const mode = normalizeIncomeLayerMode(form?.incomeLayerMode);\n if (mode === \"current\" || mode === \"disabled\") return true;\n const defaults = incomeLayerDefaultForStrategy(form?.strategy);\n const startUsd = cleanDisplayNumber(form?.incomeLayerStartUsd || defaults?.startUsd);\n const maxRatio = cleanDisplayRatio(form?.incomeLayerMaxRatio || defaults?.maxRatio);\n return Boolean(startUsd && maxRatio);\n }\n\n function hasValidOptionOverlayPolicy(platform = state.selected) {\n const form = state.forms[platform];\n const mode = normalizeOptionOverlayMode(form?.optionOverlayMode);\n return mode !== \"enabled\" || optionOverlaySupported(form?.strategy);\n }\n\n function hasValidDcaPolicy(platform = state.selected) {\n const form = state.forms[platform];\n if (!dcaSupported(form?.strategy) || !platformSupportsDca(platform)) return true;\n return Boolean(dcaModes.includes(normalizeDcaMode(form?.dcaMode)) && cleanDisplayPositiveNumber(form?.dcaBaseInvestmentUsd));\n }\n\n function hasValidStrategySelection(platform = state.selected) {\n return hasRunnableStrategySelection(platform) &&\n hasValidExecutionCashPolicy(platform) &&\n hasValidIncomeLayerPolicy(platform) &&\n hasValidOptionOverlayPolicy(platform) &&\n hasValidDcaPolicy(platform);\n }\n\n function normalizeReservePolicyMode(value) {\n return reservePolicyModes.includes(value) ? value : \"current\";\n }\n\n function reservePolicyOverrideForForm(form, platform = state.selected) {\n if (!platformSupportsReservedCashPolicy(platform)) return null;\n const mode = normalizeReservePolicyMode(form?.reservePolicyMode);\n const floor = cleanDisplayNumber(form?.minReservedCashUsd);\n const ratio = cleanDisplayRatio(form?.reservedCashRatio);\n const extraVariables = {};\n if (mode === \"current\") return null;\n if (mode === \"none\") {\n extraVariables[platformMinReservedCashVariables[platform]] = \"\";\n extraVariables[platformReservedCashRatioVariables[platform]] = \"\";\n return { inputs: {}, extraVariables };\n }\n if (mode === \"ratio\") {\n if (!ratio) return null;\n extraVariables[platformMinReservedCashVariables[platform]] = \"\";\n return { inputs: { reserved_cash_ratio: ratio }, extraVariables };\n }\n if (mode === \"floor\") {\n if (!floor) return null;\n extraVariables[platformReservedCashRatioVariables[platform]] = \"\";\n return { inputs: { min_reserved_cash_usd: floor }, extraVariables };\n }\n if (mode === \"max\") {\n if (!floor || !ratio) return null;\n return { inputs: { min_reserved_cash_usd: floor, reserved_cash_ratio: ratio }, extraVariables };\n }\n return null;\n }\n\n function runtimeTargetOverrideForForm(form) {\n const mode = normalizeRuntimeTargetMode(form?.runtimeTargetMode);\n if (mode === \"current\") return null;\n return {\n inputs: { runtime_target_enabled_mode: mode },\n extraVariables: { [runtimeTargetEnabledVariable]: mode === \"enabled\" ? \"true\" : \"false\" },\n };\n }\n\n function incomeLayerOverrideForForm(form) {\n const defaults = incomeLayerDefaultForStrategy(form?.strategy);\n if (!defaults) return null;\n const mode = normalizeIncomeLayerMode(form?.incomeLayerMode);\n if (mode === \"current\") return null;\n const extraVariables = {};\n if (mode === \"disabled\") {\n extraVariables[incomeLayerEnabledVariable] = \"false\";\n extraVariables[incomeLayerStartUsdVariable] = \"\";\n extraVariables[incomeLayerMaxRatioVariable] = \"\";\n return { inputs: { income_layer_mode: mode }, extraVariables };\n }\n const startUsd = cleanDisplayNumber(form?.incomeLayerStartUsd || defaults.startUsd);\n const maxRatio = cleanDisplayRatio(form?.incomeLayerMaxRatio || defaults.maxRatio);\n if (!startUsd || !maxRatio) return null;\n extraVariables[incomeLayerEnabledVariable] = \"true\";\n extraVariables[incomeLayerStartUsdVariable] = startUsd;\n extraVariables[incomeLayerMaxRatioVariable] = maxRatio;\n return { inputs: { income_layer_mode: mode, income_layer_start_usd: startUsd, income_layer_max_ratio: maxRatio }, extraVariables };\n }\n\n function optionOverlayOverrideForForm(form) {\n const mode = normalizeOptionOverlayMode(form?.optionOverlayMode);\n if (mode === \"current\") return null;\n if (mode === \"enabled\" && !optionOverlaySupported(form?.strategy)) return null;\n return { inputs: { option_overlay_mode: mode } };\n }\n\n function cashOnlyExecutionOverrideForForm(form, platform = state.selected) {\n if (!platformSupportsMarginPolicy(platform)) return null;\n const mode = normalizeCashOnlyExecutionMode(form?.cashOnlyExecutionMode);\n if (mode === \"current\") return null;\n return { inputs: { cash_only_execution_mode: mode } };\n }\n\n function dcaOverrideForForm(form) {\n if (!form?.dcaTouched || !dcaSupported(form?.strategy) || !platformSupportsDca(state.selected)) return null;\n const mode = normalizeDcaMode(form?.dcaMode);\n const baseInvestmentUsd = cleanDisplayPositiveNumber(form?.dcaBaseInvestmentUsd);\n if (!baseInvestmentUsd) return null;\n return { inputs: { dca_mode: mode, dca_base_investment_usd: baseInvestmentUsd } };\n }\n\n function mergeExtraVariables(inputs, extraVariables) {\n if (!extraVariables || !Object.keys(extraVariables).length) return;\n const merged = inputs.extra_variables_json ? JSON.parse(inputs.extra_variables_json) : {};\n Object.assign(merged, extraVariables);\n inputs.extra_variables_json = JSON.stringify(merged);\n }\n\n function buildInputs(platform = state.selected) {\n const form = state.forms[platform];\n const account = selectedAccount(platform);\n const targetName = account.target_name || account.key;\n const inputs = {\n platform,\n target_name: targetName,\n strategy_profile: form.strategy,\n execution_mode: form.executionMode,\n variable_scope: account.variable_scope || \"default\",\n plugin_mode: form.pluginModeTouched ? normalizePluginMode(form.pluginMode) : \"current\",\n service_targets_mode: \"auto\",\n apply: \"true\",\n trigger_platform_sync: \"true\",\n confirm_apply: \"APPLY_AND_SYNC\",\n platform_sync_workflow: \"sync-cloud-run-env.yml\",\n };\n for (const field of [\n \"github_environment\",\n \"deployment_selector\",\n \"account_selector\",\n \"account_scope\",\n \"service_name\",\n ]) {\n if (account[field]) inputs[field] = account[field];\n }\n const reserveTouched = Boolean(form.reservedCashTouched);\n const reserveOverride = reserveTouched && platformSupportsReservedCashPolicy(platform)\n ? reservePolicyOverrideForForm(form, platform)\n : null;\n if (platformSupportsReservedCashPolicy(platform)) {\n inputs.reserved_cash_policy_mode = reserveTouched ? normalizeReservePolicyMode(form.reservePolicyMode) : \"current\";\n if (reserveTouched && reserveOverride) {\n Object.assign(inputs, reserveOverride.inputs);\n mergeExtraVariables(inputs, reserveOverride.extraVariables);\n }\n }\n const runtimeTargetOverride = runtimeTargetOverrideForForm(form);\n inputs.runtime_target_enabled_mode = normalizeRuntimeTargetMode(form.runtimeTargetMode);\n if (runtimeTargetOverride) {\n Object.assign(inputs, runtimeTargetOverride.inputs);\n mergeExtraVariables(inputs, runtimeTargetOverride.extraVariables);\n }\n const incomeTouched = Boolean(form.incomeLayerTouched);\n const incomeOverride = incomeTouched ? incomeLayerOverrideForForm(form) : null;\n inputs.income_layer_mode = incomeTouched ? normalizeIncomeLayerMode(form.incomeLayerMode) : \"current\";\n if (incomeTouched && incomeOverride) {\n Object.assign(inputs, incomeOverride.inputs);\n mergeExtraVariables(inputs, incomeOverride.extraVariables);\n }\n const optionOverlayTouched = Boolean(form.optionOverlayTouched);\n const optionOverlayOverride = optionOverlayTouched ? optionOverlayOverrideForForm(form) : null;\n inputs.option_overlay_mode = optionOverlayTouched ? normalizeOptionOverlayMode(form.optionOverlayMode) : \"current\";\n if (optionOverlayTouched && optionOverlayOverride) {\n Object.assign(inputs, optionOverlayOverride.inputs);\n }\n const cashOnlyTouched = Boolean(form.cashOnlyExecutionTouched);\n const cashOnlyOverride = cashOnlyTouched ? cashOnlyExecutionOverrideForForm(form, platform) : null;\n if (platformSupportsMarginPolicy(platform)) {\n inputs.cash_only_execution_mode = cashOnlyTouched ? normalizeCashOnlyExecutionMode(form.cashOnlyExecutionMode) : \"current\";\n if (cashOnlyTouched && cashOnlyOverride) {\n Object.assign(inputs, cashOnlyOverride.inputs);\n }\n }\n const dcaOverride = dcaOverrideForForm(form);\n if (dcaOverride) {\n Object.assign(inputs, dcaOverride.inputs);\n }\n return inputs;\n }\n\n function reservedCashPolicyText(inputs, platform = state.selected, account = selectedAccount(platform), fallback = t(\"unchanged\")) {\n if (inputs?.reserved_cash_policy_mode === \"none\") return t(\"reservedCashNone\");\n const floor = cleanDisplayNumber(inputs?.min_reserved_cash_usd);\n const ratio = cleanDisplayRatio(inputs?.reserved_cash_ratio);\n const currency = selectedCashCurrency(platform, account);\n const hasEffectiveFloor = Boolean(floor && !(ratio && Number(floor) === 0));\n if (!hasEffectiveFloor && !ratio) return fallback;\n if (hasEffectiveFloor && ratio) return `max(${floor} ${currency}, ${formatRatioPercent(ratio)})`;\n if (hasEffectiveFloor) return `${floor} ${currency}`;\n return formatRatioPercent(ratio);\n }\n\n function platformReservedCashDefaultText(platform = state.selected, account = selectedAccount(platform)) {\n return t(\"reservedCashDefault\").replace(\"{currency}\", selectedCashCurrency(platform, account));\n }\n\n function currentReservedCashPolicyText(platform = state.selected, account = selectedAccount(platform)) {\n const entry = currentEntryForAccount(platform, account);\n const policy = currentReservePolicyForAccount(platform, account);\n return reservedCashPolicyText(\n {\n min_reserved_cash_usd: policy.minReservedCashUsd,\n reserved_cash_ratio: policy.reservedCashRatio,\n },\n platform,\n account,\n entry ? platformReservedCashDefaultText(platform, account) : t(\"notRead\"),\n );\n }\n\n function pendingReservedCashPolicyText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n return reservedCashPolicyText(pendingReservePolicy(inputs, platform, account).inputs, platform, account, t(\"unchanged\"));\n }\n\n function pendingReservePolicy(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const mode = normalizeReservePolicyMode(inputs.reserved_cash_policy_mode);\n if (mode === \"current\") return { changed: false, inputs: {} };\n const current = currentReservePolicyForAccount(platform, account);\n const currentFloor = cleanDisplayNumber(current.minReservedCashUsd);\n const currentRatio = cleanDisplayRatio(current.reservedCashRatio);\n const next = {\n min_reserved_cash_usd: cleanDisplayNumber(inputs.min_reserved_cash_usd),\n reserved_cash_ratio: cleanDisplayRatio(inputs.reserved_cash_ratio),\n };\n if (mode === \"none\") {\n next.reserved_cash_policy_mode = \"none\";\n }\n const entry = currentEntryForAccount(platform, account);\n const changed = Boolean(entry && (\n next.min_reserved_cash_usd !== currentFloor ||\n next.reserved_cash_ratio !== currentRatio ||\n (mode === \"none\" && (currentFloor || currentRatio))\n ));\n return { changed, inputs: next };\n }\n\n function currentIncomeLayerText(platform = state.selected, account = selectedAccount(platform), profile = state.forms[platform]?.strategy) {\n const defaults = incomeLayerDefaultForStrategy(profile);\n if (!defaults) return t(\"incomeLayerNotSupported\");\n const entry = accountReadbackEntry(platform, account);\n if (!entry) return t(\"notRead\");\n const current = incomeLayerFromEntry(entry);\n if (!incomeLayerFieldsConfigured(entry)) {\n return t(\"strategyDefault\");\n }\n const enabled = current.enabled ?? true;\n const startUsd = current.startUsd || String(defaults.startUsd);\n const ratio = current.maxRatio || defaults.maxRatio;\n return enabled\n ? t(\"incomeLayerOn\")\n .replace(\"{start}\", formatUsd(startUsd))\n .replace(\"{ratio}\", formatRatioPercent(ratio))\n : t(\"incomeLayerOff\");\n }\n\n function pendingIncomeLayerText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingIncomeLayer(inputs, platform, account);\n if (!pending.supported) return t(\"incomeLayerNotSupported\");\n if (!pending.changed) return t(\"unchanged\");\n if (pending.inputs.income_layer_enabled === false) return t(\"incomeLayerOff\");\n return t(\"incomeLayerOn\")\n .replace(\"{start}\", formatUsd(pending.inputs.income_layer_start_usd))\n .replace(\"{ratio}\", formatRatioPercent(pending.inputs.income_layer_max_ratio));\n }\n\n function pendingOptionOverlayText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingOptionOverlay(inputs, platform, account);\n if (!pending.supported && pending.inputs.option_overlay_enabled !== false) return t(\"optionOverlayNotSupported\");\n if (!pending.changed) return t(\"unchanged\");\n return optionOverlayText(pending.inputs.option_overlay_enabled);\n }\n\n function pendingCashOnlyExecutionText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingCashOnlyExecution(inputs, platform, account);\n if (!pending.changed) return t(\"unchanged\");\n return cashOnlyExecutionText(pending.inputs.cash_only_execution);\n }\n\n function pendingRuntimeTargetText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingRuntimeTarget(inputs, platform, account);\n if (!pending.changed) return t(\"unchanged\");\n return runtimeTargetText(pending.inputs.runtime_target_enabled);\n }\n\n function pendingRuntimeTargetTone(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingRuntimeTarget(inputs, platform, account);\n if (!pending.changed) return \"neutral\";\n return runtimeTargetTone(pending.inputs.runtime_target_enabled);\n }\n\n function currentDcaText(platform = state.selected, account = selectedAccount(platform), profile = state.forms[platform]?.strategy) {\n const current = currentDcaForAccount(platform, account, profile);\n if (!current.supported) return t(\"dcaNotSupported\");\n return t(\"dcaText\")\n .replace(\"{mode}\", dcaModeLabel(current.mode))\n .replace(\"{amount}\", formatUsd(current.baseInvestmentUsd));\n }\n\n function pendingDcaText(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const pending = pendingDca(inputs, platform, account);\n if (!pending.supported) return t(\"dcaNotSupported\");\n if (!pending.changed) return t(\"unchanged\");\n return t(\"dcaText\")\n .replace(\"{mode}\", dcaModeLabel(pending.inputs.dca_mode))\n .replace(\"{amount}\", formatUsd(pending.inputs.dca_base_investment_usd));\n }\n\n function pendingRuntimeTarget(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const mode = normalizeRuntimeTargetMode(inputs.runtime_target_enabled_mode);\n if (mode === \"current\") {\n return {\n changed: false,\n inputs: { runtime_target_enabled: runtimeTargetEnabledForAccount(platform, account) },\n };\n }\n const current = runtimeTargetEnabledForAccount(platform, account);\n const currentEnabled = current;\n const nextEnabled = mode === \"enabled\";\n const entry = accountReadbackEntry(platform, account);\n return {\n changed: Boolean(entry && currentEnabled !== nextEnabled),\n inputs: { runtime_target_enabled: nextEnabled },\n };\n }\n\n function pendingIncomeLayer(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const profile = cleanStrategyProfile(inputs.strategy_profile || state.forms[platform]?.strategy);\n const defaults = incomeLayerDefaultForStrategy(profile);\n if (!defaults) return { supported: false, changed: false, inputs: {} };\n const mode = normalizeIncomeLayerMode(inputs.income_layer_mode);\n const entry = accountReadbackEntry(platform, account);\n const rawCurrent = currentIncomeLayerForAccount(platform, account);\n const effective = effectiveIncomeLayerForAccount(platform, account, profile);\n const currentEnabled = effective?.enabled ?? true;\n const currentStartUsd = effective?.startUsd ?? String(defaults.startUsd);\n const currentRatio = effective?.maxRatio ?? defaults.maxRatio;\n if (mode === \"current\") {\n return {\n supported: true,\n changed: false,\n inputs: {\n income_layer_enabled: rawCurrent.enabled,\n income_layer_start_usd: rawCurrent.startUsd,\n income_layer_max_ratio: rawCurrent.maxRatio,\n },\n };\n }\n if (mode === \"disabled\") {\n if (!entry) {\n return {\n supported: true,\n changed: false,\n inputs: {\n income_layer_enabled: false,\n income_layer_start_usd: \"\",\n income_layer_max_ratio: \"\",\n },\n };\n }\n return {\n supported: true,\n changed: currentEnabled !== false || Boolean(rawCurrent.startUsd || rawCurrent.maxRatio),\n inputs: {\n income_layer_enabled: false,\n income_layer_start_usd: \"\",\n income_layer_max_ratio: \"\",\n },\n };\n }\n const nextStartUsd = cleanDisplayNumber(inputs.income_layer_start_usd || defaults.startUsd);\n const nextRatio = cleanDisplayRatio(inputs.income_layer_max_ratio || defaults.maxRatio);\n return {\n supported: true,\n changed: Boolean(entry && (currentEnabled !== true || nextStartUsd !== currentStartUsd || nextRatio !== currentRatio)),\n inputs: {\n income_layer_enabled: true,\n income_layer_start_usd: nextStartUsd,\n income_layer_max_ratio: nextRatio,\n },\n };\n }\n\n function pendingOptionOverlay(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const profile = cleanStrategyProfile(inputs.strategy_profile || state.forms[platform]?.strategy);\n const supported = optionOverlaySupported(profile);\n const mode = normalizeOptionOverlayMode(inputs.option_overlay_mode);\n const current = effectiveOptionOverlayForAccount(platform, account, profile);\n if (mode === \"current\") {\n return {\n supported,\n changed: false,\n inputs: { option_overlay_enabled: currentOptionOverlayForAccount(platform, account) },\n };\n }\n if (mode === \"enabled\") {\n return {\n supported,\n changed: supported && current !== null && current !== true,\n inputs: { option_overlay_enabled: true },\n };\n }\n return {\n supported,\n changed: current === true,\n inputs: { option_overlay_enabled: false },\n };\n }\n\n function pendingCashOnlyExecution(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const mode = normalizeCashOnlyExecutionMode(inputs.cash_only_execution_mode);\n if (!platformSupportsMarginPolicy(platform) || mode === \"current\") {\n return { changed: false, inputs: {} };\n }\n const current = effectiveCashOnlyExecutionForAccount(platform, account);\n const nextEnabled = mode === \"enabled\";\n const entry = accountReadbackEntry(platform, account);\n return {\n changed: Boolean(entry && current !== null && current !== nextEnabled),\n inputs: { cash_only_execution: nextEnabled },\n };\n }\n\n function pendingDca(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const profile = cleanStrategyProfile(inputs.strategy_profile || state.forms[platform]?.strategy);\n const defaults = dcaConfigForStrategy(profile);\n if (!defaults) return { supported: false, changed: false, inputs: {} };\n const current = currentDcaForAccount(platform, account, profile);\n const nextMode = normalizeDcaMode(inputs.dca_mode || defaults.defaultMode);\n const nextBase = cleanDisplayPositiveNumber(inputs.dca_base_investment_usd || defaults.defaultBaseInvestmentUsd);\n return {\n supported: true,\n changed: Boolean(current.mode !== nextMode || current.baseInvestmentUsd !== nextBase),\n inputs: {\n dca_mode: nextMode,\n dca_base_investment_usd: nextBase,\n },\n };\n }\n\n function pendingChangeState(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const currentProfile = currentStrategyForAccount(platform, account);\n const nextProfile = cleanStrategyProfile(inputs.strategy_profile);\n const currentEntry = currentEntryForAccount(platform, account);\n const currentMode = executionModeForDispatch(currentEntry);\n const currentPluginMode = currentPluginModeForAccount(platform, account);\n const nextPluginMode = normalizePluginMode(inputs.plugin_mode);\n const runtimeTarget = pendingRuntimeTarget(inputs, platform, account);\n const reserve = pendingReservePolicy(inputs, platform, account);\n const income = pendingIncomeLayer(inputs, platform, account);\n const optionOverlay = pendingOptionOverlay(inputs, platform, account);\n const cashOnly = pendingCashOnlyExecution(inputs, platform, account);\n const dca = pendingDca(inputs, platform, account);\n return {\n currentProfile,\n nextProfile,\n currentMode,\n currentPluginMode,\n nextPluginMode,\n strategyChanged: Boolean(nextProfile && ((state.forms[platform]?.strategyTouched) || (currentProfile && currentProfile !== nextProfile))),\n modeChanged: Boolean(inputs.execution_mode && currentMode && currentMode !== inputs.execution_mode),\n pluginModeChanged: Boolean(state.forms[platform]?.pluginModeTouched && nextPluginMode && currentPluginMode !== nextPluginMode),\n runtimeTargetChanged: runtimeTarget.changed,\n reserveCashChanged: reserve.changed,\n incomeLayerChanged: income.changed,\n optionOverlayChanged: optionOverlay.changed,\n cashOnlyChanged: cashOnly.changed,\n dcaChanged: dca.changed,\n runtimeTarget,\n reserve,\n income,\n optionOverlay,\n cashOnly,\n dca,\n };\n }\n\n function hasPendingChanges(inputs, platform = state.selected, account = selectedAccount(platform)) {\n const changes = pendingChangeState(inputs, platform, account);\n return Boolean(\n changes.strategyChanged ||\n changes.modeChanged ||\n changes.pluginModeChanged ||\n changes.runtimeTargetChanged ||\n changes.reserveCashChanged ||\n changes.incomeLayerChanged ||\n changes.optionOverlayChanged ||\n changes.cashOnlyChanged ||\n changes.dcaChanged\n );\n }\n\n function formatRatioPercent(value) {\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) return String(value);\n return `${(numeric * 100).toFixed(2).replace(/\\.?0+$/, \"\")}%`;\n }\n\n function formatUsd(value) {\n const numeric = Number(value);\n if (!Number.isFinite(numeric)) return String(value);\n return `$${numeric.toLocaleString(\"en-US\", { maximumFractionDigits: 0 })}`;\n }\n\n function incomeLayerAllocationText(defaults) {\n if (!defaults?.allocations) return \"\";\n return Object.entries(defaults.allocations)\n .map(([symbol, ratio]) => `${symbol} ${formatRatioPercent(ratio)}`)\n .join(\" / \");\n }\n\n function incomeLayerDefaultMetaText(defaults) {\n if (!defaults) return t(\"incomeLayerModeMeta\");\n return t(\"incomeLayerDefaultMeta\")\n .replace(\"{start}\", formatUsd(defaults.startUsd))\n .replace(\"{ratio}\", formatRatioPercent(defaults.maxRatio));\n }\n\n function optionOverlayDefaultMetaText(defaults) {\n if (!defaults?.families?.length) return t(\"optionOverlayModeMeta\");\n const familyText = defaults.families.map((item) => {\n const family = item.family === \"income\" ? t(\"optionOverlayFamilyIncome\") : t(\"optionOverlayFamilyGrowth\");\n const ratioText = item.ratioKind === \"risk\"\n ? t(\"optionOverlayRiskRatio\").replace(\"{ratio}\", formatRatioPercent(item.ratio))\n : t(\"optionOverlayBudgetRatio\").replace(\"{ratio}\", formatRatioPercent(item.ratio));\n return `${family}: ${item.recipe}, ${formatUsd(item.startUsd)}, ${ratioText}`;\n }).join(\" / \");\n return t(\"optionOverlayDefaultMeta\").replace(\"{defaults}\", familyText);\n }\n\n function summaryRows(inputs) {\n const account = selectedAccount();\n const changes = pendingChangeState(inputs, state.selected, account);\n const currentStrategyText = changes.currentProfile ? strategyLabel(changes.currentProfile) : t(\"notRead\");\n const rows = [\n [t(\"repository\"), state.repositories[state.selected] || defaultRepositories[state.selected]],\n [t(\"selectedAccount\"), accountDisplayLabel(account)],\n [t(\"currentStrategy\"), currentStrategyText],\n [t(\"selectedMarket\"), supportedDomainLabel(state.selected, account)],\n [\n t(\"currentRuntimeTarget\"),\n currentRuntimeTargetText(state.selected, account),\n \"\",\n currentRuntimeTargetTone(state.selected, account),\n ],\n [t(\"currentPluginMode\"), pluginModeLabel(changes.currentPluginMode)],\n [t(\"reservedCashPolicy\"), currentReservedCashPolicyText(state.selected, account)],\n ];\n if (platformSupportsMarginPolicy(state.selected)) {\n rows.push([t(\"currentCashOnlyExecution\"), currentCashOnlyExecutionText(state.selected, account)]);\n }\n if (incomeLayerSupported(inputs.strategy_profile)) {\n rows.push([t(\"currentIncomeLayer\"), currentIncomeLayerText(state.selected, account, inputs.strategy_profile)]);\n }\n if (optionOverlaySupported(inputs.strategy_profile) || changes.optionOverlayChanged) {\n rows.push([t(\"currentOptionOverlay\"), currentOptionOverlayText(state.selected, account, inputs.strategy_profile)]);\n }\n if (dcaSupported(inputs.strategy_profile)) {\n rows.push([t(\"currentDca\"), currentDcaText(state.selected, account, inputs.strategy_profile)]);\n }\n if (changes.reserveCashChanged) {\n rows.push([t(\"pendingReservedCashPolicy\"), pendingReservedCashPolicyText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.incomeLayerChanged) {\n rows.push([t(\"pendingIncomeLayer\"), pendingIncomeLayerText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.optionOverlayChanged) {\n rows.push([t(\"pendingOptionOverlay\"), pendingOptionOverlayText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.cashOnlyChanged) {\n rows.push([t(\"pendingCashOnlyExecution\"), pendingCashOnlyExecutionText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.dcaChanged) {\n rows.push([t(\"pendingDca\"), pendingDcaText(inputs, state.selected, account), \"pending\"]);\n }\n if (changes.modeChanged) {\n rows.push([t(\"pendingMode\"), modeLabel(inputs.execution_mode), \"pending\"]);\n }\n if (changes.pluginModeChanged) {\n rows.push([t(\"pendingPluginMode\"), pluginModeLabel(changes.nextPluginMode), \"pending\"]);\n }\n if (changes.runtimeTargetChanged) {\n rows.push([\n t(\"pendingRuntimeTarget\"),\n pendingRuntimeTargetText(inputs, state.selected, account),\n \"pending\",\n pendingRuntimeTargetTone(inputs, state.selected, account),\n ]);\n }\n if (changes.strategyChanged && changes.nextProfile) {\n rows.push([t(\"nextStrategy\"), strategyLabel(changes.nextProfile), \"pending\"]);\n }\n return rows;\n }\n\n function applyLanguage() {\n document.documentElement.lang = state.lang === \"zh\" ? \"zh-CN\" : \"en\";\n document.querySelectorAll(\"[data-i18n]\").forEach((node) => {\n node.textContent = t(node.dataset.i18n);\n });\n document.querySelectorAll(\"[data-i18n-aria-label]\").forEach((node) => {\n node.setAttribute(\"aria-label\", t(node.dataset.i18nAriaLabel));\n });\n document.querySelectorAll(\"[data-i18n-placeholder]\").forEach((node) => {\n node.placeholder = t(node.dataset.i18nPlaceholder);\n });\n el(\"lang-button\").textContent = state.lang === \"zh\" ? \"EN\" : \"中\";\n }\n\n function renderPlatforms() {\n const strip = el(\"platform-strip\");\n strip.replaceChildren();\n const showPrivateConfig = hasPrivateConfig();\n const visiblePlatforms = Object.keys(platformMeta).filter((platform) => platformMeta[platform].console_visible !== false);\n if (!visiblePlatforms.includes(state.selected) && visiblePlatforms.length) state.selected = visiblePlatforms[0];\n el(\"switch-view\").hidden = !visiblePlatforms.length;\n for (const platform of visiblePlatforms) {\n ensureAccountSelection(platform);\n const meta = platformMeta[platform];\n const form = state.forms[platform];\n const account = selectedAccount(platform);\n const button = document.createElement(\"button\");\n button.className = \"platform-button\";\n button.type = \"button\";\n button.dataset.platform = platform;\n button.classList.toggle(\"active\", platform === state.selected);\n button.setAttribute(\"aria-pressed\", String(platform === state.selected));\n const mark = document.createElement(\"span\");\n mark.className = \"mark\";\n mark.textContent = meta.code;\n const copyNode = document.createElement(\"span\");\n copyNode.className = \"platform-copy\";\n const labelNode = document.createElement(\"strong\");\n labelNode.textContent = meta.label;\n copyNode.append(labelNode);\n if (showPrivateConfig) {\n const accountNode = document.createElement(\"span\");\n accountNode.textContent = accountDisplayLabel(account);\n const strategyNode = document.createElement(\"small\");\n strategyNode.textContent = strategyLabel(form.strategy);\n copyNode.append(accountNode, strategyNode);\n }\n button.append(mark, copyNode);\n strip.appendChild(button);\n }\n }\n\n function accountMonitoringRecord(platform, account) {\n if (!state.auth.allowed || !account?.runtime_status_target_id) return null;\n const id = account.runtime_status_target_id;\n if (optionsFor(platform).filter(item => item.runtime_status_target_id === id).length !== 1) return null;\n const matches = state.runtimeTargetLifecycle.payload.targets.filter(entry =>\n entry.target?.target?.platform === platform && entry.target?.target_id === id);\n return matches.length === 1 ? matches[0] : null;\n }\n\n function accountMonitoringText(platform, account) {\n const record = accountMonitoringRecord(platform, account);\n if (!record) return t(account?.runtime_status_target_id ? \"runtimeUnverified\" : \"monitoringUnlinked\");\n if (record.freshness?.data_status !== \"ready\") return t(\"controlDataStale\");\n const configured = runtimeTargetStateForAccount(platform, account);\n const recorded = record.target?.target?.configured_state;\n if (configured.known && [\"enabled\", \"disabled\"].includes(recorded)\n && configured.enabled !== (recorded === \"enabled\")) return t(\"monitoringConfigMismatch\");\n return runtimeTargetLifecycleObservationLabel(record.execution_observation?.code);\n }\n\n function accountDiagnosisKey(platform, account) {\n return `${platform}:${account?.key || \"\"}`;\n }\n\n function accountDiagnosisEligible(platform, account) {\n const targetId = String(account?.runtime_status_target_id || \"\");\n return state.auth.allowed\n && ((platform === \"binance\" && targetId === \"binance.crypto_live_pool_rotation\")\n || (platform === \"longbridge\" && [\"longbridge.paper\", \"longbridge.hk\", \"longbridge.sg\"].includes(targetId)));\n }\n\n function accountDiagnosisTask(platform, account) {\n return state.accountDiagnosis.tasks[accountDiagnosisKey(platform, account)] || null;\n }\n\n function accountDiagnosisStatusAvailable(platform, account) {\n const record = accountMonitoringRecord(platform, account);\n return [\"ready\", \"stale\"].includes(record?.freshness?.data_status);\n }\n\n function accountDiagnosisStatusText(task) {\n if (!task) return \"\";\n if (task.status === \"queued\" && task.dispatch_state === \"unknown\") return t(\"accountDiagnosisDispatchUnknown\");\n if (task.status === \"queued\") return t(\"accountDiagnosisQueued\");\n if (task.status === \"running\") return t(\"accountDiagnosisRunning\");\n if (task.status === \"succeeded\" && task.recheck_status === \"sent\") return t(\"accountDiagnosisRechecking\");\n if (task.status === \"succeeded\" && task.recheck_status === \"attention\") {\n const reason = task.summary || t(\"accountDiagnosisUnavailable\");\n return t(\"accountDiagnosisNeedsReview\").replace(\"{summary}\", reason);\n }\n if (task.status === \"succeeded\" && task.recheck_status === \"passed\") return t(\"accountDiagnosisSuccess\");\n if (task.status === \"succeeded\" && task.recheck_status === \"unavailable\") return t(\"accountDiagnosisRecheckUnavailable\");\n if (task.status === \"succeeded\") return t(\"accountDiagnosisRecheckUnknown\");\n if (task.status === \"failed\" || task.status === \"unknown\") {\n const reason = task.summary || task.reason_code || t(\"accountDiagnosisUnavailable\");\n return t(\"accountDiagnosisFailed\").replace(\"{reason}\", reason);\n }\n return \"\";\n }\n\n function accountDiagnosisTrigger(platform, account) {\n const record = accountMonitoringRecord(platform, account);\n const deployment = record?.target?.deployment;\n const monitoring = record?.target?.monitoring || {};\n const configuredState = record?.target?.target?.configured_state;\n const confirmedAttention = record?.freshness?.data_status === \"ready\"\n && ((configuredState !== \"disabled\" && deployment?.runtime_enabled === false)\n || (configuredState === \"enabled\" && deployment?.scheduler_state === \"paused\")\n || monitoring.runtime_guard === \"attention\"\n || monitoring.execution_heartbeat === \"attention\");\n return confirmedAttention ? \"incident\" : \"manual_check\";\n }\n\n function renderAccountDiagnosisAction() {\n const action = el(\"account-diagnosis-action\");\n const button = el(\"account-diagnosis-button\");\n const status = el(\"account-diagnosis-status\");\n if (!action || !button || !status) return;\n const platform = state.selected;\n const account = selectedAccount(platform);\n const eligible = accountDiagnosisEligible(platform, account);\n const task = eligible ? accountDiagnosisTask(platform, account) : null;\n const statusAvailable = accountDiagnosisStatusAvailable(platform, account);\n const key = accountDiagnosisKey(platform, account);\n const submitting = Boolean(state.accountDiagnosis.submitting[key]);\n const busy = submitting || [\"queued\", \"running\"].includes(task?.status)\n || (task?.status === \"succeeded\" && task?.recheck_status === \"sent\");\n action.hidden = !eligible;\n button.disabled = !eligible || !statusAvailable\n || submitting\n || [\"queued\", \"running\"].includes(task?.status)\n || (task?.status === \"succeeded\" && task?.recheck_status === \"sent\");\n button.textContent = submitting ? t(\"accountDiagnosisSubmitting\")\n : task?.status === \"queued\" ? t(\"accountDiagnosisQueuedButton\")\n : task?.status === \"running\" ? t(\"accountDiagnosisRunningButton\")\n : task?.status === \"succeeded\" && task?.recheck_status === \"sent\"\n ? t(\"accountDiagnosisRecheckingButton\") : t(\"accountDiagnosisButton\");\n button.classList.toggle(\"is-busy\", busy);\n if (busy) button.setAttribute(\"aria-busy\", \"true\");\n else button.removeAttribute(\"aria-busy\");\n status.textContent = task && !busy ? accountDiagnosisStatusText(task)\n : eligible && !statusAvailable ? t(\"accountDiagnosisUnavailable\") : \"\";\n }\n\n function accountDeploymentObservation(platform, account) {\n const record = accountMonitoringRecord(platform, account);\n return (record?.deployment_freshness || record?.freshness)?.data_status === \"ready\" ? record.target?.deployment || null : null;\n }\n\n function accountDeploymentText(platform, account) {\n const observed = accountDeploymentObservation(platform, account);\n // Ready observation with null switch is \"unknown\", not the same as missing readback.\n if (!observed) return t(\"notRead\");\n if (typeof observed.runtime_enabled !== \"boolean\") return t(\"runtimeStateUnknown\");\n return t(observed.runtime_enabled ? \"runtimeTargetLifecycleStateEnabled\" : \"runtimeTargetLifecycleStateDisabled\");\n }\n\n function accountSchedulerText(platform, account) {\n const observed = accountDeploymentObservation(platform, account);\n if (!observed) return t(\"notRead\");\n return t({enabled:\"scheduleEnabled\", paused:\"schedulePaused\", mixed:\"scheduleMixed\",\n missing:\"scheduleMissing\", unknown:\"scheduleUnknown\",\n not_applicable:\"scheduleNotApplicable\"}[observed.scheduler_state] || \"notRead\");\n }\n\n function accountApplicationText(platform, account) {\n const observed = accountDeploymentObservation(platform, account);\n const configured = runtimeTargetStateForAccount(platform, account);\n if (!configured.known || typeof observed?.runtime_enabled !== \"boolean\") return t(\"deploymentUnverified\");\n const profile = currentStrategyForAccount(platform, account);\n if (observed.strategy_profile && profile && observed.strategy_profile !== profile) return t(\"strategyNotApplied\");\n if (observed.runtime_enabled !== configured.enabled) return t(\"settingsNotApplied\");\n if (!configured.enabled && observed.scheduler_state === \"paused\") return t(\"switchesApplied\");\n if (configured.enabled && observed.scheduler_state === \"enabled\") return t(\"switchesApplied\");\n if (!observed.scheduler_state || observed.scheduler_state === \"unknown\") return t(\"deploymentUnverified\");\n return t(\"scheduleNotApplied\");\n }\n\n function runtimeOverviewStatus(saved, applicationApplied, record, configurationReason = \"\") {\n const ready = record?.freshness?.data_status === \"ready\";\n const code = record?.execution_observation?.code;\n const healthy = code === \"monitoring_only\"\n || code === \"not_due\"\n || (code === \"not_applicable\" && saved.known && saved.enabled === false);\n if (applicationApplied && ready && healthy) {\n return { status: saved.known && saved.enabled === false ? \"paused\" : \"normal\", reason: \"\" };\n }\n return {\n status: \"abnormal\",\n reason: !record ? \"missing\"\n : record.freshness?.data_status === \"stale\" ? \"stale\"\n : code === \"attention\" ? \"attention\"\n : (typeof configurationReason === \"string\" ? configurationReason : configurationReason ? \"config\" : \"\") || \"pending\",\n };\n }\n\n function accountNextStep(platform, account) {\n const status = accountApplicationText(platform, account);\n if (status === t(\"deploymentUnverified\")) return { label: t(\"recheckRuntimeStatus\"), openSettings: false };\n if (status === t(\"switchesApplied\")) return { label: t(\"noSwitchAction\"), openSettings: false };\n return { label: t(\"reviewAccountSettings\"), openSettings: true };\n }\n\n function openAccountSettings(platform, account, edit = true) {\n state.view = \"accounts\";\n state.selected = platform;\n render();\n const select = el(\"account-select\");\n select.value = account.key;\n select.dispatchEvent(new Event(\"change\"));\n const settings = el(\"strategy-settings\");\n settings.open = edit;\n (edit ? settings : el(\"workspace-title\")).scrollIntoView({ block: \"start\" });\n select.focus({ preventScroll: true });\n }\n\n function accountMonitoringAge(record) {\n const age = (record?.deployment_freshness || record?.freshness)?.age_seconds;\n if (typeof age !== \"number\" || !Number.isFinite(age) || age < 0) return \"—\";\n const unit = age >= 86400 ? \"day\" : age >= 3600 ? \"hour\" : \"minute\";\n const seconds = unit === \"day\" ? 86400 : unit === \"hour\" ? 3600 : 60;\n return new Intl.RelativeTimeFormat(state.lang, { numeric: \"auto\" }).format(-Math.floor(age / seconds), unit);\n }\n\n function accountObservationAge(record) {\n const age = record?.freshness?.age_seconds;\n if (typeof age !== \"number\" || !Number.isFinite(age) || age < 0) return \"—\";\n const unit = age >= 86400 ? \"day\" : age >= 3600 ? \"hour\" : \"minute\";\n const seconds = unit === \"day\" ? 86400 : unit === \"hour\" ? 3600 : 60;\n return new Intl.RelativeTimeFormat(state.lang, { numeric: \"auto\" }).format(-Math.floor(age / seconds), unit);\n }\n\n function runtimeStatusDisplayText(platform, account) {\n const saved = runtimeTargetStateForAccount(platform, account);\n const record = accountMonitoringRecord(platform, account);\n const application = accountApplicationText(platform, account);\n const configurationMismatch = [\"settingsNotApplied\", \"strategyNotApplied\", \"scheduleNotApplied\"]\n .map(key => t(key)).includes(application) || accountMonitoringText(platform, account) === t(\"monitoringConfigMismatch\");\n const configurationReason = application === t(\"strategyNotApplied\") ? \"strategy\"\n : application === t(\"scheduleNotApplied\") ? \"schedule\"\n : application === t(\"settingsNotApplied\") || configurationMismatch ? \"switch\" : \"\";\n const status = runtimeOverviewStatus(saved, application === t(\"switchesApplied\"), record,\n configurationReason);\n const statusReasonText = reason => {\n const reasonKey = reason === \"missing\" ? \"overviewRuntimeReasonMissing\"\n : reason === \"stale\" ? \"overviewRuntimeReasonStale\"\n : reason === \"switch\" ? \"overviewRuntimeReasonSwitch\"\n : reason === \"strategy\" ? \"overviewRuntimeReasonStrategy\"\n : reason === \"schedule\" ? \"overviewRuntimeReasonSchedule\"\n : reason === \"config\" ? \"overviewRuntimeReasonConfig\"\n : reason === \"attention\" ? \"overviewRuntimeReasonAttention\" : \"overviewRuntimeReasonPending\";\n return t(reasonKey).replace(\"{age}\", accountObservationAge(record));\n };\n const statusKey = status.status === \"normal\" ? \"overviewRuntimeNormal\" : status.status === \"paused\" ? \"overviewRuntimePaused\" : \"overviewRuntimeAbnormal\";\n if (status.status !== \"abnormal\") return t(statusKey);\n return `${t(statusKey)} · ${statusReasonText(status.reason)}`;\n }\n\n function renderMonitoringOverview() {\n const body = el(\"monitoring-overview-body\");\n body.replaceChildren();\n if (!hasPrivateConfig()) return;\n for (const platform of Object.keys(platformMeta).filter(p => platformMeta[p].console_visible !== false)) {\n for (const account of optionsFor(platform)) {\n const record = accountMonitoringRecord(platform, account);\n const row = document.createElement(\"tr\");\n for (const value of [platformMeta[platform].label, accountDisplayLabel(account),\n runtimeStatusDisplayText(platform, account), accountObservationAge(record)]) {\n const cell = document.createElement(\"td\");\n cell.textContent = value;\n row.append(cell);\n }\n const action = document.createElement(\"td\");\n const button = document.createElement(\"button\");\n button.className = \"btn\";\n button.type = \"button\";\n button.textContent = runtimeStatusDisplayText(platform, account).startsWith(t(\"overviewRuntimeAbnormal\"))\n ? t(\"monitoringViewReason\") : t(\"switchView\");\n button.addEventListener(\"click\", () => {\n openAccountSettings(platform, account, false);\n });\n action.append(button);\n const statusText = runtimeStatusDisplayText(platform, account);\n if (accountDiagnosisEligible(platform, account) && statusText.startsWith(t(\"overviewRuntimeAbnormal\"))) {\n const diagnosisButton = document.createElement(\"button\");\n diagnosisButton.className = \"btn\";\n diagnosisButton.type = \"button\";\n diagnosisButton.dataset.accountDiagnosis = \"true\";\n diagnosisButton.dataset.platform = platform;\n diagnosisButton.dataset.accountKey = account.key;\n diagnosisButton.textContent = t(\"accountDiagnosisButton\");\n const task = accountDiagnosisTask(platform, account);\n diagnosisButton.disabled = !accountDiagnosisStatusAvailable(platform, account)\n || Boolean(state.accountDiagnosis.submitting[accountDiagnosisKey(platform, account)])\n || [\"queued\", \"running\"].includes(task?.status)\n || (task?.status === \"succeeded\" && task?.recheck_status === \"sent\");\n action.append(diagnosisButton);\n }\n row.append(action);\n body.append(row);\n }\n }\n }\n\n function renderAccountOverview() {\n const body = el(\"account-overview-body\");\n const details = el(\"account-runtime-details\");\n const detailsBody = el(\"account-runtime-details-body\");\n body.replaceChildren();\n detailsBody.replaceChildren();\n el(\"account-overview\").hidden = !hasPrivateConfig();\n details.hidden = !hasPrivateConfig();\n if (!hasPrivateConfig()) {\n if (typeof renderAccountDiagnosisAction === \"function\") renderAccountDiagnosisAction();\n return;\n }\n const platform = state.selected;\n const account = selectedAccount(platform);\n const record = accountMonitoringRecord(platform, account);\n const monitoring = accountMonitoringText(platform, account);\n const observationAge = accountObservationAge(record);\n const application = accountApplicationText(platform, account);\n const saved = runtimeTargetStateForAccount(platform, account);\n const observed = (record?.deployment_freshness || record?.freshness)?.data_status === \"ready\"\n ? record.target?.deployment || null : null;\n const configurationMismatch = [\"settingsNotApplied\", \"strategyNotApplied\", \"scheduleNotApplied\"]\n .map(key => t(key)).includes(application) || monitoring === t(\"monitoringConfigMismatch\");\n const configurationReason = application === t(\"strategyNotApplied\") ? \"strategy\"\n : application === t(\"scheduleNotApplied\") ? \"schedule\"\n : application === t(\"settingsNotApplied\") || configurationMismatch ? \"switch\" : \"\";\n const runtimeStatus = runtimeOverviewStatus(saved, application === t(\"switchesApplied\"), record,\n configurationReason);\n const statusReasonText = reason => {\n const reasonKey = reason === \"missing\" ? \"overviewRuntimeReasonMissing\"\n : reason === \"stale\" ? \"overviewRuntimeReasonStale\"\n : reason === \"switch\" ? \"overviewRuntimeReasonSwitch\"\n : reason === \"strategy\" ? \"overviewRuntimeReasonStrategy\"\n : reason === \"schedule\" ? \"overviewRuntimeReasonSchedule\"\n : reason === \"config\" ? \"overviewRuntimeReasonConfig\"\n : reason === \"attention\" ? \"overviewRuntimeReasonAttention\" : \"overviewRuntimeReasonPending\";\n return t(reasonKey).replace(\"{age}\", accountObservationAge(record));\n };\n const observationCode = record?.execution_observation?.code;\n const profile = currentStrategyForAccount(platform, account);\n const monitoringNeedsAttention = !record\n || record.freshness?.data_status !== \"ready\"\n || [\"attention\", \"unavailable\"].includes(observationCode)\n || monitoring === t(\"monitoringConfigMismatch\");\n const needsAttention = application !== t(\"switchesApplied\") || monitoringNeedsAttention;\n const nextStep = application !== t(\"switchesApplied\")\n ? accountNextStep(platform, account).label\n : runtimeStatus.status === \"abnormal\" ? t(\"recheckRuntimeStatus\")\n : t(\"openSystemStatus\");\n const runtimeSummary = runtimeStatus.status === \"abnormal\"\n ? statusReasonText(runtimeStatus.reason)\n : !observed || !saved.known\n ? t(\"overviewRuntimeReasonPending\")\n : application === t(\"switchesApplied\") && !saved.enabled && observed.scheduler_state === \"paused\"\n ? `${t(\"overviewRuntimePaused\")},未发现运行故障。`\n : application === t(\"switchesApplied\") && saved.enabled && observed.scheduler_state === \"enabled\"\n ? \"配置已应用,自动调度正常。\"\n : application === t(\"strategyNotApplied\") ? t(\"strategyNotApplied\")\n : application === t(\"settingsNotApplied\") ? t(\"settingsNotApplied\")\n : application === t(\"scheduleNotApplied\") ? t(\"scheduleNotApplied\")\n : observed.scheduler_state === \"missing\" ? t(\"scheduleMissing\")\n : t(\"overviewRuntimeReasonPending\");\n const facts = [\n [\"overviewRuntime\", `${t(runtimeStatus.status === \"normal\" ? \"overviewRuntimeNormal\" : runtimeStatus.status === \"paused\" ? \"overviewRuntimePaused\" : \"overviewRuntimeAbnormal\")}${runtimeStatus.status === \"abnormal\" ? ` · ${statusReasonText(runtimeStatus.reason)}` : \"\"}`],\n [\"configuredStrategy\", profile ? strategyLabel(profile) : t(\"notRead\")],\n [\"latestReadback\", observationAge === \"—\" ? t(\"runtimeUnverified\") : observationAge],\n ...(needsAttention ? [[\"accountDetailAction\", nextStep]] : []),\n ];\n const detailSummary = details.querySelector?.(\"summary\");\n if (detailSummary) detailSummary.textContent = `${t(\"accountRuntimeSummary\")}:${runtimeSummary}`;\n const detailFacts = [\n [\"deployedSwitch\", accountDeploymentText(platform, account)],\n [\"schedulerState\", accountSchedulerText(platform, account)],\n [\"applicationStatus\", application],\n ];\n for (const [target, rows] of [[body, facts], [detailsBody, detailFacts]]) {\n for (const [label, value] of rows) {\n const pair = document.createElement(\"div\");\n const term = document.createElement(\"dt\");\n term.textContent = t(label);\n const detail = document.createElement(\"dd\");\n detail.textContent = value;\n pair.append(term, detail);\n target.append(pair);\n }\n }\n if (typeof renderAccountDiagnosisAction === \"function\") renderAccountDiagnosisAction();\n }\n\n function renderCurrentValueSelect(select, modes, selected, known, label, placeholder = t(\"notRead\")) {\n select.replaceChildren();\n if (!known) {\n const option = new Option(placeholder, \"\", true, true);\n option.disabled = true;\n select.append(option);\n select.disabled = true;\n return;\n }\n select.disabled = false;\n for (const mode of modes) {\n select.append(new Option(label(mode), mode, false, mode === selected));\n }\n }\n\n function renderControls() {\n renderPromotionConfirmControls();\n\n const platform = state.selected;\n const meta = platformMeta[platform];\n const form = state.forms[platform];\n const accounts = optionsFor(platform);\n const account = selectedAccount(platform);\n const choices = strategyChoicesForAccount(platform, account, form.executionMode);\n const currentStrategy = currentStrategyForAccount(platform, account);\n const currentStrategyBlocked = Boolean(\n currentStrategy &&\n !strategyAllowedForAccount(platform, account, currentStrategy, form.executionMode),\n );\n const accountSelect = el(\"account-select\");\n const strategySelect = el(\"strategy-select\");\n const runtimeTargetEnabledSelect = el(\"runtime-target-enabled-select\");\n const executionModeSelect = el(\"execution-mode-select\");\n const pluginModeSelect = el(\"plugin-mode-select\");\n const incomeLayerModeSelect = el(\"income-layer-mode-select\");\n const incomeLayerStartUsdInput = el(\"income-layer-start-usd-input\");\n const incomeLayerMaxRatioInput = el(\"income-layer-max-ratio-input\");\n const optionOverlayModeSelect = el(\"option-overlay-mode-select\");\n const cashOnlyExecutionModeSelect = el(\"cash-only-execution-mode-select\");\n const dcaModeSelect = el(\"dca-mode-select\");\n const dcaBaseInvestmentUsdInput = el(\"dca-base-investment-usd-input\");\n const reservePolicyModeSelect = el(\"reserve-policy-mode-select\");\n const minReservedCashInput = el(\"min-reserved-cash-input\");\n const reservedCashRatioInput = el(\"reserved-cash-ratio-input\");\n const showPrivateControls = hasPrivateConfig();\n\n el(\"switch-panel\").style.setProperty(\"--platform-color\", meta.accent);\n el(\"platform-title\").textContent = meta.label;\n el(\"quick-form\").hidden = !showPrivateControls;\n el(\"run-area\").hidden = !showPrivateControls;\n el(\"public-note\").hidden = showPrivateControls;\n el(\"public-note\").textContent = state.auth.allowed ? t(\"missingConfigNote\") : t(\"publicReadonly\");\n\n if (!showPrivateControls) {\n accountSelect.replaceChildren();\n strategySelect.replaceChildren();\n runtimeTargetEnabledSelect.replaceChildren();\n executionModeSelect.replaceChildren();\n pluginModeSelect.replaceChildren();\n incomeLayerModeSelect.replaceChildren();\n optionOverlayModeSelect.replaceChildren();\n cashOnlyExecutionModeSelect.replaceChildren();\n dcaModeSelect.replaceChildren();\n reservePolicyModeSelect.replaceChildren();\n incomeLayerStartUsdInput.value = \"\";\n incomeLayerMaxRatioInput.value = \"\";\n dcaBaseInvestmentUsdInput.value = \"\";\n minReservedCashInput.value = \"\";\n reservedCashRatioInput.value = \"\";\n el(\"account-meta\").textContent = \"\";\n el(\"strategy-meta\").textContent = \"\";\n el(\"income-layer-mode-meta\").textContent = \"\";\n el(\"income-layer-start-meta\").textContent = \"\";\n el(\"income-layer-ratio-meta\").textContent = \"\";\n el(\"option-overlay-mode-meta\").textContent = \"\";\n el(\"cash-only-execution-mode-meta\").textContent = \"\";\n el(\"dca-mode-meta\").textContent = \"\";\n el(\"dca-base-meta\").textContent = \"\";\n return;\n }\n\n accountSelect.replaceChildren();\n if (accounts.length) {\n for (const account of accounts) {\n accountSelect.append(new Option(accountDisplayLabel(account), account.key, false, account.key === form.accountKey));\n }\n } else {\n accountSelect.append(new Option(t(\"noAccount\"), \"\"));\n }\n el(\"account-meta\").textContent = accounts.length ? accountMetaText(platform) : \"\";\n\n const strategyKnown = Boolean(form.strategy || form.strategyTouched);\n strategySelect.disabled = !choices.length || !strategyKnown;\n strategySelect.replaceChildren();\n if (currentStrategyBlocked && !choices.includes(currentStrategy)) {\n const blockedOption = new Option(\n strategyChoiceLabel(currentStrategy, platform, account, form.executionMode),\n currentStrategy,\n true,\n currentStrategy === form.strategy,\n );\n blockedOption.disabled = true;\n strategySelect.append(blockedOption);\n }\n if (choices.length) {\n for (const strategy of choices) {\n strategySelect.append(\n new Option(strategyChoiceLabel(strategy, platform, account, form.executionMode), strategy, false, strategy === form.strategy),\n );\n }\n } else {\n const option = new Option(strategyKnown ? t(\"noStrategy\") : t(\"notRead\"), \"\", true, true);\n option.disabled = true;\n strategySelect.append(option);\n }\n el(\"strategy-meta\").textContent = account\n ? strategyDisplayMetaText(platform, account, form.strategy)\n : \"\";\n const runtimeTarget = runtimeTargetStateForAccount(platform, account);\n const runtimeTargetSelected = form.runtimeTargetTouched\n ? normalizeRuntimeTargetMode(form.runtimeTargetMode)\n : (runtimeTarget.known ? (runtimeTarget.enabled ? \"enabled\" : \"disabled\") : \"\");\n renderCurrentValueSelect(\n runtimeTargetEnabledSelect,\n [\"enabled\", \"disabled\"],\n runtimeTargetSelected,\n runtimeTarget.known || form.runtimeTargetTouched,\n runtimeTargetModeLabel,\n );\n pluginModeSelect.replaceChildren();\n pluginModeSelect.disabled = false;\n for (const mode of pluginModes) {\n pluginModeSelect.append(new Option(pluginModeLabel(mode), mode, false, mode === normalizePluginMode(form.pluginMode)));\n }\n const incomeDefaults = incomeLayerDefaultForStrategy(form.strategy);\n el(\"income-layer-section\").hidden = false;\n el(\"option-overlay-section\").hidden = false;\n incomeLayerModeSelect.replaceChildren();\n if (incomeDefaults) {\n const readback = accountReadbackEntry(platform, account);\n const currentIncome = currentIncomeLayerForAccount(platform, account);\n const incomeKnown = Boolean(readback && incomeLayerFieldsConfigured(readback));\n const incomeSelected = form.incomeLayerTouched\n ? normalizeIncomeLayerMode(form.incomeLayerMode)\n : (incomeKnown ? (currentIncome.enabled === false ? \"disabled\" : \"enabled\") : \"\");\n renderCurrentValueSelect(\n incomeLayerModeSelect,\n incomeLayerModes,\n incomeSelected,\n incomeKnown || form.incomeLayerTouched,\n incomeLayerModeLabel,\n readback ? t(\"strategyDefault\") : t(\"notRead\"),\n );\n el(\"income-layer-mode-meta\").textContent = incomeKnown\n ? incomeLayerDefaultMetaText(incomeDefaults)\n : (readback ? t(\"strategyDefault\") : t(\"notRead\"));\n el(\"income-layer-start-meta\").textContent = t(\"incomeLayerStartMeta\");\n el(\"income-layer-ratio-meta\").textContent = t(\"incomeLayerAllocationMeta\").replace(\n \"{allocations}\",\n incomeLayerAllocationText(incomeDefaults),\n );\n } else {\n incomeLayerModeSelect.disabled = true;\n incomeLayerModeSelect.append(new Option(t(\"incomeLayerNotSupported\"), \"current\"));\n el(\"income-layer-mode-meta\").textContent = t(\"incomeLayerModeMeta\");\n el(\"income-layer-start-meta\").textContent = t(\"incomeLayerStartMeta\");\n el(\"income-layer-ratio-meta\").textContent = t(\"incomeLayerRatioMeta\");\n }\n const supportsMargin = platformSupportsMarginPolicy(platform);\n const supportsReserve = platformSupportsReservedCashPolicy(platform);\n if (supportsMargin) syncCashOnlyExecutionForAccount(platform);\n reconcileExecutionCashPolicy(form, \"margin\");\n const executionCashPolicyGrid = el(\"execution-cash-policy-grid\");\n const qmtPlatformCashNote = el(\"qmt-platform-cash-note\");\n const executionCashPolicyNote = el(\"execution-cash-policy-note\");\n executionCashPolicyGrid.hidden = !supportsMargin && !supportsReserve;\n qmtPlatformCashNote.hidden = supportsMargin || supportsReserve || platform !== \"qmt\";\n executionCashPolicyNote.hidden = !supportsMargin || !supportsReserve;\n\n const marginBlocksReserve = supportsMargin && supportsReserve && allowMarginExplicitlySelected(form);\n const reserveBlocksMargin = supportsMargin && supportsReserve && reserveCashOverrideActive(form);\n\n if (supportsReserve) {\n const reserveReadback = accountReadbackEntry(platform, account);\n const reserveKnown = Boolean(reserveReadback);\n const reservePolicy = currentReservePolicyForAccount(platform, account);\n const currentReserveMode = reservePolicy.minReservedCashUsd && reservePolicy.reservedCashRatio\n ? \"max\" : reservePolicy.minReservedCashUsd ? \"floor\" : reservePolicy.reservedCashRatio ? \"ratio\" : \"none\";\n const reserveSelected = form.reservedCashTouched ? normalizeReservePolicyMode(form.reservePolicyMode) : (reserveKnown ? currentReserveMode : \"\");\n renderCurrentValueSelect(\n reservePolicyModeSelect,\n reservePolicyModes,\n reserveSelected,\n reserveKnown || form.reservedCashTouched,\n mode => t(`reservePolicy${mode[0].toUpperCase()}${mode.slice(1)}`),\n );\n const reserveMode = normalizeReservePolicyMode(form.reservePolicyMode);\n el(\"min-reserved-cash-label\").textContent = t(\"minReservedCash\").replace(\n \"{currency}\",\n selectedCashCurrency(platform, account),\n );\n reservePolicyModeSelect.disabled = false;\n minReservedCashInput.disabled = reserveMode === \"current\" || reserveMode === \"none\" || reserveMode === \"ratio\";\n reservedCashRatioInput.disabled = reserveMode === \"current\" || reserveMode === \"none\" || reserveMode === \"floor\";\n minReservedCashInput.value = reserveMode === \"ratio\" || reserveMode === \"none\" ? \"\" : form.minReservedCashUsd;\n reservedCashRatioInput.value = reserveMode === \"floor\" || reserveMode === \"none\" ? \"\" : form.reservedCashRatio;\n el(\"reserve-policy-block\").classList.toggle(\"policy-block-muted\", marginBlocksReserve);\n el(\"min-reserve-block\").classList.toggle(\"policy-block-muted\", marginBlocksReserve);\n el(\"reserve-ratio-block\").classList.toggle(\"policy-block-muted\", marginBlocksReserve);\n el(\"reserve-policy-mode-meta\").textContent = marginBlocksReserve\n ? t(\"executionCashMarginBlocksReserve\")\n : t(\"reservedCashModeMeta\");\n } else {\n reservePolicyModeSelect.replaceChildren();\n minReservedCashInput.value = \"\";\n reservedCashRatioInput.value = \"\";\n }\n const incomeMode = normalizeIncomeLayerMode(form.incomeLayerMode);\n const incomeLayerInputsDisabled = !incomeDefaults || incomeMode === \"disabled\";\n incomeLayerStartUsdInput.disabled = incomeLayerInputsDisabled;\n incomeLayerMaxRatioInput.disabled = incomeLayerInputsDisabled;\n if (incomeDefaults && incomeMode !== \"disabled\" && !cleanDisplayNumber(form.incomeLayerStartUsd)) {\n form.incomeLayerStartUsd = String(incomeDefaults.startUsd);\n }\n if (incomeDefaults && incomeMode !== \"disabled\" && !cleanDisplayRatio(form.incomeLayerMaxRatio)) {\n form.incomeLayerMaxRatio = incomeDefaults.maxRatio;\n }\n incomeLayerStartUsdInput.value = incomeDefaults && incomeMode !== \"disabled\" ? form.incomeLayerStartUsd : \"\";\n incomeLayerMaxRatioInput.value = incomeDefaults && incomeMode !== \"disabled\" ? form.incomeLayerMaxRatio : \"\";\n\n const optionDefaults = optionOverlayDefaultForStrategy(form.strategy);\n optionOverlayModeSelect.replaceChildren();\n if (optionDefaults) {\n const optionReadback = accountReadbackEntry(platform, account);\n const optionValue = cleanOptionalBoolean(optionReadback?.option_overlay_enabled);\n const optionKnown = optionValue !== null;\n const optionSelected = form.optionOverlayTouched\n ? normalizeOptionOverlayMode(form.optionOverlayMode)\n : (optionKnown ? (optionValue ? \"enabled\" : \"disabled\") : \"\");\n renderCurrentValueSelect(\n optionOverlayModeSelect,\n optionOverlayModes,\n optionSelected,\n optionKnown || form.optionOverlayTouched,\n optionOverlayModeLabel,\n optionReadback ? t(\"strategyDefault\") : t(\"notRead\"),\n );\n el(\"option-overlay-mode-meta\").textContent = optionKnown\n ? optionOverlayDefaultMetaText(optionDefaults)\n : (optionReadback ? t(\"strategyDefault\") : t(\"notRead\"));\n } else {\n optionOverlayModeSelect.disabled = true;\n optionOverlayModeSelect.append(new Option(t(\"optionOverlayNotSupported\"), \"current\"));\n el(\"option-overlay-mode-meta\").textContent = t(\"optionOverlayModeMeta\");\n }\n\n if (supportsMargin) {\n const cashReadback = accountReadbackEntry(platform, account);\n const cashValue = cleanOptionalBoolean(cashReadback?.cash_only_execution);\n const cashKnown = cashValue !== null;\n const cashSelected = form.cashOnlyExecutionTouched\n ? normalizeCashOnlyExecutionMode(form.cashOnlyExecutionMode)\n : (cashKnown ? (cashValue ? \"enabled\" : \"disabled\") : \"\");\n renderCurrentValueSelect(\n cashOnlyExecutionModeSelect,\n cashOnlyExecutionModes,\n cashSelected,\n cashKnown || form.cashOnlyExecutionTouched,\n mode => mode === \"enabled\" ? t(\"cashOnlyExecutionNo\") : t(\"cashOnlyExecutionYes\"),\n cashReadback ? t(\"notConfigured\") : t(\"notRead\"),\n );\n el(\"cash-only-policy-block\").classList.toggle(\"policy-block-muted\", reserveBlocksMargin);\n el(\"cash-only-execution-mode-meta\").textContent = reserveBlocksMargin\n ? t(\"executionCashReserveBlocksMargin\")\n : t(\"cashOnlyExecutionModeMeta\");\n } else {\n cashOnlyExecutionModeSelect.replaceChildren();\n el(\"cash-only-execution-mode-meta\").textContent = \"\";\n }\n\n const dcaDefaults = dcaConfigForStrategy(form.strategy);\n dcaModeSelect.replaceChildren();\n const dcaAllowed = Boolean(dcaDefaults) && platformSupportsDca(platform);\n if (dcaAllowed) {\n const dcaReadback = accountReadbackEntry(platform, account);\n const dcaCurrent = currentDcaForAccount(platform, account, form.strategy);\n const dcaKnown = Boolean(dcaReadback && dcaCurrent.mode && dcaCurrent.baseInvestmentUsd);\n const dcaSelected = form.dcaTouched ? normalizeDcaMode(form.dcaMode) : (dcaKnown ? dcaCurrent.mode : \"\");\n renderCurrentValueSelect(dcaModeSelect, dcaModes, dcaSelected, dcaKnown || form.dcaTouched, dcaModeLabel);\n dcaBaseInvestmentUsdInput.disabled = !dcaKnown && !form.dcaTouched;\n dcaBaseInvestmentUsdInput.value = dcaKnown || form.dcaTouched ? form.dcaBaseInvestmentUsd : \"\";\n el(\"dca-mode-meta\").textContent = dcaKnown\n ? t(\"dcaDefaultMeta\")\n .replace(\"{mode}\", dcaModeLabel(dcaDefaults.defaultMode))\n .replace(\"{amount}\", formatUsd(dcaDefaults.defaultBaseInvestmentUsd))\n : t(\"notRead\");\n el(\"dca-base-meta\").textContent = t(\"dcaModeMeta\");\n } else {\n dcaModeSelect.disabled = true;\n dcaModeSelect.append(new Option(\n dcaDefaults && !platformSupportsDca(platform) ? t(\"dcaPlatformNotSupported\") : t(\"dcaNotSupported\"),\n \"fixed\",\n ));\n dcaBaseInvestmentUsdInput.disabled = true;\n dcaBaseInvestmentUsdInput.value = \"\";\n el(\"dca-mode-meta\").textContent = t(\"dcaModeMeta\");\n el(\"dca-base-meta\").textContent = t(\"dcaModeMeta\");\n }\n\n const supportedModes = supportedExecutionModesForPlatform(platform);\n const liveModeAvailable = supportedModes.includes(\"live\") && hasLiveStrategyOption(platform, account);\n const executionModeKnown = Boolean(form.executionMode || form.executionModeTouched);\n renderCurrentValueSelect(\n executionModeSelect,\n supportedModes,\n form.executionMode,\n executionModeKnown,\n mode => mode === \"live\" ? t(\"executionModeLive\") : t(\"executionModeDryRun\"),\n );\n for (const option of executionModeSelect.options) {\n option.disabled = option.value === \"live\" && !liveModeAvailable;\n }\n const displayedMode = executionEnvironmentForAccount(platform, account);\n el(\"mode-display\").textContent = modeLabel(displayedMode);\n el(\"mode-meta\").textContent = !executionModeKnown\n ? t(\"notRead\")\n : (!supportedModes.includes(\"live\")\n ? t(\"qmtDryRunOnlyNote\")\n : (!liveModeAvailable ? t(binanceResumeDigest() ? \"binanceResumeModeHint\" : \"liveModeUnavailable\") : \"\"));\n }\n\n function renderSummary() {\n const showSummary = hasPrivateConfig();\n const summaryPanel = document.querySelector(\".summary-panel\");\n const switchSurface = document.querySelector(\".switch-surface\");\n summaryPanel.hidden = !showSummary;\n switchSurface.classList.toggle(\"summary-hidden\", !showSummary);\n if (!showSummary) return;\n\n const inputs = buildInputs();\n const list = el(\"summary-list\");\n list.replaceChildren();\n document.querySelector(\".summary-head h2\").textContent = t(\"summary\");\n const currentHeading = document.createElement(\"p\");\n currentHeading.className = \"summary-section-title\";\n currentHeading.textContent = t(\"summaryCurrent\");\n list.appendChild(currentHeading);\n const detail = document.createElement(\"details\");\n detail.className = \"summary-details\";\n const detailLabel = document.createElement(\"summary\");\n detailLabel.textContent = t(\"configDetails\");\n detail.append(detailLabel);\n const primaryLabels = new Set([t(\"selectedAccount\"), t(\"currentStrategy\"), t(\"currentRuntimeTarget\")]);\n let pendingSectionInserted = false;\n for (const [label, value, rowClass, valueTone] of summaryRows(inputs)) {\n if (!pendingSectionInserted && rowClass === \"pending\") {\n const pendingHeading = document.createElement(\"p\");\n pendingHeading.className = \"summary-section-title\";\n pendingHeading.textContent = t(\"summaryPending\");\n list.appendChild(pendingHeading);\n pendingSectionInserted = true;\n }\n const row = document.createElement(\"div\");\n row.className = \"summary-row\";\n row.setAttribute(\"role\", \"listitem\");\n if (rowClass) row.classList.add(rowClass);\n const labelNode = document.createElement(\"div\");\n labelNode.className = \"summary-label\";\n labelNode.textContent = label;\n const valueNode = document.createElement(\"div\");\n valueNode.className = \"summary-value\";\n if (valueTone) {\n const badge = document.createElement(\"span\");\n badge.className = `summary-status ${valueTone}`;\n badge.textContent = value;\n valueNode.appendChild(badge);\n } else {\n valueNode.textContent = value;\n }\n row.append(labelNode, valueNode);\n if (rowClass === \"pending\" || primaryLabels.has(label)) list.appendChild(row);\n else detail.appendChild(row);\n }\n list.appendChild(detail);\n\n const account = selectedAccount();\n const currentMode = executionEnvironmentForAccount(state.selected, account);\n el(\"mode-pill\").textContent = currentMode ? modeLabel(currentMode) : t(\"notRead\");\n }\n\n function renderAuth() {\n const status = el(\"auth-status\");\n const loginLink = el(\"login-link\");\n const logoutButton = el(\"logout-button\");\n const signedIn = Boolean(state.auth.allowed && state.auth.login);\n\n status.hidden = !signedIn;\n status.textContent = signedIn ? t(\"signedInAs\").replace(\"{login}\", state.auth.login) : \"\";\n loginLink.hidden = signedIn;\n loginLink.href = \"/login\";\n loginLink.textContent = t(\"login\");\n logoutButton.hidden = !signedIn;\n logoutButton.textContent = t(\"logout\");\n\n const dispatch = el(\"dispatch-button\");\n const hasPrivateAccounts = state.configSource === \"private\";\n const loadingConfig = state.configSource === \"loading\";\n const stopOnlySelection = normalizeRuntimeTargetMode(state.forms[state.selected]?.runtimeTargetMode) === \"disabled\"\n && Boolean(selectedAccount(state.selected)?.target_name);\n const hasRunnableStrategy = hasRunnableStrategySelection();\n const hasValidReserve = hasValidExecutionCashPolicy();\n const hasValidIncomeLayer = hasValidIncomeLayerPolicy();\n const hasValidOptionOverlay = hasValidOptionOverlayPolicy();\n const hasValidDca = hasValidDcaPolicy();\n const hasValidStrategy = hasRunnableStrategy &&\n hasValidReserve &&\n hasValidIncomeLayer &&\n hasValidOptionOverlay &&\n hasValidDca;\n const hasPendingChange = hasPrivateAccounts && hasValidStrategy && hasPendingChanges(buildInputs());\n if (stopOnlySelection) {\n dispatch.disabled = !state.auth.allowed || loadingConfig || !hasPrivateAccounts || runtimeStopLock.pending;\n dispatch.textContent = state.auth.allowed\n ? (loadingConfig ? t(\"loadingConfig\") : (hasPrivateAccounts ? t(\"runSwitch\") : t(\"configureAccounts\")))\n : t(\"loginToRun\");\n } else {\n dispatch.disabled = !state.auth.allowed || loadingConfig || !hasPrivateAccounts || !hasValidStrategy || !hasPendingChange;\n dispatch.textContent = state.auth.allowed\n ? (loadingConfig\n ? t(\"loadingConfig\")\n : (hasPrivateAccounts ? (hasValidStrategy ? (hasPendingChange ? t(\"runSwitch\") : t(\"noChanges\")) : t(\"configureAccounts\")) : t(\"configureAccounts\")))\n : t(\"loginToRun\");\n }\n const note = el(\"action-note\");\n if (stopOnlySelection && state.auth.allowed && !loadingConfig && hasPrivateAccounts) {\n note.textContent = t(\"runtimeStopReadyNote\");\n note.classList.toggle(\"warning\", false);\n } else {\n note.textContent = state.auth.allowed\n ? (loadingConfig\n ? t(\"loadingConfigNote\")\n : (hasPrivateAccounts\n ? (hasRunnableStrategy\n ? (hasValidReserve\n ? (hasValidIncomeLayer\n ? (hasValidOptionOverlay\n ? (hasValidDca ? (hasPendingChange ? t(\"readyNote\") : \"\") : t(\"invalidDcaNote\"))\n : t(\"invalidOptionOverlayNote\"))\n : t(\"invalidIncomeLayerNote\"))\n : (executionCashPolicyConflict(state.forms[state.selected])\n ? t(\"invalidExecutionCashPolicyNote\")\n : t(\"invalidReservePolicyNote\")))\n : strategyActionNoteText())\n : t(\"missingConfigNote\")))\n : t(\"readonlyNote\");\n note.classList.toggle(\n \"warning\",\n state.auth.allowed && !loadingConfig && (!hasPrivateAccounts || !hasValidStrategy),\n );\n }\n }\n\n function renderAppVisibility() {\n document.body.classList.toggle(\"app-loading\", !state.appReady);\n el(\"boot-message\").textContent = t(state.bootMessageKey);\n el(\"app-shell\").hidden = !state.appReady || !state.auth.allowed;\n el(\"login-screen\").hidden = !state.appReady || state.auth.allowed;\n el(\"login-message\").textContent = t(!state.auth.available\n ? \"loginUnavailable\" : state.auth.login ? \"loginDenied\" : \"loginDescription\");\n el(\"login-link\").hidden = true;\n }\n\n function normalizeControlPlanePayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid control plane payload\");\n const candidates = Array.isArray(payload.candidates) ? payload.candidates : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n attention: payload.attention && typeof payload.attention === \"object\" && !Array.isArray(payload.attention)\n ? {\n status: [\"research_only\", \"attention_required\", \"unavailable\"].includes(payload.attention.status)\n ? payload.attention.status\n : \"unavailable\",\n reason_codes: Array.isArray(payload.attention.reason_codes) ? payload.attention.reason_codes : [],\n }\n : { status: \"unavailable\", reason_codes: [\"control_plane_attention_missing\"] },\n candidates: candidates.filter((item) => item && typeof item === \"object\" && item.lifecycle && typeof item.lifecycle === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function normalizeOwnerDecisionQueue(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid owner decision queue\");\n const candidates = Array.isArray(payload.candidates) ? payload.candidates : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n candidates: candidates.filter((entry) => entry && typeof entry === \"object\"\n && entry.candidate && typeof entry.candidate === \"object\"\n && typeof entry.candidate_evidence_sha256 === \"string\"),\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function ownerDecisionEntry(candidateId) {\n return state.ownerDecisions.candidates.find((entry) => entry.candidate?.candidate_id === candidateId) || null;\n }\n\n function ownerDecisionLabel(decision) {\n return {\n approve_limited_live_canary: t(\"ownerDecisionApprove\"),\n keep_parked: t(\"ownerDecisionPark\"),\n retire_candidate: t(\"ownerDecisionRetire\"),\n }[decision] || String(decision || \"—\");\n }\n\n const operatorLabels = {\n kind: {\n individual: { zh: \"策略\", en: \"Strategy\" },\n portfolio: { zh: \"组合\", en: \"Portfolio\" },\n plugin: { zh: \"插件\", en: \"Plugin\" },\n },\n status: {\n research: { zh: \"观察中\", en: \"Monitoring\" },\n evidence_pending: { zh: \"待复核\", en: \"To review\" },\n verified: { zh: \"正常\", en: \"Normal\" },\n deferred: { zh: \"待复核\", en: \"To review\" },\n parked: { zh: \"已暂停\", en: \"Paused\" },\n paper: { zh: \"测试中\", en: \"Testing\" },\n shadow: { zh: \"观察中\", en: \"Monitoring\" },\n owner_decision_required: { zh: \"等待处理\", en: \"Needs attention\" },\n },\n action: {\n keep_research: { zh: \"继续观察\", en: \"Keep monitoring\" },\n defer: { zh: \"稍后复核\", en: \"Review later\" },\n park: { zh: \"保持暂停\", en: \"Keep paused\" },\n auto_paper_evaluation: { zh: \"继续测试\", en: \"Continue testing\" },\n auto_shadow_evaluation: { zh: \"继续观察\", en: \"Keep monitoring\" },\n owner_live_decision: { zh: \"需要确认\", en: \"Confirmation needed\" },\n none: { zh: \"暂无操作\", en: \"No action\" },\n },\n freshness: {\n fresh: { zh: \"最新\", en: \"Current\" },\n stale: { zh: \"更新延迟\", en: \"Delayed\" },\n unavailable: { zh: \"暂不可用\", en: \"Unavailable\" },\n unknown: { zh: \"暂不可用\", en: \"Unavailable\" },\n },\n };\n\n function operatorLabel(group, value) {\n const label = operatorLabels[group]?.[value];\n return label ? (state.lang === \"zh\" ? label.zh : label.en) : \"—\";\n }\n\n function controlPlaneDataStatusText(status) {\n return status === \"ready\"\n ? t(\"controlDataReady\")\n : (status === \"stale\" ? t(\"controlDataStale\") : t(\"controlDataUnavailable\"));\n }\n\n function controlPlaneAttentionText(attention) {\n const status = attention?.status || \"unavailable\";\n if (status === \"research_only\") return t(\"controlAttentionResearchOnly\");\n if (status === \"attention_required\") return t(\"controlAttentionRequired\");\n return t(\"controlAttentionUnavailable\");\n }\n\n function candidateNeedsOperatorAction(item) {\n const decision = ownerDecisionEntry(item?.candidate_id);\n return state.controlPlane.payload.data_status === \"ready\"\n && state.ownerDecisions.data_status === \"ready\"\n && item?.freshness?.status === \"fresh\"\n && item?.lifecycle?.stage === \"P6\"\n && item.lifecycle.status === \"owner_decision_required\"\n && item?.recommendation?.code === \"owner_live_decision\"\n && Boolean(decision)\n && !decision.intent;\n }\n\n function isParkedResearchResult(item) {\n return item?.source_id === \"aiaudit.soxl_manual_validation\"\n && item?.lifecycle?.stage === \"P3\"\n && item.lifecycle.status === \"parked\"\n && item?.recommendation?.code === \"park\";\n }\n\n function candidateIsControlPlaneVisible(item) {\n return candidateNeedsOperatorAction(item);\n }\n\n function candidateIsDecisionBackgroundVisible(item) {\n return Boolean(item?.forward_observation)\n || Boolean(ownerDecisionEntry(item?.candidate_id)?.intent)\n || item?.lifecycle?.status === \"owner_decision_required\"\n || item?.recommendation?.code === \"owner_live_decision\";\n }\n\n function parkedResearchResultSourceUrl(item) {\n if (!isParkedResearchResult(item)) return \"\";\n const runId = String(item?.evidence?.p3_evidence_id || \"\").trim();\n return /^\\d{6,20}$/.test(runId)\n ? `https://github.com/QuantStrategyLab/AIAuditBridge/actions/runs/${runId}`\n : \"\";\n }\n\n function parkedResearchResultReason(item) {\n const reason = String(item?.recommendation?.reason || \"\").trim();\n return reason || t(\"parkedResearchResultFallback\");\n }\n\n function renderParkedResearchResults() {\n const board = el(\"parked-research-results\");\n const list = el(\"parked-research-results-list\");\n const results = state.controlPlane.payload.candidates.filter(isParkedResearchResult);\n board.hidden = !state.auth.allowed || !results.length;\n list.replaceChildren();\n for (const item of results) {\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"parkedResearchResultsTitle\");\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = t(\"parkedResearchResultTitle\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = parkedResearchResultReason(item);\n main.append(meta, title, reason);\n const sourceUrl = parkedResearchResultSourceUrl(item);\n if (sourceUrl) {\n const source = document.createElement(\"a\");\n source.className = \"health-card__meta\";\n source.href = sourceUrl;\n source.target = \"_blank\";\n source.rel = \"noreferrer\";\n source.textContent = t(\"parkedResearchResultSource\");\n main.appendChild(source);\n }\n const status = document.createElement(\"div\");\n status.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"parkedResearchResultsTitle\");\n const stage = document.createElement(\"strong\");\n stage.textContent = t(\"parkedResearchResultStatus\");\n status.append(label, stage);\n card.append(main, status);\n list.appendChild(card);\n }\n }\n\n function forwardObservationDisplayText(observation) {\n if (!observation || typeof observation !== \"object\") return \"\";\n return t(\"forwardObservationProgress\")\n .replace(\"{completed}\", String(observation.observations_completed ?? \"—\"))\n .replace(\"{required}\", String(observation.required_trading_sessions ?? \"—\"))\n .replace(\"{session}\", String(observation.last_observed_session || \"—\"));\n }\n\n function forwardObservationActionText(observation) {\n if (observation?.state === \"FORWARD_COMPLETE_HUMAN_REVIEW\") return t(\"forwardObservationComplete\");\n if (observation?.state === \"FORWARD_ACTIVE\") return t(\"forwardObservationActive\");\n return t(\"forwardObservationPaused\");\n }\n\n function renderControlPlaneHeading({ hasActionable, hasForwardObservation }) {\n const title = el(\"control-plane-view-title\");\n const subtitle = title?.nextElementSibling;\n const board = el(\"control-queue-title\");\n if (hasActionable && hasForwardObservation) {\n title.textContent = t(\"controlPlaneMixedTitle\");\n subtitle.textContent = t(\"controlPlaneMixedSubtitle\");\n board.textContent = t(\"controlMixedBoard\");\n } else if (hasForwardObservation) {\n title.textContent = t(\"controlPlaneProgressTitle\");\n subtitle.textContent = t(\"controlPlaneProgressSubtitle\");\n board.textContent = t(\"controlProgressBoard\");\n } else {\n title.textContent = t(\"controlPlaneTitle\");\n subtitle.textContent = t(\"controlPlaneSubtitle\");\n board.textContent = t(\"controlCandidateBoard\");\n }\n }\n\n function controlPlaneSourceCondition(payload, ownerDecisions, recoveryPayload) {\n const sources = [payload, ownerDecisions, recoveryPayload];\n const unavailable = sources.some((source) => source?.data_status === \"unavailable\");\n const stale = !unavailable && sources.some((source) => source?.data_status === \"stale\");\n const needsReview = sources.some((source) => Boolean(source?.errors?.length));\n return {\n status: unavailable ? \"unavailable\" : (stale || needsReview ? \"stale\" : \"ready\"),\n unavailable,\n stale,\n needsReview,\n };\n }\n\n function renderControlPlane() {\n const payload = state.controlPlane.payload;\n const pendingRecoveries = state.reconciliationRecovery.payload.recoveries.filter(recoveryNeedsOperatorAction);\n const actionableCandidates = payload.candidates.filter(candidateNeedsOperatorAction);\n const backgroundCandidates = payload.candidates.filter((item) =>\n !candidateNeedsOperatorAction(item) && candidateIsDecisionBackgroundVisible(item));\n const actionableCount = actionableCandidates.length + pendingRecoveries.length;\n const sourceCondition = controlPlaneSourceCondition(\n payload,\n state.ownerDecisions,\n state.reconciliationRecovery.payload,\n );\n const decisionStatus = actionableCount ? \"ready\" : sourceCondition.status;\n el(\"control-plane-status\").textContent = controlPlaneDataStatusText(decisionStatus);\n\n const notice = el(\"control-plane-notice\");\n const statePanel = notice.closest(\".decision-state\");\n renderControlPlaneHeading({ hasActionable: actionableCount > 0, hasForwardObservation: false });\n el(\"control-plane-view\").hidden = !state.auth.allowed;\n const queue = el(\"control-plane-queue\");\n queue.hidden = !actionableCandidates.length;\n statePanel.classList.toggle(\"is-attention\", actionableCount > 0);\n statePanel.classList.toggle(\"is-stale\", !actionableCount && decisionStatus === \"stale\");\n statePanel.classList.toggle(\"is-unavailable\", !state.auth.allowed || (!actionableCount && sourceCondition.unavailable));\n const stateMark = statePanel.querySelector(\".decision-state__mark\");\n stateMark.textContent = !state.auth.allowed || (!actionableCount && sourceCondition.unavailable)\n ? \"i\"\n : ((actionableCount > 0 || decisionStatus === \"stale\") ? \"!\" : \"✓\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"controlLoginNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlLoginSummary\");\n } else if (actionableCount > 0) {\n notice.textContent = t(\"controlAttentionNotice\")\n .replace(\"{count}\", String(actionableCount));\n el(\"control-plane-summary\").textContent = t(\"controlAttentionSummary\");\n } else if (sourceCondition.unavailable) {\n notice.textContent = t(\"controlUnavailableNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlUnavailableSummary\");\n } else if (sourceCondition.stale) {\n notice.textContent = t(\"controlStaleNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlStaleSummary\");\n } else if (sourceCondition.needsReview) {\n notice.textContent = t(\"controlUpstreamNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlStaleSummary\");\n } else {\n notice.textContent = t(\"controlNormalNotice\");\n el(\"control-plane-summary\").textContent = t(\"controlNormalSummary\");\n }\n\n const list = el(\"control-plane-list\");\n list.replaceChildren();\n for (const item of actionableCandidates) {\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = `${operatorLabel(\"kind\", item.candidate_kind)} · ${domainLabel(item.domain || \"\")}`;\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = String(item.candidate_id || \"unknown\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = item.forward_observation\n ? forwardObservationActionText(item.forward_observation)\n : (isParkedResearchResult(item) ? parkedResearchResultReason(item) : t(\"controlAttentionSummary\"));\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"controlItemMeta\")\n .replace(\"{kind}\", operatorLabel(\"status\", item.lifecycle?.status))\n .replace(\"{domain}\", domainLabel(item.domain || \"\"))\n .replace(\"{freshness}\", operatorLabel(\"freshness\", item.freshness?.status || \"unknown\"));\n main.append(meta, title, reason, detail);\n if (item.forward_observation) {\n const observation = document.createElement(\"div\");\n observation.className = \"health-card__meta\";\n observation.textContent = forwardObservationDisplayText(item.forward_observation);\n main.appendChild(observation);\n }\n const parkedResultUrl = parkedResearchResultSourceUrl(item);\n if (parkedResultUrl) {\n const source = document.createElement(\"a\");\n source.className = \"health-card__meta\";\n source.href = parkedResultUrl;\n source.target = \"_blank\";\n source.rel = \"noreferrer\";\n source.textContent = t(\"parkedResearchResultSource\");\n main.appendChild(source);\n }\n const stateBlock = document.createElement(\"div\");\n stateBlock.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"controlNext\");\n const stage = document.createElement(\"strong\");\n stage.textContent = item.forward_observation\n ? forwardObservationActionText(item.forward_observation)\n : operatorLabel(\"action\", item.recommendation?.code || \"none\");\n const recommendation = document.createElement(\"small\");\n recommendation.textContent = `${t(\"controlStatus\")}:${operatorLabel(\"status\", item.lifecycle?.status)}`;\n stateBlock.append(label, stage, recommendation);\n const ownerEntry = ownerDecisionEntry(item.candidate_id);\n if (ownerEntry) {\n const ownerDecision = document.createElement(\"div\");\n ownerDecision.className = \"owner-decision\";\n const ownerTitle = document.createElement(\"strong\");\n ownerTitle.textContent = t(\"ownerDecisionTitle\");\n const ownerDetail = document.createElement(\"small\");\n if (ownerEntry.intent) {\n ownerDetail.textContent = t(\"ownerDecisionRecorded\")\n .replace(\"{decision}\", ownerDecisionLabel(ownerEntry.intent.decision));\n } else if (!state.auth.admin) {\n ownerDetail.textContent = t(\"ownerDecisionAdminOnly\");\n } else {\n ownerDetail.textContent = t(\"ownerDecisionReady\");\n }\n ownerDecision.append(ownerTitle, ownerDetail);\n if (!ownerEntry.intent && state.auth.admin) {\n const actions = document.createElement(\"div\");\n actions.className = \"owner-decision__actions\";\n const submitting = state.ownerDecisions.submittingCandidateId === item.candidate_id;\n for (const [decision, labelKey] of [\n [\"approve_limited_live_canary\", \"ownerDecisionApprove\"],\n [\"keep_parked\", \"ownerDecisionPark\"],\n [\"retire_candidate\", \"ownerDecisionRetire\"],\n ]) {\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"owner-decision__button\";\n button.dataset.ownerDecision = decision;\n button.dataset.candidateId = item.candidate_id;\n button.dataset.candidateEvidenceSha256 = ownerEntry.candidate_evidence_sha256;\n button.disabled = submitting;\n button.textContent = submitting ? t(\"ownerDecisionSubmitting\") : t(labelKey);\n actions.appendChild(button);\n }\n ownerDecision.appendChild(actions);\n }\n main.appendChild(ownerDecision);\n }\n card.append(main, stateBlock);\n list.appendChild(card);\n }\n\n const progressList = el(\"control-plane-progress-list\");\n progressList.replaceChildren();\n for (const item of backgroundCandidates) {\n const card = document.createElement(\"article\");\n card.className = \"health-card is-background\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = String(item.candidate_id || \"unknown\");\n const detail = document.createElement(\"p\");\n detail.className = \"health-card__reason\";\n const recordedDecision = ownerDecisionEntry(item.candidate_id)?.intent?.decision;\n detail.textContent = item.forward_observation\n ? forwardObservationDisplayText(item.forward_observation)\n : (recordedDecision\n ? t(\"ownerDecisionRecorded\").replace(\"{decision}\", ownerDecisionLabel(recordedDecision))\n : t(\"controlStaleSummary\"));\n main.append(title, detail);\n card.appendChild(main);\n progressList.appendChild(card);\n }\n el(\"decision-background\").hidden = !backgroundCandidates.length\n && !state.reconciliationRecovery.payload.recoveries.some((entry) => !recoveryNeedsOperatorAction(entry));\n }\n\n function normalizeReconciliationRecoveryPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new Error(\"invalid reconciliation recovery payload\");\n }\n const recoveries = Array.isArray(payload.recoveries) ? payload.recoveries : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n recoveries: recoveries.filter((entry) => entry && typeof entry === \"object\"\n && entry.recovery && typeof entry.recovery === \"object\"\n && entry.recovery.dual_review && typeof entry.recovery.dual_review === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function recoveryNeedsOperatorAction(entry) {\n const recovery = entry?.recovery || {};\n return state.reconciliationRecovery.payload.data_status === \"ready\"\n && entry?.freshness?.data_status === \"ready\"\n && !entry?.confirmation\n && recovery.readiness === \"awaiting_human_confirmation\"\n && Array.isArray(recovery.blocker_codes)\n && recovery.blocker_codes.length === 0\n && Boolean(recovery.candidate_sha256)\n && recovery.dual_review?.evidence_binding_sha256 === recovery.candidate_sha256;\n }\n\n function recoveryConfirmationAvailableToCurrentUser(entry) {\n return recoveryNeedsOperatorAction(entry) && state.auth.admin;\n }\n\n function renderReconciliationRecovery() {\n const payload = state.reconciliationRecovery.payload;\n const pending = payload.recoveries.filter(recoveryNeedsOperatorAction);\n const history = payload.recoveries.filter((entry) => !recoveryNeedsOperatorAction(entry));\n el(\"reconciliation-recovery-board\").hidden = !state.auth.allowed || !pending.length;\n const notice = el(\"reconciliation-recovery-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"reconciliationRecoveryLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"reconciliationRecoveryStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"reconciliationRecoveryUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"reconciliationRecoveryUpstreamNotice\").replace(\"{count}\", payload.errors.length);\n } else {\n notice.textContent = t(\"reconciliationRecoveryNoOrder\");\n }\n const list = el(\"reconciliation-recovery-list\");\n list.replaceChildren();\n const historyList = el(\"reconciliation-recovery-history-list\");\n historyList.replaceChildren();\n const renderEntry = (entry, target) => {\n const recovery = entry.recovery || {};\n const card = document.createElement(\"article\");\n card.className = `health-card${recoveryNeedsOperatorAction(entry) ? \"\" : \" is-background\"}`;\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"reconciliationRecoveryMeta\")\n .replace(\"{strategy}\", strategyLabel(recovery.strategy_profile || \"unknown\"));\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n const platformKey = String(recovery.platform || \"\").toLowerCase();\n const platformLabel = platformMeta[platformKey]?.label || recovery.platform || t(\"commonUnknown\");\n title.textContent = t(\"reconciliationRecoveryTitle\").replace(\"{platform}\", platformLabel);\n const detail = document.createElement(\"p\");\n detail.className = \"health-card__reason\";\n const ready = recoveryNeedsOperatorAction(entry);\n detail.textContent = entry.confirmation\n ? t(\"reconciliationRecoveryConfirmed\")\n : (ready ? t(\"reconciliationRecoveryReason\") : t(\"reconciliationRecoveryBlocked\")\n .replace(\"{blockers}\", (recovery.blocker_codes || []).join(\", \") || recovery.readiness || \"unknown\"));\n const impact = document.createElement(\"p\");\n impact.className = \"health-card__meta decision-impact\";\n impact.textContent = t(\"reconciliationRecoveryImpact\");\n const technical = document.createElement(\"details\");\n technical.className = \"decision-technical-details\";\n const technicalSummary = document.createElement(\"summary\");\n technicalSummary.textContent = t(\"reconciliationRecoveryTechnicalDetails\");\n const technicalBody = document.createElement(\"p\");\n technicalBody.textContent = `${recovery.recovery_id || \"unknown\"} · ${t(\"reconciliationRecoveryDetail\")\n .replace(\"{state}\", recovery.reconciliation_state || \"unknown\")\n .replace(\"{samples}\", String(recovery.evidence_sample_count || 0))\n .replace(\"{review}\", recovery.dual_review?.outcome || \"unknown\")\n .replace(\"{lastObserved}\", recovery.last_observed_at || \"—\")}`;\n technical.append(technicalSummary, technicalBody);\n const status = document.createElement(\"div\");\n status.className = \"health-card__meta\";\n if (entry.confirmation) {\n status.textContent = t(\"reconciliationRecoveryConfirmed\");\n } else if (!ready) {\n status.textContent = t(\"reconciliationRecoveryBlocked\")\n .replace(\"{blockers}\", (recovery.blocker_codes || []).join(\", \") || recovery.readiness || \"unknown\");\n } else if (!state.auth.admin) {\n status.textContent = t(\"reconciliationRecoveryAdminOnly\");\n }\n main.append(meta, title, detail, impact);\n if (status.textContent) main.appendChild(status);\n main.appendChild(technical);\n if (recoveryConfirmationAvailableToCurrentUser(entry)) {\n const actions = document.createElement(\"div\");\n actions.className = \"owner-decision__actions\";\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"owner-decision__button\";\n button.dataset.reconciliationRecoveryConfirm = \"true\";\n button.dataset.recoveryId = recovery.recovery_id || \"\";\n button.dataset.candidateSha256 = recovery.candidate_sha256 || \"\";\n button.dataset.dualReviewBindingSha256 = recovery.dual_review?.evidence_binding_sha256 || \"\";\n const submitting = state.reconciliationRecovery.submittingRecoveryId === recovery.recovery_id;\n button.disabled = submitting;\n button.textContent = submitting ? t(\"reconciliationRecoverySubmitting\") : t(\"reconciliationRecoveryConfirm\");\n actions.appendChild(button);\n main.appendChild(actions);\n }\n const stateBlock = document.createElement(\"div\");\n stateBlock.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"controlNext\");\n const stateText = document.createElement(\"strong\");\n stateText.textContent = entry.confirmation\n ? t(\"recoveryConfirmedStatus\")\n : (ready ? t(\"recoveryReadyStatus\") : t(\"recoveryBlockedStatus\"));\n const freshness = document.createElement(\"small\");\n freshness.textContent = controlPlaneDataStatusText(entry.freshness?.data_status);\n stateBlock.append(label, stateText, freshness);\n card.append(main, stateBlock);\n target.appendChild(card);\n };\n for (const entry of pending) renderEntry(entry, list);\n for (const entry of history) renderEntry(entry, historyList);\n if (!pending.length && !history.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"reconciliationRecoveryEmpty\");\n historyList.appendChild(empty);\n }\n el(\"decision-background\").hidden = !history.length\n && !state.controlPlane.payload.candidates.some((item) =>\n !candidateNeedsOperatorAction(item) && candidateIsDecisionBackgroundVisible(item));\n }\n\n function clearBinancePrivateScope(status = \"not_available\") {\n binancePrivateScopeRequestGeneration += 1;\n state.binancePrivateScope = { status, report: null };\n el(\"binance-private-scope-list\")?.replaceChildren();\n }\n\n function normalizeBinancePrivateScopePayload(payload) {\n if (!payload || payload.ok !== true || !(\"report\" in payload)) {\n throw new Error(\"invalid Binance private scope payload\");\n }\n if (payload.report === null) return null;\n const report = payload.report;\n if (!report || typeof report !== \"object\" || Array.isArray(report) || report.platform !== \"binance\" || !Array.isArray(report.assets)) {\n throw new Error(\"invalid Binance private scope report\");\n }\n return {\n observed_at: String(report.observed_at || \"\"),\n assets: report.assets.map((item) => {\n if (!item || typeof item !== \"object\" || Array.isArray(item)) {\n throw new Error(\"invalid Binance private scope asset\");\n }\n return {\n asset: String(item.asset || \"\"),\n free: String(item.free || \"\"),\n locked: String(item.locked || \"\"),\n };\n }),\n };\n }\n\n function binancePrivateScopeShouldShow(currentState) {\n return Boolean(\n currentState?.auth?.allowed\n && currentState?.auth?.admin\n && currentState.selected === \"binance\"\n && currentState.binancePrivateScope?.report,\n );\n }\n\n function renderBinancePrivateScope() {\n const board = el(\"binance-private-scope-board\");\n const { status, report } = state.binancePrivateScope;\n board.hidden = !binancePrivateScopeShouldShow(state);\n const list = el(\"binance-private-scope-list\");\n list.replaceChildren();\n if (board.hidden) return;\n const notice = el(\"binance-private-scope-notice\");\n if (status === \"not_available\") {\n notice.textContent = t(\"binancePrivateScopeUnavailable\");\n return;\n }\n if (!report) {\n notice.textContent = t(\"binancePrivateScopeEmpty\");\n return;\n }\n notice.textContent = t(\"binancePrivateScopeObservedAt\").replace(\"{time}\", report.observed_at || \"—\");\n const account = document.createElement(\"p\");\n account.className = \"binance-private-scope__account\";\n account.textContent = `${t(\"binancePrivateScopeAccount\")} · ${t(\"binancePrivateScopePrivateIdentity\")}`;\n const warning = document.createElement(\"p\");\n warning.className = \"binance-private-scope__warning\";\n warning.textContent = t(\"binancePrivateScopeHistoricalWarning\");\n list.append(account, warning);\n if (!report.assets.length) return;\n const tableWrap = document.createElement(\"div\");\n tableWrap.className = \"binance-private-scope__table-wrap\";\n const table = document.createElement(\"table\");\n table.className = \"binance-private-scope__table\";\n const head = document.createElement(\"thead\");\n const headRow = document.createElement(\"tr\");\n for (const label of [\"binancePrivateScopeAsset\", \"binancePrivateScopeFree\", \"binancePrivateScopeLocked\"]) {\n const cell = document.createElement(\"th\");\n cell.scope = \"col\";\n cell.textContent = t(label);\n headRow.appendChild(cell);\n }\n head.appendChild(headRow);\n const body = document.createElement(\"tbody\");\n for (const asset of report.assets) {\n const row = document.createElement(\"tr\");\n for (const value of [asset.asset, asset.free, asset.locked]) {\n const cell = document.createElement(\"td\");\n cell.textContent = value;\n row.appendChild(cell);\n }\n body.appendChild(row);\n }\n table.append(head, body);\n tableWrap.appendChild(table);\n list.appendChild(tableWrap);\n }\n\n const M0_RESEARCH_DISPLAY_LIMIT = 100;\n\n const m0ResearchLabels = {\n subject: {\n asset_idea: { zh: \"资产观察\", en: \"Asset idea\" },\n theme_context: { zh: \"主题背景\", en: \"Theme context\" },\n strategy_hypothesis: { zh: \"研究假设\", en: \"Research hypothesis\" },\n risk_context: { zh: \"风险背景\", en: \"Risk context\" },\n },\n state: {\n candidate: { zh: \"待验证\", en: \"Candidate\" },\n source_verification_required: { zh: \"等待来源核验\", en: \"Source verification required\" },\n deferred: { zh: \"暂缓\", en: \"Deferred\" },\n context_only: { zh: \"仅作背景\", en: \"Context only\" },\n },\n freshness: {\n fresh: { zh: \"有效\", en: \"Fresh\" },\n stale: { zh: \"已过期\", en: \"Stale\" },\n unknown: { zh: \"未知\", en: \"Unknown\" },\n },\n horizon: {\n short: { zh: \"短期\", en: \"Short\" },\n medium: { zh: \"中期\", en: \"Medium\" },\n long: { zh: \"长期\", en: \"Long\" },\n not_applicable: { zh: \"不适用\", en: \"Not applicable\" },\n },\n confidence: {\n high: { zh: \"高\", en: \"High\" },\n medium: { zh: \"中\", en: \"Medium\" },\n low: { zh: \"低\", en: \"Low\" },\n mixed: { zh: \"混合\", en: \"Mixed\" },\n no_event: { zh: \"无事件\", en: \"No event\" },\n unknown: { zh: \"未知\", en: \"Unknown\" },\n },\n style: {\n event_driven: { zh: \"事件驱动\", en: \"Event driven\" },\n long_horizon_growth: { zh: \"长期成长\", en: \"Long-horizon growth\" },\n value_quality: { zh: \"价值质量\", en: \"Value quality\" },\n macro_context: { zh: \"宏观背景\", en: \"Macro context\" },\n mixed_research: { zh: \"综合研究\", en: \"Mixed research\" },\n },\n conflict: {\n none: { zh: \"无\", en: \"None\" },\n conflict: { zh: \"存在\", en: \"Present\" },\n unavailable: { zh: \"不可用\", en: \"Unavailable\" },\n },\n drift: {\n none: { zh: \"无\", en: \"None\" },\n drift: { zh: \"存在\", en: \"Present\" },\n unavailable: { zh: \"不可用\", en: \"Unavailable\" },\n },\n };\n\n function m0ResearchLabel(group, value) {\n const entry = m0ResearchLabels[group]?.[value];\n return entry ? (state.lang === \"zh\" ? entry.zh : entry.en) : \"—\";\n }\n\n function m0ResearchTimestamp(value) {\n return formatDateTime(value);\n }\n\n function m0ResearchHorizons(values) {\n if (!Array.isArray(values) || !values.length) return \"—\";\n const labels = values.map((value) => m0ResearchLabel(\"horizon\", value)).filter((value) => value !== \"—\");\n return labels.length ? labels.join(\" / \") : \"—\";\n }\n\n function m0ResearchEntries(subjects) {\n if (!Array.isArray(subjects)) return [];\n const entries = [];\n for (const item of subjects) {\n if (!item || typeof item !== \"object\" || !item.subject || typeof item.subject !== \"object\") continue;\n if (!Array.isArray(item.observations)) continue;\n for (const observation of item.observations) {\n if (!observation || typeof observation !== \"object\" || !observation.research_context) continue;\n entries.push({\n subject: item.subject,\n observation,\n horizonConflict: item.horizon_conflict,\n historicalStaleHorizonDrift: item.historical_stale_horizon_drift,\n });\n }\n }\n return entries;\n }\n\n function normalizeM0ResearchPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid M0 research payload\");\n const subjects = Array.isArray(payload.subjects) ? payload.subjects : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n viewed_at: typeof payload.viewed_at === \"string\" ? payload.viewed_at : null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n subjects: subjects.filter((item) => item && typeof item === \"object\"\n && item.subject && typeof item.subject === \"object\" && Array.isArray(item.observations)),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function renderM0Research() {\n const payload = state.m0Research.payload;\n const entries = m0ResearchEntries(payload.subjects);\n const shownEntries = entries.slice(0, M0_RESEARCH_DISPLAY_LIMIT);\n const notice = el(\"m0-research-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"m0ResearchLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"m0ResearchStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"m0ResearchUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"m0ResearchUpstreamNotice\").replace(\"{count}\", String(payload.errors.length));\n } else {\n const more = entries.length > M0_RESEARCH_DISPLAY_LIMIT\n ? ` ${t(\"m0ResearchMore\").replace(\"{count}\", String(M0_RESEARCH_DISPLAY_LIMIT))}`\n : \"\";\n notice.textContent = `${t(\"m0ResearchNoOrder\")}${more}`;\n }\n\n const list = el(\"m0-research-list\");\n list.replaceChildren();\n if (!shownEntries.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"m0ResearchEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const entry of shownEntries) {\n const subject = entry.subject || {};\n const observation = entry.observation || {};\n const context = observation.research_context || {};\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"m0ResearchMeta\")\n .replace(\"{kind}\", m0ResearchLabel(\"subject\", subject.kind))\n .replace(\"{viewed}\", m0ResearchTimestamp(payload.viewed_at));\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = typeof subject.identifier === \"string\" ? subject.identifier : \"—\";\n const stateFreshness = document.createElement(\"p\");\n stateFreshness.className = \"health-card__reason\";\n stateFreshness.textContent = t(\"m0ResearchStateFreshness\")\n .replace(\"{state}\", m0ResearchLabel(\"state\", context.state))\n .replace(\"{freshness}\", m0ResearchLabel(\"freshness\", observation.freshness?.status));\n const horizons = document.createElement(\"div\");\n horizons.className = \"health-card__meta\";\n horizons.textContent = t(\"m0ResearchHorizons\")\n .replace(\"{primary}\", m0ResearchLabel(\"horizon\", context.primary_horizon))\n .replace(\"{suitable}\", m0ResearchHorizons(context.suitable_horizons));\n const evidence = document.createElement(\"div\");\n evidence.className = \"health-card__meta\";\n evidence.textContent = t(\"m0ResearchEvidence\")\n .replace(\"{confidence}\", m0ResearchLabel(\"confidence\", context.source_confidence))\n .replace(\"{style}\", m0ResearchLabel(\"style\", context.source_style))\n .replace(\"{digest}\", `${shortResearchDigest(observation.source_report_digest)} / ${shortResearchDigest(observation.source_entry_digest)}`);\n const consistency = document.createElement(\"div\");\n consistency.className = \"health-card__meta\";\n consistency.textContent = t(\"m0ResearchConsistency\")\n .replace(\"{conflict}\", m0ResearchLabel(\"conflict\", entry.horizonConflict?.status))\n .replace(\"{drift}\", m0ResearchLabel(\"drift\", entry.historicalStaleHorizonDrift?.status));\n main.append(meta, title, stateFreshness, horizons, evidence, consistency);\n const status = document.createElement(\"div\");\n status.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = state.lang === \"zh\" ? \"研究\" : \"Research\";\n const freshness = document.createElement(\"strong\");\n freshness.textContent = m0ResearchLabel(\"freshness\", observation.freshness?.status);\n const stateLabel = document.createElement(\"small\");\n stateLabel.textContent = m0ResearchLabel(\"state\", context.state);\n status.append(label, freshness, stateLabel);\n card.append(main, status);\n list.appendChild(card);\n }\n }\n\n function normalizeAdaptiveSelectionPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid adaptive selection payload\");\n const selections = Array.isArray(payload.selections) ? payload.selections : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n selections: selections.filter((item) => item && typeof item === \"object\"\n && typeof item.source_id === \"string\" && item.decision && typeof item.decision === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function renderAdaptiveSelection() {\n const payload = state.adaptiveSelection.payload;\n const notice = el(\"adaptive-selection-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"adaptiveSelectionLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"adaptiveSelectionStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"adaptiveSelectionUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"adaptiveSelectionUpstreamNotice\").replace(\"{count}\", String(payload.errors.length));\n } else {\n notice.textContent = localizedExternalText(payload.policy?.notice, t(\"adaptiveSelectionNoOrder\"));\n }\n\n const list = el(\"adaptive-selection-list\");\n list.replaceChildren();\n if (!payload.selections.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"adaptiveSelectionEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const entry of payload.selections) {\n const decision = entry.decision || {};\n const context = decision.market_context || {};\n const recommended = decision.candidates?.find((item) => item.accepted\n && item.strategy_profile === decision.recommended_strategy_profile) || null;\n const rejected = (decision.candidates || []).filter((item) => !item.accepted);\n const reasons = (recommended?.reasons?.length ? recommended.reasons : rejected.flatMap((item) => item.reasons || []))\n .slice(0, 3)\n .join(\", \");\n\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"adaptiveSelectionMeta\")\n .replace(\"{source}\", entry.source_id || \"unknown\")\n .replace(\"{domain}\", domainLabel(context.domain || \"\"))\n .replace(\"{asOf}\", context.as_of || \"—\");\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = recommended\n ? `${t(\"adaptiveSelectionRecommended\")} · ${recommended.strategy_profile}`\n : t(\"adaptiveSelectionNoCandidate\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = reasons\n ? t(\"adaptiveSelectionReason\").replace(\"{reasons}\", localizedExternalText(reasons, t(\"adaptiveSelectionNoOrder\")))\n : t(\"adaptiveSelectionNoOrder\");\n main.append(meta, title, reason);\n const status = document.createElement(\"div\");\n status.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"adaptiveSelectionScoreLabel\");\n const score = document.createElement(\"strong\");\n score.textContent = typeof recommended?.score === \"number\" ? recommended.score.toFixed(3) : \"—\";\n const freshness = document.createElement(\"small\");\n freshness.textContent = controlPlaneDataStatusText(entry.freshness?.data_status);\n status.append(label, score, freshness);\n card.append(main, status);\n list.appendChild(card);\n }\n }\n\n function normalizeExecutionEvidencePayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid execution evidence payload\");\n const deployments = Array.isArray(payload.deployments) ? payload.deployments : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n deployments: deployments.filter((item) => item && typeof item === \"object\" && item.deployment && typeof item.deployment === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function executionEvidenceReceiptOutcomeLabel(value) {\n return {\n not_due: t(\"executionEvidenceReceiptNotDue\"),\n no_action: t(\"executionEvidenceReceiptNoAction\"),\n risk_blocked: t(\"executionEvidenceReceiptRiskBlocked\"),\n submitted: t(\"executionEvidenceReceiptSubmitted\"),\n broker_acknowledged: t(\"executionEvidenceReceiptAcknowledged\"),\n partially_filled: t(\"executionEvidenceReceiptPartiallyFilled\"),\n filled: t(\"executionEvidenceReceiptFilled\"),\n reconciliation_required: t(\"executionEvidenceReceiptReconciliation\"),\n failed: t(\"executionEvidenceReceiptFailed\"),\n }[value] || t(\"executionEvidenceReceiptMissing\");\n }\n\n function executionEvidenceReceiptConfirmationLabel(value) {\n return {\n not_applicable: t(\"executionEvidenceConfirmationNotApplicable\"),\n not_observed: t(\"executionEvidenceConfirmationNotObserved\"),\n acknowledged: t(\"executionEvidenceConfirmationAcknowledged\"),\n partially_filled: t(\"executionEvidenceConfirmationPartiallyFilled\"),\n filled: t(\"executionEvidenceConfirmationFilled\"),\n reconciliation_required: t(\"executionEvidenceConfirmationReconciliation\"),\n }[value] || t(\"executionEvidenceConfirmationNotObserved\");\n }\n\n function renderExecutionEvidence() {\n const payload = state.executionEvidence.payload;\n const notice = el(\"execution-evidence-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"executionEvidenceLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"executionEvidenceStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"executionEvidenceUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"executionEvidenceUpstreamNotice\").replace(\"{count}\", payload.errors.length);\n } else {\n notice.textContent = localizedExternalText(payload.policy?.notice, t(\"executionEvidenceNoOrder\"));\n }\n\n const list = el(\"execution-evidence-list\");\n list.replaceChildren();\n if (!payload.deployments.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"executionEvidenceEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const entry of payload.deployments) {\n const deployment = entry.deployment || {};\n const strategy = deployment.strategy || {};\n const target = deployment.target || {};\n const capabilities = deployment.capabilities || {};\n const evidence = deployment.evidence || {};\n const executionReceipt = deployment.execution_receipt || null;\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"executionEvidenceMeta\")\n .replace(\"{platform}\", target.platform || \"unknown\")\n .replace(\"{environment}\", target.environment || \"unknown\")\n .replace(\"{source}\", entry.source_id || \"unknown\");\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = String(strategy.candidate_id || deployment.deployment_id || \"unknown\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = localizedExternalText(deployment.recommendation?.reason_code, t(\"executionEvidenceNoOrder\"));\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"executionEvidenceDetail\")\n .replace(\"{strategy}\", evidence.strategy || \"unknown\")\n .replace(\"{data}\", evidence.target_data || \"unknown\")\n .replace(\"{execution}\", evidence.target_execution || \"unknown\")\n .replace(\"{shadow}\", capabilities.shadow || \"unknown\")\n .replace(\"{paper}\", capabilities.paper || \"unknown\");\n const receiptDetail = document.createElement(\"div\");\n receiptDetail.className = \"health-card__meta\";\n receiptDetail.textContent = executionReceipt\n ? t(\"executionEvidenceReceipt\")\n .replace(\"{outcome}\", executionEvidenceReceiptOutcomeLabel(executionReceipt.outcome))\n .replace(\"{confirmation}\", executionEvidenceReceiptConfirmationLabel(executionReceipt.broker_confirmation))\n : t(\"executionEvidenceReceiptMissing\");\n main.append(meta, title, reason, detail, receiptDetail);\n const stateBlock = document.createElement(\"div\");\n stateBlock.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"executionEvidenceNext\");\n const recommendation = document.createElement(\"strong\");\n recommendation.textContent = operatorLabel(\"action\", deployment.recommendation?.code || \"park\");\n const freshness = document.createElement(\"small\");\n freshness.textContent = controlPlaneDataStatusText(entry.freshness?.data_status);\n stateBlock.append(label, recommendation, freshness);\n card.append(main, stateBlock);\n list.appendChild(card);\n }\n }\n\n function normalizeRuntimeTargetLifecyclePayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) {\n throw new Error(\"invalid runtime target lifecycle payload\");\n }\n const targets = Array.isArray(payload.targets) ? payload.targets : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n targets: targets.filter((entry) => entry && typeof entry === \"object\"\n && entry.target && typeof entry.target === \"object\"\n && entry.target.target && typeof entry.target.target === \"object\"\n && entry.target.monitoring && typeof entry.target.monitoring === \"object\"\n && entry.target.disposition && typeof entry.target.disposition === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function runtimeTargetLifecycleCheckLabel(value) {\n return {\n pass: t(\"runtimeTargetLifecycleCheckPass\"),\n attention: t(\"runtimeTargetLifecycleCheckAttention\"),\n not_due: t(\"runtimeTargetLifecycleCheckNotDue\"),\n not_applicable: t(\"runtimeTargetLifecycleCheckNotApplicable\"),\n unavailable: t(\"runtimeTargetLifecycleCheckUnavailable\"),\n }[value] || t(\"runtimeTargetLifecycleCheckUnavailable\");\n }\n\n function runtimeTargetLifecycleStateLabel(value) {\n return value === \"enabled\"\n ? t(\"runtimeTargetLifecycleStateEnabled\")\n : t(\"runtimeTargetLifecycleStateDisabled\");\n }\n\n function runtimeTargetLifecycleObservationLabel(value) {\n return {\n not_due: t(\"runtimeTargetLifecycleObservationNotDue\"),\n monitoring_only: t(\"runtimeTargetLifecycleObservationMonitoringOnly\"),\n not_applicable: t(\"runtimeTargetLifecycleObservationNotApplicable\"),\n attention: t(\"runtimeTargetLifecycleObservationAttention\"),\n unavailable: t(\"runtimeTargetLifecycleObservationUnavailable\"),\n }[value] || t(\"runtimeTargetLifecycleObservationUnavailable\");\n }\n\n function runtimeTargetLifecycleOrderEvidenceLabel(value) {\n return {\n not_collected: t(\"runtimeTargetLifecycleOrderEvidenceNotCollected\"),\n }[value] || t(\"runtimeTargetLifecycleOrderEvidenceNotCollected\");\n }\n\n function runtimeTargetLifecycleDispositionLabel(value) {\n return {\n continue_enabled_monitoring: t(\"runtimeTargetLifecycleDispositionEnabled\"),\n continue_disabled_validation: t(\"runtimeTargetLifecycleDispositionDisabled\"),\n parked: t(\"runtimeTargetLifecycleDispositionParked\"),\n }[value] || t(\"runtimeTargetLifecycleDispositionParked\");\n }\n\n function runtimeTargetLifecycleReasonLabel(value) {\n return {\n none: t(\"runtimeTargetLifecycleReasonNone\"),\n target_intentionally_disabled: t(\"runtimeTargetLifecycleReasonDisabled\"),\n runtime_guard_attention: t(\"runtimeTargetLifecycleReasonRuntimeGuard\"),\n execution_heartbeat_attention: t(\"runtimeTargetLifecycleReasonHeartbeat\"),\n monitoring_unavailable: t(\"runtimeTargetLifecycleReasonUnavailable\"),\n }[value] || t(\"runtimeTargetLifecycleReasonUnavailable\");\n }\n\n function renderRuntimeTargetLifecycle() {\n const payload = state.runtimeTargetLifecycle.payload;\n renderMonitoringOverview();\n renderOverview();\n const notice = el(\"runtime-target-lifecycle-notice\");\n notice.hidden = false;\n if (state.runtimeTargetLifecycle.loading) {\n notice.textContent = t(\"refreshingStatus\");\n } else if (!state.auth.allowed) {\n notice.textContent = t(\"runtimeTargetLifecycleLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"runtimeTargetLifecycleStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"runtimeTargetLifecycleUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"runtimeTargetLifecycleUpstreamNotice\").replace(\"{count}\", String(payload.errors.length));\n } else {\n notice.textContent = \"\";\n notice.hidden = true;\n }\n\n const list = el(\"runtime-target-lifecycle-list\");\n list.replaceChildren();\n if (!payload.targets.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"runtimeTargetLifecycleEmpty\");\n list.appendChild(empty);\n return;\n }\n\n const targets = payload.targets.filter(entry => {\n const platform = entry.target?.target?.platform;\n return platformMeta[platform]?.console_visible !== false && platformMeta[platform]\n && optionsFor(platform).some(account => account.runtime_status_target_id === entry.target.target_id);\n }).sort((left, right) => {\n const leftParked = left.target?.disposition?.code === \"parked\" ? 0 : 1;\n const rightParked = right.target?.disposition?.code === \"parked\" ? 0 : 1;\n if (leftParked !== rightParked) return leftParked - rightParked;\n return String(left.target?.target_id || \"\").localeCompare(String(right.target?.target_id || \"\"));\n });\n for (const entry of targets) {\n const target = entry.target || {};\n const configuration = target.target || {};\n const monitoring = target.monitoring || {};\n const disposition = target.disposition || {};\n const executionObservation = entry.execution_observation || {};\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"runtimeTargetLifecycleMeta\")\n .replace(\"{platform}\", configuration.platform || \"unknown\")\n .replace(\"{state}\", runtimeTargetLifecycleStateLabel(configuration.configured_state))\n .replace(\"{mode}\", configuration.execution_mode || \"unknown\");\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = optionsFor(configuration.platform).find(account => account.runtime_status_target_id === target.target_id)?.label || t(\"runtimeUnverified\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = runtimeTargetLifecycleReasonLabel(disposition.reason_code);\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"runtimeTargetLifecycleDetail\")\n .replace(\"{guard}\", runtimeTargetLifecycleCheckLabel(monitoring.runtime_guard))\n .replace(\"{heartbeat}\", runtimeTargetLifecycleCheckLabel(monitoring.execution_heartbeat));\n const observation = document.createElement(\"div\");\n observation.className = \"health-card__meta\";\n observation.textContent = t(\"runtimeTargetLifecycleObservation\")\n .replace(\"{observation}\", runtimeTargetLifecycleObservationLabel(executionObservation.code))\n .replace(\"{evidence}\", runtimeTargetLifecycleOrderEvidenceLabel(executionObservation.order_or_fill_evidence));\n main.append(meta, title, reason, detail, observation);\n\n const stateBlock = document.createElement(\"div\");\n stateBlock.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"runtimeTargetLifecycleNext\");\n const current = document.createElement(\"strong\");\n current.textContent = runtimeTargetLifecycleDispositionLabel(disposition.code);\n const freshness = document.createElement(\"small\");\n freshness.textContent = entry.freshness?.data_status || \"unknown\";\n stateBlock.append(label, current, freshness);\n card.append(main, stateBlock);\n list.appendChild(card);\n }\n }\n\n function normalizeResearchTaskPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid research task payload\");\n const tasks = Array.isArray(payload.tasks) ? payload.tasks : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n tasks: tasks.filter((item) => item && typeof item === \"object\" && item.task && typeof item.task === \"object\"),\n policy: payload.policy && typeof payload.policy === \"object\" ? payload.policy : {},\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function shortResearchDigest(value) {\n const text = String(value || \"\");\n return /^[0-9a-f]{64}$/.test(text) ? `${text.slice(0, 10)}…` : \"—\";\n }\n\n function renderResearchTasks() {\n const payload = state.researchTasks.payload;\n const board = el(\"research-task-board\");\n const hasValidReport = state.auth.allowed && payload.data_status === \"ready\" && payload.tasks.length > 0;\n if (board) board.hidden = !hasValidReport;\n const notice = el(\"research-task-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"researchTaskLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"researchTaskStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"researchTaskUnavailableNotice\");\n } else if (payload.errors?.length) {\n notice.textContent = t(\"researchTaskUpstreamNotice\").replace(\"{count}\", payload.errors.length);\n } else {\n notice.textContent = localizedExternalText(payload.policy?.notice, t(\"researchTaskNoOrder\"));\n }\n\n const list = el(\"research-task-list\");\n list.replaceChildren();\n if (!payload.tasks.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"researchTaskEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const entry of payload.tasks) {\n const task = entry.task || {};\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"researchTaskMeta\")\n .replace(\"{type}\", task.task_type || \"research\")\n .replace(\"{domain}\", domainLabel(task.target?.domain || \"\"))\n .replace(\"{created}\", formatDateTime(task.created_at));\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = `${task.target?.candidate_id || \"unknown\"} · ${task.task_id || \"unknown\"}`;\n const hypothesis = document.createElement(\"p\");\n hypothesis.className = \"health-card__reason\";\n hypothesis.textContent = localizedExternalText(task.experiment?.hypothesis, t(\"researchTaskNoOrder\"));\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"researchTaskLimits\")\n .replace(\"{runs}\", String(task.experiment?.max_runs || \"—\"))\n .replace(\"{seconds}\", String(task.experiment?.max_wall_seconds || \"—\"))\n .replace(\"{p1}\", shortResearchDigest(task.evidence?.p1_input_digest))\n .replace(\"{p2}\", shortResearchDigest(task.evidence?.p2_config_digest))\n .replace(\"{p3}\", shortResearchDigest(task.evidence?.p3_evidence_id));\n main.append(meta, title, hypothesis, detail);\n const status = document.createElement(\"div\");\n status.className = \"health-card__score\";\n const label = document.createElement(\"small\");\n label.textContent = t(\"researchTaskNoOrderBadge\");\n const count = document.createElement(\"strong\");\n count.textContent = String(task.experiment?.max_runs || \"—\");\n const source = document.createElement(\"small\");\n source.textContent = controlPlaneDataStatusText(entry.freshness?.data_status);\n status.append(label, count, source);\n card.append(main, status);\n list.appendChild(card);\n }\n }\n\n function healthStatusLabel(status) {\n return {\n healthy: t(\"healthStatusHealthy\"),\n watch: t(\"healthStatusWatch\"),\n review: t(\"healthStatusReview\"),\n critical: t(\"healthStatusCritical\"),\n }[status] || t(\"healthStatusUnknown\");\n }\n\n function healthRecommendationText(status) {\n return {\n healthy: t(\"healthRecommendationHealthy\"),\n watch: t(\"healthRecommendationWatch\"),\n review: t(\"healthRecommendationReview\"),\n critical: t(\"healthRecommendationCritical\"),\n }[status] || t(\"healthDecisionFallbackReason\");\n }\n\n function normalizeHealthPayload(payload) {\n if (!payload || typeof payload !== \"object\" || Array.isArray(payload)) throw new Error(\"invalid health payload\");\n const strategies = Array.isArray(payload.strategies) ? payload.strategies : [];\n return {\n data_status: [\"ready\", \"stale\", \"unavailable\"].includes(payload.data_status) ? payload.data_status : \"unavailable\",\n computed_at: payload.computed_at || null,\n summary: payload.summary && typeof payload.summary === \"object\" ? payload.summary : {},\n strategies: strategies.filter((item) => item && typeof item === \"object\" && [\"healthy\", \"watch\", \"review\", \"critical\"].includes(item.status)),\n errors: Array.isArray(payload.errors) ? payload.errors : [],\n };\n }\n\n function renderHealth() {\n const payload = state.health.payload;\n const board = el(\"health-summary-board\");\n if (board) board.hidden = !state.auth.allowed || payload.data_status === \"unavailable\" || !payload.strategies.length;\n const summary = payload.summary || {};\n const healthCount = (status) => Math.max(\n Number(summary[status]) || 0,\n payload.strategies.filter((item) => item.status === status).length,\n );\n const criticalCount = healthCount(\"critical\");\n const reviewCount = healthCount(\"review\");\n const watchCount = healthCount(\"watch\");\n const hasAttention = criticalCount + reviewCount + watchCount > 0;\n const summaryAvailable = state.auth.allowed && payload.data_status !== \"unavailable\";\n const summaryCount = (value) => (summaryAvailable ? String(Number(value) || 0) : \"—\");\n const statusText = payload.data_status === \"ready\"\n ? t(\"healthDataReady\")\n : (payload.data_status === \"stale\" ? t(\"healthDataStale\") : t(\"healthDataUnavailable\"));\n el(\"health-status\").textContent = statusText;\n el(\"health-computed-at\").textContent = payload.computed_at\n ? t(\"healthComputedAt\").replace(\"{time}\", formatDateTime(payload.computed_at))\n : t(\"healthComputedAt\").replace(\"{time}\", \"—\");\n el(\"health-count-total\").textContent = summaryCount(summary.strategy_count);\n el(\"health-count-healthy\").textContent = summaryCount(summary.healthy);\n el(\"health-count-watch\").textContent = summaryCount(summary.watch);\n el(\"health-count-review\").textContent = summaryCount(summary.review);\n el(\"health-count-critical\").textContent = summaryCount(summary.critical);\n\n const notice = el(\"health-notice\");\n if (!state.auth.allowed) {\n notice.textContent = t(\"healthLoginNotice\");\n } else if (payload.data_status === \"stale\") {\n notice.textContent = t(\"healthStaleNotice\");\n } else if (payload.data_status !== \"ready\") {\n notice.textContent = t(\"healthUnavailableNotice\");\n } else if (hasAttention) {\n notice.textContent = t(\"healthAttentionNotice\")\n .replace(\"{critical}\", String(criticalCount))\n .replace(\"{review}\", String(reviewCount))\n .replace(\"{watch}\", String(watchCount));\n } else if (payload.errors?.length) {\n notice.textContent = t(\"healthUpstreamNotice\");\n } else {\n notice.textContent = t(\"healthNormalNotice\");\n }\n\n const list = el(\"health-list\");\n list.replaceChildren();\n const strategies = payload.strategies.filter((item) => state.health.filter === \"all\" || item.status !== \"healthy\");\n if (!strategies.length) {\n const empty = document.createElement(\"div\");\n empty.className = \"health-card__empty\";\n empty.textContent = t(\"healthEmpty\");\n list.appendChild(empty);\n return;\n }\n for (const item of strategies) {\n const card = document.createElement(\"article\");\n card.className = \"health-card\";\n const main = document.createElement(\"div\");\n main.className = \"health-card__main\";\n const meta = document.createElement(\"div\");\n meta.className = \"health-card__meta\";\n meta.textContent = t(\"healthCardMeta\")\n .replace(\"{status}\", healthStatusLabel(item.status))\n .replace(\"{domain}\", domainLabel(item.domain || \"\"));\n const title = document.createElement(\"h4\");\n title.className = \"health-card__title\";\n title.textContent = strategyLabel(item.profile) || t(\"commonUnknown\");\n const reason = document.createElement(\"p\");\n reason.className = \"health-card__reason\";\n reason.textContent = healthRecommendationText(item.status);\n const detail = document.createElement(\"div\");\n detail.className = \"health-card__meta\";\n detail.textContent = t(\"healthDetail\")\n .replace(\"{date}\", formatAsOfDate(item.as_of));\n main.append(meta, title, reason, detail);\n const scoreBlock = document.createElement(\"div\");\n scoreBlock.className = \"health-card__score\";\n const scoreLabel = document.createElement(\"small\");\n scoreLabel.textContent = t(\"healthScoreLabel\");\n const score = document.createElement(\"strong\");\n score.textContent = typeof item.score === \"number\" ? item.score.toFixed(1) : \"—\";\n const decision = document.createElement(\"small\");\n decision.textContent = healthStatusLabel(item.status);\n scoreBlock.append(scoreLabel, score, decision);\n card.append(main, scoreBlock);\n list.appendChild(card);\n }\n }\n\n function overviewAccounts() {\n if (!hasPrivateConfig()) return [];\n const rows = [];\n for (const platform of Object.keys(platformMeta).filter(key => platformMeta[key].console_visible !== false)) {\n for (const account of optionsFor(platform)) {\n const saved = runtimeTargetStateForAccount(platform, account);\n const record = accountMonitoringRecord(platform, account);\n const application = accountApplicationText(platform, account);\n const unknown = application === t(\"deploymentUnverified\");\n const runtimeAttention = record?.freshness?.data_status === \"ready\"\n && record.execution_observation?.code === \"attention\";\n const configurationMismatch = [\"settingsNotApplied\", \"strategyNotApplied\", \"scheduleNotApplied\"]\n .map(key => t(key)).includes(application) || accountMonitoringText(platform, account) === t(\"monitoringConfigMismatch\");\n const configurationReason = application === t(\"strategyNotApplied\") ? \"strategy\"\n : application === t(\"scheduleNotApplied\") ? \"schedule\"\n : application === t(\"settingsNotApplied\") || configurationMismatch ? \"switch\" : \"\";\n const runtimeSummary = runtimeOverviewStatus(saved, application === t(\"switchesApplied\"), record, configurationReason);\n const profile = currentStrategyForAccount(platform, account);\n rows.push({\n platform, platformLabel: platformMeta[platform].label, account,\n strategy: profile ? strategyLabel(profile) : t(\"notRead\"),\n configured: saved.known ? (saved.enabled ? \"enabled\" : \"disabled\") : \"unknown\",\n application, unknown, runtimeAttention,\n runtimeStatus: runtimeSummary.status, runtimeReason: runtimeSummary.reason,\n attention: runtimeSummary.status === \"abnormal\",\n observation: accountMonitoringText(platform, account),\n age: accountObservationAge(record),\n });\n }\n }\n return rows;\n }\n\n function filterOverviewAccounts(rows, filter, search) {\n const query = String(search || \"\").trim().toLocaleLowerCase();\n return rows.filter(row => {\n const inScope = [\"normal\", \"paused\", \"abnormal\"].includes(filter)\n ? row.runtimeStatus === filter : true;\n return inScope && (!query || [row.platformLabel, accountDisplayLabel(row.account), row.account.label, row.strategy]\n .some(value => String(value || \"\").toLocaleLowerCase().includes(query)));\n });\n }\n\n function renderOverview() {\n const rows = overviewAccounts();\n const available = hasPrivateConfig();\n const counts = Object.fromEntries([\"normal\", \"paused\", \"abnormal\"]\n .map(status => [status, rows.filter(row => row.runtimeStatus === status).length]));\n\n const filtered = filterOverviewAccounts(rows, state.overviewFilter, state.overviewSearch);\n el(\"overview-result-count\").textContent = available\n ? t(\"accountResults\").replace(\"{count}\", filtered.length).replace(\"{total}\", rows.length) : \"—\";\n document.querySelectorAll(\"[data-overview-filter]\").forEach(button => {\n button.setAttribute(\"aria-pressed\", String(button.dataset.overviewFilter === state.overviewFilter));\n button.disabled = !available;\n const count = button.querySelector(\"[data-overview-count]\");\n if (count) count.textContent = available ? `(${counts[button.dataset.overviewFilter] || 0})` : \"\";\n });\n el(\"overview-search\").disabled = !available;\n const body = el(\"overview-accounts-body\");\n body.replaceChildren();\n for (const row of filtered) {\n const tr = document.createElement(\"tr\");\n const accountCell = document.createElement(\"td\");\n accountCell.className = \"overview-account\";\n const mark = document.createElement(\"span\");\n mark.className = \"account-mark\";\n mark.setAttribute(\"aria-hidden\", \"true\");\n mark.textContent = platformMeta[row.platform].code;\n const identity = document.createElement(\"span\");\n const name = document.createElement(\"strong\");\n name.textContent = accountDisplayLabel(row.account);\n const platform = document.createElement(\"small\");\n platform.textContent = row.platformLabel;\n identity.append(name, platform);\n accountCell.append(mark, identity);\n const strategyCell = document.createElement(\"td\");\n strategyCell.className = \"overview-strategy\";\n strategyCell.textContent = row.strategy;\n const runtimeCell = document.createElement(\"td\");\n runtimeCell.className = \"overview-runtime\";\n const actual = document.createElement(\"span\");\n actual.className = `runtime-badge ${row.runtimeStatus === \"abnormal\" ? \"attention\" : row.runtimeStatus === \"paused\" ? \"unverified\" : \"applied\"}`;\n const statusKey = row.runtimeStatus === \"normal\" ? \"overviewRuntimeNormal\"\n : row.runtimeStatus === \"paused\" ? \"overviewRuntimePaused\" : \"overviewRuntimeAbnormal\";\n const reasonKey = row.runtimeReason === \"missing\" ? \"overviewRuntimeReasonMissing\"\n : row.runtimeReason === \"stale\" ? \"overviewRuntimeReasonStale\"\n : row.runtimeReason === \"switch\" ? \"overviewRuntimeReasonSwitch\"\n : row.runtimeReason === \"strategy\" ? \"overviewRuntimeReasonStrategy\"\n : row.runtimeReason === \"schedule\" ? \"overviewRuntimeReasonSchedule\"\n : row.runtimeReason === \"config\" ? \"overviewRuntimeReasonConfig\"\n : row.runtimeReason === \"attention\" ? \"overviewRuntimeReasonAttention\" : \"overviewRuntimeReasonPending\";\n actual.textContent = `${t(statusKey)}${row.runtimeStatus === \"abnormal\" ? ` · ${t(reasonKey).replace(\"{age}\", row.age)}` : \"\"}`;\n const saved = document.createElement(\"small\");\n saved.textContent = t(\"savedState\").replace(\"{state}\", t({\n enabled: \"runtimeTargetLifecycleStateEnabled\", disabled: \"runtimeTargetLifecycleStateDisabled\",\n unknown: \"runtimeStateUnknown\",\n }[row.configured]));\n runtimeCell.append(actual, saved);\n const readbackCell = document.createElement(\"td\");\n readbackCell.className = \"overview-readback\";\n const age = document.createElement(\"span\");\n age.textContent = row.age;\n const observation = document.createElement(\"small\");\n observation.textContent = row.observation;\n const mobileLabel = document.createElement(\"span\");\n mobileLabel.className = \"mobile-readback-label\";\n mobileLabel.textContent = `${t(\"latestReadback\")}:`;\n readbackCell.append(mobileLabel, age, observation);\n const actionCell = document.createElement(\"td\");\n actionCell.className = \"overview-action\";\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.className = \"btn\";\n button.textContent = t(\"viewAccount\");\n button.setAttribute(\"aria-label\", t(\"viewAccountLabel\").replace(\"{account}\", `${row.platformLabel} ${accountDisplayLabel(row.account)}`));\n button.addEventListener(\"click\", () => openAccountSettings(row.platform, row.account, false));\n actionCell.append(button);\n tr.append(accountCell, strategyCell, runtimeCell, readbackCell, actionCell);\n body.append(tr);\n }\n el(\"overview-empty\").hidden = filtered.length > 0;\n const emptyKey = !available ? (state.configSource === \"loading\" ? \"overviewLoading\" : \"overviewUnavailable\")\n : rows.length ? \"overviewEmpty\" : \"overviewNoAccounts\";\n el(\"overview-empty-title\").textContent = t(`${emptyKey}Title`);\n el(\"overview-empty-description\").textContent = t(`${emptyKey}Description`);\n el(\"overview-reset\").hidden = !available || !rows.length;\n el(\"monitoring-computed-at\").textContent = state.lastRefreshAt\n ? t(\"pageRefreshed\").replace(\"{time}\", new Intl.DateTimeFormat(locale(), {hour: \"2-digit\", minute: \"2-digit\"}).format(new Date(state.lastRefreshAt)))\n : t(\"pageNotRefreshed\");\n const queue = state.researchPromotion.payload;\n const pending = reviewablePromotionTickets(queue).length;\n el(\"overview-research-link\").hidden = !state.auth.allowed || pending === 0;\n el(\"overview-research-summary\").textContent = pending\n ? t(\"researchPendingCount\").replace(\"{count}\", pending)\n : \"\";\n }\n\n function renderWorkspace() {\n el(\"refresh-status-button\").disabled = state.refreshing;\n el(\"refresh-status-button\").textContent = t(state.refreshing ? \"refreshingStatus\" : \"refreshStatus\");\n const view = [\"overview\", \"accounts\", \"research\"].includes(state.view) ? state.view : \"overview\";\n for (const name of [\"overview\", \"accounts\", \"research\"]) el(`${name}-view`).hidden = view !== name;\n el(\"platform-strip\").hidden = view !== \"accounts\";\n el(\"platform-strip-label\").hidden = view !== \"accounts\";\n el(\"platform-strip-label\").textContent = t(\"activePlatform\");\n el(\"health-view\").hidden = view !== \"research\";\n el(\"monitoring-diagnostics\").hidden = view !== \"research\";\n el(\"workspace-title\").textContent = t(`${view}Nav`);\n el(\"workspace-description\").textContent = t(`${view}Description`);\n document.querySelector(\".workspace-nav\").hidden = !state.appReady || !state.auth.allowed;\n document.querySelectorAll(\".workspace-nav [data-workspace]\").forEach(button => {\n if (button.dataset.workspace === view) button.setAttribute(\"aria-current\", \"page\");\n else button.removeAttribute(\"aria-current\");\n });\n }\n\n function renderConsoleView() {\n el(\"switch-view\").hidden = false;\n el(\"health-view\").hidden = true;\n el(\"control-plane-view\").hidden = !state.auth.allowed;\n }\n\n function render() {\n applyLanguage();\n renderConsoleView();\n renderControlPlane();\n renderReconciliationRecovery();\n renderParkedResearchResults();\n renderBinancePrivateScope();\n renderM0Research();\n renderAdaptiveSelection();\n renderExecutionEvidence();\n renderRuntimeTargetLifecycle();\n renderResearchTasks();\n renderHealth();\n renderPlatforms();\n renderControls();\n renderBinanceResume();\n renderAccountOverview();\n renderSummary();\n renderAuth();\n renderAppVisibility();\n renderWorkspace();\n renderOverview();\n }\n\n async function refreshSession() {\n state.bootMessageKey = \"bootSession\";\n render();\n try {\n const session = await requestJson(\"/api/session\");\n state.auth = {\n available: true,\n allowed: Boolean(session.allowed),\n admin: Boolean(session.admin),\n login: session.login || null,\n };\n } catch {\n state.auth = { available: false, allowed: false, admin: false, login: null };\n }\n if (state.auth.allowed) {\n await refreshControlPlane();\n await refreshOwnerDecisions();\n await refreshConfig();\n await refreshRuntimeTargetLifecycle();\n await refreshAccountDiagnosis();\n refreshReconciliationRecovery();\n if (state.auth.allowed && state.auth.admin) refreshBinancePrivateScope();\n else clearBinancePrivateScope();\n await refreshResearchPromotionTickets();\n } else {\n clearBinancePrivateScope();\n state.bootMessageKey = \"bootPublic\";\n state.appReady = true;\n render();\n }\n }\n\n async function refreshHealth() {\n if (!state.auth.allowed) {\n renderHealth();\n return;\n }\n try {\n state.health.payload = normalizeHealthPayload(await requestJson(\"/api/strategy-health\"));\n } catch {\n state.health.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { strategy_count: 0, healthy: 0, watch: 0, review: 0, critical: 0 },\n strategies: [],\n errors: [\"health_request_failed\"],\n };\n }\n renderHealth();\n }\n\n async function refreshControlPlane() {\n if (!state.auth.allowed) {\n renderControlPlane();\n return;\n }\n try {\n state.controlPlane.payload = normalizeControlPlanePayload(await requestJson(\"/api/control-plane\"));\n } catch {\n state.controlPlane.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { candidate_count: 0, deferred: 0, parked: 0, owner_decision_required: 0 },\n attention: { status: \"unavailable\", reason_codes: [\"control_plane_request_failed\"] },\n candidates: [],\n policy: { p4_p5_automation: \"not_configured\", p6_owner_decision_required: true },\n errors: [\"control_plane_request_failed\"],\n };\n }\n renderControlPlane();\n }\n\n async function refreshOwnerDecisions() {\n if (!state.auth.allowed) {\n state.ownerDecisions = { data_status: \"unavailable\", candidates: [], errors: [] };\n renderControlPlane();\n return;\n }\n try {\n state.ownerDecisions = normalizeOwnerDecisionQueue(await requestJson(\"/api/owner-decisions\"));\n } catch {\n state.ownerDecisions = {\n data_status: \"unavailable\",\n candidates: [],\n errors: [\"owner_decision_queue_request_failed\"],\n };\n }\n renderControlPlane();\n }\n\n async function refreshReconciliationRecovery() {\n if (!state.auth.allowed) {\n renderControlPlane();\n renderReconciliationRecovery();\n return;\n }\n try {\n state.reconciliationRecovery.payload = normalizeReconciliationRecoveryPayload(\n await requestJson(\"/api/reconciliation-recovery\"),\n );\n } catch {\n state.reconciliationRecovery.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { recovery_count: 0, awaiting_human_confirmation: 0, blocked: 0, confirmed: 0 },\n recoveries: [],\n policy: { human_confirmation_required: true, current_evidence_required: true, no_order: true, execution_authority_granted: false },\n errors: [\"reconciliation_recovery_request_failed\"],\n };\n }\n renderControlPlane();\n renderReconciliationRecovery();\n }\n\n async function refreshBinancePrivateScope() {\n if (!state.auth.allowed || !state.auth.admin) {\n clearBinancePrivateScope();\n renderBinancePrivateScope();\n return;\n }\n const requestGeneration = ++binancePrivateScopeRequestGeneration;\n try {\n const report = normalizeBinancePrivateScopePayload(\n await requestJson(\"/api/binance-private-scope\"),\n );\n if (requestGeneration !== binancePrivateScopeRequestGeneration || !state.auth.allowed || !state.auth.admin) return;\n state.binancePrivateScope = {\n status: report ? \"available\" : \"empty\",\n report,\n };\n } catch {\n if (requestGeneration !== binancePrivateScopeRequestGeneration) return;\n clearBinancePrivateScope();\n }\n renderBinancePrivateScope();\n }\n\n async function refreshM0Research() {\n if (!state.auth.allowed) {\n renderM0Research();\n return;\n }\n try {\n state.m0Research.payload = normalizeM0ResearchPayload(await requestJson(\"/api/m0-research\"));\n } catch {\n state.m0Research.payload = {\n data_status: \"unavailable\",\n viewed_at: null,\n summary: {\n subject_count: 0,\n observation_count: 0,\n fresh_observation_count: 0,\n stale_observation_count: 0,\n unknown_observation_count: 0,\n horizon_conflict_count: 0,\n historical_stale_horizon_drift_count: 0,\n },\n subjects: [],\n policy: { authority: \"research_only\", no_order: true, permitted_next_step: \"research_validation_only\" },\n errors: [\"m0_research_request_failed\"],\n };\n }\n renderM0Research();\n }\n\n async function refreshAdaptiveSelection() {\n if (!state.auth.allowed) {\n renderAdaptiveSelection();\n return;\n }\n try {\n state.adaptiveSelection.payload = normalizeAdaptiveSelectionPayload(await requestJson(\"/api/adaptive-selection\"));\n } catch {\n state.adaptiveSelection.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { source_count: 0, decision_count: 0, candidate_count: 0, recommended_count: 0, rejected_candidate_count: 0 },\n selections: [],\n policy: { authority: \"shadow_only\", no_order: true, execution_authority_granted: false },\n errors: [\"adaptive_selection_request_failed\"],\n };\n }\n renderAdaptiveSelection();\n }\n\n async function recordOwnerDecision(button) {\n if (!state.auth.admin) return;\n const candidateId = String(button.dataset.candidateId || \"\");\n const candidateEvidenceSha256 = String(button.dataset.candidateEvidenceSha256 || \"\");\n const decision = String(button.dataset.ownerDecision || \"\");\n if (!candidateId || !candidateEvidenceSha256 || !decision) return;\n if (!window.confirm(t(\"ownerDecisionConfirm\"))) return;\n state.ownerDecisions.submittingCandidateId = candidateId;\n renderControlPlane();\n try {\n const response = await fetch(\"/api/owner-decisions\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n candidate_id: candidateId,\n decision,\n candidate_evidence_sha256: candidateEvidenceSha256,\n }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"ownerDecisionFailed\"));\n showToast(t(\"ownerDecisionSuccess\"), { duration: 7000 });\n await refreshControlPlane();\n await refreshOwnerDecisions();\n } catch (error) {\n showToast(`${t(\"ownerDecisionFailed\")}: ${error.message}`, { duration: 12000 });\n } finally {\n delete state.ownerDecisions.submittingCandidateId;\n renderControlPlane();\n }\n }\n\n async function recordReconciliationRecoveryConfirmation(button) {\n if (!state.auth.admin) return;\n const recoveryId = String(button.dataset.recoveryId || \"\");\n const candidateSha256 = String(button.dataset.candidateSha256 || \"\");\n const dualReviewBindingSha256 = String(button.dataset.dualReviewBindingSha256 || \"\");\n if (!recoveryId || !candidateSha256 || !dualReviewBindingSha256) return;\n if (!window.confirm(t(\"reconciliationRecoveryConfirmPrompt\"))) return;\n state.reconciliationRecovery.submittingRecoveryId = recoveryId;\n renderReconciliationRecovery();\n try {\n const response = await fetch(\"/api/reconciliation-recovery-confirmations\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n recovery_id: recoveryId,\n candidate_sha256: candidateSha256,\n dual_review_binding_sha256: dualReviewBindingSha256,\n }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"reconciliationRecoveryFailed\"));\n showToast(t(\"reconciliationRecoverySuccess\"), { duration: 9000 });\n await refreshReconciliationRecovery();\n } catch (error) {\n showToast(`${t(\"reconciliationRecoveryFailed\")}: ${error.message}`, { duration: 12000 });\n } finally {\n state.reconciliationRecovery.submittingRecoveryId = null;\n renderReconciliationRecovery();\n }\n }\n\n async function refreshExecutionEvidence() {\n if (!state.auth.allowed) {\n renderExecutionEvidence();\n return;\n }\n try {\n state.executionEvidence.payload = normalizeExecutionEvidencePayload(await requestJson(\"/api/execution-evidence\"));\n } catch {\n state.executionEvidence.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { deployment_count: 0, autonomous_shadow: 0, autonomous_paper: 0, owner_canary_decision: 0, parked: 0 },\n deployments: [],\n policy: { execution_evidence_read_only: true, p6_owner_decision_required: true, limited_live_canary_active: false },\n errors: [\"execution_evidence_request_failed\"],\n };\n }\n renderExecutionEvidence();\n }\n\n async function refreshRuntimeTargetLifecycle() {\n if (!state.auth.allowed) {\n renderRuntimeTargetLifecycle();\n return;\n }\n state.runtimeTargetLifecycle.loading = true;\n renderRuntimeTargetLifecycle();\n try {\n state.runtimeTargetLifecycle.payload = normalizeRuntimeTargetLifecyclePayload(\n await requestJson(\"/api/runtime-target-lifecycle\"),\n );\n } catch {\n state.runtimeTargetLifecycle.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { target_count: 0, enabled: 0, disabled: 0, attention: 0 },\n targets: [],\n policy: { lifecycle_status_read_only: true, no_order: true },\n errors: [\"runtime_target_lifecycle_request_failed\"],\n };\n }\n state.runtimeTargetLifecycle.loading = false;\n renderRuntimeTargetLifecycle();\n renderAccountOverview();\n }\n\n async function refreshAccountDiagnosis(platform, account) {\n const targets = platform && account\n ? [[platform, account]]\n : Object.keys(platformMeta).flatMap(itemPlatform => optionsFor(itemPlatform)\n .filter(item => accountDiagnosisEligible(itemPlatform, item))\n .map(item => [itemPlatform, item]));\n await Promise.all(targets.map(async ([itemPlatform, item]) => {\n const diagnosisKey = accountDiagnosisKey(itemPlatform, item);\n state.accountDiagnosis.loading[diagnosisKey] = true;\n try {\n const payload = await requestJson(`/api/account-diagnosis?platform=${encodeURIComponent(itemPlatform)}&key=${encodeURIComponent(item.key)}`);\n state.accountDiagnosis.tasks[diagnosisKey] = payload.task || null;\n } catch {\n state.accountDiagnosis.tasks[diagnosisKey] = null;\n } finally {\n delete state.accountDiagnosis.loading[diagnosisKey];\n }\n }));\n renderAccountDiagnosisAction();\n renderMonitoringOverview();\n }\n\n async function dispatchAccountDiagnosis(button) {\n const platform = String(button.dataset.platform || state.selected);\n const account = optionsFor(platform).find(item => item.key === button.dataset.accountKey) || selectedAccount(platform);\n if (!accountDiagnosisEligible(platform, account)) return;\n const diagnosisKey = accountDiagnosisKey(platform, account);\n if (state.accountDiagnosis.submitting[diagnosisKey]) return;\n const trigger = button.dataset.diagnosisTrigger || accountDiagnosisTrigger(platform, account);\n state.accountDiagnosis.submitting[diagnosisKey] = true;\n renderAccountDiagnosisAction();\n renderMonitoringOverview();\n try {\n const response = await fetch(\"/api/account-diagnosis\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform, key: account.key, trigger }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"accountDiagnosisUnavailable\"));\n state.accountDiagnosis.tasks[diagnosisKey] = payload.task || null;\n } catch (error) {\n showToast(error.message || t(\"accountDiagnosisUnavailable\"), { duration: 9000 });\n } finally {\n delete state.accountDiagnosis.submitting[diagnosisKey];\n renderAccountDiagnosisAction();\n renderMonitoringOverview();\n }\n }\n\n async function refreshResearchTasks() {\n if (!state.auth.allowed) {\n renderResearchTasks();\n return;\n }\n try {\n state.researchTasks.payload = normalizeResearchTaskPayload(await requestJson(\"/api/research-tasks\"));\n } catch {\n state.researchTasks.payload = {\n data_status: \"unavailable\",\n computed_at: null,\n summary: { task_count: 0 },\n tasks: [],\n policy: { research_only: true, no_order: true, size_zero_required: true, p4_p5_p6_authorized: false },\n errors: [\"research_task_request_failed\"],\n };\n }\n renderResearchTasks();\n }\n\n async function refreshStrategyProfiles() {\n state.bootMessageKey = \"bootStrategy\";\n render();\n try {\n const payload = await requestJson(\"/api/strategy-profiles\");\n applyStrategyProfiles(payload.strategyProfiles || []);\n if (payload.platformMeta) platformMeta = payload.platformMeta;\n for (const platform of Object.keys(platformMeta)) syncStrategyForAccount(platform);\n render();\n } catch {\n applyStrategyProfiles(defaultStrategyProfiles);\n for (const platform of Object.keys(platformMeta)) syncStrategyForAccount(platform);\n }\n }\n\n async function refreshConfig() {\n if (!state.auth.available || !state.auth.allowed) return;\n state.configSource = \"loading\";\n state.bootMessageKey = \"bootConfig\";\n render();\n try {\n const payload = await requestJson(\"/api/config\");\n if (payload.accountOptions) {\n applyStrategyProfiles(payload.strategyProfiles || []);\n state.accountOptions = normalizeAccountOptions(payload.accountOptions);\n if (payload.platformMeta) platformMeta = payload.platformMeta;\n state.repositories = normalizePlatformRepositories(payload.platformRepositories || {});\n state.currentStrategies = normalizeCurrentStrategies(payload.currentStrategies || {});\n state.configSource = \"private\";\n for (const platform of Object.keys(platformMeta)) {\n ensureAccountSelection(platform);\n syncStrategyForAccount(platform);\n }\n } else {\n state.configSource = \"default\";\n state.currentStrategies = {};\n }\n } catch (error) {\n state.configSource = \"default\";\n state.currentStrategies = {};\n if (isRequestTimeoutError(error)) {\n state.bootMessageKey = \"bootTimeout\";\n } else {\n state.bootMessageKey = \"bootPublic\";\n }\n } finally {\n state.lastRefreshAt = new Date().toISOString();\n state.appReady = true;\n render();\n }\n }\n\n function normalizeAccountOptions(raw) {\n const normalized = clone(defaultAccountOptions);\n for (const platform of Object.keys(platformMeta)) {\n if (!Array.isArray(raw[platform]) || !raw[platform].length) continue;\n normalized[platform] = raw[platform].map((item, index) => ({\n key: String(item.key || item.target_name || index),\n label: String(item.label || item.target_name || item.key || platform),\n target_name: String(item.target_name || item.key || \"\"),\n account_selector: item.account_selector ? String(item.account_selector) : \"\",\n broker_environment: normalizeExecutionEnvironment(item.broker_environment),\n execution_environment: normalizeExecutionEnvironment(item.execution_environment),\n deployment_selector: item.deployment_selector ? String(item.deployment_selector) : \"\",\n account_scope: item.account_scope ? String(item.account_scope) : \"\",\n service_name: item.service_name ? String(item.service_name) : \"\",\n runtime_status_target_id: String(item.runtime_status_target_id || \"\"),\n cash_currency: item.cash_currency || item.market_currency || item.trading_currency\n ? String(item.cash_currency || item.market_currency || item.trading_currency).trim().toUpperCase()\n : \"\",\n default_execution_mode: normalizeExecutionMode(item.default_execution_mode) || \"\",\n supported_domains: normalizeSupportedDomains(platform, item),\n github_environment: item.github_environment ? String(item.github_environment) : \"\",\n variable_scope: item.variable_scope ? String(item.variable_scope) : \"\",\n plugin_mode: item.plugin_mode ? String(item.plugin_mode) : \"\",\n option_overlay_mode: item.option_overlay_mode ? normalizeOptionOverlayMode(item.option_overlay_mode) : \"\",\n cash_only_execution_mode: item.cash_only_execution_mode\n ? normalizeCashOnlyExecutionMode(item.cash_only_execution_mode)\n : \"\",\n dca_mode: item.dca_mode ? normalizeDcaMode(item.dca_mode) : \"\",\n dca_base_investment_usd: cleanDisplayPositiveNumber(item.dca_base_investment_usd),\n }));\n }\n return normalized;\n }\n\n function normalizeSupportedDomains(platform, item) {\n const raw = Array.isArray(item?.supported_domains)\n ? item.supported_domains\n : String(item?.supported_domains || \"\").split(/[\\s,;]+/);\n const cleaned = raw.map(cleanStrategyDomain).filter(Boolean);\n if (cleaned.length) return [...new Set(cleaned)];\n return inferSupportedDomains(platform, item || {});\n }\n\n function normalizeCurrentStrategies(raw) {\n const normalized = {};\n for (const platform of Object.keys(platformMeta)) {\n if (!raw[platform] || typeof raw[platform] !== \"object\" || Array.isArray(raw[platform])) continue;\n normalized[platform] = {};\n for (const [key, entry] of Object.entries(raw[platform])) {\n const profile = cleanStrategyProfile(entry?.strategy_profile);\n const minReservedCashUsd = cleanDisplayNumber(entry?.min_reserved_cash_usd ?? entry?.reserved_cash_floor_usd);\n const reservedCashRatio = cleanDisplayRatio(entry?.reserved_cash_ratio);\n const incomeLayerEnabled = cleanOptionalBoolean(entry?.income_layer_enabled);\n const incomeLayerStartUsd = cleanDisplayNumber(entry?.income_layer_start_usd);\n const incomeLayerMaxRatio = cleanDisplayRatio(entry?.income_layer_max_ratio);\n const optionOverlayEnabled = cleanOptionalBoolean(entry?.option_overlay_enabled);\n const cashOnlyExecution = cleanOptionalBoolean(entry?.cash_only_execution);\n const runtimeTargetEnabled = cleanOptionalBoolean(entry?.runtime_target_enabled);\n const dcaMode = entry?.dca_mode ? normalizeDcaMode(entry.dca_mode) : \"\";\n const dcaBaseInvestmentUsd = cleanDisplayPositiveNumber(entry?.dca_base_investment_usd);\n const executionModeRaw = String(entry?.execution_mode || \"\").trim().toLowerCase();\n const executionEnvironment = normalizeExecutionEnvironment(entry?.execution_environment);\n const executionMode = normalizeExecutionMode(executionModeRaw, entry?.dry_run_only);\n const dryRunOnly = cleanOptionalBoolean(entry?.dry_run_only);\n if (\n !profile &&\n !minReservedCashUsd &&\n !reservedCashRatio &&\n incomeLayerEnabled === null &&\n !incomeLayerStartUsd &&\n !incomeLayerMaxRatio &&\n optionOverlayEnabled === null &&\n cashOnlyExecution === null &&\n runtimeTargetEnabled === null &&\n !dcaMode &&\n !dcaBaseInvestmentUsd &&\n !executionMode &&\n !executionEnvironment\n ) continue;\n normalized[platform][String(key)] = {\n strategy_profile: profile,\n execution_mode: executionMode,\n execution_mode_raw: executionModeRaw,\n execution_environment: executionEnvironment,\n dry_run_only: dryRunOnly,\n min_reserved_cash_usd: minReservedCashUsd,\n reserved_cash_ratio: reservedCashRatio,\n income_layer_enabled: incomeLayerEnabled,\n income_layer_start_usd: incomeLayerStartUsd,\n income_layer_max_ratio: incomeLayerMaxRatio,\n option_overlay_enabled: optionOverlayEnabled,\n cash_only_execution: cashOnlyExecution,\n runtime_target_enabled: runtimeTargetEnabled,\n binance_resume_target_sha256: /^[a-f0-9]{64}$/.test(entry?.binance_resume_target_sha256 || \"\")\n ? entry.binance_resume_target_sha256 : \"\",\n dca_mode: dcaMode,\n dca_base_investment_usd: dcaBaseInvestmentUsd,\n source: entry?.source ? String(entry.source) : \"\",\n };\n }\n if (!Object.keys(normalized[platform]).length) delete normalized[platform];\n }\n return normalized;\n }\n\n function normalizePlatformRepositories(raw) {\n const normalized = clone(defaultRepositories);\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return normalized;\n for (const platform of Object.keys(platformMeta)) {\n const repository = String(raw[platform] || \"\").trim();\n if (/^[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.-]+$/.test(repository)) {\n normalized[platform] = repository;\n }\n }\n return normalized;\n }\n\n function binanceResumeDigest() {\n if (!state.auth.allowed || state.configSource !== \"private\" || state.selected !== \"binance\") return \"\";\n const entry = currentEntryForAccount(\"binance\", selectedAccount(\"binance\"));\n return entry?.runtime_target_enabled === false ? entry.binance_resume_target_sha256 || \"\" : \"\";\n }\n\n function renderBinanceResume() {\n const visible = Boolean(binanceResumeDigest());\n el(\"binance-resume-panel\").hidden = !visible;\n el(\"binance-resume-button\").disabled = !visible || binanceResumeLock.pending;\n el(\"binance-resume-status\").textContent = binanceResumeLock.messageKey ? t(binanceResumeLock.messageKey) : \"\";\n }\n\n async function dispatchBinanceResume() {\n if (binanceResumeLock.pending || !state.auth.allowed || state.selected !== \"binance\") return;\n const digest = binanceResumeDigest();\n const account = selectedAccount(\"binance\");\n if (!digest || !account?.target_name || !window.confirm(t(\"binanceResumeConfirm\"))) return;\n binanceResumeLock.pending = true;\n binanceResumeLock.messageKey = \"dispatching\";\n render();\n try {\n const response = await fetch(\"/api/runtime-resume\", {\n method: \"POST\", headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform: \"binance\", target_name: account.target_name,\n runtime_target_sha256: digest, confirm: \"RESUME_EXISTING\" }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(\"resume submission unverified\");\n binanceResumeLock.messageKey = \"binanceResumePending\";\n if (payload.actions_url) window.open(payload.actions_url, \"_blank\", \"noopener,noreferrer\");\n } catch {\n binanceResumeLock.messageKey = \"binanceResumeUnknown\";\n }\n // Keep the lock after success or an uncertain write. Refresh only after\n // inspecting the existing workflow; no automatic retry or trading call.\n render();\n showToast(t(binanceResumeLock.messageKey), { duration: 12000 });\n }\n\n async function dispatchRuntimeStop() {\n if (runtimeStopLock.pending || !state.auth.allowed || !window.confirm(t(\"runtimeStopConfirm\"))) return;\n const account = selectedAccount(state.selected);\n if (!account?.target_name) return;\n runtimeStopLock.pending = true;\n const dispatch = el(\"dispatch-button\");\n if (dispatch) dispatch.disabled = true;\n showToast(t(\"dispatching\"), { duration: 0 });\n try {\n const response = await fetch(\"/api/runtime-stop\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform: state.selected, target_name: account.target_name, confirm: \"STOP_ONLY\" }),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"dispatchFailed\"));\n showToast(t(\"runtimeStopPending\"), { duration: 12000 });\n if (payload.actions_url) window.open(payload.actions_url, \"_blank\", \"noopener,noreferrer\");\n } catch (error) {\n showToast(`${t(\"dispatchFailed\")}: ${error.message}`, { duration: 12000 });\n }\n // A timeout does not prove GitHub rejected the request. Keep the main\n // control locked until the operator reloads after checking the existing run.\n }\n\n async function dispatchSwitch() {\n if (!state.auth.allowed) return;\n if (normalizeRuntimeTargetMode(state.forms[state.selected]?.runtimeTargetMode) === \"disabled\") {\n return dispatchRuntimeStop();\n }\n showToast(t(\"dispatching\"), { duration: 0 });\n try {\n const response = await fetch(\"/api/switch\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(buildInputs()),\n });\n const payload = await response.json();\n if (!response.ok || !payload.ok) throw new Error(payload.error || t(\"dispatchFailed\"));\n showToast(t(\"dispatched\"), { duration: 4000 });\n if (payload.actions_url) window.open(payload.actions_url, \"_blank\", \"noopener,noreferrer\");\n await refreshConfig();\n } catch (error) {\n showToast(`${t(\"dispatchFailed\")}: ${error.message}`, { duration: 12000 });\n }\n }\n\n async function handleLogout() {\n state.auth = { available: true, allowed: false, admin: false, login: null };\n clearBinancePrivateScope();\n renderBinancePrivateScope();\n await fetch(\"/api/logout\", { method: \"POST\" });\n window.location.reload();\n }\n\n function summaryText() {\n const inputs = buildInputs();\n return summaryRows(inputs).map(([label, value]) => `${label}: ${value}`).join(\"\\\n\");\n }\n\n function refreshResearchWorkspace() {\n return Promise.allSettled([\n refreshHealth(),\n refreshReconciliationRecovery(),\n refreshM0Research(),\n refreshAdaptiveSelection(),\n refreshExecutionEvidence(),\n refreshResearchTasks(),\n refreshResearchPromotionTickets(),\n refreshRuntimeTargetLifecycle(),\n ]);\n }\n\n document.querySelectorAll(\"[data-workspace]\").forEach(button => button.addEventListener(\"click\", () => {\n state.view = button.dataset.workspace;\n render();\n if (state.view === \"research\") void refreshResearchWorkspace();\n el(\"workspace-title\").focus({ preventScroll: true });\n window.scrollTo({ top: 0 });\n }));\n\n document.querySelectorAll(\"[data-overview-filter]\").forEach(button => button.addEventListener(\"click\", () => {\n state.overviewFilter = button.dataset.overviewFilter;\n renderOverview();\n }));\n el(\"overview-search\").addEventListener(\"input\", () => {\n state.overviewSearch = el(\"overview-search\").value;\n renderOverview();\n });\n el(\"overview-reset\").addEventListener(\"click\", () => {\n state.overviewFilter = \"all\";\n state.overviewSearch = \"\";\n el(\"overview-search\").value = \"\";\n renderOverview();\n el(\"overview-search\").focus();\n });\n document.querySelectorAll(\"[data-health-filter]\").forEach((button) => button.addEventListener(\"click\", () => {\n document.querySelectorAll(\"[data-health-filter]\").forEach((node) => node.classList.remove(\"active\"));\n button.classList.add(\"active\");\n state.health.filter = button.dataset.healthFilter;\n renderHealth();\n }));\n\n el(\"control-plane-list\").addEventListener(\"click\", (event) => {\n const button = event.target.closest(\"[data-owner-decision]\");\n if (!button || button.disabled) return;\n recordOwnerDecision(button);\n });\n\n el(\"reconciliation-recovery-list\").addEventListener(\"click\", (event) => {\n const button = event.target.closest(\"[data-reconciliation-recovery-confirm]\");\n if (!button || button.disabled) return;\n recordReconciliationRecoveryConfirmation(button);\n });\n\n el(\"account-diagnosis-button\").addEventListener(\"click\", event => {\n dispatchAccountDiagnosis(event.currentTarget);\n });\n el(\"monitoring-overview-body\").addEventListener(\"click\", event => {\n const button = event.target.closest(\"[data-account-diagnosis]\");\n if (!button || button.disabled) return;\n dispatchAccountDiagnosis(button);\n });\n\n el(\"platform-strip\").addEventListener(\"click\", (event) => {\n const button = event.target.closest(\"[data-platform]\");\n if (!button) return;\n state.selected = button.dataset.platform;\n state.forms[state.selected].strategyTouched = false;\n render();\n });\n\n el(\"refresh-status-button\").addEventListener(\"click\", async () => {\n if (!state.auth.allowed) return;\n const button = el(\"refresh-status-button\");\n state.refreshing = true;\n button.disabled = true;\n button.textContent = t(\"refreshingStatus\");\n try {\n await Promise.all([\n refreshConfig(),\n refreshRuntimeTargetLifecycle(),\n refreshReconciliationRecovery(),\n refreshBinancePrivateScope(),\n refreshResearchPromotionTickets(),\n refreshControlPlane(),\n refreshOwnerDecisions(),\n ]);\n await refreshAccountDiagnosis();\n } finally {\n state.refreshing = false;\n state.lastRefreshAt = new Date().toISOString();\n render();\n button.disabled = false;\n button.textContent = t(\"refreshStatus\");\n }\n });\n\n el(\"account-select\").addEventListener(\"change\", () => {\n state.forms[state.selected].accountKey = el(\"account-select\").value;\n state.forms[state.selected].runtimeTargetTouched = false;\n state.forms[state.selected].reservedCashTouched = false;\n state.forms[state.selected].incomeLayerTouched = false;\n state.forms[state.selected].optionOverlayTouched = false;\n state.forms[state.selected].cashOnlyExecutionTouched = false;\n state.forms[state.selected].dcaTouched = false;\n state.forms[state.selected].strategyTouched = false;\n state.forms[state.selected].executionModeTouched = false;\n state.forms[state.selected].pluginModeTouched = false;\n syncStrategyForAccount(state.selected);\n render();\n refreshAccountDiagnosis();\n });\n\n el(\"strategy-select\").addEventListener(\"change\", () => {\n state.forms[state.selected].strategy = el(\"strategy-select\").value;\n state.forms[state.selected].strategyTouched = true;\n state.forms[state.selected].incomeLayerTouched = false;\n state.forms[state.selected].optionOverlayTouched = false;\n state.forms[state.selected].dcaTouched = false;\n syncIncomeLayerForAccount(state.selected);\n syncOptionOverlayForAccount(state.selected);\n syncDcaForAccount(state.selected);\n render();\n });\n\n el(\"execution-mode-select\").addEventListener(\"change\", () => {\n const mode = el(\"execution-mode-select\").value;\n if (!supportedExecutionModesForPlatform(state.selected).includes(mode)) return;\n state.forms[state.selected].executionMode = mode;\n state.forms[state.selected].executionModeTouched = true;\n render();\n });\n\n el(\"plugin-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.pluginMode = normalizePluginMode(el(\"plugin-mode-select\").value);\n form.pluginModeTouched = true;\n render();\n });\n\n el(\"runtime-target-enabled-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.runtimeTargetMode = normalizeRuntimeTargetMode(el(\"runtime-target-enabled-select\").value);\n form.runtimeTargetTouched = form.runtimeTargetMode !== \"current\";\n render();\n });\n\n el(\"income-layer-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.incomeLayerMode = normalizeIncomeLayerMode(el(\"income-layer-mode-select\").value);\n form.incomeLayerTouched = form.incomeLayerMode !== \"current\";\n if (form.incomeLayerMode === \"current\") {\n form.incomeLayerTouched = false;\n syncIncomeLayerForAccount(state.selected);\n }\n render();\n });\n\n el(\"income-layer-start-usd-input\").addEventListener(\"input\", () => {\n const form = state.forms[state.selected];\n form.incomeLayerTouched = true;\n form.incomeLayerMode = \"enabled\";\n form.incomeLayerStartUsd = el(\"income-layer-start-usd-input\").value.trim();\n render();\n });\n\n el(\"income-layer-max-ratio-input\").addEventListener(\"input\", () => {\n const form = state.forms[state.selected];\n form.incomeLayerTouched = true;\n form.incomeLayerMode = \"enabled\";\n form.incomeLayerMaxRatio = el(\"income-layer-max-ratio-input\").value.trim();\n render();\n });\n\n el(\"option-overlay-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.optionOverlayMode = normalizeOptionOverlayMode(el(\"option-overlay-mode-select\").value);\n form.optionOverlayTouched = form.optionOverlayMode !== \"current\";\n render();\n });\n\n el(\"cash-only-execution-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.cashOnlyExecutionMode = normalizeCashOnlyExecutionMode(el(\"cash-only-execution-mode-select\").value);\n form.cashOnlyExecutionTouched = form.cashOnlyExecutionMode !== \"current\";\n if (allowMarginExplicitlySelected(form)) reconcileExecutionCashPolicy(form, \"margin\");\n else restoreReserveAfterMarginDisabled(form);\n render();\n });\n\n el(\"dca-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.dcaTouched = true;\n form.dcaMode = normalizeDcaMode(el(\"dca-mode-select\").value);\n render();\n });\n\n el(\"dca-base-investment-usd-input\").addEventListener(\"input\", () => {\n const form = state.forms[state.selected];\n form.dcaTouched = true;\n form.dcaBaseInvestmentUsd = el(\"dca-base-investment-usd-input\").value.trim();\n render();\n });\n\n el(\"reserve-policy-mode-select\").addEventListener(\"change\", () => {\n const form = state.forms[state.selected];\n form.reservePolicyMode = normalizeReservePolicyMode(el(\"reserve-policy-mode-select\").value);\n form.reservedCashTouched = form.reservePolicyMode !== \"current\";\n if (form.reservePolicyMode === \"current\") syncReservePolicyForAccount(state.selected);\n reconcileExecutionCashPolicy(form, \"reserve\");\n render();\n });\n\n el(\"min-reserved-cash-input\").addEventListener(\"input\", () => {\n state.forms[state.selected].reservedCashTouched = true;\n state.forms[state.selected].minReservedCashUsd = el(\"min-reserved-cash-input\").value.trim();\n render();\n });\n\n el(\"reserved-cash-ratio-input\").addEventListener(\"input\", () => {\n state.forms[state.selected].reservedCashTouched = true;\n state.forms[state.selected].reservedCashRatio = el(\"reserved-cash-ratio-input\").value.trim();\n render();\n });\n\n el(\"copy-button\").addEventListener(\"click\", async () => {\n try {\n await navigator.clipboard.writeText(summaryText());\n showToast(t(\"copied\"), { duration: 3000 });\n } catch {\n showToast(summaryText(), { duration: 0 });\n }\n });\n\n el(\"dispatch-button\").addEventListener(\"click\", dispatchSwitch);\n el(\"binance-resume-button\").addEventListener(\"click\", dispatchBinanceResume);\n el(\"logout-button\").addEventListener(\"click\", handleLogout);\n el(\"lang-button\").addEventListener(\"click\", () => {\n state.lang = state.lang === \"zh\" ? \"en\" : \"zh\";\n localStorage.setItem(\"qsl-switch-lang\", state.lang);\n render();\n });\n\n applyStrategyProfiles(defaultStrategyProfiles);\n for (const platform of Object.keys(platformMeta)) syncStrategyForAccount(platform);\n render();\n boot();\n\n async function boot() {\n try {\n await refreshStrategyProfiles();\n await refreshSession();\n } catch {\n state.auth = { available: false, allowed: false, admin: false, login: null };\n clearBinancePrivateScope();\n state.configSource = \"default\";\n state.currentStrategies = {};\n state.bootMessageKey = \"bootTimeout\";\n state.appReady = true;\n render();\n }\n }\n"; diff --git a/web/strategy-switch-console/index.html b/web/strategy-switch-console/index.html index d2eb01a..b8989b5 100644 --- a/web/strategy-switch-console/index.html +++ b/web/strategy-switch-console/index.html @@ -115,11 +115,7 @@

恢复前确认