Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
926936cd88 | ||
|
|
b17941248e |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-cli",
|
||||
"version": "0.2.4",
|
||||
"version": "0.2.3",
|
||||
"description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署",
|
||||
"skills": "./skills",
|
||||
"author": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-cli",
|
||||
"version": "0.2.4",
|
||||
"version": "0.2.3",
|
||||
"description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署",
|
||||
"skills": "./skills",
|
||||
"jsc": {
|
||||
|
||||
@@ -23,7 +23,7 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安
|
||||
| 工具 | 用途 |
|
||||
| --- | --- |
|
||||
| `tools/detect-clis.sh` | 列出已安裝的 AI CLI 與執行檔路徑(TSV:name / path / version;antigravity 的執行檔為 `agy`、kiro 為 `kiro-cli`) |
|
||||
| `tools/test-clis.sh` | 實際呼叫已偵測到的 AI CLI,跑版本、說明頁、plugin 清單、doctor skill 載入與 hook smoke(`test-clis.sh [cli...]`);每列標出 `cli`、`skill`、`hook` 類型、結束碼、判定與輸出摘要,最後一行 `summary` 標出通過、降級、失敗、略過數。`JSC_CLI_TEST_TIMEOUT` 可調整單項命令逾時秒數,預設 10 秒 |
|
||||
| `tools/test-clis.sh` | 實際呼叫已偵測到的 AI CLI,跑版本、說明頁與 plugin 清單等唯讀命令(`test-clis.sh [cli...]`);印出每項命令、結束碼、判定與輸出摘要,最後一行 `summary` 標出通過、降級、失敗、略過數。`JSC_CLI_TEST_TIMEOUT` 可調整單項命令逾時秒數,預設 10 秒 |
|
||||
| `tools/deploy.sh` | 對單一 CLI 執行安裝、更新或解除安裝(`deploy.sh [-n] {mode} {cli} {domain}...`,mode 為 install / update / uninstall);印出每個指令與其結束碼,最後一行 `result` 標 ok 或 fail。`-n` 只印指令不執行。上表五個 CLI 的指令差異全部收在這支腳本裡。install 或 update 全數成功時,收尾轉呼叫 `jsc-hooks` 的 `restart-gate.sh require` 掛上重啟閘門,並印一行 `restart` 標出狀態檔位置;uninstall 不寫。尋找 `restart-gate.sh` 時優先用 `$JSC_HOME/current/jsc-hooks`、本地 clone 與 Kiro skills,最後才掃各 CLI 快取,避免部署收尾綁死單一 CLI 的版號路徑。狀態檔的路徑、格式與判讀全在 `restart-gate.sh`,這支腳本不自己拼——格式只留一個真實來源。站台取自 `GITEA_HOST`,本地 clone 目錄取自 `JSC_LOCAL_PLUGINS`,兩者的預設值見下表 |
|
||||
| `tools/check-requires.sh` | `check-requires.sh {cli} {manifest}` 檢查 manifest 的 `jsc.requires` 最低版本。沒有宣告就通過;版本不符或缺相依 plugin 就回 `status=blocked`。`deploy.sh update` 在每個 domain 更新前呼叫它,不符就跳過該 domain 並列出原因 |
|
||||
| `tools/write-guides.sh` | 產生這台機器專屬的更新指引 `$JSC_HOME/update-guide.md` 與移除指引 `$JSC_HOME/remove-guide.md`(`write-guides.sh [-n] {install\|update} {domain}...`),一輪部署跑一次。CLI 清單取自 `detect-clis.sh`,每支 CLI 的指令字面直接取自 `deploy.sh -n` 的輸出,所以指引寫的就是實際會跑的指令;kiro 走不走本地複製退路也依實際偵測結果標注 |
|
||||
@@ -54,7 +54,7 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安
|
||||
|
||||
### `doctor`
|
||||
|
||||
一次體檢執行環境,只讀不改。五項檢查:技能版本(`jsc-hooks/hooks/version-guard.sh report`)、Hook 接線(`jsc-hooks/tools/wire-cli.sh status`,唯讀子命令)、CLI、skill、hook 實測(`tools/test-clis.sh` 實際呼叫版本、說明頁、plugin 清單、doctor skill 載入與 hook smoke)、全域設定與自我設定(`tools/scan-config.sh` 比對 `tools/config-spec.tsv`)。每項各出一張表,整份結果寫進 wiki `CHECK_{HASH}`,`HASH` 取 `{主機名}/{登入帳號}`,只保留最新一次。修復交給 `/jsc-cli:setup`,體檢本身不動任何設定。
|
||||
一次體檢執行環境,只讀不改。五項檢查:技能版本(`jsc-hooks/hooks/version-guard.sh report`)、Hook 接線(`jsc-hooks/tools/wire-cli.sh status`,唯讀子命令)、CLI 實測(`tools/test-clis.sh` 實際呼叫版本、說明頁與 plugin 清單)、全域設定與自我設定(`tools/scan-config.sh` 比對 `tools/config-spec.tsv`)。每項各出一張表,整份結果寫進 wiki `CHECK_{HASH}`,`HASH` 取 `{主機名}/{登入帳號}`,只保留最新一次。修復交給 `/jsc-cli:setup`,體檢本身不動任何設定。
|
||||
|
||||
### `setup`
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-cli",
|
||||
"version": "0.2.4",
|
||||
"version": "0.2.3",
|
||||
"description": "CLI 偵測、模型能力標籤、子代理派工與技能庫批次部署",
|
||||
"skills": "./skills/",
|
||||
"jsc": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: doctor
|
||||
description: Health-check the execution environment in one pass and record the result, changing nothing. Five checks - plugin versions from jsc-hooks/hooks/version-guard.sh report, hook wiring from jsc-hooks/tools/wire-cli.sh status, CLI, skill and hook runtime tests from tools/test-clis.sh, global settings and current-directory settings from tools/scan-config.sh against tools/config-spec.tsv. Report one findings table per check, then write the whole run to wiki CHECK_{HASH}; use for checkups, not fixes.
|
||||
description: Health-check the execution environment in one pass and record the result, changing nothing. Five checks - plugin versions from jsc-hooks/hooks/version-guard.sh report, hook wiring from jsc-hooks/tools/wire-cli.sh status, executable CLI tests from tools/test-clis.sh, global settings and current-directory settings from tools/scan-config.sh against tools/config-spec.tsv. Report one findings table per check, then write the whole run to wiki CHECK_{HASH} where HASH comes from {hostname}/{user}; the page keeps only the latest run. Use after installing or updating the skill set, when a skill fails on a settings, wiring or CLI runtime problem, or before handing a machine over; not for applying fixes, which is jsc-cli:setup.
|
||||
---
|
||||
|
||||
# doctor - execution environment health check
|
||||
@@ -29,20 +29,18 @@ Done when every detected CLI has a status and its missing items are listed.
|
||||
|
||||
## 3. CLI runtime tests
|
||||
|
||||
Run `tools/test-clis.sh` with no CLI arguments. It calls `tools/detect-clis.sh`, then runs real commands for every detected CLI. It covers three areas: CLI commands, skill loading, and hook runtime smoke.
|
||||
Run `tools/test-clis.sh` with no CLI arguments. It calls `tools/detect-clis.sh`, then runs real read-only commands for every detected CLI.
|
||||
|
||||
Output:
|
||||
|
||||
- `test<TAB>{area}<TAB>{cli}<TAB>{test}<TAB>{command}<TAB>{exit-code}<TAB>{verdict}<TAB>{detail}`
|
||||
- `test<TAB>{cli}<TAB>{test}<TAB>{command}<TAB>{exit-code}<TAB>{verdict}<TAB>{detail}`
|
||||
- `summary<TAB>{ok}<TAB>{warn}<TAB>{fail}<TAB>{skipped}`
|
||||
|
||||
Areas: `cli`, `skill`, `hook`.
|
||||
|
||||
Verdicts: `ok`, `warn`, `fail`, `skipped`.
|
||||
|
||||
Exit codes: 0 completed, 2 usage error, 3 missing `detect-clis.sh`. Any other script exit code is itself a doctor finding.
|
||||
|
||||
Treat every `fail` as a machine problem, including `skill` and `hook` rows. Treat `warn` as degraded capability: name it in the report, but do not put it in the fix table unless the failing skill needs that feature. Treat `skipped` as no conclusion. Map the report labels to the template as `ok` -> `通過`, `warn` -> `降級`, `fail` -> `失敗`, and `skipped` -> `略過`.
|
||||
Treat `fail` as a machine problem. Treat `warn` as degraded capability: name it in the report, but do not put it in the fix table unless the failing skill needs that feature. Treat `skipped` as no conclusion. Map the report labels to the template as `ok` -> `通過`, `warn` -> `降級`, `fail` -> `失敗`, and `skipped` -> `略過`.
|
||||
|
||||
Done when every detected CLI has at least a version test row and the summary line is read.
|
||||
|
||||
@@ -72,7 +70,7 @@ Done when the scanned directory is stated and every project row has a verdict.
|
||||
|
||||
## 6. Report and record
|
||||
|
||||
Report all five tables per `templates/check-page.md`. Then build the `待修項目` table from every `missing`, `invalid`, `unwired` and runtime `fail` item, plus every domain reported `落後`. Order them `missing` -> `invalid` -> `unwired` -> `runtime-fail` -> `落後`. Nothing wrong -> one row reading `無`.
|
||||
Report all five tables per `templates/check-page.md`. Then build the `待修項目` table from every `missing`, `invalid`, `unwired` and CLI runtime `fail` item, plus every domain reported `落後`. Order them `missing` -> `invalid` -> `unwired` -> `runtime-fail` -> `落後`. Nothing wrong -> one row reading `無`.
|
||||
|
||||
Write the page through `jsc-gitea:wiki`:
|
||||
|
||||
@@ -87,6 +85,6 @@ Done when either the wiki page URL is reported, or the skipped write is reported
|
||||
|
||||
## 7. Hand off
|
||||
|
||||
State the counts: required items missing, settings invalid, CLIs unwired, runtime failures grouped by `cli`, `skill` and `hook`, and domains behind. Recommend `/jsc-cli:setup` when any of those is above zero. Never fix anything here.
|
||||
State the counts: required items missing, settings invalid, CLIs unwired, CLI runtime failures, domains behind. Recommend `/jsc-cli:setup` when any of those is above zero. Never fix anything here.
|
||||
|
||||
Done when the counts are stated and the recommendation is given or explicitly withheld.
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
|
||||
## CLI 實測
|
||||
|
||||
| 類型 | CLI | 測試 | 指令 | 結束碼 | 判定 | 說明 |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| {cli、skill、hook} | {cli} | {version、help、plugin-list、doctor-skill、hook-smoke} | {實際命令或檔案} | {結束碼} | {通過、降級、失敗、略過} | {輸出摘要或錯誤原因} |
|
||||
| CLI | 測試 | 指令 | 結束碼 | 判定 | 說明 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| {cli} | {version、help、plugin-list} | {實際命令} | {結束碼} | {通過、降級、失敗、略過} | {輸出摘要或錯誤原因} |
|
||||
|
||||
## 全域設定
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
| 順序 | 項目 | 範圍 | 判定 | 修法 | 影響 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| {n} | {變數、檔案、hook、CLI 測試、skill 測試或 domain} | {全域、自我、CLI、skill、hook} | {缺漏、設錯、未接線、實測失敗、落後} | {自動、詢問、手動} | {不修的話哪些技能跑不動} |
|
||||
| {n} | {變數、檔案、hook、CLI 測試或 domain} | {全域、自我、CLI} | {缺漏、設錯、未接線、實測失敗、落後} | {自動、詢問、手動} | {不修的話哪些技能跑不動} |
|
||||
|
||||
## 未登錄變數
|
||||
|
||||
|
||||
+24
-94
@@ -3,7 +3,7 @@
|
||||
# 用法:
|
||||
# test-clis.sh [cli...]
|
||||
# 輸出(TSV):
|
||||
# test<TAB>{area}<TAB>{cli}<TAB>{test}<TAB>{指令}<TAB>{結束碼}<TAB>{判定}<TAB>{說明}
|
||||
# test<TAB>{cli}<TAB>{test}<TAB>{指令}<TAB>{結束碼}<TAB>{判定}<TAB>{說明}
|
||||
# summary<TAB>{ok}<TAB>{warn}<TAB>{fail}<TAB>{skipped}
|
||||
# 判定:
|
||||
# ok 實際命令成功
|
||||
@@ -37,9 +37,9 @@ cli_bin() {
|
||||
esac
|
||||
}
|
||||
|
||||
emit() { # area cli test command code verdict detail
|
||||
printf 'test\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "$1" "$2" "$3" "$4" "$5" "$6" "$7"
|
||||
case "$6" in
|
||||
emit() { # cli test command code verdict detail
|
||||
printf 'test\t%s\t%s\t%s\t%s\t%s\t%s\n' "$1" "$2" "$3" "$4" "$5" "$6"
|
||||
case "$5" in
|
||||
ok) ok_count=$((ok_count + 1)) ;;
|
||||
warn) warn_count=$((warn_count + 1)) ;;
|
||||
fail) fail_count=$((fail_count + 1)) ;;
|
||||
@@ -63,9 +63,7 @@ run_capture() { # $@=command
|
||||
return 0
|
||||
}
|
||||
|
||||
run_required() { # area cli test command...
|
||||
area=$1
|
||||
shift
|
||||
run_required() { # cli test command...
|
||||
cli=$1
|
||||
test_name=$2
|
||||
shift 2
|
||||
@@ -74,17 +72,15 @@ run_required() { # area cli test command...
|
||||
code=$RUN_CODE
|
||||
detail=$RUN_TEXT
|
||||
if [ "$code" -eq 0 ]; then
|
||||
emit "$area" "$cli" "$test_name" "$cmd_text" "$code" ok "$detail"
|
||||
emit "$cli" "$test_name" "$cmd_text" "$code" ok "$detail"
|
||||
elif [ "$code" -eq 124 ]; then
|
||||
emit "$area" "$cli" "$test_name" "$cmd_text" "$code" fail "命令逾時(${TIMEOUT_SECONDS} 秒)"
|
||||
emit "$cli" "$test_name" "$cmd_text" "$code" fail "命令逾時(${TIMEOUT_SECONDS} 秒)"
|
||||
else
|
||||
emit "$area" "$cli" "$test_name" "$cmd_text" "$code" fail "$detail"
|
||||
emit "$cli" "$test_name" "$cmd_text" "$code" fail "$detail"
|
||||
fi
|
||||
}
|
||||
|
||||
run_optional() { # area cli test command...
|
||||
area=$1
|
||||
shift
|
||||
run_optional() { # cli test command...
|
||||
cli=$1
|
||||
test_name=$2
|
||||
shift 2
|
||||
@@ -93,11 +89,11 @@ run_optional() { # area cli test command...
|
||||
code=$RUN_CODE
|
||||
detail=$RUN_TEXT
|
||||
if [ "$code" -eq 0 ]; then
|
||||
emit "$area" "$cli" "$test_name" "$cmd_text" "$code" ok "$detail"
|
||||
emit "$cli" "$test_name" "$cmd_text" "$code" ok "$detail"
|
||||
elif [ "$code" -eq 124 ]; then
|
||||
emit "$area" "$cli" "$test_name" "$cmd_text" "$code" fail "命令逾時(${TIMEOUT_SECONDS} 秒)"
|
||||
emit "$cli" "$test_name" "$cmd_text" "$code" fail "命令逾時(${TIMEOUT_SECONDS} 秒)"
|
||||
else
|
||||
emit "$area" "$cli" "$test_name" "$cmd_text" "$code" warn "$detail"
|
||||
emit "$cli" "$test_name" "$cmd_text" "$code" warn "$detail"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -106,98 +102,32 @@ has_cli() {
|
||||
"$DETECT" | awk -F '\t' -v name="$name" '$1 == name { found = 1 } END { exit found ? 0 : 1 }'
|
||||
}
|
||||
|
||||
latest_dir() {
|
||||
for pat in "$@"; do
|
||||
# shellcheck disable=SC2086
|
||||
ls -d $pat 2>/dev/null | sort | tail -n1
|
||||
done | tail -n1
|
||||
}
|
||||
|
||||
claude_plugin_root() {
|
||||
reg="$HOME/.claude/plugins/installed_plugins.json"
|
||||
[ -f "$reg" ] || return 1
|
||||
tr -d '\n' < "$reg" \
|
||||
| sed -n 's/.*"jsc-cli@jsc"[[:space:]]*:[[:space:]]*\[[^]]*"installPath"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
|
||||
| head -n1
|
||||
}
|
||||
|
||||
skill_root() {
|
||||
case "$1" in
|
||||
claude) claude_plugin_root ;;
|
||||
codex) latest_dir "$HOME/.codex/plugins/cache/jsc/jsc-cli"/* ;;
|
||||
copilot) printf '%s\n' "$HOME/.copilot/installed-plugins/jsc/jsc-cli" ;;
|
||||
antigravity) latest_dir "$HOME/.antigravity"/*/jsc-cli "$HOME/.config/antigravity"/*/jsc-cli ;;
|
||||
kiro) printf '%s\n' "$HOME/.kiro/skills/jsc-cli" ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
skill_file() {
|
||||
root=$(skill_root "$1" 2>/dev/null || true)
|
||||
[ -n "$root" ] || return 1
|
||||
for f in "$root/skills/doctor/SKILL.md" "$root/doctor/SKILL.md"; do
|
||||
[ -f "$f" ] && { printf '%s\n' "$f"; return 0; }
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
hooks_wire() {
|
||||
if [ -n "${JSC_HOOKS_TOOLS:-}" ] && [ -f "$JSC_HOOKS_TOOLS/wire-cli.sh" ]; then
|
||||
printf '%s\n' "$JSC_HOOKS_TOOLS/wire-cli.sh"
|
||||
return 0
|
||||
fi
|
||||
for f in "$HERE/../../hooks/tools/wire-cli.sh" "$HOME/.codex/plugins/cache/jsc/jsc-hooks"/*/tools/wire-cli.sh "$HOME/.claude/plugins/cache/jsc/jsc-hooks"/*/tools/wire-cli.sh "$HOME/.copilot/installed-plugins/jsc/jsc-hooks/tools/wire-cli.sh"; do
|
||||
[ -f "$f" ] && { printf '%s\n' "$f"; return 0; }
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
test_skill() {
|
||||
cli=$1
|
||||
if f=$(skill_file "$cli" 2>/dev/null); then
|
||||
emit skill "$cli" doctor-skill "$f" 0 ok "找到 doctor SKILL.md"
|
||||
else
|
||||
emit skill "$cli" doctor-skill "jsc-cli doctor skill" "-" fail "找不到已安裝的 doctor SKILL.md"
|
||||
fi
|
||||
}
|
||||
|
||||
test_hooks() {
|
||||
cli=$1
|
||||
if wire=$(hooks_wire 2>/dev/null); then
|
||||
run_required hook "$cli" hook-smoke sh "$wire" smoke "$cli"
|
||||
else
|
||||
emit hook "$cli" hook-smoke "wire-cli.sh smoke $cli" "-" skipped "找不到 wire-cli.sh"
|
||||
fi
|
||||
}
|
||||
|
||||
test_one() {
|
||||
cli=$1
|
||||
bin=$(cli_bin "$cli") || usage
|
||||
path=$(command -v "$bin" 2>/dev/null || true)
|
||||
if [ -z "$path" ]; then
|
||||
emit cli "$cli" executable "$bin" "-" skipped "未偵測到執行檔"
|
||||
emit "$cli" executable "$bin" "-" skipped "未偵測到執行檔"
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "$cli" in
|
||||
antigravity)
|
||||
run_required cli "$cli" version "$path" --version
|
||||
run_optional cli "$cli" help "$path" --help
|
||||
run_required cli "$cli" plugin-list "$path" plugin list
|
||||
run_required "$cli" version "$path" --version
|
||||
run_optional "$cli" help "$path" --help
|
||||
run_required "$cli" plugin-list "$path" plugin list
|
||||
;;
|
||||
kiro)
|
||||
run_required cli "$cli" version "$path" --version
|
||||
run_optional cli "$cli" help "$path" --help-all
|
||||
run_optional cli "$cli" plugin-list "$path" plugin list
|
||||
run_required "$cli" version "$path" --version
|
||||
run_optional "$cli" help "$path" --help-all
|
||||
run_optional "$cli" plugin-list "$path" plugin list
|
||||
;;
|
||||
*)
|
||||
run_required cli "$cli" version "$path" --version
|
||||
run_optional cli "$cli" help "$path" --help
|
||||
run_required cli "$cli" plugin-list "$path" plugin list
|
||||
run_required "$cli" version "$path" --version
|
||||
run_optional "$cli" help "$path" --help
|
||||
run_required "$cli" plugin-list "$path" plugin list
|
||||
;;
|
||||
esac
|
||||
test_skill "$cli"
|
||||
test_hooks "$cli"
|
||||
}
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
@@ -205,7 +135,7 @@ if [ "$#" -eq 0 ]; then
|
||||
fi
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
emit cli all executable "-" "-" skipped "未偵測到任何支援的 CLI"
|
||||
emit all executable "-" "-" skipped "未偵測到任何支援的 CLI"
|
||||
printf 'summary\t%s\t%s\t%s\t%s\n' "$ok_count" "$warn_count" "$fail_count" "$skipped_count"
|
||||
exit 0
|
||||
fi
|
||||
@@ -217,7 +147,7 @@ for cli in "$@"; do
|
||||
test_one "$cli"
|
||||
else
|
||||
bin=$(cli_bin "$cli") || usage
|
||||
emit cli "$cli" executable "$bin" "-" skipped "未偵測到執行檔"
|
||||
emit "$cli" executable "$bin" "-" skipped "未偵測到執行檔"
|
||||
fi
|
||||
;;
|
||||
*) usage ;;
|
||||
|
||||
Reference in New Issue
Block a user