Commit Graph
69 Commits
Author SHA1 Message Date
admin 78116a61f1 Merge pull request '釋出:條目只帶放得下 CLI 執行檔的那幾個目錄,不快照整條 PATH' (#33) from develop into master
Reviewed-on: #33
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-04 09:24:51 +00:00
admin cc5faaff21 Merge pull request '條目只帶放得下 CLI 執行檔的那幾個目錄,不快照整條 PATH' (#32) from fix/schedule-path-only-cli-dirs into develop
Reviewed-on: #32
2026-09-04 07:13:25 +00:00
jiantw83andClaude Opus 5 ffe9a20178 fix(schedule): 條目只帶放得下 CLI 執行檔的那幾個目錄,不快照整條 PATH
上一版把整條 PATH 快照進條目,實測直接裝不起來:crontab 一行有長度上限,
回的是 command too long,結束碼 4。這台機器的 PATH 是 2160 字元,去重又去掉
不存在的那幾段之後還有 1332 字元,仍然超過。

改成只帶放得下 CLI 執行檔的那幾個目錄,這台機器實測兩個、合起來 70 字元,
整行降到 685 字元。夠用的理由是這一條要解決的問題很窄:cron 只給 /usr/bin
與 /bin,而偵測 CLI 那一支靠 PATH 找執行檔,找不到就回結束碼 0 加一份空清單
——看起來像「這台機器沒裝 CLI」。巡檢要跑的指令本身走字面絕對路徑,不靠它。

收尾接上 cron 本來就會給的那兩段,免得只剩自訂目錄而找不到系統工具。

一個代價寫進註解:有些 CLI 裝在會過期的目錄底下,例如帶行程編號的多殼層
目錄,那種路徑下一次開機就不在了。不特別過濾——過濾要認得每一種安裝方式,
那份名單會過期得比路徑還快。重跑一次 install 就重新拍一份,而條目本來就是
安裝當下的快照。

實測:拿條目會帶的那條 PATH 在清空環境裡跑,五支 CLI 全解得出來;真的裝一次
回結束碼 0,服務在跑,連結檢查通過。

三份 manifest 版號 0.2.5 升到 0.2.6。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 15:12:04 +08:00
admin 1bebf7450f Merge pull request '釋出:排程條目把 PATH 一起快照進去' (#31) from develop into master
Reviewed-on: #31
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-04 06:58:38 +00:00
admin 2c0718ee19 Merge pull request '排程條目把 PATH 一起快照進去,無人值守那一輪才偵測得到 CLI' (#30) from fix/schedule-snapshots-path into develop
Reviewed-on: #30
2026-09-04 06:54:40 +00:00
jiantw83andClaude Opus 5 044676b1fc fix(schedule): 排程條目把 PATH 一起快照進去
cron 給的 PATH 只有 /usr/bin 與 /bin,而這台機器的 CLI 執行檔裝在家目錄底下。
於是無人值守那一輪偵測 CLI 一支都找不到——而且是回結束碼 0 加一份空清單,
不是失敗。看起來像「這台機器沒裝 CLI」,實際上是 PATH 上找不到。

實測踩到:那一輪印出 clis=0,帶 CLI 代入點的內建項全部代不出目標而被擋下,
同一支腳本在有人的 shell 裡回五支。

修在條目這一層,不是讓偵測那一支自己去猜安裝路徑:猜就要維護一份常見路徑
清單,而清單會過期,過期的方式跟今天修掉的那幾個一模一樣。條目本來就快照
十個環境變數,多這一個等於把「這台機器的執行檔裝在哪」交給安裝當下的環境
回答,不必任何人維護。

巡檢那一輪要跑的指令本身走的是字面絕對路徑、不靠 PATH;靠 PATH 的是那幾支
腳本自己呼叫的外部程式,所以這一條補的是後者。

實測:拿條目會帶的那條 PATH 在清空環境裡跑,五支 CLI 全解得出來;對照組用
cron 預設的 PATH,零支。

三份 manifest 版號 0.2.4 升到 0.2.5。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 14:41:31 +08:00
admin 5d353ecc40 Merge pull request '釋出:補印執行那一支的允許規則,並回頭比對本文叫得到的每一支' (#29) from develop into master
Reviewed-on: #29
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-04 06:26:06 +00:00
admin 6dbf2f1a22 Merge pull request '補印執行那一支的允許規則,並回頭比對本文叫得到的每一支' (#28) from fix/schedule-prints-run-due-rule-and-self-checks into develop
Reviewed-on: #28
2026-09-04 06:22:18 +00:00
jiantw83andClaude Opus 5 3784cb51be fix(schedule): 補印執行那一支的允許規則,並回頭比對本文叫得到的每一支
巡檢多了執行到期內建項那一步,而印允許規則的清單是寫死的、沒跟著加。少一條
的代價不是報錯:那一輪停在權限詢問,鎖已經握在手上,接下來每一輪都讓開到鎖
逾時為止,而外面只看得到「心跳過期」。

補上那一條之後順手做掉根因。清單寫死,技能本文哪天多叫一支腳本這裡不會自己
知道,所以印完回頭掃一次本文,把它叫的每一支跟印過的比對,缺的逐支點名。

三個實作決定都是被自己踩出來的:

只掃 patrol 那一節,不掃整份。start 與 status 兩個操作都有人在現場,它們叫的
腳本跳一次權限詢問有人按得掉。整份掃會讓那幾支每次都被報成缺規則,而一份
每次都有雜訊的警告,看的人第二次就會跳過它——那時候真的漏一支就沒有人看得到。

技能本文的目錄名兩種版面都找:安裝版面帶 jsc- 前綴,開發用的並排工作目錄
版面不帶。原本只認一種,於是在另一種版面底下這道檢核被檔案存在檢查靜靜跳過
——一道「找不到就當通過」的檢核,跟沒有那道檢核是同一件事。找不到就明說這
一次沒有比對過,不要不出聲。

只警告不中止。比對規則有可能跟不上本文的寫法,那時候不該連排程都裝不起來。

三份 manifest 版號 0.2.3 升到 0.2.4。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 14:15:43 +08:00
admin 0fcce1c96a Merge pull request '釋出:到期的內建檢查項真的跑一遍,成敗回寫待辦簿' (#27) from develop into master
Reviewed-on: #27
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-04 06:08:58 +00:00
admin dc7c164d9a Merge pull request '到期的內建檢查項真的跑一遍,成敗回寫待辦簿' (#26) from feat/run-due-built-in-check-items into develop
Reviewed-on: #26
2026-09-04 06:07:21 +00:00
jiantw83andClaude Opus 5 7d40c9dded feat(assistant): 巡檢那一輪接上執行到期內建項
檢核腳本沒人叫等於不存在,所以同一批把它接進巡檢的步驟五,擺在寫心跳之前
——跑過的結果要進得了這一輪的紀錄。任何一個結束碼都不中止那一輪:一支指令
失敗是發現,不是壞掉的一輪。

界線那一段補了一條,把兩件事分開:不對發現動手,跟跑自己排定的工作,不是
同一件事。待人處理那幾列是關於別人機器狀態的發現,跑那幾列等於一輪自己決定
別人的工作該怎麼做;到期的內建項是助理自己被交付的工作,來源是要走 PR 審查
的委派清單。並且寫明:哪天那一欄出現會寫入的指令,要重新吵這一段,不是悄悄
把它放寬。

收尾回報多一個區塊,因為那是待辦簿自己的工作唯一被交代的地方,並要求把
「跳過那幾筆的歷史沒有被動過」講明。

三份 manifest 版號 0.2.2 升到 0.2.3。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 13:58:16 +08:00
jiantw83andClaude Opus 5 bccdbbbd24 feat(執行): 到期的內建檢查項真的跑一遍,成敗回寫待辦簿
待辦簿蓋好之後一直沒有人執行它。十六筆內建項、十五筆到期,而 last_run 與
fail_count 從建立到現在一次都沒動過——巡檢每輪把它們印出來,如此而已。

這一支只跑動作是一行指令、而且帶著 spec_key 的那幾筆。技能名那一種不跑:
叫用一整支技能會寫頁、開 PR、改檔案,而這一支跑在沒有人看的那一輪裡;唯讀
盤點指令失敗最多回一個非零碼,一支技能中途失敗可能留下寫到一半的頁。兩種
代價不同,就該分兩次判、分兩次接。使用者親手登錄的那幾筆也不跑,那幾筆沒有
經過種入那一支的檢核,動作欄想寫什麼都行。

代入點只展開得了 CLI 那一個。存取庫掃描還沒做出來,所以帶那個代入點的一律
印一行跳過,而且**執行紀錄與失敗次數一個字都不動**:代不出目標不是那一筆做
錯了什麼,記成失敗會讓一個沒有人修得動的計數一路往上爬,而那個計數存在的
理由正是指出「有一筆壞掉的項目每輪重試而沒人知道」。把「還沒接上」記成
「壞掉」,等於用假的壞掉把真的壞掉蓋掉。

執行前再驗一次指令形狀,不信任待辦檔的內容——那是純文字,種入之後可能被改。
擋掉金錢符號、反引號、波浪號、分號、管線與連接符號,路徑一定要落在這一輪的
根目錄底下,代完之後不得留大括號。

權限閘門看不到這一支裡面跑了什麼,檔頭把理由寫明了:閘門是可信入口的白名單、
不是沙箱,清單上每一支腳本本來就做得了它該做的事。防線改由「只跑經過審查的
清單種出來的項目」加「執行前再驗一次形狀」擋。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 13:58:16 +08:00
admin 2cccafd3a9 Merge pull request '釋出:排程條目不再寫死工作階段代號,CLI 判定跟上共用函式' (#25) from develop into master
Reviewed-on: #25
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-04 04:35:13 +00:00
admin cd83b1b62a Merge pull request '排程條目不再寫死工作階段代號,CLI 判定跟上共用函式' (#24) from fix/schedule-entry-drops-fixed-session-id into develop
Reviewed-on: #24
2026-09-04 04:31:40 +00:00
jiantw83andClaude Opus 5 c76e8489a6 fix(schedule): 排程條目不再寫死工作階段代號,CLI 判定跟上共用函式
兩個坑,都在同一支腳本,都讓無人值守那一輪看起來正常卻不正常。

一、條目寫死了工作階段代號。那一輪的兩半因此落在不同的值上:start 由 hook
寫,它從 hook 的標準輸入 JSON 讀得到 CLI 真正的代號;end 由工具腳本寫,沒有
那份 JSON,只能讀環境變數,於是讀到寫死的那個字串。配對的判準是工作階段
代號加技能名,兩半的代號不同就永遠配不起來。

這台機器上實測累積了 91 筆假的「只有 start 沒有 end」,其中 90 筆是同一支
每輪都會被叫用的技能。逐個工作階段數下來:92 個是一個 start 零個 end,另有
一個工作階段收著 29 個 end 卻一個 start 都沒有——那一個就是寫死的代號。

代價不只是數字難看。那一節存在的理由正是「只有 start 沒有 end 是一支技能
中止的唯一證據」,而這批假訊號只增不減,遲早把真的中止蓋掉。不設這個變數,
兩半就都落在 CLI 自己給的代號上,實測驗過確實配得起來。

二、CLI 判定抄了一份較窄的。共用函式認三個環境標記,這一份只認第一個,而
工具腳本被叫用時那一個不會設。於是每一次不帶 --cli 的安裝都回用法錯誤——
技能本文的啟動步驟叫的正是不帶 --cli 那一種,這台機器上一定裝不起來。同一個
判斷寫兩份就是這樣漂走的:共用函式後來補了兩個標記,這一份沒跟上,而漂移
的代價是一個看起來像「這台機器沒裝 CLI」的錯誤。

殘留的那 91 筆不必手動清,那一支本來就會把開超過一天的丟掉,一天內收斂。

三份 manifest 版號 0.2.1 升到 0.2.2。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 12:29:20 +08:00
admin e782bee616 Merge pull request '釋出:人在現場那一路的根目錄解析帶上文件記載的預設值' (#23) from develop into master
Reviewed-on: #23
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-04 03:56:49 +00:00
admin eade09bf62 Merge pull request '人在現場那一路的根目錄解析帶上文件記載的預設值' (#22) from fix/attended-root-resolve-carries-its-default into develop
Reviewed-on: #22
2026-09-04 03:54:45 +00:00
jiantw83andClaude Opus 5 85a0ce9e10 fix(assistant): 人在現場那一路的根目錄解析帶上文件記載的預設值
技能本文寫著那一行「涵蓋了文件記載的 ~/.jsc 退讓」,實際上沒有。JSC_HOME
沒設時 $JSC_HOME/current 展開成 /current,不是退讓到任何地方——殼並不知道
那個變數的文件預設值是什麼。解析式現在自己帶預設,退讓才真的發生。

這台機器從頭到尾沒設過那個變數,所以每一次人在現場叫用都停在第 0 步,而且
守衛開的藥方指向不相干的地方:它說根目錄不見了、叫人跑部署,但根目錄好好
的,壞的是解析式自己。排程那一路不受影響,條目自己帶著變數值。

目錄檢查留著,理由改寫進本文:解析式交出一條看起來合理卻不存在的路徑,
不是只有變數沒設一種成因——變數指到已經刪掉的目錄、精簡環境裡連家目錄都
沒設、連結農場根本還沒部署,三種都一樣過得了前三道關。

行為清單那一份早就寫對了,是技能本文漂走。這一次把兩份對齊,並把事故記述
改成過去式,免得下一輪有人照著它重寫回錯的形狀。

實測表第四列不動:那是量到的結果,而且新寫法一樣帶變數、無人值守一樣被擋,
另外加一段講明預設值改的是解析出哪條路徑,不是誰可以跑它。

三份 manifest 版號 0.2.0 升到 0.2.1。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 11:53:10 +08:00
admin bc1c097a75 Merge pull request '釋出:種入內建項時改讀委派清單的唯讀盤點指令欄' (#21) from develop into master
Reviewed-on: #21
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-04 03:37:48 +00:00
admin f1bc17ac97 Merge pull request '助理種入內建項時改讀委派清單的唯讀盤點指令欄' (#20) from feat/seed-reads-probe-column-for-readonly-commands into develop
Reviewed-on: #20
2026-09-04 03:26:43 +00:00
jiantw83andClaude Opus 5 28f453176e feat(seed): 種入內建項時改讀委派清單的唯讀盤點指令欄
委派清單補上第十二欄 probe 之後,這一支不再把所有非 invoke 的列一律推成
只提醒:填了指令的四列改成把那一行指令代好代入點寫進動作欄,寫著
pending 的七列照舊只提醒但另外印出來,讓「入口還沒接上」跟「本來就只提醒」
在回報上分得開。

三個判斷刻意寫死:

一、way 含 invoke 的列連看都不看 probe。填了指令會讓整支技能的交出變成
只跑一支腳本,那支技能該寫的頁一頁都不會寫,而且看起來完全正常。

二、probe 代不進去一律退回只提醒並照樣種入。不種入在 apply 那一路等於
移除,於是上游一格填錯就會刪掉一筆帶著 last_run 與 fail_count 的內建項。
金錢符號與波浪號擋在種入這一刻,那兩種寫法在無人值守那一輪解不出來、
也進不了允許清單,會被靜靜擋掉。

三、{cli} 與 {repo} 留在值裡不展開。種入的當下還不知道要代什麼,展開成
多筆會讓同一個 spec_key 有好幾個檔案,一致化整個垮掉。展開由執行那一步
負責,而動作欄裡出現大括號就是還沒代好,一律不得原樣拿去執行。

清單只有十一欄時整份先數一次欄位數,全部照舊推成只提醒、只印一行說明,
行為與加這一欄之前一模一樣。第十三欄以後另接一個收尾變數,免得上游哪天
加一欄就把多出來的值黏進 probe,代入點檢查全過得了關、最後執行的卻是
一行誰都沒寫過的指令。

相依下限刻意不動。清單那一欄晚一步到也照常跑得完,把下限拉到有那一欄的
版本等於逼兩個存放庫排合併順序,而排順序正是這一段程式碼要免掉的事。

三份 manifest 的版號從 0.1.9 升到 0.2.0。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 10:16:13 +08:00
admin 8803d7a499 Merge pull request '釋出內建檢查項的種入與重建至 master,版本 0.1.8 升到 0.1.9' (#19) from develop into master
Reviewed-on: #19
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-04 01:21:11 +00:00
admin 1f02c5843d Merge pull request '依委派清單種入與重建助理的內建定期檢查項,條件式交的三支一律不種入' (#18) from feat/seed-builtin-check-items-from-delegate-spec into develop
Reviewed-on: #18
2026-09-04 01:03:28 +00:00
jiantw83 a168c5904c feat(seed): 依委派清單種入與重建助理的內建定期檢查項
待辦簿做好了但是空的,也沒有東西會去填它。內建的定期檢查項該排哪些、什麼時候排、多久一次,這些資料就在委派清單裡——每一支非不交的技能都有時間點與週期兩欄。這一輪把清單接成待辦簿的資料來源。

反查靠新增的一個欄位,它非有不可。清單移除一支之後要刪掉對應那筆,但待辦簿的識別碼是建立時間加標題的雜湊,跟技能名無關。拿標題當鍵等於把措辭變成介面,改一個字舊那筆就再也認不出來,於是每次重建都刪不掉舊的又加一筆新的,同一個檢查每輪做兩次。拿動作當鍵,提醒類那十一筆全是同一個字、一支都分不出來,而觸發類那幾筆會撞上使用者自己交辦、動作剛好是同一支技能的那一筆——撞上就是把使用者交辦的事當成內建項刪掉。所以另立一欄記那一筆對應哪一支技能。

因為要加欄位,寫入端只能改存放那一支——它是唯一寫得出待辦檔的入口,這一輪沒有自己寫檔。連帶補上移除那個操作:規格要求不留孤兒,而原本六個操作一個都刪不掉。它對使用者交辦的那幾筆一律擋下、除非人親自帶強制旗標,而種入這一支一次都不帶。擋在單一寫入者這裡最省,那條規定寫在呼叫端的話,呼叫端每多一個就要各自再實作一次。

交出方式與動作是兩套詞彙,對映是這一輪的重點。含觸發就取技能名,其餘一律取提醒。觸發的定義就是呼叫既有技能、內容照那支技能自己的流程走,所以填技能名等於照判定結果做。巡檢與提醒那兩種沒有獨立入口——沒有任何腳本或技能名代表得了某一支技能的唯讀切片——這時候填技能名,助理下一輪就會把整支技能一路跑完,那正是切片交要防的事。所以填提醒:照時程提醒、指出入口,不動手。實測十六筆裡五筆是技能名、十一筆是提醒。

條件式交的三支一律不種入,但逐支吵出來。條件本身是散文,清單裡沒有機器讀得懂的條件欄位,所以條件成立了沒有現在只有人答得出來。種進去的代價有現成例子:其中一支的條件明寫要等它自家路徑不再帶版本號,而那個條件現在不成立,種進去助理每輪都會叫它、每輪停在第一支自家腳本,沒有錯誤、沒有輸出、心跳照寫,看起來完全正常。一個會無聲卡死的項目比一個缺掉的項目難查得多。不種入的代價是看不出為什麼少了它,用逐支印一行保留原因補掉。人確認過某一支條件成立就一支一支帶旗標放行,不給全部放行的旗標,那等於用一個決定蓋掉三個不同的條件。

種入與重建是同一段程式,啟動時每次都跑。不記跑過沒有,也沒有第一次旗標,要不要動手完全由現況決定。分成兩段的話,兩段各自回答該有哪幾筆這同一個問題,等其中一段改了判準就會一邊加一邊刪同一筆,每輪反覆。啟動時跑實際套用、查現況時跑唯讀預覽,巡檢那一輪兩個都不跑——無人值守那一輪移除一筆會把那一筆的執行紀錄與失敗次數一起弄丟,而清單同步到一半就會刪錯,破壞性清理留給人。

清單讀不到的三種情況一筆都不移除。讀不到時,清單上沒有與這台機器沒裝那個外掛分不出來,照字面跑會把所有內建項一次刪光,而且結束碼看起來完全成功。

清單上還在、還可交,只是時間點或週期換了值的那種情況,規格三條規則一條都沒講到。處置是預設只報差異不改:存放那一支刻意沒有編輯操作,改值只能移除再重登,那會換識別碼、把執行紀錄與失敗次數歸零,一個已經連續失敗五次的項目會看起來像全新的。人要換就帶旗標。

跨外掛相依宣告到清單所在的那個外掛,版本下限取現行的發行版——那是清單與它的欄位說明都已經在上面的版本。寫更低的下限會讓一台裝著舊版、清單還不存在或欄位不同的機器通過相依檢查,然後在讀清單那一步才失敗。清單路徑照今天剛改的規則走,由叫用時餵進來的根目錄組成,那一支自己不解。

三份 manifest 的版號一併從 0.1.8 升到 0.1.9,並在相依欄加上清單所在的那個外掛。這一次沒有把版號分成獨立一筆:相依宣告與版號是同一個決定的兩半,宣告了新相依卻不升版,安裝端不會知道要重新檢查相依。
2026-09-03 19:05:07 +08:00
admin e0c752543e Merge pull request '釋出助理待辦簿的地基至 master,版本 0.1.6 升到 0.1.8' (#17) from develop into master
Reviewed-on: #17
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-03 08:44:00 +00:00
admin e2d7454ee6 Merge pull request '助理待辦簿:存放格式、讀寫工具、事件偵測與到期判定' (#16) from feat/assistant-task-book-storage-and-tool into develop
Reviewed-on: #16
2026-09-03 08:42:48 +00:00
jiantw83 1d220bf03f chore(manifest): 三份 manifest 升版至 0.1.8
事件偵測與到期判定要靠版號才傳得到機器端。

三份 manifest 由 sync-skill-manifest.sh 同步,只動版本欄位。
2026-09-03 16:37:44 +08:00
jiantw83 737fcf13fd feat(due): 事件偵測與到期判定,七個事件名接上狀態來源
待辦簿存得住 trigger 與 recur,但沒有東西判「現在到期了沒有」。存放那一支的檔頭明寫它不判定、算的邏輯在別的地方,這一輪就是補那個別的地方。

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

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

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

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

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

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

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

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

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

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

順手修掉一個同類的坑:用冒號當空指令去清空檔案時,重導向失敗會讓整個殼直接結束,後面的分流一次都跑不到。這一支一律改用 true 並把理由寫進註解。
2026-09-03 16:37:44 +08:00
jiantw83 e7edfcbec0 chore(manifest): 三份 manifest 升版至 0.1.7
待辦簿工具要靠版號才傳得到機器端。

三份 manifest 由 sync-skill-manifest.sh 同步,只動版本欄位。
2026-09-03 15:46:09 +08:00
jiantw83 2ec4379924 feat(tasks): 助理待辦簿的存放格式與讀寫工具
助理要記住兩種項目——內建的定期檢查項與使用者當面交辦的事——但目前沒有地方放。待辦簿是助理待辦與建議下一個指令兩批功能的共同地基,先把存放格式與讀寫工具做出來,判定邏輯之後才接。

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

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

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

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

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

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

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

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

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

這一輪只做存放與讀寫。登錄時的補問流程、事件詞彙表接上產生者、到期判定、逾期與失敗處理、提醒送到前景、wiki 雙向同步,六項都不在這一輪,但欄位都已經留在檔案裡,接的時候不必改存放格式。目前還沒有任何操作呼叫得到這六個子命令,行為契約只記下這一支工具存在,不讓清單先跑到技能前面去。
2026-09-03 15:46:09 +08:00
admin 2e6b0b9b42 Merge pull request '釋出助理巡檢的路徑修正與先前累積的變更至 master,版本 0.1.2 升到 0.1.6' (#15) from develop into master
Reviewed-on: #15
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-03 03:17:06 +00:00
admin 56fe144c38 Merge pull request '助理巡檢改用字面絕對路徑,排程根目錄由 cron 條目帶入,避免無人值守輪次被權限層擋下' (#14) from fix/literal-absolute-paths-for-unattended-patrol into develop
Reviewed-on: #14
2026-09-03 02:52:00 +00:00
jiantw83 711eecac2f fix(assistant): 根目錄守門補上目錄存在檢查
人在現場那一條路解出根目錄之後,守門只看「非空、結束碼 0、是絕對路徑」三項,攔不住 JSC_HOME 沒設的情況。

實測:JSC_HOME 沒設時,readlink -f "$JSC_HOME/current" 印出 /current、結束碼 0。三項全部符合,直接通關,而 /current 並不存在。之後每一條由它組出來的字面路徑都指向不存在的地方,錯誤要到第一支腳本才浮出來,而且訊息看不出根因。

守門加上第四項:印出來的路徑必須是存在的目錄,用 [ -d ] 在同一個已核准的步驟裡查。檢查只掛在人在現場那一條,排程那一輪照舊一個指令都不跑——它的根目錄是安裝排程的人寫進條目的,錯了就由第一支腳本呼叫失敗來反映。

行為契約的關鍵步驟與完成條件兩列跟著改。
2026-09-03 10:31:05 +08:00
jiantw83 e4a3d3ae12 chore(manifest): 三份 manifest 升版至 0.1.6
三份 manifest 的版本從 0.1.5 升到 0.1.6,由 sync-skill-manifest.sh 同步。

助理技能的路徑守則與排程條目的內容都改過,安裝端要靠版號才認得出該更新,不升版的話舊條目會一直留在機器上。

版號與主變更分開成一筆,是因為這三個檔案只帶版號、不帶行為,混進主變更會讓那一筆的 diff 夾雜非行為變更;分開之後回溯哪一版對應哪一次變更也看得清楚。
2026-09-03 10:10:02 +08:00
jiantw83 fb8b9baedd fix(assistant): 巡檢改用字面絕對路徑,根目錄由排程條目帶進來
無人看管的排程輪次在第一支腳本就被權限層擋下。心跳因此寫不出來,助理斷了兩個多小時,沒有人發現。

2026-09-02 到 09-03 用非互動模式比照排程環境實測七種寫法,歸納出兩條判準。一、無人值守時只有允許清單上的完整字面指令跑得動,沒有「預設安全的唯讀指令」這回事,連 readlink 與 ls 都要有自己的規則。二、路徑中段的萬用字元不匹配,規則與指令都必須是完整字面,所以帶版本號的快取路徑放不進允許清單。「先解路徑再用」因此不成立:解路徑的指令自己就過不了,而路徑能寫成字面就不必解。

助理技能新增路徑守則與 Step 0。守則寫明權限層比對的是指令還沒展開的字面字串,帶未展開變數或波浪號的路徑一律要核准,並附上七列實測佐證表。Step 0 從「自己跑 readlink 解路徑」改成「從叫用文字的『工具根目錄=』取字面絕對路徑」,排程那一輪一個解析指令都不跑;人在現場叫用才用 readlink 解一次,那一次有人可以按同意。取不到根目錄就停下回報,收尾狀態取 aborted,不猜也不退回帶變數的路徑。全篇 46 處腳本呼叫改成字面絕對路徑。

排程工具在安裝時把解好的字面根目錄寫進條目的提示文字,並印成 patrol_root=。條目與允許規則共用同一個值,兩邊各算各的就會差開,而差開的那一輪是被靜靜擋掉。允許規則的提示改成完整字面路徑,不寫變數、波浪號與萬用字元。JSC_HOME 解不出絕對路徑時回結束碼 6,不讓相對路徑寫進條目。自訂巡檢指令沒帶那一段只警告、不中止。

行為契約四列與說明文件兩處敘述一併跟上。
2026-09-03 10:10:01 +08:00
admin 225478f756 Merge pull request '助理巡檢目錄頁改成大標題加條列,巡檢輸出檔改名 contents-entry.md' (#13) from feat/contents-list/main into develop
Reviewed-on: #13
2026-09-02 10:00:32 +00:00
jiantw83 8053c15425 chore(manifest): 三份 manifest 升版至 0.1.5
三份外掛清單的版號一起往上推一版。

目錄頁的版面與巡檢輸出檔名都變了,呼叫端要靠版號才判得出手上這一份是新的
還是舊的。版號不動,版本閘門就不會提示更新,機器上會留著舊版工具去讀新版
範本。

三份清單各自被不同的 CLI 讀,值必須一致,所以一起改、一起提交。

範圍是外掛清單的版號宣告。
2026-09-02 17:21:23 +08:00
jiantw83 d8aa0b1f5d feat(patrol): 巡檢改組目錄頁區塊檔,輸出檔改名 contents-entry.md
一輪巡檢組給目錄頁的輸出,從一列 markdown 表格改成一整個大標題區塊:
`## {監控頁頁名}` 那一行、空行,然後每個欄位一條 `- {欄位名}:{值}`。輸出
檔跟著從 `contents.tsv` 改名 `contents-entry.md`,`contents_file=` 指向
新檔名。

目錄頁已經不放表格,再組出那一列就沒有地方放。舊檔名說的是逐欄對照的資料
檔,內容其實是一段 markdown,名不對實會讓呼叫端以為還能逐欄解析。改名讓
呼叫端契約的變動在檔名上就看得見,而不是同名檔悄悄換了格式——同名換格式
的話,還沒跟上的呼叫端會拿到讀得開卻意義全錯的內容。

新增 `oneline` 處理條列一條的值:換行一律壓成空白,因為一條條列裡的換行會
被讀成另一條,或者讓整個區塊提早結束;`|` 反而不跳脫,條列裡沒有切欄的
意思,跳脫過的符號會原樣顯示在頁面上。監控頁那一條的網址仍然留佔位,由
呼叫端換成真網址、驗過連得到才寫,這支腳本一頁都不寫。裸雜湊照樣留一條,
讓人不必從標題切字串就抄得到。

範圍是一輪巡檢給目錄頁的輸出檔。
2026-09-02 17:21:23 +08:00
jiantw83 311cdc611a feat(wiki): 巡檢目錄頁改成一台機器一個大標題區塊
巡檢目錄頁的版面從 markdown 表格換成「大標題加條列」:一台機器一個大標題
區塊,標題就是那一台機器監控頁的實際頁名,欄位改成標題底下的一層條列。
範本、技能敘述、行為清單與說明文件一併跟上,目錄頁上不再留任何表格。

表格的欄位組合是整頁共用的,表頭跟著建頁那一台機器走,之後每一台只改自己
那一列。欄位一增減,只有跑到新版的機器寫得出新的格數,同一張表就混著兩種
格數,多出來的那一格對不到任何欄名,而目錄頁又沒有整頁改寫的路可以走——
整頁覆蓋等於刪掉別台機器的紀錄。條列一筆一個區塊,欄位各自獨立,加一條只
動到自己那一個區塊。

比對鍵從裸雜湊那一格改成大標題本身,標題寫成監控頁的實際頁名。頁名只由
主機名與登入帳號決定,換主機位址、換專用存取庫或換一種頁名編碼都動不到
它;含網址的那一條連結照樣留著給人點,但不當鍵。呼叫改成拿頁名當鍵,欄號
那個參數只在舊表格頁轉檔時用得到。範本原本用二階標題寫的說明區段全部搬進
引言,否則轉檔後會被當成一筆真紀錄讀進去。

範圍是助理的巡檢目錄頁與 assistant 技能的敘述。
2026-09-02 17:21:12 +08:00
admin 6fd987fc0e Merge pull request '收尾寫一筆 skill-end 事件,執行狀態才回報得到助理' (#12) from feat/status-report into develop
Reviewed-on: #12
2026-09-02 08:04:03 +00:00
jiantw83 ed624e0743 chore(plugin 版本): 三份 manifest 升版至 0.1.4 2026-09-02 16:01:13 +08:00
jiantw83 3dac1475df feat(狀態回報): 收尾寫一筆 skill-end 事件
現行紀錄只記「被叫用」,沒有成敗也沒有結束碼。跑完整輪的技能與開場就
中止的技能,在紀錄裡長得一模一樣。

start 由技能用量 hook 順手發,不必改技能文件。end 只能由技能自己在收尾
步驟寫——hook 接在技能工具呼叫上,而實際工作發生在之後的模型輪次,它在
原理上看不到成敗。有 start 沒有配對的 end,就是那一輪中止了。

status 五選一,每支技能各自寫明什麼情況選哪一個。找不到回報腳本就安靜
跳過,回報失敗一律不改變技能自己的結論。
2026-09-02 16:01:13 +08:00
admin 94566026c7 Merge pull request '連結一律寫成 [文字](絕對網址),並在寫入前驗證連得到' (#11) from feat/link-verification/main into develop
Reviewed-on: #11
2026-09-02 06:46:35 +00:00
jiantw83 f2d30925f6 chore(plugin 版本): 三份 manifest 升版至 0.1.3 2026-09-02 14:27:18 +08:00
jiantw83 9ea83da38b feat(link): 連結一律寫成 [文字](絕對網址),寫入前先驗證連得到
取消 [[頁名]] 與 [[顯示文字|頁名]] 兩種同 wiki 寫法,不再分「同存取庫」與
「跨存取庫」兩條規則。那種寫法只在自己那個 wiki 內解析,寫錯不報錯,畫面上
看起來像普通文字或死連結,巡不到也修不了。

連結寫進頁面前先過 jsc-gitea 的 link-check.sh,結束碼 0 才寫。驗證一律走 API,
不看網頁狀態碼:私有存取庫的網頁網址對未登入請求一律回 404,拿狀態碼判會把
好連結判成壞的。認證失敗回 7,與死連結的 1 分開,免得金鑰一過期就把還在的頁
整批判死。
2026-09-02 14:27:18 +08:00
admin c36460dd59 Merge pull request 'release: wiki 目錄頁專用存取庫、HASH 完整 40 碼、閘門依 CLI 分流' (#10) from develop into master
Reviewed-on: #10
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-02 04:20:48 +00:00
admin 4e87b1e662 Merge pull request 'feat(wiki): 監控目錄頁改走專用存取庫,比對鍵改用裸 HASH' (#9) from feat/wiki-contents-repo/main into develop
Reviewed-on: #9
2026-09-02 03:27:49 +00:00
jiantw83 4bf99dde76 feat(wiki): 監控目錄頁改走專用存取庫,比對鍵改用裸 HASH
What:MONITOR_CONTENTS 改由 wiki-repo CONTENTS 解析並透過 wiki-contents.sh
upsert 寫入,MONITOR_{HASH} 仍走 wiki-repo MONITOR。目錄頁新增一欄裸 HASH 當
比對鍵,第一欄的絕對網址連結留給人看。主機名一律取短名。

Why:目錄頁集中之後兩頁不再同庫,[[...]] 只在同一個 wiki 內解析,連結必須改絕對
網址。比對鍵原本是含網址的儲存格,換主機、換存取庫或 URL 編碼有差就比對不到,
巡檢每 15 分鐘寫一次,重複列會累積得很快。

How:目錄頁解不出存取庫時不再中止巡檢——那一頁只是索引,內容頁寫成就照樣寫心跳。
內容頁寫不成仍然中止且不寫心跳,自咬環的前提沒有鬆動。

Who:jsc-assist
2026-09-02 11:01:51 +08:00
admin de3775f970 Merge pull request '釋出 jsc-assist 0.1.1:排程輪次自帶環境與權限,監控頁改成固定三塊' (#8) from develop into master
Reviewed-on: #8
Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
2026-09-02 01:29:25 +00:00