@lmzhen/dsh-evolution-skill-catalog
v0.26.26
Published
Native ctx.skills provider for the evolution-managed skill tree (community build)
Readme
@lmzhen/dsh-evolution-skill-catalog
Native ctx.skills provider for the evolution-managed skill tree — read-only; mutations go
through tool-skill-manage.
Model surface
- Model-visible: nothing of its own: no prompt and no tool schema; it supplies the read-only native
ctx.skillscatalog, and consumers own the model-visible effects. - Prompt prefix / KV cache: independent of request-prefix construction; it does not alter the assembled prompt or tool list; family-level rules:
packages/README.md§"Model-visible prompt prefix and the KV cache". - Mount it? yes — the
evolution-skill-catalogrow, carried by theevolution-alland one-clickevolution-presetbundles and by the Evolution agent preset delta.
Known limitations
- Out-of-band edits need a refresh. The catalog invalidates on the in-band
evolution/skill-mutatedevent (all writes through SkillLibrary). Edits made outside the family (manual file edit, a git pull, another process) bypass that event and cannot be auto-detected (decision C: no filesystem watcher). A root entry-name probe re-stamps the summaries cache when the provider is re-queried after a structural change (directory add/remove/rename) — the stamp is the set of non-dot entry names, not the root's mtime, so the family's own sidecar flushes in the root no longer invalidate the cache, but the probe only runs when the upstream skill registry actually consults this provider: between refreshes the registry's collect cache answerslist/snapshotwithout calling providers (the real reason E-71's out-of-band skill stays invisible), whilegetof an already-indexed name still reaches the provider, so an out-of-band CONTENT edit of an existing skill shows fresh content there (description stays stale until refresh). Any out-of-band change is only guaranteed to be visible after/evolution skills refreshruns (or the process restarts). - Upstream-invalid entries are filtered, not published.
SkillLibrary.list()reports an empty description for a 0-byte/malformed SKILL.md (C-14 keeps it visible to the curator), and a tree entry created before the 0.3.64 name tightening can still carry a trailing/consecutive hyphen. UpstreamvalidateCandidatethrows on either shape, and that throw aborts the wholectx.skillscollection (breakingagent/pre-stepand theskilltool for the session). This provider therefore skips (and warns once about) any candidate whose name is not upstreamSKILL_NAMEor whose description is empty. The entry stays visible to the curator/lifecycle; fix the SKILL.md frontmatter (or the directory name) to publish it. - Invocation frontmatter: canonical keys first, legacy keys honored conservatively. The per-skill
disable-model-invocation/user-invocablekeys are parsed from the same frontmatter the platform reads and take priority; a file that sets neither falls back to the ROW default (modelInvocable: true). Upstream THROWS on the legacy camelCase keys (disableModelInvocation/modelInvocable/userInvocable) and drops the whole file; this shadow warns once and keeps the entry, in the AUTHOR's direction: the mere PRESENCE ofdisableModelInvocationpublishesmodelInvocable: falsewhatever its value (a misspelled value no longer falls back to the row default and re-enables the skill), and a legacymodelInvocable/userInvocableis honored as written when it parses (falsestaysfalse) and falls back to the conservativefalsewhen it does not. Both legacy directions are pinned intests/catalog.spec.ts. whenToUseis published,metadatais not. A non-empty single-linewhenToUsefrom the frontmatter is forwarded to the platform catalog (the upstream filesystem provider does the same, and the host/UI read it for routing hints).metadataneeds a real YAML parse and stays unpublished by this provider.contentis the BODY, not the file. The publishedSkillDefinition.contentis the SKILL.md text AFTER the frontmatter block, matching the upstream filesystem provider (skill-filesystem:content: parsed.body.trim()). This provider shadows that provider for the same skills, so publishing the whole file made the model load a different skill depending on which provider served it. A file whose frontmatter block cannot be read keeps its raw text (the entry stays visible; the audit reports the file throughfrontmatterCatalogInvalid).- Protection markers are best-effort per entry. When the directory listing AND the per-marker probes fail,
SkillSummary.protectionUnknownis true and consumers (curator, maintenance) treat the entry as protected rather than unprotected.
Runtime invariant: No companion is published. The platform auto-assembles nothing and the family mounts no <pkg>/invariant cordis row, so a companion here would never execute (v37 S2.1 / I-3).
Notes and history
- Out-of-band edits need a refresh (0.3.18, E-71).
- Upstream-invalid entries are filtered, not published (P1-1, v18).
- Invocation frontmatter: canonical keys first, legacy keys honored conservatively (OPT-10; P2-30 / P2-9, 0.3.83).
whenToUseis published,metadatais not (E-11, v18).contentis the BODY, not the file (V27 G5.3).- Protection markers are best-effort per entry (A1-17, v18).
Skill names (the family's口径)
The family's canonical name for a skill is its directory name. SKILL.md's frontmatter must
carry the same name: validateFrontmatter(..., expectedName) refuses a mismatch ("Frontmatter
name … does not match target …"), and this provider publishes summary.name — the scanned name the
library derives from the directory.
The platform's own skill-filesystem provider publishes the frontmatter name instead, so an entry
whose frontmatter name differs from its directory can surface under two names: the family's catalog
under one, the platform's under the other.
Decision 1 is open: keep not publishing name-mismatched entries (conservative), or publish under the frontmatter name (thorough, and it moves the read path). Until it is decided this document states the behaviour that ships: the directory name wins.
