Skip to content

feat(skills): per-skill runtime compatibility (#119) - #2160

Merged
HongmingWang-Rabbit merged 2 commits into
stagingfrom
feat/skill-runtime-compat
Apr 27, 2026
Merged

feat(skills): per-skill runtime compatibility (#119)#2160
HongmingWang-Rabbit merged 2 commits into
stagingfrom
feat/skill-runtime-compat

Conversation

@HongmingWang-Rabbit

Copy link
Copy Markdown
Contributor

Summary

  • SKILL.md frontmatter can now declare `runtime: [claude-code]` or `runtime: [hermes, claude-code]` to opt out of incompatible adapters at load time instead of failing at first invocation
  • Default `["*"]` means universal — existing skill libraries need zero migration
  • Borrowed from hermes' declarative skill-compat pattern (one of three patterns surfaced in the hermes architecture survey under fix(security+scheduler): IPv6 SSRF gap + scheduler unit tests [supersedes #111, #112] #119; event-log + observability config block stay open)

Wiring

  • `SkillMetadata.runtime: list[str] = ["*"]` — new dataclass field
  • `_normalize_runtime_field()` — accepts list, string sugar, missing → `["*"]`; malformed warns + falls back to universal so a typo never silently drops a skill
  • `load_skills(..., current_runtime=...)` — filters out skills whose runtime list lacks `"*"` or `current_runtime`, with INFO log line
  • `BaseAdapter.start()` passes `type(self).name()` so the live adapter drives the filter
  • `SkillsWatcher` takes the same kwarg so hot-reload honors it

Test plan

🤖 Generated with Claude Code

SKILL.md frontmatter can now declare `runtime: [claude-code]` or
`runtime: [hermes, claude-code]` to opt out of incompatible adapters
instead of failing at first invocation. Default `["*"]` means universal —
existing skill libraries need zero migration.

Borrowed from hermes' declarative skill-compat pattern surfaced in the
hermes architecture survey. The remaining two patterns (event-log
layer, observability config block) stay open under #119.

Wiring:
- SkillMetadata.runtime: list[str] = ["*"]
- _normalize_runtime_field accepts list, string-sugar, missing -> ["*"];
  malformed warns and falls back to universal so a typo never silently
  drops a skill.
- load_skills(..., current_runtime=...) filters out skills whose runtime
  list lacks "*" or current_runtime, with an INFO log line.
- BaseAdapter.start passes type(self).name() so the live adapter drives
  the filter; SkillsWatcher takes the same kwarg so hot-reload honors it.

8 new tests cover default universal, no-field universal, explicit
match/mismatch, string sugar, wildcard short-circuit, current_runtime=None
(preserves old behavior), and malformed-warns-not-drops.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The runtime-compat change in this branch added a `current_runtime`
kwarg to load_skills(); the watcher passes it through. Test mocks
that pre-date the kwarg signature broke with TypeError, which the
watcher's reload-error try/except swallowed — the symptom was empty
callback lists, not a clear failure.

Switching the fakes to accept **kwargs keeps them forward-compat for
future load_skills additions without another test churn.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@HongmingWang-Rabbit
HongmingWang-Rabbit added this pull request to the merge queue Apr 27, 2026
Merged via the queue into staging with commit 7d872f9 Apr 27, 2026
14 checks passed
@molecule-ai
molecule-ai Bot deleted the feat/skill-runtime-compat branch May 20, 2026 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant