助理待辦簿:存放格式、讀寫工具、事件偵測與到期判定 #16

Merged
admin merged 4 commits from feat/assistant-task-book-storage-and-tool into develop 2026-09-03 08:42:48 +00:00
Member

摘要

  • 需求描述:助理要記住兩種項目——內建的定期檢查項與使用者當面交辦的事——但目前沒有地方放,也沒有東西判「現在到期了沒有」。待辦簿是助理待辦與建議下一個指令兩批功能的共同地基。這張 PR 做兩件事:存放格式與讀寫工具,以及事件偵測與到期判定。
  • 計畫名稱:無
  • 計畫頁:無
  • 分析頁:無

變更內容

檔案 為什麼改
tools/tasks.sh 新增。待辦簿的讀寫工具,六個子命令,735 行其中 202 行是註解
tools/due.sh 新增。事件偵測與到期判定,三個子命令,1161 行
tools/patrol.sh 巡檢一輪接上到期判定——快照要有人推進才活得起來
references/behaviors.md 「外部呼叫」等欄位記下這兩支工具
三份 manifest 版號 0.1.6 升到 0.1.8

存放:一筆一檔,純文字 key=value

  • 一筆一檔的理由跟重啟閘門那組檔案一樣:並行寫入不互相覆寫。 五支 CLI 加上排程那一輪有可能同時動待辦簿。整本存成一個檔案的話,兩邊各讀一次整檔、各改自己那一筆、各寫回整檔,後寫的那一次就把前一次整本蓋掉,而且沒有任何訊號。同一個 id 被同時寫也不會寫出半份:先寫暫存檔再搬過去,搬在同一個檔案系統上是原子操作;暫存檔名以點號開頭,列表跳過點號開頭的檔案。
  • id 取完整雜湊的前八碼,刻意不跟 wiki 頁名的四十碼一致。 頁名不准截短是因為撞了就是兩台機器的紀錄互相覆寫且看不出來。這裡的 id 是本機檔名,人要念它、打進指令、看它印在狀態表與提醒文字裡——四十碼沒有人讀得完也打不對,人就會改用「第三筆」這種說法指定要關哪一筆,那才是真正會關錯的地方。前八碼是同一個雜湊的前綴、不是另一套算法,拿建立時間與標題重算就驗得回來。
  • 前綴碰撞每次多取兩碼再試,不補序號——補了就算不回來。建立時間與標題都相同的不是碰撞而是同一筆被登錄兩次,一律不寫:定期檢查項會因為清單重建而重跑登錄,靜靜多寫一筆會讓同一個檢查每輪做兩次。
  • 值裡有等號或換行用兩條約定處理,不發明跳脫規則。 讀的時候只在第一個等號斷開;寫的時候把值折成一行並記一行說折過了。讀的人不只這一支腳本,跳脫規則要每個讀的人各自實作一次,漏掉一個就會把跳脫序列原樣印進報告或監控頁,而那看起來很像正常內容。

判定:另開一支,界線做成單向

  • 不併進存放那一支。 那一支的檔頭把「我不判定」寫成合約,而合約是呼叫端唯一的依據;併進去就要推翻那整段話,而讀過舊版的人會以為那一支不判、自己再判一次,於是漂移從註解裡長出來。判定這一支只讀待辦檔與印值,要改狀態一律回頭叫存放那一支的完成與失敗。
  • 事件偵測靠比對狀態快照,不改任何產生者。 六個事件名各自接上本機狀態來源:工作包鎖檔轉態、階段檔換值、錯誤紀錄行數變多、工作階段開始與結束、日誌暫存區清空。
  • 這個選擇有一個明確的代價,寫進檔頭:兩輪之間發生又消失的事件會漏掉。 往後誰假設「事件不會漏」就會出錯,而那種錯是無聲的。不為了補這個洞去改那幾支產生者——要它們各自在事件發生那一刻多寫一筆,任何一支忘了寫就讓對應的事件從此不再發生,而那同樣無聲,還散在五個 domain 裡查不出是誰漏的。快照比對至少壞掉時看得出來。
  • 第一次跑一律只建快照、不發事件。 否則機器上所有既有狀態都會被當成剛發生,讓每一筆事件型待辦一次全到期。同一條理由逐個來源再套一次,所以快照要留一列記每個來源上一輪是看得到還是不存在——少了它就分不出「上一輪沒有這個來源」與「上一輪這個來源是空的」,而只有後者的差別才算事件。
  • 四種組合一個都不壓。 時鐘型的排定點從那個時間往後數,不從上次執行起算——每次拿上次執行加間隔,執行慢幾秒就往後挪幾秒,一天下來就偏掉。漏掉的排定點只補一次不逐個追補,否則機器關一天再開會連續跑幾十輪同一件事。
  • 事件型的下次執行時間一律留空。 唯一算得出來的是重新武裝時刻,但那個值填進去會被狀態表與提醒讀成「那個時間會跑」,它其實只是「那個時間之前不會跑」,差別在畫面上看不出來。那個值改印成另一個欄位。

補了規格四個洞

  • 欄位表少建立時間。 id 是它算出來的,不存就再也算不回同一個 id、驗不出檔名對不對、前綴碰撞時也接不下去。補上之後一筆是十四個鍵。
  • 沒有累加失敗次數的操作。 規格說失敗要累加,但原本四個操作沒有一個寫得到它。少了它那個計數永遠是零,監控頁與提醒上那句「已連續失敗幾次」永遠是零次,於是一個壞掉的項目每輪重試而沒人知道——那正是這個欄位要防的事。
  • 沒有解開停用的操作。 停用只由人設,也就只有人解得開,但沒有別的元件寫得出這個轉移。只給停用不給恢復就是一道單向門,人只能去手改檔案,而手改繞過了轉移表。
  • 間隔格式從來沒定義過。 定成正整數加單位,刻意不收裸數字——排程週期以分鐘算、心跳門檻以秒算,裸數字兩種都讀得通,讀錯就差六十倍。

解了一個規格衝突

規格同時要求「同一件事不重複觸發」與「失敗照重試,不自動暫停」,而兩件事寫在同一個欄位上。不重複觸發的判準是「事件發生時間比上次執行晚」,但失敗也會寫上次執行,於是失敗過的事件型待辦再也等不到同一次事件,也就永遠不重試。

改用連續失敗次數當第三個判準把兩者分開:狀態還是待辦而次數大於零,代表上一次執行失敗,一律算到期,不再比事件也不看排定點。完成會把次數歸零,所以成功那一次不會被誤判成要重試。

這是這一批唯一改了判定語意的地方,值得覆核。

兩項刻意未接線,而且吵出來

  • 分析完成那個事件的狀態來源在 wiki 上、要連網要金鑰,跟其他六個純本機讀取不同性質。混進來之後金鑰一過期就讓事件偵測整項每輪失敗;更糟的是判不出來時那幾筆會靜靜地永遠不到期,跟填一個不存在的事件名一樣看不出壞在哪。
  • cron 式子要自己實作五個欄位的萬用字元、清單與步進,算錯一格就是差一小時或差一天,而那種錯要等真的跑錯才看得出來。

兩者的處置都是印一行未接線、列進要人接手那一節,明說「這一筆現在判不出到期,不是還沒發生」。不接線與靜靜當成沒發生是兩件事,差別就在有沒有那一行。

狀態轉移表寫死在腳本裡

  • 停用之後不收完成:停掉的那一筆助理本來就沒在跑,標成做完等於偷偷解開又收掉。
  • 停用之後不收失敗:助理沒在跑它,就不可能是它失敗。
  • 收掉的那一筆不再有下一次,四種操作全擋。
  • 停用只由停用這一個操作寫得出來,而巡檢那一輪只會叫完成與失敗,所以助理在程式上就寫不出停用。
  • 恢復刻意不把連續失敗次數歸零:那幾次失敗真的發生過,歸零會把提醒抹掉,而那筆一恢復就會照樣再失敗。

測試結果

  • 全程用隔離的根目錄實測,正式的助理目錄沒有被動到——那底下到現在還沒有待辦簿目錄、也沒有快照檔。
  • 存放那一支:六個子命令各跑一次、七種不合法轉移各回專屬結束碼、值裡有等號與換行、同一秒內建兩筆不撞、同一秒同一標題認出是同一筆、真的前綴碰撞會加長前綴、根目錄四種解析情境、並行同時登錄二十筆每一筆都完整且沒留下暫存檔。
  • 判定那一支:四種組合逐筆判定、第一次跑無快照的行為、同一事件連續兩輪不重複觸發、來源不存在與存在卻讀不到(以另一個使用者跑)兩種、快照換不上去、時鐘型不漂移、失敗照重試兩型都驗、--dry-run 不推進快照、巡檢一輪整合。
  • 實測抓到一個真的臭蟲並修掉:查找記錄原本寫成印出路徑、由呼叫端用命令替換接,於是裡面的錯誤退出只結束子行程、外層照樣往下走——訊息說欄位不合法卻回了找不到那一筆的碼。
  • 順手修掉一個同類的坑:用冒號當空指令去清空檔案時,重導向失敗會讓整個殼直接結束,後面的分流一次都跑不到(實測結束碼 2、|| 沒跑到)。改用 true 並把理由寫進註解。
  • lint-scripts.sh、check-behaviors.sh、ste100-lint.sh 都回結束碼 0。無 BOM。
  • 註解範圍那道 hook 擋過一次:case 的否定字集被認成議題編號。改寫成 grep -qE 並在註解說明,不是關掉 hook 過關。

這一批的邊界

登錄時的補問流程、逾期與失敗的處理行為、提醒怎麼送到前景、wiki 雙向同步,四項都不在這一批。但欄位都已經留在檔案裡,接的時候不必改存放格式。哪些欄位現在只存放不判定,檔頭有一段逐項寫明。

前置 Push Request

  • 無
## 摘要 - 需求描述:助理要記住兩種項目——內建的定期檢查項與使用者當面交辦的事——但目前沒有地方放,也沒有東西判「現在到期了沒有」。待辦簿是助理待辦與建議下一個指令兩批功能的共同地基。這張 PR 做兩件事:存放格式與讀寫工具,以及事件偵測與到期判定。 - 計畫名稱:無 - 計畫頁:無 - 分析頁:無 ## 變更內容 | 檔案 | 為什麼改 | | --- | --- | | `tools/tasks.sh` | 新增。待辦簿的讀寫工具,六個子命令,735 行其中 202 行是註解 | | `tools/due.sh` | 新增。事件偵測與到期判定,三個子命令,1161 行 | | `tools/patrol.sh` | 巡檢一輪接上到期判定——快照要有人推進才活得起來 | | `references/behaviors.md` | 「外部呼叫」等欄位記下這兩支工具 | | 三份 manifest | 版號 0.1.6 升到 0.1.8 | ## 存放:一筆一檔,純文字 key=value - **一筆一檔的理由跟重啟閘門那組檔案一樣:並行寫入不互相覆寫。** 五支 CLI 加上排程那一輪有可能同時動待辦簿。整本存成一個檔案的話,兩邊各讀一次整檔、各改自己那一筆、各寫回整檔,後寫的那一次就把前一次整本蓋掉,而且沒有任何訊號。同一個 `id` 被同時寫也不會寫出半份:先寫暫存檔再搬過去,搬在同一個檔案系統上是原子操作;暫存檔名以點號開頭,列表跳過點號開頭的檔案。 - **`id` 取完整雜湊的前八碼,刻意不跟 wiki 頁名的四十碼一致。** 頁名不准截短是因為撞了就是兩台機器的紀錄互相覆寫且看不出來。這裡的 `id` 是本機檔名,人要念它、打進指令、看它印在狀態表與提醒文字裡——四十碼沒有人讀得完也打不對,人就會改用「第三筆」這種說法指定要關哪一筆,**那才是真正會關錯的地方**。前八碼是同一個雜湊的前綴、不是另一套算法,拿建立時間與標題重算就驗得回來。 - 前綴碰撞每次多取兩碼再試,不補序號——補了就算不回來。建立時間與標題都相同的不是碰撞而是同一筆被登錄兩次,一律不寫:定期檢查項會因為清單重建而重跑登錄,靜靜多寫一筆會讓同一個檢查每輪做兩次。 - **值裡有等號或換行用兩條約定處理,不發明跳脫規則。** 讀的時候只在第一個等號斷開;寫的時候把值折成一行並記一行說折過了。讀的人不只這一支腳本,跳脫規則要每個讀的人各自實作一次,漏掉一個就會把跳脫序列原樣印進報告或監控頁,而那看起來很像正常內容。 ## 判定:另開一支,界線做成單向 - **不併進存放那一支。** 那一支的檔頭把「我不判定」寫成合約,而合約是呼叫端唯一的依據;併進去就要推翻那整段話,而讀過舊版的人會以為那一支不判、自己再判一次,於是漂移從註解裡長出來。判定這一支只讀待辦檔與印值,要改狀態一律回頭叫存放那一支的完成與失敗。 - **事件偵測靠比對狀態快照,不改任何產生者。** 六個事件名各自接上本機狀態來源:工作包鎖檔轉態、階段檔換值、錯誤紀錄行數變多、工作階段開始與結束、日誌暫存區清空。 - **這個選擇有一個明確的代價,寫進檔頭:兩輪之間發生又消失的事件會漏掉。** 往後誰假設「事件不會漏」就會出錯,而那種錯是無聲的。不為了補這個洞去改那幾支產生者——要它們各自在事件發生那一刻多寫一筆,任何一支忘了寫就讓對應的事件從此不再發生,而那同樣無聲,還散在五個 domain 裡查不出是誰漏的。快照比對至少壞掉時看得出來。 - **第一次跑一律只建快照、不發事件。** 否則機器上所有既有狀態都會被當成剛發生,讓每一筆事件型待辦一次全到期。同一條理由逐個來源再套一次,所以快照要留一列記每個來源上一輪是看得到還是不存在——少了它就分不出「上一輪沒有這個來源」與「上一輪這個來源是空的」,而只有後者的差別才算事件。 - **四種組合一個都不壓。** 時鐘型的排定點從那個時間往後數,不從上次執行起算——每次拿上次執行加間隔,執行慢幾秒就往後挪幾秒,一天下來就偏掉。漏掉的排定點只補一次不逐個追補,否則機器關一天再開會連續跑幾十輪同一件事。 - **事件型的下次執行時間一律留空。** 唯一算得出來的是重新武裝時刻,但那個值填進去會被狀態表與提醒讀成「那個時間會跑」,它其實只是「那個時間之前不會跑」,差別在畫面上看不出來。那個值改印成另一個欄位。 ## 補了規格四個洞 - **欄位表少建立時間。** `id` 是它算出來的,不存就再也算不回同一個 `id`、驗不出檔名對不對、前綴碰撞時也接不下去。補上之後一筆是十四個鍵。 - **沒有累加失敗次數的操作。** 規格說失敗要累加,但原本四個操作沒有一個寫得到它。少了它那個計數永遠是零,監控頁與提醒上那句「已連續失敗幾次」永遠是零次,於是一個壞掉的項目每輪重試而沒人知道——**那正是這個欄位要防的事**。 - **沒有解開停用的操作。** 停用只由人設,也就只有人解得開,但沒有別的元件寫得出這個轉移。只給停用不給恢復就是一道單向門,人只能去手改檔案,而手改繞過了轉移表。 - **間隔格式從來沒定義過。** 定成正整數加單位,刻意不收裸數字——排程週期以分鐘算、心跳門檻以秒算,裸數字兩種都讀得通,讀錯就差六十倍。 ## 解了一個規格衝突 規格同時要求「同一件事不重複觸發」與「失敗照重試,不自動暫停」,而兩件事寫在同一個欄位上。不重複觸發的判準是「事件發生時間比上次執行晚」,但失敗也會寫上次執行,於是失敗過的事件型待辦再也等不到同一次事件,也就永遠不重試。 改用連續失敗次數當第三個判準把兩者分開:狀態還是待辦而次數大於零,代表上一次執行失敗,一律算到期,不再比事件也不看排定點。完成會把次數歸零,所以成功那一次不會被誤判成要重試。 **這是這一批唯一改了判定語意的地方,值得覆核。** ## 兩項刻意未接線,而且吵出來 - **分析完成那個事件**的狀態來源在 wiki 上、要連網要金鑰,跟其他六個純本機讀取不同性質。混進來之後金鑰一過期就讓事件偵測整項每輪失敗;更糟的是判不出來時那幾筆會靜靜地永遠不到期,跟填一個不存在的事件名一樣看不出壞在哪。 - **cron 式子**要自己實作五個欄位的萬用字元、清單與步進,算錯一格就是差一小時或差一天,而那種錯要等真的跑錯才看得出來。 兩者的處置都是印一行未接線、列進要人接手那一節,明說「這一筆現在判不出到期,不是還沒發生」。**不接線與靜靜當成沒發生是兩件事,差別就在有沒有那一行。** ## 狀態轉移表寫死在腳本裡 - 停用之後不收完成:停掉的那一筆助理本來就沒在跑,標成做完等於偷偷解開又收掉。 - 停用之後不收失敗:助理沒在跑它,就不可能是它失敗。 - 收掉的那一筆不再有下一次,四種操作全擋。 - 停用只由停用這一個操作寫得出來,而巡檢那一輪只會叫完成與失敗,**所以助理在程式上就寫不出停用**。 - 恢復刻意不把連續失敗次數歸零:那幾次失敗真的發生過,歸零會把提醒抹掉,而那筆一恢復就會照樣再失敗。 ## 測試結果 - 全程用隔離的根目錄實測,正式的助理目錄沒有被動到——那底下到現在還沒有待辦簿目錄、也沒有快照檔。 - 存放那一支:六個子命令各跑一次、七種不合法轉移各回專屬結束碼、值裡有等號與換行、同一秒內建兩筆不撞、同一秒同一標題認出是同一筆、真的前綴碰撞會加長前綴、根目錄四種解析情境、並行同時登錄二十筆每一筆都完整且沒留下暫存檔。 - 判定那一支:四種組合逐筆判定、第一次跑無快照的行為、同一事件連續兩輪不重複觸發、來源不存在與存在卻讀不到(以另一個使用者跑)兩種、快照換不上去、時鐘型不漂移、失敗照重試兩型都驗、`--dry-run` 不推進快照、巡檢一輪整合。 - **實測抓到一個真的臭蟲並修掉**:查找記錄原本寫成印出路徑、由呼叫端用命令替換接,於是裡面的錯誤退出只結束子行程、外層照樣往下走——訊息說欄位不合法卻回了找不到那一筆的碼。 - **順手修掉一個同類的坑**:用冒號當空指令去清空檔案時,重導向失敗會讓整個殼直接結束,後面的分流一次都跑不到(實測結束碼 2、`||` 沒跑到)。改用 `true` 並把理由寫進註解。 - `lint-scripts.sh`、`check-behaviors.sh`、`ste100-lint.sh` 都回結束碼 0。無 BOM。 - 註解範圍那道 hook 擋過一次:`case` 的否定字集被認成議題編號。改寫成 `grep -qE` 並在註解說明,不是關掉 hook 過關。 ## 這一批的邊界 登錄時的補問流程、逾期與失敗的處理行為、提醒怎麼送到前景、wiki 雙向同步,四項都不在這一批。但欄位都已經留在檔案裡,接的時候不必改存放格式。哪些欄位現在只存放不判定,檔頭有一段逐項寫明。 ## 前置 Push Request - 無
jiantw83 added 2 commits 2026-09-03 07:51:29 +00:00
助理要記住兩種項目——內建的定期檢查項與使用者當面交辦的事——但目前沒有地方放。待辦簿是助理待辦與建議下一個指令兩批功能的共同地基,先把存放格式與讀寫工具做出來,判定邏輯之後才接。

存成一筆一檔,純文字 key=value。一筆一檔的理由同重啟閘門那組檔案:並行寫入不互相覆寫。五支 CLI 加上排程那一輪有可能同時動待辦簿,整本存成一個檔案的話兩邊各讀一次整檔、各改自己那一筆、各寫回整檔,後寫的那一次就把前一次整本蓋掉,而且沒有任何訊號。同一個 id 被同時寫也不會寫出半份:先寫暫存檔再搬過去,搬在同一個檔案系統上是原子操作。暫存檔名以點號開頭,列表跳過點號開頭的檔案,寫到一半的那一份不會被列出來。

規格的欄位表少一個欄位。id 是建立時間加標題的雜湊,但表上沒有存建立時間的欄位,不存它就再也算不回同一個 id、驗不出檔名對不對、前綴碰撞時也接不下去。補上建立時間,所以一筆是十四個鍵。

id 取完整雜湊的前八碼,不跟 wiki 頁名的四十碼一致。兩者用途不同:四十碼那條規則管的是 wiki 頁名,頁名一撞就是兩台機器的紀錄互相覆寫且看不出來,所以不准截短;這裡的 id 是本機檔名,人要念它、打進指令、看它印在狀態表與提醒文字裡,四十碼沒有人讀得完也打不對,人就會改用「第三筆」這種說法指定要關哪一筆,那才是真正會關錯的地方。前八碼是同一個雜湊的前綴不是另一套算法,拿建立時間與標題重算就驗得回來。前綴撞上而內容不同就每次多取兩碼再試,不在後面補序號——補了就算不回來。建立時間與標題都相同的不是碰撞而是同一筆被登錄兩次,一律不寫並回專屬結束碼,因為定期檢查項會因為清單重建而重跑登錄,靜靜多寫一筆會讓同一個檢查每輪做兩次。

操作補到六個,兩個都是補規格的洞。失敗那一個是因為規格說失敗要累加連續失敗次數,但原本四個操作沒有一個寫得到它,少了它那個計數永遠是零,監控頁與提醒上那句「已連續失敗幾次」永遠是零次,於是一個壞掉的項目每輪重試而沒人知道,那正是這個欄位要防的事。恢復那一個是因為停用只由人設,也就只有人解得開,沒有別的元件寫得出這個轉移;只給停用不給恢復就是一道單向門,人只能去手改檔案,而手改繞過了轉移表。

上次執行與下次執行不另開操作:完成與失敗都吃選項把值餵進來,值由算到期那一邊算好。這一支不算下一次是什麼時候,兩邊各算一次就會漂移。也刻意沒有編輯操作:id 由建立時間與標題算出來,改掉標題之後 id 就對不回去了。

狀態轉移寫成明確的表並在腳本裡擋住不合法的轉移。停用之後不收完成,因為停掉的那一筆助理本來就沒在跑,標成做完等於偷偷解開又收掉;停用之後不收失敗,因為助理沒在跑它就不可能是它失敗;收掉的那一筆不再有下一次,四種操作全擋。恢復刻意不把連續失敗次數歸零,那幾次失敗真的發生過,歸零會把提醒抹掉而那筆一恢復就會照樣再失敗,要歸零就等它跑成功一次。

值裡有等號或換行用兩條約定處理,不發明跳脫規則。讀的時候只在第一個等號斷開,十四個鍵都是固定的詞、一個都不含等號。寫的時候把值折成一行並在標準錯誤記一行說折過了。選折行不選跳脫,是因為讀的人不只這一支腳本,技能本文與巡檢那一輪都直接把檔案當 key=value 讀,跳脫規則要每個讀的人各自實作一次,漏掉一個就會把跳脫序列原樣印進報告或監控頁,而那看起來很像正常內容。

根目錄解析退回使用者家目錄底下那一層,跟排程、巡檢與心跳三支退回同一個值——兩邊退回的位置不同,待辦簿就會躲在一個沒有人去讀的目錄裡,而每一支都自認為讀對了。連家目錄也沒有才拒絕,不猜路徑:猜錯就是把待辦寫到一個沒有人會去讀的地方,而且看起來像成功。

實測抓到一個真的臭蟲並修掉。查找記錄原本寫成印出路徑、由呼叫端用命令替換接,於是裡面的錯誤退出只結束子行程、外層照樣往下走,訊息說欄位不合法卻回了找不到那一筆的碼,呼叫端拿到的碼與真正的原因不一樣。改寫成直接設變數再回碼。

這一輪只做存放與讀寫。登錄時的補問流程、事件詞彙表接上產生者、到期判定、逾期與失敗處理、提醒送到前景、wiki 雙向同步,六項都不在這一輪,但欄位都已經留在檔案裡,接的時候不必改存放格式。目前還沒有任何操作呼叫得到這六個子命令,行為契約只記下這一支工具存在,不讓清單先跑到技能前面去。
待辦簿工具要靠版號才傳得到機器端。

三份 manifest 由 sync-skill-manifest.sh 同步,只動版本欄位。
jiantw83 added 2 commits 2026-09-03 08:38:04 +00:00
待辦簿存得住 trigger 與 recur,但沒有東西判「現在到期了沒有」。存放那一支的檔頭明寫它不判定、算的邏輯在別的地方,這一輪就是補那個別的地方。

另開一支而不併進存放那一支。那一支的檔頭把「我不判定」寫成合約,而合約是呼叫端唯一的依據;併進去就要推翻那整段話,而讀過舊版的人會以為那一支不判、自己再判一次,於是漂移從註解裡長出來。界線做成單向:判定這一支只讀待辦檔與印值,要改狀態一律回頭叫存放那一支的完成與失敗。

事件偵測靠比對狀態快照,不改任何產生者。每一輪讀那幾支產生者留下的狀態,跟上一輪存下的快照比,有差別就算事件發生。六個事件名各自接上本機狀態來源:工作包鎖檔轉態、階段檔換值、錯誤紀錄行數變多、工作階段開始與結束、日誌暫存區清空。

這個選擇有一個明確的代價,寫進檔頭:兩輪之間發生又消失的事件會漏掉。往後誰假設「事件不會漏」就會出錯,而那種錯是無聲的。不為了補這個洞去改那幾支產生者——要它們各自在事件發生那一刻多寫一筆,任何一支忘了寫就讓對應的事件從此不再發生,而那同樣無聲,還散在五個 domain 裡查不出是誰漏的。快照比對至少壞掉時看得出來。

第一次跑一律只建快照、不發事件,否則機器上所有既有狀態都會被當成剛發生,讓每一筆事件型待辦一次全到期。同一條理由逐個來源再套一次:某個來源上一輪不存在、這一輪才出現,那個來源這一輪也只建快照。所以快照要留一列記每個來源上一輪是看得到還是不存在——少了它就分不出「上一輪沒有這個來源」與「上一輪這個來源是空的」,而只有後者的差別才算事件。來源目錄從有變成不見時也不發事件,只記警示:整個目錄被砍掉不是每一支工作包都合併了。

四種組合一個都不壓。時鐘型的排定點從那個時間往後數、一次加一個間隔,不從上次執行起算——每次拿上次執行加間隔,執行慢幾秒就往後挪幾秒,一天下來就偏掉。漏掉的排定點只補一次不逐個追補,否則機器關一天再開會連續跑幾十輪同一件事。事件型配間隔時,那個間隔照存放那一支的定義當「重新武裝的最短間隔」。

事件型的下次執行時間一律留空。事件型沒有預定時間,唯一算得出來的是重新武裝時刻,但那個值填進去會被狀態表與提醒讀成「那個時間會跑」,它其實只是「那個時間之前不會跑」,差別在畫面上看不出來。那個值改印成另一個欄位,要看的人看得到。

規格有兩條在同一個欄位上打架。同一件事不重複觸發的判準是「事件發生時間比上次執行晚」,但失敗也會寫上次執行,於是失敗過的事件型待辦再也等不到同一次事件,也就永遠不重試——而規格明確要求失敗照重試。改用連續失敗次數當第三個判準把兩者分開:狀態還是待辦而次數大於零,代表上一次執行失敗,一律算到期,不再比事件也不看排定點。完成會把次數歸零,所以成功那一次不會被誤判成要重試。

兩項刻意標成未接線並吵出來,不假裝算得出來。分析完成那一個事件的狀態來源在 wiki 上、要連網要金鑰,混進來之後金鑰一過期就讓事件偵測整項每輪失敗;更糟的是判不出來時那幾筆會靜靜地永遠不到期,跟填一個不存在的事件名一樣看不出壞在哪。cron 式子同理,五個欄位的萬用字元與步進算錯一格就是差一小時或差一天,而那種錯要等真的跑錯才看得出來。兩者的處置都是印一行未接線、列進要人接手那一節,明說「這一筆現在判不出到期,不是還沒發生」。

間隔格式規格從來沒定義過,這一輪定成正整數加單位,刻意不收裸數字——排程週期以分鐘算、心跳門檻以秒算,裸數字兩種都讀得通,讀錯就差六十倍。

巡檢那一路一併接上:快照要有人推進才活得起來。刻意不把它算進既有五項的成敗,避免動到摘要表的欄名與本輪項目那一列的文字,舊頁那些列的欄名不會跟著改,同一張表就會有兩種寫法。失敗時改成記警示與待人處理。

順手修掉一個同類的坑:用冒號當空指令去清空檔案時,重導向失敗會讓整個殼直接結束,後面的分流一次都跑不到。這一支一律改用 true 並把理由寫進註解。
事件偵測與到期判定要靠版號才傳得到機器端。

三份 manifest 由 sync-skill-manifest.sh 同步,只動版本欄位。
jiantw83 changed title from 助理待辦簿的存放格式與讀寫工具,六個子命令與明確的狀態轉移表 to 助理待辦簿:存放格式、讀寫工具、事件偵測與到期判定 2026-09-03 08:40:07 +00:00
admin merged commit e2d7454ee6 into develop 2026-09-03 08:42:48 +00:00
admin deleted branch feat/assistant-task-book-storage-and-tool 2026-09-03 08:42:48 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: plugins/assist#16