feat(log): 工作日誌支援待寫入暫存
What:新增 tools/worklog-pending.sh,worklog 技能改成寫入前先併入暫存內容、寫成功後才清除。
Why:SDLC 階段跑完沒寫工作日誌時,內容如果只留在對話裡,換一個工作階段就補不回來了。
How:暫存放在 $JSC_HOME/worklog-pending/{HASH}/,檔名帶 UTC 時間與 pid,同一秒的兩個工作階段不會互相覆蓋。jsc-sdlc 的階段回報負責存入,worklog 負責併入與清除;清除排在 wiki 寫入成功之後,先清再寫會兩邊都沒有。
Who:用 jsc-sdlc 跑階段、事後要靠工作日誌回頭查的人。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+92
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env sh
|
||||
# worklog-pending.sh — 待寫入工作日誌的暫存區(供 jsc-sdlc 階段回報與 jsc-log:worklog 使用)。
|
||||
#
|
||||
# 為什麼要有這支腳本:SDLC 每個階段結束都要回報工作日誌連結。階段跑完卻沒寫日誌時,
|
||||
# 內容如果只留在對話裡,換一個工作階段就消失了,下次寫日誌也補不回來。所以暫存搬到檔案層:
|
||||
# 階段回報發現沒有日誌,就把該階段的內容存進本區並警告使用者;下次 jsc-log:worklog 寫入時
|
||||
# 先把本區的內容一併寫進去,寫完才清掉。
|
||||
#
|
||||
# 用法:
|
||||
# worklog-pending.sh add <hash> <file> 把一段待寫入的日誌內容存起來,印出存放路徑
|
||||
# worklog-pending.sh list <hash> 列出該 hash 的暫存檔路徑(一行一個,依時間排序)
|
||||
# worklog-pending.sh cat <hash> 依時間順序印出全部暫存內容
|
||||
# worklog-pending.sh clear <hash> 清掉該 hash 的暫存(寫入日誌成功後才做)
|
||||
#
|
||||
# <hash> 為 jsc-gitea/tools/hash-id 算出的 8 碼工作日誌 hash,也就是 LOG_{HASH} 的 HASH。
|
||||
# 存放位置: $JSC_HOME/worklog-pending/{hash}/{UTC 時間}-{pid}.md(JSC_HOME 預設 ~/.jsc)
|
||||
#
|
||||
# 結束碼: 0=成功 1=讀寫失敗 2=用法錯誤 3=該 hash 沒有暫存內容
|
||||
#
|
||||
# 陷阱:
|
||||
# - clear 只在日誌確實寫進 wiki 之後才呼叫。先清再寫,寫失敗就兩邊都沒有。
|
||||
# - 檔名帶 UTC 時間與 pid,同一秒內兩個工作階段各存各的,不會互相覆蓋。
|
||||
set -eu
|
||||
|
||||
JSC_HOME="${JSC_HOME:-$HOME/.jsc}"
|
||||
ROOT="$JSC_HOME/worklog-pending"
|
||||
|
||||
usage() {
|
||||
cat >&2 <<'EOF'
|
||||
用法:
|
||||
worklog-pending.sh add <hash> <file> 存一段待寫入的日誌內容
|
||||
worklog-pending.sh list <hash> 列出暫存檔路徑
|
||||
worklog-pending.sh cat <hash> 印出全部暫存內容
|
||||
worklog-pending.sh clear <hash> 清掉暫存(寫入日誌成功後才做)
|
||||
結束碼: 0=成功 1=讀寫失敗 2=用法錯誤 3=沒有暫存內容
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
valid_hash() { # 只收 8 碼大寫英數,擋掉路徑穿越
|
||||
case "$1" in
|
||||
[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]) return 0 ;;
|
||||
*) echo "[jsc][工作日誌暫存][ERR]:hash 須為 8 碼大寫英數,收到「${1:-空值}」。" >&2; exit 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
cmd="${1:-}"; [ -n "$cmd" ] || usage
|
||||
shift || true
|
||||
hash="${1:-}"; [ -n "$hash" ] || usage
|
||||
valid_hash "$hash"
|
||||
dir="$ROOT/$hash"
|
||||
|
||||
case "$cmd" in
|
||||
add)
|
||||
src="${2:-}"
|
||||
[ -n "$src" ] || usage
|
||||
[ -f "$src" ] || { echo "[jsc][工作日誌暫存][ERR]:找不到內容檔「$src」。" >&2; exit 1; }
|
||||
mkdir -p "$dir" || { echo "[jsc][工作日誌暫存][ERR]:建不出暫存目錄「$dir」。" >&2; exit 1; }
|
||||
stamp=$(date -u +%Y%m%dT%H%M%SZ)
|
||||
target="$dir/$stamp-$$.md"
|
||||
cp "$src" "$target" || { echo "[jsc][工作日誌暫存][ERR]:寫不進「$target」。" >&2; exit 1; }
|
||||
printf '%s\n' "$target"
|
||||
;;
|
||||
list)
|
||||
[ -d "$dir" ] || exit 3
|
||||
found=0
|
||||
for f in "$dir"/*.md; do
|
||||
[ -f "$f" ] || continue
|
||||
printf '%s\n' "$f"
|
||||
found=1
|
||||
done
|
||||
[ "$found" -eq 1 ] || exit 3
|
||||
;;
|
||||
cat)
|
||||
[ -d "$dir" ] || exit 3
|
||||
found=0
|
||||
for f in "$dir"/*.md; do
|
||||
[ -f "$f" ] || continue
|
||||
cat "$f"
|
||||
printf '\n'
|
||||
found=1
|
||||
done
|
||||
[ "$found" -eq 1 ] || exit 3
|
||||
;;
|
||||
clear)
|
||||
[ -d "$dir" ] || exit 3
|
||||
rm -rf "$dir" || { echo "[jsc][工作日誌暫存][ERR]:清不掉「$dir」。" >&2; exit 1; }
|
||||
printf '已清除暫存:%s\n' "$dir"
|
||||
;;
|
||||
*)
|
||||
usage ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user