fix(#1925): make _isSkillsRuntime gate descriptor-driven so zcode installs skills

The legacy _isSkillsRuntime gate was a hardcoded isCodex || isCopilot || ...
roster; zcode was absent so the layout-driven skills-install path was skipped
(commands + agents installed, but no skills). Adding || isZcode would violate
AC#3 (no runtime === 'zcode' branches), so the gate is now derived from the
descriptor: a runtime takes the skills path iff its scoped artifactLayout
declares a skills kind. Behavior-preserving for all 15 existing runtimes
(verified by their install contracts); includes zcode (and any future skills
runtime) with zero per-runtime branches. opencode/kilo keep their specialized
combined path.

Regenerate the golden-install-parity fixtures: the non-zcode runtimes shift only
the shared model-catalog.json hash (zcode was added to the catalog); zcode now
includes its skills tree.
This commit is contained in:
Tom Boucher
2026-07-06 07:28:34 -04:00
parent 7acbdc71b8
commit 50aaf09342
17 changed files with 105 additions and 24 deletions

View File

@@ -8594,11 +8594,21 @@ function install(isGlobal, runtime = 'claude', options = {}) {
// applyRuntimeContentRewritesInPlace (called inside installRuntimeArtifacts)
// handles per-runtime path + branding rewrites, including Qwen/Hermes.
// Cline global: emit skills to ~/.cline/skills/ (Cline >= v3.48.0 — #782).
const _isSkillsRuntime = isCodex || isCopilot || isAntigravity || isCursor || isWindsurf ||
isAugment || isTrae || isCodebuddy || isQwen || isHermes ||
isKimi ||
(runtime === 'claude' && isGlobal) ||
(isCline && isGlobal);
// Descriptor-driven (ADR-1016 / ADR-1239): a runtime takes the layout-driven
// skills-install path when its scoped artifactLayout declares a skills kind.
// This replaces the prior hardcoded `isCodex || isCopilot || ...` roster so a
// newly-added runtime with a skills layout installs without a per-runtime
// branch — the add-a-host tax ADR-1239 Phase B retires. opencode/kilo keep
// their specialized combined commands+skills path (copyFlattenedCommands +
// installOpencodeFamilySkills) below.
const _isSkillsRuntime = (() => {
if (isOpencode || isKilo) return false;
const cap = _capabilityRegistry && _capabilityRegistry.runtimes && _capabilityRegistry.runtimes[runtime];
const layout = cap && cap.runtime && cap.runtime.artifactLayout;
if (!layout) return false;
const scopeLayout = isGlobal ? layout.global : layout.local;
return Array.isArray(scopeLayout) && scopeLayout.some((k) => k && k.kind === 'skills');
})();
if (_isSkillsRuntime) {
// Layout-driven install for skills-based runtimes (full and minimal modes)