現行紀錄只記「被叫用」,沒有成敗也沒有結束碼。跑完整輪的技能與開場就 中止的技能,在紀錄裡長得一模一樣。 start 由技能用量 hook 順手發,不必改技能文件。end 只能由技能自己在收尾 步驟寫——hook 接在技能工具呼叫上,而實際工作發生在之後的模型輪次,它在 原理上看不到成敗。有 start 沒有配對的 end,就是那一輪中止了。 status 五選一,每支技能各自寫明什麼情況選哪一個。找不到回報腳本就安靜 跳過,回報失敗一律不改變技能自己的結論。
13 KiB
name, description
| name | description |
|---|---|
| skill-update | Update one existing skill in the jsc skill set. List all skills from the Gitea canonical marketplace (cloning any missing domain repo) and let the user pick one, ask update details via decision tree, apply the change, re-check against the guidelines checklist until it passes, open a PR via jsc-git pr, then deploy and verify per references/deploy-verify.md from a fresh CLI process, and append the change report to wiki SKILLSET_{HASH}. Use for modifying a single skill; not for creating (skill-new), not for removing (skill-delete), and not for a change spanning several skills or domains (skillset-update). |
skill-update — update a skill
Single source of guidelines: ../../references/guidelines.md.
Flow
-
Run
tools/sync-domains.shto sync every domain repo of the Gitea canonical marketplace. Completion condition: the script exits 0 and prints onedomain<TAB>pathline per marketplace domain — exit 0 is the only code that means every repo is present and current. Exit 3 means some repos were not updated: reconcile every path named on stderr (commit or stash the dirty tree, or fix the failing pull) and rerun; when the user confirms a dirty tree is intentional local work, record that decision and continue on the local version — never read exit 3 as current. Exit 2 means a domain could not be cloned. Exit 1 means the root could not be derived,gitea.shwas not found, or the canonical marketplace was unreadable; when stderr says the root could not be derived, setJSC_PLUGINS_ROOTto the directory that holds the domain repos and rerun, because under a plugin install the script sits in the CLI's plugin cache and its built-in guess lands there instead of the domain workspace. Resolve 2 and 1 before continuing. -
Run
tools/list-skills.shand present itsdomain / name / descriptionrows to the user. The tool prints skills, not domains, so read the domain column to prove coverage. Exit 1 means the root could not be derived, the domain list was unreadable, or no skill was found — read stderr, fix the named cause (JSC_PLUGINS_ROOTfor the root case, as in step 1) and rerun; never read it as an empty skill set. Completion condition: the script exits 0 and every domain printed by step 1 appears in at least one row; a domain with no row means its repo is missing or holds no skill — return to step 1 for that domain. -
Let the user pick the skill to update. Completion condition: one
{domain}/{name}pair is confirmed. -
Ask for update details via the
jsc-ask:askdecision tree (change the goal? the trigger? the flow? move rules down to a hook or a tool?). Every option states its impact scope (example: renaming breaks the existing invocation command). Completion condition: every question has a recorded answer. -
Update the skill — the modification part MUST run as a sub agent: modify SKILL.md and related files. In the same pass, update this skill's
## {name}section inreferences/behaviors.mdso its five rows — 觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象 — describe the new behavior. A renamed skill gets its section renamed and moved back into dictionary order. The behavior list ships in this same PR: a behavior change that lands without its section makes the domain's list wrong from the merge onward, and the next audit reports drift this step created. Then runtools/sync-skill-manifest.sh {domain-path}directly (no sub agent needed) to sync the domain README's 「Skills 目錄」 section and bump the version in all three manifests. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path,skills/,README.md, theJSC-SKILLSmarkers, aSKILL.md, a manifest, or a manifestversionfield is missing, so fix the named cause on stderr and rerun; 2 — usage error, the script takes exactly one argument; any other code — the script runs underset -e, so treat it as an environment fault and stop, never as a successful sync. Completion condition: the skill files carry the change, the skill'sreferences/behaviors.mdsection states the new behavior with all five rows filled, and all three manifests show the same new version. -
Check every item of the guidelines.md audit checklist. Run
tools/check-behaviors.sh {domain-path}for the behavior-list item instead of comparing by eye, and route each exit code: 0 — the list matchesskills/and all five rows are filled; 1 — every mismatch is printed on stderr as{檔案}:{技能名}:{說明}, so fix each one and rerun; 2 — usage error, the tool takes exactly one argument; 3 — nothing was checked, becausereferences/behaviors.mdis missing,skills/is missing, or noSKILL.mdwas found, so create the missing file and rerun. Exit 3 is never a pass. On any failure, return to step 4: ask again and fix, until all items pass. Completion condition: every checklist item passes andtools/check-behaviors.sh {domain-path}exits 0. -
Call
jsc-git:prto open a Push Request. Completion condition: a PR URL comes back and is reported with the table format in../../references/pr-report.md. -
Deploy the update, verify it runs, then report:
-
Follow
../../references/deploy-verify.mdfrom section 1 to section 5:tools/deploy-route.sh {domain-path}picks the route, the deploy route or the worktree route runs, and the verification then runs in a fresh CLI process, never in the session that ran the deploy. That session raised the restart gate itself and still holds the old skill body, so verifying inside it either gets blocked or passes on stale behavior. Verify the updateddescriptionin the skill'stools/list-skills.shrow, every tool this change touched, and one minimal prompt per checkable CLI — the per-CLI prompts run in parallel. Completion condition: every completion condition indeploy-verify.mdsections 1 to 5 holds for this domain repo. -
Write the change report to the wiki — this part MUST run as a sub agent. It is two pages in two repos, and they must not be mixed up.
-
Content page
SKILLSET_{HASH}. Resolve its repo withjsc-gitea/tools/gitea.sh wiki-repo SKILLSET, which readsJSC_WIKI_REPO_SKILLSETfirst, thenJSC_WIKI_REPO.{HASH}isgitea.sh hash-id "{owner}/{repo}"of the changed domain repo, used at the full 40 characters it prints. Write it throughjsc-gitea:wikifollowing../../templates/skillset-page.md: append a section for this change — date, 「更新」, skill name, changed files, PR URL, the step 8.1 route verdict and verification result per item — and keep every earlier section. -
Directory page
SKILLSET_CONTENTS. It lives in the CONTENTS repo, never in the SKILLSET one.wiki-contents.shresolves it itself withgitea.sh wiki-repo CONTENTS, whose chain isJSC_WIKI_REPO_CONTENTSthenJSC_WIKI_REPOand never falls back toJSC_WIKI_REPO_SKILLSET. Build one file holding the single row from../../templates/skillset-contents.md, its 異動頁 cell written as[SKILLSET_{HASH}]({url})with the absolute URL fromgitea.sh wiki-url {SKILLSET repo} SKILLSET_{HASH}. Every link on both pages takes that[{text}]({url})form; the double-bracket wiki-link form resolves only inside one wiki, so it is never used. Then run:jsc-gitea/tools/wiki-contents.sh upsert SKILLSET 2 "{owner}/{repo}" {row file} templates/skillset-contents.mdThe key column is
2, the 存取庫 column, holding that repo's{owner}/{repo}exactly as the row file writes it, so one domain keeps exactly one row and no other domain's row moves. Never hand-edit the directory page. Write the content page first and fetch the URL only after it exists. -
Check the links before writing. Hand every URL going onto the content page and into the directory row to
jsc-gitea/tools/link-check.sh, and write only when it exits 0. It verifies through the Gitea API, never a web status code: a private repo answers 404 to an unauthenticated web request, so a status-code check would call a live page dead. -
Exit codes. Route every one of them:
Call Exit Do gitea.sh wiki-repo2 The page type was misspelled. Fix the argument and rerun 3 No wiki repo is configured for that type. Name the variable ( JSC_WIKI_REPO_SKILLSETfor the content page,JSC_WIKI_REPO_CONTENTSfor the directory page) andJSC_WIKI_REPO, ask per thejsc-ask:askrules, then rerungitea.sh hash-id1 No SHA-1 helper on this machine. Stop and report that sha1sumorshasumhas to be installed, and never hand-compute the hash2 Empty input, so the {owner}/{repo}was never resolved. Fix that firstContent page read 0 Append into the sections already there 4 The page does not exist yet, so build it from templates/skillset-page.md7 or 8 Stop and write nothing: a page rebuilt on top of an unread read loses every section already on it gitea.sh wiki-url4 The content page is not there, so the write above did not succeed. Go back and write it, and add no directory row until the page exists 5 The API answered with no html_url. Stop and report it; never assemble the URL by hand from the host and the page namelink-check.sh0 Every link is reachable. Write the page 1 At least one link is dead. Write nothing, and report the DEADlines it printed2 No URL was passed, which is a defect here. Pass the links and rerun 3 GITEA_HOSTis unset. Set it and rerun; never skip the check instead7 Gitea authentication failed. Stop and report the key problem, and never read it as a dead link wiki-contents.sh upsert0 The row is in place. Report the updatedoraddedit printed1 The write failed. Report SKILLSET_CONTENTSas not written, together with the row content2 An argument was rejected. Fix it and rerun; nothing was written 3 No CONTENTS wiki repo is configured. Report JSC_WIKI_REPO_CONTENTSandJSC_WIKI_REPOas the two variables to set; the new section is onSKILLSET_{HASH}and stays there4 The directory page is absent and no template was passed. Rerun with templates/skillset-contents.mdas the fifth argument7 The token is invalid or lacks permission, so the other domains' rows are unknown. Stop, report the token problem, and create no page 8 Some other API failure. Stop, report that status, and create no page
On any failure, hand the page name and the unwritten entry back to the user and leave this step open; never close the flow on an unwritten report. Completion condition:
SKILLSET_{HASH}holds the new section plus all earlier sections, andwiki-contents.sh upsertexited 0 with this domain's row onSKILLSET_CONTENTSlinking that page by absolute URL. -
-
-
Report this run's outcome to the local event stream — the last step of every run, the ones that stop early included. Run:
jsc-hooks/tools/report-status.sh skill-end jsc-meta:skill-update {status} {exit code} [detail]Resolve
jsc-hooksfrom thedomain<TAB>pathrow step 1 printed for thehooksdomain, the same way this skill resolves every other cross-plugin script. When that script is not on this machine, skip this step in silence and close the run as normal. A reporting path that is absent must never fail the run it reports on, and this call's own exit code never changes what this skill reports.Pick
{status}from what the run actually did:status Use it when okthe skill files and the behavior-list section carry the change, the checklist passes, the PR is open, deploy-verify.mdsections 1 to 5 hold, and both wiki writes exited 0blockeda gate or a missing prerequisite stopped the run before any file changed — sync-domains.shnever reached exit 0, or no skill could be listed to pick fromfailedthe run broke mid-way — the step 6 checklist loop kept failing, or a wiki write failed again after its one retry degradedthe update landed with a part missing — the content page was written while its SKILLSET_CONTENTSrow was not, or a CLI could not be verified and the reason was recordedabortedthe user stopped the run, or a prerequisite turned out not to hold and this skill stopped on its own {exit code}is this run's own result as a number:0forok, non-zero otherwise.detailis optional, one line, at most 200 characters.The matching
skill-startcomes free from the hook, which fires when the skill loads. The update itself happens in the model turns after that, so no hook can see how the run ended — astartwith noendreads as an abort, which is why writing theendis this skill's own job.Completion condition: one
skill-endline for this run is appended to$JSC_HOME/usage/events.jsonl, or the script was absent and the final report says so.