style(obs): compact observability 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_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。
|
||||
- V10.644 起 `/ai_intelligence` 的商品明細列不得只用句子描述比價;每列必須顯示 PChome 價格、MOMO 參考價、差距、可信度四格價格證據,並保留下一步按鈕。單位價候選需顯示單位價與單位,候選待確認或缺資料則以「待補 / 候選待確認」呈現,不得捏造價格。
|
||||
- V10.645 起 `/ai_intelligence` 的商品明細分流切換後,必須顯示「這類商品怎麼處理」的行動摘要,包含件數、近 7 天業績、平均可信度、最大價差、代表商品與主按鈕;使用者不得只能看到商品列表而不知道下一步。
|
||||
- V10.646 起 `/ai_intelligence` 的商品明細必須提供搜尋與排序;搜尋至少涵蓋商品、分類、商品編號與 MOMO 候選資訊,排序至少支援優先級、近 7 天業績、價差、下滑幅度與可信度。搜尋/排序後的行動摘要與明細列表必須使用同一批結果。
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
## P1 - Product Visibility And Professional Website Experience
|
||||
|
||||
狀態: 進行中,本輪已完成 `/ai_intelligence` 密集 AI 工作台文字密度守門。
|
||||
狀態: 進行中,本輪已完成 `/ai_intelligence` 與 `/observability/overview` 密集 AI 工作台文字密度守門。
|
||||
|
||||
目的: 讓 AI 自動化在產品裡可見,成為專業營運工作流,而不是只藏在後端。
|
||||
|
||||
@@ -124,6 +124,10 @@
|
||||
- 首屏改成 `data-density-guardrail="compact-ai-workbench"`,以「AI 作戰 / 證據優先 / 下一步」短標籤取代長說明。
|
||||
- KPI note、benchmark detail、alert 副句、mini-card 說明、策略 note、decision copy、來源長句與單品 reason list 從可見 UI 退場。
|
||||
- `tests/test_ai_intelligence_text_density_guardrails.py` 已鎖住短任務文案、detail meta 與 explanatory copy hidden contract。
|
||||
- `/observability/overview` 密集 AI 觀測工作台文字密度 guard 已完成:
|
||||
- 首屏改成 `data-density-guardrail="compact-observability-workbench"`,以「AI 觀測 / 風險優先 / 下一步」短標籤承接 golden signals。
|
||||
- hero lede、signal note、route desc、host meta 與資料來源長句從可見 UI 退場,保留狀態、數字與子頁入口。
|
||||
- `tests/test_observability_text_density_guardrails.py` 已鎖住 compact marker、第一層狀態數字與 explanatory copy hidden contract。
|
||||
|
||||
已完成 / 下一步,必須照順序:
|
||||
|
||||
@@ -244,6 +248,7 @@
|
||||
| P1.2 | UI wording guard for no raw engineering terms | 已完成 | focused wording guard test | P2.1 benchmark guardrails |
|
||||
| P1.3 | AI intelligence product evidence guardrails | 已完成 | detail rows + single product detail expose four evidence cells + focused guard tests | P2 / P3 automation surfaces |
|
||||
| P1.4 | AI intelligence compact workbench text-density guardrails | 已完成 | `/ai_intelligence` first viewport and drilldown hide explanatory copy; focused density guard test | P2.2 benchmark guardrails and future AI surfaces |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
||||
@@ -75,11 +75,27 @@
|
||||
}
|
||||
|
||||
.obs-lede {
|
||||
max-width: 760px;
|
||||
margin: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.obs-mode {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.45rem;
|
||||
margin-top: 0.7rem;
|
||||
}
|
||||
|
||||
.obs-mode span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
border: 1px solid rgba(86, 64, 48, 0.12);
|
||||
border-radius: 999px;
|
||||
background: var(--momo-bg-elevated, #fdfaf3);
|
||||
color: var(--obs-muted);
|
||||
font-size: var(--momo-text-body, 0.875rem);
|
||||
line-height: 1.75;
|
||||
font-size: 0.68rem;
|
||||
font-weight: 900;
|
||||
padding: 0.24rem 0.55rem;
|
||||
}
|
||||
|
||||
.obs-command-strip,
|
||||
@@ -93,7 +109,7 @@
|
||||
.obs-signal {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
min-height: 104px;
|
||||
min-height: 78px;
|
||||
padding: 0.92rem;
|
||||
border: 1px solid var(--obs-line);
|
||||
border-radius: var(--momo-radius-lg, 8px);
|
||||
@@ -120,9 +136,7 @@
|
||||
}
|
||||
|
||||
.obs-signal-note {
|
||||
margin-top: 0.25rem;
|
||||
color: var(--obs-muted);
|
||||
font-size: 0.82rem;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.obs-grid {
|
||||
@@ -202,6 +216,11 @@
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.obs-host-meta,
|
||||
.obs-footer-source {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.obs-sparkline {
|
||||
height: 54px;
|
||||
}
|
||||
@@ -368,11 +387,7 @@
|
||||
}
|
||||
|
||||
.obs-route-desc {
|
||||
display: block;
|
||||
margin-top: 0.08rem;
|
||||
color: var(--obs-muted);
|
||||
font-size: 0.76rem;
|
||||
line-height: 1.45;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.obs-empty {
|
||||
@@ -421,9 +436,14 @@
|
||||
{% set risk_count = (summary.budget_alerts|length if summary.budget_alerts else 0) + host_bad.value + (1 if ai and ai.error_rate >= 15 else 0) + (1 if summary.episodes and summary.episodes.pending > 0 else 0) %}
|
||||
|
||||
<div class="obs-war-room">
|
||||
<section class="obs-hero">
|
||||
<section class="obs-hero" data-density-guardrail="compact-observability-workbench">
|
||||
<span class="obs-kicker"><i class="fas fa-satellite-dish"></i> 01 指揮總覽 <span class="obs-kicker-date">· {{ today }}</span></span>
|
||||
<h1 class="obs-title">AI 觀測戰情室</h1>
|
||||
<div class="obs-mode" aria-label="AI 觀測模式">
|
||||
<span>AI 觀測</span>
|
||||
<span>風險優先</span>
|
||||
<span>下一步</span>
|
||||
</div>
|
||||
<p class="obs-lede">
|
||||
私有 AI 中樞的第一入口:模型主機、AI 呼叫、知識學習、工具編排、自癒、預算與 PPT 視覺審核收斂到同一張工作台。所有數字只讀正式資料來源;缺資料時呈現可診斷空狀態。
|
||||
</p>
|
||||
@@ -645,7 +665,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p class="obs-microcopy mt-3">
|
||||
<p class="obs-microcopy obs-footer-source mt-3">
|
||||
<i class="fas fa-database me-1"></i>
|
||||
資料來源:主機探測、AI 呼叫、預算、學習事件、知識查詢、工具呼叫、事件與自癒、PPT 審核。
|
||||
</p>
|
||||
|
||||
67
tests/test_observability_text_density_guardrails.py
Normal file
67
tests/test_observability_text_density_guardrails.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def _template() -> str:
|
||||
return (ROOT / "templates/admin/observability_overview.html").read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _any_css_block_has(template: str, selector: str, expected: str) -> bool:
|
||||
marker = f"{selector} {{"
|
||||
assert marker in template
|
||||
return any(expected in block.split("}", 1)[0] for block in template.split(marker)[1:])
|
||||
|
||||
|
||||
def test_observability_overview_first_viewport_is_compact_workbench():
|
||||
template = _template()
|
||||
hero = template.split('<section class="obs-hero"', 1)[1].split(
|
||||
'<section class="obs-grid">',
|
||||
1,
|
||||
)[0]
|
||||
|
||||
assert 'data-density-guardrail="compact-observability-workbench"' in hero
|
||||
assert 'aria-label="AI 觀測模式"' in hero
|
||||
assert "AI 觀測" in hero
|
||||
assert "風險優先" in hero
|
||||
assert "下一步" in hero
|
||||
assert 'aria-label="AI 自動化狀態"' in hero
|
||||
assert 'data-benchmark-guardrail="golden-signals"' in hero
|
||||
|
||||
|
||||
def test_observability_overview_hides_explanatory_copy_layers():
|
||||
template = _template()
|
||||
hidden_selectors = [
|
||||
".obs-lede",
|
||||
".obs-signal-note",
|
||||
".obs-host-meta,\n .obs-footer-source",
|
||||
".obs-route-desc",
|
||||
]
|
||||
|
||||
for selector in hidden_selectors:
|
||||
assert _any_css_block_has(template, selector, "display: none")
|
||||
|
||||
|
||||
def test_observability_overview_keeps_first_layer_to_status_numbers_and_actions():
|
||||
template = _template()
|
||||
hero = template.split('<section class="obs-hero"', 1)[1].split(
|
||||
'<section class="obs-grid">',
|
||||
1,
|
||||
)[0]
|
||||
|
||||
for marker in ["即時風險", "24 小時呼叫", "成本水位", "知識命中率"]:
|
||||
assert marker in hero
|
||||
|
||||
for long_copy in [
|
||||
"私有 AI 中樞的第一入口",
|
||||
"主機探測、AI 呼叫、自癒、預算與品質訊號已進總覽",
|
||||
"以正式資料回讀主機健康、錯誤率、成本與知識命中",
|
||||
"即時風險分層;詳細事件保留在各子頁",
|
||||
"持續觀察健康、成本與自癒訊號",
|
||||
]:
|
||||
assert long_copy in template
|
||||
assert long_copy in hero
|
||||
|
||||
assert "display: none" in template.split(".obs-signal-note {", 1)[1].split("}", 1)[0]
|
||||
assert "display: none" in template.split(".obs-lede {", 1)[1].split("}", 1)[0]
|
||||
Reference in New Issue
Block a user