fix(sdlc-gate): 能力閘門依 CLI 分流,判不出能力就擋下
What:
- current_model_report() 的偵測鏈依 CLI 分流,一支只讀自己的紀錄。claude 讀 transcript 與 hook stdin,codex 讀 hook stdin 與自己的 session 記錄,copilot、antigravity、kiro 本機沒有可讀的模型紀錄,判不出是哪一支 CLI 時不採用任何自動來源。JSC_MODEL 人工覆寫五支都保留,而且一律排在最後。
- session_id() 的退路鏈補上 CLAUDE_CODE_SESSION_ID,cli_name() 補上 CLAUDECODE 與 CLAUDE_CODE_SESSION_ID。
- 階段鎖狀態檔改成 sessions/{CLI 代號}-{sid}.stage。舊路徑仍讀得到,unlock 不帶參數時新舊兩份一起清,也收一個狀態檔路徑當參數。
- check 改成 fail-closed:判不出 CLI、判不出模型、模型不在能力標籤表上,三種一律以 exit 2 擋下該輪提示。每一則擋下的訊息都印出兩條逃生門。
- write-guard.sh 的 stage 模式改讀 lib.sh 的路徑函式,擋人訊息把實際讀到的狀態檔路徑寫進解除指令。
- codex_session_file() 取「全樹最新一支」的做法改掉。
- wire-cli.sh 的冒煙夾具跟著補:模型來源四條各自指定 CLI 代號,另加三種擋下情形、check 的 fail-closed、階段鎖的 CLI 區隔與舊格式相容,這一組的判定條數由四條增為十二條。
- README 的 hooks 表、狀態檔分界表與環境變數表跟著改。
Why:
- 使用者回報兩件事:在 claude 底下被 codex 的模型判定,而且這道閘門應該只鎖能力標籤、不鎖模型。查下來根因是同一個——閘門完全不分辨自己跑在哪一支 CLI 上。
- 偵測鏈不分流,claude 拿不到 transcript 就一路掉進 codex 的 session 記錄,拿別支的模型判這一支。順帶每一輪都對一個上千個檔、兩百多 MB 的目錄樹跑一次 find,宿主 CLI 跟著卡。
- session_id() 讀的變數名在目前的 claude 上並不存在,sid 一路退回 default。cli_name() 犯同一類錯:只認 plugin 接線才有的變數,技能以 Bash 工具呼叫腳本時取不到,一律判成 unknown。
- 前三項合起來的後果是:技能呼叫 lock 算出的檔名,跟 hook 算出的檔名永遠不同。階段鎖上了也對不上,所以這道閘門在 claude 上一直沒有真正生效。
- 狀態檔不分 CLI,各支就共用同一支 default.stage,一支上的鎖擋到另一支。那不只擋提示,write-guard.sh 的 stage 模式連 Write、Edit、MultiEdit 一起擋。
How:
- 政策改成 fail-closed:不知道能力就擋下,知道才比對標籤。原本判不出模型只提醒不擋,那等於「換一支讀不到紀錄的 CLI 就能繞過去」,閘門形同虛設。代價是把人鎖在送不出提示的狀態,所以每一則擋下的訊息都要帶兩條逃生門,照抄就脫困。
- 逃生門的路徑照抄進指令裡。擋人的是 hook,解鎖的是人在殼層手動執行,兩邊算出來的檔名未必相同,不點名就解不到真正擋人的那一支。
- unlock 的參數只收 sessions 目錄底下的 .stage 檔,逃生門不該順便變成任意刪檔的工具。判準刻意不綁這支行程算出的 JSC_HOME:擋人的一側跟解鎖的一側未必相同,綁上去就會把照抄訊息的人擋掉,那正是這個逃生門要避免的事。
- 狀態檔用檔名前綴不用子目錄。外部工具以單層的 sessions/*.stage 盤點階段鎖,改成子目錄會讓每一支鎖從那些盤點裡整批消失。
- 舊路徑只讀不搬也不刪,unlock 一併清掉。只清新的那一份,舊格式的鎖就永遠解不開,被它擋住的人沒有逃生門。
- 變數名只補實測看得到的那幾個,而且只補 claude 這一支。其他 CLI 的變數名與環境特徵沒有實測過,猜一個填進來只會多一個錯誤來源,那幾支本來就由接線設定明確帶 JSC_CLI。
- codex_session_file() 原本寫成 xargs ls -t 再 head -n 1,那是錯的:xargs 依參數長度分批,ls -t 只在自己那一批裡排序,取到的是第一批裡最新的,不是全域最新。改成讓 find 一併印出修改時間再全域排序;沒有 -printf 就退回路徑排序,那些檔名以 ISO 時間開頭,字典序等同時間序。
- 冒煙的擋人案例連訊息一起驗,不只比結束碼。訊息漏掉逃生門一樣是綠燈,而那才是這道 fail-closed 真正的風險。
- 四支腳本併成一筆。write-guard.sh 讀 lib.sh 的路徑函式,wire-cli.sh 是驗這些行為的冒煙夾具,拆開會留下跑不過的中間版本:路徑函式與呼叫端分兩筆,中間那一筆狀態檔的讀寫兩側就對不上。
- 一次性代價:升級後每台機器第一次 SessionStart 會清一次重啟閘門。sid 換了名字,看起來像新的工作階段。只發生這一次。
- 三份 manifest 這一筆不動,版本號另外提升。
Who:
SDLC 階段能力閘門。修的是它一直沒有生效的那條路徑,順帶把 codex session 記錄的取檔方式一起修掉。
This commit is contained in:
+127
-14
@@ -1354,7 +1354,8 @@ if [ "$action" = smoke ]; then
|
||||
# 那一類會讓總數永遠對不上,斷言也就形同虛設。
|
||||
# hook 模式 九支 hook 的每個接線模式各一條。sdlc-gate.sh、comment-scope.sh、
|
||||
# lang-guard.sh 與 write-guard.sh 各有多個模式,所以比 hook 支數多
|
||||
# 模型來源 sdlc-gate.sh lock 取模型代號的四條來源判定路徑
|
||||
# 模型與階段鎖 sdlc-gate.sh 取模型代號的四條來源判定路徑,加上「不知道能力就擋下」的
|
||||
# 三種情形、check 的 fail-closed,以及階段鎖狀態檔的 CLI 區隔與舊格式相容
|
||||
# 工作包 sdlc-gate.sh wp-check skill 的歸屬判定路徑
|
||||
# 重啟閘門 restart-gate.sh 的判定、清除路徑與狀態檔範圍檢查
|
||||
# 寫入閘門 write-guard.sh 三種擋人模式與 release 解除模式的判定路徑
|
||||
@@ -1364,7 +1365,7 @@ if [ "$action" = smoke ]; then
|
||||
# 跨 CLI 貫通 restart-gate.sh 吃五支 CLI 的真實負載,驗判定與輸出形態串得起來
|
||||
# 接線形狀 每支 CLI 要寫出去的內容真的產出來一次,驗結構本身(正反案例各一組)
|
||||
SMOKE_EXPECT_HOOK=17
|
||||
SMOKE_EXPECT_MODEL=4
|
||||
SMOKE_EXPECT_MODEL=12
|
||||
SMOKE_EXPECT_WP=6
|
||||
SMOKE_EXPECT_RS=16
|
||||
SMOKE_EXPECT_WG=21
|
||||
@@ -1424,8 +1425,11 @@ if [ "$action" = smoke ]; then
|
||||
smoke_one sdlc-gate.sh "wp-check prompt"
|
||||
smoke_one sdlc-gate.sh "wp-check skill"
|
||||
|
||||
smoke_model_case() { # $1=情境 $2=來源模式 $3=預期來源片段
|
||||
_name="$1"; _mode="$2"; _want="$3"
|
||||
# 第四個參數是這個案例要用的 CLI 代號,不跟著這一輪接線的 $cli 走:模型偵測鏈已經依 CLI
|
||||
# 分流,transcript 只有 claude 讀得到、codex session 記錄只有 codex 讀得到。拿 $cli 去跑
|
||||
# 每一個案例,換一支 CLI 冒煙就會有一半的案例本來就不該命中,測的東西跟著變。
|
||||
smoke_model_case() { # $1=情境 $2=來源模式 $3=預期來源片段 $4=案例用的 CLI 代號
|
||||
_name="$1"; _mode="$2"; _want="$3"; _mcli="$4"
|
||||
# 先計數再開工:底下建不出暫存目錄那條路徑也會印一條結果行,計數放在後面就會漏掉它。
|
||||
smoke_n_model=$((smoke_n_model + 1))
|
||||
_home=$(mktemp -d 2>/dev/null) || {
|
||||
@@ -1446,11 +1450,11 @@ if [ "$action" = smoke ]; then
|
||||
override) _json='{"session_id":"smoke-model-override"}'; _env="JSC_MODEL=gpt-5.x" ;;
|
||||
esac
|
||||
if [ "$_mode" = override ]; then
|
||||
_out=$(printf '%s' "$_json" | JSC_HOME="$_home" CODEX_HOME="$_home/codex" JSC_CLI="$cli" JSC_MODEL="gpt-5.x" sh "$HOOKS/sdlc-gate.sh" lock plan 2>&1); _rc=$?
|
||||
_out=$(printf '%s' "$_json" | JSC_HOME="$_home" CODEX_HOME="$_home/codex" JSC_CLI="$_mcli" JSC_MODEL="gpt-5.x" sh "$HOOKS/sdlc-gate.sh" lock plan 2>&1); _rc=$?
|
||||
else
|
||||
_out=$(printf '%s' "$_json" | JSC_HOME="$_home" CODEX_HOME="$_home/codex" JSC_CLI="$cli" sh "$HOOKS/sdlc-gate.sh" lock plan 2>&1); _rc=$?
|
||||
_out=$(printf '%s' "$_json" | JSC_HOME="$_home" CODEX_HOME="$_home/codex" JSC_CLI="$_mcli" sh "$HOOKS/sdlc-gate.sh" lock plan 2>&1); _rc=$?
|
||||
fi
|
||||
_rep=$(JSC_HOME="$_home" CODEX_HOME="$_home/codex" JSC_CLI="$cli" \
|
||||
_rep=$(JSC_HOME="$_home" CODEX_HOME="$_home/codex" JSC_CLI="$_mcli" \
|
||||
sh "$HOOKS/sdlc-gate.sh" report </dev/null 2>/dev/null)
|
||||
if [ "$_rc" -eq 0 ] && printf '%s\n%s' "$_out" "$_rep" | grep -qF "$_want"; then
|
||||
printf '[jsc] sdlc-gate.sh model(%s):exit 0,來源含 %s,與預期相同。\n' "$_name" "$_want" >> "$smoke_out"
|
||||
@@ -1461,10 +1465,117 @@ if [ "$action" = smoke ]; then
|
||||
fi
|
||||
rm -rf "$_home"
|
||||
}
|
||||
smoke_model_case "transcript 實查" transcript "transcript:"
|
||||
smoke_model_case "Codex session 記錄" codex "codex-session:"
|
||||
smoke_model_case "stdin model 欄位" stdin "hook-stdin"
|
||||
smoke_model_case "JSC_MODEL 人工覆寫" override "人工覆寫:JSC_MODEL"
|
||||
smoke_model_case "transcript 實查" transcript "transcript:" claude
|
||||
smoke_model_case "Codex session 記錄" codex "codex-session:" codex
|
||||
smoke_model_case "stdin model 欄位" stdin "hook-stdin" claude
|
||||
# 人工覆寫對每一支 CLI 都保留,所以這一條照這一輪接線的 CLI 跑。
|
||||
smoke_model_case "JSC_MODEL 人工覆寫" override "人工覆寫:JSC_MODEL" "$cli"
|
||||
|
||||
# 「不知道能力就擋下」的三種情形。判定結果與訊息一起驗:只比結束碼的話,訊息漏掉逃生門
|
||||
# 一樣是綠燈,而被擋住的人就真的出不來了——那才是這道 fail-closed 真正的風險。
|
||||
smoke_model_deny_case() { # $1=情境 $2=案例用的 CLI 代號 $3=JSC_MODEL 值 $4=預期訊息片段
|
||||
smoke_n_model=$((smoke_n_model + 1))
|
||||
_home=$(mktemp -d 2>/dev/null) || {
|
||||
smoke_fails=$((smoke_fails + 1))
|
||||
printf '[jsc] sdlc-gate.sh model(%s):建不出暫存目錄,擋人判定沒驗到。\n' "$1" >> "$smoke_out"
|
||||
return
|
||||
}
|
||||
mkdir -p "$_home/sessions" "$_home/codex/sessions/2026/08/28" 2>/dev/null
|
||||
printf 'stage\tplan\treasoning-max\nmodel\tgpt-5.x\treasoning-max,reasoning-high,coding\n' > "$_home/model-tags.tsv"
|
||||
# codex 的 session 記錄照樣擺著:claude 情境要驗的正是「明明有這一份,也不去讀」。
|
||||
printf '{"type":"turn_context","payload":{"model":"gpt-5.x"}}\n' \
|
||||
> "$_home/codex/sessions/2026/08/28/rollout-2026-08-28T00-00-00-smoke-deny.jsonl"
|
||||
# claude 的三個環境特徵一併清空:JSC_CLI 是空字串時 cli_name() 會退去看它們,只要有一個
|
||||
# 留著繼承來的值,「判不出 CLI」那一條就會被測成 claude。三個要一起清,漏一個等於沒清。
|
||||
_out=$(printf '{"session_id":"smoke-model-deny"}' \
|
||||
| env JSC_HOME="$_home" CODEX_HOME="$_home/codex" JSC_CLI="$2" \
|
||||
CLAUDE_PLUGIN_ROOT="" CLAUDECODE="" CLAUDE_CODE_SESSION_ID="" \
|
||||
JSC_MODEL="$3" sh "$HOOKS/sdlc-gate.sh" lock plan 2>&1); _rc=$?
|
||||
if [ "$_rc" -eq 1 ] && printf '%s' "$_out" | grep -qF "$4" \
|
||||
&& printf '%s' "$_out" | grep -qF 'JSC_MODEL={模型 id}'; then
|
||||
printf '[jsc] sdlc-gate.sh model(%s):exit 1,擋下且訊息帶得出逃生門,與預期相同。\n' "$1" >> "$smoke_out"
|
||||
else
|
||||
smoke_fails=$((smoke_fails + 1))
|
||||
printf '[jsc] sdlc-gate.sh model(%s):exit %s,預期 exit 1 且訊息含「%s」與逃生門,能力閘門壞了:%s\n' \
|
||||
"$1" "$_rc" "$4" "$(printf '%s' "$_out" | tr '\n' ' ' | cut -c1-200)" >> "$smoke_out"
|
||||
fi
|
||||
rm -rf "$_home"
|
||||
}
|
||||
smoke_model_deny_case "claude 情境不去讀 codex 紀錄" claude "" "判定不出目前實際使用的模型"
|
||||
smoke_model_deny_case "判不出是哪一支 CLI" "" "" "判不出是哪一支 CLI"
|
||||
smoke_model_deny_case "模型不在能力標籤表上" claude "mystery-model-not-listed" "不在能力標籤表上"
|
||||
|
||||
# check 的 fail-closed:階段鎖在、判不出模型,要 exit 2 擋下該輪提示並帶出逃生門。
|
||||
# 這一條原本是「只提醒不擋」,改成擋下之後逃生門就是唯一的出路,所以訊息一起驗。
|
||||
smoke_n_model=$((smoke_n_model + 1))
|
||||
if ck_home=$(mktemp -d 2>/dev/null) && mkdir -p "$ck_home/sessions" 2>/dev/null; then
|
||||
printf 'stage\tplan\treasoning-max\nmodel\tgpt-5.x\treasoning-max,coding\n' > "$ck_home/model-tags.tsv"
|
||||
printf 'plan\treasoning-max\tgpt-5.x\tsmoke\n' > "$ck_home/sessions/claude-smoke-check.stage"
|
||||
ck_out=$(printf '{"session_id":"smoke-check"}' \
|
||||
| env JSC_HOME="$ck_home" JSC_CLI=claude CLAUDE_PLUGIN_ROOT="" JSC_MODEL="" \
|
||||
JSC_SESSION_ID=smoke-check sh "$HOOKS/sdlc-gate.sh" check 2>&1); ck_rc=$?
|
||||
if [ "$ck_rc" -eq 2 ] && printf '%s' "$ck_out" | grep -qF 'JSC_MODEL={模型 id}' \
|
||||
&& printf '%s' "$ck_out" | grep -qF 'unlock'; then
|
||||
printf '[jsc] sdlc-gate.sh check(判不出模型時擋下):exit 2,兩條逃生門都印出來,與預期相同。\n' >> "$smoke_out"
|
||||
else
|
||||
smoke_fails=$((smoke_fails + 1))
|
||||
printf '[jsc] sdlc-gate.sh check(判不出模型時擋下):exit %s,預期 exit 2 且訊息含 JSC_MODEL 與 unlock 兩條逃生門,輸出:%s\n' \
|
||||
"$ck_rc" "$(printf '%s' "$ck_out" | tr '\n' ' ' | cut -c1-200)" >> "$smoke_out"
|
||||
fi
|
||||
rm -rf "$ck_home"
|
||||
else
|
||||
smoke_fails=$((smoke_fails + 1))
|
||||
printf '[jsc] sdlc-gate.sh check(判不出模型時擋下):建不出暫存目錄,沒驗到。\n' >> "$smoke_out"
|
||||
fi
|
||||
|
||||
# 階段鎖狀態檔的 CLI 區隔:兩支 CLI 各上一次鎖,兩份狀態檔要分得開,解鎖也只解自己那一份。
|
||||
# session id 判不出時會退回 default,不分 CLI 就會共用同一支檔案,一支上的鎖擋到另一支。
|
||||
smoke_st_case() { # $1=情境 $2=條件成立就通過(已求值的結果字串 ok 或其他)
|
||||
smoke_n_model=$((smoke_n_model + 1))
|
||||
if [ "$2" = ok ]; then
|
||||
printf '[jsc] sdlc-gate.sh 階段鎖(%s):與預期相同。\n' "$1" >> "$smoke_out"
|
||||
else
|
||||
smoke_fails=$((smoke_fails + 1))
|
||||
printf '[jsc] sdlc-gate.sh 階段鎖(%s):不如預期,狀態檔的 CLI 區隔壞了。\n' "$1" >> "$smoke_out"
|
||||
fi
|
||||
}
|
||||
if st_home=$(mktemp -d 2>/dev/null) && mkdir -p "$st_home/sessions" 2>/dev/null; then
|
||||
printf 'stage\tplan\treasoning-max\nstage\timplement\tcoding\nmodel\tgpt-5.x\treasoning-max,coding\n' \
|
||||
> "$st_home/model-tags.tsv"
|
||||
# 兩支各上一次鎖,而且刻意上不同的階段:檔名分開之外,內容也要各記各的。
|
||||
# 不寫成迴圈是為了不動到腳本的位置參數——這一段跑在函式外,set -- 會蓋掉整支腳本的 $@。
|
||||
env JSC_HOME="$st_home" JSC_CLI=claude CLAUDE_PLUGIN_ROOT="" JSC_MODEL=gpt-5.x \
|
||||
JSC_SESSION_ID=smoke-stage sh "$HOOKS/sdlc-gate.sh" lock plan </dev/null >/dev/null 2>&1
|
||||
env JSC_HOME="$st_home" JSC_CLI=codex CLAUDE_PLUGIN_ROOT="" JSC_MODEL=gpt-5.x \
|
||||
JSC_SESSION_ID=smoke-stage sh "$HOOKS/sdlc-gate.sh" lock implement </dev/null >/dev/null 2>&1
|
||||
st_a="$st_home/sessions/claude-smoke-stage.stage"
|
||||
st_b="$st_home/sessions/codex-smoke-stage.stage"
|
||||
st_r=bad; { [ -f "$st_a" ] && [ -f "$st_b" ]; } && st_r=ok
|
||||
smoke_st_case "兩支 CLI 各寫出自己那一份" "$st_r"
|
||||
st_r=bad
|
||||
[ "$(cut -f1 "$st_a" 2>/dev/null)" = plan ] \
|
||||
&& [ "$(cut -f1 "$st_b" 2>/dev/null)" = implement ] && st_r=ok
|
||||
smoke_st_case "兩份互不覆蓋,各自記自己的階段" "$st_r"
|
||||
env JSC_HOME="$st_home" JSC_CLI=claude CLAUDE_PLUGIN_ROOT="" \
|
||||
JSC_SESSION_ID=smoke-stage sh "$HOOKS/sdlc-gate.sh" unlock </dev/null >/dev/null 2>&1
|
||||
st_r=bad; { [ ! -f "$st_a" ] && [ -f "$st_b" ]; } && st_r=ok
|
||||
smoke_st_case "解鎖只解自己那一份" "$st_r"
|
||||
# 舊格式 sessions/{sid}.stage 的往後相容:新路徑沒有時要讀得到它,unlock 也要清得掉。
|
||||
rm -f "$st_b"
|
||||
printf 'plan\treasoning-max\tgpt-5.x\tsmoke\n' > "$st_home/sessions/smoke-legacy.stage"
|
||||
st_out=$(env JSC_HOME="$st_home" JSC_CLI=claude CLAUDE_PLUGIN_ROOT="" JSC_MODEL=gpt-5.x \
|
||||
JSC_SESSION_ID=smoke-legacy sh "$HOOKS/sdlc-gate.sh" report </dev/null 2>/dev/null)
|
||||
st_r=bad; printf '%s' "$st_out" | grep -qF 'smoke-legacy plan reasoning-max' && st_r=ok
|
||||
smoke_st_case "舊格式狀態檔仍讀得到" "$st_r"
|
||||
rm -rf "$st_home"
|
||||
else
|
||||
smoke_fails=$((smoke_fails + 4))
|
||||
printf '[jsc] sdlc-gate.sh 階段鎖:建不出暫存目錄,狀態檔的 CLI 區隔沒驗到。\n' >> "$smoke_out"
|
||||
printf '[jsc] sdlc-gate.sh 階段鎖:同上,兩份互不覆蓋沒驗到。\n' >> "$smoke_out"
|
||||
printf '[jsc] sdlc-gate.sh 階段鎖:同上,解鎖範圍沒驗到。\n' >> "$smoke_out"
|
||||
printf '[jsc] sdlc-gate.sh 階段鎖:同上,舊格式相容沒驗到。\n' >> "$smoke_out"
|
||||
smoke_n_model=$((smoke_n_model + 4))
|
||||
fi
|
||||
|
||||
# 工作包歸屬判定(wp-check 的第二段):上面兩支清空技能名,只走得到「沒有未結清 PR」與
|
||||
# 「取不到技能名」兩條捷徑,歸屬比對整段都沒跑到。這裡自備一份暫時的 $JSC_HOME 狀態檔,
|
||||
@@ -1650,6 +1761,8 @@ if [ "$action" = smoke ]; then
|
||||
wg_state="$wg_home/sessions/smoke-write.stage"
|
||||
wg_last="$wg_home/sessions/smoke-write.lastskill"
|
||||
# stage:階段鎖狀態檔的格式沿用 sdlc-gate.sh 那一份,這裡照樣寫三欄。
|
||||
# 檔名刻意用舊格式的 sessions/{sid}.stage,順帶把 write-guard 這一側的往後相容也蓋到:
|
||||
# 新路徑不存在時要退回舊路徑讀得出來,否則既有的鎖會在換路徑那一刻整批失效。
|
||||
smoke_wg_case "沒有階段鎖" stage 0
|
||||
printf 'plan\treasoning-max\tsmoke\n' > "$wg_state"
|
||||
smoke_wg_case "階段鎖 plan" stage 2
|
||||
@@ -2061,7 +2174,7 @@ if [ "$action" = smoke ]; then
|
||||
[ "$smoke_n_hook" = "$SMOKE_EXPECT_HOOK" ] \
|
||||
|| smoke_mismatch="${smoke_mismatch}hook 模式 $smoke_n_hook 條(預期 $SMOKE_EXPECT_HOOK);"
|
||||
[ "$smoke_n_model" = "$SMOKE_EXPECT_MODEL" ] \
|
||||
|| smoke_mismatch="${smoke_mismatch}模型來源 $smoke_n_model 條(預期 $SMOKE_EXPECT_MODEL);"
|
||||
|| smoke_mismatch="${smoke_mismatch}模型與階段鎖 $smoke_n_model 條(預期 $SMOKE_EXPECT_MODEL);"
|
||||
[ "$smoke_n_wp" = "$SMOKE_EXPECT_WP" ] \
|
||||
|| smoke_mismatch="${smoke_mismatch}工作包 $smoke_n_wp 條(預期 $SMOKE_EXPECT_WP);"
|
||||
[ "$smoke_n_rs" = "$SMOKE_EXPECT_RS" ] \
|
||||
@@ -2081,7 +2194,7 @@ if [ "$action" = smoke ]; then
|
||||
[ "$smoke_lines" = "$smoke_total" ] \
|
||||
|| smoke_mismatch="${smoke_mismatch}結果行數 $smoke_lines 行(預期 $smoke_total);"
|
||||
|
||||
smoke_breakdown="hook 模式 $SMOKE_EXPECT_HOOK 條、模型來源 $SMOKE_EXPECT_MODEL 條、工作包 $SMOKE_EXPECT_WP 條、重啟閘門 $SMOKE_EXPECT_RS 條、寫入閘門 $SMOKE_EXPECT_WG 條、相依版本 $SMOKE_EXPECT_VG 條、技能名解析 $SMOKE_EXPECT_SN 條、阻擋形態 $SMOKE_EXPECT_DN 條、跨 CLI 貫通 $SMOKE_EXPECT_CX 條、接線形狀 $SMOKE_EXPECT_SH 條"
|
||||
smoke_breakdown="hook 模式 $SMOKE_EXPECT_HOOK 條、模型與階段鎖 $SMOKE_EXPECT_MODEL 條、工作包 $SMOKE_EXPECT_WP 條、重啟閘門 $SMOKE_EXPECT_RS 條、寫入閘門 $SMOKE_EXPECT_WG 條、相依版本 $SMOKE_EXPECT_VG 條、技能名解析 $SMOKE_EXPECT_SN 條、阻擋形態 $SMOKE_EXPECT_DN 條、跨 CLI 貫通 $SMOKE_EXPECT_CX 條、接線形狀 $SMOKE_EXPECT_SH 條"
|
||||
if [ -n "$smoke_mismatch" ]; then
|
||||
printf 'status=failed reason=%s\n' "冒煙結果行數與預期不符:${smoke_mismatch}判定路徑有增減時要一併改腳本裡的預期條數"
|
||||
printf 'lines\t%s\n' "$smoke_lines"
|
||||
@@ -2092,7 +2205,7 @@ if [ "$action" = smoke ]; then
|
||||
fi
|
||||
|
||||
if [ "$smoke_fails" -eq 0 ]; then
|
||||
printf 'status=ok reason=%s\n' "九支 hook 的每個接線模式都跑得完,模型來源、工作包歸屬、部署後重啟閘門、寫入提交閘門、相依版本檢查、五支 CLI 的技能名解析、四種阻擋形態、跨 CLI 貫通與各 CLI 的接線形狀的每條路徑也各走過一次($smoke_breakdown),沒有執行期錯誤"
|
||||
printf 'status=ok reason=%s\n' "九支 hook 的每個接線模式都跑得完,模型與階段鎖、工作包歸屬、部署後重啟閘門、寫入提交閘門、相依版本檢查、五支 CLI 的技能名解析、四種阻擋形態、跨 CLI 貫通與各 CLI 的接線形狀的每條路徑也各走過一次($smoke_breakdown),沒有執行期錯誤"
|
||||
printf 'lines\t%s\n' "$smoke_lines"
|
||||
cat "$smoke_out"; rm -f "$smoke_out"; exit 0
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user