#!/bin/bash # station-done-guard.sh — 收工判準是「站的考題全綠」,不是「任務全關」(JDD 規則 J6) # # 掛 Stop / SubagentStop(收工那一刻),只在 orchestrator 實例生效。 # # ── 它在攔什麼 ────────────────────────────────── # 「任務都關了 ⇒ 這期做完了」——這句話是整套假綠的源頭。 # 任務是**技術軌**的單位(沿系統結構切),站是**PM 軌**的單位(沿人的經歷切)。 # 零件全部做完、每個都對,人還是可能掉進零件之間的縫裡。 # 所以收工只認一件事:**指定站的考題有沒有實測通過**。 # # ── 它不做什麼(重要)──────────────────────────── # 它**不會**自己去跑考題判斷過沒過——Gherkin 的 Then 寫的是「使用者看到什麼」, # 那本來就不是 shell 判得出來的。它做的是:在你要收工的那一刻, # 把「指定站」和「它們現在的狀態」攤在你眼前,逼你面對還沒填的那幾格。 # 自動判綠反而危險:那會製造一個「機器說過了」的假權威。 # # 誠實限制:讀的是 sprint.md/journeys.md 的文字狀態。 # 有人亂填「✅」它看不出來——它擋的是「忘了填」與「用任務數充當進度」,不是造假。 set -uo pipefail HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" . "$HOOK_DIR/lib/role-lib.sh" 2>/dev/null || exit 0 [ "$(sdt_scope)" = "orchestrator" ] || exit 0 ROOT="$(sdt_repo_root)" SPRINT="$ROOT/system-dev/docs/sprint.md" [ -f "$SPRINT" ] || exit 0 # 還沒開始用站號 sprint → 不干擾 # 本期指定的站 STATIONS="$(grep -oE 'S-?[0-9]+' "$SPRINT" 2>/dev/null | sort -u | tr '\n' ' ')" [ -z "$STATIONS" ] && exit 0 # 還沒亮的站(sprint.md 的「❌ 未亮」「◐ 半通」段) UNLIT="$(awk '/未亮|◐|半通/ {print}' "$SPRINT" 2>/dev/null | grep -oE 'S-?[0-9]+' | sort -u | tr '\n' ' ')" echo "════════════════════════════════════════════════" echo "🚦 收工判準:站的考題全綠,不是任務全關(J6)" echo "════════════════════════════════════════════════" echo " 本期指定站:${STATIONS}" if [ -n "$UNLIT" ]; then echo " ⚠️ 還沒亮:${UNLIT}" echo "" echo " 這幾站沒亮,這期就還沒收。收工前擇一:" echo " · 真的通了 → 在 journeys.md 標記點亮,**附實測輸出**(不是「應該會過」)" echo " · 半通 → 標 ◐ 並寫明缺什麼" echo " · 沒通 → 標 ❌ 誠實留著,搬到下一期並寫一行為什麼" echo "" echo " ⛔ 不准用「任務都關了」當收工理由——那是技術軌的單位,不是驗收線。" else echo " ✅ 本期指定站都已標記點亮。記得每一站都要附得出實測證據。" fi echo "" exit 0