feat(巡檢): 監控頁三塊的接法收進腳本,新增 rebuild 子命令

接三塊這件事本來留給呼叫端,而呼叫端是一個代理人,於是它每一輪臨場挑工具。
實測某一輪挑了 awk,兩次都被權限擋掉;那一輪有人在場所以它改用別的方式繞過
去了,並且自己在報告裡指出,無人值守那一輪遇到同一個擋法會直接卡住——而鎖
在第一步就取走了,接下來每一輪都會讓開到鎖逾時。

更根本的證據在暫存目錄:實測累積了 124 個檔案,名字是 newpage.md、new-page.md、
new_page.md、page-new.md、monitor-new.md 這種。同一件事每輪重做一次,每輪換一
組檔名。規格說那裡只該有五個檔案。

接法只有一種對的形狀,那就不該放在提示裡。收進腳本之後那一步不再需要任何
通用文字工具,也就沒有東西可以被擋。

基本資料那一塊逐字照抄,連尾端空行都不動。第一版剝掉尾端空行再補一個,內容
沒少但技能本文寫的是「逐字保留」,那句話就變成假的了——實測比對出差一個空行
之後改成只在它沒有以空行收尾時才補分隔。

舊格式頁由腳本自己認:沒有「最新一輪」那個標題就留基本資料、丟掉堆疊的各輪
小節、摘要表從本輪開始,並印 old_format=yes converted=1,不讓呼叫端自己判。

實測:拿這台機器真的監控頁跑,三個區塊、摘要 24 列、舊列留 23、基本資料逐字
相同;舊格式頁轉成三區塊且摘要從本輪開始;把結果再當舊頁餵一次冪等;沒帶
--old、舊頁檔不存在、缺同輪產出的區塊三種都回 6。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 17:42:54 +08:00
co-authored by Claude Opus 5
parent cc5faaff21
commit ebce7fc0c3
+54 -1
View File
@@ -237,6 +237,7 @@ usage() {
usage: patrol.sh collect [--out 目錄] [--trigger 排程|事件|手動] usage: patrol.sh collect [--out 目錄] [--trigger 排程|事件|手動]
patrol.sh finish --round 輪次代號 [--out 目錄] [--dry-run] patrol.sh finish --round 輪次代號 [--out 目錄] [--dry-run]
patrol.sh abort --round 輪次代號 [--out 目錄] patrol.sh abort --round 輪次代號 [--out 目錄]
patrol.sh rebuild --old 舊頁檔 [--out 目錄]
EOF EOF
exit 6 exit 6
} }
@@ -1078,7 +1079,7 @@ compose() {
CMD="${1:-}" CMD="${1:-}"
[ -n "$CMD" ] || usage [ -n "$CMD" ] || usage
shift shift
case "$CMD" in collect|finish|abort) ;; *) usage ;; esac case "$CMD" in collect|finish|abort|rebuild) ;; *) usage ;; esac
OUT='' OUT=''
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
@@ -1087,9 +1088,11 @@ while [ "$#" -gt 0 ]; do
--trigger) [ "$#" -ge 2 ] || usage; TRIGGER="$2"; shift 2 ;; --trigger) [ "$#" -ge 2 ] || usage; TRIGGER="$2"; shift 2 ;;
--round) [ "$#" -ge 2 ] || usage; ROUND="$2"; shift 2 ;; --round) [ "$#" -ge 2 ] || usage; ROUND="$2"; shift 2 ;;
--dry-run) DRYRUN=1; shift ;; --dry-run) DRYRUN=1; shift ;;
--old) [ "$#" -ge 2 ] || usage; OLD_PAGE="$2"; shift 2 ;;
*) usage ;; *) usage ;;
esac esac
done done
OLD_PAGE="${OLD_PAGE:-}"
[ -n "$OUT" ] && RD="$OUT" [ -n "$OUT" ] && RD="$OUT"
case "$CMD" in case "$CMD" in
@@ -1204,4 +1207,54 @@ case "$CMD" in
printf 'heartbeat=not-written\n' printf 'heartbeat=not-written\n'
lock_release lock_release
exit 0 ;; exit 0 ;;
# 拿舊頁重組出要寫回去的整頁。三塊的接法固定,所以由這一支做完,呼叫端只要「讀回舊頁、
# 叫這一支、把結果寫回去」三步。
#
# 為什麼要有這個子命令:接三塊這件事本來留給呼叫端,而呼叫端是一個代理人,於是它每一輪
# 臨場挑工具——實測某一輪挑了 awk,兩次都被權限擋掉;那一輪有人在場所以它改用別的方式繞
# 過去了,並且自己指出無人值守那一輪遇到同一個擋法會直接卡住,而鎖在第一步就取走了。
# 更根本的是暫存目錄實測累積了 124 個檔案,名字是 newpage.md、new-page.md、new_page.md、
# page-new.md 這種——同一件事每輪重做一次,每輪換一組檔名。規格說那裡只該有五個檔案。
# 接法寫死在這裡之後,那一步不再需要任何通用文字工具,也就沒有東西可以被擋。
rebuild)
[ -n "$OLD_PAGE" ] || usage
[ -f "$OLD_PAGE" ] || die 6 "舊頁檔讀不到:$OLD_PAGE。這一支不自己讀 wiki,舊頁要由呼叫端先取下來。"
for _f in "$RD/latest.md" "$RD/summary.md"; do
[ -f "$_f" ] || die 6 "$_f 不在。rebuild 要接的是同一輪 collect 產出的那幾塊,先跑 collect。"
done
_out="$RD/rebuilt.md"
# 舊頁那一塊「本頁基本資料」原樣留著,從它的標題到「最新一輪」前一行為止。整頁沒有
# 「最新一輪」那個標題時視為舊格式:基本資料留著、堆疊的各輪小節丟掉,摘要表從本輪開始。
if grep -q '^## 最新一輪' "$OLD_PAGE" 2>/dev/null; then
awk '/^## 最新一輪/{exit} {print}' "$OLD_PAGE" >"$RD/rb-head.md" 2>/dev/null || die 5 "暫存檔寫不進去:$RD/rb-head.md。"
printf 'old_format=no\n'
else
awk '/^## /{n++} n<=1{print}' "$OLD_PAGE" >"$RD/rb-head.md" 2>/dev/null || die 5 "暫存檔寫不進去:$RD/rb-head.md。"
printf 'old_format=yes converted=1\n'
fi
# 舊表的資料列照原順序留在本輪那一列底下,整張表截到 24 列。摘要那一塊已經含標題、
# 表頭與本輪那一列,所以這裡只補舊列。
awk '/^## 近 24 輪摘要/{f=1;next} f && /^\| 2/{print}' "$OLD_PAGE" >"$RD/rb-rows.md" 2>/dev/null || die 5 "暫存檔寫不進去:$RD/rb-rows.md。"
_new_rows=$(awk '/^\| 2/{n++} END{print n+0}' "$RD/summary.md")
_keep=$((24 - _new_rows))
[ "$_keep" -lt 0 ] && _keep=0
# 基本資料那一塊逐字照抄,連尾端空行都不動——技能本文寫的是「逐字保留」,剝掉再補一個
# 雖然內容沒少,那句話就變成假的了。只在它沒有以空行收尾時補一個分隔,免得下一塊的
# 標題黏在表格最後一列後面。
_tail=$(awk 'END{print (NF==0 ? "blank" : "text")}' "$RD/rb-head.md" 2>/dev/null)
{
cat "$RD/rb-head.md"
[ "$_tail" = "blank" ] || printf '\n'
cat "$RD/latest.md"
printf '\n'
cat "$RD/summary.md"
[ "$_keep" -gt 0 ] && head -n "$_keep" "$RD/rb-rows.md"
} >"$_out" 2>/dev/null || die 5 "暫存檔寫不進去:$_out。"
printf 'rebuilt_file=%s\n' "$_out"
printf 'blocks=%s summary_rows=%s old_rows_kept=%s\n' \
"$(grep -c '^## ' "$_out")" \
"$(awk '/^## 近 24 輪摘要/{f=1;next} f && /^\| 2/{n++} END{print n+0}' "$_out")" \
"$([ "$_keep" -gt 0 ] && awk 'END{print NR+0}' "$RD/rb-rows.md" | awk -v k="$_keep" '{print ($1<k?$1:k)}' || echo 0)"
exit 0 ;;
esac esac