feat(狀態回報): 收尾寫一筆 skill-end 事件
現行紀錄只記「被叫用」,沒有成敗也沒有結束碼。跑完整輪的技能與開場就 中止的技能,在紀錄裡長得一模一樣。 start 由技能用量 hook 順手發,不必改技能文件。end 只能由技能自己在收尾 步驟寫——hook 接在技能工具呼叫上,而實際工作發生在之後的模型輪次,它在 原理上看不到成敗。有 start 沒有配對的 end,就是那一輪中止了。 status 五選一,每支技能各自寫明什麼情況選哪一個。找不到回報腳本就安靜 跳過,回報失敗一律不改變技能自己的結論。
This commit is contained in:
@@ -130,3 +130,24 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
||||
- **On a failed write.** Retry once. Still failing, hand the user the page name and the full section that was not written, so the round's result is not lost. **Never close the run reporting a page as written when it was not**, and never close it silently with the content only in the transcript.
|
||||
|
||||
Completion condition: every changed domain repo has one new section on its `SKILLSET_{HASH}` and one row in `SKILLSET_CONTENTS` written by a `wiki-contents.sh upsert` that exited 0, or — where nothing changed — the `plugins/meta` page carries the 「本輪無發現」 section and its row on the same terms; every content-page write is confirmed by a successful read-back or reported as not written with its full content handed back.
|
||||
9. Report this round's outcome to the local event stream — the last step of every run, the ones that stop early included. Run:
|
||||
|
||||
`jsc-hooks/tools/report-status.sh skill-end jsc-meta:skill-check {status} {exit code} [detail]`
|
||||
|
||||
Resolve `jsc-hooks` from the `domain<TAB>path` row step 1 printed for the `hooks` domain, the same way this skill resolves every other cross-plugin script. **When that script is not on this machine, skip this step in silence and close the round 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 round actually did:
|
||||
|
||||
| status | Use it when |
|
||||
| --- | --- |
|
||||
| `ok` | every domain ended with a complete checklist, every accepted fix passed its re-check, every affected repo has a PR URL, and every wiki write exited 0 |
|
||||
| `blocked` | a gate or a missing prerequisite stopped the round before anything was audited — `sync-domains.sh` never reached exit 0, or the call itself was refused |
|
||||
| `failed` | the round broke mid-way — a re-check in step 6 kept failing, or a wiki write failed again after its one retry |
|
||||
| `degraded` | the round finished with a part missing — a domain carries 「本輪未取得已決議清單,優化建議暫不提出」, or a content page was written while its `SKILLSET_CONTENTS` row was not |
|
||||
| `aborted` | the user stopped the round, or a prerequisite turned out not to hold and this skill stopped on its own |
|
||||
|
||||
`{exit code}` is this round'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 audit itself happens in the model turns after that, so no hook can see how the round ended — a `start` with no `end` reads as an abort, which is why writing the `end` is this skill's own job.
|
||||
|
||||
Completion condition: one `skill-end` line for this round is appended to `$JSC_HOME/usage/events.jsonl`, or the script was absent and the final report says so.
|
||||
|
||||
@@ -69,3 +69,24 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
||||
| | 8 | Some other API failure. Stop, report that status, and create no page |
|
||||
|
||||
On any failure, hand the page name and the unwritten entry back to the user and leave this step open; never close the flow on an unwritten report. Completion condition: `SKILLSET_{HASH}` holds the new section plus all earlier sections, and `wiki-contents.sh upsert` exited 0 with this domain's row on `SKILLSET_CONTENTS` linking that page by absolute URL.
|
||||
9. Report this run's outcome to the local event stream — the last step of every run, the ones that stop early included. Run:
|
||||
|
||||
`jsc-hooks/tools/report-status.sh skill-end jsc-meta:skill-delete {status} {exit code} [detail]`
|
||||
|
||||
Resolve `jsc-hooks` from the `domain<TAB>path` row step 1 printed for the `hooks` domain, the same way this skill resolves every other cross-plugin script. **When that 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 skill directory and its behavior-list section are gone, the PR is open, `deploy-verify.md` sections 1 to 5 hold, `verify-skill-removed.sh` exited 0, and both wiki writes exited 0 |
|
||||
| `blocked` | a gate or a missing prerequisite stopped the run before any file changed — `sync-domains.sh` never reached exit 0, or no skill could be listed to pick from |
|
||||
| `failed` | the run broke mid-way — a leftover from `verify-skill-removed.sh` exit 1 could not be removed, or a wiki write failed again after its one retry |
|
||||
| `degraded` | the deletion landed with a part missing — the deep-delete check came back 「無處可查」, or the content page was written while its `SKILLSET_CONTENTS` row was not |
|
||||
| `aborted` | the user stopped the run, or a prerequisite turned out not to hold and 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 deletion itself happens 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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -78,3 +78,24 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
||||
| | 8 | Some other API failure. Stop, report that status, and create no page |
|
||||
|
||||
On any failure, hand the page name and the unwritten entry back to the user and leave this step open; never close the flow on an unwritten report. Completion condition: `SKILLSET_{HASH}` holds the new section plus all earlier sections, and `wiki-contents.sh upsert` exited 0 with this domain's row on `SKILLSET_CONTENTS` linking that page by absolute URL.
|
||||
7. Report this run's outcome to the local event stream — the last step of every run, the ones that stop early included. Run:
|
||||
|
||||
`jsc-hooks/tools/report-status.sh skill-end jsc-meta:skill-new {status} {exit code} [detail]`
|
||||
|
||||
Resolve `jsc-hooks` from the `domain<TAB>path` row step 1.1 printed for the `hooks` domain, the same way this skill resolves every other cross-plugin script. **When that 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 new `SKILL.md` and its behavior-list section are in place, the checklist passes, the PR is open, `deploy-verify.md` sections 1 to 5 hold, and both wiki writes exited 0 |
|
||||
| `blocked` | a gate or a missing prerequisite stopped the run before any file was created — `sync-domains.sh` never reached exit 0, or Gitea refused the repository creation and nobody created it by hand |
|
||||
| `failed` | the run broke mid-way — `sync-marketplace.sh` or `sync-skill-manifest.sh` kept failing, or a wiki write failed again after its one retry |
|
||||
| `degraded` | the skill landed with a part missing — the content page was written while its `SKILLSET_CONTENTS` row was not, or a CLI could not be verified and the reason was recorded |
|
||||
| `aborted` | the user stopped the run, or a prerequisite turned out not to hold and 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 creation itself happens 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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -53,3 +53,24 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
||||
| | 8 | Some other API failure. Stop, report that status, and create no page |
|
||||
|
||||
On any failure, hand the page name and the unwritten entry back to the user and leave this step open; never close the flow on an unwritten report. Completion condition: `SKILLSET_{HASH}` holds the new section plus all earlier sections, and `wiki-contents.sh upsert` exited 0 with this domain's row on `SKILLSET_CONTENTS` linking that page by absolute URL.
|
||||
9. Report this run's outcome to the local event stream — the last step of every run, the ones that stop early included. Run:
|
||||
|
||||
`jsc-hooks/tools/report-status.sh skill-end jsc-meta:skill-update {status} {exit code} [detail]`
|
||||
|
||||
Resolve `jsc-hooks` from the `domain<TAB>path` row step 1 printed for the `hooks` domain, the same way this skill resolves every other cross-plugin script. **When that 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 skill files and the behavior-list section carry the change, the checklist passes, the PR is open, `deploy-verify.md` sections 1 to 5 hold, and both wiki writes exited 0 |
|
||||
| `blocked` | a gate or a missing prerequisite stopped the run before any file changed — `sync-domains.sh` never reached exit 0, or no skill could be listed to pick from |
|
||||
| `failed` | the run broke mid-way — the step 6 checklist loop kept failing, or a wiki write failed again after its one retry |
|
||||
| `degraded` | the update landed with a part missing — the content page was written while its `SKILLSET_CONTENTS` row was not, or a CLI could not be verified and the reason was recorded |
|
||||
| `aborted` | the user stopped the run, or a prerequisite turned out not to hold and 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 update itself happens 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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -54,3 +54,24 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
||||
| | 8 | Some other API failure. Stop, report that status, and create no page |
|
||||
|
||||
On any failure, hand the page name and the unwritten entry back to the user and leave this step open; never close the flow on an unwritten report. Completion condition: every affected repo's `SKILLSET_{HASH}` holds the new section plus all earlier sections, and every one of those repos has a row on `SKILLSET_CONTENTS` written by a `wiki-contents.sh upsert` that exited 0, linking its page by absolute URL.
|
||||
6. Report this run's outcome to the local event stream — the last step of every run, the ones that stop early included. One event for the whole batch, not one per domain. Run:
|
||||
|
||||
`jsc-hooks/tools/report-status.sh skill-end jsc-meta:skillset-update {status} {exit code} [detail]`
|
||||
|
||||
Resolve `jsc-hooks` from the `domain<TAB>path` row step 1.1 printed for the `hooks` domain, the same way this skill resolves every other cross-plugin script. **When that 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` | every affected repo carries the change and its behavior-list update, every checklist passes, every repo has a PR URL, `deploy-verify.md` sections 1 to 5 hold for all of them, and every wiki write exited 0 |
|
||||
| `blocked` | a gate or a missing prerequisite stopped the run before any file changed — `sync-domains.sh` never reached exit 0, or the affected-skill list was never agreed |
|
||||
| `failed` | the run broke mid-way — the step 3 checklist loop kept failing for some repo, or a wiki write failed again after its one retry |
|
||||
| `degraded` | part of the batch landed and part did not — some repos got their PR and others did not, or a content page was written while its `SKILLSET_CONTENTS` row was not. Name the repos in `detail` |
|
||||
| `aborted` | the user stopped the run, or a prerequisite turned out not to hold and 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 batch itself happens 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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -27,6 +27,27 @@ Keep `references/ste100.md` in sync with its upstream source, [speak-human-tw](h
|
||||
7. Run `tools/ste100-lint.sh` over every jsc repo (`tools/sync-domains.sh` prints the repo paths). The repos are independent, so lint them **in parallel**, one run per repo. Route each exit code: 0 — that repo is clean; 1 — hits printed as `{檔案}:{行號}:{類別}:{命中內容}`; 2 — no target was given, so fix the arguments and rerun, never read it as clean. 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.
|
||||
8. Run `tools/sync-skill-manifest.sh .` to sync the README's 「Skills 目錄」 section and bump the manifests. Route each exit code: 0 — the README block and all three manifests are synced; 1 — `skills/`, `README.md`, the `JSC-SKILLS` markers, a `SKILL.md`, a manifest, or a manifest `version` field is missing, so fix the named cause on stderr and rerun; 2 — usage error, the script takes exactly one argument; any other code — the script runs under `set -e`, so treat it as an environment fault and stop, never as a successful sync. Completion condition: all three manifests show the same new version.
|
||||
9. Open a PR via `jsc-git:pr`. Completion condition: a PR URL comes back and is reported with the table format in [`../../references/pr-report.md`](../../references/pr-report.md).
|
||||
10. Report this run's outcome to the local event stream — the last step of every run, **the step 1.3 early stop included**. Run:
|
||||
|
||||
`jsc-hooks/tools/report-status.sh skill-end jsc-meta:ste100-sync {status} {exit code} [detail]`
|
||||
|
||||
Resolve `jsc-hooks` the same way step 6 resolves `jsc-hooks/hooks/simplified.txt`: the sibling checkout in the workspace. On the step 1.3 early stop, where `tools/sync-domains.sh` has not run, that sibling path is the only source. **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` | upstream had a new version and every adopted change is in `references/ste100.md`, the lint runs clean here, the manifests are bumped and the PR is open — **and also when step 1.3 stopped the run on 「上游沒有新版」**, because that is this skill's normal ending, not an abort |
|
||||
| `blocked` | a gate or a missing prerequisite stopped the run before any comparison — the call itself was refused, or neither the raw read nor the clone could reach upstream, so no version could be compared |
|
||||
| `failed` | the run broke mid-way — `sh -n tools/ste100-lint.sh` kept failing after the pattern edit, or `sync-skill-manifest.sh` could not be resolved |
|
||||
| `degraded` | the sync landed with a part missing — this repo lints clean but hits in other repos were only handed to their owners, or a simplified-character change reached the lint and not `jsc-hooks/hooks/simplified.txt` |
|
||||
| `aborted` | the user stopped the run, or the user dropped every distilled change so nothing was left to apply |
|
||||
|
||||
`{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 comparison and the sync 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, and why the 「上游沒有新版」 path must write one too.
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
|
||||
- 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.
|
||||
|
||||
@@ -98,6 +99,28 @@ Done when the scope and the output target are each written down as one of the va
|
||||
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user