feat(狀態回報): 收尾寫一筆 skill-end 事件

現行紀錄只記「被叫用」,沒有成敗也沒有結束碼。跑完整輪的技能與開場就
中止的技能,在紀錄裡長得一模一樣。

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

status 五選一,每支技能各自寫明什麼情況選哪一個。找不到回報腳本就安靜
跳過,回報失敗一律不改變技能自己的結論。
This commit is contained in:
2026-09-02 16:01:14 +08:00
parent 9f7865b428
commit bf68ee3436
3 changed files with 40 additions and 6 deletions
+17
View File
@@ -24,6 +24,23 @@ description: 'Group all pending file changes by conventional type and feature, t
- Exit 4 (API call failed) → report the failure and leave the PR state as unknown. Never read a failed call as "no open PR": that leaves a stale title on a branch that just gained commits.
- Any other non-zero → treat it as exit 4.
- Done when the report states exactly one of these: the lookup was skipped because `jsc-git:pr` called this run, the branch has no open PR, `jsc-git:pr` reported each of the three items as matched or updated, or the lookup failed and the failure is named.
6. Record how this run ended, as the very last thing this skill does:
`jsc-hooks/tools/report-status.sh skill-end jsc-git:commit {status} {exit} "{detail}"`
Resolve that path the way step 2 already resolves `jsc-hooks/hooks/comment-scope.sh` — the sibling plugin directory, no separate lookup rule for this one call. **A missing script is not a failure here: skip this step in silence and let the run end as it stands**, the same way step 2 commits anyway when the sweep is not installed. The script swallows its own write errors and exits 0 even then, so nothing branches on its code either. Commits that landed stay landed whether or not the run could be recorded.
| status | This skill's case |
| --- | --- |
| `ok` | Every group is committed, `git status --porcelain` prints nothing, and step 5 stated one of its four outcomes. A step 2 sweep that was skipped because the script is not on this machine is still `ok` — say so in `{detail}`, since a run judged without the sweep is worth telling apart from one the sweep passed |
| `blocked` | The `jsc-hooks` PreToolUse `Bash` guard rejected the commit before git ran — a bulk `git add -A` pair, or a message carrying no Traditional Chinese — so no commit landed and the working tree is exactly as it was |
| `degraded` | Every group is committed and the tree is clean, but the close-out is short: step 5's `pr-of-branch` returned 4, or the `jsc-git:pr` calibration failed, so the open PR still carries a title written before these commits |
| `failed` | A `git add` or `git commit` returned non-zero part-way through, leaving some groups committed and the tree dirty. Report the group that broke; a partial commit set is what the next run has to reconcile |
| `aborted` | Step 1's inventory came back empty, so there was nothing to commit and nothing was attempted. Also the user stopping the run at the grouping or the message-style question. This is not a success: a run that committed nothing must not read like a run that committed everything |
`{exit}` is the exit code of whatever decided the status, `0` for `ok`. `{detail}` is one short line well under 200 characters: group and commit counts plus exit codes, never commit messages, branch names, or personal data.
Done when the command has run, or the script was absent and this step was skipped.
## Type table
+17
View File
@@ -77,6 +77,23 @@ The ladder rules live in one place only: section 「PR 分支階梯」 of `jsc-m
Then report the PR with the table format in `jsc-meta/references/pr-report.md`, followed by the base branch, the target branch, which of the three calibration items were updated, the feature trunk the script auto-created when step 4 printed that line, and every comment that got no reply.
Done when every handled comment holds either a reply link or a recorded failure reason, and the report includes the PR table columns `{owner}/{repo}`, PR number, PR URL and PR summary, names all branch and calibration details, and names the comments that got no reply.
10. Record how this run ended, as the very last thing this skill does:
`jsc-hooks/tools/report-status.sh skill-end jsc-git:pr {status} {exit} "{detail}"`
Resolve that path the way this file already resolves `jsc-gitea/tools/gitea.sh` — the sibling plugin directory, no separate lookup rule for this one call. **A missing script is not a failure here: skip this step in silence and let the run end as it stands.** The script swallows its own write errors and exits 0 even then, so nothing branches on its code either. A PR that is open stays open whether or not the run could be recorded.
| status | This skill's case |
| --- | --- |
| `ok` | A PR URL is held, the prerequisite is settled by a `pr-depend` exit 0 or by a description that names none, and every handled comment holds a reply link. Calibrating an existing PR and changing none of the three items is `ok` as well: silence is the correct outcome there |
| `blocked` | The ladder refused before anything was pushed: `base-branch.sh` exit 3 (origin unreachable), exit 4 (the caller base is not on origin), exit 7 (no unique legal base), exit 8 (the derived base is missing on origin) or exit 9 (the auto-create failed). No branch reached origin and no PR was opened |
| `degraded` | The PR is open but part of the close-out did not land: `pr-depend` exit 4 sent the run to the `WIP:` fallback, so the dependency is not on the PR, or a handled comment ended with a recorded failure instead of a reply link |
| `failed` | The run got partway and then git or the API refused: `pick-type.sh` exit 3 (commits exist but no subject carries a ladder type), a push that failed, `pr-create` exit 4, or a non-zero `pr-edit` that left the old title and description in place |
| `aborted` | **`pick-type.sh` exit 2 — step 2 produced no commit, so there is nothing to open a PR for.** That is a run which correctly stopped, not a run that failed and not a run that succeeded; recording it as anything else is what made a round with no change look identical to a round that shipped eight PRs. The user declining the confirmation before `pr-create`, `pr-edit` or `pr-depend` is `aborted` too |
`{exit}` is the exit code of whatever decided the status, `0` for `ok` — so the no-change round above carries `aborted` with `2`. `{detail}` is one short line well under 200 characters: counts and exit codes plus which of the three calibration items moved, never the PR title, the PR number, branch names, or personal data.
Done when the command has run, or the script was absent and this step was skipped.
## Rules