Merge develop

三份 manifest 取分支上的較高版號:develop 那邊到 0.3.6,這條分支本來就是為了
讓開那一號才升到 0.3.7,取低的等於把版號往回退。

行為清單第 10 行兩邊各改了同一行的不同地方,合起來留:develop 加的是委派
清單檢核多判一種填錯的 probe、以及修法要回該技能的存取庫核對過再改寫;這條
分支加的是第一組多跑一項腳本路徑檢查。兩件事互不相干,取任一邊都會弄丟另
一邊。外部呼叫那一行 develop 沒動過,直接取分支上的。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 11:29:00 +08:00
co-authored by Claude Opus 5
9 changed files with 209 additions and 78 deletions
+4 -4
View File
@@ -23,9 +23,9 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
6. Run the two wiki-rule checkers once each, not per domain — both judge shared rules, so a second run adds nothing:
- `jsc-gitea/tools/check-wiki-rules.sh`, which verifies wiki repo resolution and the `hash-id` rule for every page type. It takes no argument. Route each exit code: 0 — printed `OK` on stdout, every item passed; 1 — the first mismatch is printed on stderr as `{項目}: want=… got=…` and the script stops there, so report that item and rerun after the fix, because the remaining items were never reached. Those are its only two codes. Until this audit, no flow in the whole repository ever called it.
- `tools/check-page-name.sh {root}`, where `{root}` is the directory holding the domain repos — the parent directory of the paths `tools/sync-domains.sh` printed in step 1, so no extra derivation is needed. It compares the page-name pattern in its three copies: `jsc-gitea/tools/page-name.sh` (the canonical one), `jsc-hooks/hooks/comment-scope.sh` and `jsc-log/tools/worklog-pending.sh`. Route each exit code: 0 — the three agree; 1 — the mismatches are printed on stderr as `{檔案}:{說明}`, so report each one as a compliance failure, and a copy that could not be found is one of those lines; 2 — usage error, the tool takes exactly one argument; 3 — none of the three copies was found, so the root is wrong: fix it and rerun. Record exit 3 as 「什麼都沒查」; it is **never** a pass. The three copies stay separate on purpose — a hook must be self-contained and may not depend on another plugin's path at run time — so consistency is checked here instead of shared in a function.
7. Run `tools/check-delegate.sh {root}` once for the whole round, with the same `{root}` item 6 passed to `check-page-name.sh`. It compares the delegation list `tools/delegate-spec.tsv` against the skills `tools/list-skills.sh` finds on this machine: one skill one row, eleven columns, every mandatory column filled, and every `next` naming a skill that exists. It belongs in group 1 for the same reason `ste100-lint.sh` does — it is a deterministic script verdict, and it is judged **once for the whole round** rather than per domain, because the list is a single file covering every domain. Handing it to the group 2 sub agents would have ten agents run the same script over the same file and report ten copies of the same lines, with no single verdict anywhere; handing it to group 3 would turn a pass-or-fail check into a suggestion. Route each exit code:
- 0 — the list and the machine's skills correspond one to one and every mandatory column is filled. **A run that printed lines on stdout and exited 0 passed.** Those lines are hints, not compliance failures, and they are printed on stdout precisely so they are told apart from the failures on stderr: `origin=seed` marks a row seeded from the earlier inventory that has not been through the decision tree yet, and a version-behind line marks a row whose recorded `version` trails its domain's current one. The version number is per domain, so one skill's change marks every other skill of that domain — counting those as failures paints whole domains red on every release, and the hint stops being read at all. Report the hint count and the rows, and open no decision-tree item for them.
- 1 — a missing row, a duplicate row, a row for a skill this machine does not have, an empty column, a column value outside its vocabulary, or a `next` naming a skill that does not exist. Every one is printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}`. Report each as a compliance failure, named by the skill it belongs to. A missing row means the assistant is blind to that skill; an extra row means it will trigger a skill that cannot be called, and a failing trigger retries instead of pausing.
7. Run `tools/check-delegate.sh {root}` once for the whole round, with the same `{root}` item 6 passed to `check-page-name.sh`. It compares the delegation list `tools/delegate-spec.tsv` against the skills `tools/list-skills.sh` finds on this machine: one skill one row, twelve columns, every mandatory column filled, every `next` naming a skill that exists, and every `probe` either a runnable read-only command, a `pending:{reason}`, or a `-` on the rows that take one. It belongs in group 1 for the same reason `ste100-lint.sh` does — it is a deterministic script verdict, and it is judged **once for the whole round** rather than per domain, because the list is a single file covering every domain. Handing it to the group 2 sub agents would have ten agents run the same script over the same file and report ten copies of the same lines, with no single verdict anywhere; handing it to group 3 would turn a pass-or-fail check into a suggestion. Route each exit code:
- 0 — the list and the machine's skills correspond one to one and every mandatory column is filled. **A run that printed lines on stdout and exited 0 passed.** Those lines are hints, not compliance failures, and they are printed on stdout precisely so they are told apart from the failures on stderr: `origin=seed` marks a row seeded from the earlier inventory that has not been through the decision tree yet, a version-behind line marks a row whose recorded `version` trails its domain's current one, a `probe=pending:` line marks a delegated slice whose read-only entry point is not wired yet, and a line saying a `probe` domain is not installed here marks a script this machine cannot check. The version number is per domain, so one skill's change marks every other skill of that domain — counting those as failures paints whole domains red on every release, and the hint stops being read at all. Report the hint count and the rows, and open no decision-tree item for them.
- 1 — a missing row, a duplicate row, a row for a skill this machine does not have, an empty column, a column value outside its vocabulary, a `next` naming a skill that does not exist, or a `probe` in the wrong shape — a command on a row whose `way` holds `invoke`, a `-` on a row whose `way` holds only `patrol` or `remind`, a dollar sign or tilde, an unknown substitution point, or a script that does not exist. Every one is printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}`. Report each as a compliance failure, named by the skill it belongs to. A missing row means the assistant is blind to that skill; an extra row means it will trigger a skill that cannot be called, and a failing trigger retries instead of pausing. A wrong `probe` fails every unattended round in the same silent way, and the command-on-an-`invoke`-row case is worse than a failure: the assistant runs a bare script where the whole skill was supposed to run, and the round looks clean.
- 2 — usage error: the script takes at most one argument. Fix the call and rerun; this is a defect in this skill, not a finding about the skill set.
- 3 — nothing was checked, because `tools/delegate-spec.tsv` is missing, the root could not be derived, or `list-skills.sh` listed no skill. Record it as 「無委派清單可查」 with the cause from stderr and carry it into the step 3 merge; **exit 3 is never a pass**, because a check that read nothing reports neither a missing row nor an extra one.
@@ -86,7 +86,7 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
- Optimization options: apply / defer / custom. Record the chosen option in the finding's 決議 field as `套用`, `延後` or `自訂`, and today's date in 決議日期. Any suggestion that weakens a protection must name the protection it removes and must not be applied unless the user explicitly accepts that tradeoff. Cost optimization may move, merge, cache, or narrow checks; it must not delete a compliance check only because it is expensive.
Completion condition: every domain's checklist is complete after the merge, with the two whole-round verdicts carrying the same value in every domain, and every compliance failure and every optimization finding has a recorded decision — every optimization finding carrying both 決議 and 決議日期.
4. Apply the confirmed fixes and accepted optimizations — the file-change part MUST run as a sub agent, one sub agent per affected domain repo, and those sub agents run **in parallel**: each repo's files are independent. A fix that changes a skill's behavior also updates that skill's `## {name}` section in the same repo's `references/behaviors.md`, in the same pass, so the fix and the behavior list land in one PR. A confirmed `check-delegate.sh` fix is written by the **main agent**, never by the per-repo sub agents: `tools/delegate-spec.tsv` is one file for the whole skill set, and parallel agents writing one file overwrite each other's rows. A missing row is filled by running the decision tree of [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md) for that skill through `jsc-ask:ask` and writing the answer as a row with `origin` set to `judged`; an extra row is deleted; a dead `next` is repointed at a skill that exists. A fix that changed a skill's behavior in this same round also re-judges that skill and moves its row's `version`. 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. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path, `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: every affected repo carries the changes, the matching `references/behaviors.md` update for every fix that changed a skill's behavior, the `tools/delegate-spec.tsv` rows for every accepted delegation fix, and the manifest bump.
4. Apply the confirmed fixes and accepted optimizations — the file-change part MUST run as a sub agent, one sub agent per affected domain repo, and those sub agents run **in parallel**: each repo's files are independent. A fix that changes a skill's behavior also updates that skill's `## {name}` section in the same repo's `references/behaviors.md`, in the same pass, so the fix and the behavior list land in one PR. A confirmed `check-delegate.sh` fix is written by the **main agent**, never by the per-repo sub agents: `tools/delegate-spec.tsv` is one file for the whole skill set, and parallel agents writing one file overwrite each other's rows. A missing row is filled by running the decision tree of [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md) for that skill through `jsc-ask:ask` and writing the answer as a row with `origin` set to `judged`; an extra row is deleted; a dead `next` is repointed at a skill that exists; a wrong `probe` is rewritten per that same file — verified against the owning repo, not guessed — and set to `pending:{reason}` when the slice has no read-only entry point on this machine. A fix that changed a skill's behavior in this same round also re-judges that skill and moves its row's `version`. 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. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path, `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: every affected repo carries the changes, the matching `references/behaviors.md` update for every fix that changed a skill's behavior, the `tools/delegate-spec.tsv` rows for every accepted delegation fix, and the manifest bump.
5. Sync the canonical marketplace — a **required** step, never optional. The canonical pair lives in `plugins/meta` and every domain repo carries a byte-identical copy, so a fix that leaves the copies apart makes some repos register a stale plugin set. Run `tools/sync-marketplace.sh {domain} {repo-url} {description}` once with an existing entry's own current values (rewriting the same entry is idempotent); the script rewrites both canonical files and copies them into every domain repo. 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: the script takes exactly three arguments. Fix them and rerun.
+3 -3
View File
@@ -23,15 +23,15 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
Completion condition: every file in the step 4 inventory is marked either fixed-with-a-clean-checklist, explicitly no-fix-needed with a reason, or deferred to step 6 as the delegation list is — no file is left without a verdict.
6. Delete the skill directory `skills/{name}/` and remove that skill's `## {name}` section from `references/behaviors.md` — the whole section, its table included, leaving every other section untouched. Both deletions ship in this same PR: a behavior list still carrying a deleted skill fails the domain's next audit, and the extra section is exactly what `check-behaviors.sh` reports. 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. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path, `skills/`, `README.md`, the `JSC-SKILLS` markers, a remaining `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.
Delete that skill's row from `jsc-meta/tools/delegate-spec.tsv` in the same pass — that one row, every other row left byte for byte as it was. A list still carrying a deleted skill makes the background assistant trigger a skill that cannot be called, and a failing trigger does not pause itself: it retries every round, for good. Then repoint every remaining row whose `next` column named the deleted skill; those rows now name something that cannot be called either, and they are the second half of the same defect. The file lives in `plugins/meta` whichever domain lost the skill, so deleting a skill outside `meta` changes two repos and step 7 opens the second Push Request for this one.
Delete that skill's row from `jsc-meta/tools/delegate-spec.tsv` in the same pass — that one row, every other row left byte for byte as it was. A list still carrying a deleted skill makes the background assistant trigger a skill that cannot be called, and a failing trigger does not pause itself: it retries every round, for good. Then repoint every remaining row whose `next` column named the deleted skill; those rows now name something that cannot be called either, and they are the second half of the same defect. In the same pass, check every remaining row's `probe` column against the files this deletion removed: a deletion that took a `tools/` script down with the skill leaves any row whose read-only command named that script pointing at nothing, and the assistant then fails that entry every round without ever pausing on it. Repoint such a row at a script that exists, or set it to `pending:{reason}` when this deletion left the slice with no read-only entry at all. The file lives in `plugins/meta` whichever domain lost the skill, so deleting a skill outside `meta` changes two repos and step 7 opens the second Push Request for this one.
**The task-book half is not wired yet.** [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md) also asks this skill to drop the assistant task-book entries that name the deleted skill. That task book does not exist yet, so there is nothing to remove from and this skill does not go looking for it. When the task book ships, add that removal here as a step of its own. Until then, carry 「待辦簿引用尚未接線」 into the step 8.3 wiki section, so a later reader does not take this deletion as having cleaned a place it never touched.
Then run `tools/check-behaviors.sh {domain-path}` and route each exit code: 0 — the remaining sections match the remaining skills; 1 — every mismatch is printed on stderr as `{檔案}:{技能名}:{說明}`, so fix each one and rerun, the deleted skill's leftover section included; 2 — usage error, the tool takes exactly one argument; 3 — nothing was checked, because `references/behaviors.md` is missing, `skills/` is missing, or no `SKILL.md` was found, so fix the named cause and rerun. **Exit 3 is never a pass.**
Then run `tools/check-delegate.sh`. It takes the plugins root, not a domain path, and the list is one file covering every domain, so it runs **once for the whole flow**. Route each exit code:
- 0 — the list matches the skills on this machine and every mandatory column is filled; the deleted skill has no row left, and no surviving row points at it. **A run that printed lines on stdout and exited 0 still passed.** Those lines are hints, not defects: `origin=seed` marks a row seeded from the earlier inventory and awaiting review, and a version-behind line marks a row whose `version` trails its domain's current one, which every skill of the domain this deletion just bumped will now show. Report them as hints and fix nothing for them; a deletion held open over a version-behind line would never close.
- 1 — a row remains for a skill this machine no longer has, or a surviving row's `next` points at the deleted skill. Both are printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}` — the first is the row this step was supposed to remove, the second is a `next` this step was supposed to repoint. Fix each and rerun.
- 0 — the list matches the skills on this machine and every mandatory column is filled; the deleted skill has no row left, and no surviving row points at it. **A run that printed lines on stdout and exited 0 still passed.** Those lines are hints, not defects: `origin=seed` marks a row seeded from the earlier inventory and awaiting review, and a version-behind line marks a row whose `version` trails its domain's current one, a `probe=pending:` line marks a delegated slice whose read-only entry point is not wired yet, and a line saying a `probe` domain is not installed here marks a script this machine cannot check, which every skill of the domain this deletion just bumped will now show. Report them as hints and fix nothing for them; a deletion held open over a version-behind line would never close.
- 1 — a row remains for a skill this machine no longer has, a surviving row's `next` points at the deleted skill, or a surviving row's `probe` points at a script this deletion removed. All three are printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}` — the first is the row this step was supposed to remove, the second is a `next` this step was supposed to repoint, the third a `probe` this step was supposed to repoint or set to `pending:{reason}`. Fix each and rerun.
- 2 — usage error: the script takes at most one argument. Fix the call and rerun.
- 3 — nothing was checked, because `tools/delegate-spec.tsv` is missing, the root could not be derived, or `list-skills.sh` listed no skill. Read stderr and fix the named cause; set `JSC_PLUGINS_ROOT` to the directory holding the domain repos for the root case, as in step 1. **Exit 3 is never a pass** — a check that looked nowhere reports no leftover row either.
+6 -4
View File
@@ -20,7 +20,9 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
- 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 (offer the domain list from the step 1.1 `domain<TAB>path` rows — the domains registered in the canonical marketplace)
- Delegation verdict — the five decision-tree questions of [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md), in the order that file lists them, plus a sixth question for the `next` column: which skill should run after this one. Ask all six through this same `jsc-ask:ask` tree; never answer them from the model's own reading of the draft flow. Every option states its impact scope: a `full` verdict lets the background assistant run the skill unattended, a `slice` or `cond` verdict leaves the other half in the user's hands, `none` keeps the whole skill there. The `next` question applies to all four verdicts, `none` included — `none` says the assistant does not run this skill for the user, which says nothing about what should follow it — so offer the step 1.1 skill rows as its options and the answer then names a skill that exists.
- Delegation verdict — the five decision-tree questions of [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md), in the order that file lists them, plus a sixth question for the `next` column: which skill should run after this one, and a seventh for the `probe` column: which read-only command the assistant actually runs for the delegated slice. Ask all seven through this same `jsc-ask:ask` tree; never answer them from the model's own reading of the draft flow. Every option states its impact scope: a `full` verdict lets the background assistant run the skill unattended, a `slice` or `cond` verdict leaves the other half in the user's hands, `none` keeps the whole skill there. The `next` question applies to all four verdicts, `none` included — `none` says the assistant does not run this skill for the user, which says nothing about what should follow it — so offer the step 1.1 skill rows as its options and the answer then names a skill that exists.
The `probe` question is asked only when the `way` answer holds no `invoke`; a `way` containing `invoke`, and a `none` verdict, both take `-` without asking, because the assistant's action there is the skill itself and a command in that column would silently downgrade the whole delegation to a bare script run. When it is asked, settle three things per that same reference file and never by copying another row: which script, whether it takes a read-only flag, and how a failure is reported. Verify the script, the sub-command and the flag name in the owning repo before writing them down — a description of a script is not evidence the script exists. The flag matters most: the patrol round is unattended, and a wrong flag turns a read-only stocktake into something that writes. An entry that needs the network gets `pending:{reason}` this round rather than a command, because an expired key then fails or silently reports nothing on every round while a local read fails on none.
Completion condition: goal, trigger, input/output, owning domain and the delegation verdict each have a recorded answer, and the verdict carries a value for every column `delegate-criteria.md` marks mandatory for that verdict, `-` where it marks the column unused.
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):
@@ -37,15 +39,15 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
3. Generate the skill per guidelines.md — this step MUST run as a sub agent:
- `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/`
- `jsc-meta/tools/delegate-spec.tsv`: append this skill's row, built from the step 1.2 verdict — one skill one row, the eleven tab-separated columns in the order that file's header lists. A column the verdict does not use holds a single `-`; an empty cell and a cell holding a space both fail the checker. `origin` is `judged`, because the verdict came from the decision tree in this same run, and `version` is the version the three manifests carry after the `sync-skill-manifest.sh` run below. **A skill with no row is not created.** The row is the only thing that tells the background assistant this skill exists, so without it every later round is blind to it, and no later step recreates it. The file lives in `plugins/meta` whichever domain gained the skill, so a skill added to another domain changes two repos and step 5 opens the second Push Request for this one.
- `jsc-meta/tools/delegate-spec.tsv`: append this skill's row, built from the step 1.2 verdict — one skill one row, the twelve tab-separated columns in the order that file's header lists, `probe` last. A column the verdict does not use holds a single `-`; an empty cell and a cell holding a space both fail the checker. Write `probe` as the header describes: the script path starts at `{root}/jsc-{domain}/`, `{cli}` and `{repo}` are the only other substitution points, no dollar sign and no tilde, and any read-only flag goes in front of the command. `origin` is `judged`, because the verdict came from the decision tree in this same run, and `version` is the version the three manifests carry after the `sync-skill-manifest.sh` run below. **A skill with no row is not created.** The row is the only thing that tells the background assistant this skill exists, so without it every later round is blind to it, and no later step recreates it. The file lives in `plugins/meta` whichever domain gained the skill, so a skill added to another domain changes two repos and step 5 opens the second Push Request for this one.
- `references/behaviors.md`: add one `## {name}` section for the new skill, placed in dictionary order among the existing sections, carrying the five rows the guidelines' 「技能行為清單」 section defines — 觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象. Write what the skill really does; do not copy the `description`. A read-only skill still fills 可驗證跡象 with 「無寫入跡象,只有回報內容」. The behavior list ships in this same PR — a skill added without its section leaves the domain's list out of sync the moment this PR merges. When the domain has no `references/behaviors.md` yet, create it with the header line `# jsc-{domain} 技能行為清單`.
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. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path, `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: `skills/{name}/SKILL.md` exists, `references/behaviors.md` holds a `## {name}` section with all five rows filled, `tools/delegate-spec.tsv` holds this skill's row with every mandatory column filled, 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. Run `tools/check-behaviors.sh {domain-path}` for the behavior-list item instead of comparing by eye, and route each exit code: 0 — the list matches `skills/` and all five rows are filled; 1 — every mismatch is printed on stderr as `{檔案}:{技能名}:{說明}`, so fix each one and rerun; 2 — usage error, the tool takes exactly one argument; 3 — nothing was checked, because `references/behaviors.md` is missing, `skills/` is missing, or no `SKILL.md` was found, so create the missing file and rerun. **Exit 3 is never a pass.**
Then run `tools/check-delegate.sh` for the delegation-list item. It takes the plugins root, not a domain path, and the list is one file covering every domain, so it runs **once for the whole flow** — a second run per domain checks the same file again and reports the same lines. Route each exit code:
- 0 — the list matches the skills on this machine and every mandatory column is filled. **A run that printed lines on stdout and exited 0 still passed.** Those lines are hints, not defects: `origin=seed` marks a row seeded from the earlier inventory and awaiting review, and a version-behind line marks a row whose `version` trails its domain's current one. The version number is per domain, so bumping one skill's domain marks every other skill in it — reading those lines as failures paints the whole domain red on every release until nobody reads them at all. Report the hints, fix nothing for them, and treat this item as passed.
- 1 — a missing row, a duplicate row, a row for a skill this machine does not have, an empty column, a column value outside its vocabulary, or a `next` pointing at a skill that does not exist. Every one is printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}`; fix each and rerun. The new skill's own missing row is the expected finding when step 3 skipped its write, and the fix is that write, not an edit here.
- 0 — the list matches the skills on this machine and every mandatory column is filled. **A run that printed lines on stdout and exited 0 still passed.** Those lines are hints, not defects: `origin=seed` marks a row seeded from the earlier inventory and awaiting review, and a version-behind line marks a row whose `version` trails its domain's current one, a `probe=pending:` line marks a delegated slice whose read-only entry point is not wired yet, and a line saying a `probe` domain is not installed here marks a script this machine cannot check. The version number is per domain, so bumping one skill's domain marks every other skill in it — reading those lines as failures paints the whole domain red on every release until nobody reads them at all. Report the hints, fix nothing for them, and treat this item as passed.
- 1 — a missing row, a duplicate row, a row for a skill this machine does not have, an empty column, a column value outside its vocabulary, a `next` pointing at a skill that does not exist, or a `probe` in the wrong shape — a command on a row whose `way` holds `invoke`, a `-` on a row whose `way` holds only `patrol` or `remind`, a dollar sign or tilde, an unknown substitution point, or a script that does not exist. Every one is printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}`; fix each and rerun. The new skill's own missing row is the expected finding when step 3 skipped its write, and the fix is that write, not an edit here.
- 2 — usage error: the script takes at most one argument. Fix the call and rerun.
- 3 — nothing was checked, because `tools/delegate-spec.tsv` is missing, the root could not be derived, or `list-skills.sh` listed no skill. Read stderr and fix the named cause; set `JSC_PLUGINS_ROOT` to the directory holding the domain repos for the root case, as in step 1.1. **Exit 3 is never a pass** — it means the check looked nowhere, so a new skill with no row would sail through it.
+4 -4
View File
@@ -14,13 +14,13 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
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.
Settle the delegation verdict in the same tree, before any file is touched. A change that touches the **flow** or the **`description`** re-runs the whole decision tree of [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md) — all five questions plus the `next` question — and produces a fresh verdict. Skipping that leaves a skill that just turned from read-only into file-writing sitting on its old verdict, and the background assistant keeps triggering it on a description of behavior it no longer has. A change that only rewrites wording and touches no behavior may keep the recorded verdict; then step 5 moves the row's `version` alone and the reuse is stated in the report, never left silent. Every option states its impact scope, this one included: reusing a verdict wrongly is the one failure this flow cannot detect later, because the row still looks complete. Completion condition: the run holds either a fresh verdict with a value in every column `delegate-criteria.md` marks mandatory for it, or a recorded decision to reuse the existing verdict together with the reason it changed no behavior.
5. Update the skill — the modification part MUST run as a sub agent: modify SKILL.md and related files. In the same pass, update this skill's `## {name}` section in `references/behaviors.md` so its five rows — 觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象 — describe the new behavior. A renamed skill gets its section renamed and moved back into dictionary order. In the same pass, update this skill's row in `jsc-meta/tools/delegate-spec.tsv` from the step 4 answer: a re-judged skill has every column rewritten from the fresh verdict with `origin` set to `judged`; a reused verdict keeps its columns and its `origin` untouched. Either way the `version` column moves to the version the manifests carry after the `sync-skill-manifest.sh` run below — a row left on the old version reads as never revisited, and the next audit reports it as pending re-judgement. The reuse itself is **not** recorded in the row: the eleven columns hold no note column and a twelfth column fails the checker, so state it in the PR description and in the step 8.2 wiki section as 「沿用前一輪判定」 with the date that judgement was made. A renamed skill also has its row's `name` column renamed, and every other row whose `next` named the old name is repointed in the same edit — those rows now name a skill that cannot be called, and the assistant retries such a name instead of pausing on it. The file lives in `plugins/meta` whichever domain owns the skill, so updating a skill outside `meta` changes two repos. The behavior list ships in this same PR: a behavior change that lands without its section makes the domain's list wrong from the merge onward, and the next audit reports drift this step created. 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. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path, `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: the skill files carry the change, the skill's `references/behaviors.md` section states the new behavior with all five rows filled, its `tools/delegate-spec.tsv` row carries the fresh verdict or the reused one with a moved `version`, and all three manifests show the same new version.
Settle the delegation verdict in the same tree, before any file is touched. A change that touches the **flow** or the **`description`** re-runs the whole decision tree of [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md) — all five questions, the `next` question and the `probe` question — and produces a fresh verdict. The `probe` question is re-asked even when the verdict itself comes back unchanged: a skill that switched which script it calls, or that gained a read-only flag it did not have, leaves that column naming something the assistant can no longer run, and the reference file's three points settle it — which script, whether it takes a read-only flag, how a failure is reported — each verified in the owning repo rather than copied from the old value. Skipping that leaves a skill that just turned from read-only into file-writing sitting on its old verdict, and the background assistant keeps triggering it on a description of behavior it no longer has. A change that only rewrites wording and touches no behavior may keep the recorded verdict; then step 5 moves the row's `version` alone and the reuse is stated in the report, never left silent. Every option states its impact scope, this one included: reusing a verdict wrongly is the one failure this flow cannot detect later, because the row still looks complete. Completion condition: the run holds either a fresh verdict with a value in every column `delegate-criteria.md` marks mandatory for it, or a recorded decision to reuse the existing verdict together with the reason it changed no behavior.
5. Update the skill — the modification part MUST run as a sub agent: modify SKILL.md and related files. In the same pass, update this skill's `## {name}` section in `references/behaviors.md` so its five rows — 觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象 — describe the new behavior. A renamed skill gets its section renamed and moved back into dictionary order. In the same pass, update this skill's row in `jsc-meta/tools/delegate-spec.tsv` from the step 4 answer: a re-judged skill has every column rewritten from the fresh verdict with `origin` set to `judged`; a reused verdict keeps its columns and its `origin` untouched. Either way the `version` column moves to the version the manifests carry after the `sync-skill-manifest.sh` run below — a row left on the old version reads as never revisited, and the next audit reports it as pending re-judgement. The reuse itself is **not** recorded in the row: the twelve columns hold no note column and a thirteenth column fails the checker, so state it in the PR description and in the step 8.2 wiki section as 「沿用前一輪判定」 with the date that judgement was made. A reused verdict still gets its `probe` column re-checked against the files this run touched — a renamed or removed script leaves that column naming something the assistant cannot run, and the checker reports it as a missing script. A renamed skill also has its row's `name` column renamed, and every other row whose `next` named the old name is repointed in the same edit — those rows now name a skill that cannot be called, and the assistant retries such a name instead of pausing on it. The file lives in `plugins/meta` whichever domain owns the skill, so updating a skill outside `meta` changes two repos. The behavior list ships in this same PR: a behavior change that lands without its section makes the domain's list wrong from the merge onward, and the next audit reports drift this step created. 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. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path, `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: the skill files carry the change, the skill's `references/behaviors.md` section states the new behavior with all five rows filled, its `tools/delegate-spec.tsv` row carries the fresh verdict or the reused one with a moved `version`, and all three manifests show the same new version.
6. Check every item of the guidelines.md audit checklist. Run `tools/check-behaviors.sh {domain-path}` for the behavior-list item instead of comparing by eye, and route each exit code: 0 — the list matches `skills/` and all five rows are filled; 1 — every mismatch is printed on stderr as `{檔案}:{技能名}:{說明}`, so fix each one and rerun; 2 — usage error, the tool takes exactly one argument; 3 — nothing was checked, because `references/behaviors.md` is missing, `skills/` is missing, or no `SKILL.md` was found, so create the missing file and rerun. **Exit 3 is never a pass.**
Then run `tools/check-delegate.sh` for the delegation-list item. It takes the plugins root, not a domain path, and the list is one file covering every domain, so it runs **once for the whole flow**. Route each exit code:
- 0 — the list matches the skills on this machine and every mandatory column is filled. **A run that printed lines on stdout and exited 0 still passed.** Those lines are hints, not defects: `origin=seed` marks a row seeded from the earlier inventory and awaiting review, and a version-behind line marks a row whose `version` trails its domain's current one. The version number is per domain, so bumping one skill's domain marks every other skill in it — reading those lines as failures paints the whole domain red on every release until nobody reads them at all. Report the hints and treat this item as passed. The one hint worth acting on here is a version-behind line naming **the skill this run just changed**: that row's `version` was supposed to move in step 5, so go back and move it.
- 1 — a missing row, a duplicate row, a row for a skill this machine does not have, an empty column, a column value outside its vocabulary, or a `next` pointing at a skill that does not exist. Every one is printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}`; fix each and rerun. A rename that left the old name behind lands here twice — once as a stale row, once as another row's dead `next`.
- 0 — the list matches the skills on this machine and every mandatory column is filled. **A run that printed lines on stdout and exited 0 still passed.** Those lines are hints, not defects: `origin=seed` marks a row seeded from the earlier inventory and awaiting review, and a version-behind line marks a row whose `version` trails its domain's current one, a `probe=pending:` line marks a delegated slice whose read-only entry point is not wired yet, and a line saying a `probe` domain is not installed here marks a script this machine cannot check. The version number is per domain, so bumping one skill's domain marks every other skill in it — reading those lines as failures paints the whole domain red on every release until nobody reads them at all. Report the hints and treat this item as passed. The one hint worth acting on here is a version-behind line naming **the skill this run just changed**: that row's `version` was supposed to move in step 5, so go back and move it.
- 1 — a missing row, a duplicate row, a row for a skill this machine does not have, an empty column, a column value outside its vocabulary, a `next` pointing at a skill that does not exist, or a `probe` in the wrong shape — a command on a row whose `way` holds `invoke`, a `-` on a row whose `way` holds only `patrol` or `remind`, a dollar sign or tilde, an unknown substitution point, or a script that does not exist. Every one is printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}`; fix each and rerun. A rename that left the old name behind lands here twice — once as a stale row, once as another row's dead `next`.
- 2 — usage error: the script takes at most one argument. Fix the call and rerun.
- 3 — nothing was checked, because `tools/delegate-spec.tsv` is missing, the root could not be derived, or `list-skills.sh` listed no skill. Read stderr and fix the named cause; set `JSC_PLUGINS_ROOT` to the directory holding the domain repos for the root case, as in step 1. **Exit 3 is never a pass.**
+4 -4
View File
@@ -16,14 +16,14 @@ Single source of guidelines: [`../../references/guidelines.md`](../../references
Completion condition: the `domain<TAB>path` rows are in hand, and the affected-skill list plus the three checks are agreed with the user.
2. Apply the change to every affected skill — the modification part MUST run as a sub agent, one sub agent per affected domain repo, and those sub agents **run in parallel**: each repo's files are independent. Every sub agent also updates its own repo's `references/behaviors.md` in the same pass: a changed behavior rewrites that skill's `## {name}` section, a new skill gets a section inserted in dictionary order, a removed skill loses its section. Keep all five rows filled — 觸發時機、關鍵步驟、外部呼叫、完成條件、可驗證跡象. Each repo's behavior list ships in that repo's own PR, so no cross-repo PR pair has to be merged in order.
Every sub agent also re-runs the delegation decision tree of [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md) for **every** skill its repo touched — one skill at a time, not one verdict for the repo, and **not one skipped**. A batch is exactly where skipping happens: the change that turned three skills from read-only into file-writing looks like one change, and re-judging only the obvious one leaves the other two being triggered on a verdict that no longer describes them. A skill whose text this batch rewrote without touching its flow or its `description` may keep its verdict, and then only its `version` moves; that reuse is stated in step 5.2's wiki section, exactly as a fresh verdict is.
Every sub agent also re-runs the delegation decision tree of [`../../references/delegate-criteria.md`](../../references/delegate-criteria.md) for **every** skill its repo touched — all five questions, the `next` question and the `probe` question, one skill at a time, not one verdict for the repo, and **not one skipped**. A batch is exactly where skipping happens: the change that turned three skills from read-only into file-writing looks like one change, and re-judging only the obvious one leaves the other two being triggered on a verdict that no longer describes them. A skill whose text this batch rewrote without touching its flow or its `description` may keep its verdict, and then only its `version` moves; that reuse is stated in step 5.2's wiki section, exactly as a fresh verdict is.
The sub agents do **not** write those verdicts. `jsc-meta/tools/delegate-spec.tsv` is one file for the whole skill set, and parallel sub agents writing one file overwrite each other's rows. Each sub agent returns its verdicts as rows — eleven tab-separated columns each, `-` in every column its verdict leaves unused, `origin` set to `judged` for a fresh verdict and left as it was for a reused one — and the **main agent** merges them into the file in one edit after the sub agents finish. When `meta` is one of the affected repos, that edit rides in its PR; when it is not, it is a change to `plugins/meta` and step 4 opens the extra Push Request for it. 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; these runs are independent per repo and may also go in parallel. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path, `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: every affected domain repo carries the change, its behavior-list update, the README sync, and the manifest bump; and every touched skill has a delegation verdict from this run — fresh, or recorded as reused with the reason — merged into `tools/delegate-spec.tsv` by the main agent, with no touched skill left without one.
The sub agents do **not** write those verdicts. `jsc-meta/tools/delegate-spec.tsv` is one file for the whole skill set, and parallel sub agents writing one file overwrite each other's rows. Each sub agent returns its verdicts as rows — twelve tab-separated columns each, `probe` last, `-` in every column its verdict leaves unused, `origin` set to `judged` for a fresh verdict and left as it was for a reused one — and the **main agent** merges them into the file in one edit after the sub agents finish. A batch is where the `probe` column goes stale fastest: a change that moves or renames a `tools/` script across several domains leaves every row naming it pointing at nothing, so each sub agent verifies that column against its own repo's files — which script, whether it takes a read-only flag, how a failure is reported — and returns `pending:{reason}` rather than a command for any slice that would need the network. When `meta` is one of the affected repos, that edit rides in its PR; when it is not, it is a change to `plugins/meta` and step 4 opens the extra Push Request for it. 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; these runs are independent per repo and may also go in parallel. Route each exit code: 0 — the README block and all three manifests are synced; 1 — the domain path, `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: every affected domain repo carries the change, its behavior-list update, the README sync, and the manifest bump; and every touched skill has a delegation verdict from this run — fresh, or recorded as reused with the reason — merged into `tools/delegate-spec.tsv` by the main agent, with no touched skill left without one.
3. Check every item of the guidelines.md audit checklist for each touched skill — one sub agent per affected domain repo, run in parallel. Each sub agent runs `tools/check-behaviors.sh {domain-path}` for the behavior-list item of its own repo instead of comparing by eye, and routes each exit code: 0 — that repo's list matches its `skills/` and all five rows are filled; 1 — every mismatch is printed on stderr as `{檔案}:{技能名}:{說明}`, so fix each one and rerun; 2 — usage error, the tool takes exactly one argument; 3 — nothing was checked, because `references/behaviors.md` is missing, `skills/` is missing, or no `SKILL.md` was found, so create the missing file and rerun. **Exit 3 is never a pass.**
The **main agent** then runs `tools/check-delegate.sh` once for the whole batch, not inside the per-repo sub agents: the list is one file covering every domain, so a run per repo checks the same file over again and hands back the same lines from every agent, with nobody holding one verdict. Route each exit code:
- 0 — the list matches the skills on this machine and every mandatory column is filled. **A run that printed lines on stdout and exited 0 still passed.** Those lines are hints, not defects: `origin=seed` marks a row seeded from the earlier inventory and awaiting review, and a version-behind line marks a row whose `version` trails its domain's current one. A batch bumps several domains at once, so it produces those lines by the dozen — reading them as failures would fail every batch this skill ever runs. Report them as hints. The ones worth acting on are the version-behind lines naming **skills this batch touched**: their `version` was supposed to move in step 2, so go back and move it.
- 1 — a missing row, a duplicate row, a row for a skill this machine does not have, an empty column, a column value outside its vocabulary, or a `next` pointing at a skill that does not exist. Every one is printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}`; fix each and rerun. A merge that lost one sub agent's rows shows up here as those skills missing, so read this code as a merge check too.
- 0 — the list matches the skills on this machine and every mandatory column is filled. **A run that printed lines on stdout and exited 0 still passed.** Those lines are hints, not defects: `origin=seed` marks a row seeded from the earlier inventory and awaiting review, and a version-behind line marks a row whose `version` trails its domain's current one, a `probe=pending:` line marks a delegated slice whose read-only entry point is not wired yet, and a line saying a `probe` domain is not installed here marks a script this machine cannot check. A batch bumps several domains at once, so it produces those lines by the dozen — reading them as failures would fail every batch this skill ever runs. Report them as hints. The ones worth acting on are the version-behind lines naming **skills this batch touched**: their `version` was supposed to move in step 2, so go back and move it.
- 1 — a missing row, a duplicate row, a row for a skill this machine does not have, an empty column, a column value outside its vocabulary, a `next` pointing at a skill that does not exist, or a `probe` in the wrong shape — a command on a row whose `way` holds `invoke`, a `-` on a row whose `way` holds only `patrol` or `remind`, a dollar sign or tilde, an unknown substitution point, or a script that does not exist. Every one is printed on stderr as `{清單路徑}:{domain}/{技能名}:{說明}`; fix each and rerun. A merge that lost one sub agent's rows shows up here as those skills missing, so read this code as a merge check too.
- 2 — usage error: the script takes at most one argument. Fix the call and rerun.
- 3 — nothing was checked, because `tools/delegate-spec.tsv` is missing, the root could not be derived, or `list-skills.sh` listed no skill. Read stderr and fix the named cause; set `JSC_PLUGINS_ROOT` to the directory holding the domain repos for the root case, as in step 1.1. **Exit 3 is never a pass.**