diff --git a/docs/UIUX-STANDARD.md b/docs/UIUX-STANDARD.md index 99a84360..e26a9c44 100644 --- a/docs/UIUX-STANDARD.md +++ b/docs/UIUX-STANDARD.md @@ -7,28 +7,31 @@ - 語言:介面全繁體中文,僅保留無法翻譯的技術詞 - 密度:預設「寬」,另提供「緊密」;與既有 `--app-zoom` 正交 +> **本檔是設計專案「RedLog 設計規範」的鏡像**(2026-09-04 取自該專案的 `docs/UIUX-STANDARD.md`, +> 22 節全文)。規範本體在設計專案著作,這裡加上實作狀態註記: +> **✓ 已實作** = 程式碼與本節一致;**▲ 分歧** = 實作刻意與本節不同,附上原因與 commit。 +> 只有註記是 repo 端加的,敘述本身不改。回寫紀錄見 `docs/design-project-sync.md`。 + --- ## 0. 設計稿導覽 一份檔案,由新到舊: -| | 內容 | -|---|---| -| **9a–9b** | 上手成本:單一路徑首次執行、漸進揭露時程(§22,已實作) | -| **8a–8b** | 6a 的修法落成畫面:範圍回溯、標記修訂 | -| **7a–7c** | 對齊 v0.14.3 後的實作:流量歷史、四閘模型、錄影內搜尋 | -| **6a** | 串連檢查——一次任務八步,跨畫面狀態比對 | -| **5a–5c** | 更新流程、設定十二頁內容 | -| **4a–4e** | 設定容器、範圍、目標、逐字稿、戰利品與標記 | -| **3a–3d** | 命令面板、事件流 + Inspector、需要注意、錯誤 | -| **2a–2g** | 證據包(暫緩)、終端機、標記對話框、截圖、首次執行、回放器與骨架屏、視窗層級狀態 | -| **1a** | 規範本體(tokens、狀態、字型、密度、元件、UX 原則、程式片段) | -| **1c** | 改良基準——儀表板、時間軸、空狀態、危險三級 | - -已移除以避免混淆:**1b 現況重建**、**1c 的設定檢視**(4a 取代)、**2f 的市集面板**(5b 外掛頁取代)。 - -> **repo 對帳(2026-08-24)**:本檔是工程摘要,設計專案本體已到 22 節。與 repo 實作分歧處在各節以「▲ 分歧」標記,依據 `DESIGN-core-and-capture.md` 的核心修訂;完整對帳見 `design-project-sync.md`。 +| | 內容 | 實作狀態 | +|---|---|---| +| **9a–9b** | 上手成本:單一路徑首次執行、漸進揭露時程 | ✓ 已實作(PR #28) | +| **8a–8b** | 6a 的修法落成畫面:範圍回溯、標記修訂 | ✓ 8a 已實作(#27)/8b 部分(#26) | +| **7a–7c** | 對齊 v0.14.3 後的實作:流量歷史、四閘模型、錄影內搜尋 | ✓ 已實作 | +| **6a** | 串連檢查——一次任務八步,跨畫面狀態比對 | — | +| **5a–5c** | 更新流程、設定十二頁內容 | ✓ 已實作(5c 見 §22) | +| **4a–4e** | 設定容器、範圍、目標、逐字稿、戰利品與標記 | ✓ 已實作 | +| **3a–3d** | 命令面板、事件流 + Inspector、需要注意、錯誤 | ✓ 已實作 | +| **2a–2g** | 證據包(暫緩)、終端機、標記對話框、截圖、首次執行、回放器與骨架屏、視窗層級狀態 | 部分(見各節註記) | +| **1a** | 規範本體(tokens、狀態、字型、密度、元件、UX 原則、程式片段) | ✓ 已實作 | +| **1c** | 改良基準——儀表板、時間軸、空狀態、危險三級 | ✓ 已實作 | + +已移除以避免混淆:**1b 現況重建**(舊 app 的忠實複本,基準已記在 §1a A 節)、**1c 的設定檢視**(4a 取代)、**2f 的市集面板**(5b 外掛頁取代)。1c 側欄未實作的列一律降透明並停用。 ## 1. Tokens @@ -50,25 +53,15 @@ **紅色語意收緊**:品牌紅只在**命令按鈕**上填色,其餘一律只做文字或細線;危險紅只填色,且可以填在任何地方。區別不靠「有沒有底色」,而靠「這是可以按的動詞,還是在報告狀態」。硬限制:**同一個動作區(對話框底部、工具列、卡片頁腳)不得同時出現實心品牌紅與實心危險紅**。搭配「一屏最多一顆主要按鈕」與「全 app 同時只允許一處危險紅」,這個情境不會發生。 -**填色一律配深色字**:這個色盤的彩色全是中亮度,白字在每一個上面都不過 AA——`#d75f63` 3.68:1、`#ff4d4f` 3.27:1、`#5ecf9c` 1.93:1、`#3fc7d6` 2.03:1。深色字全部過 5:1 以上。所以規則不分顏色、不分元件:**填色就配深色字**,涵蓋按鈕、徽章、chip、進度標示。 - -| 填色 | 配的字色 | 對比 | -|---|---|---| -| `accent` `#d75f63` | `on-accent` `#16090a` | 5.3:1 | -| `danger` `#ff4d4f` | `on-danger` `#1a0303` | 6.1:1 | -| `warn` `#d4ac5a` | `on-warn` `#1a1203` | 7.2:1 | -| `safe` `#5ecf9c` | `on-safe` `#03150d` | 9.7:1 | -| `info` `#3fc7d6` | `on-info` `#031215` | 9.4:1 | - -不調暗 `#ff4d4f`——它的亮度正是與品牌紅拉開距離的手段。也不另開第三個紅。 - **狀態唯一真相表** | 狀態 | 色彩 | 唯一允許的表現 | |---|---|---| | 正常/安全 | `#5ecf9c` | 圓點 + 文字,無實心底、無動畫 | | 未知/閒置 | `#d4ac5a` | 圓點 + 文字 + 一句「怎麼補」 | -| 危險/違規 | `#ff4d4f` | 實心徽章或實心按鈕,`on-danger` 深色字 | +| 危險/違規 | `#ff4d4f` | 實心徽章或實心按鈕,深色字 `#1a0303` | +|  ↳ 數值型狀態 | `#d4ac5a` | 結束碼、違規計數、待處理數等**數字**一律琥珀色文字,不用危險紅——數字太小、出現太頻繁,用危險紅會讓「全 app 只有一處」失守 | +|  ↳ 圖示 | `#ff4d4f` | 非文字元素可用危險紅描邊或填色(對比 ≥3:1 即可),例如刪除清單前的 ✕ | | 錄製中 | `#d75f63` | 閃爍圓點,僅狀態列與 HUD | | 資訊/連線 | `#3fc7d6` | HUD 邊框、拓樸、minimap;不用於狀態判定 | @@ -99,7 +92,8 @@ - **標誌**:單一字標 `REDL(●)G`,O 為錄製指示環。介面內不再並列「R」方塊與字標。環全部以 em 表示(換字級不必重算):外徑 `0.72em`(= Noto Sans TC 大寫字高)、環寬 `0.115em`(外徑 16%)、內點 `0.216em`(外徑 30%)、上移 `0.02em`;環必須 `box-sizing: border-box`,用 content-box 會讓外徑多出兩倍環寬。字標下限 12px。切角符號只用於 app 圖示、Dock、系統列、favicon,切角 = 邊長 22%(固定左上/右下;HUD 面板用的是 `lib/hud.ts` 的固定 11px/5px,因為面板尺寸不一,標誌是等比縮放所以改用比例),16px 以下環收成實心點。標誌永遠 `#d75f63`,不用危險紅、不動畫;單色場合用 `#ececf0` 或純黑;留白 ≥ 環直徑 - **按鈕**四級,高 34px(緊密 30px),圓角 8px,focus 環 2px `#d75f6366` 外偏移 2px。同一畫面最多一個主要 - 主要 = 實心 `accent` + 深色字(`#16090a`)。這是 §1 允許品牌紅填色的唯一場合 - - 次要 = `elevated` 底 + 1px 邊框;安靜 = 純文字;危險 = 實心 `danger` + `on-danger` 深色字 + - 次要 = `elevated` 底 + 1px 邊框;安靜 = 純文字;危險 = 實心 `danger` + 深色字 `#1a0303` + - **所有實心色塊一律深色字。**這個色盤的彩色都是中亮度,白字全部不過 AA:`#d75f63`+白 = 3.68:1、`#ff4d4f`+白 = 3.27:1、`#5ecf9c` 與 `#d4ac5a` 更低。改深色字後分別是 5.3:1 與 6.1:1。徽章、chip、進度標示適用同一條 - **卡片**:取消頂部 2px 色條,改為左側色塊包住圖示(危險用實心,其餘用 12% 底色,與徽章規則一致)。卡片底色永遠是 `surface`,不因狀態改變 - **徽章**:12% 底色 + 同色文字 + 圓點;只有危險用實心 - **chip**:選取時 `elevated` + 1px 邊框,不用紅色 @@ -118,15 +112,22 @@ 7. 符合 macOS 慣例:設定為左清單 + 右內容;⌘. 暫停、⌘K 命令面板、⌘F 頁內搜尋、Esc 逐層退出;破壞性動作在對話框右下(Windows 自動對調);tooltip 不得是唯一的資訊來源 8. 可及性硬門檻:文字 ≥4.5:1、非文字狀態元素 ≥3:1、focus 環處處可見、`prefers-reduced-motion` 保留 +> ✓ **§5-3 的實作註記**:⌘ 編號取自 `lib/sidebarOrder.ts` 的 `DEFAULT_ORDER` 位置,不是渲染位置。 +> 側欄原本印渲染索引,因此三列印著開不了東西的 9/10/11、設定列也印 9;已修(#28)。 +> 十一個視圖只有前八個有 chord,其餘不印數字——印一個開別的地方的數字比不印更糟。 + ## 6. 時間軸 - **兩種形態**:可視範圍內任一泳道 >50 筆 → 全部泳道一起折疊成事件流(保持時間對齊);使用者手動改過模式後,本次 session 不再自動切換 - **事件流每列**:時間戳 + tier glyph + 泳道名 + 一行摘要。保留泳道篩選(逐字稿則固定只看指令與對話) - **Inspector**:右側 380px 可拖抽屜,三分頁〈詳細/相關/原始〉。「相關」就是全局因果鏈面板,不另建。預設關;視窗 >1600px 預設開 + - ▲ **分歧**:實作是**底部**可調高度面板,非右側抽屜,且無分頁;`_causes`/效應 chip 與原始 JSON 直接列在面板內。 - **滑鼠**:滾輪捲時間;Ctrl/⌘+滾輪與雙指開合**以游標為錨**縮放(不是畫面中心);雙擊空白處縮放到前後 5 分鐘 - **鍵盤**:← → 同泳道走;↑ ↓ 跨泳道落在時間最接近的事件;Shift+← → 跳下一筆帶狀態的事件;Home/End;+ − / 0 以選中事件為錨;Enter 開關 Inspector - 鍵盤移動必須有可見選取框(2px 品牌紅外環 + 事件點 1.3×);自動捲入視野**不得改變縮放層級** -- ~~**檢視模式**(取代工具列八組並列開關):作業中/稽核/除錯~~ — **▲ 分歧**:已實作後 revert(`59ff5fc`,人設硬套旗標組合、預設落在「除錯」)。現行做法:切換**按作用分組**,罕用的檢視/稽核項收進〈更多〉overflow(`48713ba`);18 泳道另按擷取組分帶(`183b9ac`)。 +- **檢視模式**(取代工具列八組並列開關):作業中(收合代理逐輪 + 略過閒置 + 本機時區)/稽核(只上鏈事件 + 異常標記 + UTC + 不壓縮時間,**鎖定不可微調**)/除錯(全部事件 + session 邊界 + 原始時間) + - ▲ **分歧**:已實作後 revert(`59ff5fc`)——人設硬套旗標組合、預設落在「除錯」。現行做法:切換**按作用分組**, + 罕用的檢視/稽核項收進〈更多〉overflow(`48713ba`);18 泳道另按擷取組分帶(`183b9ac`)。 ## 7. 跨頁互連 @@ -154,6 +155,7 @@ - **錯誤訊息三段式**:發生什麼事(中文)+ 為什麼 + 一顆動作;原始錯誤收在「詳細」折疊區 - **Toast**:錯誤不自動消失;同類合併計數;上限 3 則;容器需 `aria-live="polite"`(錯誤用 `assertive`) - **持續性故障**分兩層固定在狀態列左側:〈需要注意 N〉只收影響證據的(抓取中斷、錨定失敗、鏈斷、DB 寫入錯誤、檔案遺失)—— **不可忽略**、紅點;其餘收〈待處理〉—— 可忽略、灰色、不寫稽核 + - **範圍違規不進〈需要注意〉**。它不是故障,也可能是刻意的;側欄徽章與狀態列已經夠明顯。〈需要注意〉只收「系統沒在正常運作」 - **時間**:一律 24 小時。相對時間**只用於新鮮度欄位**(最後一次抓取、3 秒前);事件本身、時間軸軸標、逐字稿、匯出一律絕對時間,匯出用 ISO 8601 - **文字截斷**:一律可 hover 看全文(原生 `title`),長內容另可展開成多行 - **大量資料**:全部改無限捲動 + 虛擬列表,底部顯示「已載入 N/共 M」。目標頁改 SQL 聚合(`GROUP BY detectedTarget`),不再讀 1000 筆原始事件在前端聚合 @@ -164,13 +166,16 @@ ## 10. 刪除與修正的功能 - **狀態列〈⏱ 時戳〉刪除** —— 與標記寫入同一張表,只差沒有標題與嚴重度,功能重複。改由標記對話框提供「快速落點」(HUD 已是此模型) -- ~~**側欄搜尋頁刪除**~~ — **▲ 分歧**:搜尋頁已**復原**(事後找證據是核心用途,下拉不是對的形狀;⌘K 保留為跳轉器)。原文:全部收進 ⌘K(導航、事件/標記/operator/host 模糊搜尋、動作、檢視模式與密度切換、專案切換、最近指令)。頁內篩選單獨給 ⌘F。設定項不進 ⌘K,由設定頁自己的搜尋框負責 +- **側欄搜尋頁刪除** —— 全部收進 ⌘K(導航、事件/標記/operator/host 模糊搜尋、動作、檢視模式與密度切換、專案切換、最近指令)。頁內篩選單獨給 ⌘F。設定項不進 ⌘K,由設定頁自己的搜尋框負責 + - ▲ **分歧**:搜尋頁**保留**。⌘K 是導航與動作,錄影內全文搜尋(`.cast` FTS5)需要一個能停留、能讀回位元組範圍的頁面,命令面板承載不了。 - **operator 搜尋沒有前置條件**:`operators:list` 已是既有 IPC(`TranscriptView` 已在用),直接接上 - **host 搜尋不是面板的問題**:host 只存在於事件的 `data.host` JSON 裡,只有時間軸把事件載進記憶體才數得出來。要讓它全域可搜,需要 DB 端的 distinct-host 聚合——那與 §9「目標頁改 SQL 聚合(`GROUP BY detectedTarget`)」是同一件事,host 與 target 是同一組資料。兩者一起做,面板讀同一份聚合結果 - 時間軸本地面板懂泳道,是資料庫搜尋做不到的,保留為面板內的動作項 -- **〈顯示 N 個機密〉與本機遮蔽全部刪除** —— 資料已在使用者自己的機器上。**例外:進入證據包、任何匯出的資料仍須經 redaction**(▲ 雲端分享與藍隊 webhook 已移除),這條線要在程式裡分開實作 +- **〈顯示 N 個機密〉與本機遮蔽全部刪除** —— 資料已在使用者自己的機器上。**例外:進入證據包、任何匯出、雲端分享、藍隊 webhook 的資料仍須經 redaction**,這條線要在程式裡分開實作 + - ▲ **分歧**:雲端分享與藍隊 webhook **已整個移除**(PR #23),所以那兩條 redaction 路徑不存在;證據包與匯出的 redaction 仍在。 - **Token 不再靠使用者複製** —— 寫入 `~/.redlog/tokens/`(與專案分離,不會被證據包或匯出收進去)並在 Finder/檔案總管點亮 -- ~~**外掛信任**~~ — **▲ 分歧**:市集、發行者信任與撤銷清單已整個移除(散佈非核心);只剩已安裝外掛管理。原文:一張對話框列出每項權限的具體影響 + 內容雜湊指紋 + 勾選框;「一鍵信任 registry 建議的發行者」改為逐一信任,並列出該發行者能簽署的外掛數 +- **外掛信任** —— 一張對話框列出每項權限的具體影響 + 內容雜湊指紋 + 勾選框;「一鍵信任 registry 建議的發行者」改為逐一信任,並列出該發行者能簽署的外掛數 + - ▲ **分歧**:外掛**市集/發行者/撤銷清單已移除**(PR #23)。外掛信任仍是逐一,但沒有 registry 這個概念。 - **範圍頁重做** —— 現況顯示證據鏈筆數(與範圍無關,屬儀表板),卻缺少「允許清單是什麼、哪條規則命中」。改為:允許清單 + 排除清單(可直接編輯)+ 可展開的違規清單 - **匯出六處收成一個下拉** —— 工具列右上〈匯出 ▾〉:當前頁面/可視切片/全部;JSON 或 Markdown;另加〈證據包(含驗證器)〉。每個選項下方一行預覽「將匯出 412 筆事件、約 2.1 MB」 - **終端機**:分頁顯示 cwd 而非 `term-1`;錄影中顯示 `.cast` 大小與上限進度;字級改 ⌘+/⌘−;搜尋改 ⌘F 並顯示符合筆數;關閉分頁改為可復原 @@ -180,126 +185,224 @@ - **暫停錄製的文案** —— 標記與系統事件在暫停期間**仍會記錄**(見 `e2e/recording-pause.spec.ts`)。不得寫成「不會擷取任何東西」,否則操作員會以為剛落的標記遺失 - **右鍵落標記改為右鍵菜單裡的一項**〈在此落標記〉—— 主程序的 `context-menu` 事件不受 renderer 的 `preventDefault` 影響,現況會同時落標記與開複製菜單,而那筆標記已寫進證據鏈 -## 11. 已知的既存缺陷(非設計問題) - -- **已修**(9b 一併處理)側欄印的是**渲染位置**而非該視圖的編號。`DEFAULT_ORDER` 有 11 項、只有 8 項有快捷鍵,所以範圍/戰利品/標記一直印著 9、10、11——都是開不了任何東西的號碼——而設定列也印 9,同一畫面上兩個 9。 -- **已修**(9b 一併處理)⌘K 與快捷鍵面板都以 view id 組標籤鍵(`sidebar.http_history`),該鍵兩本語言檔都沒有,所以那一列直接把鍵名印給操作員。字面鍵掃描器看不到動態鍵,而 `shortcuts.test.ts` 的 fixture 是手抄的八項清單,漏掉最新兩個視圖。 +## 12. 尚未涵蓋的畫面(turn 2,設計稿 2a–2g) + +- **證據包報告**(2a)—— 包內新增 `report.pdf` / `report.html`,白底黑字、Letter、兩頁:封面(任務、期間、操作員、鏈頭、錨定、消毒次數)+ 摘要(統計、**完整展開的範圍違規清單**、三步自行驗證)。標誌用純黑單色。現有 `README.md` 保留為技術收件人的補充。兩份新檔一併列入 manifest 雜湊 +- **終端機**(2b)—— 分頁顯示 cwd + 錄影用量條;**每個窗格頁首標示〈記錄中〉/〈未記錄〉**;互動式工作階段(ligolo、msfconsole)誠實標為未記錄;底部橫幅說明外部終端機是否被擷取,可關閉但狀態仍留在〈需要注意〉 +- **標記對話框**(2c)—— 一個對話框,「仔細」由〈加上備註…〉就地展開,不是第二個入口。標題自動聚焦、⌘↩ 送出。〈將一併記錄〉列出 URL / IP / 截圖;截圖是唯一可取消項,取消時就地說明原因。嚴重度用 §C 狀態色。Esc 先清空欄位,第二次才關閉 +- **截圖頁**(2d)—— 去重收成 `×N` 角標而非隱藏;觸發原因(定時/手動/隨標記)是主篩選軸;SHA-256 印在縮圖下。**批次刪除是第二級**(不是第三級):`screenshot:deleteFile` 只刪檔案,原始事件留在鏈上並寫入帶 `sha256_pre_delete` 的 `system.screenshot_deleted`——證據鏈見證了這次刪除,所以第三級要保護的性質已經存在。**升級條件:批次中只要有任一張被標記引用,就升到第三級**——標記代表操作員說過「這件事重要」,而這種缺失要到寫報告時才發現。門檻跟後果走,不跟批次大小走;輸入一次涵蓋整批 +- **首次執行**(2e)—— **擷取來源不編號**。來源互不依賴,依「抓什麼」分組:**指令**(shell hook、AI 代理、RedLog 終端機)、**流量**(mitmproxy 的 HTTP 與 DNS、瀏覽器 CDP)、**畫面與檔案**(截圖、剪貼簿、檔案傳輸、程序)。只做 Web 測試的人要的是流量不是 shell hook,編號會讓他看起來缺了兩項。跳過是安靜連結;明寫「不會再出現」 + - ⚙ **`captureReadiness.ts` 需改模型**:`CORE_SOURCE_ORDER` 把 mitmproxy 等流量來源排除在「dark → recording」路徑外,並把三個 core 來源寫成有序步驟。改為無序集合 + 分組,`nextStep` 依狀態而非位置選出 + - ✓ **已實作**,且 9a 之後這張卡整個降為首次執行畫面底下的折疊區(見 §22)。 +- **回放器 / 市集 / 骨架屏**(2f)—— 回放進度條上以紅刻度標出該段錄影期間的標記;市集把發行者與撤銷清單降為每列的徽章與說明(消滅第三、四層);骨架屏每塊對應真實內容的字級與寬度 + - ▲ **分歧**:市集已移除(PR #23),該段不再適用。 +- **視窗層級狀態**(2g)—— DB 損毀/被鎖(強調「RedLog 不會自行修復或覆寫證據檔」)、第二實例被擋、選單列(承載 §M 的不靠點擊退出)、WSL 逐發行版安裝且系統發行版自動略過 + +## 13. 寫了規則、尚未畫過的畫面(turn 3,設計稿 3a–3d) + +- **命令面板**(3a)—— 640px。分組固定順序:前往 → 事件 → 動作 → 設定 → 專案。空查詢只顯示最近與動作。頁尾固定:`↑↓` 選擇 / `↩` 執行 / `⌘↩` 在時間軸開啟 / `esc` +- **事件流 + Inspector**(3b)—— 列規格:層級字符 → 時間 → 泳道 → 摘要 → 結束碼。泳道欄取代泳道位置;只有 `⌇`(已記錄)畫字符。Inspector 380px,分頁詳細/相關/原始 +- **需要注意**(3c)—— 兩層同一個彈出層。上層每列一顆修復按鈕、無關閉鈕;下層可逐項或整批忽略,不寫稽核 +- **錯誤**(3d)—— 錯誤 Toast 不自動消失、有關閉鈕;可逆動作自動消失、無關閉鈕但有復原。致命畫面先講「記錄沒有中斷」 + +## 14. 設定與其餘五頁(turn 4,設計稿 4a–4e) + +- **設定**(4a)—— 左清單**五組十二頁**,任何設定項兩層可達;頂部設定搜尋。擷取來源依 §12 分組(指令/流量/畫面與檔案),依 §17 四閘呈現:hook 類(閘 4)給按鈕與獨立的「解除安裝 hook」、開關類(閘 2)給 toggle、無兩者的標「自動」。**停用(閘 2)與解除 hook(閘 4)是兩個動作**,後者收在該列的 ⋯ 選單。側欄徽章只用於需要處理的數量 + - 十二頁:**開始記錄**(擷取來源、終端機、AI 代理)、**控制抓取**(範圍、網路與 IP、敏感來源)、**證據保全**(證據鏈與錨定、保存與匯出)、**協作**(操作員、外掛)、**應用程式**(外觀與語言、HUD) + - 雲端分享與藍隊通報未列入——它們把資料送出本機,不在目前範圍。日後恢復則歸入「協作」組 +- **範圍**(4b)—— 左側可編輯的允許/排除清單,右側違規;展開一筆違規顯示命中哪條規則與完整指令,並直接提供〈加入允許清單〉。移除與範圍無關的證據鏈筆數 +- **目標**(4c)—— 每個目標可展開列出指令(時間、結束碼),每條可單獨跳時間軸(⌘↩)。計數由 SQL 聚合 +- **逐字稿**(4d)—— 預設輸入 + 輸出首行;結束碼非 0 或含戰利品自動展開 +- **戰利品與標記**(4e)—— 戰利品需按住才顯示、跳轉至來源指令而非時間點;標記以圓點表嚴重度、圖示表示附截圖 + +## 15. 更新與設定內頁(turn 5,設計稿 5a–5c) + +- **更新**(5a)—— 記錄中只在狀態列多一顆青點,不跳 Toast、不彈視窗。點開才顯示版本與變更;下載進度行內不遮蓋。**重啟前先錨定鏈頭**,並在確認框寫出「約 8 秒不記錄」——那是證據鏈上真實的空白。更新永不自動套用 +- **設定內頁**(5b/5c)—— 十二頁全部繪出。欄位量大的四頁:終端機(外觀/錄影上限與用量/分頁)、網路與 IP(安全與暴露清單、輪詢間隔與信標警告)、證據鏈與錨定(鏈頭與錨定狀態卡、頻率、四個動作、錨定紀錄)、外掛(信任徽章與撤銷就地顯示,不另開分頁)。其餘七頁照同一列樣式 +- 範圍設定頁只放不常改的行為開關;允許清單與違規在範圍頁(4b)編輯,不重複兩處 + +## 16. 標誌檔案 + +- `assets/redlog-mark.svg` —— 1024×1024 app 圖示原稿(切角 22%、環外徑 45%、環寬 16%、內點 30%)。`.icns` / `.ico` 由此產生 +- `assets/redlog-mark-small.svg` —— 256×256 以下變體,環收成實心點;16px 尺寸用它 +- **字標沒有 SVG 檔,這是刻意的。** 它在每個出現的地方都是即時文字(app 介面、證據包報告的 HTML 與 PDF),幾何由 §4 的 em 規則決定,會隨字級自動正確。手寫座標的向量字標試過一次就壞了三處:環壓到 L、環在兩字之間偏 29 單位、G 被 viewBox 切掉 —— 位置是猜的,不是量的。真的需要向量字標時(貼紙、投影片),從打包的 Noto Sans TC 700 轉外框,不要手排 +- 舊標 `assets/logo.svg`(圓角方形漸層底 + 漸層 R + 斜線 + 右上紅點與外光暈)由新標取代。新標保留了它唯一真正在說話的元素——那顆紅色錄製點——並把它從角落的裝飾升成名字本身;漸層、外光暈與斜線移除,因為它們在 16px 下全部糊成一團,且與 §1「去飽和、不發光」的整體方向相反 + +## 17. 串連檢查(turn 6,設計稿 6a) + +一次任務從建立專案到交付八步,比對同一件事在不同畫面是否一致。三個只在串起來時才浮出的問題: + +- **範圍要回溯。**真實順序常是先打了幾個指令才想起設範圍,那幾筆已進鏈且已超出範圍,卻不會被標為違規。允許清單存檔時需**回溯重算既有事件**,並顯示「已回溯標記 N 筆」 + - ✓ **已實作**(8a,PR #27)。細節與收緊處見 §20。 +- **違規不進〈需要注意〉**(見 §9) +- **標記可編輯,但編輯是一筆新的鏈上事件**(`marker.amended`,帶前後值)。寫報告時發現標題打錯或嚴重度標高是必然的;證據鏈不因此變弱,反而記錄了修訂過程。標記頁與 Inspector 都要有〈編輯〉 + - ✓ **已實作**(8b,PR #26),但只在 Inspector;細節與差異見 §20。 + +- **儀表板「什麼都沒在記錄」卡只列有問題的來源**(開著但沒在送、已就緒但未有事件)。刻意關閉的來源不列,收成一行「其餘 N 個來源已關閉」 +- **擷取來源列要看得到安裝按鈕**:未安裝→〈安裝〉(主要)、已裝未開→toggle、開著沒送→〈診斷〉、運作中→只顯示新鮮度 + +## 18. 對齊 v0.14.3 後的實作(turn 7,設計稿 7a–7b) + +- **流量歷史**(7a)—— 補上規範缺的整個畫面(`HttpHistoryPanel.tsx`)。§3 的「單點或區間」:一列一個動作而非一列一條連線,一次 40,000+ 的暴力嘗試與單一 curl 都佔一列。形狀帶語意(圓點=單點、短條=區間)並以文字標籤重複(形狀不是可及通道)。狀態桶沿用青色資訊系;4xx/5xx 用琥珀色文字而非危險紅(§C 數值例外)。`⌘` 表示鏈到來源指令,`↗` 跳時間軸。第二檢視為網站地圖樹(主機→路徑→查詢) +- **錄影內搜尋**(7c)—— 終端機 ⌘F 的結果層(`CastResults.tsx`)。主要動作是就地展開輸出(從 `.cast` 依位元組範圍讀回),回答「那次掃描的輸出在哪」;`↗` 跳時間軸是次要。依 token 邊界比對不做子字串。索引未完成時顯示琥珀色 `role="status"` 提示——命中數會隨索引增加,絕不能讓它讀成「沒有東西」 +- **四閘模型**(7b)—— 修正 §M 的「安裝/啟用兩軸」為 `CAPTURE-SOURCE-TAXONOMY.md` 的四閘:存在/已啟用/已信任(🔴)/hook 已安裝。**停用 ≠ 解除安裝**——閘 2 只翻 `state.json`,不移除 `.zshrc` 的 hook 行,兩者必須是分開的 UI 動作,否則孤兒 hook 累積。分組仍按「抓什麼」(§12),但每項預設開/關由「誰發起位元組」決定:操作員主動類預設開,環境吸取類(剪貼簿、定時截圖)預設關 + +## 20. 6a 修法落成畫面(turn 8,設計稿 8a–8b) + +- **範圍回溯**(8a)—— 允許清單存檔後重算既有事件的標記,**不改事件**,另寫 `scope.recomputed`(規則版本、重算/新標/解除三個數)。回溯標記的違規列帶琥珀色「回溯標記」chip,稽核員能分辨「當時就知道」與「事後才判定」 + - ✓ **已實作**(PR #27)。存的 subtype 是 `scope_recomputed`(snake_case,所有 `system` subtype 皆然); + 另有 `system.scope_cleared` 撤回既有違規。實作時收緊的判斷: + - **撤回由「違規紀錄」算,不是重掃語料**——語料大半在 logged 層、30 天後被清,重掃式的撤回會讓那些違規永遠掛著。 + - **候選目標用 SQL 依 live 路徑的方式推導,不是 `target_id`**——DNS producer 存的是帶結尾點的 FQDN, + 當初判定的是去點形式,而網域比對是精確比對。 + - **`in_scope` 判定也寫成 `scope_violation` 列**(遵循度統計需要正面證據),不能算成既有違規,否則新標會變成改判。 + - 三道閘:未設定範圍時跳過、2 秒尾端去抖動、專案切換時放棄排程中的工作。 +- **標記修訂**(8b)—— 可改標題、嚴重度、備註;時間戳、URL、截圖、來源事件不可改。儲存寫入 `marker.amended`(前後值 + operator)。標記列顯示「已修訂 N 次」,Inspector 原始分頁列修訂紀錄。第一級(無確認框)、無復原——復原就是再修一次 + - ✓ **部分實作**(PR #26)。存的是 `marker` + `subtype:'amended'`,只夾帶變更欄位(不存前值——前值由 fold + 自原列推導,重複存會出現兩個真相)。差異: + - **marker 事件沒有 `url` 欄位**(只有 title/notes/severity/category + 選填 `atTimestamp`);`url` 屬 `quickmarks` 表。 + - **截圖不是 marker 的欄位**,是另一筆鏈上事件以 `_causes` 指回標記。 + - 「來源事件」目前沒有產生者會設,所以那一列只在真的有值時出現。 + - ▲ 側欄「標記」頁背後是 `quickmarks` 表,**至今仍可 UPDATE/DELETE**。待裁決:把它也改成附加式修訂, + 或明確標成「書籤表,不是紀錄」。 + +## 21. 規則測試(進 CI,沿用 `test/lane-colours.test.ts` 的作法) + +每條都從原始碼解析,不靠人工目視: + +```ts +// test/design-rules.test.ts +it('次級文字對底色 ≥ 4.5:1', () => expect(contrast(T.text_dim, T.bg)).toBeGreaterThanOrEqual(4.5)) +it('每個填色 token 都有 on-* 且 ≥ 4.5:1', () => { for (const f of FILLS) expect(contrast(T[`on_${f}`], T[f])).toBeGreaterThanOrEqual(4.5) }) +it('白字在任何填色上都不過(規則的理由)', () => { for (const f of FILLS) expect(contrast('#fff', T[f])).toBeLessThan(4.5) }) +it('renderer 無 text-white / text-[10px] / text-[11px] / text-[12px]', () => expect(grep(RENDERER, /text-white|text-\[1[012]px\]/)).toEqual([])) +it('泳道色唯一且為 lane 灰', () => expect(new Set(Object.values(LANE_COLORS))).toEqual(new Set([T.lane]))) +it('危險紅不出現在數值文字上', () => expect(grep(RENDERER, /text-redlog-danger[^"]*">\s*\d/)).toEqual([])) +it('同一 ConfirmDialog 不同時有實心 accent 與實心 danger', ...) +``` + +三期 PR 模板各自引用對應的測試名;reviewer 勾的是「測試存在且綠」,不是「我看過了」。 + +> ✓ **七條全部在 CI**,但拆在既有的守衛檔而非單一 `design-rules.test.ts`: +> 前三條與泳道色在 `test/design-tokens.test.ts`/`test/lane-colours.test.ts`, +> 字級與 `text-white` 在 `test/design-tokens.test.ts`, +> ConfirmDialog 那條在 `test/buttons.test.ts`, +> 「危險紅不出現在數值文字上」在 `test/danger-not-on-numbers.test.ts`——實作改以 +> `tabular-nums` 與 danger 類名**同時出現在同一個 className** 為判準,比原本的 regex 穩: +> 數字未必緊接在標籤後面,而數值一定帶 `tabular-nums`。 + +## 22. 上手成本(turn 9,設計稿 9a–9b) + +前面的規範追一致與正確,沒追學習成本。修法不是加教學,是漸進揭露: + +- **首次執行改單一路徑**(9a)—— 一個畫面、一件事:在內建終端機打一個指令,右欄時間軸實際亮起。九個來源(2e)成為第二步。先驗到產品做了什麼,再決定餵它什麼 +- **名詞在它的資料存在之前不出現**(9b)—— 第一天側欄四格(儀表板、時間軸、終端機、設定),目標→範圍→戰利品→標記依資料出現逐一長出。狀態列的層級字符、錨定、跳板節點同理。所有隱藏項在 ⌘K 與設定始終可達;設定內有「一次全部顯示」開關 +- **被淘汰的作法**:導覽式教學、首次進頁的 tooltip 巡覽、空狀態裡的名詞解釋——這些都是在解釋一個使用者還沒遇到的概念 +- 工程:側欄項的可見性由一個 `visibility.ts` 依資料推導,不存使用者狀態;⌘數字快捷鍵編號不因隱藏而改變(§5-3) +- 已對齊:6a 第 02 步改指 9a;5c 外觀頁新增「一次顯示所有頁面」開關。1c 與 4a 描繪的是 28,338 筆事件的成熟專案,九格側欄正確 +- **下一步不是再畫:**上手成本只能用真人驗——找三位沒用過的測試員,計時到「第一筆事件落地」與「第一次自己找到範圍頁」,目標 30 秒與 10 分鐘。這兩個數字沒量之前,再多畫一張都是猜 + +> ✓ **已實作**(PR #28)。**解鎖對照表**(`lib/visibility.ts`,括號內為訊號所在的層): +> +> | 名詞 | 等到什麼 | 為何是這個訊號,不是更寬鬆的那個 | +> |---|---|---| +> | 搜尋 | 任一筆「操作員做的事」(兩層) | 判定用 `EVIDENCE_SQL` 這個**正面**述詞,不是「非 housekeeping」。alert runtime 每次開專案都會啟動,IP policy 無條件送出第一筆判定(離線也送 `unknown`),所以幾秒內就有一筆非 housekeeping 的上鏈列 | +> | 逐字稿 | 已完成的指令,或任一 agent 回合 | 就是該頁實際渲染的兩種列 | +> | 目標 | 由**指令**推導出的目標 ≥1(上鏈) | proxy addon 對每筆 HTTP/DNS、連線監控對每個 socket 都會蓋 `target_id`——跨型別去算,一次瀏覽器開頁就會解鎖,正好與 9b 的規則相反 | +> | 範圍 | 同上,≥2 | | +> | 戰利品/截圖 | 自己那一型的上鏈列 | `loot:getCount` 是記憶體計數器、重啟歸零,不是資料 | +> | 標記 | 一筆 `quickmarks` 列 | 該頁只列這張表;`marker` 事件是另一個儲存區,而且可由外部 POST | +> | HTTP | logged 層的 `http_request_start` / `http_response` | 該頁只查 logged 層。上鏈的 `scanner:connection` 會解鎖一張永遠空的頁 | +> | 層級字符 | 任一 logged 列,或 `system.retention_pruned_logged` 稽核列 | 稽核列比它描述的資料活得久,所以 logged 層被清空後字符不會消失 | +> | 錨定/跳板節點 | 無需程式碼 | 儀表板 ⚓ 子行與 HUD 膠囊本來就以資料為條件 | +> +> 另外三條工程約束:**單調**(出現過的名詞不再消失,否則 30 天後的 retention 會被讀成證據被銷毀); +> `null` 訊號代表「還沒問到」、不等於「還沒有」(否則成熟專案會閃一下四格側欄),探測失敗時**全部顯示**; +> **首次執行畫面用閂鎖**,直接讀「還沒有資料」的話,第一列進來的瞬間畫面就被卸載——而那正是它要讓人看到的一刻。 +> +> **5c** 的開關是**按專案**存的(localStorage):切專案是同源 reload,全域鍵會讓一次勾選對之後每個案子永久生效。 + +## 19. 已知的既存缺陷(非設計問題) + +- ✓ **已修**(#28)側欄印的是**渲染位置**而非該視圖的編號。`DEFAULT_ORDER` 有 11 項、只有 8 項有快捷鍵,所以範圍/戰利品/標記一直印著 9、10、11——都是開不了任何東西的號碼——而設定列也印 9,同一畫面上兩個 9 +- ✓ **已修**(#28)⌘K 與快捷鍵面板都以 view id 組標籤鍵(`sidebar.http_history`),該鍵兩本語言檔都沒有,所以那一列直接把鍵名印給操作員。字面鍵掃描器看不到動態鍵,而 `shortcuts.test.ts` 的 fixture 是手抄的八項清單,漏掉最新兩個視圖 +- ✓ **已修**(#26)`marker:create` 丟掉 `atTimestamp`;標記事件發布時未 `bypassPause`(暫停中寫的標記進了鏈卻不顯示);標記文字沒有 redaction spans(第四層因此永遠遮不掉標記備註裡的密碼) +- ✓ **已修**(#28)TerminalView 的分頁清單在元件本地 state,離開再回來會再 spawn 一個 pty 並孤兒化前一個——每次進出漏一個 shell - `v0.14.0` per-row tier glyph 的已上鏈列用 `zinc-700` (`#3f3f46`) 於 `#0a0a0a`,約 **1.7:1**,遠低於 3:1。依例外報告原則:已上鏈是預設不畫字符,只有 logged 列畫 `⌇`,用 `#9a9aa4` - CDP 設定指引裡的 `--remote-debugging-port=9222` 是硬寫的,使用者改過埠號後照抄會失敗——指令中的路徑與埠號必須是當前專案的實際值 - 快捷鍵表分散硬寫在監聽器、側欄、儀表板與 `?` 面板四處,已經漂移過一次(Settings 鎖定 ⌘9 那次)。須從單一來源(`lib/shortcuts.ts`)產生 - -## 21. 規則測試(進 CI) - -設計稿列七條,沿用 `lane-colours.test.ts` 從原始碼解析的作法。**repo 現況:六條已有,一條本次補上。** - -| # | 規則 | repo 測試 | -|---|---|---| -| 1 | 文字 ≥4.5:1、非文字 ≥3:1 | `design-tokens.test.ts` | -| 2 | 填色一律配深色字 | `buttons.test.ts` | -| 3 | 白字在每個填色上**必不過** AA(反向斷言) | `buttons.test.ts:117` + 全 repo 無 `text-white` | -| 4 | 字級下限 13px | `design-tokens.test.ts:94` | -| 5 | 泳道單色 | `lane-colours.test.ts` | -| 6 | 危險紅不上數值(`tabular-nums` 永不配 danger) | `danger-not-on-numbers.test.ts`(本次新增) | -| 7 | 同一動作區不得同時實心品牌紅與實心危險紅 | `confirm-dialog.test.tsx` / `buttons.test.ts` | - -PR 模板改勾「測試存在且綠」。 - -## 22. 漸進揭露 - -一條規則:**名詞在它的資料存在之前不出現。** 第一天側欄只有四格(儀表板、時間軸、終端機、設定)。隱藏不等於不可達——⌘K 一律列出全部視圖,快捷鍵照常開啟原本的頁面,外觀頁還有一個總開關。 - -**解鎖對照表**(`lib/visibility.ts`;括號內是該訊號所在的層) - -| 名詞 | 等到什麼 | 為何是這個訊號,不是更寬鬆的那個 | -|---|---|---| -| 搜尋 | 任一筆「操作員做的事」(兩層) | 判定用 `EVIDENCE_SQL` 這個**正面**述詞,不是「非 housekeeping」。alert runtime 每次開專案都會啟動,IP policy 無條件送出第一筆判定(離線也會送 `unknown`),所以幾秒內就會有一筆非 housekeeping 的上鏈列 | -| 逐字稿 | 已完成的指令,或任一 agent 回合 | 就是該頁實際渲染的兩種列 | -| 目標 | 由**指令**推導出的目標 ≥1(上鏈) | proxy addon 對每筆 HTTP/DNS 都會蓋 `target_id`,連線監控對每個 socket 也會——跨型別去算,一次瀏覽器開頁就會解鎖,正好與本節的規則相反 | -| 範圍 | 同上,≥2 | | -| 戰利品/截圖 | 自己那一型的上鏈列 | `loot:getCount` 是記憶體計數器,重啟歸零,不是資料 | -| 標記 | 一筆 `quickmarks` 列 | 該頁只列這張表;`marker` 事件是另一個儲存區,而且可由外部 POST,用它會讓外部工具解鎖一張空頁 | -| HTTP | logged 層的 `http_request_start` / `http_response` | 該頁只查 logged 層。上鏈的 `scanner:connection` 會解鎖一張永遠空著的頁 | -| 層級字符(Inspector chip) | 任一 logged 列,或 `system.retention_pruned_logged` 稽核列 | 稽核列比它描述的資料活得久,所以 logged 層被清空後字符不會消失——否則會被讀成「這個層不見了」 | -| 錨定/跳板節點 | 無需程式碼 | 儀表板的 ⚓ 子行與 HUD 膠囊本來就以資料為條件 | - -**工程約束** -- 可見性由資料推導、**不存使用者狀態**(唯一例外是 5c);`visibility.ts` 是純模組,不碰 React、window 或 core。 -- **單調**:出現過的名詞不再消失。logged 層 30 天後會被清,頁面若因此消失會被讀成證據被銷毀。 -- ⌘ 編號取自 `DEFAULT_ORDER` 的位置,不是渲染位置——隱藏一列不會讓其他列換號。 -- `null` 訊號代表「還沒問到」,不等於「還沒有」:外殼會等專案與訊號都回來才畫,否則成熟專案會閃一下四格側欄。探測失敗時**全部顯示**。 -- 重新探測有兩道閘:只有可能打開尚未開啟之閘的列才算,且要等該批事件安定;全開之後解除訂閱。 - -**5c** 外觀頁的「一次顯示所有頁面」是**按專案**存的(localStorage)。切專案是同源 reload,全域鍵會讓一次勾選對之後每個案子永久生效;也不放 config.yaml,因為它會隨交接檔旅行。 - -**9a 首次執行單一路徑**:一個畫面一件事——在內建終端機打一個指令,右欄的時間軸長條亮起。十個擷取來源降為底下一個折疊區(原封不動的 `CaptureHealthCard`)。畫面狀態是**閂鎖**的,不是直接讀 `firstRun`:後者在第一列進來的瞬間就翻面,而那正是這個畫面要讓人看到的一刻。開始打字十秒後仍無事發生,右欄改說真正的原因(內建終端機的掛勾需要 python3 與 curl)。 +- **未修,已記錄**:Timeline 的 `eventCompare` 同毫秒 tiebreak 是死碼——`padMonoNs` 寫出 `bootMs-ns` 形式,`BigInt()` 直接丟例外,所以同毫秒事件實際以 UUID 排序。修它會重排整個面板上所有同毫秒配對,與標記修訂無關,另案處理 +- **未修,已記錄**:`marker.atTimestamp` 的 i18n 用單大括號 `{time}`,而插值只認 `{{var}}`,對每位操作員都是字面渲染 --- # 實作檢查表(三期,帶依賴) +> ✓ **三期皆已併入 `main`**(PR #23 為第一至三期與核心修訂的大合併)。以下保留為當時的拆解與驗收條件。 + 三期 = 三個 PR,每期一次大合併。第一期改 tokens 會同時動到數十個檔,拆太細會出現新舊並存的中間狀態。 ## 第一期 · Tokens 與字型(無前置依賴) -- [ ] `tailwind.config.js`:`redlog` 命名色改為新值,新增 `danger` / `danger-hover` / `lane` / `text-faint` -- [ ] `tailwind.config.js`:`fontFamily` 加入 `Noto Sans TC` / `JetBrains Mono`;打包字型檔 -- [ ] `tailwind.config.js`:`fontSize` 的 `xs`/`sm`/`base` 抬到 13/15/17px -- [ ] `index.css`:`html` 根字級 17px → 16px(字級下限已在 `fontSize` 抬過一次,兩處疊加會過大) -- [ ] `index.css`:body 背景與文字改新 token;保留既有的 `user-select` 殼層規則不動 -- [ ] `index.css`:新增 `--row-h` / `--pad` / `--gap` / `--section-gap` 與 `[data-density='tight']` -- [ ] `index.css`:捲軸 6px → 10px -- [ ] 清除全部 `text-[10px]` / `text-[11px]`(約 155 處),HUD 例外保留至 11px -- [ ] 次級文字一律 `text-redlog-text-dim`,不得再用 `zinc-600` / `zinc-700` 承載可讀文字 -- [ ] `Timeline.tsx`:`LANE_COLORS` 全部改 `#6e6e78`;狀態色改由事件本身承載 -- [ ] `lib/hud.ts`:`muted` 由 `#5f7a82` 抬到可讀值;HUD 標籤字下限 11px -- [ ] 導入 Lucide,替換側欄與元件的 Unicode 幾何符號(狀態/標記類保留符號者需個別確認) -- [ ] `TierBadge`:已上鏈列不畫字符,logged 列用 `#9a9aa4` +- [x] `tailwind.config.js`:`redlog` 命名色改為新值,新增 `danger` / `danger-hover` / `lane` / `text-faint` +- [x] `tailwind.config.js`:`fontFamily` 加入 `Noto Sans TC` / `JetBrains Mono`;打包字型檔 +- [x] `tailwind.config.js`:`fontSize` 的 `xs`/`sm`/`base` 抬到 13/15/17px +- [x] `index.css`:`html` 根字級 17px → 16px(字級下限已在 `fontSize` 抬過一次,兩處疊加會過大) +- [x] `index.css`:body 背景與文字改新 token;保留既有的 `user-select` 殼層規則不動 +- [x] `index.css`:新增 `--row-h` / `--pad` / `--gap` / `--section-gap` 與 `[data-density='tight']` +- [x] `index.css`:捲軸 6px → 10px +- [x] 清除全部 `text-[10px]` / `text-[11px]`(約 155 處),HUD 例外保留至 11px +- [x] 次級文字一律 `text-redlog-text-dim`,不得再用 `zinc-600` / `zinc-700` 承載可讀文字 +- [x] `Timeline.tsx`:`LANE_COLORS` 全部改 `#6e6e78`;狀態色改由事件本身承載 +- [x] `lib/hud.ts`:`muted` 由 `#5f7a82` 抬到可讀值;HUD 標籤字下限 11px +- [x] 導入 Lucide,替換側欄與元件的 Unicode 幾何符號(狀態/標記類保留符號者需個別確認) +- [x] `TierBadge`:已上鏈列不畫字符,logged 列用 `#9a9aa4` **驗收**:`vitest` 全綠 · `playwright` 全綠 · 三平台截圖人工目視 · 新增對比度與最小字級的回歸測試(沿用 `test/lane-colours.test.ts` 從原始碼解析斷言的作法) ## 第二期 · 行為規則(依賴第一期的 tokens 與字級) -- [ ] 錯誤訊息三段式;`toast(e.message)` 全部改掉(約 50 處) -- [ ] Toast:錯誤不自動消失、同類合併、上限 3、`aria-live` -- [ ] 狀態列〈需要注意 N〉/〈待處理〉兩層指示器 -- [ ] 時間格式統一;相對時間限縮到新鮮度欄位;匯出 ISO 8601 -- [ ] 文字截斷一律附 `title`;長內容可展開 -- [ ] 危險操作三級;`ConfirmDialog` 加勾選框與輸入確認兩種型態 + focus trap -- [ ] 可復原動作改 Toast 附復原(含三項延遲執行) -- [ ] 清單頁鍵盤操作(方向鍵/Enter/⌘↩/Esc) -- [ ] 時間軸滑鼠縮放改以游標為錨;補雙指開合與雙擊縮放 -- [ ] 時間軸鍵盤移動(← → / ↑ ↓ / Shift+← → / Home End / + − 0 / Enter)+ 可見選取框 -- [ ] 快捷鍵表集中到 `lib/shortcuts.ts`,補齊 Windows/Linux 欄,餵給監聽器/側欄/儀表板/`?` 面板 -- [ ] HUD 透明度、位置(頂部置中偏右)、每螢幕記憶、穿透按鈕 + `⌘⇧P` 退出 -- [ ] 右鍵落標記改為右鍵菜單項 -- [ ] 致命錯誤畫面 + 診斷資訊清洗(路徑相對化、`` / ``)+ 送出前預覽 -- [ ] 刪除〈顯示 N 個機密〉與本機遮蔽;確認匯出路徑的 redaction 仍在 -- [ ] Token 改寫入 `~/.redlog/tokens/` 並在檔案管理員點亮 -- [ ] 擷取來源的雙軸控制與狀態組合對應的單一主要動作;安裝失敗顯示真正原因;指令中的埠號與路徑取當前專案實際值 +- [x] 錯誤訊息三段式;`toast(e.message)` 全部改掉(約 50 處) +- [x] Toast:錯誤不自動消失、同類合併、上限 3、`aria-live` +- [x] 狀態列〈需要注意 N〉/〈待處理〉兩層指示器 +- [x] 時間格式統一;相對時間限縮到新鮮度欄位;匯出 ISO 8601 +- [x] 文字截斷一律附 `title`;長內容可展開 +- [x] 危險操作三級;`ConfirmDialog` 加勾選框與輸入確認兩種型態 + focus trap +- [x] 可復原動作改 Toast 附復原(含三項延遲執行) +- [x] 清單頁鍵盤操作(方向鍵/Enter/⌘↩/Esc) +- [x] 時間軸滑鼠縮放改以游標為錨;補雙指開合與雙擊縮放 +- [x] 時間軸鍵盤移動(← → / ↑ ↓ / Shift+← → / Home End / + − 0 / Enter)+ 可見選取框 +- [x] 快捷鍵表集中到 `lib/shortcuts.ts`,補齊 Windows/Linux 欄,餵給監聽器/側欄/儀表板/`?` 面板 +- [x] HUD 透明度、位置(頂部置中偏右)、每螢幕記憶、穿透按鈕 + `⌘⇧P` 退出 +- [x] 右鍵落標記改為右鍵菜單項 +- [x] 致命錯誤畫面 + 診斷資訊清洗(路徑相對化、`` / ``)+ 送出前預覽 +- [x] 刪除〈顯示 N 個機密〉與本機遮蔽;確認匯出路徑的 redaction 仍在 +- [x] Token 改寫入 `~/.redlog/tokens/` 並在檔案管理員點亮 +- [x] 擷取來源的雙軸控制與狀態組合對應的單一主要動作;安裝失敗顯示真正原因;指令中的埠號與路徑取當前專案實際值 **驗收**:同上 + 錯誤路徑的 e2e(安裝失敗、錨定失敗、鏈斷)· 鍵盤操作 e2e · 無障礙檢查(focus trap、`aria-live`) ## 第三期 · 結構重整(依賴第二期的行為規則) -- [ ] 側欄順序固定、數字上欄、移除拖曳排序(或改為釘選) -- [ ] 設定改左清單 + 右內容;外掛/市集/發行者/撤銷清單從四層攤平到兩層;頂部搜尋框 -- [ ] 側欄搜尋頁刪除;⌘K 命令面板(導航/模糊搜尋/動作/模式與密度/專案/最近指令) -- [ ] ⌘F 頁內篩選 -- [ ] 儀表板改「一屏一個問題」+ 寬屏 1400px 居中 -- [ ] 時間軸事件流模式 + 折疊門檻 + 模式列 -- [ ] 時間軸 Inspector 三分頁;工具列八組開關收成檢視模式下拉;稽核 chip 併入稽核模式 -- [ ] 跨頁互連五條 + 麵包屑返回 -- [ ] 逐字稿新預設(首行預覽 + 條件自動展開) -- [ ] 範圍頁重做(允許清單 + 排除清單 + 可展開違規) -- [ ] 目標頁改 SQL 聚合 -- [ ] 全部清單改無限捲動 + 虛擬列表 +「已載入 N/共 M」 -- [ ] 匯出六處收成一個下拉 -- [ ] 終端機分頁資訊、⌘+/⌘−、⌘F、可復原關閉 -- [ ] 回放器改狀態列上方抽屜 -- [ ] 空狀態三件套套用到全部空狀態 -- [ ] 外掛信任流程改逐一信任 + 權限清單 + 指紋 -- [ ] 卡片左側色塊改版(影響所有卡片) -- [ ] 移除狀態列〈⏱ 時戳〉 -- [ ] 字標改單一 `REDL(●)G`(標題列 + Project Picker);app 圖示/`.icns`/`.ico` 需向量原稿,不屬本期 +- [x] 側欄順序固定、數字上欄、移除拖曳排序(或改為釘選) +- [x] 設定改左清單 + 右內容(五組十二頁,見 §14);外掛/市集/發行者/撤銷清單從四層攤平到兩層;頂部搜尋框 —— ▲ 市集與發行者已整個移除 +- [ ] 側欄搜尋頁刪除;⌘K 命令面板(導航/模糊搜尋/動作/模式與密度/專案/最近指令) —— ▲ ⌘K 已做;搜尋頁**保留**(見 §10) +- [x] ⌘F 頁內篩選 +- [x] 儀表板改「一屏一個問題」+ 寬屏 1400px 居中 +- [x] 時間軸事件流模式 + 折疊門檻 + 模式列 +- [ ] 時間軸 Inspector 三分頁;工具列八組開關收成檢視模式下拉;稽核 chip 併入稽核模式 —— ▲ 檢視模式已 revert(見 §6);Inspector 為底部面板、無分頁 +- [x] 跨頁互連五條 + 麵包屑返回 +- [x] 逐字稿新預設(首行預覽 + 條件自動展開) +- [x] 範圍頁重做(允許清單 + 排除清單 + 可展開違規) +- [x] 目標頁改 SQL 聚合 +- [x] 全部清單改無限捲動 + 虛擬列表 +「已載入 N/共 M」 +- [x] 匯出六處收成一個下拉 +- [x] 終端機分頁資訊、⌘+/⌘−、⌘F、可復原關閉 +- [x] 回放器改狀態列上方抽屜 +- [x] 空狀態三件套套用到全部空狀態 +- [x] 外掛信任流程改逐一信任 + 權限清單 + 指紋 —— ▲ 無 registry/市集 +- [x] 卡片左側色塊改版(影響所有卡片) +- [x] 單一字標 `REDL(●)G` 取代「R 方塊 + REDLOG」並列(標題列、Project Picker),依 §4 的 em 幾何與 `box-sizing: border-box` +- [x] 移除狀態列〈⏱ 時戳〉 **驗收**:同上 + 資訊架構走查(每個設定項 ≤2 層可達)· 虛擬列表在 28k 事件下的捲動效能 · 全畫面截圖比對 diff --git a/docs/design-project-sync.md b/docs/design-project-sync.md index 0747002b..6a210745 100644 --- a/docs/design-project-sync.md +++ b/docs/design-project-sync.md @@ -15,6 +15,25 @@ path: src/renderer date: 2026-08-24T02:30:00Z +### 2026-09-04 · 回寫設計專案(單向鏡像首次雙向) + +操作員登入 `/design-login` 後,本次把 `github.md` 寫回設計專案(8a/8b/9a/9b/5c 的落地 +狀態、命名裁決、收緊後的解鎖條件、以及順手修掉的既有缺陷)。 + +**方向是單向的,兩邊各取所長。** 設計專案的 `docs/UIUX-STANDARD.md` 沒有被覆寫——那份有 +22 節,整份寫回會蓋掉設計側的內容,規範本體仍以設計專案為著作處。反過來,repo 這份鏡像則 +**改為設計稿全文**(22 節,2026-09-04 取回),原本只有 11 節的部分鏡像作廢。 + +鏡像加上、也只加上**實作狀態註記**:`✓ 已實作` 與 `▲ 分歧`(附原因與 commit)。敘述本身 +一字不改。這樣 repo 端讀到的是完整規範,而不會重新宣稱程式碼裡沒有的東西——§6 的三種檢視 +模式已 revert、搜尋頁保留、雲端分享/webhook/市集已移除,這四處若照抄設計稿就會是假的。 + +順帶修掉設計稿在傳輸中混進的簡體字與一處錯字(单一/实際/琳璀色/「進定要表在 9b」), +repo 全庫是繁體。 + +**留給設計端裁決的一項**:8b 記為部分完成——設計稿的「標記」畫面對應的 `quickmarks` 表仍可 +覆寫,而 `url` 欄位只存在於該表。要嘛把它也改成附加式修訂,要嘛明確標成「書籤表,不是紀錄」。 + ### 2026-09-04 · 9a/9b/5c 漸進揭露落地 §22 上線。第一天側欄四格,其餘頁面在自己的資料出現後才列出;隱藏不等於不可達(⌘K @@ -136,7 +155,7 @@ append-only trigger 本來就不允許,這正是把修訂做成新事件而非 - **9b 漸進揭露(§22)**:~~待做~~ → **已完成**(同上)。 - **5c「一次顯示所有頁面」開關**:~~待做~~ → **已完成**(同上,按專案存)。 -**設計專案該被告知的(本次無法回寫:DesignSync 需 `/design-login`)** +**設計專案該被告知的**(2026-09-04 已回寫 `github.md`,見該檔 2026-09-04 條目) 核心修訂(防竄改 → 可知性)、三期已全部完成、上述五處分歧。設計稿最後一則建議「實作第一期 tokens」已過時——三期皆併入 `main`。 抽取方式備註:DesignSync 無授權、沙盒瀏覽器撞登入牆、Chrome 擴充套件對 design SPA 的分頁反覆 park;最終以設計專案的對話紀錄 + 編輯器前 47 行(§0、§1 逐字)為據,其餘章節為敘述層級對帳。