What:新增 references/behaviors.md,一支技能一節,共七支技能。每節五列,記下觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象。新增 tools/check-behaviors.sh,比對 skills/ 與這份清單。skill-new、skill-update、skill-delete、skillset-update 加上同步更新清單的步驟。skill-check 把這支腳本併進第一組稽核。 Why:技能驗證原本沒有基準,稽核只能靠眼睛比對 SKILL.md。十個 domain 每輪都要重做一遍,還會漏掉。行為清單當基準,技能改了、清單沒跟著改,就是漂移。漂移交給程式判定才穩。 How:腳本檢查節數、節名、節序、每節一張表、五個欄位齊全、內容欄非空。退出碼 0 代表相符,1 代表不符,2 代表用法錯誤,3 代表找不到清單或找不到 skills 目錄。domain 名以 plugin.json 的 name 為準,checkout 目錄名只是退路。四支異動技能在同一個 PR 內改清單,並照退出碼分流。 Who:屬於「技能行為清單」這件需求,提供技能驗證的參考基準。
9.9 KiB
name, description
| name | description |
|---|---|
| skill-new | Create a new skill in the jsc skill set. Prefetch the skill list and the domain list in parallel, ask skill details via decision tree, generate the skill under the right jsc-{domain} per guidelines.md (create the domain from the template repo if missing), 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 when the user wants to add a skill; not for editing an existing one (use skill-update). |
skill-new — create a skill
Single source of guidelines: ../../references/guidelines.md.
Flow
-
Collect the decision tree's inputs first, then ask:
-
Prefetch both inputs — run
tools/list-skills.shandtools/sync-domains.shin parallel. They share no data, and both answers are needed before the first question, so running them after the questions only makes the user wait. Route each exit code:list-skills.shexit 0 — keep thedomain<TAB>name<TAB>descriptionrows. Exit 1 — the root could not be derived, the domain list was unreadable, or no skill was found; read stderr and fix the named cause. When stderr says the root could not be derived, setJSC_PLUGINS_ROOTto the directory that holds the domain repos and rerun: under a plugin install the script sits in the CLI's plugin cache, so its built-in guess lands in that cache instead of the domain workspace.sync-domains.shexit 0 — the only code that means every repo is present and current; keep thedomain<TAB>pathrows. Exit 3 — 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. Exit 2 — a domain could not be cloned. Exit 1 — the root could not be derived,gitea.shwas not found, or the canonical marketplace was unreadable; for the root case setJSC_PLUGINS_ROOTas above and rerun. Resolve 2 and 1 before continuing.
Completion condition: the skill rows and the
domain<TAB>pathrows are both in hand. -
Ask for skill details via the
jsc-ask:askdecision tree until no doubt remains:- Goal (single and not duplicating an existing skill; show the similar skills from the step 1.1 rows for comparison — options must state the impact scope of "reuse existing" versus "create new")
- Trigger (when to use, when not to, trigger keywords)
- Input and output (can a standard input/output flow move down to
tools/; does it need Gitea operations — if so, make the skill usejsc-gitea/tools/gitea.sh+ token) - Owning domain (offer the domain list from the step 1.1
domain<TAB>pathrows — the domains registered in the canonical marketplace)
Completion condition: goal, trigger, input/output and owning domain each have a recorded answer.
-
-
If the domain does not exist (
tools/sync-domains.shclones every domain registered in the marketplace, so a missing directory means the domain is unregistered — the repository itself may already exist on Gitea):-
Propose one short English word for the new domain (a single word preferred) and confirm it with the user. Completion condition: the user confirms the domain word.
-
Check before creating: run
jsc-gitea/tools/gitea.sh clone-url plugins/{domain}. A URL comes back when the repository already exists — clone it, skip creation, and go on to step 2.3 to fill in whatever content is missing. Only when no URL comes back create the repository through the tool, never by hand:gitea.sh api POST /orgs/plugins/reposwhenpluginsis an organization,POST /user/reposwhenpluginsis the token's own account (tea repo createdoes the same job). Only when the call is refused (403 — the token has write but not admin rights on the owner) ask the user to createplugins/{domain}by hand, then continue. Completion condition:gitea.sh clone-url plugins/{domain}prints a URL and cloning it succeeds. -
Build the content following the structure of
https://gitea.jsc.idv.tw/plugins/template: three plugin manifests (plugin namejsc-{domain}, version starting at0.0.1),skills/, README.md, AGENTS.md. Completion condition: the three manifests,skills/, README.md and AGENTS.md all exist in the new repo. -
Register the plugin: run
tools/sync-marketplace.sh {domain} {repo-url} {description}. It needspython3on PATH — it edits the marketplace JSON with the json module. It writes the entry into both canonical marketplace files inplugins/metaand copies both into every domain repo, so any repo works as the registration entry point. Route each exit code:- Exit 3 — written, but some domain repo is not present locally. Run
tools/sync-domains.sh, then rerun this step. - Exit 2 — usage error. Fix the three arguments and rerun.
- Exit 1 — the root could not be derived, python3 is missing, a canonical file was unreadable, or copies differ byte for byte. Read stderr and fix the named cause: install python3 for the second; for the root case set
JSC_PLUGINS_ROOTto the directory that holds the domain repos, because under a plugin install the script sits in the CLI's plugin cache and its built-in guess lands there. Then rerun. - Exit 0 — every copy holds identical bytes; the script verifies that itself.
Completion condition: the script exits 0 and prints the touched paths.
- Exit 3 — written, but some domain repo is not present locally. Run
-
-
Generate the skill per guidelines.md — this step MUST run as a sub agent:
skills/{name}/SKILL.md: entirely in English (description within either cap — ≤ 5 sentences or ≤ 5 steps — and stating when to use and when not to; body in STE100-style English)- Rules enforceable by hooks go to
jsc-hooks(never scattered in this domain); standard input/output flows go totools/ references/behaviors.md: add one## {name}section for the new skill, placed in dictionary order among the existing sections, carrying the five rows the guidelines' 「技能行為清單」 section defines — 觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象. Write what the skill really does; do not copy thedescription. A read-only skill still fills 可驗證跡象 with 「無寫入跡象,只有回報內容」. The behavior list ships in this same PR — a skill added without its section leaves the domain's list out of sync the moment this PR merges. When the domain has noreferences/behaviors.mdyet, create it with the header line# jsc-{domain} 技能行為清單.
Then run
tools/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:skills/{name}/SKILL.mdexists,references/behaviors.mdholds a## {name}section with all five rows filled, the README lists the skill, and all three manifests show the same new version. -
Self-check every item of the guidelines.md audit checklist; fix anything that fails. 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. 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 new skill, 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 added skill's row intools/list-skills.sh, every tool the skill added, 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 wiki page
SKILLSET_{HASH}— this part MUST run as a sub agent. Calljsc-gitea:wiki;{HASH}comes from the{owner}/{repo}of the domain repo that gained the skill, and the wiki repo resolves throughJSC_WIKI_REPO_SKILLSETfirst, thenJSC_WIKI_REPO. Append a section for this change — date, 「新增」, skill name, changed files, PR URL, the step 6.1 route verdict and verification result per item — and keep every earlier section. Add the page toSKILLSET_CONTENTSwhen it is new. When the write fails — no{owner}/{repo}resolves, orjsc-gitea:wikireports an API error — 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: the page holds the new section plus all earlier sections, andSKILLSET_CONTENTSlinks it.
- Follow