fix(collector): daemon 不再改用戶版控中的檔案,接 repo 只讀整理好的 wiki(#105/#104)
## #105 daemon 會改用戶的檔案(不可逆,先修) 2026-08-14 21:45 實撞:InkStoneCo 在看守清單裡,daemon 回報「已把 1 張舊卡片歸位」, 實際把 system-dev/wiki/cards/autonomy/ 整個子目錄壓平改名,16 個版控中的檔案變成刪除。 真兇是 MigrateCardNames 的一句假設:「那兩個目錄從頭到尾只有 daemon 會寫」。 那句話在 vault 上成立,在 repo 上不成立——system-dev/wiki/cards/ 是 template 的規約 路徑,而 template 就是要裝進開發者自己的 repo,那裡本來就有人家自己的檔案。 - 新增 repoguard.go:`.git` 判準(含 linked worktree),與 #104 共用同一個判準源 - 版控中的資料夾一個檔都不自動動;改成記帳+講給使用者聽,出口是 collector tidy --apply - Blocked 只算「確定是我們寫的」(帶 arcrun- 標記)——報使用者自己的卡等於發假訊息 - 落卡與工作區改走 .arcrun-rag/(與 vault 同待遇),自帶 .gitignore(*) 讓它對 git 隱形 - 非版控資料夾(含 vault)行為與 #60 第三輪完全一致,不推翻前兩輪的成果 ## #104 接上開發 repo 會把上萬個原始檔排進佇列 leo 的規格:「它要辨識這個庫已經有 wiki,那就直接 ingest 了」「只有文件要讀,程式碼不用讀」。 - 新增 ingestplan.go:掃描前先問「這個資料夾是什麼」——all/curated-wiki/docs-only - 排除靠路徑身分不靠副檔名:依賴、建置產物、templatefs 範本、linked worktree、巢狀子 repo - 策略與擋掉的數字經 TriggerPayload.Plan 走進 status.json,CLI 走 stderr(排除規則要看得見) - 子專案自己的 wiki 刻意不收,但一定列出來讓使用者知道去哪裡找 - 與 TemplateOwns(把 system-dev/ 整棵當開發用的)的對撞用身分化解,不拿掉任一條: 我們代裝的資料夾沒有 .git(舊規則照舊),他自己的 repo 有(收那份 wiki) ## 實測 #105:舊版 daemon 對真 repo 跑一輪 → git status 32 行(16 個 D + 16 個 ??,與 21:45 撞到的一字不差);新版跑同一輪 → 0 行。另有真 git init 的端到端測試。 #104:造出 leo 那棵樹的形狀(InkStoneCo + products/arcrun-rag + 3 份出貨 worktree, 967 個文件檔)→ 舊版送 91 個檔(多收的全是 -wt*ship/ 裡的 templatefs 範本、 benchmark 結果、docs-site 產物),新版送 32 個,全部落在 system-dev/wiki/ 底下。 MachineMark 規約新增唯一例外 IsMachineOwnedRel:.arcrun-rag/ 底下的檔以目錄名為標記 (.gitignore 的檔名是 git 定的,改不得)。迴歸網判準同步換過去。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UUwsLkFEGN8496bZTqhjFq
This commit is contained in:
+20
-12
@@ -262,7 +262,7 @@ func assertVaultUntouched(t *testing.T, vaultDir string, before, after map[strin
|
||||
t.Logf("筆記庫裡新增的檔案(%d 個):%v", len(added), added)
|
||||
|
||||
for _, rel := range added {
|
||||
if !IsMarked(filepath.Base(rel)) {
|
||||
if !IsMachineOwnedRel(rel) {
|
||||
t.Fatalf("筆記庫裡多了一個沒帶 %q 標記的檔:%s", MachineMark, rel)
|
||||
}
|
||||
if !isHiddenRel(rel) {
|
||||
@@ -324,11 +324,19 @@ func TestVaultFootprint_WatchRootInsideVault(t *testing.T) {
|
||||
if len(added) == 0 {
|
||||
t.Fatal("這一輪什麼都沒產出——紅線是「東西照樣產出、但不撞進使用者的命名空間」")
|
||||
}
|
||||
// 卡片確實落在 docs/.arcrun-rag/... 底下(在監看根裡,且是隱藏的)。
|
||||
wantPrefix := filepath.ToSlash(filepath.Join("docs", vaultCardsRelDir)) + "/"
|
||||
// 產物一律落在 docs/.arcrun-rag/ 底下(在監看根裡,且是隱藏的),
|
||||
// 其中**卡片**還要再進一層 wiki/cards/。
|
||||
// 分兩層檢查是因為工作區裡不只有卡片:#105 起還有一份 `.gitignore`
|
||||
// (讓整個工作區對 git 隱形)。它同樣是隱藏的、同樣不撞使用者的命名空間,
|
||||
// 但它本來就不該住在 cards/ 裡。
|
||||
workspacePrefix := filepath.ToSlash(filepath.Join("docs", workspaceRelDir)) + "/"
|
||||
cardsPrefix := filepath.ToSlash(filepath.Join("docs", vaultCardsRelDir)) + "/"
|
||||
for _, rel := range added {
|
||||
if !strings.HasPrefix(rel, wantPrefix) {
|
||||
t.Fatalf("產物 %s 不在預期的隱藏卡片區 %s 底下", rel, wantPrefix)
|
||||
if !strings.HasPrefix(rel, workspacePrefix) {
|
||||
t.Fatalf("產物 %s 不在預期的隱藏工作區 %s 底下", rel, workspacePrefix)
|
||||
}
|
||||
if strings.HasSuffix(rel, ".md") && !strings.HasPrefix(rel, cardsPrefix) {
|
||||
t.Fatalf("卡片 %s 不在預期的隱藏卡片區 %s 底下", rel, cardsPrefix)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -396,7 +404,7 @@ func TestVaultFootprint_SubVaultBelowWatchRoot(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
produced++
|
||||
if !IsMarked(filepath.Base(rel)) {
|
||||
if !IsMachineOwnedRel(rel) {
|
||||
t.Fatalf("監看根上多了一個沒帶標記的檔:%s", rel)
|
||||
}
|
||||
}
|
||||
@@ -466,12 +474,12 @@ func TestMigrateCardNames_RelocatesVisibleCardsInsideVault(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Logf("收拾前:%v", relList(t, watch))
|
||||
n := MigrateCardNames(watch)
|
||||
mig := MigrateCardNames(watch)
|
||||
got := relList(t, watch)
|
||||
t.Logf("收拾後(搬了 %d 筆):%v", n, got)
|
||||
t.Logf("收拾後(搬了 %d 筆):%v", mig.Moved, got)
|
||||
|
||||
if n != 2 {
|
||||
t.Fatalf("搬了 %d 筆,want 2", n)
|
||||
if mig.Moved != 2 {
|
||||
t.Fatalf("搬了 %d 筆,want 2", mig.Moved)
|
||||
}
|
||||
for _, rel := range got {
|
||||
if !isHiddenRel(rel) {
|
||||
@@ -483,8 +491,8 @@ func TestMigrateCardNames_RelocatesVisibleCardsInsideVault(t *testing.T) {
|
||||
}
|
||||
|
||||
// 冪等:再跑一次不該有任何動作。
|
||||
if again := MigrateCardNames(watch); again != 0 {
|
||||
t.Fatalf("第二次跑又搬了 %d 筆,應為 0(冪等)", again)
|
||||
if again := MigrateCardNames(watch); again.Moved != 0 {
|
||||
t.Fatalf("第二次跑又搬了 %d 筆,應為 0(冪等)", again.Moved)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user