Files
cli/skills/doctor/SKILL.md
T

6.1 KiB

name, description
name description
doctor Health-check the execution environment in one pass and record the result, changing nothing. Five checks - plugin versions from jsc-hooks/hooks/version-guard.sh report, hook wiring from jsc-hooks/tools/wire-cli.sh status, CLI, skill and hook runtime tests from tools/test-clis.sh, global settings and current-directory settings from tools/scan-config.sh against tools/config-spec.tsv. Report one findings table per check, then write the whole run to wiki CHECK_{HASH}; use for checkups, not fixes.

doctor - execution environment health check

Read-only. Every command below either reads local state, calls a read-only CLI command, or asks Gitea. None of them writes a setting. That is the contract with jsc-cli:setup: doctor states the facts, setup changes things.

Collection (steps 1 to 5) MUST run as a sub agent - one sub agent for all five, returning the raw TSV lines. Only the report and the wiki write stay in the main agent.

1. Skill versions

Run jsc-hooks/hooks/version-guard.sh report. It prints {domain}<TAB>{local}<TAB>{remote}<TAB>{落後|最新|超前|查詢失敗} per plugin, then behind<TAB>{count}.

A report with no {domain} row, or one carrying noregistry<TAB>{path}, means this CLI has no local plugin registry. Report it as 無法驗證 - never as 最新. behind<TAB>0 proves nothing when no domain row precedes it.

Done when every installed domain has a status literal, or the CLI is reported as unverifiable.

2. Hook wiring

Run jsc-hooks/tools/wire-cli.sh status {cli} for every CLI that tools/detect-clis.sh found. Use status and nothing else: wire-cli.sh without a subcommand rewires, purge deletes, and smoke executes hooks - all three break the read-only contract.

Exit codes: 0 wired, 1 degraded, 3 skipped because the CLI is not installed, 5 unwired. Each item line names one wiring point and whether it is present.

Only claude reaches wired. The other four have no pre-tool hook, so degraded is their healthy state. Report the degradation reason as-is and never present it as a defect to fix.

Done when every detected CLI has a status and its missing items are listed.

3. CLI runtime tests

Run tools/test-clis.sh with no CLI arguments. It calls tools/detect-clis.sh, then runs real commands for every detected CLI. It covers three areas: CLI commands, skill loading, and hook runtime smoke.

Output:

  • test<TAB>{area}<TAB>{cli}<TAB>{test}<TAB>{command}<TAB>{exit-code}<TAB>{verdict}<TAB>{detail}
  • summary<TAB>{ok}<TAB>{warn}<TAB>{fail}<TAB>{skipped}

Areas: cli, skill, hook.

Verdicts: ok, warn, fail, skipped.

Exit codes: 0 completed, 2 usage error, 3 missing detect-clis.sh. Any other script exit code is itself a doctor finding.

Treat every fail as a machine problem, including skill and hook rows. Treat warn as degraded capability: name it in the report, but do not put it in the fix table unless the failing skill needs that feature. Treat skipped as no conclusion. Map the report labels to the template as ok -> 通過, warn -> 降級, fail -> 失敗, and skipped -> 略過.

Done when every detected CLI has at least a version test row and the summary line is read.

4. Global settings

Run tools/scan-config.sh scan global. It checks every scope=global row of tools/config-spec.tsv and prints item<TAB>scope<TAB>required<TAB>actual<TAB>expect<TAB>fix<TAB>verdict, closing with summary<TAB>{missing}<TAB>{invalid}<TAB>{unset}<TAB>{skipped}.

Verdicts: ok, default, unset, missing, invalid, skipped.

Map the report labels to the template as ok -> 通過, default -> 走預設, unset -> 未設定, missing -> 缺漏, invalid -> 設錯, and skipped -> 略過.

Add -o when Gitea is unreachable; the Gitea-dependent rows then come back skipped. Report those rows as inconclusive and never as passes.

Also run tools/scan-config.sh orphans - variables used in the source but absent from the spec table. They are a maintenance note for the skill set, not a fault on this machine.

Done when the summary line is read and every missing and invalid row is named.

5. Own settings

Run tools/scan-config.sh scan project from the current working directory. Same output format, scope=project rows only.

Say which directory was scanned in the report. A project-scope result is meaningless without it, because the answer changes with every cd.

When .env or .envrc exists, name the spec-table variables it overrides and state the value actually in effect. A global setting silently overridden here is the failure this check exists to catch.

Done when the scanned directory is stated and every project row has a verdict.

6. Report and record

Report all five tables per templates/check-page.md. Then build the 待修項目 table from every missing, invalid, unwired and runtime fail item, plus every domain reported 落後. Order them missing -> invalid -> unwired -> runtime-fail -> 落後. Nothing wrong -> one row reading 無.

Write the page through jsc-gitea:wiki:

  • Wiki repo: jsc-gitea/tools/gitea.sh wiki-repo CHECK.
  • Page name: CHECK_ plus gitea.sh hash-id "{hostname}/{user}" - the host and the login account, not {owner}/{repo}. Doctor checks a machine, and it has to work in directories that are not repositories at all.
  • Overwrite the whole page. This page type keeps only the latest run.
  • Update CHECK_CONTENTS from templates/check-contents.md in the same pass.

wiki-repo exiting 3 means no wiki repo is configured for CHECK. Print the tables, skip the wiki write, and put JSC_WIKI_REPO_CHECK at the top of the 待修項目 table - that unset variable is itself a finding, so a failed write never fails the health check.

Done when either the wiki page URL is reported, or the skipped write is reported together with the reason.

7. Hand off

State the counts: required items missing, settings invalid, CLIs unwired, runtime failures grouped by cli, skill and hook, and domains behind. Recommend /jsc-cli:setup when any of those is above zero. Never fix anything here.

Done when the counts are stated and the recommendation is given or explicitly withheld.