Files
meta/skills/tooling-guide/SKILL.md
T
jiantw83 b87dbb12cd feat(狀態回報): 收尾寫一筆 skill-end 事件
現行紀錄只記「被叫用」,沒有成敗也沒有結束碼。跑完整輪的技能與開場就
中止的技能,在紀錄裡長得一模一樣。

start 由技能用量 hook 順手發,不必改技能文件。end 只能由技能自己在收尾
步驟寫——hook 接在技能工具呼叫上,而實際工作發生在之後的模型輪次,它在
原理上看不到成敗。有 start 沒有配對的 end,就是那一輪中止了。

status 五選一,每支技能各自寫明什麼情況選哪一個。找不到回報腳本就安靜
跳過,回報失敗一律不改變技能自己的結論。
2026-09-02 16:01:16 +08:00

144 lines
17 KiB
Markdown

---
name: tooling-guide
description: Inventory the current jsc plugins, skills, hook management, and usage paths as the baseline tooling guide, taking the skill, CLI, and hook-wiring facts from one inventory-tooling.sh run rather than re-running the scripts it already called. On request, publish that inventory through jsc-gitea:wiki to TOOLING_{HASH}, hashed from {hostname}/{tool}/{account}, and register it in TOOLING_CONTENTS. Use when the user asks for a skill-set guide, tooling map, supported plugin list, supported skill list, hook management overview, or onboarding reference. Do not use for installing, updating, deleting, auditing, or repairing the skill set; use jsc-cli:deploy, jsc-meta:skill-check, jsc-meta:skill-update, jsc-meta:skill-delete, or jsc-hooks:hooks-install instead.
---
# tooling-guide - build the baseline tooling guide
Goal: produce a current guide for the jsc skill set from the local repos and the supported tooling scripts.
Single source of guidelines: [`../../references/guidelines.md`](../../references/guidelines.md).
## Rules
- Every factual claim in the guide carries the source path or the tool output line it came from.
- Prefer script output over copied lists.
- Use `tools/inventory-tooling.sh` for the baseline inventory.
- Keep command syntax in the guide only when it comes from README files or tool output.
- Do not modify README files, manifests, marketplace files, hooks, tools, or other skills.
- Put generated guide text in the response or in the user-requested target only.
- Run detail synthesis as a sub agent when the guide needs explanations, grouping, or onboarding prose.
- Route every wiki read and write through `jsc-gitea:wiki`, and every `{HASH}` through `jsc-gitea/tools/hash-id`.
- Close every run with the step 8 `skill-end` event. That one line in `$JSC_HOME/usage/events.jsonl` is the only thing this skill writes outside the recorded output target, and the rule above about not modifying files does not cover it.
Done when each rule above has a recorded pass, or a recorded exception naming the claim and the reason, checked before the final report.
## Inputs
- Optional user scope: plugin inventory, skill inventory, hook management, CLI usage, or all areas.
- Optional output target: chat response, wiki draft text, a named file that the user explicitly requests, or the wiki pages `TOOLING_{HASH}` and `TOOLING_CONTENTS`.
Done when the scope and the output target are each written down as one of the values listed above. With no scope given, write down `all areas`. With no target given, write down `chat response`. Only the `wiki page` target runs step 7.
## Flow
1. Confirm the working roots. Run `tools/plugins-root.sh` — it prints the workspace root that holds the domain checkouts, and it is the same derivation every other tool here uses. Exit 1 means the root could not be derived: read stderr, set `JSC_PLUGINS_ROOT` to the directory that holds the domain repos, and rerun. Under a plugin install the tools sit in the CLI's plugin cache, so the built-in guess lands in that cache instead of the workspace. The meta root is `{root}/meta`, or `{root}/jsc-meta` when that is the checkout name; the sibling directories under `{root}` are the domain checkouts. Completion condition: the script exits 0, and the meta root it names exists and contains `references/guidelines.md`.
2. Sync the domain inventory with `tools/sync-domains.sh`. This script owns marketplace discovery and local repo synchronization.
- Exit 0: continue with the printed `domain<TAB>path` rows.
- Exit 3: keep the printed rows, report every skipped or dirty repo from stderr as stale input, and continue only after the user accepts a guide with stale rows.
- Exit 2: report the clone failure and stop.
- Exit 1: report which cause stderr names — the root could not be derived, `gitea.sh` was not found, or the canonical marketplace was unreadable — then stop. For the root case, fix it the same way as step 1 and rerun.
Completion condition: each plugin row used by the guide has a domain and a local path, or the stale-input decision is recorded.
3. Collect the baseline inventory and the management-flow facts. The two halves are independent — one reads tool output, the other reads files — so run them **at the same time**.
**Baseline inventory.** Build it with `tools/inventory-tooling.sh` and use its Markdown output as the base document.
- Exit 0: continue with the generated guide.
- Exit 1: report which cause stderr names — the root could not be derived, the root does not exist, or the marketplace or `list-skills.sh` is missing — then stop.
- Any other exit: report the command, exit code, and stderr, then stop.
**This one run already covers the skill catalog, the CLI detection and the hook wiring status.** Internally it runs `meta/tools/list-skills.sh`, `cli/tools/detect-clis.sh` and `hooks/tools/wire-cli.sh status {cli}` and writes each result into its own section, so read those sections instead of calling the three scripts again:
- `Supported skills` — one row per skill, from `list-skills.sh`. An empty table means no skill was scanned; return to step 2.
- `Supported CLIs` — one row per detected CLI with its path and version, from `detect-clis.sh`. The single placeholder row means no CLI is installed here, or `detect-clis.sh` is missing; mark CLI-specific checks as not available on this machine.
- `Hook wiring status` — one row per detected CLI with the `wire-cli.sh status` exit code and verdict, `CLI 代號不符合 wire-cli.sh 用法` for exit 2 and `未知狀態,結束碼 {rc}` for anything outside 0, 1, 3 and 5. The single placeholder row means no CLI was detected or `wire-cli.sh` is missing; state the hook verdict as unknown and say why.
Re-running those three scripts on top of this buys nothing and can disagree with the base document — the second run sees a different machine state, and the guide then carries two answers for one fact. What that costs is written down under `Notes`.
**Management-flow facts.** Collect them from the current docs and skills. Read only README files, `SKILL.md` files, and tool help or headers from `tools/` under the domain repo paths that step 2 printed — never a hardcoded absolute path, because the workspace root differs per machine and per install form. Do not infer support from missing or stale files.
Completion condition: the generated guide contains `Source freshness`, `Supported plugins`, `Supported skills`, `Supported CLIs`, `Hook wiring status`, `Hook management`, `Plugin and skill management`, `Operational checks` and `Use this when`; the skill, CLI and hook facts used by the guide are quoted from those sections; and each management flow in the guide points to one source file or one tool output.
4. Synthesize the guide. This step MUST run as a sub agent when the output needs explanations, grouping, onboarding prose, or cross-domain comparison. Give the sub agent only the collected inventories, the relevant README and SKILL paths, and this required section list:
- Supported plugins
- Supported skills
- Supported CLIs and usage forms
- Hook management
- Plugin and skill management
- Health checks and repair paths
- Known coverage limits
Completion condition: the sub agent returns a guide draft with every required section and with source paths for each factual claim.
5. Verify the draft in the main agent.
- Check that each plugin comes from the step 2 `sync-domains.sh` rows.
- Check that each skill comes from the step 3 `Supported skills` section.
- Check that each CLI fact comes from the step 3 `Supported CLIs` section, and each hook-wiring fact from the step 3 `Hook wiring status` section.
- Check that install, update, delete, audit, repair, and health-check actions point to the owning skill or tool.
- Check that the draft does not copy long implementation details from README files or scripts.
Completion condition: every factual claim has a source path or tool output, and no required section is empty.
6. Deliver the guide in the requested target. If the target is chat, keep it concise and include the source paths used. If the target is a file, write only that user-requested file and do not update manifests or README files. If the target is the wiki page, step 7 performs the delivery — keep the chat summary short here and let step 7 report the page names and URLs. Completion condition: the guide is delivered and the final report names the target, source freshness, stale inputs if any, and any unknown hook verdicts.
7. Publish the inventory to the wiki. Run this step only when the recorded output target is the wiki page; for any other target, record `wiki publish skipped — target is {target}` and go to the final report. **This whole step MUST run as a sub agent.** Every wiki read and write goes through `jsc-gitea:wiki`; never assemble a Gitea API call here.
7.1 **Build one page name per detected CLI.** Take the CLI code names from the step 3 `Supported CLIs` section — that section already carries the first column of `jsc-cli/tools/detect-clis.sh`, one of `claude`, `codex`, `copilot`, `antigravity`, `kiro`. Pair each code name with this machine's host name and the current login account, then hand `{hostname}/{tool}/{account}` to `jsc-gitea/tools/hash-id`. The hash rules live in `../../references/guidelines.md` and are not restated here; compute nothing by hand. One page per host, CLI, and account: every CLI carries its own installed plugin set and its own hook wiring, and the tool segment is what keeps five CLIs off one page. A missing host name, tool name, or account stops the step — name the missing segment and substitute no default value. `hash-id` exit 1 means this machine has neither `sha1sum` nor `shasum`: stop and report that one of them has to be installed. Completion condition: every detected CLI has one `TOOLING_{HASH}` name built from three non-empty segments, all of them produced by `hash-id`.
7.2 **Resolve the wiki repo** for type `TOOLING` through `jsc-gitea:wiki`, which reads `JSC_WIKI_REPO_TOOLING` first and `JSC_WIKI_REPO` second. Exit 3 — neither variable is set: ask for that type's `{owner}/{repo}` per the `jsc-ask:ask` rules. Exit 2 — the installed `jsc-gitea` does not accept the `TOOLING` type yet: stop and report that the type has to be registered there first. Completion condition: exactly one `{owner}/{repo}` is recorded, and every write in this step targets it.
7.3 **Write the content pages first.** Render `templates/tooling-page.md` for each `TOOLING_{HASH}` from the step 3 inventory, keeping only that page's own CLI row in the `Supported CLIs` and `Hook wiring status` tables. Each run overwrites the whole page: it records what this machine looks like right now, so keeping earlier runs buys nothing. Content pages go before the contents page for the same reason as every other jsc skill — a contents row must never point at a page whose write failed. Completion condition: every `TOOLING_{HASH}` write returned exit 0, or its failure went to step 7.5.
7.4 **Register the pages in `TOOLING_CONTENTS` second.** Read that page first, then route the read exit code:
- 0 — the page is there. Find the row whose host, tool, and account all match this run, refresh that one row per `templates/tooling-contents.md`, leave every other row exactly as it was, and write the whole page back.
- 4 — the page does not exist yet. **This is the only code that allows creating it.** Build it from the template with this run's rows.
- 7 or 8 — the key was rejected, or the API failed, so the old content is unknown. Stop. Create nothing and overwrite nothing: a page built on top of unknown content deletes rows that nobody can get back. Report the exit code and the page name.
Completion condition: `TOOLING_CONTENTS` holds one row per page written in step 7.3, every row belonging to another machine or CLI is unchanged, or the step stopped with the read exit code and the page name reported.
7.5 **Route a failed write.** Retry the failed `jsc-gitea:wiki` write once. When it fails again, stop the publish and report the page name together with the content that never reached the wiki, so the user can place it by hand. Report a page as written only after its write returned exit 0. Completion condition: every page named in this step is either confirmed written with its page name, or listed as unwritten with its exit code and its full content.
8. Report this run's outcome to the local event stream — the last step of every run, the ones that stop early included, and the ones whose target was the chat response. Run:
`jsc-hooks/tools/report-status.sh skill-end jsc-meta:tooling-guide {status} {exit code} [detail]`
Resolve `jsc-hooks` from the `domain<TAB>path` row step 2 printed for the `hooks` domain, the same way this skill resolves every other cross-plugin script; when step 2 never produced rows, take the sibling checkout under the root step 1 printed. **When the 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 |
| --- | --- |
| `ok` | the guide holds every required section with a source behind each claim, it reached the recorded target, and — for the wiki target — every page write and the `TOOLING_CONTENTS` registration returned exit 0 |
| `blocked` | a gate or a missing prerequisite stopped the run before any inventory was built — `tools/plugins-root.sh` exited 1, or `sync-domains.sh` exited 2 or 1 |
| `failed` | the run broke mid-way — `inventory-tooling.sh` exited non-zero, or a wiki write failed again after its one retry |
| `degraded` | the guide was delivered with a part missing — stale rows were accepted from `sync-domains.sh` exit 3, a hook verdict stayed unknown, or the content pages were written while `TOOLING_CONTENTS` was not |
| `aborted` | the user stopped the run, or the user refused a guide built on stale input so this skill stopped on its own |
`{exit code}` is this run's own result as a number: `0` for `ok`, non-zero otherwise. `detail` is optional, one line, at most 200 characters.
The matching `skill-start` comes free from the hook, which fires when the skill loads. The inventory and the delivery happen in the model turns after that, so no hook can see how the run ended — a `start` with no `end` reads as an abort, which is why writing the `end` is this skill's own job. This is the one write a read-only skill still makes.
Completion condition: one `skill-end` line for this run is appended to `$JSC_HOME/usage/events.jsonl`, or the script was absent and the final report says so.
## Notes
- **Removed protection, on purpose.** The flow used to carry three more steps that re-ran `list-skills.sh`, `detect-clis.sh` and `wire-cli.sh status {cli}` after `inventory-tooling.sh` had already called all three. That second pass doubled as an independent cross-check: it read the same three facts straight from the source scripts, so a wrong skill row, a missing CLI, or a stale hook verdict produced by `inventory-tooling.sh` surfaced as a disagreement between the two sets. That cross-check is gone. The guide now takes the skill catalog, the CLI list and the hook wiring status from one `inventory-tooling.sh` run, with no second raw output to compare against, so a bug in that script's own scanning, parsing, or section writing reaches the guide unnoticed and reads as fact. Two things bound the risk: step 5 still rejects any claim with no source section behind it, and `Hook wiring status` carries the per-CLI exit code, so a nonsense verdict stays visible. When a decision rests on the guide's skill, CLI, or hook facts, get the second opinion elsewhere — run the three scripts by hand and compare, or run `jsc-cli:doctor` for an independent wiring verdict.
## Output Contract
The guide must include these fields in this order:
1. `Source freshness`: synced, stale accepted, or blocked.
2. `Supported plugins`: one row per domain.
3. `Supported skills`: one row per skill.
4. `Supported CLIs`: one row per detected CLI, or one sentence for none detected.
5. `Hook management`: wiring, smoke, error scan, repair owner, and coverage limits, with the per-CLI wiring verdicts from `Hook wiring status`.
6. `Plugin and skill management`: install, update, delete, audit, and creation owners.
7. `Operational checks`: doctor, setup, version guard, restart gate, language guard, and comment-scope guard.
8. `Use this when`: short usage guidance for maintainers.
Done when the output has all fields in order and each non-empty table has at least one source reference.
For the wiki-page target, the same fields go to `TOOLING_{HASH}` in the section order of `templates/tooling-page.md`, and the row registered in `TOOLING_CONTENTS` follows `templates/tooling-contents.md`. Both templates own their own field lists; do not restate them here.