Files
assist/templates/monitor-page.md
T
jiantw83 2b7176a644 feat(patrol): 一輪巡檢落地,心跳改由巡檢跑完才寫
What:
- 新增 tools/patrol.sh,三個子命令:collect 收集、finish 收尾、abort 中止。這一輪的巡檢項目是四項純讀取:使用統計、版本落差與重啟閘門、階段鎖與工作包鎖、心跳自述。
- 心跳的寫入從排程移到巡檢收尾。排程只呼叫巡檢,不再直接寫心跳。
- 排程週期由心跳門檻推導,不再寫死。install heartbeat 這個工作代號改為拒絕。

Why:
- 排程直接寫心跳的話,心跳新鮮只證明排程活著。巡檢整個壞掉、每輪都失敗,心跳照樣新鮮,閘門照樣放行,而且沒有任何錯誤訊息——這是無聲失效,是最難發現的一種。
- 改成巡檢寫,心跳新鮮才等於上一輪真的跑完了。閘門判的才是工作訊號,不是行程存活訊號。
- 門檻是讀取端的設定,心跳檔裡不存它。所以週期與門檻各寫死一個數字一定會撞:門檻五分鐘、巡檢十五分鐘,心跳永遠是過期的。

How:
- 週期取「滿足漏掉一輪還算新鮮、漏掉兩輪才過期」的最大值,並且要能整除一小時。要拉長巡檢週期就調大門檻,週期自動跟著長,兩個數字不會各走各的。
- 心跳只看「這一輪有沒有把結果記下來」,不看四項的成敗。四項有失敗但監控頁寫成了就寫心跳,頁上判定標警示;頁寫不成就中止,一定不寫,讓心跳自己過期。頁每輪都寫失敗卻照樣寫心跳,等於把這次要修掉的缺陷原封不動搬過去。
- 整輪拿一把目錄鎖,搶不到就讓開,不排隊也不並行。並行兩輪會在同一頁附兩節,還會互相蓋掉用量快照。鎖逾時可被下一輪搶走,被搶走的那一輪收尾時對不上就不寫心跳——它沒跑到底,不該蓋章。
- 任一項失敗不影響其餘項目。失敗要在監控頁上看得出來是失敗,不是沒資料;來源是空的則明寫「那是零次,不是故障」。
- 版本盤點照抄腳本原字。抄到查詢失敗就寫查詢失敗,不改寫成相符、也不自己補查遠端版本——查不到是沒有證據,不是版本沒問題。

Who:
助理落地的第四塊。排程那一輪留下的問題在這裡解掉了。
2026-09-01 15:06:10 +08:00

5.5 KiB
Raw Blame History

助理巡檢 — {主機名}/{登入帳號}

由 jsc-assist 維護。這是監控頁 MONITOR_{HASH}。 這頁是這台機器的巡檢軌跡:一次巡檢附加一節,節標題帶時間戳,舊的節一個字都不動。 附加是刻意的。助理的寫入是背景行為,覆寫錯了沒人在現場,軌跡被抹掉也看不出斷在哪一輪。 目錄頁 MONITOR_CONTENTS 只更新自己那一列,寫入語意與這頁不同,不要混用。

flowchart LR
  A[巡檢一輪] --> B[收攏各類結果]
  B --> C[附加一節,節標題帶時間戳]
  C --> D[既有的節原樣保留]
  D --> E[回頭更新 MONITOR_CONTENTS 自己那一列]
  E --> F[最後才寫心跳]

心跳排在最後一步,不能提前。心跳新鮮的意思就是「上一輪跑到這一步了」:這一節沒寫上來,心跳就不寫,讓它自己過期。那是巡檢在空轉的唯一訊號。

本頁基本資料

建頁時寫一次,之後不再更動。

項目 內容
主機 {主機名}
帳號 {登入帳號}
雜湊來源 {主機名}/{登入帳號}
狀態檔根目錄 $JSC_HOME/assistant/($JSC_HOME 未設定就退回 ~/.jsc)

巡檢 {yyyy-MM-dd HH:mm}

一輪巡檢就是這樣一節,最新的一節放在最下面。六個子節固定都寫;某個來源讀不到,就在那個子節寫明是哪個路徑讀不到,不要整節略過。還沒實作的子節也照寫,寫明「這一輪不做這一項」——空表格會被讀成「查過了,沒問題」。

項目 內容
巡檢時間 {yyyy-MM-dd HH:mm}
觸發方式 {排程、事件、手動 三選一}
本輪判定 {正常、警示、異常 三選一}
本輪項目 {這一輪跑了哪幾項,成功幾項、失敗幾項}
讀不到的來源 {路徑清單,全部讀得到就寫「無」}

心跳與閘門狀態

項目 內容
心跳 {新鮮、過期、不存在 三選一}
上次心跳 {yyyy-MM-dd HH:mm},距這次巡檢 {n} 秒
cli {claude、codex、copilot、antigravity、kiro 五選一}
session {工作階段代號}
pid {數字}。只給要找行程的人參考,不參與判定

這一欄讀到的是上一輪巡檢寫的心跳:心跳由巡檢寫,本輪那一次要等這一節寫上來之後才寫。

心跳的判準只看 ts 距現在有沒有超過門檻,預設 300 秒。不看 pid 存活:五支 CLI 與容器裡的行程互相看不到彼此的 pid。閘門的判定留在 hook,助理只維持心跳。心跳新鮮代表上一輪巡檢跑完了,不代表那一輪四項都成功——那要看本節上面的「本輪判定」。

技能與呼叫鏈使用統計

資料出自 $JSC_HOME/usage/skills.jsonl 與 $JSC_HOME/usage/chains.jsonl,由 jsc-log:stats 聚合。

對象 類別 本輪次數 累計次數
{技能名或呼叫鏈} {技能、呼叫鏈 二選一} {n} {n}

hook 執行期錯誤

資料出自 jsc-hooks 的 tools/scan-hook-errors.sh 與 tools/scan-logs.sh。助理只記錄與發動 jsc-hooks:repair,不自己改 hook。

發生時間 hook CLI 結束碼 錯誤摘要 已寫 ERROR 頁
{yyyy-MM-dd HH:mm} {腳本檔名} {CLI 代號} {n} {一句摘要} {ERROR_{HASH} 連結或「否」}

版本落差與重啟閘門

資料出自 version-guard.sh report 與 restart-gate.sh report。

domain 本機版本 應有版本 判定
{domain} {版本字串} {版本字串} {相符、落後、查不到 三選一}
CLI 重啟閘門 升起時間
{CLI 代號} {已升起、未升起 二選一} {yyyy-MM-dd HH:mm 或「-」}

SDLC 階段鎖與工作包鎖現況

資料出自 $JSC_HOME/sessions/{sid}.stage 與 $JSC_HOME/wp/*.pr。只讀狀態,不做判定。

工作階段 階段 存取庫 登記時間
{工作階段代號} {plan、analyze、implement、maintain 四選一} {owner}/{repo} {yyyy-MM-dd HH:mm}
存取庫 工作包 PR 歸屬工作階段
{owner}/{repo} {WP-nn} {PR 連結} {工作階段代號}

待辦簿到期與逾期

資料出自 $JSC_HOME/assistant/tasks/ 底下的每一個檔案,一筆一列。

id 標題 狀態 下次執行 到期 連續失敗 標記
{id} {title} {pending、done、paused 三選一} {next_run} {due 或「-」} {fail_count} {已連續失敗 N 次,或「-」}

fail_count 大於 0 的列,標記欄一律寫「已連續失敗 N 次」,N 照檔案原值抄。待辦簿的項目失敗不會自動暫停,會每輪重試;沒標出來,一個壞掉的項目會一直重試而沒人知道。

待人處理

助理只提醒,不代為執行。這一節列的是本輪要人接手的項目。

項目 來源子節 建議入口
{一句話講完要處理什麼} {上面六個子節之一} {技能名或指令}

寫入規則

  • 一次巡檢附加一節,節標題帶時間戳,節名不重複。
  • 既有的節原樣保留,一個字都不改。
  • 禁止整頁覆寫。覆寫等於把這台機器的巡檢軌跡刪掉。
  • 讀不到舊內容就中止,不附加,也不寫入。
  • 附加成功之後,才回頭更新 MONITOR_CONTENTS 自己那一列。
  • 兩頁都寫成之後,才寫這一輪的心跳。任一頁沒寫成就不寫心跳,讓它過期。