fix/sync-marketplace-and-hooks-install-script #6
@@ -1,75 +1,89 @@
|
||||
{
|
||||
"name": "jsc",
|
||||
"description": "jsc 跨 AI 助理技能組的統一 marketplace(claude / codex / copilot / antigravity / kiro)。",
|
||||
"owner": {
|
||||
"name": "JSC"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "jsc-ask",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/ask.git"
|
||||
}
|
||||
},
|
||||
"description": "決策樹問詢與問詢紀錄(QUESTION_* wiki 頁)"
|
||||
},
|
||||
{
|
||||
"name": "jsc-cli",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/cli.git"
|
||||
}
|
||||
},
|
||||
"description": "CLI 偵測、模型能力標籤與技能庫批次部署"
|
||||
},
|
||||
{
|
||||
"name": "jsc-git",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/git.git"
|
||||
}
|
||||
},
|
||||
"description": "Commit 分組認可與 Push Request 建立"
|
||||
},
|
||||
{
|
||||
"name": "jsc-gitea",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/gitea.git"
|
||||
}
|
||||
},
|
||||
"description": "Gitea API 工具、Wiki 讀寫與存取庫批次同步"
|
||||
},
|
||||
{
|
||||
"name": "jsc-hooks",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/hooks.git"
|
||||
}
|
||||
},
|
||||
"description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄"
|
||||
},
|
||||
{
|
||||
"name": "jsc-log",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/log.git"
|
||||
}
|
||||
},
|
||||
"description": "工作日誌(LOG_* wiki 頁)與技能使用統計"
|
||||
},
|
||||
{
|
||||
"name": "jsc-meta",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/meta.git"
|
||||
}
|
||||
},
|
||||
"description": "技能組自我管理:新建、更新、刪除技能與技能準則"
|
||||
},
|
||||
{
|
||||
"name": "jsc-pkg",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/pkg.git"
|
||||
}
|
||||
},
|
||||
"description": "套件批次更新(nodejs/python/dotnet),失敗還原"
|
||||
},
|
||||
{
|
||||
"name": "jsc-review",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/review.git"
|
||||
}
|
||||
},
|
||||
"description": "程式碼審查:Refactoring 壞味道六組 + 註解規範 + 淺模組"
|
||||
},
|
||||
{
|
||||
"name": "jsc-sdlc",
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/sdlc.git"
|
||||
}
|
||||
},
|
||||
"description": "開發生命週期:規劃/分析/實作/維護(wiki 追蹤)"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
"source": "url",
|
||||
"url": "https://gitea.jsc.idv.tw/plugins/meta.git"
|
||||
},
|
||||
"description": "技能組自我管理:新建/更新/刪除技能與技能準則"
|
||||
"description": "技能組自我管理:新建、更新、刪除技能與技能準則"
|
||||
},
|
||||
{
|
||||
"name": "jsc-pkg",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-hooks",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄、SDLC 模型鎖",
|
||||
"skills": "./skills",
|
||||
"author": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-hooks",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄、SDLC 模型鎖",
|
||||
"skills": "./skills"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ Claude 由 `hooks/hooks.json` 自動接線;其他 CLI 用 `hooks-install` 技
|
||||
| --- | --- |
|
||||
| `tools/jsc-wrap.sh` | 無 hook 系統 CLI 的包裝啟動器:匯出 `JSC_CLI`、`JSC_SESSION_ID`,前後接 `session-timer.sh`,結束時自動跑 `scan-logs.sh` 回填 |
|
||||
| `tools/scan-logs.sh` | 離線回填:解析 copilot、antigravity、codex 的原生日誌,把技能用量與階段界線補進 `$JSC_HOME`,重掃不重複 |
|
||||
| `tools/wire-cli.sh` | 單一 CLI 的接線流程:`{cli}` 對應的設定編輯、包裝別名安裝、hook 檔建立,皆以 `<!-- jsc-hooks -->`(或 `# jsc-hooks`)標記整段取代,重跑不重複;以 `status=wired\|degraded\|skipped` 回報結果 |
|
||||
|
||||
## 失敗回報範本
|
||||
|
||||
@@ -52,7 +53,7 @@ Claude 由 `hooks/hooks.json` 自動接線;其他 CLI 用 `hooks-install` 技
|
||||
|
||||
### `hooks-install`
|
||||
|
||||
把四支 hook 接線到所有已安裝的 CLI:偵測 CLI 後逐一套用原生 hook 設定(claude 由 `hooks.json` 自動接線)。copilot、antigravity 改用兩段式:以 `tools/jsc-wrap.sh` 包裝啟動器補上計時與用量回填(結束時自動跑 `tools/scan-logs.sh`),語言規則仍追加到各自的規則檔(以 `<!-- jsc-hooks -->` 標記整段取代,不重複追加)。codex、kiro 的 SDLC 模型鎖降級為技能步驟檢查,鎖檔仍由 SDLC 技能直接呼叫 `sdlc-gate.sh lock` 寫入。
|
||||
把四支 hook 接線到所有已安裝的 CLI:偵測 CLI 後,逐一呼叫 `tools/wire-cli.sh {cli}` 完成接線(claude 由 `hooks.json` 自動接線,無需寫入)。copilot、antigravity 由該腳本裝上 `tools/jsc-wrap.sh` 包裝別名補上計時與用量回填(結束時自動跑 `tools/scan-logs.sh`),語言規則仍追加到各自的規則檔(以 `<!-- jsc-hooks -->` 標記整段取代,不重複追加)。codex、kiro 的 SDLC 模型鎖降級為技能步驟檢查,鎖檔仍由 SDLC 技能直接呼叫 `sdlc-gate.sh lock` 寫入。腳本以 `status=wired|degraded|skipped` 回報結果,供技能對照 verify 表。
|
||||
|
||||
<!-- JSC-SKILLS:END -->
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jsc-hooks",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.4",
|
||||
"description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄、SDLC 模型鎖",
|
||||
"skills": "./skills/"
|
||||
}
|
||||
|
||||
@@ -12,18 +12,18 @@ The detailed flow **MUST run as a sub agent**; the main agent only reports the s
|
||||
## Steps
|
||||
|
||||
1. Run `jsc-cli/tools/detect-clis.sh`. Done when you hold the list of installed CLIs; when the list is empty, report that and stop.
|
||||
2. Wire each CLI per the table below. A row counts as done only when its verify check passes:
|
||||
2. For each installed CLI, run `tools/wire-cli.sh {cli}`. The script performs the config edit, wrapper alias install, or hook file creation for that CLI, and replaces its `<!-- jsc-hooks -->` (or `# jsc-hooks`) marker block idempotently — reruns never duplicate content. Read its exit code and first output line (`status=wired|degraded|skipped reason=...`), then confirm against the table below:
|
||||
|
||||
| CLI | Wiring | Verify |
|
||||
| CLI | Exit / status | Verify |
|
||||
| --- | --- | --- |
|
||||
| claude | the plugin loads `jsc-hooks/hooks/hooks.json` automatically on install (all four hooks, `sdlc-gate.sh check` included); nothing to write | `claude plugin list` shows `jsc-hooks` and `/hooks` shows the registrations |
|
||||
| codex | set `notify` in `~/.codex/config.toml` to `session-timer.sh mark` (with `JSC_CLI=codex`); append the STE100 rule block to `~/.codex/AGENTS.md` (prompt fallback) | `config.toml` contains the `notify` entry and `AGENTS.md` contains the block |
|
||||
| copilot | (a) install the wrapper: add a shell alias or launcher that starts the CLI via `jsc-hooks/tools/jsc-wrap.sh copilot`, so session timing and usage backfill work — `tools/scan-logs.sh` runs automatically at wrapper exit; (b) keep appending the STE100 rule block to `~/.config/copilot/copilot-instructions.md` (prompt fallback for the language rules) | the alias resolves to `jsc-wrap.sh copilot` and the instruction file contains the block |
|
||||
| antigravity | (a) install the wrapper: add a shell alias or launcher that starts the CLI via `jsc-hooks/tools/jsc-wrap.sh antigravity` — `tools/scan-logs.sh` runs automatically at wrapper exit; (b) keep appending the STE100 rule block to the global rules file (prompt fallback for the language rules) | the alias resolves to `jsc-wrap.sh antigravity` and the rules file contains the block |
|
||||
| kiro | create an agent hook under the workspace `.kiro/hooks/` that runs the matching script (with `JSC_CLI=kiro`) | the hook file exists under `.kiro/hooks/` and names the script |
|
||||
| claude | `status=wired` (exit 0) — hooks.json auto-wires everything, nothing to write | `claude plugin list` shows `jsc-hooks` and `/hooks` shows the registrations |
|
||||
| codex | `status=degraded` (exit 1) — notify + AGENTS.md prompt fallback | `~/.codex/config.toml` contains the `notify` entry and `AGENTS.md` contains the block |
|
||||
| copilot | `status=wired` (exit 0) when the CLI is detected, `status=skipped` (exit 3) otherwise | the alias resolves to `jsc-wrap.sh copilot` and `copilot-instructions.md` contains the block |
|
||||
| antigravity | `status=wired` (exit 0) when the CLI is detected, `status=skipped` (exit 3) otherwise | the alias resolves to `jsc-wrap.sh antigravity` and the rules file contains the block |
|
||||
| kiro | `status=degraded` (exit 1) | the hook file exists under `.kiro/hooks/` and names the script |
|
||||
|
||||
3. The appended rule text is always the exact output of `ste100-guard.sh` (a Traditional Chinese literal). Wrap it in `<!-- jsc-hooks -->` markers; on re-run, replace the whole block instead of appending again. Done when each touched instruction file contains exactly one `<!-- jsc-hooks -->` block.
|
||||
4. Report the wiring result for every CLI. Done when every detected CLI has exactly one status: succeeded, degraded to prompt, or skipped with a reason.
|
||||
A row counts as done only when its verify check passes. Exit 2 means bad usage (wrong CLI name), not a wiring outcome.
|
||||
3. Report the exact `status=` line `tools/wire-cli.sh` printed for each CLI; do not reinterpret or recompute the outcome by hand. Done when every detected CLI has exactly one reported status: wired, degraded, or skipped with a reason.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
Executable
+149
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env sh
|
||||
# wire-cli.sh — 把 jsc 四支 hook 接線到單一 CLI(供 hooks-install 技能呼叫)。
|
||||
# 用法: wire-cli.sh {claude|codex|copilot|antigravity|kiro}
|
||||
# 行為(依 CLI 而定,皆為冪等:重跑只取代既有的 jsc-hooks 標記段落,不會重複疊加):
|
||||
# claude — 什麼都不用寫,hooks.json 已自動接線四支 hook
|
||||
# codex — 在 config.toml 設 notify(呼叫 session-timer.sh mark,JSC_CLI=codex);
|
||||
# 在 AGENTS.md 附加 STE100 規則段落(prompt 降級)
|
||||
# copilot — 在 shell rc 檔加上 copilot 別名,轉呼叫 tools/jsc-wrap.sh copilot;
|
||||
# 在 copilot-instructions.md 附加 STE100 規則段落
|
||||
# antigravity — 在 shell rc 檔加上 agy 別名,轉呼叫 tools/jsc-wrap.sh antigravity;
|
||||
# 在全域規則檔附加 STE100 規則段落
|
||||
# kiro — 在工作區 .kiro/hooks/ 下建立 jsc-hooks.json(JSC_CLI=kiro)
|
||||
#
|
||||
# 輸出: 第一行固定為 `status={wired|degraded|skipped} reason=...`(可供程式判讀),
|
||||
# 其後為人類可讀的繁中說明。
|
||||
# 結束碼: 0=wired(已完整接線) 1=degraded(降級為 prompt/技能步驟檢查)
|
||||
# 2=用法錯誤 3=skipped(該 CLI 未偵測到執行檔,略過)
|
||||
set -u
|
||||
HERE=$(cd "$(dirname "$0")" && pwd)
|
||||
ROOT=$(cd "$HERE/.." && pwd)
|
||||
HOOKS="$ROOT/hooks"
|
||||
|
||||
cli="${1:-}"
|
||||
case "$cli" in
|
||||
claude|codex|copilot|antigravity|kiro) ;;
|
||||
*)
|
||||
echo "用法:wire-cli.sh {claude|codex|copilot|antigravity|kiro}" >&2
|
||||
exit 2 ;;
|
||||
esac
|
||||
|
||||
# 每個 CLI 對應的實際執行檔名稱(antigravity 的執行檔是 agy,其餘與 CLI 代號同名)
|
||||
cli_bin() {
|
||||
case "$1" in
|
||||
antigravity) printf 'agy' ;;
|
||||
kiro) printf 'kiro-cli' ;;
|
||||
*) printf '%s' "$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# STE100 規則段落的唯一來源:ste100-guard.sh 的實際輸出
|
||||
ste100_text() { sh "$HOOKS/ste100-guard.sh" 2>/dev/null | sed '/^exit /d'; }
|
||||
|
||||
# 以標記整段取代(冪等);標記不存在就在檔尾新增;檔案不存在就建立。
|
||||
# $1=檔案 $2=開頭標記行 $3=結尾標記行 $4=標記之間要寫入的內容
|
||||
replace_block() {
|
||||
file="$1"; bopen="$2"; bshut="$3"; content="$4"
|
||||
dir=$(dirname "$file")
|
||||
mkdir -p "$dir" 2>/dev/null || return 1
|
||||
touch "$file" 2>/dev/null || return 1
|
||||
block=$(printf '%s\n%s\n%s' "$bopen" "$content" "$bshut")
|
||||
if grep -qF "$bopen" "$file" 2>/dev/null; then
|
||||
awk -v bopen="$bopen" -v bshut="$bshut" -v block="$block" '
|
||||
$0==bopen { print block; skip=1; next }
|
||||
$0==bshut { skip=0; next }
|
||||
skip { next }
|
||||
{ print }
|
||||
' "$file" > "$file.jsc-tmp" 2>/dev/null && mv "$file.jsc-tmp" "$file"
|
||||
else
|
||||
printf '\n%s\n' "$block" >> "$file"
|
||||
fi
|
||||
}
|
||||
|
||||
# 找出可寫入別名的 shell rc 檔;都不存在就以 ~/.bashrc 為預設(自動建立)。
|
||||
# 印出找到/建立的 rc 檔路徑,一行一個。
|
||||
rc_files() {
|
||||
found=""
|
||||
for f in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.config/fish/config.fish"; do
|
||||
[ -f "$f" ] && { printf '%s\n' "$f"; found=1; }
|
||||
done
|
||||
[ -n "$found" ] || printf '%s\n' "$HOME/.bashrc"
|
||||
}
|
||||
|
||||
skip() { # $1=reason
|
||||
printf 'status=skipped reason=%s\n' "$1"
|
||||
echo "[jsc] 略過:$1"
|
||||
exit 3
|
||||
}
|
||||
|
||||
case "$cli" in
|
||||
claude)
|
||||
printf 'status=wired reason=%s\n' "hooks.json 自動接線"
|
||||
echo "[jsc] claude:由 hooks/hooks.json 自動接線全部四支 hook,無需寫入設定。"
|
||||
exit 0 ;;
|
||||
|
||||
codex)
|
||||
command -v "$(cli_bin codex)" >/dev/null 2>&1 || skip "未偵測到 codex 執行檔"
|
||||
CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
|
||||
config="$CODEX_HOME/config.toml"
|
||||
agents="$CODEX_HOME/AGENTS.md"
|
||||
notify_line="notify = [\"env\", \"JSC_CLI=codex\", \"sh\", \"$HOOKS/session-timer.sh\", \"mark\"]"
|
||||
replace_block "$config" "# jsc-hooks" "# /jsc-hooks" "$notify_line" \
|
||||
|| skip "無法寫入 $config"
|
||||
replace_block "$agents" "<!-- jsc-hooks -->" "<!-- /jsc-hooks -->" "$(ste100_text)" \
|
||||
|| skip "無法寫入 $agents"
|
||||
printf 'status=degraded reason=%s\n' "STE100 降級為 prompt 檔,SDLC 模型鎖降級為技能步驟檢查"
|
||||
echo "[jsc] codex:已設定 $config 的 notify 呼叫 session-timer.sh mark。"
|
||||
echo "[jsc] codex:已在 $agents 寫入 STE100 規則段落(prompt 降級)。"
|
||||
echo "[jsc] codex:SDLC 模型鎖降級為技能步驟檢查,鎖檔仍由 sdlc-gate.sh lock 寫入。"
|
||||
exit 1 ;;
|
||||
|
||||
copilot)
|
||||
bin=$(cli_bin copilot)
|
||||
command -v "$bin" >/dev/null 2>&1 || skip "未偵測到 copilot 執行檔"
|
||||
instr="${JSC_COPILOT_INSTRUCTIONS:-$HOME/.config/copilot/copilot-instructions.md}"
|
||||
alias_line="alias $bin='sh \"$HERE/jsc-wrap.sh\" copilot'"
|
||||
rc_files | while IFS= read -r rc; do
|
||||
replace_block "$rc" "# jsc-hooks:copilot" "# /jsc-hooks:copilot" "$alias_line"
|
||||
done
|
||||
replace_block "$instr" "<!-- jsc-hooks -->" "<!-- /jsc-hooks -->" "$(ste100_text)" \
|
||||
|| skip "無法寫入 $instr"
|
||||
printf 'status=wired reason=%s\n' "wrapper 別名 + 規則檔已接線"
|
||||
echo "[jsc] copilot:已在 shell rc 加上 $bin 別名,轉呼叫 tools/jsc-wrap.sh copilot。"
|
||||
echo "[jsc] copilot:已在 $instr 寫入 STE100 規則段落。"
|
||||
exit 0 ;;
|
||||
|
||||
antigravity)
|
||||
bin=$(cli_bin antigravity)
|
||||
command -v "$bin" >/dev/null 2>&1 || skip "未偵測到 antigravity(agy)執行檔"
|
||||
rules="${JSC_ANTIGRAVITY_RULES:-$HOME/.antigravity/AGENTS.md}"
|
||||
alias_line="alias $bin='sh \"$HERE/jsc-wrap.sh\" antigravity'"
|
||||
rc_files | while IFS= read -r rc; do
|
||||
replace_block "$rc" "# jsc-hooks:antigravity" "# /jsc-hooks:antigravity" "$alias_line"
|
||||
done
|
||||
replace_block "$rules" "<!-- jsc-hooks -->" "<!-- /jsc-hooks -->" "$(ste100_text)" \
|
||||
|| skip "無法寫入 $rules"
|
||||
printf 'status=wired reason=%s\n' "wrapper 別名 + 規則檔已接線"
|
||||
echo "[jsc] antigravity:已在 shell rc 加上 $bin 別名,轉呼叫 tools/jsc-wrap.sh antigravity。"
|
||||
echo "[jsc] antigravity:已在 $rules 寫入 STE100 規則段落。"
|
||||
exit 0 ;;
|
||||
|
||||
kiro)
|
||||
command -v "$(cli_bin kiro)" >/dev/null 2>&1 || skip "未偵測到 kiro-cli 執行檔"
|
||||
hookdir="./.kiro/hooks"
|
||||
hookfile="$hookdir/jsc-hooks.json"
|
||||
mkdir -p "$hookdir" 2>/dev/null || skip "無法建立 $hookdir"
|
||||
cat > "$hookfile" 2>/dev/null <<EOF || skip "無法寫入 $hookfile"
|
||||
{
|
||||
"name": "jsc-hooks",
|
||||
"description": "jsc session timer + STE100 guard bridge (auto-generated by jsc-hooks:hooks-install, do not edit by hand)",
|
||||
"on": ["sessionStart", "sessionEnd", "userPromptSubmit"],
|
||||
"env": { "JSC_CLI": "kiro" },
|
||||
"run": "sh \\"$HOOKS/session-timer.sh\\" mark; sh \\"$HOOKS/ste100-guard.sh\\""
|
||||
}
|
||||
EOF
|
||||
printf 'status=degraded reason=%s\n' "SDLC 模型鎖降級為技能步驟檢查"
|
||||
echo "[jsc] kiro:已建立 $hookfile(JSC_CLI=kiro)。"
|
||||
echo "[jsc] kiro:SDLC 模型鎖降級為技能步驟檢查,鎖檔仍由 sdlc-gate.sh lock 寫入。"
|
||||
exit 1 ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user