roster-guard 認不出真實的 subagent_type,整個環境派不出工

Claude Code 給 plugin agent 的 subagent_type 帶前綴(isep:isep-hand),
而 agents/*.md 的 frontmatter name 沒有(isep-hand)。roster.find() 用完全相等比對
⇒ 真實派工一律被擋,而名單上的裸名字工具又不收 ⇒ 兩種寫法都派不出去。

測試沒抓到是因為 24 條全部餵手寫 payload,沒有一條用真實的 subagent_type 形狀。
補第 19 條專測這個:舊 roster.py + 新測試 → 紅;修好 → 25/25。

順手補 gate-ok 漏掉的 roster——v0.15.0 新增那支閘時沒同步逃生口清單,
所以撞上死鎖時連留痕的出口都沒有。
This commit is contained in:
claude-code
2026-08-28 12:36:13 +00:00
parent a0a34b629e
commit 5342917f2b
4 changed files with 36 additions and 3 deletions
+8 -1
View File
@@ -97,11 +97,18 @@ def names(directory=None):
def find(name, directory=None):
# 🔴 subagent_type 在 plugin 裡帶前綴:Claude Code 給的是 "isep:isep-hand"
# 而 agents/*.md 的 frontmatter name 是 "isep-hand"。原本用完全相等比對
# ⇒ 真實的派工一律認不出來,而名單裡的名字工具又不收 ⇒ 兩種寫法都派不出去。
# 2026-08-28 v0.16.0 上線後實撞:整個環境派不出任何工,只能蓋 solo 戳記自己修。
# 測試沒抓到是因為 24 條全部餵手寫 payload,沒有一條用真實的 subagent_type 形狀。
n = (name or "").strip()
if not n:
return None
# 允許 "<plugin>:<name>";冒號後面那半才是名單上的名字
bare = n.rsplit(":", 1)[-1].strip() if ":" in n else n
for w in load(directory):
if w["name"] == n:
if w["name"] == n or w["name"] == bare:
return w
return None
+24
View File
@@ -176,6 +176,30 @@ else
printf ' ❌ ⑱ 身份欄沒有吃下工人名字(或把原本的三個角色弄壞了)\n'; FAIL=$((FAIL+1))
fi
echo "── 驗收 4:真實的 subagent_type 形狀(2026-08-28 實撞的死鎖)──────"
N=$((N+1))
if python3 - "$ROOT" <<'PY' 2>/dev/null
import sys, os
sys.path.insert(0, os.path.join(sys.argv[1], "hooks", "lib"))
import roster
d = os.path.join(sys.argv[1], "agents")
# Claude Code 給 plugin agent 的真實值帶前綴,agents/*.md 的 name 沒有
assert roster.find("isep:isep-hand", d), "帶 plugin 前綴的真實 subagent_type 認不出來"
assert roster.find("isep:scout", d), "帶前綴的 scout 認不出來"
# 名單上的裸名字仍然要收(人會照 roster list 直接貼)
assert roster.find("isep-hand", d), "裸名字被弄壞了"
# 剝前綴不能變成放行任何東西
assert roster.find("isep:nobody", d) is None, "不存在的名字被放行了"
assert roster.find("nobody", d) is None, "不存在的裸名字被放行了"
assert roster.find("", d) is None, "空字串被放行了"
PY
then
printf ' ✅ ⑲ 帶 plugin 前綴的真實 subagent_type 認得出來,不存在的仍然擋\n'; PASS=$((PASS+1))
else
printf ' ❌ ⑲ 真實的 subagent_typeisep:isep-hand)認不出來——就是這個造成 8/28 的死鎖\n'; FAIL=$((FAIL+1))
fi
echo
printf '結果:%s 通過 / %s 失敗(共 %s 條)\n' "$PASS" "$FAIL" "$N"
[ "$FAIL" -eq 0 ] || exit 1