feat(狀態回報): 收尾寫一筆 skill-end 事件

現行紀錄只記「被叫用」,沒有成敗也沒有結束碼。跑完整輪的技能與開場就
中止的技能,在紀錄裡長得一模一樣。

start 由技能用量 hook 順手發,不必改技能文件。end 只能由技能自己在收尾
步驟寫——hook 接在技能工具呼叫上,而實際工作發生在之後的模型輪次,它在
原理上看不到成敗。有 start 沒有配對的 end,就是那一輪中止了。

status 五選一,每支技能各自寫明什麼情況選哪一個。找不到回報腳本就安靜
跳過,回報失敗一律不改變技能自己的結論。
This commit is contained in:
2026-09-02 16:01:16 +08:00
parent 03188837d3
commit b87dbb12cd
11 changed files with 240 additions and 37 deletions
+22 -5
View File
@@ -3,21 +3,30 @@
#
# 用法: check-behaviors.sh <domain-path>
#
# 檢查六項(格式合約見 jsc-meta references/guidelines.md 的「技能行為清單」一節):
# 檢查七項(格式合約見 jsc-meta references/guidelines.md 的「技能行為清單」一節):
# 1. 標題 — 第一行是「# jsc-{domain} 技能行為清單」,檔案不得有 UTF-8 BOM。
# 2. 節對技能 — 每支 skills/*/SKILL.md 一個「## {技能名}」節,名稱與目錄名逐字相同,不多不少。
# 3. 節順序 — 節的排列照技能目錄名的字典序(LC_ALL=C)。
# 4. 表格 — 每節恰好一張表,表頭是「| 項目 | 內容 |」。
# 5. 五個欄位 — 依序為 觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象,不多不少。
# 6. 內容 — 每一列的「內容」欄不得空白。
# 7. 收尾事件 — 「可驗證跡象」那一列要寫到 skill-end 或 events.jsonl。
#
# 為什麼要這支: 技能改了行為、清單沒跟著改,兩邊就漂移。漂移靠眼睛比對,10 個 domain 每次稽核
# 都要重做一遍,還會漏。這六項的輸入輸出固定,交給程式判定才穩。
# 都要重做一遍,還會漏。這七項的輸入輸出固定,交給程式判定才穩。
#
# 為什麼加第 7 項: 技能的成敗只有技能自己寫得出來。hook 接在技能工具呼叫之後就觸發,那一刻
# 實際工作還在後面的模型輪次,看不到結果;有 start 沒有配對的 end 就是中止。收尾少寫這一筆,
# 那支技能每一次都會被算成中止,而且不會有任何錯誤訊息。跡象欄是清單裡唯一寫得下「跑完在
# 環境裡留下什麼」的地方,所以判準放在這一列,而不是另開一項只檢查文字。
# 本腳本是所有 domain 共用的稽核入口,這一項加進來之後,還沒補收尾事件的 domain 會開始回 1。
# 那是預期的結果,不是誤報:要修的是那些 domain 的技能與清單,不是把斷言放寬。
#
# 輸出: 一行一個不合格項目,格式 {behaviors.md 路徑}:{技能名或 -}:{說明}(stderr);
# 通過時在 stderr 印一行摘要。stdout 不印東西。
# 結束碼: 0=行為清單與 skills/ 相符,五個欄位齊全且內容欄非空
# 1=不符:缺節、多節、順序不對、表格不對、缺欄位或欄位空白,清單在 stderr
# 結束碼: 0=行為清單與 skills/ 相符,五個欄位齊全、內容欄非空,且每節都寫了收尾事件
# 1=不符:缺節、多節、順序不對、表格不對、缺欄位、欄位空白,或跡象欄沒寫收尾事件,
# 清單在 stderr
# 2=用法錯誤(本腳本只吃一個參數)
# 3=找不到 {domain-path}/references/behaviors.md,或找不到 {domain-path}/skills/,
# 或 skills/ 底下一支 SKILL.md 都沒有——**什麼都沒查**,不等於通過
@@ -155,6 +164,14 @@ while IFS= read -r name; do
want=$(echo "$FIELDS" | cut -d' ' -f"$i")
[ "$item" = "$want" ] || report "$name" "第 $i 列的項目要是「$want」,實際是「$item」"
[ -n "$body" ] || report "$name" "「$item」的內容欄空白,請補實際行為"
# 第 7 項只在跡象欄成立。認項目名不認列號: 列號錯位時上面那一行已經報過,
# 這裡再報一次只是同一個缺陷印兩遍,反而蓋掉真正沒寫收尾事件的那幾節。
if [ "$item" = '可驗證跡象' ]; then
case $body in
*skill-end*|*events.jsonl*) ;;
*) report "$name" '「可驗證跡象」沒寫到收尾的 skill-end 事件,請補上這一筆(見準則「執行狀態回報」)' ;;
esac
fi
done < "$TMPD/rows.txt"
done < "$TMPD/skills.txt"
@@ -164,7 +181,7 @@ if awk -F"$TAB" '$2 == "-" { found = 1 } END { exit found ? 0 : 1 }' "$TMPD/pars
fi
if [ "$fail" -eq 0 ]; then
echo "行為清單檢查通過:$DOC 對上 $(wc -l < "$TMPD/skills.txt" | tr -d ' ') 支技能,五個欄位齊全" >&2
echo "行為清單檢查通過:$DOC 對上 $(wc -l < "$TMPD/skills.txt" | tr -d ' ') 支技能,五個欄位齊全,跡象欄都寫了收尾事件" >&2
else
echo "行為清單檢查不符:$DOC 與 $SKILLS 對不起來,逐項見上方" >&2
fi