diff --git a/README.md b/README.md index eb2099e..f5063df 100644 --- a/README.md +++ b/README.md @@ -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/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`,這支腳本不自己拼——格式只留一個真實來源。站台取自 `GITEA_HOST`,本地 clone 目錄取自 `JSC_LOCAL_PLUGINS`,兩者的預設值見下表 | +| `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/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 走不走本地複製退路也依實際偵測結果標注 | | `tools/list-models.sh` | 讀各 CLI 設定檔列出模型(TSV:cli / model / in-use);設定檔缺失就不輸出該 CLI 的列,一律 exit 0。設定檔位置只寫在這支腳本裡 | | `tools/model-config.sh` | 解析 SDLC 各階段的偏好模型鏈(`get {stage}`、`list`、`resolve {stage}` 印出目前 CLI 可用的第一個模型);專案 `.jsc/models` 優先於 `$JSC_HOME/models.conf`,格式見 `references/model-tags.md`。鏈只影響建議與偏好順序,不影響閘門放行 | @@ -48,7 +48,7 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安 ### `deploy` -技能庫批次安裝、更新、解除安裝:偵測 CLI → **先比對各 plugin 的本機與已發佈版本並列表,只要有任一個落後就把「更新」設為推薦選項** → 決策樹選模式 → 每個 CLI 一個 sub agent 呼叫 `tools/deploy.sh` 執行原生 plugin 指令(統一 marketplace `jsc`,token `jsc-{domain}@jsc`)。domain 名單動態取自 `plugins/meta` 的 marketplace.json,不硬編碼。 +技能庫批次安裝、更新、解除安裝:偵測 CLI → **先比對各 plugin 的本機與已發佈版本並列表,只要有任一個落後就把「更新」設為推薦選項** → 決策樹選模式 → 每個 CLI 一個 sub agent 呼叫 `tools/deploy.sh` 執行原生 plugin 指令(統一 marketplace `jsc`,token `jsc-{domain}@jsc`)→ install、update 後呼叫 `jsc-hooks:hooks-install`,並把每支 CLI 的 smoke 結果納入部署成敗。domain 名單動態取自 `plugins/meta` 的 marketplace.json,不硬編碼。 ### `doctor` diff --git a/skills/deploy/SKILL.md b/skills/deploy/SKILL.md index b4b4248..71d05d9 100644 --- a/skills/deploy/SKILL.md +++ b/skills/deploy/SKILL.md @@ -22,7 +22,7 @@ description: Batch install, update, or uninstall the whole jsc skill set on ever `jsc-gitea/tools/gitea.sh api GET /repos/plugins/meta/raw/.claude-plugin/marketplace.json`. The marketplace is unified as `jsc`; the install token is `jsc-{domain}@jsc`. Each `plugins[].name` already carries the `jsc-` prefix (e.g. `jsc-ask`) — pass it to `tools/deploy.sh` as-is, prefixed or not; the script normalizes it. Done when the domain list comes from that response and holds at least one name. 5. Run `tools/deploy.sh {mode} {cli} {domain}...` once per detected CLI, passing the whole domain list in one call so the marketplace command runs only once. This step **MUST run as a sub agent** (one sub agent per CLI). The script prints `cmd` and `exit` lines for every command, then one `result` line; `-n` prints the commands without running them. Antigravity cannot install from a Gitea URL, so the script clones each domain into the local plugin directory (`JSC_LOCAL_PLUGINS`, default `$JSC_HOME/plugins`) and installs from that path — keep that clone, because update pulls the same one. That default deliberately avoids a development checkout: when the directory holds uncommitted changes or unpushed commits, the script prints a `skip` line, leaves the tree untouched, and installs the on-disk content. Done when every detected CLI has reported an exit status for every command it ran. -6. After install or update, call `jsc-hooks:hooks-install` to rewire the hooks. Done when hooks-install reports a wiring result for each detected CLI. +6. After install or update, call `jsc-hooks:hooks-install` to rewire the hooks. The hook installer must refresh `$JSC_HOME/current/jsc-hooks` and must run `tools/wire-cli.sh smoke {cli}` for every detected CLI. Treat any `No such file` in those smoke results as a failed update and report it; do not let the deploy finish as successful when a rewritten hook path cannot execute. Done when hooks-install reports purge, wiring, smoke and scan results for each detected CLI, and every smoke result is either `status=ok` or explicitly reported as the update failure. 7. After install or update, run `tools/write-guides.sh {mode} {domain}...` **once for the whole machine**, after every CLI in step 5 has finished. It rewrites `$JSC_HOME/update-guide.md` and `$JSC_HOME/remove-guide.md` from the live detection result, so the later update and removal runs have the real commands for this machine. Skip it for `uninstall`: the guides describe an installed skill set. Done when the script printed a `wrote` line for both files. 8. Report the result and any failure reason for every CLI × mode, plus every `skip` line and every CLI that could not be version-checked in step 2. Done when every detected CLI appears in the report with its `result` status. 9. For install or update, close the report with the restart instruction, in these words: 「請關閉目前的工作階段並重新啟動,新的技能內容才會載入」. `deploy.sh` recorded this round in `$JSC_HOME/restart-required.d/{cli}` — one file per CLI — and prints its path on a `restart` line; `jsc-hooks` reads only that CLI's own file and keeps reminding until that CLI restarts, with `JSC_RESTART_GATE=off` as the escape hatch. Restarting one CLI clears its own file and leaves the others' gates standing. Name the two guide paths from step 7 in the same closing block, so the operator knows where this machine's update and removal commands now live. Done when the restart instruction is printed and both guide paths are named. diff --git a/tools/deploy.sh b/tools/deploy.sh index c1795fc..c0d050a 100755 --- a/tools/deploy.sh +++ b/tools/deploy.sh @@ -64,17 +64,27 @@ usage() { exit 2 } -# 找 jsc-hooks 的 restart-gate.sh。順序比照 jsc-sdlc 的 wp-gate.sh:環境變數指定優先, -# 再找並排的工作樹,最後找 plugin 快取。找不到就回非零,由呼叫端據實回報。 +# 找 jsc-hooks 的 restart-gate.sh。優先用穩定連結與安裝後複製目錄,再找並排工作樹, +# 最後才掃各 CLI 的 plugin 快取。找不到就回非零,由呼叫端據實回報。 restart_gate_sh() { if [ -n "${JSC_HOOKS_DIR:-}" ] && [ -f "$JSC_HOOKS_DIR/restart-gate.sh" ]; then printf '%s\n' "$JSC_HOOKS_DIR/restart-gate.sh"; return 0 fi _root=$(cd "$(dirname "$0")/.." 2>/dev/null && pwd) || return 1 - for _c in "$_root/../hooks/hooks/restart-gate.sh" "$_root/../jsc-hooks/hooks/restart-gate.sh"; do + for _c in \ + "${JSC_HOME:-$HOME/.jsc}/current/jsc-hooks/hooks/restart-gate.sh" \ + "${JSC_LOCAL_PLUGINS:-${JSC_HOME:-$HOME/.jsc}/plugins}/hooks/hooks/restart-gate.sh" \ + "${JSC_KIRO_SKILLS:-$HOME/.kiro/skills}/jsc-hooks/hooks/restart-gate.sh" \ + "$_root/../hooks/hooks/restart-gate.sh" \ + "$_root/../jsc-hooks/hooks/restart-gate.sh" + do [ -f "$_c" ] && { printf '%s\n' "$_c"; return 0; } done - _c=$(ls -d "$HOME"/.claude/plugins/cache/*/jsc-hooks/*/hooks/restart-gate.sh 2>/dev/null | sort | tail -n1) + _c=$(ls -d \ + "$HOME"/.claude/plugins/cache/*/jsc-hooks/*/hooks/restart-gate.sh \ + "$HOME"/.codex/plugins/cache/*/jsc-hooks/*/hooks/restart-gate.sh \ + "$HOME"/.kiro/skills/jsc-hooks/hooks/restart-gate.sh \ + 2>/dev/null | sort | tail -n1) [ -n "$_c" ] && [ -f "$_c" ] && { printf '%s\n' "$_c"; return 0; } return 1 }