修首頁狀態說謊+DMG 補上拖曳版面(leo 08-05 封測回報 ①②)
## ② 首頁狀態是壞的
leo:「拖新的檔案進資料夾,完成本地萃取、上傳,但自始至終 daemon 的首頁都顯示
『有變動就自動開始』『等待中』,都顯示綠燈沒動,實際上已經做完了。」
兩個獨立的真兇:
**A. 「同步中」判斷用錯依據(回歸)**
t191 早就做好機制:collector 開工印 phase:"start"、跑完印 "done",
supervisor 據此維護 StateSyncing。**換 Wails 時 App 沒接這條線**,改看 sync-now 訊號檔:
① 訊號檔只有手動按「立刻同步」才產生 ⇒ 拖檔進資料夾(自動觸發)整輪不亮燈
② 就算手動按,collector 是**先刪檔再跑**(consumeSyncNowSignal)⇒ 真正在跑時檔早沒了
⇒ 改讀 sup.Status().State == StateSyncing。**接回既有機制,不發明第三種判斷法。**
**B. 做完的證據被下一輪抹掉**
ExtractedOK/ExtractFailed 是**本輪**計數、每輪覆寫整份 status.json
⇒ 有產出那輪寫下 N,十幾秒後空轉的一輪把它蓋成 0
⇒ 「上一輪 N 份」永遠空白、四步時間軸的綠燈只靠「跑過任何一輪」判斷=與實際進度脫鉤。
⇒ 新增 last_activity_{at,ok,failed}:有產出記本輪、空轉沿用上一輪(CarryForwardActivity)。
首頁改顯示「幾點整理了幾份」,綠燈只在真的整理過東西時才亮。
## ① Mac DMG 少了「看得出要拖」的版面
leo:「要跳出虛擬隨身碟,打開一個 finder 的視窗,**顯示 Arcrun 和 Application 的捷徑**,
用戶把 App 拖進 Application」。
原本 DMG 內容是對的(Arcrun.app+Applications 捷徑),但**沒設版面**
⇒ 預設清單視圖、位置隨機,看不出「要往右拖」。
⇒ build-dmg.sh 改走 UDRW → Finder AppleScript 設大圖示/視窗大小/左右並排 → 轉 UDZO。
best-effort:無桌面工作階段時只警告不中止(版面是加分,不該讓打包掛掉)。
⚠️ 真正讓 leo 拿到 zip 的原因不在這裡——是**線上 portal 還沒出貨**(見下)。
## 驗(實測輸出)
· collector 全測綠;新增 TestCarryForwardActivity 四子測(含「空轉不該抹掉上次成果」)
· 掛載 dist/Arcrun-v0.18.5.dmg 實查:
內容剛好兩項(Arcrun.app + Applications→/Applications 捷徑)
.DS_Store 6148 bytes(版面已存進去)
Contents/MacOS/ 有 arcrun-app **和 arcrun-collector**
CFBundleShortVersionString = 0.18.5(不是 1.0.0)/LSUIElement = true/codesign -v 通過
· 三支機械閘 check-cis/check-render/check-tray 全 PASS
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+51
-17
@@ -78,6 +78,11 @@ type syncStatus struct {
|
||||
ExtractFailed int `json:"extract_failed"`
|
||||
ExtractorOK bool `json:"extractor_ok"`
|
||||
ExtractorError string `json:"extractor_error,omitempty"`
|
||||
// 「上次真的有做事」那一輪(2026-08-05)——ExtractedOK 是本輪計數、會被下一輪歸零,
|
||||
// 只靠它顯示成果,使用者在同步完成 15 秒後就看不到任何證據(leo 實撞)。
|
||||
LastActivityAt string `json:"last_activity_at,omitempty"`
|
||||
LastActivityOK int `json:"last_activity_ok"`
|
||||
LastActivityFailed int `json:"last_activity_failed"`
|
||||
}
|
||||
|
||||
// loadCfg 同時保留原始 map ⇒ 回寫時**不會弄丟我們沒宣告的欄位**
|
||||
@@ -164,21 +169,33 @@ func buildSteps(s syncStatus, syncing bool) []Step {
|
||||
{Title: "上傳到你的知識庫", State: ""},
|
||||
}
|
||||
}
|
||||
// 🔴 2026-08-05:這三步以前只要「跑過任何一輪」(LastSync 非空)就全標綠,
|
||||
// 而 meta 用的是**本輪**計數(下一輪歸零)⇒ 綠燈與實際進度脫鉤、數字又永遠空白,
|
||||
// 正是 leo 說的「都顯示綠燈沒動,實際上已經做完了」。
|
||||
// ⇒ 綠燈只在「真的有整理過東西」時才亮,且亮的是上次有產出那輪的數字+時間。
|
||||
done := ""
|
||||
if s.ExtractedOK > 0 || s.LastSync != "" {
|
||||
if s.LastActivityOK > 0 || s.LastActivityFailed > 0 {
|
||||
done = "done"
|
||||
}
|
||||
found := "等待中"
|
||||
if done != "" {
|
||||
if t, err := time.Parse(time.RFC3339, s.LastActivityAt); err == nil {
|
||||
found = "上次 " + t.Local().Format("15:04")
|
||||
} else {
|
||||
found = "已處理"
|
||||
}
|
||||
}
|
||||
meta := ""
|
||||
if s.ExtractedOK > 0 {
|
||||
meta = fmt.Sprintf("上一輪 %d 份", s.ExtractedOK)
|
||||
if s.LastActivityOK > 0 {
|
||||
meta = fmt.Sprintf("上次 %d 份", s.LastActivityOK)
|
||||
}
|
||||
up := Step{Title: "上傳到你的知識庫", Meta: meta, State: done}
|
||||
if s.ExtractFailed > 0 {
|
||||
up.Meta = fmt.Sprintf("%s · ⚠ %d 份失敗", meta, s.ExtractFailed)
|
||||
if s.LastActivityFailed > 0 {
|
||||
up.Meta = strings.TrimPrefix(fmt.Sprintf("%s · ⚠ %d 份失敗", meta, s.LastActivityFailed), " · ")
|
||||
}
|
||||
return []Step{
|
||||
watch,
|
||||
{Title: "發現變化", Meta: "等待中", State: done},
|
||||
{Title: "發現變化", Meta: found, State: done},
|
||||
{Title: "用 AI 整理成知識卡", State: done},
|
||||
up,
|
||||
}
|
||||
@@ -232,14 +249,23 @@ func loadSyncStatus() syncStatus {
|
||||
// · collector 沒在跑 → 明說「同步引擎沒有在跑」,不要假裝在整理
|
||||
// · 有訊號檔且引擎活著 → 才是真的「同步中」
|
||||
// · 其餘 → 看守中
|
||||
//
|
||||
// 🔴 2026-08-05 第二修(leo:「拖新檔進資料夾…自始至終都顯示『等待中』,
|
||||
//
|
||||
// 實際上已經做完了,這個 status 是壞的」)——t195 只補了「引擎活著」那半,
|
||||
// 「同步中」仍靠 sync-now 訊號檔判斷,那是錯的判準,兩個理由:
|
||||
// ① 訊號檔**只有手動按「立刻同步」才會產生**;leo 這次是拖檔進資料夾
|
||||
// (自動觸發),整輪從頭到尾沒有訊號檔 ⇒ 畫面永遠停在「看守中/等待中」。
|
||||
// ② 就算是手動按的,collector 是**先刪檔再跑**(consumeSyncNowSignal),
|
||||
// 所以真正在跑的那段時間訊號檔早就不見了。
|
||||
// ⇒ 改用 t191 已經做好的機制:collector 開工印 phase:"start"、跑完印 "done",
|
||||
// supervisor 據此維護 StateSyncing(supervisor.go)。**那條線本來就在,
|
||||
// Wails 版換代時沒接上而已**——不要再自己發明第三種判斷法。
|
||||
func describeStatus(s syncStatus) (syncing bool, big, sub string) {
|
||||
alive := collectorAlive()
|
||||
_, queued := os.Stat(syncNowSignal())
|
||||
|
||||
if !alive {
|
||||
if !collectorAlive() {
|
||||
return false, "同步引擎沒有在跑", "資料夾不會被自動整理 ⇒ 請結束 Arcrun 再重新開啟"
|
||||
}
|
||||
if queued == nil {
|
||||
if collectorSyncing() {
|
||||
return true, "同步中… 正在讀檔並整理成知識卡", "請稍候,完成後會顯示整理了幾份"
|
||||
}
|
||||
if s.ExtractorError != "" && !s.ExtractorOK {
|
||||
@@ -247,13 +273,21 @@ func describeStatus(s syncStatus) (syncing bool, big, sub string) {
|
||||
}
|
||||
parts := []string{}
|
||||
if t, err := time.Parse(time.RFC3339, s.LastSync); err == nil {
|
||||
parts = append(parts, "上次同步 "+t.Local().Format("15:04"))
|
||||
parts = append(parts, "上次檢查 "+t.Local().Format("15:04"))
|
||||
}
|
||||
if s.ExtractedOK > 0 {
|
||||
parts = append(parts, fmt.Sprintf("已整理 %d 份", s.ExtractedOK))
|
||||
}
|
||||
if s.ExtractFailed > 0 {
|
||||
parts = append(parts, fmt.Sprintf("⚠ %d 份失敗", s.ExtractFailed))
|
||||
// 用「上次真的有做事」那輪的數字,不用本輪計數——後者每輪歸零,
|
||||
// 會讓剛整理完的成果在十幾秒後從畫面上消失(就是 leo 撞到的那個「壞掉的 status」)。
|
||||
if s.LastActivityOK > 0 || s.LastActivityFailed > 0 {
|
||||
when := ""
|
||||
if t, err := time.Parse(time.RFC3339, s.LastActivityAt); err == nil {
|
||||
when = t.Local().Format("15:04") + " "
|
||||
}
|
||||
if s.LastActivityOK > 0 {
|
||||
parts = append(parts, fmt.Sprintf("%s已整理 %d 份", when, s.LastActivityOK))
|
||||
}
|
||||
if s.LastActivityFailed > 0 {
|
||||
parts = append(parts, fmt.Sprintf("⚠ %d 份失敗", s.LastActivityFailed))
|
||||
}
|
||||
}
|
||||
if len(parts) == 0 {
|
||||
return false, "看守中 · 資料夾有變動就會自動整理", "還沒有同步紀錄"
|
||||
|
||||
Reference in New Issue
Block a user