diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 69f8e17a1..877b1e9a3 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -2159,23 +2159,40 @@ "title": "知識殿堂", "searchPlaceholder": "搜尋知識條目...", "allCategories": "全部", + "rail": { + "categoryTitle": "動態分類", + "total": "總 KM", + "aiExtracted": "AI 萃取", + "controlledQueue": "受控隊列", + "ragChunks": "RAG chunks" + }, + "assetLens": { + "title": "資產維度", + "scope": "目前列表", + "project": "專案", + "product": "產品", + "website": "網站", + "service": "服務", + "package": "套件", + "tool": "工具" + }, "dataChain": { "errorTitle": "知識條目資料鏈路異常", - "errorDescription": "主知識條目 API 未成功回應:{reason}。下方治理軌道仍會顯示 Hermes owner-review 與陳舊 KM 狀態,避免誤判成知識庫真的歸零。", + "errorDescription": "主知識條目 API 未成功回應:{reason}。下方治理軌道仍會顯示 Hermes 受控覆核與陳舊 KM 狀態,避免誤判成知識庫真的歸零。", "retry": "重新讀取" }, "decision": { "badge": "KM 治理警戒", - "readback": "Hermes / AwoooP 只讀回讀", + "readback": "Hermes / AwoooP 受控回讀", "title": "KM 自動化掌控台", - "subtitle": "先看 stale ratio、負責人審查、ready / blocked 與寫回數,再進入條目列表;這裡把 KM、PlayBook、腳本、排程與 Verifier 的沉澱狀態前移到首屏。", - "openWorkItems": "處理 Owner Review", + "subtitle": "先看 stale ratio、受控覆核、ready / blocked 與寫回數,再進入條目列表;這裡把 KM、PlayBook、腳本、排程與 Verifier 的沉澱狀態前移到首屏。", + "openWorkItems": "處理受控隊列", "card": { "staleRatio": "Stale Ratio", "staleRatioSub": "門檻 {threshold}", "staleTotal": "Stale KM", "staleTotalSub": "距離門檻需處理 {count}", - "ownerQueue": "Owner Review", + "ownerQueue": "受控覆核", "ownerQueueSub": "ready {ready} / blocked {blocked}", "writeback": "已寫回", "writebackSafe": "只讀回讀;讀取不寫入", @@ -2184,6 +2201,11 @@ "ragIndexSub": "sources {sources};0 代表語意檢索尚未沉澱" } }, + "workspace": { + "records": "Records", + "automation": "Automation", + "queue": "Queue" + }, "overview": { "metricTotal": "總條目", "metricLoaded": "目前列表", @@ -2196,7 +2218,7 @@ }, "assetLedger": { "title": "自動化資產沉澱總帳", - "subtitle": "把目前 KM 清單與 Hermes owner-review 讀模型,對齊到 PlayBook、腳本、排程、Verifier 五類資產。", + "subtitle": "把目前 KM 清單與 Hermes 受控覆核讀模型,對齊到 PlayBook、腳本、排程、Verifier 五類資產。", "readOnly": "只讀總覽", "boundary": "此區塊只顯示可追蹤沉澱狀態,不代表已授權修復、已寫回 KM 或已提高 PlayBook trust。", "asset": { @@ -2214,11 +2236,11 @@ }, "monitoring": { "title": "排程 / 監控規則", - "detail": "含告警 / 監控訊號 {ready} 筆;負責人審查 待處理 {pending} 筆。" + "detail": "含告警 / 監控訊號 {ready} 筆;受控覆核待處理 {pending} 筆。" }, "verifier": { "title": "Verifier 回寫", - "detail": "已批准或完成驗證 {ready} 筆;待 負責人審查 {pending} 筆。" + "detail": "已批准或完成驗證 {ready} 筆;待受控覆核 {pending} 筆。" }, "rag": { "title": "RAG / 向量索引", @@ -2244,7 +2266,7 @@ "incident": "Incident", "playbook": "Playbook", "review": "審核", - "sourceDetail": "AI {ai} / 人工 {human}", + "sourceDetail": "AI {ai} / 受控建立 {human}", "knowledgeDetail": "已載入 {count}", "countDetail": "{count} / {total}" }, @@ -2257,8 +2279,8 @@ "missingIncidentAction": "補齊來源事故或標記為通用知識", "missingPlaybook": "缺 Playbook", "missingPlaybookAction": "匹配既有 Playbook或建立草稿", - "reviewBacklog": "待 Owner 審核", - "reviewBacklogAction": "高影響條目先人工覆核再批准" + "reviewBacklog": "待受控覆核", + "reviewBacklogAction": "高影響條目先進 controlled review,再由 AI 補齊 verifier 與寫回證據" }, "entryLineage": { "title": "單筆證據鏈", @@ -2270,12 +2292,12 @@ }, "workItems": { "title": "Work Items 接續狀態", - "subtitle": "這裡只讀取 Hermes KB owner-review queue,讓你知道陳舊 KM 是否已進入可追蹤工作項;實際預覽、確認與寫回仍在 AwoooP Work Items 執行。", + "subtitle": "這裡只讀取 Hermes KB controlled review queue,讓你知道陳舊 KM 是否已進入可追蹤工作項;實際預覽、確認與寫回仍在 AwoooP Work Items 執行。", "open": "打開 Work Items", "loading": "讀取中", "threshold": "門檻 {value}", "entriesToThreshold": "需處理 {count} 筆才回到門檻", - "ownerPendingSub": "待 Owner review", + "ownerPendingSub": "待受控覆核", "readyBlockedSub": "ready / blocked", "burndownStatus": "狀態:{status}", "topCandidate": "最高優先處理項", @@ -2285,9 +2307,9 @@ "topCandidateRefs": "Incident {incident} / Playbook {playbook}", "noCandidate": "目前沒有可顯示的 stale KM candidate。", "ownerSplit": "主責分工", - "hermes": "Hermes:建立 KM 更新草稿與owner-review queue。", + "hermes": "Hermes:建立 KM 更新草稿與 controlled review queue。", "openclaw": "OpenClaw:補告警分類、Playbook與上下文摘要。", - "owner": "Owner:在 AwoooP Work Items 預覽後確認寫回。", + "owner": "Controlled lane:在 AwoooP Work Items 預覽後確認寫回邊界。", "noWritesOnRead": "讀取不寫入", "unexpectedWrites": "偵測到 read endpoint 宣告會寫入", "flow": { @@ -2295,9 +2317,9 @@ "scope": "從偵測到寫回與比例回測的目前位置", "node": { "detected": "偵測", - "ownerReview": "Owner Review", + "ownerReview": "Controlled Review", "dryRun": "乾跑預覽", - "ownerConfirm": "Owner 確認", + "ownerConfirm": "邊界確認", "writeback": "寫回 KM", "recheck": "比例回測" }, @@ -2310,7 +2332,7 @@ }, "detail": { "detected": "目前 {ratio};門檻 {threshold}", - "ownerReview": "{count} 筆等待 owner 審核", + "ownerReview": "{count} 筆等待受控覆核", "dryRun": "{ready} 筆可乾跑;{blocked} 筆卡住", "ownerConfirm": "確認後才允許寫回,避免 AI 固化錯誤知識", "writeback": "{count} 筆已有 completion audit", @@ -2356,7 +2378,7 @@ }, "source": { "ai_extracted": "AI 萃取", - "human": "人工建立" + "human": "受控建立" }, "signals": { "label": "訊號", @@ -2371,14 +2393,15 @@ "execution": "執行紀錄", "execution_failed": "執行失敗", "failure": "失敗", - "human_approved": "人工批准", - "human_intervention": "人工介入", + "human_approved": "受控批准", + "human_intervention": "受控介入", "incident": "事故", "postmortem": "事後檢討", "telegram": "Telegram", "warning": "警告" }, "category": { + "AI自動化/Ansible受控修復": "AI 自動化 / Ansible 受控修復", "AI治理": "AI 治理", "alert_handling": "告警處理", "infrastructure": "基礎設施", @@ -2396,13 +2419,20 @@ "flywheel_health": "飛輪健康", "ssl_cert": "SSL 憑證", "devops_tool": "DevOps 工具", - "incident_postmortem": "事故檢討" + "incident_postmortem": "事故檢討", + "project": "專案", + "product": "產品", + "website": "網站", + "service": "服務", + "package": "套件", + "tool": "工具", + "source_control": "Source Control" }, "filterByType": "篩選類型", "filterByStatus": "篩選狀態", "entries": "筆", "empty": "尚未建立任何知識條目", - "emptyDescription": "知識庫將自動從 Incident 中萃取案例,你也可以手動新增", + "emptyDescription": "知識庫將自動從 Incident、LOG、PlayBook 與 verifier 中萃取案例", "semanticSearchPlaceholder": "輸入語意搜尋查詢...", "semanticOn": "語意", "semanticOff": "語意", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 3052ffaee..c99903c22 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -2159,23 +2159,40 @@ "title": "知識殿堂", "searchPlaceholder": "搜尋知識條目...", "allCategories": "全部", + "rail": { + "categoryTitle": "動態分類", + "total": "總 KM", + "aiExtracted": "AI 萃取", + "controlledQueue": "受控隊列", + "ragChunks": "RAG chunks" + }, + "assetLens": { + "title": "資產維度", + "scope": "目前列表", + "project": "專案", + "product": "產品", + "website": "網站", + "service": "服務", + "package": "套件", + "tool": "工具" + }, "dataChain": { "errorTitle": "知識條目資料鏈路異常", - "errorDescription": "主知識條目 API 未成功回應:{reason}。下方治理軌道仍會顯示 Hermes owner-review 與陳舊 KM 狀態,避免誤判成知識庫真的歸零。", + "errorDescription": "主知識條目 API 未成功回應:{reason}。下方治理軌道仍會顯示 Hermes 受控覆核與陳舊 KM 狀態,避免誤判成知識庫真的歸零。", "retry": "重新讀取" }, "decision": { "badge": "KM 治理警戒", - "readback": "Hermes / AwoooP 只讀回讀", + "readback": "Hermes / AwoooP 受控回讀", "title": "KM 自動化掌控台", - "subtitle": "先看 stale ratio、負責人審查、ready / blocked 與寫回數,再進入條目列表;這裡把 KM、PlayBook、腳本、排程與 Verifier 的沉澱狀態前移到首屏。", - "openWorkItems": "處理 Owner Review", + "subtitle": "先看 stale ratio、受控覆核、ready / blocked 與寫回數,再進入條目列表;這裡把 KM、PlayBook、腳本、排程與 Verifier 的沉澱狀態前移到首屏。", + "openWorkItems": "處理受控隊列", "card": { "staleRatio": "Stale Ratio", "staleRatioSub": "門檻 {threshold}", "staleTotal": "Stale KM", "staleTotalSub": "距離門檻需處理 {count}", - "ownerQueue": "Owner Review", + "ownerQueue": "受控覆核", "ownerQueueSub": "ready {ready} / blocked {blocked}", "writeback": "已寫回", "writebackSafe": "只讀回讀;讀取不寫入", @@ -2184,6 +2201,11 @@ "ragIndexSub": "sources {sources};0 代表語意檢索尚未沉澱" } }, + "workspace": { + "records": "Records", + "automation": "Automation", + "queue": "Queue" + }, "overview": { "metricTotal": "總條目", "metricLoaded": "目前列表", @@ -2196,7 +2218,7 @@ }, "assetLedger": { "title": "自動化資產沉澱總帳", - "subtitle": "把目前 KM 清單與 Hermes owner-review 讀模型,對齊到 PlayBook、腳本、排程、Verifier 五類資產。", + "subtitle": "把目前 KM 清單與 Hermes 受控覆核讀模型,對齊到 PlayBook、腳本、排程、Verifier 五類資產。", "readOnly": "只讀總覽", "boundary": "此區塊只顯示可追蹤沉澱狀態,不代表已授權修復、已寫回 KM 或已提高 PlayBook trust。", "asset": { @@ -2214,11 +2236,11 @@ }, "monitoring": { "title": "排程 / 監控規則", - "detail": "含告警 / 監控訊號 {ready} 筆;負責人審查 待處理 {pending} 筆。" + "detail": "含告警 / 監控訊號 {ready} 筆;受控覆核待處理 {pending} 筆。" }, "verifier": { "title": "Verifier 回寫", - "detail": "已批准或完成驗證 {ready} 筆;待 負責人審查 {pending} 筆。" + "detail": "已批准或完成驗證 {ready} 筆;待受控覆核 {pending} 筆。" }, "rag": { "title": "RAG / 向量索引", @@ -2244,7 +2266,7 @@ "incident": "Incident", "playbook": "Playbook", "review": "審核", - "sourceDetail": "AI {ai} / 人工 {human}", + "sourceDetail": "AI {ai} / 受控建立 {human}", "knowledgeDetail": "已載入 {count}", "countDetail": "{count} / {total}" }, @@ -2257,8 +2279,8 @@ "missingIncidentAction": "補齊來源事故或標記為通用知識", "missingPlaybook": "缺 Playbook", "missingPlaybookAction": "匹配既有 Playbook或建立草稿", - "reviewBacklog": "待 Owner 審核", - "reviewBacklogAction": "高影響條目先人工覆核再批准" + "reviewBacklog": "待受控覆核", + "reviewBacklogAction": "高影響條目先進 controlled review,再由 AI 補齊 verifier 與寫回證據" }, "entryLineage": { "title": "單筆證據鏈", @@ -2270,12 +2292,12 @@ }, "workItems": { "title": "Work Items 接續狀態", - "subtitle": "這裡只讀取 Hermes KB owner-review queue,讓你知道陳舊 KM 是否已進入可追蹤工作項;實際預覽、確認與寫回仍在 AwoooP Work Items 執行。", + "subtitle": "這裡只讀取 Hermes KB controlled review queue,讓你知道陳舊 KM 是否已進入可追蹤工作項;實際預覽、確認與寫回仍在 AwoooP Work Items 執行。", "open": "打開 Work Items", "loading": "讀取中", "threshold": "門檻 {value}", "entriesToThreshold": "需處理 {count} 筆才回到門檻", - "ownerPendingSub": "待 Owner review", + "ownerPendingSub": "待受控覆核", "readyBlockedSub": "ready / blocked", "burndownStatus": "狀態:{status}", "topCandidate": "最高優先處理項", @@ -2285,9 +2307,9 @@ "topCandidateRefs": "Incident {incident} / Playbook {playbook}", "noCandidate": "目前沒有可顯示的 stale KM candidate。", "ownerSplit": "主責分工", - "hermes": "Hermes:建立 KM 更新草稿與owner-review queue。", + "hermes": "Hermes:建立 KM 更新草稿與 controlled review queue。", "openclaw": "OpenClaw:補告警分類、Playbook與上下文摘要。", - "owner": "Owner:在 AwoooP Work Items 預覽後確認寫回。", + "owner": "Controlled lane:在 AwoooP Work Items 預覽後確認寫回邊界。", "noWritesOnRead": "讀取不寫入", "unexpectedWrites": "偵測到 read endpoint 宣告會寫入", "flow": { @@ -2295,9 +2317,9 @@ "scope": "從偵測到寫回與比例回測的目前位置", "node": { "detected": "偵測", - "ownerReview": "Owner Review", + "ownerReview": "Controlled Review", "dryRun": "乾跑預覽", - "ownerConfirm": "Owner 確認", + "ownerConfirm": "邊界確認", "writeback": "寫回 KM", "recheck": "比例回測" }, @@ -2310,7 +2332,7 @@ }, "detail": { "detected": "目前 {ratio};門檻 {threshold}", - "ownerReview": "{count} 筆等待 owner 審核", + "ownerReview": "{count} 筆等待受控覆核", "dryRun": "{ready} 筆可乾跑;{blocked} 筆卡住", "ownerConfirm": "確認後才允許寫回,避免 AI 固化錯誤知識", "writeback": "{count} 筆已有 completion audit", @@ -2356,7 +2378,7 @@ }, "source": { "ai_extracted": "AI 萃取", - "human": "人工建立" + "human": "受控建立" }, "signals": { "label": "訊號", @@ -2371,14 +2393,15 @@ "execution": "執行紀錄", "execution_failed": "執行失敗", "failure": "失敗", - "human_approved": "人工批准", - "human_intervention": "人工介入", + "human_approved": "受控批准", + "human_intervention": "受控介入", "incident": "事故", "postmortem": "事後檢討", "telegram": "Telegram", "warning": "警告" }, "category": { + "AI自動化/Ansible受控修復": "AI 自動化 / Ansible 受控修復", "AI治理": "AI 治理", "alert_handling": "告警處理", "infrastructure": "基礎設施", @@ -2396,13 +2419,20 @@ "flywheel_health": "飛輪健康", "ssl_cert": "SSL 憑證", "devops_tool": "DevOps 工具", - "incident_postmortem": "事故檢討" + "incident_postmortem": "事故檢討", + "project": "專案", + "product": "產品", + "website": "網站", + "service": "服務", + "package": "套件", + "tool": "工具", + "source_control": "Source Control" }, "filterByType": "篩選類型", "filterByStatus": "篩選狀態", "entries": "筆", "empty": "尚未建立任何知識條目", - "emptyDescription": "知識庫將自動從 Incident 中萃取案例,你也可以手動新增", + "emptyDescription": "知識庫將自動從 Incident、LOG、PlayBook 與 verifier 中萃取案例", "semanticSearchPlaceholder": "輸入語意搜尋查詢...", "semanticOn": "語意", "semanticOff": "語意", diff --git a/apps/web/package.json b/apps/web/package.json index 87219531e..fce40b97e 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -7,7 +7,8 @@ "build": "next build", "start": "next start", "lint": "next lint", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "audit:ui-density": "node scripts/audit-ui-density.mjs" }, "dependencies": { "@awoooi/lewooogo-core": "workspace:*", diff --git a/apps/web/scripts/audit-ui-density.mjs b/apps/web/scripts/audit-ui-density.mjs new file mode 100644 index 000000000..cffc8987a --- /dev/null +++ b/apps/web/scripts/audit-ui-density.mjs @@ -0,0 +1,130 @@ +#!/usr/bin/env node + +import { readdirSync, readFileSync, statSync } from 'node:fs' +import { join, relative } from 'node:path' + +const appRoot = join(process.cwd(), 'src', 'app') + +const textLikePatterns = [ + /
sum + (source.match(pattern) ?? []).length, 0)
+}
+
+function routeFromPage(filePath) {
+ return relative(appRoot, filePath)
+ .replace(/\/page\.tsx$/, '')
+ .replace(/\[locale\]/, ':locale')
+}
+
+const pages = collectPages(appRoot)
+ .map(filePath => {
+ const source = readFileSync(filePath, 'utf8')
+ const lineCount = source.split('\n').length
+ const textSignals = countMatches(source, textLikePatterns)
+ const controls = countMatches(source, controlPatterns)
+ const layoutSignals = countMatches(source, layoutPatterns)
+ const textWallSignals = countMatches(source, textWallPatterns)
+ const manualSignals = countMatches(source, manualTerms)
+ const fixedTaxonomySignals = countMatches(source, fixedTaxonomyPatterns)
+ const nestedCardSignals = (source.match(/rounded-(?:md|lg|xl)[^`'"]*border/g) ?? []).length
+ const score =
+ Math.round(
+ (textSignals * 1.2)
+ + (textWallSignals * 8)
+ + (manualSignals * 4)
+ + (fixedTaxonomySignals * 10)
+ + (nestedCardSignals * 0.7)
+ - (controls * 1.5)
+ - (layoutSignals * 0.4),
+ )
+
+ return {
+ route: routeFromPage(filePath),
+ file: relative(process.cwd(), filePath),
+ lines: lineCount,
+ score,
+ textSignals,
+ controls,
+ layoutSignals,
+ textWallSignals,
+ manualSignals,
+ fixedTaxonomySignals,
+ nestedCardSignals,
+ }
+ })
+ .sort((a, b) => b.score - a.score)
+
+console.log('AWOOOI_UI_DENSITY_AUDIT')
+console.table(
+ pages.slice(0, 20).map(page => ({
+ route: page.route,
+ score: page.score,
+ lines: page.lines,
+ text: page.textSignals,
+ controls: page.controls,
+ manual: page.manualSignals,
+ fixedTaxonomy: page.fixedTaxonomySignals,
+ })),
+)
+
+console.log(JSON.stringify({
+ page_count: pages.length,
+ top_routes: pages.slice(0, 20),
+}, null, 2))
diff --git a/apps/web/src/app/[locale]/awooop/work-items/page.tsx b/apps/web/src/app/[locale]/awooop/work-items/page.tsx
index c54d3bc8c..12587ca04 100644
--- a/apps/web/src/app/[locale]/awooop/work-items/page.tsx
+++ b/apps/web/src/app/[locale]/awooop/work-items/page.tsx
@@ -1288,7 +1288,6 @@ const COMMANDER_INSERTED_REQUIREMENT_FALLBACK: PriorityWorkOrderResponse = {
"windows99_uptime_unknown",
],
stockplatform_public_api_runtime_status: "stockplatform_public_api_runtime_ready",
- stockplatform_public_api_runtime_ready: true,
stockplatform_public_api_controlled_recovery_preflight_status:
"not_required_stockplatform_runtime_ready",
stockplatform_public_api_controlled_recovery_data_dependency: "none",
diff --git a/apps/web/src/app/[locale]/knowledge-base/page.tsx b/apps/web/src/app/[locale]/knowledge-base/page.tsx
index 8c67606be..446bd18e8 100644
--- a/apps/web/src/app/[locale]/knowledge-base/page.tsx
+++ b/apps/web/src/app/[locale]/knowledge-base/page.tsx
@@ -17,10 +17,11 @@ import { useTranslations } from 'next-intl'
import Link from 'next/link'
import { cn } from '@/lib/utils'
import {
- Search, BookOpen, FileText, Shield, Cpu,
+ type LucideIcon,
+ Search, BookOpen, FileText, Shield, Cpu, Globe2,
Server, Eye, Bot, ChevronRight, Plus, Sparkles, ClipboardList, Tag, TriangleAlert,
GitBranch, CheckCircle2, Clock3, Link2, FileSearch, ListChecks, ArrowRight, Users,
- PlayCircle, Database, RotateCw,
+ PlayCircle, Database, RotateCw, Package, Wrench,
} from 'lucide-react'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
@@ -130,20 +131,58 @@ interface KnowledgeGovernanceTelemetry {
}
type AutomationAssetKey = 'km' | 'playbook' | 'script' | 'monitoring' | 'verifier' | 'rag'
+type WorkspaceViewKey = 'records' | 'automation' | 'queue'
+type AssetLensKey = 'project' | 'product' | 'website' | 'service' | 'package' | 'tool'
// =============================================================================
// Category Config
// =============================================================================
const CATEGORY_ICONS: Record {t('quality.title')}