Commit Graph

26 Commits

Author SHA1 Message Date
Leo f1658fd2ad sync: collector/ 同步自 inkstone/arcrun-rag@a39cea2(桌面小幫手 0.18.34) 2026-08-20 11:26:28 +08:00
Leo 8c22c6858b feat(daemon): 0.18.33——機器 ID 進二進位,三平台成品全裸號(inkstone/mira#6)
collector 加了 machineid.go 之後 daemon 源碼與成品脫節,
daemon-source-check 擋下(閘是對的)。照規矩補 changelog 再重編三平台。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 17:53:23 +08:00
Leo 48546a768c feat(daemon): 0.18.32 三平台全裸號成品+補上 msix 的搬運缺口(arcrun-rag#88)
- 產生端實測吐裸號:changelog 標題 `## 0.18.31`、二進位 -X main.version=0.18.31
- 三平台成品檔名全裸:Arcrun-0.18.32.dmg / Arcrun-win-0.18.32.exe / Arcrun-0.18.32.msix
- 🔴 補上一個安靜的洞:build-msix.sh 只吐到 dist-msix/Arcrun.msix,
  而出貨線找的是 dist/Arcrun-<版本>.msix,且 msix 標 required:false
  ⇒ 它會安靜地少一個檔而出貨線照印綠。上一版的 msix 是人手搬的。
  這正是 daemon-sync 當初要根治的「只活在人記憶裡的步驟」。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 16:55:59 +08:00
Leo 03a2c3d5f8 fix(ship): 解開出貨線的兩個自鎖——閘改成量指紋、戳版順序倒過來(arcrun-rag#88)
出貨線從第 5 站 daemon-source-check 就把自己鎖死,push/deploy/verify/
release-record 四站一次都沒執行過。實查真兇是**兩個**,不是一個,而且同源:
D95 第一輪把 `CHANGELOG.md` 搬進 `collector/`(為了讓 collector/ 自足、
有資格獨立成 repo)之後,**「宣告新版本」這個動作本身就是在改 collector/**。

── 自鎖① 出貨線那道閘:用 git 歷史當代理 ────────────────────────────
舊判法=`git log <宣告那顆>..HEAD -- collector` 非空就擋。
⇒ 一顆**只改宣告、一行程式都沒動**的 commit(dcd0132 就是)也被算成
  「宣告之後源碼又動過」⇒ 閘擋自己。
⇒ 反過來也不準:collector/ 底下有些檔案(打包腳本旁的 .mjs 工具、README)
  根本不會進到執行檔,動了它們一樣被判「要重打包」。

🔴 兩件事都對,疊起來變成死結:**衝突在範圍重疊,不在任何一方做錯。**

修法不是把 changelog 搬回去(那會推翻 D95 第一輪),也不是加路徑白名單
(那就是被禁的字串比對)。改成問**同一件事實**,而那份事實這個 repo 早就在算:
`daemon-version.py` 每次戳版都把「當下的原始碼指紋」記進
`.version-source.json`(2026-08-06 起就存在)。
**版本 X 的指紋 == 現在算出來的 ⇒ X 的成品確實是照這份源碼打的。**
宣告那一步改到的檔案,在戳版當下就已經算進指紋 ⇒ 結構上不可能擋自己;
而「改了 code 卻沒重打包」照樣指紋不同 ⇒ 原本要擋的一個都沒放過。

指紋怎麼算是 daemon 自己的知識,出貨線**不重寫一份**(兩套並存必然漂移):
新增唯讀的 `daemon-version.py --source-state`,`daemon-freshness.mjs` 只負責問與判。
這就是遷移計畫寫的「daemon-freshness 該**搬家**不是加固」。

── 自鎖② 戳版的順序:帳本記的是「還沒戳版」那一刻的樹 ──────────────
`main()` 原本先 `check_or_record()` 再把宣告寫進 changelog。而 changelog 就住在
指紋涵蓋的樹底下 ⇒ 帳本記下來的那棵樹,從寫完宣告那一刻起就不存在了。
實撞(本輪 A/B 重現,見 daemon-version.test.mjs ⑦):
  build-mac.sh 戳版打完 dmg → 同一輪 build-win.sh 走「重打同一版」路徑
  → 現在的指紋(含已戳版的 changelog)≠ 帳本裡那個 → dist/ 已有 dmg
  → 判「版號已對應另一份原始碼」→ **第二個平台永遠打不出來**
而上游 `daemon-sync` 兩個平台都要,缺一不准出貨 ⇒ 出貨線在這裡也走不完。
⇒ 先寫宣告、再記指紋。(這條路是升版,帳本不可能已有該版號 ⇒ 不會中途 die。)
🔴 這個病是 D95 第一輪帶進來的:v0.18.29 打包時 changelog 還在 docs-site/,
  不在指紋範圍內,所以當時不會發作。

── 為什麼要多一本逐檔帳(.version-source-files.json)────────────────
總指紋只有 16 個字,對不上時只講得出「不一樣」。而紅線要求
「回報通過時要說得出它實際比對了什麼」⇒ 逐檔雜湊讓閘講得出**哪幾個檔**變了。
只留最新一版(閘只問最上面那一版),與總指紋帳本一樣排除在指紋之外(自我參照)。

── 閘要留痕(InkStoneCo#48)────────────────────────────────────────
`installer/daemon-freshness-gate-log.md`:擋下、放行、明知故犯放行,三種都記。

── 順手收進來的一筆(同一輪的複驗項)───────────────────────────────
cherry-pick 89dd323:`checkDocsLive()` 的假綠。實測線上 stage 文件站——
那一頁是舊的(135KB 逐版列表、沒有 dcd0132 的 meta-refresh),卻因為內文
剛好含一次 releases 網址而被 `body.includes()` 判過 ⇒ fails=0。修後 fails=1。

實測
  · daemon 0.18.30:Mac dmg 8.3M + Windows exe 22M **同一輪打出來**(修前不可能)
  · 閘判決:status=ok,帳本 ad1106716ae426d2 == 現在 ad1106716ae426d2(涵蓋 228 個檔)
  · installer 測試 257 支全綠;collector 版本產生器 9 支全綠(新增 ⑦⑧⑨)
  · daemon-freshness 自己的演練 15 支:兩個方向各有案例
    (不擋自己/仍擋得住沒重打包/問不出來一律停/留痕)

紅線遵守:只碰 stage;沒推 main、沒併分支、沒碰 prod/GitHub。

Refs: inkstone/arcrun-rag#88

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:39:52 +08:00
Leo 8764a8870e ship(daemon): 戳版號 v0.18.29——移除要真的收回/不再把套件文件當你的知識
changelog(使用者語言,三條):
· 「移除資料夾」現在真的會收回——先前只是停止監看,已進雲端的知識一筆都不會消失
· 不會再把別人的套件當成你的知識——實測一次 27 張卡有 21 張是第三方 API 文件與授權條款
· 有沒有用 git 不再影響收哪些檔——先前在自己筆記資料夾開一次版控,收檔數就會大幅減少

刻意不寫進 changelog 的:#44 的卡片對照原文檢查。
機制已進 main,但判定結果目前流不到任何人眼前(leo 已裁 A+C,接線尚未做)
⇒ 使用者感覺不到的事不寫進版本說明。

三平台產物:
  dist/Arcrun-v0.18.29.dmg          8.3M
  dist/Arcrun-win-v0.18.29.exe       22M(單一執行檔、自帶同步引擎)
  dist-msix/Arcrun.msix              8.7M(未簽章=送 Store 的正確狀態)

⚠️ 既有缺陷(非本次造成):Homebrew makensis 在這台 macOS 壞掉
   ⇒ Windows 仍只有裸 exe,沒有 NSIS 安裝程式(leo 08-06 要的「正常安裝流程」未兌現)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 23:50:35 +08:00
Leo 345be49d4d ship(daemon): 戳版號 v0.18.28——把待打包的 28 個 collector 檔真的打包出去
出貨 CP 步驟④(InkStoneCo#44 → comment 2785):changelog 最上面的已發佈段
停在 v0.18.27,而 collector/ 早已往前走 30 個檔(00bface 結構先行/ef5e6c5
規範形 wiki 卡/dce2e15 免金鑰路補齊/c5a9163+e4b7745 ⑦⑩ 關聯段與改名比對
修法/829da02+cc6e500 daemon 不再誤動使用者版控中的檔案)。

changelog「下一版(未發佈)」補上這一輪缺的三條(免金鑰路、關聯段修復、
改名/搬移不誤殺),戳成 v0.18.28(2026-08-16),daemon-version.py 記錄
本版原始碼指紋。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 16:13:52 +08:00
Leo 64cb20a1aa chore(desktop): 戳版號 v0.18.27——把 f71e5a2/578ac2b 兩個 #60 修法真的打包出去
main 上 1e36bb1/f71e5a2/578ac2b 三個 #60 修法都已進了原始碼,但只有第一個
(1e36bb1)進過發佈出去的 v0.18.26 執行檔——後兩個修好之後從沒被打包。
daemon-version.py 唯讀檢查也證實:v0.18.26 這個版號已對應過另一份原始碼
(代表戳完版號之後 code 又動了)。

本次動作:
- changelog 補「下一版(未發佈)」段(用戶語言描述兩個修法),
  daemon-version.py --stamp 戳成 v0.18.27。
- 重打 mac dmg/win exe,三支機械閘(check-cis/check-render/check-tray)全過,
  DMG 掛載實查(兩項/版本號/LSUIElement/簽章)、win exe 內容確認。
- strings 掃兩份執行檔:collector.DetectVaultContext/VaultDirUnder(578ac2b)、
  collector.MarkName/IsMarked(f71e5a2)皆存在——不是只有 commit 在 main,
  是真的編進這次的二進位。
- go test ./... 全綠。

daemon-version.py(唯讀)現在乾淨印出 v0.18.27,不再抱怨版號對應兩份原始碼。
2026-08-13 12:30:08 +08:00
Leo 04b99ad1cf chore(desktop): 重打桌面版 v0.18.26,實測 #59/#60 修復真的在新二進位裡
- main 上 #59(額度卡假訊息)與 #60(vault 辨識+不覆蓋原稿)的修復合併後,
  daemon-version.py 的指紋帳本偵測到 v0.18.25 對應的原始碼已經變了
  (fp a753d866… ≠ 記錄的 33f4bdcb…),代表照舊重戳 v0.18.25 會產出
  「跟 leo 機器上那支同版號、內容卻不同」的二進位——版本號說謊。
  ⇒ changelog 補一段「下一版(未發佈)」,daemon-version.py --stamp
  正確升版成 v0.18.26,v0.18.25 的舊指紋原樣保留不動。

- 用 build-dmg.sh 實際打出 dist/Arcrun-v0.18.26.dmg(8.2M),
  Info.plist CFBundleShortVersionString 確認為 0.18.26。

- 拿同一支打包出來的 arcrun-app 執行檔(--collector direct --once),
  對著本機自建的假 Logseq/Obsidian/一般資料夾三種監看根各跑一輪
  (mock 掉 /portal/daemon/extract 與收卡 workflow,不碰任何真實帳號/額度):
  vault 兩種都落在 .arcrun-rag/wiki/cards/(隱藏,筆記軟體不掃描)、
  一般資料夾落在 system-dev/wiki/cards/(行為不變);
  三種都故意預先放一張同名舊卡,跑完舊卡被備份成 <name>.md.bak-<nanos>、
  新卡才落地,沒有無聲覆蓋;Logseq 的 journals/*.md 原稿位元不動。

不動 collector/cmd/arcrun-app/arcrun-app(那支是舊的、脫離版控管理的建置產物,
本次 go build ./... 順手覆蓋過又還原,不屬於這次的變更範圍)。
2026-08-11 14:05:57 +08:00
Leo 3862a1a877 chore(daemon): 版號戳到 v0.18.25,補迎新精靈的 changelog 段(Gitea #23)
daemon-version.py 的指紋鎖已擋下 v0.18.24(onboarding wizard 合併後
原始碼與該版指紋不符)。補上「## 下一版(未發佈)」段描述兩步引導
精靈,重跑 --stamp 機械戳出 v0.18.25,三平台(dmg/exe/msix)已重打
包並逐一拆開驗證內嵌版本,見 #23 留言。本次僅打包,未出貨。
2026-08-09 17:41:37 +08:00
Leo 0cdbda8694 v0.18.24 changelog 補齊(診斷檔 engine 狀態+路徑遮蔽)+三平台打包驗證
changelog 原本只涵蓋 5fcc139/5effcb2/9f1ca58 三項,補上今天另兩項使用者可見改動:
- 疑難排解按鈕的診斷檔現在也看得出小幫手還在不在跑(8eeb393)
- 診斷檔不再洩漏本機絕對路徑(4f81ad6)

三平台已本機打包驗證(未出貨、未碰 stage/prod):
- Mac dmg:CFBundleShortVersionString=0.18.24、codesign 有效、內含 Applications 捷徑
- Windows exe:單一自帶同步引擎執行檔(NSIS 安裝程式因本機 makensis 工具鏈壞掉暫缺,非本輪修復範圍)
- MSIX:AppxManifest Identity Version=0.18.24.0

.version-source.json 的 v0.18.24 指紋隨之更新(fingerprint 現涵蓋 8eeb393/4f81ad6 的 collector/ 改動)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 16:59:18 +08:00
Leo 92fecb48c1 stage 驗收:t213 兩半+t210+t209 全鏈打通(InkStoneCo 總管交辦)
- changelog 補 v0.18.24(下一版)條目:失敗真因不再被抹掉/首頁改統計/
  疑難排解按鈕搬進小幫手本體——三批合一次驗收
- .version-source.json 記錄 v0.18.24 指紋(daemon-version.py 版本閘產物)
- staging 安裝器釘子換到 arcrun-rag-bundles-staging@51f84bf(source Arcrun@8447165,
  含 93b1140 新端點 GET /portal/daemon/diagnostics + 8447165 portal 按鈕文案)

驗收方式:deploy-all.mjs 全量部署到 youlin 測試實例(stage)、collector direct --once
真跑一輪(3 ingested/2 unreadable,格式不支援)、buildDiagnosticsPayload() 真跑產出
合併診斷 JSON(本機 Progress/FailureBreakdown + 雲端 /portal/daemon/diagnostics)。
四題考卷用該 JSON 逐題核對,詳見本次回報。

未動:prod bundle repo/github-arm/publish-github(紅線,一步未碰)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 13:53:53 +08:00
Leo 2b06a0456d v0.18.23 changelog(用戶語言)+三平台打包
指紋閘擋下重打同版號(「兩個內容不同卻都叫 v0.18.22=版本號說謊」),
照它要求先寫 changelog 才放行——這個閘今天第一次真的攔到人,有效。

打包踩到一個坑:dmg 壓製回 resource temporarily unavailable,
真因是前一次對照實驗留下的 /Volumes/Arcrun 1 掛載點沒卸載。
hdiutil detach -force 後即通過。記下來免得下次誤判成打包壞了。
2026-08-08 03:10:11 +08:00
Leo 837e5e8052 出 v0.18.22:aa65efa 積壓分批四件套+新增預設庫,全平台已打包驗證
changelog 補上用戶語言的更新內容(daemon-version.py --stamp 依此機械
算出版號、記錄原始碼指紋)。三平台已打包並拆開驗證內嵌版本 == v0.18.22:
- Mac DMG:Info.plist CFBundleShortVersionString=0.18.22,
  arcrun-app --collector --version → v0.18.22,codesign 有效
- Windows exe:ldflags 內嵌 v0.18.22(無舊版號殘留),
  build-win.sh 內建探針確認 --collector --version → v0.18.22
- MSIX:AppxManifest Identity Version=0.18.22.0(真身分,非佔位值),
  內嵌 Arcrun.exe 同樣是 v0.18.22

尚未出貨(ship.mjs/purge jsDelivr/D20 開閘),產物留在
collector/cmd/arcrun-app/dist(-msix)/(gitignored,不進版控)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 00:27:44 +08:00
Leo 8ad6f25ba3 出貨 v0.18.21:釘子 → c1566cf(Windows 修復鏈+首發 MSIX 已送達封測者) 2026-08-06 23:18:00 +08:00
Leo 5c0bddacc4 v0.18.20:失敗清單改摺疊式+修指紋閘的自我參照
## UI(leo 實測版面被壓扁)
失敗清單改用原生 `<details>`:只列檔名、旁邊三角形、**預設收合**,
點開才看原因。先前把原因攤在檔名旁邊,中文檔名被擠成一行一個字。

## 🔴 指紋閘三修:帳本自己不能算進指紋(經典自我參照)
`.version-source.json` 就住在 `collector/` 底下 ⇒ 戳版號寫入它、指紋跟著變
⇒ **同一輪連續打 win/mac/msix,第二支就被自己的閘擋下**(實撞)。
查證過才修(沒有亂放寬):
  · `gen-icons.py` 產的 .ico **位元一致**,不是它
  · `dist/` 早就 gitignore,不在名單裡
  · 真兇只有帳本
⇒ **只排除帳本一個檔**。一度想順手排掉整個 `build/`,那會讓「換 app icon」
  不算原始碼變更=在閘上挖洞,已收回。
驗:連跑兩次版本號相同(冪等)。

## 三種產物都備齊(在共用資料夾)
`Arcrun-win-v0.18.20.exe`/`送審用/Arcrun-v0.18.20.dmg`/`送審用/Arcrun-v0.18.20.msix`
⚠️ MSIX 的 **Identity 三值仍是佔位**(`PLACEHOLDER.ArcrunRAG`)⇒ **不能送 Store**,
需 leo 從 Partner Center 提供 `IDENTITY_NAME`/`PUBLISHER`/`PUBLISHER_DISPLAY` 再重打。

## 未送達
線上仍 v0.18.8。推遠端需 leo 開 D20 閘。
2026-08-06 22:39:42 +08:00
Leo d0852e9b45 v0.18.19:失敗訊息改成人話(leo:「這個錯誤訊息我真的看不懂」)
v0.18.18 雖然把失敗檔案列出來了,但寫的是
「上次失敗(第 5 次),5h38m38s 後重試(上面是自動重試的排程,真正的原因是前一次失敗)」
——**那是我寫給自己看的**:只是把 collector 的原文轉貼、再補一句解釋為什麼看起來怪。

使用者要的是三件事:**現在怎樣、為什麼、我要不要做什麼**。

## 改法
- 解析退避訊息取出「試幾次/多久後再試/原因」,重新組成人話
- **有原因**時以原因為主、排程放後面補充(他要判斷的是原因)
- **沒有原因**時(舊版失敗的檔案沒存 LastError)誠實說:
  「已經自動試過 5 次都沒成功,約 5 小時後會再試一次。這個檔是在舊版失敗的,
    當時沒有記下原因;如果一直沒好,把紀錄檔傳給我們。」
- 時間不再精確到秒(`5h38m38s` → 「約 5 小時」)——使用者要的是量級不是秒數

## 實測輸出(三種情境都印出來看過)
  舊:上次失敗(第 5 次),5h38m38s 後重試(上面是自動重試的排程…)
  新:已經自動試過 5 次都沒成功,約 5 小時後會再試一次。這個檔是在舊版失敗的…
  新:今天的免費 AI 額度用完了 ⇒ 明天會自動恢復,這些檔案會自己補上,你不用做什麼。
  新:這份 PDF 看起來是掃描的圖片 ⇒ 需要先做文字辨識(OCR),或換一份有文字的版本。
2026-08-06 22:02:32 +08:00
Leo 857420dfa7 v0.18.18:失敗原因真的顯示在畫面上(前面幾版只做了一半)
## 補完「上游錯誤要看得到」這條線
- 退避中的檔案也進 `status.failures`(先前退避期間該欄是空的
  ⇒ 畫面只有「⚠ N 份失敗」沒有原因,等於前面白做)
- `shortError` 從 120 放寬到 240 字:真因在訊息**後半段**,砍 120 會整段切掉

## 實測輸出(不是推測,是印出來的卡片內容)
  有 2 份沒有送進知識庫
   · 2021超新星品牌白皮書-科特勒.pdf
     今天的免費 AI 額度用完了 ⇒ 明天會自動恢復,這些檔案會自己補上,你不用做什麼。
   · 台灣青年創新創業協會謝侑霖.pdf
     這份 PDF 看起來是掃描的圖片 ⇒ 需要先做文字辨識(OCR),或換一份有文字的版本。
⇒ 同樣是「失敗」,處置完全相反(等就好/要動手),使用者現在分得出來。
(測試資料取自 leo Windows collector.log 的原文。)
2026-08-06 21:41:28 +08:00
Leo 6e0b65a2bb mistakes:Workers AI 額度用完/掃描版 PDF——兩個「不是 bug 但要說清楚」的已知現象 2026-08-06 20:48:01 +08:00
Leo 9dc7cbc803 v0.18.17:失敗的檔案列出檔名與原因;補上「上一版說有、其實沒做進畫面」的按鈕
leo Windows 實測 v0.18.16:連線誤報已消失( 那個修正生效),
但出現「⚠ 3 份失敗」→ 加檔後「⚠ 1 份失敗」,兩個新檔沒推上雲端也沒產卡。

## 修:數字不能代替原因(今天第四次同款病)
collector **早就**把「哪個檔失敗、為什麼」寫進 status.json(`Failures[]`),
但 App 一直只讀計數 ⇒ 畫面只會說「⚠ 3 份失敗」
⇒ leo 只能回報「沒推到雲端」,我只能猜。
前三次同款:exit status 2 蓋掉真話/非文件檔不點名/誤判沒連線。
現在列出檔名+原因(最多 8 份,總數照實講)。

## 🔴 更正:v0.18.12 宣稱的「一鍵打開紀錄檔資料夾」**根本沒進到畫面**
Go 那邊 `OpenLogFolder()`/`EngineTrouble` 都做了,但前端那次 `str.replace()`
**錨點縮排不符、沒命中**,而我沒加斷言 ⇒ 檔案沒變,我卻在回覆與 changelog 裡宣稱做好了。
(同一天已經因為「取代沒驗證」出過一次事,這是第二次。)
本次三處錨點**全部 assert**,並機械複驗五個關鍵字+`node --check`。
changelog 也已更正 v0.18.12 那段。

## 順帶修 .bat 的收集段(leo:「有按照 1 然後 2,你要檢查 bat」)
收集 log 那段用 `>nul 2>&1` **把錯誤全吞掉** ⇒ 失敗了也沒人知道,
我還以為是 leo 沒按 Enter。改成**逐檔回報 v/X/-**,並把輸出目錄
從中文「記錄檔」改成純英文 `logs`(中文路徑+UNC+Big5 主控台三者疊加容易出事)。
2026-08-06 20:22:24 +08:00
Leo 01fbb21357 v0.18.16:修「明明連上卻說沒連上」——第三次「我這台好好的」
leo Windows 實測:首頁跳「需要你處理一下 ⇒ 還沒連上知識庫」,
但側邊欄有 geek6688、Portal 的庫目錄管理也看得到它的庫(win_on_mac_test_lib)。

## 真兇:又是「只看根層欄位」
`direct.go` 判連線只看 **根層** `cypher_url`/`api_key`,
而多帳號設定(現在的常態)根層是空的 ⇒ **恆判成沒連線**。
為什麼開發機沒事:leo 的 Mac config 帶著**單帳號時代留下的根層欄位**。
⇒ **今天第三次同一個模式**(另兩次:config 缺 manifest 靠舊檔補齊、
   啟動 log 用根層組出 `/webhooks/named//…`)。
修:抽出 `accountsConnected()`=「根層有 **或** 任一帳號有」,並補測試
(刻意用「只有 accounts、根層全空」=全新使用者的形狀)。

## 順帶:那句話還指錯路
訊息叫人「點托盤選單的『+ 新增帳號…』」——**托盤選單早就只剩「結束 Arcrun」**
(t194 起所有設定都在視窗裡)⇒ 使用者照著做會找不到入口。
改指「左邊『知識庫』下方的新增知識庫帳號」。

## 順帶修我自己的測試腳本(leo 實撞)
`① 測試最新版.bat` 用 `dir /o-d`(修改時間)挑版本 ⇒ 複製到共用資料夾後
時間順序不一定等於版本順序,**leo 那次挑到了 v0.18.13**。
改用 `dir /on`(檔名排序)取最後一個。
另把「固定等 20 秒」改成「等你操作完按 Enter 再收 log」——
清空後第一次跑,引擎本來就不該啟動,等 20 秒收到的是空的。

## 附帶確認(leo 截圖)
- 「有 1 個檔案沒有被整理」**已列出檔名**(`scripts/sdd-active-check.sh`)⇒ 08-06 那個修正生效
- Portal 庫目錄管理三個庫都在(含 Windows 的 `win_on_mac_test_lib`)⇒ 子庫沒出現是假警報
2026-08-06 19:57:05 +08:00
Leo 458ff3fd88 v0.18.14/15:全新使用者連上知識庫後會自己開始+log 不再印不存在的網址
leo 08-06 用共用資料夾實測,兩張圖把最後一個病逼出來:
「第一次直接跑可以,**清空再來一次,就不跑了**」。

## 真兇:restartWatch 第一行就早退
全新使用者的順序是:
  ① 打開程式(**還沒有任何設定**)⇒ startSupervisor 早退,`sup` 是 nil
  ② 連上知識庫、加資料夾 ⇒ restartWatch
  ③ 舊版:`if sup == nil { return }` ⇒ **什麼都沒發生**
  ⇒ 引擎永遠不啟動,畫面叫人「請結束 Arcrun 再重新開啟」
「不算錯」(重開真的會好),但等於要求剛裝好的人自己想到去重開程式。
**每一個第一次用的人都會撞到**;開發機永遠有設定,所以永遠測不到。

修:`sup == nil` 時**現場建立**(設定剛出現,正是該啟動的時機)。
新測試 `TestFirstRunStartsEngineAfterConnect` 從「沒有設定」開始走完整順序;
反向驗證拿掉即紅。

## 順帶把那句沒用的話拿掉
「請結束 Arcrun 再重新開啟」=把系統的無能推給使用者。
改成「正在啟動同步引擎,請稍候…」;還沒連知識庫時說
「按『新增知識庫帳號』就會開始」。

## log 不再說謊(今天第三次同一個主題)
啟動訊息印 `cfg.triggerURL(...)`=用**根層**的 cypher_url/namespace 組的,
而多帳號設定根層是空的 ⇒ 印出 `→ /webhooks/named//rag_ingest/trigger`
(沒網域、雙斜線)**看起來像設定壞了,其實功能正常**。
改印每個帳號真正會用到的網址。

## 實測證據(共用資料夾自動收回來的 log,非截圖轉述)
  19:13:54  設定檔缺必填欄位,已自動補上 manifest=C:\Users\leo21\.arcrun-rag\manifest.json
  19:13:55  collector direct daemon 啟動:監看 …\win_on_mac_test_lib  {"phase":"start"}
⇒ v0.18.13 的自我修復在真機生效,config 已補上 manifest,collector 真的跑起來。
2026-08-06 19:33:36 +08:00
Leo 8dc9a2ee85 v0.18.13:舊設定檔自我修復——我第一次修錯了,只修好全新安裝
leo 裝了 v0.18.12 **仍然是同一句錯**(實拍:重試 30 次、
「collector direct: config 缺必填欄位:manifest」),並提供了他的 config.json。

## 我錯在哪
v0.18.11 只在 `saveCfg`(存檔)補必填欄位。但使用者打開程式時
**只是「讀 config → 啟動引擎」,saveCfg 根本不會被呼叫**
⇒ 已經存在的壞設定永遠修不好。全新安裝好了,**現有使用者一個都沒被救到**。

leo 的 config 鐵證:頂層只有 `accounts`/`extractor`/`extractor_explicit`/
`gemini_api_key` —— **正好是 saveCfg 寫的那四個鍵**,沒有 manifest。

## 為什麼我的測試沒抓到
`TestFreshInstallCollectorStarts` 是**從 saveCfg 出發**建 config ——
它測的是「我修的那條路」,不是「leo 正在走的那條路」。
**測試照著修正寫,就只會證明修正存在,不會證明問題解決。**

## 這版
- `fillRequired()` 抽出來,**讀取時也補**(升級路徑)+存檔時也補(新建路徑)
- 讀取時補完**寫回磁碟**——collector 是另一個行程,讀的是磁碟那份不是記憶體
- 補完寫進 app.log 留痕

## 驗
新測試 `TestExistingBrokenConfigSelfHeals` **從磁碟上已存在的壞 config 出發**
(內容逐字取自 leo 那份,只把值改假),驗三件:讀取後磁碟上有 manifest、
JSON 仍合法、**真的把執行檔當 collector 跑起來不再 exit 2**。
反向驗證:拿掉自我修復即紅(訊息就是 leo 撞到的那句)。全套測試綠。

⚠️ 更正 changelog:v0.18.11 原本寫「已經裝過舊版的人不用做任何事,更新後會自動補好」
   —— **那句是假的**,已改成指向本版。
2026-08-06 18:58:31 +08:00
Leo 9f64615cfd v0.18.12:出問題時一鍵打開紀錄檔資料夾(leo:「不能用一個 debug mode?」)
leo 08-06:「不能用一個 debug mode,就是它會把 log 寫在一個檔案?」

## 回答:log 一直都在寫,缺的是「找得到」
`~/.arcrun-rag/collector.log`(含 collector 的 stderr,以 `[stderr]` 開頭)
與 `app.log` 從 t14 就在寫。這次 Windows 事故的真正死因
(`config 缺必填欄位:manifest`)**一直躺在 collector.log 裡**,
但使用者只看得到畫面上一句話,沒有任何入口通到那些檔案。

⇒ **不做「debug mode 開關」**(多一個要教使用者的東西,而且出事當下才想到要開就來不及了),
   改成**永遠寫、出事時一鍵打開**:
- `OpenLogFolder()` 綁定(Windows 走 explorer/Mac 走 open/其餘 xdg-open)
- 首頁在 `engineTrouble` 時才長出「需要回報這個問題?」卡,附按鈕與**路徑文字**
  (按鈕失效時仍找得到)。沒事時不顯示——否則會變常駐噪音,真出事反而沒人看。

## 真機證據:v0.18.10 的「說出死因」有效
leo 的 Windows 畫面實拍:
  「同步引擎一直啟動失敗 / 已自動重試 8 次都失敗,所以重新開啟也沒有用。
    原因:collector direct: config 缺必填欄位:manifest(exit status 2)」
⇒ **與 v0.18.11 修的根因一字不差**,診斷鏈完整閉合:
   症狀(閃爍)→ 機制(子行程 exit 2 無限重拉)→ 死因(config 缺 manifest)→ 修正。
2026-08-06 18:47:17 +08:00
Leo fcf00bb5df v0.18.11:修好 Windows「裝了完全不會動」的真兇——全新 config 缺 manifest 欄位
leo 08-06 提供決定性線索:**exit status 2,已自動重試 21 次失敗**。

## 真兇
`app.go` 的 `saveCfg` 只寫四個鍵(accounts/extractor/extractor_explicit/
gemini_api_key),**從來不寫 `manifest`**。
而 `manifest` 是 collector 的必填欄位(`direct.go`:
`if c.Manifest == "" { missing = append(missing, "manifest") }`)
⇒ 讀 config 失敗 → `runDirect` 回 2 → supervisor 無限重拉
⇒ ①「看守中/沒有在跑」一直閃、重開無效(死因沒變)
⇒ ②加資料夾沒反應(collector 從沒跑完一輪)

## 為什麼一路活到封測
**開發機的 config 是舊版留下的、早就有這一欄。**
只有「從零長出 config」的機器才會撞到——也就是**每一台封測者的機器**。
「我這台好好的」正是這個 bug 能活下來的原因。
⇒ 新測試 `TestFreshConfigIsUsableByCollector` **從零建 config**,
   並且不只驗欄位在不在,而是**真的餵給 `collector.LoadDirectConfig`**。
   已反向驗證:把修正拿掉,測試會紅(不是假測試)。

## 順帶修好「為什麼只看得到 exit status 2」
supervisor 在行程結束時用 `cmd.Wait()` 的錯誤當訊息,
**蓋掉**了 stderr 剛寫進 `LastError` 的那句真話
(`collector direct: config 缺必填欄位:manifest`)。
⇒ 改成以 stderr 為主、退出碼放括號補充。
(v0.18.10 已讓死因上畫面+進 app.log,這版讓那句話是**對的**那一句。)

## 三種 exit 2 的實測輸出(重現測試打出來的,非推測)
- config 不是合法 JSON → `config JSON 解析失敗:invalid character …`
- 缺必填欄位 → `config 缺必填欄位:manifest, accounts(或 cypher_url 連線設定)`
- Windows 反斜線路徑 → 正常解析(**排除「反斜線害的」這個猜測**)

## 驗
collector 全測試過、app 測試過、mac+windows 皆編得過;
產物 `Arcrun-win-v0.18.11.exe`(22M)已放 leo 桌面。
⚠️ **尚未真機驗**——要 leo 在 Windows 全新裝一次才算通。
2026-08-06 18:41:31 +08:00
Leo 6698f9fbda v0.18.10:讓「同步引擎沒在跑」說出死因(leo Windows 實測①②的診斷前置)
leo 08-06 Windows 回報:「一直在『看守中』和『沒有在跑』中間閃,要我重啟但重啟無效,
我覺得它在跑個迴圈不停重複」+「加一個資料夾明顯沒產生看守資料夾」。
朋友的一般 PC(非 ARM)也一樣,停在等待中 ⇒ **不是 ARM 模擬的問題,是 Windows 通用**。

## 已定位的機制(不是根因,是「為什麼查不出根因」)
閃爍=子行程一啟動就死 → supervisor 退避重拉 → 狀態在 Starting(alive=true)與
Error(false)之間彈跳 ⇒ 畫面跟著閃。而**死因一直被記在 Status().LastError 裡,
從來沒有上過畫面、也沒寫進 app.log** ⇒ 使用者只看到閃爍與「請重新開啟」,
重開當然無效(死因沒變)。這是「安靜地略過」的同一種病換地方發作。

## 這版做的
- 死因上畫面:重試 >= 3 次改顯示「同步引擎一直啟動失敗,已自動重試 N 次|原因:…」,
  且**黏住不閃**(不受重起過程中的 Starting 影響)
- 每次異常結束寫進 app.log(同錯誤 10 次內只記一次,避免洗爆)

## 排除掉的嫌疑(查過,不是)
- PDF 引擎(pdfium/wasm):**延遲初始化**,第一次讀 PDF 才啟動 ⇒ 不會在啟動時炸
- ARM 模擬:leo 朋友的一般 x64 PC 同樣症狀
- 待查嫌疑:Wails 的 Windows 版是 `-H windowsgui`(GUI subsystem,無主控台),
  而 v0.18.8 的 collector.exe 是 `go build` 的 console subsystem——
  v0.18.9 合併成單一 binary 後,子行程換成 GUI subsystem 的自己。**尚未證實。**

## 順帶修好自己的閘(它擋對了我)
指紋閘擋下「v0.18.10 已對應另一份原始碼」——因為第一次打包失敗、版號卻已被戳。
⇒ 加判準:**磁碟上沒有該版號產物=從未出貨,允許重戳**(不用去手改 JSON,
那種爛示範遲早被改成「都放行」)。

## 安裝程式(leo ③)尚未兌現,誠實記錄
`wails build -nsis` 需要 makensis;Homebrew 的 3.12 在這台 macOS **連兩行的最小腳本
都在寫檔階段丟 std::bad_alloc**,zlib/bzip2/lzma 三壓縮器全崩,brew extract 舊版
被 homebrew/core 擋。且帶 -nsis 會讓 wails 整個中止、連 exe 都不產
⇒ build-win.sh 改成**先煙霧測試 makensis**,壞的就只出裸 exe 並大聲警告。
2026-08-06 18:27:08 +08:00
Leo 0b8bc83bd1 版本指紋閘(同一版號只准一份原始碼,實測有效)+落帳封測兩病與 md 真相 2026-08-06 16:17:40 +08:00