Files
hooks/skills/repair/SKILL.md
jiantw83 4afb282c78 feat(狀態回報): 兩支技能的收尾寫一筆 skill-end
hook 在原理上看不到技能的成敗:它接在技能工具呼叫上,而實際工作發生在
之後的模型輪次。start 由技能用量 hook 順手發,end 只能由技能自己寫。
有 start 沒有配對的 end,就是那一輪中止了。
2026-09-02 16:05:54 +08:00

5.1 KiB

name, description
name description
repair Repair failed hook wiring by delegating diagnosis to installed AI agent CLIs as subagents, patching the hooks repo, syncing manifests, and opening a PR against develop. Use when hooks-install or report-error.sh reports a failed hook, or when a hook keeps failing after rewiring; not for routine wiring or unrelated work.

repair — repair a failed hook

Single source of guidelines: jsc-meta's references/guidelines.md.

This skill is exempt from the version guard and the post-deploy restart gate, because it is the only path back from a broken hook. hooks/version-guard.sh and hooks/restart-gate.sh own those two exemption lists.

Flow

  1. Read the failure context from ERROR_{HASH} through jsc-gitea:wiki, or from the failed status= line when no page was written. A wiki read that fails stops the skill: report which page could not be read and ask for the failure output instead of guessing. Done when the failure context names the script, the exit code and the CLI, and the PR base branch is fixed at develop.
  2. Run jsc-cli/tools/detect-clis.sh. It always exits 0 and prints one name<TAB>path<TAB>version line per installed CLI; empty output means no CLI is installed. Delegate diagnosis to one subagent per detected CLI — each MUST run as a sub agent, must receive the failure context, must stay read-only, and must return root cause, the files to change, and the verification command to run. Done when every detected CLI has returned one proposal, or the output was empty and the main agent has recorded that it diagnoses alone.
  3. Pick the smallest repair that makes the wiring pass, then apply it in the hooks repo. When the fix touches wiring behaviour, update hooks/tools/wire-cli.sh, hooks/skills/hooks-install/SKILL.md and hooks/README.md in the same change. Run tools/wire-cli.sh smoke {cli} for the affected CLI: exit 0 means the repair holds, exit 4 means it does not — go back to step 2 with the new output, exit 2 means a bad CLI name, so fix the name and rerun. Done when the fix is on disk and smoke exits 0.
  4. Run jsc-meta/tools/sync-skill-manifest.sh . from the repo root. Exit 0 means the README skill list and all three manifests carry the same new version. Exit 1 means a missing path, a missing JSC-SKILLS marker or an unreadable manifest — fix the named file and rerun. Exit 2 means a usage error, so pass exactly one path. Any other exit code is an environment fault, never a successful sync: stop and report it. Done when the script exits 0 and the three manifests show the same version.
  5. Commit, push and open a PR with jsc-git:pr against develop. When jsc-git:pr returns no PR URL, report the repair as applied but unmerged, name the branch that holds it, and hand back the failure reason — never claim a PR exists. Done when a PR URL comes back, or the branch name and the failure reason are both reported.
  6. Record how the repair ended. Run tools/report-status.sh skill-end jsc-hooks:repair {status} {exit} "{detail}" — the script is in this same repo, so it takes the plain tools/ path, like tools/wire-cli.sh in step 3. This step runs on every route out of steps 1 to 5, the ones that stopped early included. What records a skill's start fires when the skill is loaded and cannot see how it ended, so a repair that never writes this line is indistinguishable afterwards from one that was abandoned with a hook still broken.
    • {status} is one of five. ok: the fix is on disk, wire-cli.sh smoke exits 0 for every affected CLI, sync-skill-manifest.sh exits 0 with all three manifests on the same version, and a PR URL against develop came back. degraded: the repair holds — smoke exits 0 — but the change did not get all the way out, because jsc-git:pr returned no PR URL and the fix is sitting on a branch, or sync-skill-manifest.sh left the manifests unaligned. failed: the hook could not be repaired. Smoke still exits 4 after the diagnosis loop of step 2 came back around, or step 4 hit an environment fault, so the broken wiring is still broken. aborted: there was nothing to repair — step 1 found no failure context, no ERROR_{HASH} page and no failed status= line, so the run stopped on a precondition rather than on a fault. blocked does not arise: this skill is exempt from the version guard and the post-deploy restart gate, which are the only two gates that could hold it, and that exemption exists precisely because it is the way back from a broken hook.
    • Take {exit} from whatever decided the ending — the wire-cli.sh smoke or sync-skill-manifest.sh code — and otherwise use 0 for ok and 1 for every other status. {detail} is optional, one line, at most 200 characters: the hook and CLI that were repaired, or the branch that holds an unmerged fix. Diagnosis output and diffs never go on this line.
    • Reporting never changes the repair. report-status.sh swallows its own write failures and always exits 0, and an absent file is skipped in silence, so a missing reporter can never be the reason a repaired hook reads as unrepaired. Done when the call was made, or the script was absent and this step was skipped without a word.