feat/sdlc-model-lock-and-wrapper #5

Merged
admin merged 5 commits from feat/sdlc-model-lock-and-wrapper into develop 2026-08-24 03:47:22 +00:00
2 changed files with 50 additions and 1 deletions
Showing only changes of commit 05b3779118 - Show all commits
+4 -1
View File
@@ -4,7 +4,10 @@
{ "hooks": [ { "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/session-timer.sh\" start" } ] }
],
"UserPromptSubmit": [
{ "hooks": [ { "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/ste100-guard.sh\"" } ] }
{ "hooks": [
{ "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/ste100-guard.sh\"" },
{ "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/sdlc-gate.sh\" check" }
] }
],
"Stop": [
{ "hooks": [ { "type": "command", "command": "sh \"${CLAUDE_PLUGIN_ROOT}/hooks/session-timer.sh\" mark" } ] }
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env sh
# sdlc-gate.sh — SDLC 每 session 模型鎖(stage ∈ plan/analyze/implement/maintain)。
# 狀態檔: $JSC_HOME/sessions/{sid}.stage,單行「{stage} {model}」。
# 用法:
# sdlc-gate.sh lock {stage} {model} # 階段閘門通過時上鎖(覆寫既有鎖)
# sdlc-gate.sh unlock # 移除狀態檔
# sdlc-gate.sh check # hook 模式(UserPromptSubmit):模型不符時注入繁中提醒
# sdlc-gate.sh report # 印出 {sid} {stage} {model};無鎖不印
# 缺資料時安靜降級,永遠 exit 0,不可中斷宿主 CLI。
HERE=$(dirname "$0"); . "$HERE/lib.sh"
read_stdin
sid=$(session_id)
state="$JSC_HOME/sessions/$sid.stage"
case "${1:-check}" in
lock)
# 需要 stage 與 model 兩個參數,缺一就安靜降級
if [ -n "${2:-}" ] && [ -n "${3:-}" ]; then
printf '%s %s\n' "$2" "$3" > "$state" 2>/dev/null || true
fi ;;
unlock)
rm -f "$state" 2>/dev/null || true ;;
check)
[ -f "$state" ] || exit 0
stage=$(sed -n '1s/ .*//p' "$state" 2>/dev/null)
locked=$(sed -n '1s/^[^ ]* //p' "$state" 2>/dev/null)
[ -n "$stage" ] && [ -n "$locked" ] || exit 0
# 目前模型判定順序:stdin JSON model > JSC_MODEL > ~/.claude/settings.json(僅 JSC_CLI 為 claude 或未設定時)
cur=$(json_str model)
[ -n "$cur" ] || cur="${JSC_MODEL:-}"
if [ -z "$cur" ] && { [ -z "${JSC_CLI:-}" ] || [ "${JSC_CLI:-}" = "claude" ]; }; then
cur=$(tr -d '\n' < "$HOME/.claude/settings.json" 2>/dev/null \
| sed -n 's/.*"model"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1)
fi
[ -n "$cur" ] || exit 0
# 別名相容:一方包含另一方就視為同一模型(例:opus 對 claude-opus-4-6)
case "$cur" in *"$locked"*) exit 0 ;; esac
case "$locked" in *"$cur"*) exit 0 ;; esac
echo "[jsc] SDLC 模型鎖:階段「${stage}」已鎖定模型「${locked}」,目前模型「${cur}」不符。請拒絕執行任何 SDLC 工作,並請使用者切回模型「${locked}」後再繼續。此鎖會在下一個 SDLC 階段閘門執行時解除。" ;;
report)
if [ -f "$state" ]; then
line=$(sed -n '1p' "$state" 2>/dev/null)
[ -n "$line" ] && echo "$sid $line"
fi ;;
esac
exit 0