From ea11ca0590c3b296d3d28e1b444f0f5390639e92 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 25 Aug 2026 14:58:54 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix(pkg):=20=E8=A3=9C=E9=BD=8A=E7=A8=BD?= =?UTF-8?q?=E6=A0=B8=E7=BC=BA=E5=A4=B1=E4=B8=A6=E4=BF=AE=E6=8E=89=E8=AD=B7?= =?UTF-8?q?=E6=AC=84=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What:依 jsc-meta:skill-check 的稽核結果修正技能與工具——補上每個步驟的可檢核完成條件、 把留在內文的標準輸入輸出流程下放 tools/、修正查表與退碼路由造成的誤判。 Why:稽核發現這些缺失會讓技能在實際執行時走錯分支或靜默通過。 完成條件缺漏是最常被違反的一項;退碼誤判與查表錯誤則會讓良性狀況被當成失敗。 How:逐項對照 references/guidelines.md 的審核檢查清單修正,新增的工具都有 documented exit codes,並以真實執行驗證每條路徑。 Who:jsc-meta:skill-check 例行稽核(2026-08-25)。 Co-Authored-By: Claude Opus 5 --- skills/pkg-update/SKILL.md | 55 ++++++++++++++++++----- tools/apply-version.sh | 35 +++++++++++---- tools/build-test.sh | 91 ++++++++++++++++++++++++++++++++++++++ tools/install-deps.sh | 73 ++++++++++++++++++++++++++++++ tools/latest-version.sh | 28 +++++++++--- tools/list-packages.sh | 23 ++++++++-- 6 files changed, 277 insertions(+), 28 deletions(-) create mode 100755 tools/build-test.sh create mode 100755 tools/install-deps.sh diff --git a/skills/pkg-update/SKILL.md b/skills/pkg-update/SKILL.md index 839d2a5..345cdff 100644 --- a/skills/pkg-update/SKILL.md +++ b/skills/pkg-update/SKILL.md @@ -5,18 +5,49 @@ description: Update every external package of a project to its latest stable ver # pkg-update — batch-update packages +## Exit-code routes + +Every tool exit code below has exactly one route. Three routes exist: + +- **skip** — record the reason, keep going. +- **stop** — report and end the run. Change no file, and never enter step 5. +- **revert** — go to step 5, which reverts the working tree. + +Only a real install, build or test failure takes the revert route. A missing input, a bad argument, an unknown ecosystem or a missing command is a broken call or a broken toolchain, so it takes the stop route. + +One number carries one meaning across all five tools. Exit 6 is always a missing project directory and always stops the run — never fold it into the exit 3 skip, or a bad path hides as "nothing to do". + +| Tool | 0 | 1 (bad argument count) | 2 (unknown ecosystem) | 3 (no source file) | 4 | 5 | 6 (project dir not found) | other | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| `list-packages.sh` | continue | stop | — | — | stop (python3 missing) | — | stop | stop | +| `latest-version.sh` | continue | stop | stop | — | skip (not in registry) | stop (curl or python3 missing) | — (takes no project dir) | stop | +| `apply-version.sh` | continue | stop | stop | skip | skip (package absent from the file) | stop (python3 missing) | stop | stop | +| `install-deps.sh` | continue | stop | stop | skip | stop (npm, pip or dotnet missing) | — | stop | **revert** | +| `build-test.sh` | continue | stop | stop | — (uses 5 instead) | stop (npm, python3, pytest or dotnet missing) | ask the user | stop | **revert** | + +Exit 4 and exit 5 are the two codes whose meaning depends on the tool, so read them off this table rather than from memory. + ## Steps -1. Run `tools/list-packages.sh {project dir}` to get every external package (ecosystem, name, current version). -2. Confirm the working tree is clean: stop and report when uncommitted changes exist, so the revert cannot destroy them. +1. Run `tools/list-packages.sh {project dir}` to get every external package (ecosystem, name, current version). Route the exit code per the table above. Step 1 is done only when the tool exited 0 and at least one row came back, with an ecosystem, a name and a current version in every row. Zero rows → stop and report the project directory you scanned plus the supported ecosystems (nodejs / python / dotnet), and run no further step. +2. Prove the project directory is a git repository with a clean tree. Run this before any step changes a file: + 1. Run `git -C {project dir} rev-parse --git-dir`. Exit 0 is required to continue, because step 5's revert is impossible outside a git repository. Any other exit code → stop and report the directory, and run no further step. + 2. Run `git -C {project dir} status --porcelain`. Continuing requires that it prints **nothing at all**. Any output stops the run and reports that output, **including `??` untracked lines**: step 5 runs `git clean -fd`, which deletes untracked files with no reflog and no way back. + 3. Step 2 is done only when `rev-parse --git-dir` exited 0 and `status --porcelain` printed zero bytes. Report both results, then enter step 3. 3. Update ecosystem by ecosystem. This step **MUST run as a sub agent** (one sub agent per ecosystem): - 1. For every package, run `tools/latest-version.sh {ecosystem} {name}` to get the latest stable version. - 2. Run `tools/apply-version.sh {ecosystem} {project dir} {name} {version}` to rewrite the version source file (package.json / requirements.txt / pyproject.toml / *.csproj). - 3. Re-resolve and install (`npm install` / `pip install -r` / `dotnet restore`). -4. Run build and tests: - - nodejs: `npm run build` (if present) plus `npm test` (if present). - - python: `pytest` (when tests exist). - - dotnet: `dotnet build` plus `dotnet test`. - - When the commands cannot be inferred, ask the user per the `jsc-ask:ask` rules. -5. Build or tests fail → revert every change (`git checkout -- .` and clean untracked lock changes), then report the failing packages with an error summary. -6. Success → report the update list (package, old version, new version) and hand off to `jsc-git:commit`. + 1. For every package, run `tools/latest-version.sh {ecosystem} {name}` for the latest stable version, then `tools/apply-version.sh {ecosystem} {project dir} {name} {version}` to rewrite the version source file (package.json / requirements.txt / pyproject.toml / *.csproj). This substep is done when every package of the ecosystem carries either an applied version or a skip reason from substep 2. + 2. Route every exit code per the table above. The skip route covers `latest-version.sh` exit 4 (package not found in the registry), `apply-version.sh` exit 3 (no version source file) and `apply-version.sh` exit 4 (package absent from the file): record the package and the reason, move on to the next package, and never abort the whole ecosystem. The stop route covers exit 1, exit 2, `latest-version.sh` or `apply-version.sh` exit 5 (a required command is missing) and `apply-version.sh` exit 6 (project directory not found): report the code and end the run without entering step 5. This substep is done when every exit code seen has taken exactly one route. + 3. Run `tools/install-deps.sh {ecosystem} {project dir}` once, after every package of that ecosystem is applied. Exit 0 means the install finished. Exit 3 means this ecosystem has no dependency source file, which is the same documented skip as substep 2: record the ecosystem and the reason, and install nothing. Exit 1, exit 2, exit 4 and exit 6 take the stop route — exit 6 is a missing project directory, so report it instead of skipping it. Only another non-zero code is a real install failure and goes to step 5. This substep is done when the exit code is recorded together with the route it took. + 4. The sub agent returns one row per package from substep 1: name, old version, new version — or `skipped` plus the reason. It also returns the `install-deps.sh` exit code and its route. The ecosystem is done only when every package appears in exactly one row. +4. Run `tools/build-test.sh {ecosystem} {project dir}` for every ecosystem and route on the exit code: + - 0 → this ecosystem passed. + - 1, 2, 4 or 6 → stop route. Report the code and the missing argument, ecosystem, command or directory, and enter no further step. Exit 4 means the toolchain is broken, not that the packages are broken, so reverting would destroy files for nothing. + - 5 → no build or test command could be inferred. Ask the user for the build command and the test command per the `jsc-ask:ask` rules, run the answers in that order, and take their exit codes as this ecosystem's result: all 0 → passed; any non-zero → step 5. + - any other code → a real build or test failure. Go to step 5. + + Step 4 is done only when every ecosystem reached exit 0, from the tool or from the user's own commands. +5. A real install, build or test failure reached this step → revert: + 1. Run `git -C {project dir} checkout -- .` to restore every tracked file to HEAD. + 2. Run `git -C {project dir} clean -fd` to remove the untracked files and directories this run created, such as a new lock file. Gitignored paths survive `-fd` on purpose: `node_modules`, `__pycache__`, `bin/` and `obj/` stay behind, so restoring install output is out of scope for this skill. Do not reach for `-fdx` — it deletes far more than this run created. + 3. The revert is done only when `git -C {project dir} status --porcelain` prints nothing. Report the failing packages with an error summary after that check passes. +6. Success → report the update list (package, old version, new version), plus every skip and its reason, and hand off to `jsc-git:commit`. Step 6 is done when the hand-off is made and every package from step 1 appears either as an update or as a skip. diff --git a/tools/apply-version.sh b/tools/apply-version.sh index c519d8c..d8605dc 100755 --- a/tools/apply-version.sh +++ b/tools/apply-version.sh @@ -1,17 +1,36 @@ #!/usr/bin/env sh # apply-version.sh — 改寫版本來源檔案,把套件釘選到指定版本。 -# 用法: apply-version.sh -# ecosystem: nodejs | python | dotnet -# 對應檔案(與 list-packages.sh 相同的解析邏輯): +# 用法:apply-version.sh +# ecosystem:nodejs | python | dotnet +# 對應檔案(與 list-packages.sh 相同的解析邏輯): # nodejs → package.json(dependencies / devDependencies) # python → requirements.txt(優先)或 pyproject.toml 的 [project] dependencies # dotnet → *.csproj 的 PackageReference -# 找不到對應檔案 exit 3;檔案中找不到該套件 exit 4 +# 結束碼(慣例見 README「工具」章的結束碼總表): +# 0 改寫成功 +# 1 參數個數不對 +# 2 ecosystem 不認識 +# 3 找不到對應的版本來源檔案——呼叫方跳過這個套件 +# 4 檔案中找不到該套件——呼叫方跳過這個套件 +# 5 需要的指令不存在(python3) +# 6 找不到專案目錄——呼叫方停手,不要當成跳過 set -u -eco="${1:?ecosystem required (nodejs|python|dotnet)}" -DIR="${2:?project dir required}" -name="${3:?package name required}" -version="${4:?version required}" + +if [ "$#" -ne 4 ]; then + echo "用法:apply-version.sh " >&2 + exit 1 +fi + +eco="$1" +DIR="$2" +name="$3" +version="$4" + +# 先擋找不到專案目錄。少了這道,壞路徑會被報成「沒有版本來源檔案」,然後被當成跳過藏起來。 +[ -d "$DIR" ] || { echo "project dir not found: $DIR" >&2; exit 6; } + +# 三種來源檔案都靠 python3 改寫。少了 python3 會被誤判成檔案中找不到該套件,所以先擋。 +command -v python3 >/dev/null 2>&1 || { echo "python3 not found" >&2; exit 5; } case "$eco" in nodejs) diff --git a/tools/build-test.sh b/tools/build-test.sh new file mode 100755 index 0000000..d7fcfea --- /dev/null +++ b/tools/build-test.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env sh +# build-test.sh — 偵測並執行專案的建置與測試,先建置再測試。 +# 用法:build-test.sh +# ecosystem:nodejs | python | dotnet +# 偵測方式: +# nodejs → package.json 的 scripts.build 與 scripts.test(npm init 產生的佔位 test 視為沒有) +# python → pytest 設定(pytest.ini、setup.cfg、tox.ini、pyproject.toml)或 tests 目錄與 test_*.py +# dotnet → *.sln 或 *.csproj,建置與測試都用 dotnet +# 輸出:底層指令的原始輸出。 +# 結束碼(慣例見 README「工具」章的結束碼總表): +# 0 建置與測試都通過 +# 1 參數個數不對 +# 2 ecosystem 不認識 +# 4 需要的指令不存在(npm、python3、pytest、dotnet) +# 5 推不出任何建置或測試指令——呼叫方要改問使用者 +# 6 找不到專案目錄——呼叫方停手 +# 其他 建置或測試失敗,帶回失敗指令的結束碼 +# 本工具不用 3:3 保留給「該 ecosystem 沒有來源檔案」,這支改用 5 表達推不出指令。 +set -u + +if [ "$#" -ne 2 ]; then + echo "用法:build-test.sh " >&2 + exit 1 +fi + +eco="$1" +DIR="$2" + +NO_COMMAND=5 + +[ -d "$DIR" ] || { echo "project dir not found: $DIR" >&2; exit 6; } + +case "$eco" in + nodejs) + [ -f "$DIR/package.json" ] || { echo "no build or test command inferred for $DIR" >&2; exit "$NO_COMMAND"; } + # package.json 靠 python3 解析。少了 python3 會解出空字串,被誤判成推不出指令,所以先擋。 + command -v python3 >/dev/null 2>&1 || { echo "python3 not found" >&2; exit 4; } + scripts=$(python3 - "$DIR/package.json" <<'EOF' +import json,sys +try: + d=json.load(open(sys.argv[1],encoding="utf-8")) +except Exception: + sys.exit(0) +s=(d.get("scripts") or {}) +if s.get("build"): print("build") +t=s.get("test") or "" +if t and "no test specified" not in t: print("test") +EOF +) + [ -n "$scripts" ] || { echo "no build or test command inferred for $DIR" >&2; exit "$NO_COMMAND"; } + command -v npm >/dev/null 2>&1 || { echo "npm not found" >&2; exit 4; } + for s in $scripts; do + ( cd "$DIR" && npm run --if-present "$s" ) || exit $? + done + exit 0 + ;; + + python) + has_tests=0 + for f in pytest.ini setup.cfg tox.ini pyproject.toml; do + if [ -f "$DIR/$f" ] && grep -q 'pytest' "$DIR/$f" 2>/dev/null; then has_tests=1; fi + done + [ -d "$DIR/tests" ] && has_tests=1 + if [ "$has_tests" -eq 0 ]; then + found=$(find "$DIR" -maxdepth 3 -name 'test_*.py' 2>/dev/null | head -n 1) + [ -n "$found" ] && has_tests=1 + fi + [ "$has_tests" -eq 1 ] || { echo "no build or test command inferred for $DIR" >&2; exit "$NO_COMMAND"; } + if command -v pytest >/dev/null 2>&1; then + ( cd "$DIR" && pytest ) + exit $? + elif command -v python3 >/dev/null 2>&1 && python3 -m pytest --version >/dev/null 2>&1; then + ( cd "$DIR" && python3 -m pytest ) + exit $? + else + echo "pytest not found" >&2 + exit 4 + fi + ;; + + dotnet) + projs=$(find "$DIR" -maxdepth 3 \( -name '*.sln' -o -name '*.csproj' \) 2>/dev/null) + [ -n "$projs" ] || { echo "no build or test command inferred for $DIR" >&2; exit "$NO_COMMAND"; } + command -v dotnet >/dev/null 2>&1 || { echo "dotnet not found" >&2; exit 4; } + ( cd "$DIR" && dotnet build ) || exit $? + ( cd "$DIR" && dotnet test ) || exit $? + exit 0 + ;; + + *) echo "unknown ecosystem: $eco" >&2; exit 2 ;; +esac diff --git a/tools/install-deps.sh b/tools/install-deps.sh new file mode 100755 index 0000000..48027b5 --- /dev/null +++ b/tools/install-deps.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env sh +# install-deps.sh — 重新解析並安裝專案的相依套件。 +# 用法:install-deps.sh +# ecosystem:nodejs | python | dotnet +# 對應動作: +# nodejs → npm install +# python → pip install -r requirements.txt(優先)或 pip install -e .(pyproject.toml) +# dotnet → dotnet restore +# 輸出:底層指令的原始輸出。 +# 檢查順序:先確認相依來源檔案存在,才檢查指令存在。順序顛倒會把「沒有來源檔案」報成「指令不存在」。 +# 結束碼(慣例見 README「工具」章的結束碼總表): +# 0 安裝成功 +# 1 參數個數不對 +# 2 ecosystem 不認識 +# 3 該 ecosystem 沒有相依來源檔案——呼叫方跳過這個 ecosystem +# 4 需要的指令不存在(npm、pip、dotnet) +# 6 找不到專案目錄——呼叫方停手,不要當成跳過 +# 其他 底層指令的結束碼,代表安裝失敗 +set -u + +if [ "$#" -ne 2 ]; then + echo "用法:install-deps.sh " >&2 + exit 1 +fi + +eco="$1" +DIR="$2" + +[ -d "$DIR" ] || { echo "project dir not found: $DIR" >&2; exit 6; } + +case "$eco" in + nodejs) + [ -f "$DIR/package.json" ] || { echo "package.json not found in $DIR" >&2; exit 3; } + command -v npm >/dev/null 2>&1 || { echo "npm not found" >&2; exit 4; } + ( cd "$DIR" && npm install ) + exit $? + ;; + + python) + if [ -f "$DIR/requirements.txt" ]; then + target="-r requirements.txt" + elif [ -f "$DIR/pyproject.toml" ]; then + target="-e ." + else + echo "requirements.txt or pyproject.toml not found in $DIR" >&2 + exit 3 + fi + pip="" + for c in pip3 pip; do + if command -v "$c" >/dev/null 2>&1; then pip="$c"; break; fi + done + if [ -z "$pip" ]; then + if command -v python3 >/dev/null 2>&1 && python3 -m pip --version >/dev/null 2>&1; then + pip="python3 -m pip" + else + echo "pip not found" >&2 + exit 4 + fi + fi + ( cd "$DIR" && $pip install $target ) + exit $? + ;; + + dotnet) + projs=$(find "$DIR" -maxdepth 3 \( -name '*.csproj' -o -name '*.sln' \) 2>/dev/null) + [ -n "$projs" ] || { echo "*.csproj or *.sln not found in $DIR" >&2; exit 3; } + command -v dotnet >/dev/null 2>&1 || { echo "dotnet not found" >&2; exit 4; } + ( cd "$DIR" && dotnet restore ) + exit $? + ;; + + *) echo "unknown ecosystem: $eco" >&2; exit 2 ;; +esac diff --git a/tools/latest-version.sh b/tools/latest-version.sh index 81a3e98..01a82b3 100755 --- a/tools/latest-version.sh +++ b/tools/latest-version.sh @@ -1,11 +1,29 @@ #!/usr/bin/env sh # latest-version.sh — 查詢套件最新且穩定的版本號。 -# 用法: latest-version.sh -# ecosystem: nodejs | python | dotnet -# 輸出: 版本號一行;查不到 exit 4 +# 用法:latest-version.sh +# ecosystem:nodejs | python | dotnet +# 輸出:版本號一行。 +# 結束碼(慣例見 README「工具」章的結束碼總表): +# 0 查到版本號 +# 1 參數個數不對 +# 2 ecosystem 不認識 +# 4 登錄站上查不到這個套件——呼叫方跳過這個套件 +# 5 需要的指令不存在(curl、python3) +# 本工具不收專案目錄,所以沒有 6。 set -u -eco="${1:?ecosystem required (nodejs|python|dotnet)}" -name="${2:?package name required}" + +if [ "$#" -ne 2 ]; then + echo "用法:latest-version.sh " >&2 + exit 1 +fi + +eco="$1" +name="$2" + +# 回應靠 curl 取得、靠 python3 解析。少了任一支會解出空字串,被誤判成查不到套件,所以先擋。 +for c in curl python3; do + command -v "$c" >/dev/null 2>&1 || { echo "$c not found" >&2; exit 5; } +done case "$eco" in nodejs) diff --git a/tools/list-packages.sh b/tools/list-packages.sh index ee12fc1..7488f71 100755 --- a/tools/list-packages.sh +++ b/tools/list-packages.sh @@ -1,11 +1,28 @@ #!/usr/bin/env sh # list-packages.sh — 列出專案的所有外部套件與目前版本。 -# 用法: list-packages.sh [專案目錄](預設目前目錄) -# 輸出(TSV): ecosystemnamecurrent -# 支援: nodejs(package.json)、python(requirements.txt / pyproject.toml)、dotnet(*.csproj) +# 用法:list-packages.sh [專案目錄](預設目前目錄) +# 輸出(TSV):ecosystemnamecurrent +# 支援:nodejs(package.json)、python(requirements.txt / pyproject.toml)、dotnet(*.csproj) +# 結束碼(慣例見 README「工具」章的結束碼總表): +# 0 掃描完成(沒有套件時輸出零行) +# 1 參數個數不對 +# 4 需要的指令不存在(python3) +# 6 找不到專案目錄——呼叫方停手 set -u + +if [ "$#" -gt 1 ]; then + echo "用法:list-packages.sh [專案目錄]" >&2 + exit 1 +fi + DIR="${1:-.}" +# 先擋找不到專案目錄。少了這道,壞路徑會輸出零行,被誤判成專案沒有套件。 +[ -d "$DIR" ] || { echo "project dir not found: $DIR" >&2; exit 6; } + +# 四種來源檔案都靠 python3 解析。少了 python3 會輸出零行,被誤判成專案沒有套件,所以先擋。 +command -v python3 >/dev/null 2>&1 || { echo "python3 not found" >&2; exit 4; } + # nodejs: package.json 的 dependencies / devDependencies if [ -f "$DIR/package.json" ]; then python3 - "$DIR/package.json" <<'EOF' From bb2e6821c1c23af25e497d3d9a3d52868f2fa43f Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 25 Aug 2026 14:58:54 +0800 Subject: [PATCH 2/5] =?UTF-8?q?docs(pkg):=20=E5=90=8C=E6=AD=A5=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E8=88=87=E5=8F=83=E8=80=83=E8=B3=87=E6=96=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What:更新 README、AGENTS.md、templates 與 references,讓文件敘述與實際行為一致。 Why:稽核發現多處文件與程式行為分歧,違反「每個意義只有單一真實來源」。 How:以實際程式行為為準改寫敘述,重複的規則收成單一來源並以一行指引指過去。 Who:jsc-meta:skill-check 例行稽核(2026-08-25)。 Co-Authored-By: Claude Opus 5 --- README.md | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6e3b7f1..93d7b23 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,36 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安 ## 工具 -| 工具 | 用途 | -| --- | --- | -| `tools/list-packages.sh` | 偵測專案類型並列出所有外部套件與目前版本(TSV:ecosystem / name / current) | -| `tools/latest-version.sh` | `latest-version.sh ` 查最新穩定版(npm / pypi / nuget),查無 exit 4 | -| `tools/apply-version.sh` | `apply-version.sh ` 改寫版本來源檔案,把套件釘選到指定版本 | +五支工具都靠 python3 解析或改寫檔案。少了 python3,每一支都回報「需要的指令不存在」,不會裝成查無套件。 + +| 工具 | 用途 | 需要的指令 | +| --- | --- | --- | +| `tools/list-packages.sh` | `list-packages.sh [專案目錄]` 偵測專案類型並列出所有外部套件與目前版本(TSV:ecosystem / name / current) | python3 | +| `tools/latest-version.sh` | `latest-version.sh ` 查最新穩定版(npm / pypi / nuget) | curl、python3 | +| `tools/apply-version.sh` | `apply-version.sh ` 改寫版本來源檔案,把套件釘選到指定版本 | python3 | +| `tools/install-deps.sh` | `install-deps.sh ` 重新解析並安裝相依套件(npm install、pip install、dotnet restore) | npm、pip、dotnet | +| `tools/build-test.sh` | `build-test.sh ` 偵測並執行建置與測試 | npm、python3、pytest、dotnet | + +### 結束碼總表 + +一個數字只有一個意思,五支工具共用。新增工具請沿用這張表,不要自己編號。 + +| 碼 | 意思 | 呼叫方的動作 | +| --- | --- | --- | +| 0 | 成功 | 繼續 | +| 1 | 參數個數不對 | 停手 | +| 2 | ecosystem 不認識 | 停手 | +| 3 | 該 ecosystem 沒有來源檔案 | 跳過這個 ecosystem 或套件 | +| 4 | 依工具而定:`list-packages.sh`、`build-test.sh`、`install-deps.sh` 是指令不存在(停手);`latest-version.sh`、`apply-version.sh` 是查不到該套件(跳過) | 見左欄 | +| 5 | 依工具而定:`latest-version.sh`、`apply-version.sh` 是指令不存在(停手);`build-test.sh` 是推不出建置或測試指令(改問使用者) | 見左欄 | +| 6 | 找不到專案目錄 | 停手 | +| 其他 | 底層指令的結束碼 | 只有 `install-deps.sh`、`build-test.sh` 會走還原 | + +6 不與 3 合併:找不到專案目錄是輸入壞了,併進 3 會被當成跳過藏起來。`latest-version.sh` 不收專案目錄,所以沒有 6。 + +4 與 5 在各工具間意思不同,是為了保住既有的跳過路由;新增工具請優先用 4 表示指令不存在。 + +回 1、回 2、回 6 與回「指令不存在」時,技能只回報並停手,不還原工作樹——工具鏈壞了不是套件壞了,還原只會白白刪掉檔案。 ## Skills 目錄 From 35d4de6522af3b2b5c7a117bc9273bf3be44b867 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 25 Aug 2026 14:58:54 +0800 Subject: [PATCH 3/5] =?UTF-8?q?chore(pkg):=20=E4=B8=89=E4=BB=BD=20manifest?= =?UTF-8?q?=20=E5=90=8C=E6=AD=A5=E5=8D=87=E7=89=88=E4=B8=A6=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=20marketplace=20=E6=AD=A3=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What:三份 plugin manifest 版本同步 bump,兩份 marketplace 檔與 plugins/meta 正本對齊。 Why:準則要求技能異動必須同步升版;marketplace 副本必須與正本完全一致。 How:以 jsc-meta 的 tools/sync-skill-manifest.sh 升版,marketplace 檔由正本複製。 Who:jsc-meta:skill-check 例行稽核(2026-08-25)。 Co-Authored-By: Claude Opus 5 --- .agents/plugins/marketplace.json | 6 +++--- .claude-plugin/marketplace.json | 6 +++--- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- plugin.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index a9b4e66..8a2f91b 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -43,7 +43,7 @@ "source": "url", "url": "https://gitea.jsc.idv.tw/plugins/hooks.git" }, - "description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄" + "description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄、SDLC 模型鎖、版本前置檢查" }, { "name": "jsc-log", @@ -75,7 +75,7 @@ "source": "url", "url": "https://gitea.jsc.idv.tw/plugins/review.git" }, - "description": "程式碼審查:Refactoring 壞味道六組 + 註解規範 + 淺模組" + "description": "程式碼審查:Refactoring 壞味道六組、註解規範、淺模組" }, { "name": "jsc-sdlc", @@ -83,7 +83,7 @@ "source": "url", "url": "https://gitea.jsc.idv.tw/plugins/sdlc.git" }, - "description": "開發生命週期:規劃/分析/實作/維護(wiki 追蹤)" + "description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)" } ] } diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a9b4e66..8a2f91b 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -43,7 +43,7 @@ "source": "url", "url": "https://gitea.jsc.idv.tw/plugins/hooks.git" }, - "description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄" + "description": "跨 CLI hooks:STE100 語言強制、工時計時、技能用量記錄、SDLC 模型鎖、版本前置檢查" }, { "name": "jsc-log", @@ -75,7 +75,7 @@ "source": "url", "url": "https://gitea.jsc.idv.tw/plugins/review.git" }, - "description": "程式碼審查:Refactoring 壞味道六組 + 註解規範 + 淺模組" + "description": "程式碼審查:Refactoring 壞味道六組、註解規範、淺模組" }, { "name": "jsc-sdlc", @@ -83,7 +83,7 @@ "source": "url", "url": "https://gitea.jsc.idv.tw/plugins/sdlc.git" }, - "description": "開發生命週期:規劃/分析/實作/維護(wiki 追蹤)" + "description": "開發生命週期:規劃、分析、實作、維護(wiki 追蹤)" } ] } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 3f65887..3f02e63 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-pkg", - "version": "0.0.3", + "version": "0.0.5", "description": "套件批次更新(nodejs/python/dotnet),失敗還原", "skills": "./skills", "author": { diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 26561ef..14f0d74 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-pkg", - "version": "0.0.3", + "version": "0.0.5", "description": "套件批次更新(nodejs/python/dotnet),失敗還原", "skills": "./skills" } diff --git a/plugin.json b/plugin.json index 923fddf..e4e2e85 100644 --- a/plugin.json +++ b/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-pkg", - "version": "0.0.3", + "version": "0.0.5", "description": "套件批次更新(nodejs/python/dotnet),失敗還原", "skills": "./skills/" } From 992d9c759cece008a9384ebd4225be3af763fd5b Mon Sep 17 00:00:00 2001 From: Jeffery Date: Wed, 26 Aug 2026 19:00:22 +0800 Subject: [PATCH 4/5] =?UTF-8?q?feat(pkg-update):=20=E5=8A=A0=E5=85=A5?= =?UTF-8?q?=E8=A8=BB=E8=A7=A3=E7=95=8C=E7=B7=9A=E8=A6=8F=E5=89=87=E8=88=87?= =?UTF-8?q?=20README=20=E5=90=8C=E6=AD=A5=E8=AA=AA=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What:在 pkg-update 技能的步驟 3.5 新增註解界線規則,並在 README.md 的 pkg-update 段落同步同一份指引。 Why:套件更新途中常會為了鎖版本或繞道不相容而留註解,過去沒有界線,容易把文件相關資訊寫進程式碼註解,造成註解與文件重複、且內容很快過期。 How:規則正文留在 jsc-review 的 references/comment-scope.md,這裡只放指引與連結、不重複清單。註解只寫鎖版本或繞道的原因;第三方套件的 issue 連結屬白名單,用來說明繞道成因與解除條件;內部議題編號、工作包編號、人名與 @ 提及、產生來源署名一律不得寫。步驟 3.5 另附可檢核的完成條件,並指向 jsc-hooks 的 comment-scope.sh 即時告警與修正回檢流程。 Who:jsc-pkg 的 pkg-update 技能,以及 README.md 的技能說明區塊。 --- README.md | 2 ++ skills/pkg-update/SKILL.md | 1 + 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index 93d7b23..06362db 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ Marketplace 統一為 `jsc`(https://gitea.jsc.idv.tw/plugins/meta.git),安 套件批次更新:列套件 → 查最新穩定版 → 逐 ecosystem 以 sub agent 更新 → 建置與測試(指令不明時決策樹詢問)→ 失敗還原全部變更。 +更新途中要在版本來源檔案或程式碼留註解時,只寫鎖版本或繞道的原因,不寫內部議題編號、工作包編號、人名與 @ 提及、產生來源署名;第三方套件的 issue 連結可以寫,用來說明繞道成因與解除條件。完整清單與白名單見 [`jsc-review`](https://gitea.jsc.idv.tw/plugins/review) 的 `references/comment-scope.md`。 + ## 相關 domain diff --git a/skills/pkg-update/SKILL.md b/skills/pkg-update/SKILL.md index 345cdff..4fb5f75 100644 --- a/skills/pkg-update/SKILL.md +++ b/skills/pkg-update/SKILL.md @@ -39,6 +39,7 @@ Exit 4 and exit 5 are the two codes whose meaning depends on the tool, so read t 2. Route every exit code per the table above. The skip route covers `latest-version.sh` exit 4 (package not found in the registry), `apply-version.sh` exit 3 (no version source file) and `apply-version.sh` exit 4 (package absent from the file): record the package and the reason, move on to the next package, and never abort the whole ecosystem. The stop route covers exit 1, exit 2, `latest-version.sh` or `apply-version.sh` exit 5 (a required command is missing) and `apply-version.sh` exit 6 (project directory not found): report the code and end the run without entering step 5. This substep is done when every exit code seen has taken exactly one route. 3. Run `tools/install-deps.sh {ecosystem} {project dir}` once, after every package of that ecosystem is applied. Exit 0 means the install finished. Exit 3 means this ecosystem has no dependency source file, which is the same documented skip as substep 2: record the ecosystem and the reason, and install nothing. Exit 1, exit 2, exit 4 and exit 6 take the stop route — exit 6 is a missing project directory, so report it instead of skipping it. Only another non-zero code is a real install failure and goes to step 5. This substep is done when the exit code is recorded together with the route it took. 4. The sub agent returns one row per package from substep 1: name, old version, new version — or `skipped` plus the reason. It also returns the `install-deps.sh` exit code and its route. The ecosystem is done only when every package appears in exactly one row. + 5. **Comments this step writes.** Holding a package at an older version, or coding around an incompatibility, sometimes needs a comment in the version source file or in the code. Write **why** the pin or the workaround exists, never a tracking number. The one this skill trips over most: **a third-party package's issue link is on the allow list** — it is what states the cause of the workaround and the condition for removing it, as in `// works around github.com/foo/bar/issues/88; drop this pin once that ships`. Out of a comment: internal issue ids, work package ids, personal names, `@` mentions and generated-by credits. Full list and allow list: `jsc-review/references/comment-scope.md`. `jsc-hooks/hooks/comment-scope.sh` compares every write against that list right after the file is written and prints a warning on a hit; fix the comment on the spot, then continue this step. Completion condition: every comment line this step added names a reason, carries no internal issue id, work package id, personal name, `@` mention or generated-by credit, and every `comment-scope.sh` warning this step received has been fixed and re-checked with no warning left. 4. Run `tools/build-test.sh {ecosystem} {project dir}` for every ecosystem and route on the exit code: - 0 → this ecosystem passed. - 1, 2, 4 or 6 → stop route. Report the code and the missing argument, ecosystem, command or directory, and enter no further step. Exit 4 means the toolchain is broken, not that the packages are broken, so reverting would destroy files for nothing. From 913a51796d29b5ffe620a5903fa590582b80ad18 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Wed, 26 Aug 2026 19:00:22 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat(manifest):=20=E4=B8=89=E4=BB=BD=20mani?= =?UTF-8?q?fest=20=E7=89=88=E6=9C=AC=E5=8D=87=E8=87=B3=200.0.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What:把 plugin.json、.claude-plugin/plugin.json、.codex-plugin/plugin.json 的 version 由 0.0.5 升為 0.0.6。 Why:pkg-update 技能新增註解界線規則,屬於行為變更,必須發版才會被各 CLI 的外掛版本守衛辨識並更新。 How:三份 manifest 同步改動同一個 version 欄位,其餘欄位不動,維持三份內容一致。 Who:jsc-pkg 外掛的三份 manifest。 --- .claude-plugin/plugin.json | 2 +- .codex-plugin/plugin.json | 2 +- plugin.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 3f02e63..4dfa658 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-pkg", - "version": "0.0.5", + "version": "0.0.6", "description": "套件批次更新(nodejs/python/dotnet),失敗還原", "skills": "./skills", "author": { diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 14f0d74..fb1d4d2 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-pkg", - "version": "0.0.5", + "version": "0.0.6", "description": "套件批次更新(nodejs/python/dotnet),失敗還原", "skills": "./skills" } diff --git a/plugin.json b/plugin.json index e4e2e85..0be2a4c 100644 --- a/plugin.json +++ b/plugin.json @@ -1,6 +1,6 @@ { "name": "jsc-pkg", - "version": "0.0.5", + "version": "0.0.6", "description": "套件批次更新(nodejs/python/dotnet),失敗還原", "skills": "./skills/" }