feat(assistant): 逾期判定接上來,逾期與連續失敗每一輪都提
逾期本來沒實作,監控頁上就寫著「上面的判定只講到期,不講逾期」。 到期與逾期分兩欄,不合成一個判定:到期是「該跑了」,逾期是「due 欄那個 截止時間過了」。一筆七天一次的檢查項天天都可能到期,卻永遠不會逾期; 一筆有截止時間的交辦可能早就逾期,卻因為排定點還沒到而判成還沒到。 合成一個值就把兩種情況混成同一格。 due.sh 多第十二欄 overdue,值是減號(沒有截止時間)、no、逾期的秒數, 或 bad。bad 算成欄位不合法回 2——一個解不開的截止時間跟沒有截止時間 在畫面上長得一模一樣,而前者是登錄的時候就填錯了。done 那幾筆不算逾期; 被暫停的那幾筆照算,因為暫停中止的是到期判定,不是日曆,而一筆被暫停 又逾期的交辦正好是最容易被忘掉的那一種。 另加唯讀子命令 due.sh overdue 給狀態查詢那一路走。走 scan 會推進快照, 那一輪之後的事件判定會全部落空;走 events 又判不到逾期;讓呼叫端自己 拿 due 欄去比更糟,那是第二套判定,漂移的那一天兩邊都說自己對。 patrol.sh 在逾期或連續失敗筆數大於 0 時各列一筆待人處理,每一輪都列。 兩種都不會自己好:截止時間過了不會因為過更久就不逾期,連續失敗的項目 每一輪都會再試一次然後再失敗一次。「提過了」不是「處理過了」,而助理 不替人按暫停,那個狀態留給人設。 監控頁那一節逐筆點名連續失敗的那幾筆——id、失敗幾次、最後一次執行、 標題。原本只印一個總數,而失敗次數這個欄位存在的理由是指出「有一筆壞掉 的項目每輪重試而沒人知道」,不說出是哪一筆,那個理由只完成一半。 目錄頁刻意不加欄位。那一頁一台機器一個區塊、各自那一輪寫,新加一條只有 跑到新版的機器寫得出來,讀的人分不出「這台沒有逾期」與「這台還沒寫這 一條」——理由與當初把「本輪非 ok 事件數」擋在那一頁外面的一樣。 欄位數從 11 變 12,run-due.sh 那道欄位數檢核跟著改成 12。那道檢核擋的 不是第 12 欄本身,是「兩支不是同一版」——版本不同的時候,前 11 欄的 順序也不能假設還是原來那樣。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+162
-23
@@ -8,8 +8,9 @@
|
||||
# [--created {ISO 時間}] [--last-run {ISO 時間}] [--fail-count {數字}]
|
||||
# [--now {epoch 秒}]
|
||||
#
|
||||
# scan 一輪一次:比對狀態快照算出本輪新事件、推進快照與事件計數,再逐筆判到期。
|
||||
# events 唯讀預覽:只比對、只印,一律不推進快照,也不判到期。
|
||||
# scan 一輪一次:比對狀態快照算出本輪新事件、推進快照與事件計數,再逐筆判到期與逾期。
|
||||
# events 唯讀預覽:只比對、只印,一律不推進快照,也不判到期。
|
||||
# overdue 只判逾期,唯讀:一份快照都不推進,一個事件都不比。狀態查詢那一路走這一個。
|
||||
# next 純算:給一組欄位算出 next_run,不讀待辦簿、不碰快照、不發事件。
|
||||
#
|
||||
# 結束碼:
|
||||
@@ -17,7 +18,8 @@
|
||||
# 1 至少一個狀態來源存在卻讀不到。**結果照樣印得出來**,只是那一個來源本輪不判事件、
|
||||
# 快照那一段原樣留著,呼叫端要把它標成警示
|
||||
# 2 欄位值不合法或算不出來:trigger 或 recur 解不開、時間字串解不出 epoch、間隔寫錯、
|
||||
# --now 不是非負整數。scan 遇到這種待辦只把那一筆標成判不了,其餘各筆照判
|
||||
# due 欄的截止時間解不開、--now 不是非負整數。scan 遇到這種待辦只把那一筆標成判不了,
|
||||
# 其餘各筆照判
|
||||
# 3 快照或事件計數換不上去。算是算出來了,但下一輪會拿同一份舊快照再比一次,於是同一批
|
||||
# 事件會被判第二次。這一碼要吵出來,不能當成成功
|
||||
# 4 待辦簿目錄不存在或零筆,這一輪沒有任何一筆可判。不是失敗,但呼叫端要知道「沒判過」
|
||||
@@ -139,8 +141,13 @@
|
||||
#
|
||||
# --- 這一支不判什麼 ---
|
||||
#
|
||||
# 不判逾期(due 欄有沒有過),不執行任何一筆待辦,不改任何一筆的 state,不送提醒到前景,不碰 wiki。
|
||||
# 它只回答兩個問題:本輪有哪些新事件、哪幾筆現在到期。做不做、怎麼做、失敗怎麼記,都在呼叫端。
|
||||
# 不執行任何一筆待辦,不改任何一筆的 state,不送提醒到前景,不碰 wiki。
|
||||
# 它只回答三個問題:本輪有哪些新事件、哪幾筆現在到期、哪幾筆逾期了。做不做、怎麼做、失敗怎麼記,
|
||||
# 都在呼叫端。
|
||||
#
|
||||
# 到期與逾期分兩欄,不合成一個判定:到期是「該跑了」,逾期是「due 欄那個截止時間過了」。
|
||||
# 一筆七天一次的檢查項天天都可能到期,卻永遠不會逾期(它沒有截止時間);一筆有截止時間的交辦
|
||||
# 可能早就逾期,卻因為排定點還沒到而判成「還沒到」。合成一個值就會把這兩種情況混成同一格。
|
||||
#
|
||||
# 環境變數:
|
||||
# JSC_HOME 助理狀態檔的根目錄,預設 ~/.jsc。要是連 HOME 也沒有就回 6,不猜
|
||||
@@ -195,8 +202,9 @@ note() { printf '[jsc][助理到期判定]:%s\n' "$1" >&2; }
|
||||
|
||||
usage() {
|
||||
cat >&2 <<'EOF'
|
||||
usage: due.sh scan [--out 目錄] [--now epoch 秒] [--dry-run]
|
||||
due.sh events [--now epoch 秒]
|
||||
usage: due.sh scan [--out 目錄] [--now epoch 秒] [--dry-run]
|
||||
due.sh events [--now epoch 秒]
|
||||
due.sh overdue [--now epoch 秒]
|
||||
due.sh next --trigger at:...|after:... --recur once|every:間隔
|
||||
[--created ISO 時間] [--last-run ISO 時間] [--fail-count 數字]
|
||||
[--now epoch 秒]
|
||||
@@ -869,15 +877,51 @@ kv_get() { # $1=檔案 $2=鍵
|
||||
# 不寫成 key=value:cron 式子與標題裡有空白,key=value 的那一行沒辦法只靠空白切回來,切錯就是
|
||||
# recur 只剩「cron:0」那半截,而那半截看起來還很像一個完整的值。值一律折過,裡面不會有定位
|
||||
# 字元也不會有換行,所以定位字元切得準。
|
||||
row_out() { # 十一個欄位,順序如上
|
||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
||||
row_out() { # 十二個欄位,順序如上
|
||||
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' \
|
||||
"$(flat "$1")" "$(flat "$2")" "$(flat "$3")" "$(flat "$4")" "$(flat "$5")" \
|
||||
"$(flat "$6")" "$(flat "$7")" "$(flat "$8")" "$(flat "$9")" \
|
||||
"$(flat "${10}")" "$(flat "${11}")" >>"$ROWS"
|
||||
"$(flat "${10}")" "$(flat "${11}")" "$(flat "${12}")" >>"$ROWS"
|
||||
}
|
||||
|
||||
# 逾期判定。到期與逾期是兩件事:到期是「該跑了」,逾期是「截止時間過了」。
|
||||
# 一筆七天一次的檢查項天天都可能到期,卻永遠不會逾期(它沒有截止時間);一筆有截止時間的
|
||||
# 交辦事項可能早就逾期,卻因為排定點還沒到而判成「還沒到」。兩個判定各自獨立,一欄一個值。
|
||||
#
|
||||
# 回傳三種值:due 欄是空的印減號、還沒過印 no、過了印逾期的秒數。
|
||||
# 印秒數不印 yes 的理由是「逾期一分鐘」與「逾期三個月」在報告上要看得出差別,而呼叫端
|
||||
# 只要判「是不是數字」就分得出有沒有逾期。
|
||||
# due 欄解不開的一律印 bad 並算成欄位不合法:一個解不開的截止時間跟沒有截止時間,
|
||||
# 在畫面上長得一模一樣,而前者是登錄時就填錯了。
|
||||
# 逾期多久,給人看的寫法。機器可讀的那幾處一律留秒數:秒數比得出大小、也不必解析。
|
||||
# 頁面上只印秒數讀不出輕重——「528462 秒」要算過才知道是六天,而報告的用途正是讓人一眼
|
||||
# 分出「逾期一分鐘」與「逾期三個月」。
|
||||
dur_human() { # $1=秒數
|
||||
_ds=$(( $1 / 86400 )); _hs=$(( ($1 % 86400) / 3600 )); _ms=$(( ($1 % 3600) / 60 ))
|
||||
if [ "$_ds" -gt 0 ]; then printf '%s 天 %s 小時' "$_ds" "$_hs"
|
||||
elif [ "$_hs" -gt 0 ]; then printf '%s 小時 %s 分' "$_hs" "$_ms"
|
||||
else printf '%s 分' "$_ms"; fi
|
||||
}
|
||||
|
||||
overdue_of() { # $1=due 欄的值;回傳值印在 stdout
|
||||
case "$1" in
|
||||
''|'-') printf '%s' '-'; return 0 ;;
|
||||
esac
|
||||
_de=$(iso_to_epoch "$1") || _de=''
|
||||
case "${_de:-}" in
|
||||
''|*[!0-9]*) printf '%s' 'bad'; return 1 ;;
|
||||
esac
|
||||
if [ "$NOW" -gt "$_de" ]; then
|
||||
printf '%s' "$((NOW - _de))"
|
||||
else
|
||||
printf '%s' 'no'
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
scan_tasks() {
|
||||
T_TOTAL=0; T_DUE=0; T_WAIT=0; T_INVALID=0; T_UNWIRED=0; T_SKIP=0
|
||||
T_OVERDUE=0; T_DUEBAD=0; OVERDUE_LINES=''
|
||||
true >"$ROWS" 2>/dev/null || { RC_FS=5; die 5 "逐筆判定的輸出檔寫不進去:$ROWS。"; }
|
||||
if [ ! -d "$TASKS_DIR" ]; then
|
||||
RC_EMPTY=4
|
||||
@@ -898,11 +942,28 @@ scan_tasks() {
|
||||
_cr=$(kv_get "$_f" created)
|
||||
_lr=$(kv_get "$_f" last_run)
|
||||
_fc=$(kv_get "$_f" fail_count)
|
||||
_du=$(kv_get "$_f" due)
|
||||
|
||||
# 逾期照每一筆都判,連 paused 那幾筆也判。到期判定跳過 paused 是對的(那是人設的,
|
||||
# 助理判它到期只會讓人以為它還在跑),但截止時間過了這件事不會因為有人按了暫停就消失
|
||||
# ——一筆被暫停又逾期的交辦,正好是最容易被忘掉的那一種。
|
||||
# done 那幾筆不算逾期:做完了就沒有截止時間可以過。
|
||||
_ov='-'
|
||||
if [ "$_st" != done ]; then
|
||||
_ov=$(overdue_of "$_du") || { T_DUEBAD=$(( T_DUEBAD + 1 )); RC_FIELD=2; }
|
||||
case "$_ov" in
|
||||
''|*[!0-9]*) ;;
|
||||
*) T_OVERDUE=$(( T_OVERDUE + 1 ))
|
||||
OVERDUE_LINES="${OVERDUE_LINES}$(printf '%s\t%s\t%s\t%s\t%s' \
|
||||
"$(flat "$_id")" "$(flat "$_st")" "$(flat "$_du")" "$_ov" "$(flat "$_ti")")
|
||||
" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$_st" != pending ]; then
|
||||
# done 與 paused 一律不判。paused 是人設的,助理判它到期只會讓人以為它還在跑。
|
||||
# done 與 paused 一律不判到期。
|
||||
T_SKIP=$(( T_SKIP + 1 ))
|
||||
row_out "$_id" skip "$_st" "$_kd" "$_ac" '' '' '' '' 'state 不是 pending,不判到期' "$_ti"
|
||||
row_out "$_id" skip "$_st" "$_kd" "$_ac" '' '' '' '' 'state 不是 pending,不判到期' "$_ti" "$_ov"
|
||||
continue
|
||||
fi
|
||||
|
||||
@@ -914,7 +975,7 @@ scan_tasks() {
|
||||
unwired) T_UNWIRED=$(( T_UNWIRED + 1 )) ;;
|
||||
esac
|
||||
row_out "$_id" "$R_VERDICT" "$_st" "$_kd" "$_ac" "$_tg" "$_rc" \
|
||||
"$R_NEXT" "$R_REARM" "$R_WHY" "$_ti"
|
||||
"$R_NEXT" "$R_REARM" "$R_WHY" "$_ti" "$_ov"
|
||||
done
|
||||
[ "$T_TOTAL" -eq 0 ] && {
|
||||
RC_EMPTY=4
|
||||
@@ -931,7 +992,7 @@ compose_md() {
|
||||
printf '事件靠比對狀態快照偵測:每一輪讀那幾支產生者留下的狀態,跟上一輪的快照比,有差別就算事件發生。快照在 `%s`,事件計數在 `%s`。\n\n' \
|
||||
"$PREV" "$SEEN"
|
||||
printf '**兩輪之間發生又消失的事件會漏掉。** 一支工作包在同一個巡檢週期之內鎖上又合併、一個工作階段在同一個週期之內開又關,這一節都看不到——看到的只有兩張快照的差別。往後誰假設「事件不會漏」就會出錯,而那種錯是無聲的:那筆待辦看起來就是還沒到期。\n\n'
|
||||
printf '這一節不判逾期(`due` 欄有沒有過),也不執行任何一筆。到期的那幾筆要不要做、怎麼做,在呼叫端。\n\n'
|
||||
printf '到期與逾期是兩件事,這一節兩件都判:到期是「該跑了」,逾期是「`due` 欄那個截止時間過了」。一筆七天一次的檢查項天天都可能到期,卻永遠不會逾期;一筆有截止時間的交辦可能早就逾期,卻因為排定點還沒到而判成還沒到。這一節不執行任何一筆——到期的那幾筆要不要做、怎麼做,在呼叫端。\n\n'
|
||||
printf '| 項目 | 內容 |\n'
|
||||
printf '| --- | --- |\n'
|
||||
printf '| 判定時間 | %s |\n' "$(epoch_to_iso "$NOW")"
|
||||
@@ -943,10 +1004,12 @@ compose_md() {
|
||||
printf '| 本輪新事件 | %s 種 |\n' "$EV_NEW"
|
||||
printf '| 待辦簿筆數 | %s |\n' "$T_TOTAL"
|
||||
printf '| 到期 | %s |\n' "$T_DUE"
|
||||
printf '| 逾期 | %s |\n' "$T_OVERDUE"
|
||||
printf '| 還沒到 | %s |\n' "$T_WAIT"
|
||||
printf '| 判不了(欄位不合法) | %s |\n' "$T_INVALID"
|
||||
printf '| 判不了(來源還沒接線) | %s |\n' "$T_UNWIRED"
|
||||
printf '| 不判(state 不是 pending) | %s |\n' "$T_SKIP"
|
||||
[ "$T_DUEBAD" -gt 0 ] && printf '| `due` 欄解不開 | %s |\n' "$T_DUEBAD"
|
||||
|
||||
printf '\n#### 狀態來源\n\n'
|
||||
printf '| 來源 | 狀態 | 筆數 | 說明 |\n'
|
||||
@@ -975,19 +1038,36 @@ compose_md() {
|
||||
printf '本輪沒有新事件。\n'
|
||||
fi
|
||||
|
||||
printf '\n#### 逾期\n\n'
|
||||
if [ "$T_OVERDUE" -gt 0 ]; then
|
||||
printf '**這幾筆的截止時間過了。逾期每一輪都提,不因為提過就不再提**——助理只提醒,不代為執行,也不自己把它移出這一節。\n\n'
|
||||
printf '| id | state | 截止時間 | 逾期多久 | 標題 |\n'
|
||||
printf '| --- | --- | --- | ---: | --- |\n'
|
||||
printf '%s' "$OVERDUE_LINES" | while IFS="$(printf '\t')" read -r _oi _os _od _oa _ot; do
|
||||
[ -n "$_oi" ] || continue
|
||||
printf '| `%s` | %s | %s | %s | %s |\n' "$_oi" "$_os" "$(cell "$_od")" "$(dur_human "$_oa")" "$(cell "${_ot:--}")"
|
||||
done
|
||||
printf '\n被暫停的那幾筆也算在裡面:截止時間過了這件事不會因為有人按了暫停就消失,而一筆被暫停又逾期的交辦正好是最容易被忘掉的那一種。\n'
|
||||
else
|
||||
printf '沒有逾期的待辦。`due` 欄是空的那幾筆沒有截止時間,永遠不會逾期。\n'
|
||||
fi
|
||||
if [ "$T_DUEBAD" -gt 0 ]; then
|
||||
printf '\n有 %s 筆的 `due` 欄解不開,上表 `overdue` 那一欄是 `bad`。**一個解不開的截止時間跟沒有截止時間,在畫面上長得一模一樣**,而前者是登錄的時候就填錯了:重新登錄一筆,`id` 由建立時間與標題算出來,改欄位值算不回同一個 id。\n' "$T_DUEBAD"
|
||||
fi
|
||||
|
||||
printf '\n#### 逐筆判定\n\n'
|
||||
if [ -s "$ROWS" ]; then
|
||||
printf '| id | 判定 | 標題 | 動作 | trigger | recur | next_run | 重新武裝 | 為什麼 |\n'
|
||||
printf '| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n'
|
||||
printf '| id | 判定 | 逾期 | 標題 | 動作 | trigger | recur | next_run | 重新武裝 | 為什麼 |\n'
|
||||
printf '| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n'
|
||||
# 這一段交給 awk 一次做完,不用殼的 while read 逐列切。殼的 read 拿定位字元當分隔時會
|
||||
# 把連續的定位字元併成一個——定位字元算 IFS 的空白字元——於是空欄位整個消失,後面每一欄
|
||||
# 都往前挪一格,印出來的表格看起來完整,值卻全錯位。awk 的 -F'\t' 不併,空欄位就是空欄位。
|
||||
awk -F'\t' '
|
||||
function d(s) { return s == "" ? "-" : s }
|
||||
function esc(s) { gsub(/\|/, "\\|", s); return s }
|
||||
NF >= 11 && $1 != "" {
|
||||
printf "| `%s` | %s | %s | %s | `%s` | `%s` | %s | %s | %s |\n", \
|
||||
$1, $2, esc(d($11)), esc(d($5)), d($6), d($7), d($8), d($9), esc(d($10))
|
||||
NF >= 12 && $1 != "" {
|
||||
printf "| `%s` | %s | %s | %s | %s | `%s` | `%s` | %s | %s | %s |\n", \
|
||||
$1, $2, d($12), esc(d($11)), esc(d($5)), d($6), d($7), d($8), d($9), esc(d($10))
|
||||
}' "$ROWS"
|
||||
else
|
||||
printf '待辦簿零筆,或目錄不存在。這一輪沒有任何一筆可判——「沒判過」不等於「都沒到期」。\n'
|
||||
@@ -1042,9 +1122,9 @@ cmd_scan() {
|
||||
# stdout 上的 task= 那幾行是給人看的。trigger、recur、why、title 四欄都可能帶空白,所以這
|
||||
# 幾行切不回欄位——要逐筆取值的呼叫端讀 rows_file 那個定位字元分隔的檔案,不要切這幾行。
|
||||
if [ -s "$ROWS" ]; then
|
||||
awk -F'\t' 'NF >= 11 && $1 != "" {
|
||||
printf "task=%s verdict=%s state=%s kind=%s action=%s next_run=%s rearm_at=%s trigger=%s recur=%s why=%s title=%s\n", \
|
||||
$1, $2, $3, $4, $5, $8, $9, $6, $7, $10, $11
|
||||
awk -F'\t' 'NF >= 12 && $1 != "" {
|
||||
printf "task=%s verdict=%s state=%s kind=%s action=%s next_run=%s rearm_at=%s trigger=%s recur=%s overdue=%s why=%s title=%s\n", \
|
||||
$1, $2, $3, $4, $5, $8, $9, $6, $7, $12, $10, $11
|
||||
}' "$ROWS"
|
||||
fi
|
||||
printf 'tasks_total=%s\n' "$T_TOTAL"
|
||||
@@ -1053,8 +1133,18 @@ cmd_scan() {
|
||||
printf 'tasks_invalid=%s\n' "$T_INVALID"
|
||||
printf 'tasks_unwired=%s\n' "$T_UNWIRED"
|
||||
printf 'tasks_skipped=%s\n' "$T_SKIP"
|
||||
printf 'tasks_overdue=%s\n' "$T_OVERDUE"
|
||||
printf 'tasks_due_bad=%s\n' "$T_DUEBAD"
|
||||
# 逾期的那幾筆逐筆點名,不只印一個數字。一份只有數字的回報讀不出「是哪一筆過期了」,
|
||||
# 而那正是唯一有用的資訊;逾期的處置一律是人接手,人要知道接哪一筆。
|
||||
if [ -n "$OVERDUE_LINES" ]; then
|
||||
printf '%s' "$OVERDUE_LINES" | while IFS="$(printf '\t')" read -r _oi _os _od _oa _ot; do
|
||||
[ -n "$_oi" ] || continue
|
||||
printf 'overdue_row=%s state=%s due=%s overdue_secs=%s title=%s\n' "$_oi" "$_os" "$_od" "$_oa" "$_ot"
|
||||
done
|
||||
fi
|
||||
printf 'rows_file=%s\n' "$ROWS"
|
||||
printf 'rows_columns=id verdict state kind action trigger recur next_run rearm_at why title\n'
|
||||
printf 'rows_columns=id verdict state kind action trigger recur next_run rearm_at why title overdue\n'
|
||||
printf 'due_file=%s\n' "$MD"
|
||||
printf 'prev_file=%s\n' "$PREV"
|
||||
printf 'seen_file=%s\n' "$SEEN"
|
||||
@@ -1062,6 +1152,53 @@ cmd_scan() {
|
||||
finish_rc
|
||||
}
|
||||
|
||||
# 只判逾期,一律唯讀。
|
||||
#
|
||||
# 為什麼另開一個子命令:逾期判定跟事件與到期判定不同,它一個狀態都不必比、一份快照都不必推進
|
||||
# ——只要把每一筆的 due 欄跟現在比一下。狀態查詢那一路每次都想知道「有沒有逾期的」,走 scan
|
||||
# 就會推進快照,同一輪之後的事件判定會全部落空;走 events 又判不到逾期。
|
||||
# 讓呼叫端自己拿 due 欄去比更糟:那就是第二套判定,跟這一支的規則會漂移,而漂移的那一天
|
||||
# 兩邊都說自己是對的。
|
||||
cmd_overdue() {
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--now) [ "$#" -ge 2 ] || usage; NOW_ARG="$2"; shift 2 ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
resolve_now
|
||||
T_TOTAL=0; T_OVERDUE=0; T_DUEBAD=0; OVERDUE_LINES=''
|
||||
if [ ! -d "$TASKS_DIR" ]; then
|
||||
RC_EMPTY=4
|
||||
note "待辦簿目錄不存在($TASKS_DIR),這一輪沒有任何一筆可判。「沒判過」不等於「都沒逾期」。"
|
||||
else
|
||||
for _f in "$TASKS_DIR"/*; do
|
||||
[ -f "$_f" ] || continue
|
||||
T_TOTAL=$(( T_TOTAL + 1 ))
|
||||
_id=$(kv_get "$_f" id); [ -n "$_id" ] || _id=$(basename "$_f")
|
||||
_st=$(kv_get "$_f" state); [ -n "$_st" ] || _st=pending
|
||||
_ti=$(kv_get "$_f" title)
|
||||
_du=$(kv_get "$_f" due)
|
||||
[ "$_st" = done ] && continue
|
||||
_ov=$(overdue_of "$_du") || { T_DUEBAD=$(( T_DUEBAD + 1 )); RC_FIELD=2; }
|
||||
case "$_ov" in
|
||||
''|*[!0-9]*) continue ;;
|
||||
esac
|
||||
T_OVERDUE=$(( T_OVERDUE + 1 ))
|
||||
printf 'overdue_row=%s state=%s due=%s overdue_secs=%s human=%s title=%s\n' \
|
||||
"$_id" "$_st" "$_du" "$_ov" "$(dur_human "$_ov")" "$_ti"
|
||||
done
|
||||
[ "$T_TOTAL" -eq 0 ] && { RC_EMPTY=4; note "待辦簿目錄在($TASKS_DIR),但零筆。"; }
|
||||
fi
|
||||
printf 'now=%s\n' "$(epoch_to_iso "$NOW")"
|
||||
printf 'tasks_total=%s\n' "$T_TOTAL"
|
||||
printf 'tasks_overdue=%s\n' "$T_OVERDUE"
|
||||
printf 'tasks_due_bad=%s\n' "$T_DUEBAD"
|
||||
note '這是唯讀判定:一份快照都沒推進,一筆待辦都沒改。逾期的處置一律是人接手。'
|
||||
cleanup_tmp
|
||||
finish_rc
|
||||
}
|
||||
|
||||
cmd_events() {
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
@@ -1149,6 +1286,7 @@ FIRST_RUN=0
|
||||
EV_NAMES=''
|
||||
EV_NEW=0
|
||||
T_TOTAL=0; T_DUE=0; T_WAIT=0; T_INVALID=0; T_UNWIRED=0; T_SKIP=0
|
||||
T_OVERDUE=0; T_DUEBAD=0; OVERDUE_LINES=''
|
||||
|
||||
CMD="${1:-}"
|
||||
[ -n "$CMD" ] || usage
|
||||
@@ -1156,6 +1294,7 @@ shift
|
||||
case "$CMD" in
|
||||
scan) cmd_scan "$@" ;;
|
||||
events) cmd_events "$@" ;;
|
||||
overdue) cmd_overdue "$@" ;;
|
||||
next) cmd_next "$@" ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
|
||||
Reference in New Issue
Block a user