Skip to content

[Bug] Skills-only delivery emits /opsx:* command references #879

@m9dfukc

Description

@m9dfukc

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

  1. Skill templates hardcode /opsx:*: The workflow template functions in src/core/templates/workflows/*.ts (e.g., getOpsxProposeSkillTemplate, getApplyChangeSkillTemplate) embed /opsx:* command references directly in the instructions strings.

  2. No delivery-aware transformer for skills: generateSkillContent() in src/core/shared/skill-generation.ts accepts a transformInstructions callback, but:

    • The only transformer is transformToHyphenCommands (for OpenCode: /opsx:/opsx-)
    • No transformer exists for the skills-only case (/opsx:*/openspec-*)
    • In src/core/init.ts and src/core/update.ts, when delivery === 'skills', no transformer is passed

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:

  1. Add a transformToSkillReferences function in src/utils/command-references.ts with the explicit mapping table above. Apply it in init.ts and update.ts when delivery === 'skills'.
  2. Or refactor templates to accept a reference-format parameter, emitting correct cross-references at construction time.

Reproduction

  1. Run openspec init and choose delivery: 'skills'
  2. Inspect any generated skill, e.g., .claude/skills/openspec-propose/SKILL.md
  3. Observe /opsx:apply in the output text — a command that was never generated

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions