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:
Claude
2026-08-14 14:41:08 +00:00
parent 64cb20a1aa
commit 129fe79ecb
13 changed files with 1104 additions and 36 deletions
+9 -3
View File
@@ -73,15 +73,21 @@ const cardsRelDir = "system-dev/wiki/cards"
const vaultCardsRelDir = ".arcrun-rag/wiki/cards"
// cardsRelDirFor 決定某次萃取的卡片該落在哪個相對路徑:
// 監看根不在任何筆記庫範圍內cardsRelDir(一般資料夾行為,零改變);
// 落在筆記庫範圍內=vaultCardsRelDir(隱藏目錄)。
// 監看根不在筆記庫、也不在版控裡cardsRelDir(一般資料夾行為,零改變);
// 落在筆記庫或版控範圍內=vaultCardsRelDir(隱藏目錄)。
//
// 🔴 arcrun-rag#60 第三輪:判準從 IsVault(只看監看根**這一層**)換成 DetectVaultContext
// (監看根**在不在**某個筆記庫裡)。前者在「監看根是 vault 底下的子資料夾」時回 false,
// 於是卡片落回 `<監看根>/system-dev/wiki/cards/`——那個位置就在使用者的 vault 裡面,
// 而且不是隱藏目錄,Logseq/Obsidian 會把每一張卡收編成一頁。全文見 vault.go 第三輪那段。
//
// 🔴 arcrun-rag#105**版控中的資料夾與 vault 同待遇**。理由是同一個形狀——
// `system-dev/wiki/cards/` 在 repo 裡不是空地,那是 template 規約路徑,
// 使用者自己的卡就住在那裡;而且不管撞不撞名,往那裡寫東西就是往他的 git status
// 裡塞 untracked 檔。落進 `.arcrun-rag/`(配 EnsureWorkspaceIgnored 自我忽略)
// =寫得進去、又不弄髒他的版控。
func cardsRelDirFor(absRoot string) string {
if DetectVaultContext(absRoot).InVault() {
if DetectVaultContext(absRoot).InVault() || UnderVersionControl(absRoot) {
return vaultCardsRelDir
}
return cardsRelDir