style(obs): compact ai calls workbench copy
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
This commit is contained in:
@@ -99,6 +99,7 @@
|
||||
- 2026-07-02 起 `/ai_intelligence` 與 `/observability/overview` 必須同樣套用 AI automation benchmark golden signals:首屏需有 `AI 自動化狀態` 區塊,直接顯示「已自動落地、已驗證、異動狀態、下一步」。`/ai_intelligence` 需以 `/api/ai/pchome-growth/ai-automation-surface-summary` 只讀更新首屏,該 endpoint 由 `/api/ai/pchome-growth/ai-automation-readiness` 聚合 safe lanes 後輸出 `golden_signals`、`safe_automation_lanes`、`surface_contract`、`primary_human_gate_count=0`、`writes_database_count=0` 與 `next_machine_action`;`/observability/overview` 需用正式觀測資料分層呈現風險與下一步。raw endpoint、artifact、DB table、manual/human gate 文字不得進首屏訊號。
|
||||
- 2026-07-02 起 `/ai_automation_smoke` 也必須採密集 AI 巡檢工作台:首屏使用 `data-density-guardrail="compact-smoke-workbench"`,以「AI 巡檢、風險優先、推播摘要」短標籤保留狀態模式;重複說明、趨勢教學與診斷細節提示必須退到 hidden contract,畫面第一層只保留狀態、數字、趨勢、每日摘要與檢查項目 summary。
|
||||
- 2026-07-02 起 `/observability/agent_orchestration` 必須採密集 AI Agent 工作台:首屏使用 `data-density-guardrail="compact-agent-workbench"`,以「AI 分工、成本守門、知識命中」短標籤承接分工狀態;hero 說明、KPI 小註、列內描述、卡片描述與頁尾重複標題不得佔用第一層視覺,畫面先保留呼叫總量、主力路徑占比、付費成本、知識命中率、分工矩陣與工具協作表。
|
||||
- 2026-07-02 起 `/observability/ai_calls` 必須採密集 AI 流量工作台:首屏使用 `data-density-guardrail="compact-ai-calls-workbench"`,以「流量監控、成本守門、知識命中」短標籤承接 AI 呼叫狀態;hero 說明、KPI 小註、素材說明與頁尾重複標題不得佔用第一層視覺,畫面先保留呼叫總量、用量、成本、延遲、知識命中、錯誤、情境矩陣與最近呼叫。
|
||||
- 2026-07-02 起 `/ai_intelligence` 商品明細與單品作戰詳情的四格價格證據必須可測:PChome 價格、MOMO 參考價、差距、可信度需以 `data-evidence` 固定,並以 `aria-label="價格證據"` 對應可掃描區塊;候選待確認或缺資料只能顯示「候選待確認 / 待補」,不得捏造價格或讓使用者打開 raw payload 才知道判斷依據。
|
||||
- 2026-07-02 起 `/ai_intelligence` 必須是密集 AI 工作台,不得退回大段文字說明頁:首屏與明細可見內容只保留短狀態、數字、四格證據與下一步按鈕;KPI note、benchmark detail、alert 副句、策略說明、decision copy、來源長句與單品 reason list 不得佔用第一層視覺。`tests/test_ai_intelligence_text_density_guardrails.py` 必須鎖住 `data-density-guardrail="compact-ai-workbench"`、短任務文案、detail meta 與 hidden explanatory copy。
|
||||
- 2026-07-02 起 `/observability/overview` 也必須採密集 AI 觀測工作台:首屏以 `data-density-guardrail="compact-observability-workbench"`、`AI 觀測 / 風險優先 / 下一步` 與 golden signals 先呈現狀態、數字與操作入口;hero lede、signal note、route desc、host meta 與資料來源長句不得佔用第一層視覺。`tests/test_observability_text_density_guardrails.py` 必須鎖住 compact marker 與 hidden explanatory copy。
|
||||
|
||||
@@ -73,6 +73,7 @@ Baymard 的商品頁與比較 UX 研究強調:使用者需要清楚的 product
|
||||
- Dashboard-as-code: benchmark 結論必須進 tests;`tests/test_pchome_dashboard_benchmark_guardrails.py` 是 PChome AI dashboard benchmark guard。
|
||||
- Surface rollout: `/ai_intelligence` 與 `/observability/overview` 已套用相同 golden-signal guardrails;`tests/test_ai_surface_benchmark_guardrails.py` 鎖住兩頁首屏的狀態分層、下一步優先與 evidence-on-demand 語言。
|
||||
- AI Agent surface rollout: `/observability/agent_orchestration` 已套用 compact Agent workbench guardrails;`tests/test_agent_orchestration_text_density_guardrails.py` 鎖住首屏短標籤、核心訊號與 hidden explanatory copy。
|
||||
- AI traffic surface rollout: `/observability/ai_calls` 已套用 compact AI traffic workbench guardrails;`tests/test_ai_calls_text_density_guardrails.py` 鎖住首屏短標籤、成本/錯誤/知識核心訊號與 hidden explanatory copy。
|
||||
|
||||
## 下一步 TODO 候選
|
||||
|
||||
@@ -84,6 +85,7 @@ Baymard 的商品頁與比較 UX 研究強調:使用者需要清楚的 product
|
||||
- 已完成: `/api/ai/pchome-growth/ai-automation-surface-summary` 以 `golden_signals` 固化「已自動落地、已驗證、異動狀態、下一步」。
|
||||
- 已完成: `/ai_intelligence` 首屏直接消費 surface summary,raw receipt / hash / DB table / endpoint 細節留在 evidence-on-demand 層。
|
||||
- 已完成: `/observability/agent_orchestration` 首屏以「AI 分工 / 成本守門 / 知識命中」短標籤與四個核心數字呈現 Agent 編排狀態。
|
||||
- 已完成: `/observability/ai_calls` 首屏以「流量監控 / 成本守門 / 知識命中」短標籤與六個核心數字呈現 AI 呼叫、成本、錯誤與知識狀態。
|
||||
|
||||
## 參考來源
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
## P1 - Product Visibility And Professional Website Experience
|
||||
|
||||
狀態: 進行中,本輪已完成 `/ai_intelligence`、`/observability/overview`、`/ai_automation_smoke` 與 `/observability/agent_orchestration` 密集 AI 工作台文字密度守門。
|
||||
狀態: 進行中,本輪已完成 `/ai_intelligence`、`/observability/overview`、`/ai_automation_smoke`、`/observability/agent_orchestration` 與 `/observability/ai_calls` 密集 AI 工作台文字密度守門。
|
||||
|
||||
目的: 讓 AI 自動化在產品裡可見,成為專業營運工作流,而不是只藏在後端。
|
||||
|
||||
@@ -136,6 +136,10 @@
|
||||
- 首屏改成 `data-density-guardrail="compact-agent-workbench"`,以「AI 分工 / 成本守門 / 知識命中」短標籤承接 Agent 編排狀態。
|
||||
- hero 說明、KPI 小註、列內描述、卡片描述與頁尾重複標題從可見 UI 退場,保留呼叫總量、主力路徑、付費成本、知識命中、分工矩陣與工具協作表。
|
||||
- `tests/test_agent_orchestration_text_density_guardrails.py` 已鎖住 compact marker、第一層狀態數字與 explanatory copy hidden contract。
|
||||
- `/observability/ai_calls` 密集 AI 流量工作台文字密度 guard 已完成:
|
||||
- 首屏改成 `data-density-guardrail="compact-ai-calls-workbench"`,以「流量監控 / 成本守門 / 知識命中」短標籤承接 AI 呼叫狀態。
|
||||
- hero 說明、KPI 小註、素材說明與頁尾重複標題從可見 UI 退場,保留呼叫總量、用量、成本、延遲、知識命中、錯誤、情境矩陣與最近呼叫。
|
||||
- `tests/test_ai_calls_text_density_guardrails.py` 已鎖住 compact marker、第一層狀態數字與 explanatory copy hidden contract。
|
||||
|
||||
已完成 / 下一步,必須照順序:
|
||||
|
||||
@@ -259,6 +263,7 @@
|
||||
| P1.5 | Observability compact workbench text-density guardrails | 已完成 | `/observability/overview` first viewport hides explanatory copy; focused density guard test | Apply density guard to remaining high-visibility AI surfaces |
|
||||
| P1.6 | AI automation smoke compact workbench text-density guardrails | 已完成 | `/ai_automation_smoke` first viewport hides explanatory copy; focused density guard test | Apply density guard to remaining high-visibility AI surfaces |
|
||||
| P1.7 | Agent orchestration compact workbench text-density guardrails | 已完成 | `/observability/agent_orchestration` first viewport hides explanatory copy; focused density guard test | Apply density guard to remaining high-visibility AI surfaces |
|
||||
| P1.8 | AI calls compact workbench text-density guardrails | 已完成 | `/observability/ai_calls` first viewport hides explanatory copy; focused density guard test | Apply density guard to remaining high-visibility AI surfaces |
|
||||
| P2.1 | External benchmark encoded into requirements | 已完成 | benchmark guide + focused guard test + first-viewport status | P3.1 safe lane expansion |
|
||||
| P3.1 | Extend receipt / replay / drift pattern to more lanes | 已完成 | direct mapping candidate decision lane closeout route + focused tests | P3.2 scheduled automation health summaries |
|
||||
| P3.2 | Scheduled automation health summaries | 已完成 | `/api/ai-automation/scheduled-health-summary` + smoke service focused tests | P3.3 rollback evidence packages |
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
.calls-kicker { color: var(--obs-accent); font-size:.76rem; letter-spacing:.13em; text-transform:uppercase; font-weight:800; }
|
||||
.calls-title { margin:.45rem 0 .25rem; font-family: var(--momo-font-display, "Inter", "Noto Sans TC", system-ui, sans-serif); font-size:var(--obs-title-size); letter-spacing: 0; line-height:.98; }
|
||||
.calls-subtitle { color:var(--obs-muted); max-width:830px; line-height:1.7; }
|
||||
.calls-mode-row { display:flex; flex-wrap:wrap; gap:.5rem; margin-top:.75rem; }
|
||||
.calls-mode { display:inline-flex; align-items:center; min-height:28px; padding:.32rem .65rem; border:1px solid var(--obs-line); border-radius:10px; background:rgba(255,255,255,.62); color:var(--obs-muted); font-size:.74rem; font-weight:850; white-space:nowrap; }
|
||||
.calls-subtitle, .calls-note, .calls-context-note, .calls-footer-copy { display:none; }
|
||||
.calls-actions { display:flex; flex-wrap:wrap; gap:.6rem; margin-top:1rem; align-items:center; }
|
||||
.calls-filter { display:flex; flex-wrap:wrap; gap:.5rem; padding:.8rem; border:1px solid var(--obs-line); border-radius:20px; background:rgba(255,255,255,.58); }
|
||||
.calls-command { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:.75rem; margin-top:1rem; }
|
||||
@@ -50,9 +53,10 @@
|
||||
{% set avg_tokens = ((summary.total_tokens or 0) // (total or 1)) %}
|
||||
|
||||
<div class="container-fluid mt-3">
|
||||
<section class="calls-hero">
|
||||
<section class="calls-hero" data-density-guardrail="compact-ai-calls-workbench">
|
||||
<div class="calls-kicker"><i class="fas fa-chart-bar me-1"></i> AI 流量管制 · {{ hours }} 小時視窗</div>
|
||||
<h1 class="calls-title">AI 流量控制塔</h1>
|
||||
<div class="calls-mode-row" aria-label="AI 流量狀態模式"><span class="calls-mode">流量監控</span><span class="calls-mode">成本守門</span><span class="calls-mode">知識命中</span></div>
|
||||
<p class="calls-subtitle">看成本、錯誤率與知識命中,確保 AI 建議穩定支援業績判斷。</p>
|
||||
<div class="calls-actions">
|
||||
<button class="btn btn-warning btn-sm" onclick="triggerCodeReview()"><i class="fas fa-microscope me-1"></i>啟動品質審查</button>
|
||||
@@ -107,7 +111,7 @@
|
||||
<article class="calls-panel">
|
||||
<div class="calls-panel-head"><div><div class="calls-label">建議素材</div><h2 class="calls-panel-title">最近作戰素材</h2></div></div>
|
||||
<div class="calls-panel-body">
|
||||
{% for c in recent_contexts[:5] %}<div class="mb-2 pb-2 border-bottom"><span class="badge bg-info">{{ obs_label.caller(c.agent_name) }}</span><div class="text-muted small mt-1">已納入近期業績判斷素材</div></div>{% endfor %}
|
||||
{% for c in recent_contexts[:5] %}<div class="mb-2 pb-2 border-bottom"><span class="badge bg-info">{{ obs_label.caller(c.agent_name) }}</span><div class="text-muted small mt-1 calls-context-note">已納入近期業績判斷素材</div></div>{% endfor %}
|
||||
</div>
|
||||
</article>
|
||||
{% endif %}
|
||||
@@ -126,7 +130,7 @@
|
||||
<div class="table-responsive"><table class="table table-sm table-striped mb-0"><thead class="table-light"><tr><th>編號</th><th>時間</th><th>使用情境</th><th>建議路徑</th><th class="text-end">輸入</th><th class="text-end">輸出</th><th class="text-end">耗時</th><th>狀態</th><th class="text-end">成本</th><th>標記</th></tr></thead><tbody>{% for r in recent %}<tr {% if r.status not in ['ok','cache_only'] %}class="table-warning"{% endif %}><td>{{ r.id }}</td><td><small>{{ r.called_at }}</small></td><td><span>{{ r.caller_display or '營運建議流程' }}</span></td><td><small>{{ obs_label.provider(r.provider) }}</small></td><td class="text-end">{{ r.in_tokens }}</td><td class="text-end">{{ r.out_tokens }}</td><td class="text-end">{{ r.duration_ms }}</td><td><small>{{ obs_label.status(r.status, '-') }}</small></td><td class="text-end">${{ "%.4f"|format(r.cost) }}</td><td>{% for badge in r.route_badges %}<span class="badge bg-secondary me-1">{{ badge }}</span>{% endfor %}{% if r.cache_hit %}<span class="badge bg-success">快取</span>{% endif %}{% if r.rag_hit %}<span class="badge bg-info">知識命中</span>{% endif %}</td></tr>{% endfor %}</tbody></table></div>
|
||||
</section>
|
||||
|
||||
<p class="text-muted mt-3"><small><i class="fas fa-robot me-1"></i>AI 流量控制塔</small></p>
|
||||
<p class="text-muted mt-3 calls-footer-copy"><small><i class="fas fa-robot me-1"></i>AI 流量控制塔</small></p>
|
||||
</div>
|
||||
|
||||
{% set ai_calls_payload = {
|
||||
|
||||
37
tests/test_ai_calls_text_density_guardrails.py
Normal file
37
tests/test_ai_calls_text_density_guardrails.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def test_ai_calls_uses_compact_workbench_contract():
|
||||
template = (ROOT / "templates/admin/ai_calls_dashboard.html").read_text(encoding="utf-8")
|
||||
|
||||
assert 'data-density-guardrail="compact-ai-calls-workbench"' in template
|
||||
assert 'aria-label="AI 流量狀態模式"' in template
|
||||
assert "流量監控" in template
|
||||
assert "成本守門" in template
|
||||
assert "知識命中" in template
|
||||
|
||||
|
||||
def test_ai_calls_keeps_core_signals_and_hides_explanatory_copy():
|
||||
template = (ROOT / "templates/admin/ai_calls_dashboard.html").read_text(encoding="utf-8")
|
||||
|
||||
for marker in ["呼叫總量", "用量", "成本", "延遲", "知識命中", "錯誤"]:
|
||||
assert marker in template
|
||||
|
||||
assert ".calls-subtitle, .calls-note, .calls-context-note, .calls-footer-copy { display:none; }" in template
|
||||
assert 'class="calls-subtitle"' in template
|
||||
assert 'class="calls-note"' in template
|
||||
assert "calls-context-note" in template
|
||||
assert "calls-footer-copy" in template
|
||||
|
||||
|
||||
def test_ai_calls_preserves_workbench_tables_and_non_raw_wording():
|
||||
template = (ROOT / "templates/admin/ai_calls_dashboard.html").read_text(encoding="utf-8")
|
||||
|
||||
for marker in ["情境 × 知識命中矩陣", "最近作戰素材", "最近呼叫 100 筆"]:
|
||||
assert marker in template
|
||||
|
||||
for forbidden in ["權杖量", "權杖/次", ">權杖<", "Agent 上下文", "RAG × MCP"]:
|
||||
assert forbidden not in template
|
||||
Reference in New Issue
Block a user