v1.4.3 — 抗辯在 v1.4.2 與它的第一批修法裡找到的
這一版的內容來自兩層審查:先對已發佈的 v1.4.2 跑抗辯,再對「修 v1.4.2 的那些修法」跑一次——大部分的內容出自第二層。每一項的第一次修法都是錯的,而錯法是第二輪才抓到的。
修復
.fable 不是目錄時,目標關卡會靜默死亡。 os.makedirs 在 try 之外,所以當 .fable 剛好是一個檔案時,例外會被 hook 的 fail-open 吞掉,整個組件停止運作——不計數、不擱置、不提醒,而且沒有任何徵兆。狀態檔讀不到時本來就會大聲擋下;現在寫不進去也一樣會出聲。
狀態檔可能被寫到、也可能被讀自 repo 之外。 一個 repo 可以 commit 一個指向外部的 .fable 連結。第一版守衛用 os.path.islink,而它兩處都看錯:它只看路徑的最後一層(所以 symlink 的 .fable/.gitignore 照樣寫出去),而且在 Windows 上對 junction 回 False——junction 不需要管理員權限,symlink 才需要。等於擋住了罕見的形狀,放過了常見的那個。 現在改以「解析後的真實路徑是否落在 repo 內」判定,而且讀取路徑同樣適用:跟著連結讀出去、再把內容注入上下文,是同一個洞的另一面。
不再改寫使用者的忽略檔。 先前的版本會讀既有的 .fable/.gitignore、判斷它「夠不夠」、不夠就 append 一行 *。那條路每一段都是錯的:append 會跟著 symlink 寫到 repo 外;沒補前導換行,把 something_else 變成 something_else*;它對「夠不夠」的判準比 git 自己寬(* 後面接 !*、或行尾有空白,都會被誤判為夠);兩個 session 並行會 append 兩次。猜一個屬於使用者的檔案,每猜一次就多一種傷害,所以現在不猜了——只有在關卡自己建立那個目錄時才寫。
擱置項的 note 注入前會截斷。 last_command 早有 160 字上限,note 沒有,而兩者同樣來自一個 repo 可以 commit 的檔案。
已知限制
- 兩個 session 同時擱置項目時可能遺失一筆:狀態是沒有鎖的 read-modify-write(實測 5 次全中)。記錄在
tests/test_goal_gate.py。 - 使用者若已經把
goal_state.jsoncommit 進版控,忽略檔對它無效;此時寫入會顯示為git status的修改,是可見的,不是靜默。
完整英文變更記錄見 CHANGELOG.md。