From de504ee2edb1ef3d4431ea581a79483fb6e8340c Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 24 Aug 2026 11:36:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(model-config):=20=E6=96=B0=E5=A2=9E=20SDLC?= =?UTF-8?q?=20=E9=9A=8E=E6=AE=B5=E6=8C=87=E5=AE=9A=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E9=8F=88=E8=A7=A3=E6=9E=90=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What:新增 tools/model-config.sh,提供 get {stage} 與 list 兩個子命令,解析 SDLC 各階段(plan、analyze、implement、maintain)的指定模型鏈。 Why:讓 jsc-sdlc 各階段閘門能以角色式模型路由指定模型與遞補鏈,而不是只靠能力標籤比對;同時讓專案能覆寫全域設定。 How:以 POSIX sh 加 awk 實作;先讀專案目錄 .jsc/models,該階段沒設定才退回 $JSC_HOME/models.conf(JSC_HOME 預設 ~/.jsc);設定格式 stage=model[,fallback...],同階段多行取最後一行;get 未設定時空輸出且 exit 0,list 每階段輸出 stage、chain、source(未設定印「-」)。 Who:jsc-cli models 技能與 jsc-sdlc 各階段的模型閘門。 Co-Authored-By: Claude Fable 5 --- tools/model-config.sh | 84 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100755 tools/model-config.sh diff --git a/tools/model-config.sh b/tools/model-config.sh new file mode 100755 index 0000000..e9108d7 --- /dev/null +++ b/tools/model-config.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env sh +# model-config.sh — 解析 SDLC 各階段的指定模型鏈(角色式路由)。 +# 設定格式(一行一階段):stage=model[,fallback1[,fallback2...]] +# 「#」開頭為註解,空白行忽略。階段限定:plan、analyze、implement、maintain。 +# 解析順序: +# 1. 目前工作目錄的 ./.jsc/models(專案覆寫) +# 2. $JSC_HOME/models.conf(JSC_HOME 預設 ~/.jsc) +# 專案檔有設定的階段完全覆寫全域設定;其餘階段仍讀全域檔。 +# 用法: +# model-config.sh get {stage} 印出該階段解析後的模型鏈(逗號分隔);未設定不印。兩種情況都 exit 0。 +# model-config.sh list 每階段一行:stagechainsource(project 或 global);未設定的 chain 與 source 印「-」。 +set -u + +JSC_HOME="${JSC_HOME:-$HOME/.jsc}" +PROJECT_FILE=./.jsc/models +GLOBAL_FILE="$JSC_HOME/models.conf" +STAGES="plan analyze implement maintain" + +# 取出單一設定檔裡某階段的模型鏈。 +# 同階段出現多行時取最後一行,結果才有確定性。 +read_chain() { # $1=設定檔 $2=階段 + [ -f "$1" ] || return 0 + awk -F= -v stage="$2" ' + { sub(/\r$/, "") } # 去掉 CR + /^[ \t]*#/ { next } # 註解行 + /^[ \t]*$/ { next } # 空白行 + index($0, "=") == 0 { next } + { + key = $1 + gsub(/[ \t]/, "", key) + if (key != stage) next + val = substr($0, index($0, "=") + 1) + gsub(/[ \t]/, "", val) + if (val != "") chain = val + } + END { if (chain != "") print chain } + ' "$1" +} + +# 解析單一階段:專案檔優先,該階段沒設定才退回全域檔。 +# 輸出:chainsource;兩檔都沒設定時不輸出。 +resolve() { # $1=階段 + chain=$(read_chain "$PROJECT_FILE" "$1") + if [ -n "$chain" ]; then + printf '%s\tproject\n' "$chain" + return 0 + fi + chain=$(read_chain "$GLOBAL_FILE" "$1") + if [ -n "$chain" ]; then + printf '%s\tglobal\n' "$chain" + fi + return 0 +} + +usage() { + echo "用法:model-config.sh get {plan|analyze|implement|maintain} | list" >&2 + exit 1 +} + +case "${1:-}" in + get) + stage="${2:-}" + case " $STAGES " in + *" $stage "*) ;; + *) usage ;; + esac + resolve "$stage" | cut -f1 + exit 0 + ;; + list) + for stage in $STAGES; do + line=$(resolve "$stage") + if [ -n "$line" ]; then + printf '%s\t%s\n' "$stage" "$line" + else + printf '%s\t-\t-\n' "$stage" + fi + done + exit 0 + ;; + *) + usage + ;; +esac