From 7d183dc73888141339c7074e50313907c1ceb033 Mon Sep 17 00:00:00 2001 From: ogt Date: Fri, 26 Jun 2026 07:43:50 +0800 Subject: [PATCH] fix: hide raw ops terms on governance pages --- config.py | 2 +- docs/AI_INTELLIGENCE_MODULE_SOT.md | 1 + templates/admin/_observability_labels.html | 26 ++++- templates/admin/ai_calls_dashboard.html | 12 +-- templates/cicd_dashboard.html | 106 ++++++++++++-------- templates/vendor_stockout_history_v2.html | 2 +- templates/vendor_stockout_index_v2.html | 2 +- tests/test_frontend_v2_assets.py | 39 ++++++- tests/test_pchome_revenue_growth_service.py | 4 +- web/static/js/observability-charts.js | 6 +- 10 files changed, 137 insertions(+), 63 deletions(-) diff --git a/config.py b/config.py index a9508e9..2ae0c8e 100644 --- a/config.py +++ b/config.py @@ -402,7 +402,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.701" +SYSTEM_VERSION = "V10.702" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docs/AI_INTELLIGENCE_MODULE_SOT.md b/docs/AI_INTELLIGENCE_MODULE_SOT.md index 46bd619..9b5e6c6 100644 --- a/docs/AI_INTELLIGENCE_MODULE_SOT.md +++ b/docs/AI_INTELLIGENCE_MODULE_SOT.md @@ -778,3 +778,4 @@ POSTGRES_HOST=momo-db | 2026-06-25 | 工具頁與簡報頁也必須使用作戰語言;Google Drive token 必須固定到持久化掛載 | V10.699 起簡報預覽、品牌素材、比價、匯入、缺貨與觀測台操作提示移除英文/內部流程字,改成可直接理解的狀態與下一步;正式容器明確指定 `/app/config/google_token.json` 與 `/app/config/google_credentials.json`,背景匯入不得因主機重啟或工作目錄變動而改找瀏覽器授權。 | | 2026-06-26 | 邊角治理頁不得把 raw caller、模型資料或推版代碼當主訊息 | V10.700 起 AI 流量、主機健康、通知模板與缺貨匯入提示再收斂為「使用情境、建議路徑、服務資料、更新摘要、先選擇供應商缺貨檔」等營運語言,避免低頻治理頁回流 `原始`、模型品牌、commit/pipeline 欄位或泛用檔案提示。 | | 2026-06-26 | 靜態資源部署必須保持容器可讀 | V10.701 起部署 SOP 改用 Git 物件打包差異檔,並以測試檢查 `web/static` 檔案可被容器讀取,避免 macOS / iCloud 工作目錄權限造成正式 `/static/*` 500,讓全站 CSS/JS 不再因檔案模式回歸而失效。 | +| 2026-06-26 | 治理頁也要用營運情境語,不得渲染 raw caller、服務代碼或錯誤日誌 | V10.702 起 AI 流量頁把 caller/provider/上下文改成「使用情境、建議路徑、作戰素材」;服務更新監控頁隱藏 branch/sha/error log/pod 名稱等工程細節,改用「更新流程、服務元件、診斷線索」語言;缺貨頁移除英文 Vendor Stockout。 | diff --git a/templates/admin/_observability_labels.html b/templates/admin/_observability_labels.html index aa18aa6..cf70757 100644 --- a/templates/admin/_observability_labels.html +++ b/templates/admin/_observability_labels.html @@ -119,16 +119,36 @@ 'gcp_ollama': '主力建議路徑', 'ollama_secondary': '備援建議路徑', 'ollama_111': '第三建議路徑', - 'nim_via_elephant': 'NIM Elephant', + 'nim_via_elephant': '雲端加速備援', 'gemini': '雲端備援', 'claude': '雲端審查備援', - 'nim': 'NIM', - 'openrouter': 'OpenRouter', + 'nim': '快速雲端建議', + 'openrouter': '外部備援路徑', 'unknown': '未分類供應商' } -%} {%- if value -%}{{ labels.get(value, value|replace('_', ' ')) }}{%- else -%}{{ fallback }}{%- endif -%} {%- endmacro %} +{% macro caller(value, fallback='營運建議流程') -%} + {%- set labels = { + 'hermes_analyst': '業績分析建議', + 'nemotron_dispatch': '深度策略判斷', + 'openclaw_strategist': '作戰策略建議', + 'openclaw': '作戰策略建議', + 'code_review_openclaw': '程式品質審查', + 'pchome_growth': 'PChome 成長判斷', + 'pchome_growth_dashboard': 'PChome 成長儀表板', + 'pchome_price_intelligence': 'PChome 價格情報', + 'price_recommendation': '價格建議', + 'sales_analysis': '業績分析', + 'monthly_summary': '月度結構分析', + 'ai_recommend': '銷售建議', + 'telegram_bot': '通知助理', + 'scheduler': '排程任務' + } -%} + {%- if value -%}{{ labels.get(value, fallback) }}{%- else -%}{{ fallback }}{%- endif -%} +{%- endmacro %} + {% macro source(value, fallback='未分類來源') -%} {%- set labels = { 'ai_insights': 'AI 知識庫', diff --git a/templates/admin/ai_calls_dashboard.html b/templates/admin/ai_calls_dashboard.html index c9e6c4b..cd2498f 100644 --- a/templates/admin/ai_calls_dashboard.html +++ b/templates/admin/ai_calls_dashboard.html @@ -55,10 +55,10 @@

AI 流量控制塔

看成本、錯誤率與知識命中,確保 AI 建議穩定支援業績判斷。

- +
- +
@@ -87,8 +87,8 @@ {% if caller_richness %}
-
呼叫端編排

呼叫端 × 知識與工具編排矩陣

-
{% for c in caller_richness %}{% endfor %}
呼叫端總呼叫知識命中工具編排知識反饋筆數
{{ c.caller }}{{ "{:,}".format(c.total_calls) }}{{ "%.1f"|format(c.rag_hit_rate) }}% ({{ c.rag_hits }}){{ "%.1f"|format(c.mcp_rate) }}%{% if c.feedback_count > 0 %}{{ "%.2f"|format(c.avg_rag_feedback) }}/5{% else %}{% endif %}{{ c.feedback_count }}
+
使用情境

情境 × 知識命中矩陣

+
{% for c in caller_richness %}{% endfor %}
使用情境總次數知識命中工具協作品質回饋筆數
{{ obs_label.caller(c.caller) }}{{ "{:,}".format(c.total_calls) }}{{ "%.1f"|format(c.rag_hit_rate) }}% ({{ c.rag_hits }}){{ "%.1f"|format(c.mcp_rate) }}%{% if c.feedback_count > 0 %}{{ "%.2f"|format(c.avg_rag_feedback) }}/5{% else %}{% endif %}{{ c.feedback_count }}
{% endif %}
@@ -107,9 +107,9 @@ {% if recent_contexts %}
-
AI 上下文

最近上下文

+
建議素材

最近作戰素材

- {% for c in recent_contexts[:5] %}
{{ c.agent_name }} {{ c.context_key }}
{{ c.preview }}{% if c.preview|length >= 120 %}…{% endif %}
{% endfor %} + {% for c in recent_contexts[:5] %}
{{ obs_label.caller(c.agent_name) }}
已納入近期業績判斷素材
{% endfor %}
{% endif %} diff --git a/templates/cicd_dashboard.html b/templates/cicd_dashboard.html index 75ab029..21e8b99 100644 --- a/templates/cicd_dashboard.html +++ b/templates/cicd_dashboard.html @@ -1,6 +1,6 @@ {% extends "ewoooc_base.html" %} -{% block title %}部署監控 - EwoooC{% endblock %} +{% block title %}服務更新監控 - EwoooC{% endblock %} {% block extra_head %} @@ -80,7 +80,7 @@ font-weight: 800; } - /* 部署流程 */ + /* 服務更新流程 */ .pipeline-flow { display: flex; align-items: center; @@ -200,7 +200,7 @@ .pod-status .pod-ready.healthy { background: rgba(40, 167, 69, 0.3); } .pod-status .pod-ready.unhealthy { background: rgba(220, 53, 69, 0.3); } - /* 部署歷史 */ + /* 更新歷史 */ .pipeline-item { display: flex; align-items: center; @@ -473,8 +473,8 @@
-

部署監控

-

PChome 業績成長自動化作戰系統 · 持續整合與部署監控

+

服務更新監控

+

PChome 業績成長自動化作戰系統 · 正式服務更新與可用性監控

@@ -524,11 +524,11 @@
- +
- 最新部署流程 - #-- + 最新更新流程 + 待確認
@@ -564,12 +564,12 @@
@@ -589,7 +589,7 @@
@@ -617,7 +617,7 @@ 診斷
@@ -625,12 +625,12 @@
- +
- 部署歷史 + 更新歷史 - 查看部署紀錄 + 查看更新紀錄
@@ -687,7 +687,7 @@ updateLastUpdate(); } } catch (error) { - console.error('Failed to load dashboard:', error); + console.error('服務更新監控讀取失敗:', error); } } @@ -718,10 +718,10 @@
${issue.type === 'job' ? `${displayStageName(issue.stage)}` : ''} ${issue.type === 'runtime' ? `${issue.environment?.toUpperCase()}` : ''} - ${issue.error ? `
${escapeHtml(issue.error.substring(0, 120))}` : ''} + ${issue.error ? `
已記錄診斷線索` : ''}
${issue.fix_suggestion ? `
💡 ${escapeHtml(issue.fix_suggestion)}
` : ''} - ${issue.error_log ? `
${escapeHtml(issue.error_log.substring(0, 300))}
` : ''} + ${issue.error_log ? `
已保留診斷資料,請由維護者查看。
` : ''}
${issue.auto_fixable ? ` @@ -768,7 +768,7 @@ return; } - pipelineIdEl.textContent = `#${latestPipeline.id}`; + pipelineIdEl.textContent = '最近一次'; // 如果已有 jobs 數據,直接使用 if (latestJobs && latestJobs.length > 0) { @@ -940,8 +940,8 @@ ${!env.healthy && env.error ? `
-
❌ 連線錯誤
-
${escapeHtml(env.error)}
+
❌ 服務連線需確認
+
已記錄診斷線索,請先確認健康檢查與服務狀態。
@@ -949,7 +949,7 @@ ` : ''}
- 執行環境狀態: + 服務元件狀態: ${renderPods(env.pods, envId)}
@@ -963,14 +963,14 @@ // 渲染 runtime 狀態 function renderPods(pods, envId) { if (!pods || pods.length === 0) { - return '

Docker Compose 執行環境;外部叢集資訊不適用

'; + return '

正式服務由主機容器管理,暫無元件明細。

'; } return pods.map(pod => `
- ${pod.name} - ${pod.ready} + ${displayServiceName(pod.name)} + ${pod.healthy ? '正常' : '需確認'} ${pod.age} ${pod.restarts > 0 ? `${pod.restarts} 重啟` : ''} ${!pod.healthy ? `${pod.status}` : ''} @@ -978,12 +978,12 @@ `).join(''); } - // 更新部署歷史 + // 更新歷史 function updatePipelineHistory(pipelines) { const container = document.getElementById('pipelineHistory'); if (!pipelines || pipelines.length === 0) { - container.innerHTML = '

暫無部署流程紀錄

'; + container.innerHTML = '

暫無更新紀錄

'; return; } @@ -992,9 +992,9 @@ html += `
${p.status_icon} - #${p.id} + 更新
-
${p.ref} @ ${p.sha}
+
${displayRefName(p.ref)}
${formatTime(p.created_at)} ${p.duration ? `• ${p.duration}` : ''}
@@ -1014,9 +1014,9 @@ el.textContent = `最後更新: ${now.toLocaleTimeString('zh-TW')}`; } - // 觸發部署 + // 觸發服務更新 async function triggerDeploy(env) { - if (!confirm(`確定要觸發 ${env.toUpperCase()} 部署嗎?`)) return; + if (!confirm(`確定要更新${displayEnvName(env)}嗎?`)) return; try { const response = await fetch('/api/cicd/deploy', { @@ -1032,13 +1032,13 @@ setTimeout(loadDashboard, 2000); } } catch (error) { - showNotification('錯誤', '無法觸發部署'); + showNotification('錯誤', '無法啟動服務更新'); } } // 觸發回滾 async function triggerRollback(env) { - if (!confirm(`確定要回滾 ${env.toUpperCase()} 嗎?這將恢復到上一個版本。`)) return; + if (!confirm(`確定要回復${displayEnvName(env)}到上一個版本嗎?`)) return; try { const response = await fetch('/api/cicd/rollback', { @@ -1074,9 +1074,9 @@ // 自動修復 async function triggerAutoFix(action, env) { - if (!confirm(`確定要執行自動修復 (${action}) 嗎?`)) return; + if (!confirm(`確定要執行服務修復嗎?`)) return; - showNotification('執行中', `正在執行 ${action}...`); + showNotification('執行中', '正在執行服務修復...'); try { const response = await fetch('/api/cicd/auto-fix', { @@ -1094,11 +1094,11 @@ showNotification('❌ 修復失敗', data.error, true); } } catch (error) { - showNotification('❌ 錯誤', '無法執行自動修復: ' + error, true); + showNotification('❌ 錯誤', '無法執行自動修復', true); } } - // 部署修復 + // 服務修復 async function triggerFullRepair() { const env = prompt('請輸入要修復的環境 (uat 或 prod):', 'uat'); if (!env || !['uat', 'prod'].includes(env)) { @@ -1106,9 +1106,9 @@ return; } - if (!confirm(`確定要對 ${env.toUpperCase()} 執行部署修復嗎?\n這會執行必要服務修復與環境診斷。`)) return; + if (!confirm(`確定要對${displayEnvName(env)}執行服務修復嗎?\n這會執行必要服務修復與環境診斷。`)) return; - showNotification('執行中', '正在修復部署狀態...'); + showNotification('執行中', '正在修復服務狀態...'); try { const response = await fetch('/api/cicd/auto-fix', { @@ -1120,13 +1120,13 @@ const data = await response.json(); if (data.success) { - showNotification('✅ 部署修復完成', `已執行 ${data.results?.length || 0} 個修復動作`); + showNotification('✅ 服務修復完成', `已執行 ${data.results?.length || 0} 個修復動作`); setTimeout(loadDashboard, 5000); } else { showNotification('❌ 修復失敗', data.error, true); } } catch (error) { - showNotification('❌ 錯誤', '無法執行部署修復: ' + error, true); + showNotification('❌ 錯誤', '無法執行服務修復', true); } } @@ -1138,7 +1138,7 @@ return; } - showNotification('執行中', `正在診斷 ${env.toUpperCase()} 環境...`); + showNotification('執行中', `正在診斷${displayEnvName(env)}...`); try { const response = await fetch('/api/cicd/diagnose', { @@ -1171,7 +1171,7 @@ showNotification('❌ 診斷失敗', data.error, true); } } catch (error) { - showNotification('❌ 錯誤', '無法執行診斷: ' + error, true); + showNotification('❌ 錯誤', '無法執行診斷', true); } } @@ -1194,6 +1194,26 @@ return labels[stage] || stage || '未分類'; } + function displayEnvName(env) { + const labels = { uat: '測試站', prod: '正式站' }; + return labels[env] || '指定環境'; + } + + function displayRefName(ref) { + const labels = { main: '正式版更新', master: '正式版更新', dev: '測試版更新', uat: '測試版更新', prod: '正式版更新' }; + return labels[ref] || '服務更新'; + } + + function displayServiceName(name) { + const labels = { + 'momo-pro-system': '主系統', + 'momo-scheduler': '排程與匯入', + 'momo-telegram-bot': '通知服務', + 'momo-db': '資料服務' + }; + return labels[name] || '服務元件'; + } + function displayStatusText(status) { const labels = { ok: '正常', diff --git a/templates/vendor_stockout_history_v2.html b/templates/vendor_stockout_history_v2.html index 0576fe2..8eff8c7 100644 --- a/templates/vendor_stockout_history_v2.html +++ b/templates/vendor_stockout_history_v2.html @@ -8,7 +8,7 @@
- Vendor Stockout + 供貨風險

發送歷史

回看缺貨處理紀錄,找出需要補救的供貨風險。

diff --git a/templates/vendor_stockout_index_v2.html b/templates/vendor_stockout_index_v2.html index fab1bd5..f35505c 100644 --- a/templates/vendor_stockout_index_v2.html +++ b/templates/vendor_stockout_index_v2.html @@ -14,7 +14,7 @@
- VENDOR STOCKOUT + 供貨風險

廠商缺貨

diff --git a/tests/test_frontend_v2_assets.py b/tests/test_frontend_v2_assets.py index ce419c0..80f9e45 100644 --- a/tests/test_frontend_v2_assets.py +++ b/tests/test_frontend_v2_assets.py @@ -80,8 +80,8 @@ def test_high_visibility_pages_use_traditional_chinese_labels(): assert "工作隊列" in combined assert "覆蓋率流程" in combined assert "同步部署" in combined - assert "部署監控" in combined - assert "最新部署流程" in combined + assert "服務更新監控" in combined + assert "最新更新流程" in combined assert "執行環境正常" in combined assert "視覺檢查" in combined @@ -617,10 +617,27 @@ def test_utility_pages_keep_operator_copy_professional(): auto_import = (ROOT / "templates/auto_import_index.html").read_text(encoding="utf-8") stockout_import = (ROOT / "templates/vendor_stockout_import_v2.html").read_text(encoding="utf-8") vendor_import_js = (ROOT / "web/static/js/page-vendor-import.js").read_text(encoding="utf-8") + stockout_index = (ROOT / "templates/vendor_stockout_index_v2.html").read_text(encoding="utf-8") + stockout_history = (ROOT / "templates/vendor_stockout_history_v2.html").read_text(encoding="utf-8") ai_calls = (ROOT / "templates/admin/ai_calls_dashboard.html").read_text(encoding="utf-8") + observability_labels = (ROOT / "templates/admin/_observability_labels.html").read_text(encoding="utf-8") host_health = (ROOT / "templates/admin/host_health.html").read_text(encoding="utf-8") + cicd_dashboard = (ROOT / "templates/cicd_dashboard.html").read_text(encoding="utf-8") observability_js = (ROOT / "web/static/js/observability-charts.js").read_text(encoding="utf-8") - combined = "\n".join([ppt_history, ppt_preview, auto_import, stockout_import, vendor_import_js, ai_calls, host_health, observability_js]) + combined = "\n".join([ + ppt_history, + ppt_preview, + auto_import, + stockout_import, + vendor_import_js, + stockout_index, + stockout_history, + ai_calls, + observability_labels, + host_health, + cicd_dashboard, + observability_js, + ]) assert "簡報線上預覽" in ppt_preview assert "下載簡報檔" in ppt_history @@ -628,6 +645,11 @@ def test_utility_pages_keep_operator_copy_professional(): assert "缺少必要資料時,會先停止匯入" in stockout_import assert "先選擇供應商缺貨 Excel 檔。" in vendor_import_js assert "使用情境" in ai_calls + assert "全部使用情境" in ai_calls + assert "情境 × 知識命中矩陣" in ai_calls + assert "服務更新監控" in cicd_dashboard + assert "正式服務更新與可用性監控" in cicd_dashboard + assert "供貨風險" in stockout_index assert "無服務資料 / 未連線" in host_health assert "部署檢查已排入背景處理" in observability_js @@ -638,6 +660,17 @@ def test_utility_pages_keep_operator_copy_professional(): "原始:", "無模型資料", "請選擇 Excel 檔案", + "Vendor Stockout", + "VENDOR STOCKOUT", + "全部呼叫端", + "呼叫端 ×", + "{{ c.caller }}", + "NIM Elephant", + "OpenRouter", + "GitLab 部署紀錄", + "${p.ref} @ ${p.sha}", + "error_log.substring", + "${escapeHtml(env.error)}", "系統會去重", "系統會拒絕", "管線 ID", diff --git a/tests/test_pchome_revenue_growth_service.py b/tests/test_pchome_revenue_growth_service.py index d0f2ed7..ebc2ec8 100644 --- a/tests/test_pchome_revenue_growth_service.py +++ b/tests/test_pchome_revenue_growth_service.py @@ -905,9 +905,9 @@ def test_visible_operations_pages_hide_internal_runtime_terms(): "templates/vendor_stockout_import_v2.html": ["會先停止匯入", "處理缺貨清單"], "templates/admin/ppt_audit_history.html": ["產出紀錄", "最近產出", "保存紀錄"], "templates/admin/agent_orchestration.html": ["AI 分工指揮台", "建議路徑、工具與知識命中矩陣", "工具服務明細"], - "templates/admin/ai_calls_dashboard.html": ["用量", "AI 上下文", "知識與工具編排矩陣"], + "templates/admin/ai_calls_dashboard.html": ["用量", "最近作戰素材", "情境 × 知識命中矩陣"], "templates/admin/observability_overview.html": ["用量", "知識與工具矩陣"], - "templates/cicd_dashboard.html": ["部署流程", "部署歷史", "修復部署", "查看部署紀錄"], + "templates/cicd_dashboard.html": ["最新更新流程", "更新歷史", "修復服務", "查看更新紀錄"], } forbidden_by_path = { "templates/ai_recommend.html": ["權杖:", "AI 模型", "分析模型", "AI 路徑", "Gemini 備援", "Ollama 主路徑"], diff --git a/web/static/js/observability-charts.js b/web/static/js/observability-charts.js index 993579f..c11623e 100644 --- a/web/static/js/observability-charts.js +++ b/web/static/js/observability-charts.js @@ -11,9 +11,9 @@ ollama_111: '第三建議路徑', gemini: '雲端備援', claude: 'Claude', - nim: 'NIM', - openrouter: 'OpenRouter', - nim_via_elephant: 'NIM Elephant' + nim: '快速雲端建議', + openrouter: '外部備援路徑', + nim_via_elephant: '雲端加速備援' }; function readJson(id, fallback) {