-
Notifications
You must be signed in to change notification settings - Fork 2.4k
[Bug] Skills-only delivery emits /opsx:* command references #879
Description
OpenSpec Bug Report: Skills-only delivery emits /opsx:* command references
Date: 2026-03-26
OpenSpec version: 1.2.0
Context: Discovered while auditing .claude/ files in a project configured with delivery: 'skills'. All generated openspec-* skills contained /opsx:* cross-references pointing to commands that were never generated.
Bug title
Skills-only delivery generates skill files with /opsx:* command references instead of /openspec-* skill references
Description
When OpenSpec is configured with delivery: 'skills' (skills only, no commands), the generated SKILL.md files contain hardcoded /opsx:* cross-references (e.g., /opsx:apply, /opsx:archive, /opsx:verify). These reference commands that don't exist in a skills-only setup, creating broken workflows.
Expected behavior
When delivery: 'skills', cross-references in generated skills should use the skill namespace: /openspec-apply-change, /openspec-archive-change, /openspec-verify-change, etc.
Actual behavior
All cross-references use the command namespace (/opsx:apply, /opsx:archive, etc.) regardless of the delivery setting.
Affected skills
Every skill with cross-references is affected:
| Skill | Broken references found |
|---|---|
openspec-propose |
/opsx:apply |
openspec-ff-change |
/opsx:apply |
openspec-apply-change |
/opsx:apply, /opsx:archive |
openspec-explore |
/opsx:explore |
Root cause
-
Skill templates hardcode
/opsx:*: The workflow template functions insrc/core/templates/workflows/*.ts(e.g.,getOpsxProposeSkillTemplate,getApplyChangeSkillTemplate) embed/opsx:*command references directly in theinstructionsstrings. -
No delivery-aware transformer for skills:
generateSkillContent()insrc/core/shared/skill-generation.tsaccepts atransformInstructionscallback, but:- The only transformer is
transformToHyphenCommands(for OpenCode:/opsx:→/opsx-) - No transformer exists for the skills-only case (
/opsx:*→/openspec-*) - In
src/core/init.tsandsrc/core/update.ts, whendelivery === 'skills', no transformer is passed
- The only transformer is
Suggested fix
The mapping isn't a simple regex — command short names differ from skill directory names:
| Command ref | Skill ref |
|---|---|
/opsx:apply |
/openspec-apply-change |
/opsx:archive |
/openspec-archive-change |
/opsx:verify |
/openspec-verify-change |
/opsx:continue |
/openspec-continue-change |
/opsx:propose |
/openspec-propose |
/opsx:explore |
/openspec-explore |
/opsx:ff |
/openspec-ff-change |
/opsx:new |
/openspec-new-change |
Options:
- Add a
transformToSkillReferencesfunction insrc/utils/command-references.tswith the explicit mapping table above. Apply it ininit.tsandupdate.tswhendelivery === 'skills'. - Or refactor templates to accept a reference-format parameter, emitting correct cross-references at construction time.
Reproduction
- Run
openspec initand choosedelivery: 'skills' - Inspect any generated skill, e.g.,
.claude/skills/openspec-propose/SKILL.md - Observe
/opsx:applyin the output text — a command that was never generated