diff --git a/plugins/kyberforge/.apm/skills/agent-audit/SKILL.md b/plugins/kyberforge/.apm/skills/agent-audit/SKILL.md index cc923e0..67396dc 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/SKILL.md +++ b/plugins/kyberforge/.apm/skills/agent-audit/SKILL.md @@ -7,7 +7,7 @@ description: > directory -> skill-audit. allowed-tools: Bash Read metadata: - version: "1.0.0" + version: "1.0.1" category: factory source_keys: - context7-websites-code-claude diff --git a/plugins/kyberforge/.apm/skills/agent-audit/references/description-quality.md b/plugins/kyberforge/.apm/skills/agent-audit/references/description-quality.md index 0b360a3..4083917 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/references/description-quality.md +++ b/plugins/kyberforge/.apm/skills/agent-audit/references/description-quality.md @@ -36,9 +36,12 @@ Read the frontmatter before judging a single word. Its Claude Code counterpart has no equivalent field and stays model-invoked, so the two halves of the pair carrying differently shaped descriptions is expected there rather than a pair-consistency finding. - `user-invocable: false` does not belong in this bullet: it only blocks manual invocation and is - independent of `disable-model-invocation` — an agent can be `user-invocable: false` and still - model-routed, in which case the three-part shape below still applies. It carries no + `user-invocable: false` does not belong in this bullet. The two are separate fields with opposite + defaults — `disable-model-invocation` (default `false`) governs runtime auto-selection, + `user-invocable` (default `true`) governs manual invocation, and the retired `infer` field was + replaced by the pair rather than by either one. So `user-invocable: false` says nothing about + whether the agent is model-routed: judge that from `disable-model-invocation` alone, and where + that is absent the three-part shape below still applies. `user-invocable` carries no description-quality contract of its own and is out of this file's scope entirely. - **No such flag** — the agent is model-invoked and the rest of this file applies. diff --git a/plugins/kyberforge/.apm/skills/agent-audit/references/scope-project-user.md b/plugins/kyberforge/.apm/skills/agent-audit/references/scope-project-user.md index d91a5ad..642c128 100644 --- a/plugins/kyberforge/.apm/skills/agent-audit/references/scope-project-user.md +++ b/plugins/kyberforge/.apm/skills/agent-audit/references/scope-project-user.md @@ -41,8 +41,8 @@ those same sections, so any restatement is a copy that can disagree with the che If it carries one, it still has to be kebab-case. - `Use proactively` is meaningful in a CC description and steers the runtime to offer the agent unprompted. In a Copilot description it does nothing; `KyberforgeCopilot.ProactivePhrase` flags - it. The Copilot equivalent is `disable-model-invocation` / `user-invocable`, which changes the - description contract entirely — see `references/description-quality.md`, Step 0. + it. The Copilot equivalent is `disable-model-invocation`, which changes the description contract + entirely — see `references/description-quality.md`, Step 0. ## Pair consistency diff --git a/plugins/kyberforge/.apm/skills/agent-author/SKILL.md b/plugins/kyberforge/.apm/skills/agent-author/SKILL.md index b81b5ae..c399ffa 100644 --- a/plugins/kyberforge/.apm/skills/agent-author/SKILL.md +++ b/plugins/kyberforge/.apm/skills/agent-author/SKILL.md @@ -6,7 +6,7 @@ description: > Not read-only review -> `agent-audit`. Not skills -> `skill-author`. allowed-tools: Bash Read Write Edit metadata: - version: "1.0.0" + version: "1.0.1" category: factory source_keys: - context7-websites-code-claude @@ -31,7 +31,7 @@ metadata: Signals: grill output, `agent-audit` findings, inline feedback, session context describing what went wrong. With none, ask: "No improvement signals found. Did you mean to create a new agent, or do you have feedback to apply?" -Read only the reference for the resolved flow. Capture `git log --oneline -1` before touching the filesystem; Step 4 needs it. +Read only the reference for the resolved flow. Capture `rtk git log --oneline -1` before touching the filesystem; Step 4 needs it. ## Step 2 — Scope @@ -62,4 +62,4 @@ Invoke `agent-audit` on each file written and resolve every FAIL before reportin At plugin/APM scope bump the resolved package's `apm.yml` `version` — **minor** on create, **patch** on improve — because consumers compare it to detect updates. Project and user scope have no manifest. -**Commit verification.** Once the audit is clean, run `git add` and `git commit` — do not stop at staging. Re-run `git log --oneline -1` and confirm the hash changed from Step 1's. A non-empty `git diff --stat` is not proof: staged-but-uncommitted work is part of no commit and is lost if the tree is cleaned up. Report done only once the hash has changed. +**Commit verification.** Once the audit is clean, run `rtk git add` and `rtk git commit` — do not stop at staging. Re-run `rtk git log --oneline -1` and confirm the hash changed from Step 1's. A non-empty `git diff --stat` is not proof: staged-but-uncommitted work is part of no commit and is lost if the tree is cleaned up. Report done only once the hash has changed. diff --git a/plugins/kyberforge/.apm/skills/skill-author/README.md b/plugins/kyberforge/.apm/skills/skill-author/README.md index f169f44..53e49d7 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/README.md +++ b/plugins/kyberforge/.apm/skills/skill-author/README.md @@ -4,7 +4,7 @@ Author and refine skills conforming to the [agentskills.io](https://agentskills. ## What it does -Routes to one of two flows based on context: if no skill directory exists at the target path, it scaffolds the directory from annotated templates, fills in `SKILL.md` and supporting files, and validates the result. If an existing skill directory and improvement signals are both present, it groups those signals by root cause and applies targeted edits, then re-validates. In both flows, bumps the skill's `metadata.version` when present (minor for create, patch for improve). +Routes to one of two flows based on context: if no skill directory exists at the target path, it scaffolds the directory from annotated templates, fills in `SKILL.md` and supporting files, and validates the result. If an existing skill directory and improvement signals are both present, it groups those signals by root cause and applies targeted edits, then re-validates. In both flows, bumps the skill's `metadata.version` — minor for create, patch for improve — which every skill carries (ADR-0022). `SKILL.md` itself carries only the dispatch table, the invocation-axis decision, the contract gates and the shared close; each flow lives in its own self-contained reference file, per ADR-0020. diff --git a/plugins/kyberforge/.apm/skills/skill-author/SKILL.md b/plugins/kyberforge/.apm/skills/skill-author/SKILL.md index 6d35dfc..80ecb37 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/SKILL.md +++ b/plugins/kyberforge/.apm/skills/skill-author/SKILL.md @@ -6,7 +6,7 @@ description: > Not read-only review -> `skill-audit`. Not agent files -> `agent-author`. allowed-tools: Bash Read Write Edit metadata: - version: "1.0.0" + version: "1.0.1" category: factory source_keys: - agentskills-home @@ -34,7 +34,7 @@ metadata: Signals: grill output, `/skill-audit` findings, inline feedback, eval results, session context describing what went wrong. With none, ask whether the user meant to create a new skill or has feedback to apply. -Read only the reference matching the resolved flow — each is self-contained. If the target sits inside a git worktree, capture `git log --oneline -1` before touching the filesystem; Step 4 needs it. +Read only the reference matching the resolved flow — each is self-contained. If the target sits inside a git worktree, capture `rtk git log --oneline -1` before touching the filesystem; Step 4 needs it. ## Step 2 — Invocation axis @@ -59,4 +59,4 @@ Run `/skill-audit` on the resolved skill directory; resolve every FAIL before re Bump `metadata.version`: the **minor** version on create (new skills start at `0.1.0`) and the **patch** version on improve. -**Commit verification.** Inside a git worktree: once the audit is clean, run `git add` and `git commit` — do not stop at staging. Re-run `git log --oneline -1` and confirm the hash changed from Step 1's. A non-empty `git diff --stat` is not proof: staged-but-uncommitted work is part of no commit and is silently lost if the tree is cleaned up. Report done only once the hash has changed. Outside a worktree (a skill under `~/.claude/skills/`, say) nothing is committable — report done on a clean audit, naming that as the reason. +**Commit verification.** Inside a git worktree: once the audit is clean, run `rtk git add` and `rtk git commit` — do not stop at staging. Re-run `rtk git log --oneline -1` and confirm the hash changed from Step 1's. A non-empty `git diff --stat` is not proof: staged-but-uncommitted work is part of no commit and is silently lost if the tree is cleaned up. Report done only once the hash has changed. Outside a worktree (a skill under `~/.claude/skills/`, say) nothing is committable — report done on a clean audit, naming that as the reason. diff --git a/plugins/kyberforge/.apm/skills/skill-author/assets/templates/SKILL.md b/plugins/kyberforge/.apm/skills/skill-author/assets/templates/SKILL.md index 81b03d9..7fc910c 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/assets/templates/SKILL.md +++ b/plugins/kyberforge/.apm/skills/skill-author/assets/templates/SKILL.md @@ -45,14 +45,18 @@ description: > # Optional. 1–500 characters. State tool requirements, runtime versions, # and network access needs. Omit for skills with no special environment requirements. -# metadata: +metadata: + version: "0.1.0" # author: your-name -# version: "1.0" # category: general # source_keys: # - source-slug-one # - source-slug-two -# Optional. Arbitrary key-value map. Common keys: author, version, category. +# `metadata.version` is REQUIRED on every skill (ADR-0022) and is enforced by the +# `skill-frontmatter` pre-commit hook. Three-component semver. A newly created +# skill starts at "0.1.0" — leave the seeded value as it is; "1.0.0" is the seed +# for a pre-existing skill retrofitted into the rule, not for a new one. +# The rest of the map is optional: author, category, source_keys. # source_keys: populated when built from /research output. Lists slugs from references/sources.md. # Also add source_keys to each references/*.md file that was informed by research. diff --git a/plugins/kyberforge/.apm/skills/skill-author/references/create.md b/plugins/kyberforge/.apm/skills/skill-author/references/create.md index 9e754cb..984a45e 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/references/create.md +++ b/plugins/kyberforge/.apm/skills/skill-author/references/create.md @@ -84,8 +84,10 @@ already covers the new skill. Use Read/Edit directly on `apm.yml`; this is not p ## Step 3 — Fill in SKILL.md Open the new skill's `SKILL.md` (the path Step 1 printed) and replace every `FILL IN:` -placeholder. The scaffold template already carries the compliant frontmatter and body skeleton — -fill it rather than restructuring it. +placeholder. The scaffold template carries the ADR-0020 body skeleton and the two frontmatter +fields that cannot be left as placeholders — `name`, substituted by the script, and +`metadata.version`, seeded live at `"0.1.0"` — so fill the template in rather than restructuring +it. **`name`** — already set by the scaffold script. Must exactly match the directory name. Format: 1–64 characters, lowercase letters, numbers and hyphens only; no leading, trailing or consecutive @@ -96,15 +98,18 @@ against `references/contract.md`, which holds the three-part shape, the banned c boundary-clause form and the length tiers. A hand-invoked skill (`SKILL.md` Step 2) takes one plain sentence and `disable-model-invocation: true` instead. +**`metadata.version`** — required on every skill (ADR-0022), not a per-skill or per-plugin choice, +and enforced by the `skill-frontmatter` pre-commit hook. The scaffold seeds a new skill at +`"0.1.0"`; leave that value alone here and let `SKILL.md` Step 4 bump it. (`"1.0.0"` is the seed +for a pre-existing skill retrofitted into the rule, and never applies to a skill created here.) + **Optional frontmatter** — uncomment and fill in, or remove entirely: - `license` — include when distributing the skill externally - `compatibility` — include if the skill requires specific tools, runtimes, or network access (max 500 characters) -- `metadata` — key-value map. `version` is **required** on every skill (ADR-0022), seeded at - `"1.0.0"` for a retrofitted skill with no prior version and at `"0.1.0"` for a newly created - skill; `author` and `category` stay optional; add `source_keys` now (Step 6) if research sources - are in context +- `metadata` — the rest of the map, all of it optional: `author` and `category`, plus `source_keys` + now (Step 6) if research sources are in context - `allowed-tools` — space-separated pre-approved tools; reduces permission prompts (experimental — support varies by client) - `disable-model-invocation` — hand-invoked skills only diff --git a/plugins/kyberforge/.apm/skills/skill-author/references/improve.md b/plugins/kyberforge/.apm/skills/skill-author/references/improve.md index ffdf625..feda975 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/references/improve.md +++ b/plugins/kyberforge/.apm/skills/skill-author/references/improve.md @@ -85,6 +85,10 @@ improvise the cuts — four dry runs invented six to ten different answers to th If a signal points to a script or reference file, edit that file directly rather than adding a workaround in SKILL.md. +**A skill carrying no `metadata.version` is seeded at `"1.0.0"`, not bumped** — `SKILL.md` Step 4's +patch bump presumes a version to bump, and ADR-0022 reserves `"0.1.0"` for a newly created skill. +`references/retrofit.md` carries the reasoning. + **Check for regressions before handing back.** `SKILL.md` Step 4 tells you to resolve every FAIL, which says nothing about a check that passed *before* these edits and no longer does. Compare the closing audit against the skill's pre-edit state — a PASS that has become a SUGGESTION, or a diff --git a/plugins/kyberforge/.apm/skills/skill-author/references/retrofit.md b/plugins/kyberforge/.apm/skills/skill-author/references/retrofit.md index 337bb1d..0755773 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/references/retrofit.md +++ b/plugins/kyberforge/.apm/skills/skill-author/references/retrofit.md @@ -105,16 +105,37 @@ them for you. After every retrofit that adds, removes or renames a file: zero. - [ ] Re-run `/skill-audit` and confirm its `### Provenance` dimension does not report the new file as missing `source_keys`. -- [ ] **Compression must not add authority the source text didn't have.** The bullet above is - about a `sources.md` entry going *stale* — Contributing files left uncited after content - moves. This is a distinct failure: a compression or rewrite pass that upgrades an honest - hedge in a Description into an unsupported confident claim, without the underlying source - having changed at all — "no forge-specific content drawn directly from it beyond that" - quietly becoming "Grounds Step 2's dispatch table." Nothing in `/skill-audit`'s structural - checks catches this; a bash script can verify an entry is internally consistent, never - whether the claim is *true*. If a retrofit strengthens or otherwise changes the wording of a - provenance claim, re-read the upstream research doc first and confirm the stronger wording - is actually still true before committing it. + +## Compression must not add authority the source text didn't have + +This one is **not** part of the checklist above, and deliberately so: it fires on a wording change +with no file change at all, so a retrofit that adds and removes nothing still owes it. + +The `sources.md` bullet above is about an entry going *stale* — Contributing files left uncited +after content moves. This is a distinct failure: a compression or rewrite pass that upgrades an +honest hedge in a Description into an unsupported confident claim, without the underlying source +having changed at all — "no forge-specific content drawn directly from it beyond that" quietly +becoming "Grounds Step 2's dispatch table." + +`/skill-audit`'s provenance script does now notice this class: it diffs each slug's `Description` +and `Contributing files` text against a base ref and raises an **INFO** when the wording changed. +That is a prompt, not a verdict — it reports only *that* the claim moved, never whether the new +claim is true, because a bash script can verify an entry is internally consistent and nothing more. +Answering it is this flow's job: if a retrofit strengthens or otherwise changes the wording of a +provenance claim, re-read the upstream research doc first and confirm the stronger wording is +actually still true before committing it. + +## Versioning a retrofitted skill + +`SKILL.md` Step 4 says to bump the **patch** version on improve, which presumes there is a version +to bump. A pre-ADR-0020 skill often carries none — `metadata.version` only became mandatory under +ADR-0022, and this flow is exactly where those skills surface. + +A skill with no `metadata.version` is **seeded at `"1.0.0"`, not bumped**. `"0.1.0"` is reserved +for a skill created new by the create flow: it means "created and never yet revised", which +understates a skill that has been through retrofit and audit passes without tracking a version. +Add the field in this retrofit — the `skill-frontmatter` pre-commit hook blocks the commit without +it. ## Worked example — a description retrofit diff --git a/plugins/kyberforge/.apm/skills/skill-author/tests/new-skill.bats b/plugins/kyberforge/.apm/skills/skill-author/tests/new-skill.bats index dd3a188..5540f28 100644 --- a/plugins/kyberforge/.apm/skills/skill-author/tests/new-skill.bats +++ b/plugins/kyberforge/.apm/skills/skill-author/tests/new-skill.bats @@ -156,6 +156,18 @@ EOF assert_success } +@test "scaffold emits a live metadata.version seeded at 0.1.0 (ADR-0022)" { + # The scaffold must clear .pre-commit-config.yaml's `skill-frontmatter` hook + # on its first commit: a commented-out metadata block ships a skill with no + # version and is blocked. Assert the field is live, not a comment. + bash "$SCRIPT" my-tool "$DEST" + run grep -E '^metadata:$' "$DEST/my-tool/SKILL.md" + assert_success + run grep -E '^ version: "[0-9]+\.[0-9]+\.[0-9]+"$' "$DEST/my-tool/SKILL.md" + assert_success + assert_output --partial '0.1.0' +} + @test "walk-up skips a type-less apm.yml (marketplace-only) and finds a real package root further up" { mkdir -p "$DEST/mid/sub" cat > "$DEST/apm.yml" <<'EOF'