From fb63d9f0c4478855cd9a98f4480c506006bdf595 Mon Sep 17 00:00:00 2001 From: richblack Date: Tue, 28 Jul 2026 12:03:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(t89=20=F0=9F=94=B4=F0=9F=94=B4):=20?= =?UTF-8?q?=E7=B4=94=E4=B8=AD=E6=96=87=E8=B3=87=E6=96=99=E5=A4=BE=E5=90=8D?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E9=9D=9C=E9=BB=98=E4=BD=B5=E9=80=B2=20kb=20?= =?UTF-8?q?=E5=BA=AB=E2=80=94=E2=80=94slug=20=E7=A9=BA=E6=94=B9=E7=94=9F?= =?UTF-8?q?=E8=B7=AF=E5=BE=91=E7=A9=A9=E5=AE=9A=E9=9B=9C=E6=B9=8A=E9=8D=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit leo 07-28 實測:「官方總圖」被顯示成「知識庫」=slug 後為空退到 kb; 兩個純中文資料夾會塌縮同庫(靜默混庫,B5 分庫隔離形同虛設)。 修:libraryFor 第三優先從退 c.Library/kb 改為 lib_+sha256(絕對路徑)前6hex—— 路徑穩定故鍵穩定、不同路徑必不同鍵;後端庫名鍵限 A-Za-z0-9_- 相容。 測試(t52_library_test.go):純中文→lib_雜湊非kb/兩中文夾不同鍵/同夾重跑鍵穩定/ ASCII 行為不變/明列對映仍最優先。collector go test 全綠(總管親跑)。 (實作=子 CC headless;審查+commit=總管) --- direct.go | 15 ++++---- t52_library_test.go | 83 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 87 insertions(+), 11 deletions(-) diff --git a/direct.go b/direct.go index 2dbbf11..e946c48 100644 --- a/direct.go +++ b/direct.go @@ -61,7 +61,7 @@ type DirectConfig struct { } // librarySlug 把資料夾名轉成合法庫名(A-Za-z0-9_-;中文等非 ASCII 轉為底線分段)。 -// 空結果(如純中文名)回 "",交由 libraryFor 退回後備值——不硬造出無意義的庫名。 +// 空結果(如純中文名)回 "",由 libraryFor 改生路徑穩定雜湊鍵(t89)。 func librarySlug(folder string) string { base := filepath.Base(strings.TrimRight(folder, string(filepath.Separator))) var b strings.Builder @@ -85,7 +85,12 @@ func librarySlug(folder string) string { } // libraryFor 決定某個看守資料夾的資料該蓋哪個庫章(t52)。 -// 優先序:config.Libraries 明列 > 資料夾名 slug > config.Library(後備,預設 kb)。 +// 優先序:config.Libraries 明列 > 資料夾名 slug > 路徑穩定雜湊鍵(t89)。 +// +// t89(leo 2026-07-28 實測):純中文資料夾名(如「官方總圖」)slug 後為空字串, +// 若退到 c.Library/"kb",兩個不同純中文資料夾會塌縮進同一個庫(靜默混庫)。 +// 後端庫名鍵限 A-Za-z0-9_-(Arcrun KBDB 約束),故改生 lib_+sha256(絕對路徑) 前 6 hex—— +// 路徑穩定所以鍵穩定;兩個不同路徑必然不同鍵。 func (c *DirectConfig) libraryFor(absRoot string) string { if c.Libraries != nil { if lib, ok := c.Libraries[absRoot]; ok && strings.TrimSpace(lib) != "" { @@ -95,10 +100,8 @@ func (c *DirectConfig) libraryFor(absRoot string) string { if slug := librarySlug(absRoot); slug != "" { return slug } - if c.Library != "" { - return c.Library - } - return "kb" + sum := sha256.Sum256([]byte(absRoot)) + return "lib_" + hex.EncodeToString(sum[:3]) } // expandHome 把開頭的 `~/`(或單獨的 `~`)展開成使用者家目錄的絕對路徑。 diff --git a/t52_library_test.go b/t52_library_test.go index 1fa730e..f3950e5 100644 --- a/t52_library_test.go +++ b/t52_library_test.go @@ -1,14 +1,25 @@ package main -import "testing" +import ( + "crypto/sha256" + "encoding/hex" + "testing" +) + +// stableHashLib 重現 libraryFor 對純中文資料夾的穩定雜湊鍵(t89 驗收用)。 +func stableHashLib(absPath string) string { + sum := sha256.Sum256([]byte(absPath)) + return "lib_" + hex.EncodeToString(sum[:3]) +} func TestLibraryPerFolder(t *testing.T) { cfg := &DirectConfig{Library: "kb"} cases := map[string]string{ - "/Users/x/Desktop/finance": "finance", - "/Users/x/Desktop/HR Docs": "hr_docs", - "/Users/x/Desktop/官方總圖": "kb", - "/Users/x/Desktop/test 01": "test_01", + "/Users/x/Desktop/finance": "finance", + "/Users/x/Desktop/HR Docs": "hr_docs", + // t89:純中文資料夾名不再退 kb,改生穩定唯一鍵 + "/Users/x/Desktop/官方總圖": stableHashLib("/Users/x/Desktop/官方總圖"), + "/Users/x/Desktop/test 01": "test_01", } for in, want := range cases { if got := cfg.libraryFor(in); got != want { @@ -20,3 +31,65 @@ func TestLibraryPerFolder(t *testing.T) { t.Errorf("明列對映應優先,got %q", got) } } + +// ── t89 五條驗收測試 ──────────────────────────────────────────────────────── + +// ①純中文資料夾 → lib_+6hex,非 "kb" +func TestT89ChineseFolderNotKb(t *testing.T) { + cfg := &DirectConfig{Library: "kb"} + got := cfg.libraryFor("/Users/x/Desktop/官方總圖") + if got == "kb" { + t.Errorf("純中文資料夾不應退到 'kb',got %q", got) + } + if len(got) != len("lib_")+6 || got[:4] != "lib_" { + t.Errorf("預期格式 lib_<6hex>,got %q", got) + } +} + +// ②兩個不同純中文資料夾 → 不同鍵(不混庫) +func TestT89TwoChineseFoldersDifferentKeys(t *testing.T) { + cfg := &DirectConfig{Library: "kb"} + k1 := cfg.libraryFor("/Users/x/Desktop/官方總圖") + k2 := cfg.libraryFor("/Users/x/Desktop/人事資料") + if k1 == k2 { + t.Errorf("不同純中文資料夾必須對映不同鍵,got k1=%q k2=%q", k1, k2) + } +} + +// ③同一路徑重跑 → 鍵穩定(冪等) +func TestT89SameFolderStableKey(t *testing.T) { + cfg := &DirectConfig{Library: "kb"} + k1 := cfg.libraryFor("/Users/x/Desktop/官方總圖") + k2 := cfg.libraryFor("/Users/x/Desktop/官方總圖") + if k1 != k2 { + t.Errorf("同路徑重跑必須回傳同一鍵,got %q vs %q", k1, k2) + } +} + +// ④ASCII 資料夾行為不變(test 01 → test_01) +func TestT89ASCIIFolderUnchanged(t *testing.T) { + cfg := &DirectConfig{Library: "kb"} + cases := map[string]string{ + "/Users/x/Desktop/finance": "finance", + "/Users/x/Desktop/test 01": "test_01", + "/Users/x/Desktop/HR Docs": "hr_docs", + } + for in, want := range cases { + if got := cfg.libraryFor(in); got != want { + t.Errorf("libraryFor(%q) = %q, want %q", in, got, want) + } + } +} + +// ⑤明列 Libraries 對映仍最優先(即使是純中文資料夾) +func TestT89ExplicitMappingWins(t *testing.T) { + cfg := &DirectConfig{ + Library: "kb", + Libraries: map[string]string{ + "/Users/x/Desktop/官方總圖": "official", + }, + } + if got := cfg.libraryFor("/Users/x/Desktop/官方總圖"); got != "official" { + t.Errorf("明列對映應優先,got %q", got) + } +}