fix(meta): 補齊稽核缺失並修掉護欄失效

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 <noreply@anthropic.com>
This commit is contained in:
2026-08-25 14:58:54 +08:00
co-authored by Claude Opus 5
parent 287e3ff113
commit 9ab5b42864
12 changed files with 490 additions and 51 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
## Flow
1. Query the Gitea canonical marketplace for the authoritative domain list: run `jsc-gitea/tools/gitea.sh api GET /repos/plugins/meta/raw/.claude-plugin/marketplace.json`. Clone any domain repo missing from the working directory (`gitea.sh clone-url plugins/{domain}`) and pull the rest. Completion condition: every domain repo exists locally and is current.
1. Run `tools/sync-domains.sh` to sync every domain repo of the Gitea canonical marketplace. Completion condition: the script exits 0 and prints one `domain<TAB>path` line 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 and exit 1 means the canonical marketplace was unreadable — resolve either before continuing.
2. Audit every skill of every domain against the guidelines.md audit checklist — this step MUST run as a sub agent, one sub agent per domain repo. Each sub agent reports its findings: skill, failed checklist item, evidence (file:line), proposed fix. Completion condition: every domain has an audit result.
3. Present each failed item via the `jsc-ask:ask` decision tree (apply the proposed fix / skip / custom fix). Every option states its impact scope (example: skipping leaves the skill non-compliant until the next audit). Completion condition: every finding has a recorded decision.
4. Apply the confirmed fixes — the fix-application part MUST run as a sub agent, one sub agent per affected domain repo: modify the files per the confirmed fix. Then run `tools/sync-skill-manifest.sh {domain-path}` directly (no sub agent needed) for each affected domain repo to refresh that domain README's 「Skills 目錄」 section and bump the version in all three manifests. Completion condition: every affected repo carries the fixes and the manifest bump.
+20 -12
View File
@@ -1,6 +1,6 @@
---
name: skill-delete
description: Remove a skill from the jsc skill set safely. List skills from the Gitea canonical marketplace (cloning any missing domain repo) and let the user pick, inventory every file referencing the skill via a sub agent, fix each affected file through decision-tree questions until guideline checks pass, then delete the skill, verify the removal is clean, and open a PR via jsc-git pr. Use only for removal; not for renaming (use skill-update).
description: Remove a skill from the jsc skill set safely. Pick the skill from the Gitea canonical marketplace skill list, inventory every file referencing it, fix each affected file through decision-tree questions until guideline checks pass, delete the skill and verify no on-disk leftover in any CLI, then open a PR via jsc-git pr. Use only for removal; not for renaming (use skill-update).
---
# skill-delete — delete a skill
@@ -9,14 +9,22 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
## Flow
1. Query Gitea for the canonical skill set first: run `jsc-gitea/tools/gitea.sh api GET /repos/plugins/meta/raw/.claude-plugin/marketplace.json` to get the authoritative domain list, then scan local `jsc-*/skills/*/SKILL.md` and present a "domain / name / description" list covering every domain in the marketplace. Completion condition: the list covers all marketplace domains.
2. For any marketplace domain whose repo is missing from the working directory, clone it first (`gitea.sh clone-url plugins/{domain}`), then rescan. Completion condition: every domain repo exists locally.
3. Let the user pick the skill to delete. Options state the impact scope: which skills reference it, and that its command stops working after deletion.
4. Inventory every file related to the skill: run `tools/find-skill-refs.sh {domain} {name}` to list every file across all jsc-* repositories referencing the skill name or its `/jsc-{domain}:{name}` command form (covers other SKILL.md files, the domain README's 「Skills 目錄」 section, the two marketplace.json files in `plugins/meta` plus their synced copies in every domain repo, `tools/`, and the `jsc-hooks` wiring). Completion condition: the tool's file list is captured for step 5.
5. For each affected file:
1. Decide whether the file needs a fix to keep its current behavior after the deletion. If no fix is needed, **skip the rest of this loop**.
2. Ask for fix details via the `jsc-ask:ask` decision tree (call a replacement skill? move a deterministic input/output flow to `tools/`? run the detailed flow as a sub agent? drop the feature too?). If the fix touches wiki or Gitea access, confirm it reads inherited environment variables before asking the user. Every option states its impact scope.
3. After fixing, check the guidelines.md audit checklist. On failure, return to step 5.2.
6. Delete the skill directory `skills/{name}/`, then run `tools/sync-skill-manifest.sh {domain-path}` directly (no sub agent needed) to sync the domain README and bump the version in all three manifests.
7. Deep-delete verification — this step MUST run as a sub agent: after deleting via each CLI's native plugin commands, physically inspect every installed CLI's on-disk skill and hook storage. Detect CLIs via `jsc-cli/tools/detect-clis.sh`; check Claude's `~/.claude/plugins/cache/` and hook entries in settings, plus the equivalent locations for codex / copilot / antigravity / kiro. Confirm no file or hook wiring for the deleted skill remains. Completion condition: every location checked and clean; remove any leftover by hand and recheck.
8. Call `jsc-git:pr` to open a Push Request.
1. Run `tools/sync-domains.sh` to sync every domain repo of the Gitea canonical marketplace. Completion condition: the script exits 0 and prints one `domain<TAB>path` line 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 and exit 1 means the canonical marketplace was unreadable — resolve either before continuing.
2. Run `tools/list-skills.sh` and present its `domain / name / description` rows to the user. The tool prints skills, not domains, so read the domain column to prove coverage. Completion condition: 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.
3. Let the user pick the skill to delete. Options state the impact scope: which skills reference it, and that its command stops working after deletion. Completion condition: one `{domain}/{name}` pair is confirmed for deletion.
4. Inventory every file related to the skill: run `tools/find-skill-refs.sh {domain} {name}` to list every file that references the skill name or its `/jsc-{domain}:{name}` command form, across every marketplace domain repo on this machine (covers other SKILL.md files, the domain README's 「Skills 目錄」 section, the two marketplace.json files in `plugins/meta` plus their synced copies in every domain repo, `tools/`, and the `jsc-hooks` wiring). The skill-name pattern is a bare substring match, so the list also carries other skills whose name starts with the same word plus plain prose — treat it as candidates to read, not as files that must change. Exit 1 means a clean zero-hit scan; exit 3 means the scan failed — fix the root path or the missing domain repos and rerun, never treat it as zero hits. Completion condition: the tool's file list is captured as the step 5 inventory.
5. Fix every file in the step 4 inventory. For each file:
1. Read the file and decide whether it needs a fix to keep its current behavior after the deletion. If no fix is needed, record it as no-fix-needed with the reason and **skip the rest of this loop**. Completion condition: the file carries a recorded verdict — needs-fix or no-fix-needed with a reason.
2. Ask for fix details via the `jsc-ask:ask` decision tree (call a replacement skill? move a deterministic input/output flow to `tools/`? run the detailed flow as a sub agent? drop the feature too?). If the fix touches wiki or Gitea access, confirm it reads inherited environment variables before asking the user. Every option states its impact scope. Completion condition: every question has a recorded answer.
3. Apply the confirmed fix, then check the guidelines.md audit checklist for the file — the per-file fix work MUST run as a sub agent, one sub agent per affected domain repo, each reporting one line per file: the path and either the applied fix or「無需修正」with the reason. On any checklist failure, return to step 5.2. Completion condition: the fix is in the file and every checklist item passes for it.
Completion condition: every file in the step 4 inventory is marked either fixed-with-a-clean-checklist or explicitly no-fix-needed with a reason — no file is left without a verdict.
6. Delete the skill directory `skills/{name}/`, then run `tools/sync-skill-manifest.sh {domain-path}` directly (no sub agent needed) to sync the domain README and bump the version in all three manifests. Completion condition: the directory is gone, the README's 「Skills 目錄」 no longer lists the skill, and all three manifests show the same new version.
7. Deep-delete verification: after removing the plugin through each CLI's native plugin commands, run `tools/verify-skill-removed.sh {domain} {name}`. It detects the installed CLIs and greps each one's skill cache and hook config for the skill. Route each exit code:
- Exit 1 — leftovers printed as `{file}:{line}:{content}`. Remove every one by hand, then rerun.
- Exit 2 — usage error. Fix the two arguments and rerun.
- Exit 3 — nothing was checkable: no CLI detected, or no config location exists. The script prints no leftover because it looked nowhere, so this is **never** clean. Report「無處可查」with the reason from stderr and stop the deep-delete verification here; state in the PR that on-disk verification did not run.
- Exit 0 — no leftover in the locations listed on stderr.
Completion condition: the script exits 0, or exit 3 is reported to the user and recorded in the PR.
8. Call `jsc-git:pr` to open a Push Request. Completion condition: a PR URL comes back.
+19 -10
View File
@@ -10,18 +10,27 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
## Flow
1. Ask for skill details via the `jsc-ask:ask` decision tree until no doubt remains:
- Goal (single and not duplicating an existing skill; first scan `jsc-*/skills/*/SKILL.md` and list similar skills for comparison — options must state the impact scope of "reuse existing" versus "create new")
- Goal (single and not duplicating an existing skill; run `tools/list-skills.sh` first and show the similar skills 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 use `jsc-gitea/tools/gitea.sh` + token)
- Owning domain (list the existing `jsc-*` domains to choose from)
2. If the domain does not exist (if the repository exists on Gitea but not in the working directory, clone it and skip to step 3):
1. Propose one short English word for the new domain (a single word preferred) and confirm it with the user.
2. Ask the user to create the repository `plugins/{domain}`. Clone it, then build the content following the structure of `https://gitea.jsc.idv.tw/plugins/template`: three plugin manifests (plugin name `jsc-{domain}`, version starting at `0.0.1`), `skills/`, README.md, AGENTS.md.
3. Add the plugin entry (URL source pointing at the new repository) to `.claude-plugin/marketplace.json` and `.agents/plugins/marketplace.json` in `plugins/meta` (the canonical copy), then sync the two updated files to every domain repository, including the new one. Every repo carries the same marketplace files, so any repo works as the registration entry point. The sync MUST run as a sub agent.
- Owning domain (run `tools/sync-domains.sh` and offer its domain list — the domains registered in the canonical marketplace)
Completion condition: goal, trigger, input/output and owning domain each have a recorded answer.
2. If the domain does not exist (`tools/sync-domains.sh` clones every domain **registered in the marketplace**, so a missing directory means the domain is unregistered — the repository itself may already exist on Gitea):
1. 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.
2. 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/repos` when `plugins` is an organization, `POST /user/repos` when `plugins` is the token's own account (`tea repo create` does 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 create `plugins/{domain}` by hand, then continue. Completion condition: `gitea.sh clone-url plugins/{domain}` prints a URL and cloning it succeeds.
3. Build the content following the structure of `https://gitea.jsc.idv.tw/plugins/template`: three plugin manifests (plugin name `jsc-{domain}`, version starting at `0.0.1`), `skills/`, README.md, AGENTS.md. Completion condition: the three manifests, `skills/`, README.md and AGENTS.md all exist in the new repo.
4. Register the plugin: run `tools/sync-marketplace.sh {domain} {repo-url} {description}`. It needs `python3` on PATH — it edits the marketplace JSON with the json module. It writes the entry into both canonical marketplace files in `plugins/meta` and 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 — missing python3, an unreadable canonical file, or a byte mismatch between copies. Read stderr, fix the named cause (install python3 for the first), 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.
3. Generate the skill per guidelines.md — this step MUST run as a sub agent:
- `skills/{name}/SKILL.md`: entirely in English (description ≤ 5 sentences with trigger conditions; body in STE100-style English)
- `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 to `tools/`
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.
4. Self-check every item of the guidelines.md audit checklist; fix anything that fails.
5. Call `jsc-git:pr` to open a Push Request.
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. Completion condition: `skills/{name}/SKILL.md` exists, the README lists the skill, and all three manifests show the same new version.
4. Self-check every item of the guidelines.md audit checklist; fix anything that fails. Completion condition: every checklist item passes.
5. Call `jsc-git:pr` to open a Push Request. Completion condition: a PR URL comes back.
+8 -8
View File
@@ -1,6 +1,6 @@
---
name: skill-update
description: Update an 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, then re-check against the guidelines checklist until it passes and open a PR via jsc-git pr. Use for modifying a skill; not for creating (skill-new) or removing (skill-delete).
description: 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, then re-check against the guidelines checklist until it passes and open a PR via jsc-git pr. 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
@@ -9,10 +9,10 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
## Flow
1. Query Gitea for the canonical skill set first: run `jsc-gitea/tools/gitea.sh api GET /repos/plugins/meta/raw/.claude-plugin/marketplace.json` to get the authoritative domain list, then scan local `jsc-*/skills/*/SKILL.md` and present a "domain / name / description" list covering every domain in the marketplace. Completion condition: the list covers all marketplace domains.
2. For any marketplace domain whose repo is missing from the working directory, clone it first (`gitea.sh clone-url plugins/{domain}`), then rescan. Completion condition: every domain repo exists locally.
3. Let the user pick the skill to update.
4. Ask for update details via the `jsc-ask:ask` decision 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).
5. Update the skill — the modification part MUST run as a sub agent: modify SKILL.md and related files. 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.
6. Check every item of the guidelines.md audit checklist. On any failure, **return to step 4**: ask again and fix, until all items pass.
7. Call `jsc-git:pr` to open a Push Request.
1. Run `tools/sync-domains.sh` to sync every domain repo of the Gitea canonical marketplace. Completion condition: the script exits 0 and prints one `domain<TAB>path` line 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 and exit 1 means the canonical marketplace was unreadable — resolve either before continuing.
2. Run `tools/list-skills.sh` and present its `domain / name / description` rows to the user. The tool prints skills, not domains, so read the domain column to prove coverage. Completion condition: 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.
3. Let the user pick the skill to update. Completion condition: one `{domain}/{name}` pair is confirmed.
4. Ask for update details via the `jsc-ask:ask` decision 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.
5. Update the skill — the modification part MUST run as a sub agent: modify SKILL.md and related files. 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. Completion condition: the skill files carry the change and all three manifests show the same new version.
6. Check every item of the guidelines.md audit checklist. On any failure, **return to step 4**: ask again and fix, until all items pass. Completion condition: every checklist item passes.
7. Call `jsc-git:pr` to open a Push Request. Completion condition: a PR URL comes back.
+2 -2
View File
@@ -10,7 +10,7 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
## Flow
1. Ask for the change details via the `jsc-ask:ask` decision tree: what rule or behavior changes, which skills and which domains are affected. Include three required checks before the affected-skill list is final: whether any deterministic input/output flow must move to `tools/`, whether any detailed flow must run as a sub agent, and whether any wiki or Gitea flow must read inherited environment variables before asking the user. Every option states its impact scope (example: changing a shared flow step touches every skill that calls it). Completion condition: the affected-skill list and the three checks are agreed with the user.
2. Query the Gitea canonical marketplace for the authoritative domain list: run `jsc-gitea/tools/gitea.sh api GET /repos/plugins/meta/raw/.claude-plugin/marketplace.json`. Clone any domain repo missing from the working directory (`gitea.sh clone-url plugins/{domain}`) and pull the rest. Completion condition: every domain repo exists locally and is current.
2. Run `tools/sync-domains.sh` to sync every domain repo of the Gitea canonical marketplace. Completion condition: the script exits 0 and prints one `domain<TAB>path` line 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 and exit 1 means the canonical marketplace was unreadable — resolve either before continuing.
3. Apply the change to every affected skill — the modification part MUST run as a sub agent, one sub agent per affected domain repo: modify SKILL.md and related files and tools. Then run `tools/sync-skill-manifest.sh {domain-path}` directly (no sub agent needed) for each affected domain repo to sync that domain README's 「Skills 目錄」 section and bump the version in all three manifests. Completion condition: every affected domain repo carries the change, the README sync, and the manifest bump.
4. Check every item of the guidelines.md audit checklist for each touched skill. On any failure, **return to step 1**: ask again and fix, until all items pass.
4. Check every item of the guidelines.md audit checklist for each touched skill. On any failure, **return to step 1**: ask again and fix, until all items pass. Completion condition: every checklist item passes for every touched skill.
5. Call `jsc-git:pr` once per affected domain repo to open a Push Request. Completion condition: every affected repo has a PR URL.
+14 -9
View File
@@ -1,6 +1,6 @@
---
name: ste100-sync
description: Sync the STE100 language rules with upstream speak-human-tw. Compare the pinned upstream version in references/ste100.md against the latest release, distill applicable changes, refresh ste100-lint.sh patterns, re-lint all jsc repos, then open a PR via jsc-git pr. Use on periodic maintenance or when upstream releases a new version; not for editing local-only rules.
description: Sync the STE100 language rules with upstream speak-human-tw. Compare the pinned upstream version in references/ste100.md against the latest release, distill applicable changes and confirm each one via decision tree, refresh ste100-lint.sh patterns, re-lint all jsc repos, then open a PR via jsc-git pr. Use on periodic maintenance or when upstream releases a new version; not for editing local-only rules.
---
# ste100-sync
@@ -9,17 +9,22 @@ Keep `references/ste100.md` in sync with its upstream source, [speak-human-tw](h
## Steps
1. Read the pinned version from the「上游版本」line in `references/ste100.md`.
2. Clone the upstream repo (`--depth 1`). Read the `version` and `changelog` fields in its `SKILL.md` frontmatter.
3. Same version: report「上游沒有新版」and stop.
4. Newer version — distill the changes. **MUST run as a sub agent**:
1. Read the pinned version from the「上游版本」line in `references/ste100.md`. Completion condition: the pinned version string is in hand.
2. Clone the upstream repo (`--depth 1`). Read the `version` and `changelog` fields in its `SKILL.md` frontmatter. Completion condition: the upstream version string and its changelog entries are in hand.
3. Same version: report「上游沒有新版」and stop. Completion condition: either the run stops here, or the upstream version is newer than the pinned one.
4. Newer version — distill the changes into a change list. **MUST run as a sub agent**:
- Walk the changelog entries newer than the pinned version.
- Keep only changes that apply to technical documents and conversation: Taiwan term replacements, punctuation rules, de-AI patterns, humanize targets.
- Drop marketing-copy scenes, eval material, and workflow-mode changes.
- Apply the distilled changes to `references/ste100.md`. Keep its trimmed structure. Update the「上游版本」line.
5. If the replacement table or cliché list changed, update the `TERMS` and `CLICHES` patterns in `tools/ste100-lint.sh`.
6. Run `tools/ste100-lint.sh` over every jsc repo. Fix hits in files this repo owns; report hits elsewhere.
7. Open a PR via `jsc-git:pr`.
- Decide nothing and edit no file. Report one line per candidate change: the rule, the upstream wording, and what it would change in `references/ste100.md` or in the lint patterns.
Completion condition: every kept changelog entry appears as one line in the distilled list.
5. Present the distilled list via the `jsc-ask:ask` decision tree, one question per change (adopt / drop / adapt). Every option states its impact scope (example: adopting a term replacement changes the `TERMS` pattern, so every repo re-linted in step 8 can gain new hits). `references/ste100.md` is the single source of truth for the whole skill set, so no change lands without a recorded decision. Completion condition: every distilled change has a recorded decision.
6. Apply the adopted and adapted changes to `references/ste100.md`. Keep its trimmed structure. Update the「上游版本」line. Completion condition: every adopted change is visible in the file and the「上游版本」line shows the new upstream version.
7. If the replacement table or the cliché list changed, update the `TERMS`, `CLICHES` and `SIMPLIFIED` patterns in `tools/ste100-lint.sh`. Completion condition: `sh -n tools/ste100-lint.sh` passes and each newly adopted term hits on a test string.
8. Run `tools/ste100-lint.sh` over every jsc repo (`tools/sync-domains.sh` prints the repo paths). Fix hits in files this repo owns. Completion condition: the lint exits 0 for this repo, and hits in other repos are reported with `file:line` for their owners.
9. Run `tools/sync-skill-manifest.sh .` to sync the README's 「Skills 目錄」 section and bump the manifests. Completion condition: all three manifests show the same new version.
10. Open a PR via `jsc-git:pr`. Completion condition: a PR URL comes back.
## Notes