釋出技能委派判定的地基與接線至 master,版本 0.2.8 升到 0.3.3 #70

Merged
admin merged 17 commits from develop into master 2026-09-03 07:26:31 +00:00
6 changed files with 410 additions and 3 deletions
Showing only changes of commit 737e3560f3 - Show all commits
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "jsc-meta", "name": "jsc-meta",
"version": "0.3.1", "version": "0.3.2",
"description": "技能組自我管理:新建、更新、刪除技能與技能準則", "description": "技能組自我管理:新建、更新、刪除技能與技能準則",
"skills": "./skills", "skills": "./skills",
"author": { "author": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "jsc-meta", "name": "jsc-meta",
"version": "0.3.1", "version": "0.3.2",
"description": "技能組自我管理:新建、更新、刪除技能與技能準則", "description": "技能組自我管理:新建、更新、刪除技能與技能準則",
"skills": "./skills", "skills": "./skills",
"jsc": { "jsc": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "jsc-meta", "name": "jsc-meta",
"version": "0.3.1", "version": "0.3.2",
"description": "技能組自我管理:新建、更新、刪除技能與技能準則", "description": "技能組自我管理:新建、更新、刪除技能與技能準則",
"skills": "./skills/", "skills": "./skills/",
"jsc": { "jsc": {
+115
View File
@@ -0,0 +1,115 @@
# 技能委派判準
本文件是「一支技能能不能交給背景助理」的唯一判準來源。`skill-new`、`skill-update`、`skill-delete`、`skillset-update` 四支技能異動技能共用這一份,不各自抄一套。
判定結果一律寫進 [`tools/delegate-spec.tsv`](../tools/delegate-spec.tsv),由 [`tools/check-delegate.sh`](../tools/check-delegate.sh) 檢核。本文件只寫判準,不放判定結果。
## 交出方式只有三種
超出這三種的一律不交。
| 代號 | 方式 | 邊界 |
| --- | --- | --- |
| `invoke` | 觸發 | 呼叫既有技能,內容照那支技能自己的流程走。助理只決定「什麼時候跑」,不改那支技能的判斷 |
| `patrol` | 巡檢 | 跑既有的唯讀腳本或讀既有狀態,產出現況。一個字都不改,讀完寫進監控頁 |
| `remind` | 提醒 | 把巡檢結果留到前景會話提出來。不代替使用者決定,也不自己動手 |
一支技能可以同時用多種方式,例如先巡檢再提醒。
## 判定決策樹
一支技能照順序回答五個問題,答完就得到結論。
| 題號 | 問題 | 答「是」往哪走 |
| --- | --- | --- |
| 一 | 本體會改檔案,或對外不可逆? | 是就跳到第四題 |
| 二 | 本體需要使用者決策? | 需要就跳到第四題 |
| 三 | 輸出穩定,跑兩次結果一致? | 是就結論「全交」,方式填觸發 |
| 四 | 切得出唯讀盤點或提醒的一段? | 切得出就結論「切片交」 |
| 五 | 要加條件才切得出? | 是就結論「條件式交」,切不出就結論「不交」 |
```mermaid
flowchart TD
S[一支技能] --> Q1{本體會改檔案,<br/>或對外不可逆?}
Q1 -->|會| Q4
Q1 -->|不會| Q2{本體需要使用者決策?}
Q2 -->|需要| Q4
Q2 -->|不需要| Q3{輸出穩定、跑兩次結果一致?}
Q3 -->|是| R1[全交:觸發]
Q3 -->|否| Q4
Q4{切得出唯讀盤點<br/>或提醒的一段?} -->|切得出| R2[切片交]
Q4 -->|要加條件才切得出| R3[條件式交]
Q4 -->|切不出| R4[不交]
```
結論之外還要多填一項:**這支技能跑完之後建議接哪一支**,寫進清單的 `next` 欄。不交的技能也要填——不交講的是助理不代跑,跟「跑完之後該接什麼」無關。
## 四種結論,每一種都要留一列
| 結論 | `verdict` | 要記什麼 |
| --- | --- | --- |
| 全交 | `full` | 交出方式、預設 `trigger` 與 `recur` |
| 切片交 | `slice` | 交出的那一段、方式、**留在人手上的那一半** |
| 條件式交 | `cond` | 條件講清楚,連同條件不成立時的行為 |
| 不交 | `none` | 不交的理由。不交也要留一列,否則下次分不出「判過決定不交」與「還沒判」 |
「留在人手上的那一半」是切片交的必填欄位。少了它,助理下一輪會把整支技能當成可交的一路跑完。
## 每種結論的必填欄位
`-` 代表這一格填一個減號,不是留白。TSV 沒有空格這種值,留白會被檢核判成缺欄位。
| 欄位 | 全交 | 切片交 | 條件式交 | 不交 |
| --- | --- | --- | --- | --- |
| `way` | 必填 | 必填 | 必填 | `-` |
| `slice` | `-` | 必填 | 必填,條件寫在這裡 | `-` |
| `human` | `-` | 必填 | 必填 | 必填,寫不交的理由 |
| `trigger` | 必填 | 必填 | 必填 | `-` |
| `recur` | 必填 | 必填 | 必填 | `-` |
| `next` | 必填 | 必填 | 必填 | 必填 |
| `version` | 必填 | 必填 | 必填 | 必填 |
| `origin` | 必填 | 必填 | 必填 | 必填 |
`trigger` 與 `recur` 是兩個獨立欄位,四種組合都成立,登錄時不可以壓成兩種。
| 欄位 | 可填值 |
| --- | --- |
| `trigger` | `at:{ISO 時間}`,立刻要做寫 `at:now`;或 `after:{事件名}` |
| `recur` | `once`、`every:{間隔}`、`cron:{式子}` |
事件名只認固定詞彙表:`worklog-written`、`wp-merged`、`stage-entered`、`analyze-completed`、`hook-error`、`session-start`、`session-end`。填一個永遠不會發生的事件名,那一筆就永遠不到期,而且看不出壞在哪。
## 判定結果放哪裡
真實來源是 [`tools/delegate-spec.tsv`](../tools/delegate-spec.tsv),一支技能一列。作法沿用 `jsc-cli/tools/config-spec.tsv` 那套:TSV 加一支檢核腳本,能被腳本比對,不靠人讀。
判定結果**不寫進 `SKILL.md` 的 frontmatter**。`name` 與 `description` 之外的自訂欄位有被各 CLI 的技能驗證擋掉的風險。
「過舊」的判準是比 plugin 版本號:清單上記的版本號落後該 domain 現行版本,就是要複判。版本號是 domain 層級,所以同 domain 改一支技能,其餘技能也會被標成要複判——**這只是提示,不算稽核缺失**。當成缺失的話,每次發版整個 domain 都亮紅,提示很快就被當雜訊忽略。
`origin` 欄記這一列怎麼來的:
| 值 | 意思 | 檢核怎麼看 |
| --- | --- | --- |
| `seed` | 依既有盤點種入,還沒正式走過決策樹 | 印成待複核提示,不算缺失 |
| `judged` | 正式走過決策樹判定 | 不印 |
種入的那一批先掛 `seed`。之後那支技能有異動時就地走一次決策樹,把它轉成 `judged`。
## 各種異動要做的事
| 異動 | 技能 | 要做的事 | 沒做的後果 |
| --- | --- | --- | --- |
| 新增技能 | `skill-new` | 決策樹五題加 `next` 欄那一題,全部照 `jsc-ask:ask` 問過,產出判定結果並寫進清單。**沒有判定結果不算建立完成** | 清單缺列,助理永遠不知道這支技能存在,也建議不到它 |
| 修改技能 | `skill-update` | 動到流程或 `description` 就重判;只改文案不動行為可沿用舊結論,但要更新清單上的版本號並註明沿用 | 技能從唯讀變成會寫檔,助理還照舊觸發它 |
| 刪除技能 | `skill-delete` | 刪掉清單那一列,並移除待辦簿裡引用它的內建項 | 助理會去觸發一支不存在的技能,而且失敗不會自動暫停,會一路重試 |
| 一次改多支 | `skillset-update` | 逐支重判,一支都不能跳 | 同上,而且範圍更大 |
| 例行稽核 | `skill-check` | 跑 `tools/check-delegate.sh`,檢查清單與實際技能一一對應。缺列與多列算缺失;版本號落後與 `seed` 只列成提示 | 清單慢慢與實際脫節,回到手工盤點會過期的老問題 |
## 助理要跟著更新
清單改動之後,助理的內建定期檢查項要重建一次。
- 清單新增可交項目,待辦簿加一筆,來源標成助理內建。
- 清單移除或改成不交,待辦簿移除對應那筆,不留孤兒。
- 使用者自己交辦的項目一律不動。助理不會因為一支技能改判就把使用者交辦的事刪掉。
+225
View File
@@ -0,0 +1,225 @@
#!/usr/bin/env sh
# check-delegate.sh — 檢查委派判定清單 tools/delegate-spec.tsv 有沒有跟本機實際技能對齊。
#
# 用法: check-delegate.sh [<plugins-root>]
# 不給參數就交給 tools/plugins-root.sh 推導根目錄,判準與 list-skills.sh 完全相同。
#
# 檢查四項:
# 1. 一一對應 — 清單一支技能一列,跟 list-skills.sh 的實際技能不多不少,也不重複。
# 2. 欄位齊全 — 11 欄,每一欄非空;四種結論各自的必填欄位都填了,不該填的填 -。
# 3. 欄位可填值 — verdict、way、trigger、recur、origin 只認固定詞彙;next 要指到
# 一支真的存在的技能。指到不存在的技能,助理會一路重試一支叫不出來的東西。
# 4. 版本號與來源 — 只印提示,不影響結束碼,理由見下。
#
# 為什麼要這支: 技能組每天在動,手工盤點只會過期。清單缺一列,助理就永遠不知道那支技能
# 存在;清單多一列,助理會去觸發一支不存在的技能,而且失敗不會自動暫停。這兩件事靠眼睛
# 比對每輪都會漏,交給程式判定才穩。
#
# 為什麼版本號落後只算提示: 版本號是 domain 層級的,同一個 domain 改一支技能,其餘技能的
# 版本號也會一起落後、也會被標成要複判。當成稽核缺失的話,每次發版整個 domain 都亮紅,
# 提示很快就會被當成雜訊忽略,真正要複判的那一支反而看不見。
#
# 為什麼 origin=seed 只算提示: 種入的那一批是依既有盤點填的,還沒正式走過決策樹,本來就
# 知道它待複核。它是「已經有結論、但要再確認一次」,不是「漏填」。列成缺失會讓清單從
# 第一天就是紅的,紅到全部複核完為止,這段期間所有真的缺失都會被蓋掉。
#
# 輸出: 缺失一行一個,格式 {清單路徑}:{domain}/{name}:{說明}(stderr);
# 提示同格式(stdout),讓呼叫端分得開缺失與提示;統計摘要走 stderr。
# 結束碼: 0=清單與實際技能一一對應、必填欄位齊全(可能帶提示,提示不影響這一碼)
# 1=缺列、多列、重複列、欄位空著、欄位值不合法,或 next 指到不存在的技能,
# 清單在 stderr
# 2=用法錯誤(本腳本最多吃一個參數)
# 3=找不到 tools/delegate-spec.tsv、推導不出根目錄,或列不出任何技能——
# **什麼都沒查**,不等於通過
set -u
usage() {
echo 'usage: check-delegate.sh [<plugins-root>]' >&2
exit 2
}
[ "$#" -le 1 ] || usage
if [ "$#" -eq 1 ]; then
[ -n "$1" ] || usage
JSC_PLUGINS_ROOT=${1%/}
export JSC_PLUGINS_ROOT
fi
HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
SPEC="$HERE/delegate-spec.tsv"
[ -f "$SPEC" ] || { echo "找不到委派判定清單:$SPEC" >&2; exit 3; }
. "$HERE/plugins-root.sh"
ROOT=$(jsc_plugins_root) || { echo "推導不出技能組工作目錄根位置" >&2; exit 3; }
TMPD=$(mktemp -d) || { echo "無法建立暫存目錄" >&2; exit 3; }
trap 'rm -rf "$TMPD"' EXIT
TAB=$(printf '\t')
# 實際技能清單。真實來源只有 list-skills.sh 一處,本腳本不自己掃 SKILL.md:
# 兩套掃法會各自漂移,屆時分不出是清單錯還是掃法錯。
"$HERE/list-skills.sh" > "$TMPD/raw.txt" 2>/dev/null \
|| { echo "list-skills.sh 列不出技能,先跑 sync-domains.sh:$ROOT" >&2; exit 3; }
cut -f1,2 "$TMPD/raw.txt" | LC_ALL=C sort > "$TMPD/skills.txt"
[ -s "$TMPD/skills.txt" ] || { echo "掃不到任何技能:$ROOT" >&2; exit 3; }
# 各 domain 的現行版本號。domain 名以 plugin.json 的 name 為準,checkout 目錄名只是退路:
# 目錄名是誰 clone 誰決定的,換一台機器就可能叫別的名字。
: > "$TMPD/versions.txt"
for p in "$ROOT"/*/plugin.json; do
[ -f "$p" ] || continue
n=$(sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$p" | head -n1)
v=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$p" | head -n1)
case $n in
jsc-?*) ;;
*) continue ;;
esac
[ -n "$v" ] || continue
printf '%s\t%s\n' "${n#jsc-}" "$v" >> "$TMPD/versions.txt"
done
# 清單資料列:# 開頭的註解與空行都不算。
grep -v '^[[:space:]]*#' "$SPEC" | grep -v '^[[:space:]]*$' > "$TMPD/rows.txt" || true
[ -s "$TMPD/rows.txt" ] || { echo "清單裡一列資料都沒有:$SPEC" >&2; exit 3; }
: > "$TMPD/fail-set.txt"
: > "$TMPD/fail-row.txt"
: > "$TMPD/hint.txt"
report() { # $1=domain/name 或 -,$2=說明
printf '%s:%s:%s\n' "$SPEC" "$1" "$2" >> "$TMPD/fail-set.txt"
}
# --- 1. 一一對應 ---
cut -f1,2 "$TMPD/rows.txt" | LC_ALL=C sort > "$TMPD/keys.txt"
LC_ALL=C uniq -d "$TMPD/keys.txt" > "$TMPD/dup.txt"
LC_ALL=C uniq "$TMPD/keys.txt" > "$TMPD/keys-uniq.txt"
LC_ALL=C comm -23 "$TMPD/skills.txt" "$TMPD/keys-uniq.txt" > "$TMPD/missing.txt"
LC_ALL=C comm -13 "$TMPD/skills.txt" "$TMPD/keys-uniq.txt" > "$TMPD/extra.txt"
while IFS="$TAB" read -r d n; do
[ -n "${d:-}" ] || continue
report "$d/$n" '清單有兩列以上寫同一支技能,只留一列'
done < "$TMPD/dup.txt"
while IFS="$TAB" read -r d n; do
[ -n "${d:-}" ] || continue
report "$d/$n" '這支技能存在,清單缺這一列。沒有判定結果,助理永遠不知道它存在'
done < "$TMPD/missing.txt"
while IFS="$TAB" read -r d n; do
[ -n "${d:-}" ] || continue
report "$d/$n" '清單多這一列,本機沒有這支技能。請刪掉,否則助理會去觸發叫不出來的技能'
done < "$TMPD/extra.txt"
# --- 2~4. 逐列查欄位。多出來的列上面已經報過,這裡跳過,同一個缺陷不印兩遍。 ---
awk -F"$TAB" \
-v SPEC="$SPEC" -v SKILLS="$TMPD/skills.txt" -v VERS="$TMPD/versions.txt" \
-v FAILS="$TMPD/fail-row.txt" -v HINTS="$TMPD/hint.txt" '
function bad(k, m) { printf "%s:%s:%s\n", SPEC, k, m > FAILS }
function hint(k, m) { printf "%s:%s:%s\n", SPEC, k, m > HINTS }
function vlt(a, b, x, y, na, nb, n, i, ai, bi) {
na = split(a, x, "."); nb = split(b, y, ".")
n = (na > nb) ? na : nb
for (i = 1; i <= n; i++) {
ai = (i <= na) ? x[i] + 0 : 0
bi = (i <= nb) ? y[i] + 0 : 0
if (ai < bi) return 1
if (ai > bi) return 0
}
return 0
}
function way_ok(w, t, m, i) {
m = split(w, t, ",")
for (i = 1; i <= m; i++) if (!(t[i] in WAY)) return 0
return (m > 0)
}
function trig_ok(t, e) {
if (t ~ /^at:..*$/) return 1
if (t ~ /^after:..*$/) { e = substr(t, 7); sub(/:.*$/, "", e); return (e in EV) }
return 0
}
BEGIN {
split("full slice cond none", a, " "); for (i in a) VERDICT[a[i]] = 1
split("invoke patrol remind", b, " "); for (i in b) WAY[b[i]] = 1
split("seed judged", c, " "); for (i in c) ORIGIN[c[i]] = 1
split("worklog-written wp-merged stage-entered analyze-completed hook-error session-start session-end", \
d, " "); for (i in d) EV[d[i]] = 1
}
FILENAME == SKILLS { sk[$1 "\t" $2] = 1; next }
FILENAME == VERS { cur[$1] = $2; next }
{
key = $1 "/" $2
if (NF != 11) { bad(key, "這一列有 " NF " 欄,合約規定 11 欄"); next }
if (!(($1 "\t" $2) in sk)) next
verdict = $3; way = $4; slice = $5; human = $6
trig = $7; rec = $8; nxt = $9; ver = $10; org = $11
for (i = 1; i <= 11; i++)
if ($i == "") bad(key, "第 " i " 欄是空的。TSV 沒有空格這種值,不填就寫一個減號")
if (!(verdict in VERDICT)) {
bad(key, "verdict 只認 full、slice、cond、none,實際是「" verdict "」")
next
}
# 不交的那一列只留理由:交出方式、切片、時間點、週期全部要空成減號。
# 留著值等於清單自己在說「不交但這樣交」,下一輪讀的人不知道該信哪一邊。
if (verdict == "none") {
if (way != "-") bad(key, "不交的列,way 要寫 -,實際是「" way "」")
if (slice != "-") bad(key, "不交的列,slice 要寫 -,實際是「" slice "」")
if (trig != "-") bad(key, "不交的列,trigger 要寫 -,實際是「" trig "」")
if (rec != "-") bad(key, "不交的列,recur 要寫 -,實際是「" rec "」")
if (human == "-") bad(key, "不交的列要寫不交的理由,否則下次分不出「判過決定不交」與「還沒判」")
} else {
if (way == "-") bad(key, "交出去的列一定要有交出方式,way 不可以是 -")
else if (!way_ok(way)) bad(key, "way 只認 invoke、patrol、remind,多個用半形逗號隔開,實際是「" way "」")
if (!trig_ok(trig)) bad(key, "trigger 要寫 at:{時間} 或 after:{固定事件名},實際是「" trig "」")
if (rec != "once" && rec !~ /^every:..*$/ && rec !~ /^cron:..*$/)
bad(key, "recur 只認 once、every:{間隔}、cron:{式子},實際是「" rec "」")
}
if (verdict == "full") {
if (slice != "-") bad(key, "全交是整支都交,slice 要寫 -,實際是「" slice "」")
if (human != "-") bad(key, "全交沒有留在人手上的那一半,human 要寫 -,實際是「" human "」")
}
# 切片交與條件式交少了「留在人手上的那一半」,助理下一輪會把整支技能當成可交的一路跑完。
if (verdict == "slice" || verdict == "cond") {
if (slice == "-") bad(key, "交出的那一段沒寫,slice 不可以是 -")
if (human == "-") bad(key, "留在人手上的那一半沒寫,助理下一輪會把整支技能當成可交的一路跑完")
}
if (nxt !~ /^jsc-[a-z0-9-]+:[a-z0-9-]+$/)
bad(key, "next 要寫成 jsc-{domain}:{name},實際是「" nxt "」")
else {
n2 = substr(nxt, 5); sub(/:/, "\t", n2)
if (!(n2 in sk)) bad(key, "next 指到不存在的技能「" nxt "」,助理會一路重試叫不出來的東西")
}
if (!(org in ORIGIN)) bad(key, "origin 只認 seed 與 judged,實際是「" org "」")
else if (org == "seed") hint(key, "origin=seed:依既有盤點種入,還沒走過決策樹,待複核")
if (ver !~ /^[0-9]+(\.[0-9]+)*$/) bad(key, "version 要是 plugin 版本號,實際是「" ver "」")
else if (($1 in cur) && vlt(ver, cur[$1]))
hint(key, "判定時記的版本號 " ver " 落後 jsc-" $1 " 現行的 " cur[$1] ",要複判")
}
' "$TMPD/skills.txt" "$TMPD/versions.txt" "$TMPD/rows.txt"
cat "$TMPD/fail-set.txt" "$TMPD/fail-row.txt" > "$TMPD/fails.txt"
if [ -s "$TMPD/hint.txt" ]; then
LC_ALL=C sort "$TMPD/hint.txt"
fi
rows=$(wc -l < "$TMPD/rows.txt" | tr -d ' ')
skills=$(wc -l < "$TMPD/skills.txt" | tr -d ' ')
hints=$(wc -l < "$TMPD/hint.txt" | tr -d ' ')
if [ -s "$TMPD/fails.txt" ]; then
LC_ALL=C sort "$TMPD/fails.txt" >&2
echo "委派判定清單不符:$SPEC 有 $rows 列,本機有 $skills 支技能,逐項見上方(另有 $hints 則提示,見 stdout)" >&2
exit 1
fi
echo "委派判定清單檢查通過:$SPEC 的 $rows 列對上 $skills 支技能,必填欄位齊全(另有 $hints 則提示,見 stdout)" >&2
exit 0
+67
View File
@@ -0,0 +1,67 @@
# delegate-spec.tsv — jsc 技能組的委派判定清單。一支技能一列,記「這一支能不能交給背景助理」。
#
# 判準本身寫在 references/delegate-criteria.md,四支技能異動技能(skill-new、skill-update、
# skill-delete、skillset-update)共用那一份。這張表只放判定結果,不放判準。
#
# 判定結果只放這裡,不寫進 SKILL.md 的 frontmatter:name 與 description 之外的自訂欄位,
# 有被各 CLI 的技能驗證擋掉的風險。新增或刪除技能時同時補上或刪掉這一列,
# tools/check-delegate.sh 才對得起來;缺列的技能,助理永遠不知道它存在。
#
# 欄位:domain<TAB>name<TAB>verdict<TAB>way<TAB>slice<TAB>human<TAB>trigger<TAB>recur<TAB>next<TAB>version<TAB>origin
# domain 技能所屬 domain,去掉開頭的 jsc-。形狀比照 list-skills.sh 第一欄
# name 技能名。形狀比照 list-skills.sh 第二欄,兩欄合起來就是一支技能的身分
# verdict full=全交 slice=切片交 cond=條件式交 none=不交
# way 交出方式,多個用半形逗號隔開:invoke=觸發 patrol=巡檢 remind=提醒;不交寫 -
# slice 交出的那一段。全交寫 -,整支都交;條件式交要把條件與條件不成立時的行為
# 一起寫進來;不交寫 -
# human 留在人手上的那一半。切片交與條件式交必填——少了它,助理下一輪會把整支技能
# 當成可交的一路跑完。不交填不交的理由,否則下次分不出「判過決定不交」與
# 「還沒判」。全交寫 -
# trigger 第一次什麼時候到期:at:{ISO 時間},立刻要做寫 at:now;或 after:{事件名}。
# 事件名只認固定詞彙:worklog-written、wp-merged、stage-entered、
# analyze-completed、hook-error、session-start、session-end。不交寫 -
# recur 做完之後還要不要再排:once、every:{間隔}、cron:{式子}。事件型 trigger 配
# every:{間隔} 時,間隔讀作重新武裝的最短間隔。不交寫 -
# next 跑完之後建議接哪一支,寫成 jsc-{domain}:{name}。每一列都要填,不交的也要填
# ——不交講的是助理不代跑,跟「跑完之後該接什麼」無關
# version 判定當下該 domain 的 plugin 版本號。落後現行版本代表要複判,那只是提示,
# 不算稽核缺失:版本號是 domain 層級,同 domain 改一支技能其餘技能也會被標到,
# 當成缺失的話每次發版整個 domain 都亮紅,提示很快就被當雜訊忽略
# origin seed=依既有盤點種入、待複核 judged=正式走過決策樹判定。
# seed 只印成待複核提示,不算缺失;技能有異動時就地走一次決策樹,轉成 judged
#
ask ask slice patrol 唯讀查 QUESTION_CONTENTS,確認要交辦的事是不是早就有答案 問答本身。助理在背景問不到人,沒有人在場就收不到答案 at:now every:1d jsc-gitea:wiki 0.1.3 seed
assist assistant none - - 助理本身。讓它自我發動,一輪巡檢會在背景又叫起另一輪,誰都停不下來 - - jsc-log:stats 0.1.6 seed
cli delegate cond invoke 條件是這一項任務唯讀:唯讀巡檢可以委派給別支 CLI,省當前 CLI 的額度。條件不成立,也就是會改檔案的任務,一律不委派;委派失敗就退回自己跑 判斷哪一項算唯讀、額度要不要省,還有委派給哪一支 CLI at:now every:1d jsc-log:stats 0.3.4 seed
cli deploy slice remind 遠端有新版就提醒 安裝、更新、卸除、要求重啟 at:now every:1d jsc-hooks:hooks-install 0.3.4 seed
cli doctor cond invoke 條件式:只有在 doctor 呼叫自家 tools/ 與 templates/ 的路徑不再帶版本號之後才可以交。交出的那一段是定期整輪健檢、寫 CHECK_{HASH}。條件不成立時的行為:一律不交,維持人在現場叫用 修——那是 jsc-cli:setup,逐項確認。另外,條件沒滿足之前整支都留在人手上:doctor 自家腳本走的是 CLI 載入技能時給的外掛基底目錄,那條路徑帶版本號、進不了允許清單,無人值守的每一輪都會無聲卡在第一支腳本 at:now every:7d jsc-cli:setup 0.3.4 seed
cli models slice invoke 定期跑 model-tags.sh sync 重建能力標籤表,並盤點各 CLI 可用模型 換模型、改設定 at:now every:7d jsc-cli:doctor 0.3.4 seed
cli setup none - - 改設定與接線,要逐項確認 - - jsc-cli:doctor 0.3.4 seed
git commit none - - 對外不可逆 - - jsc-git:pr 0.1.5 seed
git pr none - - 對外不可逆 - - jsc-log:worklog 0.1.5 seed
gitea html-export none - - 要人指定是哪一頁或哪一個議題。助理在背景猜不到,猜錯就匯出別人的頁 - - jsc-gitea:html-style 0.2.5 seed
gitea html-style none - - 版型與樣式是使用者的偏好,要逐項確認才寫得下去 - - jsc-gitea:html-export 0.2.5 seed
gitea repo-sync slice patrol 盤點哪些存取庫落後遠端、哪些還沒同步下來 clone 與 update——會動工作目錄 at:now every:1d jsc-git:pr 0.2.5 seed
gitea wiki none - - 助理的手腳,不獨立排程。助理所有 wiki 讀寫都經過它,一律附加 - - jsc-gitea:html-export 0.2.5 seed
gitea wiki-to-issue none - - 對外不可逆 - - jsc-sdlc:analyze 0.2.5 seed
hooks hooks-install slice patrol wire-cli.sh status 唯讀盤點接線 重新接線 at:now every:1d jsc-hooks:repair 0.4.4 seed
hooks repair slice invoke 巡檢抓到 hook 錯誤就發動修復 診斷、改哪一支、開 PR,全照 repair 自己的流程 after:hook-error every:1h jsc-git:pr 0.4.4 seed
log learn slice patrol 發動技能前先查過去教訓,也就是 consult 那一段 記錄教訓的判斷。哪一次值得留下來要人說 at:now every:1d jsc-log:worklog 0.1.9 seed
log report slice invoke 週期到了就產週報、月報、年報 報告要不要改寫、要不要送人看 at:now every:7d jsc-log:learn 0.1.9 seed
log stats full invoke - - at:now every:7d jsc-log:report 0.1.9 seed
log worklog slice patrol,remind 任務結束時收口計時與 token,補進 worklog-pending;該寫沒寫就催 寫日誌本體——狀態、細節、難處要人給 after:session-end every:1h jsc-log:learn 0.1.9 seed
meta skill-check cond invoke 條件是只交機械檢核那一段:腳本語法、manifest 版本一致、README 技能清單與實際技能對得上。條件不成立的那一段,也就是語意審查與流程效率判斷,一律不交,那要讀完整份 SKILL.md 語意審查、流程與成本效率判斷,還有要不要套用建議 at:now every:7d jsc-meta:skill-update 0.3.1 seed
meta skill-delete none - - 改技能組本身,等於助理改自己 - - jsc-meta:skill-check 0.3.1 seed
meta skill-new none - - 改技能組本身,等於助理改自己 - - jsc-meta:skill-check 0.3.1 seed
meta skill-update none - - 改技能組本身,等於助理改自己 - - jsc-meta:skill-check 0.3.1 seed
meta skillset-update none - - 改技能組本身,等於助理改自己 - - jsc-meta:skill-check 0.3.1 seed
meta ste100-sync slice patrol,remind 定期比對上游版本,落後就提醒 套用上游變更 at:now every:7d jsc-meta:skill-check 0.3.1 seed
meta tooling-guide full invoke - - at:now every:7d jsc-meta:skill-check 0.3.1 seed
pkg pkg-update slice patrol 用 list-packages.sh、latest-version.sh 唯讀盤點落後最新穩定版的套件 升版、跑建置與測試 at:now every:7d jsc-review:code-review 0.1.0 seed
review api-doc none - - 審查要判斷,判準要讀完整份文件與程式碼;助理在背景判不出來 - - jsc-git:pr 0.1.3 seed
review code-review none - - 審查要判斷,而且要不要照著改由呼叫端決定 - - jsc-review:api-doc 0.1.3 seed
review comment-cleanup none - - 會改專案檔案 - - jsc-git:commit 0.1.3 seed
sdlc analyze slice patrol,remind 盤點 ANALYZE_CONTENTS 未完成的分析並先把選項清單備好;另巡檢分析頁勾選與工作包議題狀態對不對得上 分析本體全部要決策。勾選與議題對不上時要對齊哪一邊,是真實來源衝突,也要人判 at:now every:1d jsc-sdlc:implement 0.3.2 seed
sdlc implement slice patrol,remind wp-gate.sh check-deps 盤點哪些工作包可以開始;階段鎖殘留就提醒 挑工作包、寫程式碼、開 PR。鎖檔不自己刪 at:now every:1d jsc-log:worklog 0.3.2 seed
sdlc maintain none - - 核心是決策與寫程式碼 - - jsc-log:worklog 0.3.2 seed
sdlc plan slice patrol,remind 盤點 PLAN_CONTENTS 還沒分析的計畫,先把選項清單備好 規劃本體全部要決策 at:now every:1d jsc-sdlc:analyze 0.3.2 seed
1 # delegate-spec.tsv — jsc 技能組的委派判定清單。一支技能一列,記「這一支能不能交給背景助理」。
2 #
3 # 判準本身寫在 references/delegate-criteria.md,四支技能異動技能(skill-new、skill-update、
4 # skill-delete、skillset-update)共用那一份。這張表只放判定結果,不放判準。
5 #
6 # 判定結果只放這裡,不寫進 SKILL.md 的 frontmatter:name 與 description 之外的自訂欄位,
7 # 有被各 CLI 的技能驗證擋掉的風險。新增或刪除技能時同時補上或刪掉這一列,
8 # tools/check-delegate.sh 才對得起來;缺列的技能,助理永遠不知道它存在。
9 #
10 # 欄位:domain<TAB>name<TAB>verdict<TAB>way<TAB>slice<TAB>human<TAB>trigger<TAB>recur<TAB>next<TAB>version<TAB>origin
11 # domain 技能所屬 domain,去掉開頭的 jsc-。形狀比照 list-skills.sh 第一欄
12 # name 技能名。形狀比照 list-skills.sh 第二欄,兩欄合起來就是一支技能的身分
13 # verdict full=全交 slice=切片交 cond=條件式交 none=不交
14 # way 交出方式,多個用半形逗號隔開:invoke=觸發 patrol=巡檢 remind=提醒;不交寫 -
15 # slice 交出的那一段。全交寫 -,整支都交;條件式交要把條件與條件不成立時的行為
16 # 一起寫進來;不交寫 -
17 # human 留在人手上的那一半。切片交與條件式交必填——少了它,助理下一輪會把整支技能
18 # 當成可交的一路跑完。不交填不交的理由,否則下次分不出「判過決定不交」與
19 # 「還沒判」。全交寫 -
20 # trigger 第一次什麼時候到期:at:{ISO 時間},立刻要做寫 at:now;或 after:{事件名}。
21 # 事件名只認固定詞彙:worklog-written、wp-merged、stage-entered、
22 # analyze-completed、hook-error、session-start、session-end。不交寫 -
23 # recur 做完之後還要不要再排:once、every:{間隔}、cron:{式子}。事件型 trigger 配
24 # every:{間隔} 時,間隔讀作重新武裝的最短間隔。不交寫 -
25 # next 跑完之後建議接哪一支,寫成 jsc-{domain}:{name}。每一列都要填,不交的也要填
26 # ——不交講的是助理不代跑,跟「跑完之後該接什麼」無關
27 # version 判定當下該 domain 的 plugin 版本號。落後現行版本代表要複判,那只是提示,
28 # 不算稽核缺失:版本號是 domain 層級,同 domain 改一支技能其餘技能也會被標到,
29 # 當成缺失的話每次發版整個 domain 都亮紅,提示很快就被當雜訊忽略
30 # origin seed=依既有盤點種入、待複核 judged=正式走過決策樹判定。
31 # seed 只印成待複核提示,不算缺失;技能有異動時就地走一次決策樹,轉成 judged
32 #
33 ask ask slice patrol 唯讀查 QUESTION_CONTENTS,確認要交辦的事是不是早就有答案 問答本身。助理在背景問不到人,沒有人在場就收不到答案 at:now every:1d jsc-gitea:wiki 0.1.3 seed
34 assist assistant none - - 助理本身。讓它自我發動,一輪巡檢會在背景又叫起另一輪,誰都停不下來 - - jsc-log:stats 0.1.6 seed
35 cli delegate cond invoke 條件是這一項任務唯讀:唯讀巡檢可以委派給別支 CLI,省當前 CLI 的額度。條件不成立,也就是會改檔案的任務,一律不委派;委派失敗就退回自己跑 判斷哪一項算唯讀、額度要不要省,還有委派給哪一支 CLI at:now every:1d jsc-log:stats 0.3.4 seed
36 cli deploy slice remind 遠端有新版就提醒 安裝、更新、卸除、要求重啟 at:now every:1d jsc-hooks:hooks-install 0.3.4 seed
37 cli doctor cond invoke 條件式:只有在 doctor 呼叫自家 tools/ 與 templates/ 的路徑不再帶版本號之後才可以交。交出的那一段是定期整輪健檢、寫 CHECK_{HASH}。條件不成立時的行為:一律不交,維持人在現場叫用 修——那是 jsc-cli:setup,逐項確認。另外,條件沒滿足之前整支都留在人手上:doctor 自家腳本走的是 CLI 載入技能時給的外掛基底目錄,那條路徑帶版本號、進不了允許清單,無人值守的每一輪都會無聲卡在第一支腳本 at:now every:7d jsc-cli:setup 0.3.4 seed
38 cli models slice invoke 定期跑 model-tags.sh sync 重建能力標籤表,並盤點各 CLI 可用模型 換模型、改設定 at:now every:7d jsc-cli:doctor 0.3.4 seed
39 cli setup none - - 改設定與接線,要逐項確認 - - jsc-cli:doctor 0.3.4 seed
40 git commit none - - 對外不可逆 - - jsc-git:pr 0.1.5 seed
41 git pr none - - 對外不可逆 - - jsc-log:worklog 0.1.5 seed
42 gitea html-export none - - 要人指定是哪一頁或哪一個議題。助理在背景猜不到,猜錯就匯出別人的頁 - - jsc-gitea:html-style 0.2.5 seed
43 gitea html-style none - - 版型與樣式是使用者的偏好,要逐項確認才寫得下去 - - jsc-gitea:html-export 0.2.5 seed
44 gitea repo-sync slice patrol 盤點哪些存取庫落後遠端、哪些還沒同步下來 clone 與 update——會動工作目錄 at:now every:1d jsc-git:pr 0.2.5 seed
45 gitea wiki none - - 助理的手腳,不獨立排程。助理所有 wiki 讀寫都經過它,一律附加 - - jsc-gitea:html-export 0.2.5 seed
46 gitea wiki-to-issue none - - 對外不可逆 - - jsc-sdlc:analyze 0.2.5 seed
47 hooks hooks-install slice patrol wire-cli.sh status 唯讀盤點接線 重新接線 at:now every:1d jsc-hooks:repair 0.4.4 seed
48 hooks repair slice invoke 巡檢抓到 hook 錯誤就發動修復 診斷、改哪一支、開 PR,全照 repair 自己的流程 after:hook-error every:1h jsc-git:pr 0.4.4 seed
49 log learn slice patrol 發動技能前先查過去教訓,也就是 consult 那一段 記錄教訓的判斷。哪一次值得留下來要人說 at:now every:1d jsc-log:worklog 0.1.9 seed
50 log report slice invoke 週期到了就產週報、月報、年報 報告要不要改寫、要不要送人看 at:now every:7d jsc-log:learn 0.1.9 seed
51 log stats full invoke - - at:now every:7d jsc-log:report 0.1.9 seed
52 log worklog slice patrol,remind 任務結束時收口計時與 token,補進 worklog-pending;該寫沒寫就催 寫日誌本體——狀態、細節、難處要人給 after:session-end every:1h jsc-log:learn 0.1.9 seed
53 meta skill-check cond invoke 條件是只交機械檢核那一段:腳本語法、manifest 版本一致、README 技能清單與實際技能對得上。條件不成立的那一段,也就是語意審查與流程效率判斷,一律不交,那要讀完整份 SKILL.md 語意審查、流程與成本效率判斷,還有要不要套用建議 at:now every:7d jsc-meta:skill-update 0.3.1 seed
54 meta skill-delete none - - 改技能組本身,等於助理改自己 - - jsc-meta:skill-check 0.3.1 seed
55 meta skill-new none - - 改技能組本身,等於助理改自己 - - jsc-meta:skill-check 0.3.1 seed
56 meta skill-update none - - 改技能組本身,等於助理改自己 - - jsc-meta:skill-check 0.3.1 seed
57 meta skillset-update none - - 改技能組本身,等於助理改自己 - - jsc-meta:skill-check 0.3.1 seed
58 meta ste100-sync slice patrol,remind 定期比對上游版本,落後就提醒 套用上游變更 at:now every:7d jsc-meta:skill-check 0.3.1 seed
59 meta tooling-guide full invoke - - at:now every:7d jsc-meta:skill-check 0.3.1 seed
60 pkg pkg-update slice patrol 用 list-packages.sh、latest-version.sh 唯讀盤點落後最新穩定版的套件 升版、跑建置與測試 at:now every:7d jsc-review:code-review 0.1.0 seed
61 review api-doc none - - 審查要判斷,判準要讀完整份文件與程式碼;助理在背景判不出來 - - jsc-git:pr 0.1.3 seed
62 review code-review none - - 審查要判斷,而且要不要照著改由呼叫端決定 - - jsc-review:api-doc 0.1.3 seed
63 review comment-cleanup none - - 會改專案檔案 - - jsc-git:commit 0.1.3 seed
64 sdlc analyze slice patrol,remind 盤點 ANALYZE_CONTENTS 未完成的分析並先把選項清單備好;另巡檢分析頁勾選與工作包議題狀態對不對得上 分析本體全部要決策。勾選與議題對不上時要對齊哪一邊,是真實來源衝突,也要人判 at:now every:1d jsc-sdlc:implement 0.3.2 seed
65 sdlc implement slice patrol,remind wp-gate.sh check-deps 盤點哪些工作包可以開始;階段鎖殘留就提醒 挑工作包、寫程式碼、開 PR。鎖檔不自己刪 at:now every:1d jsc-log:worklog 0.3.2 seed
66 sdlc maintain none - - 核心是決策與寫程式碼 - - jsc-log:worklog 0.3.2 seed
67 sdlc plan slice patrol,remind 盤點 PLAN_CONTENTS 還沒分析的計畫,先把選項清單備好 規劃本體全部要決策 at:now every:1d jsc-sdlc:analyze 0.3.2 seed