feat(console): 分流台勾掉/還原——雙向銷案(console 勾掉=終局,萃取端絕不復活) #42

Merged
Leo merged 1 commits from feat/console-triage-checkoff into main 2026-07-08 15:32:35 +00:00
Owner

[總管-subagent]PR#41 分流台上線後的勾掉(check-off)功能,leo 2026-07-08 拍板四點全數落地。

改了什麼

  1. 勾掉按鈕(需求 1):三欄每筆 todo/inbox 項右側 44px 圓形 ✓ 鈕(手機好按)。按下 → 後端把該 KBDB entry 的 content JSON statusdone + 加 checked_via:"console"checked_at 時間戳,其餘欄位原樣保留;回寫成功才改本地狀態重繪,該筆立即從三欄移出(done 預設隱藏=既有機制),失敗誠實 toast、按鈕解鎖可重試(不樂觀假裝)。
  2. console session 保護的小端點(需求 2):POST /console/triage-check(body {entry_id, action?:"check"|"restore"}),沿用 triage-data 同款 validateConsoleSession。瀏覽器沒有 KBDB token → PATCH 由 server 端做(kbdbBase 慣例);先 GET 原 entry 再整串回寫(KBDB PATCH content 是給什麼存什麼,不先讀就會蓋掉 text/marker/owner_tier)。另守兩道邊界:owner_id 必須=CONSOLE_TENANT(非本租戶回 404 不洩漏存在性)、entry_type 限 todo/inbox(這不是泛用 entry 改寫器)。
  3. 雙向銷案語意(需求 3,死循環防呆——已寫進 applyTriageCheck 與 route 的代碼註解,萃取端配合同一套規約):
    • console 勾掉=終局checked_via:"console"):即使 Logseq 原文還是 TODO,萃取端也絕不復活它(不改回 new、不重灌覆蓋)——否則「console 勾掉→下輪萃取又出現」死循環。
    • Logseq 那邊改 DONE 的,由萃取端 PATCH status:donechecked_via:"logseq")。同一個 status slot、兩個來源靠 checked_via 溯源。
    • console 只需忠實顯示非 done 項。
  4. 誤勾救濟(需求 4):「顯示已完成」清單裡每筆加「還原」鈕——status 改回 new移除 checked_via/checked_at(回到未銷案的乾淨狀態,不留殘欄位讓萃取端誤讀)。

分層照舊:改寫邏輯=lib/console-triage-model.ts 純函式 applyTriageCheck,route 只做 IO(session 閘+GET→PATCH)。

測試證據

  • 純函式 7 例tests/console-triage-model.test.ts,先紅後綠:實作前 7 failed → 實作後全綠):check 保留其餘欄位/inbox 契約不掉 from/非 JSON 殘資料包 {"text":原文} 不丟字/已 done 再勾冪等/restore 移除 checked_* 保留其餘/restore 非 JSON/null content 防禦。
  • route 層 8 例(新檔 tests/console-triage-check-route.test.ts,fetchMock 假 host kbdb.test + disableNetConnect()——測試絕不外連、更不碰官方 uncle6 fallback):無 Bearer 401/壞 token 401/缺 entry_id 400/整串回寫欄位保留+checked_via:console/他租戶 404 不 PATCH/wiki_card 400 不 PATCH/KBDB 404 透傳/restore 整串驗證 {text,from,status:new}
  • 全套:113 passed / 1 failed——唯一 fail 是 executor.test.ts「不存在的零件回傳失敗」文案斷言,main 基線就紅(已 stash 驗證,與本 PR 無關)。tsc --noEmit 錯誤數與 main 相同(6 個,全在 validate.ts/webhooks-named.ts,pre-existing)。
  • 前端煙測:渲染 console HTML 抽出兩段 <script>node --check 全過(防 template string 手滑)。

附帶

  • wrangler.test.tomlSESSIONS_KV KV mock + KBDB_BASE_URL=https://kbdb.testCONSOLE_TENANT=leo 測試 vars(route 測試需要)。

不部署——merge 後由 leo21c wrangler 直推線走(本 PR 只有 code+測試)。

🤖 Generated with Claude Code

[總管-subagent]PR#41 分流台上線後的勾掉(check-off)功能,leo 2026-07-08 拍板四點全數落地。 ## 改了什麼 1. **勾掉按鈕**(需求 1):三欄每筆 todo/inbox 項右側 44px 圓形 ✓ 鈕(手機好按)。按下 → 後端把該 KBDB entry 的 content JSON `status` 改 `done` + 加 `checked_via:"console"` + `checked_at` 時間戳,**其餘欄位原樣保留**;回寫成功才改本地狀態重繪,該筆立即從三欄移出(done 預設隱藏=既有機制),失敗誠實 toast、按鈕解鎖可重試(不樂觀假裝)。 2. **console session 保護的小端點**(需求 2):`POST /console/triage-check`(body `{entry_id, action?:"check"|"restore"}`),沿用 triage-data 同款 `validateConsoleSession`。瀏覽器沒有 KBDB token → PATCH 由 server 端做(kbdbBase 慣例);**先 GET 原 entry 再整串回寫**(KBDB PATCH content 是給什麼存什麼,不先讀就會蓋掉 text/marker/owner_tier)。另守兩道邊界:`owner_id` 必須=CONSOLE_TENANT(非本租戶回 404 不洩漏存在性)、`entry_type` 限 todo/inbox(這不是泛用 entry 改寫器)。 3. **雙向銷案語意**(需求 3,死循環防呆——已寫進 `applyTriageCheck` 與 route 的代碼註解,萃取端配合同一套規約): - console 勾掉=**終局**(`checked_via:"console"`):即使 Logseq 原文還是 TODO,萃取端也**絕不復活它**(不改回 new、不重灌覆蓋)——否則「console 勾掉→下輪萃取又出現」死循環。 - Logseq 那邊改 DONE 的,由萃取端 PATCH `status:done`(`checked_via:"logseq"`)。同一個 status slot、兩個來源靠 checked_via 溯源。 - console 只需忠實顯示非 done 項。 4. **誤勾救濟**(需求 4):「顯示已完成」清單裡每筆加「還原」鈕——status 改回 `new`、**移除 checked_via/checked_at**(回到未銷案的乾淨狀態,不留殘欄位讓萃取端誤讀)。 分層照舊:改寫邏輯=`lib/console-triage-model.ts` 純函式 `applyTriageCheck`,route 只做 IO(session 閘+GET→PATCH)。 ## 測試證據 - **純函式 7 例**(`tests/console-triage-model.test.ts`,先紅後綠:實作前 7 failed → 實作後全綠):check 保留其餘欄位/inbox 契約不掉 from/非 JSON 殘資料包 `{"text":原文}` 不丟字/已 done 再勾冪等/restore 移除 checked_* 保留其餘/restore 非 JSON/null content 防禦。 - **route 層 8 例**(新檔 `tests/console-triage-check-route.test.ts`,fetchMock 假 host `kbdb.test` + `disableNetConnect()`——測試**絕不外連**、更不碰官方 uncle6 fallback):無 Bearer 401/壞 token 401/缺 entry_id 400/整串回寫欄位保留+checked_via:console/他租戶 404 不 PATCH/wiki_card 400 不 PATCH/KBDB 404 透傳/restore 整串驗證 `{text,from,status:new}`。 - **全套**:113 passed / 1 failed——唯一 fail 是 `executor.test.ts`「不存在的零件回傳失敗」文案斷言,**main 基線就紅**(已 stash 驗證,與本 PR 無關)。`tsc --noEmit` 錯誤數與 main 相同(6 個,全在 validate.ts/webhooks-named.ts,pre-existing)。 - **前端煙測**:渲染 console HTML 抽出兩段 `<script>` 過 `node --check` 全過(防 template string 手滑)。 ## 附帶 - `wrangler.test.toml` 補 `SESSIONS_KV` KV mock + `KBDB_BASE_URL=https://kbdb.test`/`CONSOLE_TENANT=leo` 測試 vars(route 測試需要)。 **不部署**——merge 後由 leo21c wrangler 直推線走(本 PR 只有 code+測試)。 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Leo added 1 commit 2026-07-08 15:31:02 +00:00
leo 2026-07-08 拍板,PR#41 分流台的後續:

- lib/console-triage-model.ts:applyTriageCheck 純函式(check→status:done+
  checked_via:console+checked_at;restore→status:new+移除 checked_via/checked_at;
  content 非 JSON 殘資料包成 {"text":原文} 不丟字)。雙向銷案語意寫死在註解:
  console 勾掉=終局,即使 Logseq 原文還是 TODO 萃取端也絕不復活;Logseq 改 DONE
  由萃取端 PATCH(checked_via:logseq);console 只忠實顯示非 done 項。
- console-dashboard.ts:POST /console/triage-check(沿 triage-data 同款 session 驗證;
  瀏覽器沒 KBDB token 故 server 端做 PATCH——先 GET 原 entry 整串回寫防蓋掉別的欄位;
  守 owner_id=CONSOLE_TENANT 與 entry_type∈{todo,inbox} 兩道邊界)。
- console.ts:每筆待辦 44px 圓形勾掉鈕(手機好按)+done 清單「還原」鈕(誤勾救濟);
  後端回寫成功才改本地狀態移出三欄(done 預設隱藏既有機制),失敗誠實 toast 可重試。
- 測試:applyTriageCheck 7 例(先紅後綠)+ route 層 8 例(fetchMock 假 host
  kbdb.test + disableNetConnect,絕不外連;驗 session 閘/整串回寫/邊界/restore)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Leo merged commit 1c4f79b623 into main 2026-07-08 15:32:35 +00:00
Sign in to join this conversation.