Skip to content

fix: use skill references in SKILL.md for skills-only delivery#1194

Open
mc856 wants to merge 3 commits into
Fission-AI:mainfrom
mc856:fix/skills-only-references
Open

fix: use skill references in SKILL.md for skills-only delivery#1194
mc856 wants to merge 3 commits into
Fission-AI:mainfrom
mc856:fix/skills-only-references

Conversation

@mc856

@mc856 mc856 commented Jun 10, 2026

Copy link
Copy Markdown

Fixes #881, closes #879.

When delivery: 'skills' is configured, generated SKILL.md files contained hardcoded /opsx:* command references pointing to commands that were never generated. This implements the fix outlined in #881: adds transformToSkillReferences() with the explicit 11-entry command-to-skill mapping and wires it at every generateSkillContent call site — init.ts, both sites in update.ts (including upgradeLegacyTools), and both sites in workspace/skills.ts.

Deviations from the issue snapshot

  • Kept the existing pi branch in the transformer condition. The issue snippet only checks opencode, but main already routes pi through transformToHyphenCommands; copying the snippet verbatim would regress pi.
  • workspace/skills.ts wired in addition to the files listed in the issue. It generates SKILL.md from the same globalConfig.delivery and is itself a skills-only surface, so the bug persisted there. Regression test included (verified to fail against the unwired code).
  • Note: WORKFLOW_TO_SKILL_DIR exists in both init.ts (local copy) and profile-sync-drift.ts (exported); the two are identical and COMMAND_TO_SKILL_REFERENCE matches both.

Open question for maintainers

In skills-only mode, opencode/pi still take the transformToHyphenCommands branch, so their SKILL.md files contain /opsx-* references to commands that were also never generated — same class of bug. I didn't expand scope because it's unclear whether /openspec-<skill> slash references resolve in those tools. Happy to file a follow-up issue. The legacy-upgrade path also lacks a skills-only content assertion; same offer.

Testing

  • npx eslint src/ clean
  • transformToSkillReferences unit tests: per-mapping assertions for all 11 commands, multi-reference, backtick, unknown-command, and bulk-archive/archive boundary cases
  • Integration: init + update skills-only cases assert generated SKILL.md contains no /opsx: and does contain /openspec- (explore template verified to contain /opsx: references, so the assertion is discriminative); new workspace test mutation-verified
  • Full vitest suite passing

Generated with Claude (Cowork) using claude-fable-5.

Summary by CodeRabbit

  • Bug Fixes

    • Skills-only delivery now generates correct skill reference links in all generated skill files (init, update, workspace), replacing incorrect command-style references.
  • Tests

    • Tests added/expanded to verify skill files contain skill references (and no command paths) across init, update, and workspace scenarios, and to validate the reference transformation logic.

mc856 added 2 commits June 9, 2026 19:13
When delivery is configured as 'skills', generated SKILL.md files
contained hardcoded /opsx:* command references pointing to commands
that were never generated, breaking cross-skill workflows.

Add transformToSkillReferences() with the explicit command-to-skill
mapping (kept in sync with WORKFLOW_TO_SKILL_DIR) and wire it in
init and update wherever skill content is generated, following the
approach outlined in Fission-AI#881.

Closes Fission-AI#881
Closes Fission-AI#879

Generated with Claude (Cowork) using claude-fable-5; verified with the
full vitest suite (1683 tests passing).
Review follow-up for the skills-only delivery fix: workspace skill
setup (src/core/workspace/skills.ts) generates SKILL.md via the same
generateSkillContent path but was not wired with
transformToSkillReferences, leaving dangling /opsx:* references when
delivery is 'skills'. Wire both call sites, add a regression test
(verified to fail against the unwired code), strengthen the update
skills-only test with content assertions, and correct the
COMMAND_TO_SKILL_REFERENCE comment (WORKFLOW_TO_SKILL_DIR exists in
both profile-sync-drift.ts and init.ts).

Generated with Claude (Cowork) using claude-fable-5; verified with
eslint and targeted vitest suites (144 tests passing).
@mc856 mc856 requested a review from TabishB as a code owner June 10, 2026 03:27
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bcedb74a-5bda-400c-919e-99ad82d5db99

📥 Commits

Reviewing files that changed from the base of the PR and between 45f3e56 and 4ef4c48.

📒 Files selected for processing (7)
  • src/core/init.ts
  • src/core/update.ts
  • src/core/workspace/skills.ts
  • src/utils/command-references.ts
  • src/utils/index.ts
  • test/core/workspace/skills.test.ts
  • test/utils/command-references.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/utils/index.ts
  • test/utils/command-references.test.ts
  • test/core/workspace/skills.test.ts
  • src/utils/command-references.ts
  • src/core/update.ts

📝 Walkthrough

Walkthrough

Skills-only delivery now rewrites hardcoded /opsx:<command> tokens in generated SKILL.md to /openspec-* skill references using a new transformer selected by tool and delivery mode; utilities and exports were added and tests updated to validate the behavior.

Changes

Skills-Only Delivery Reference Transformation

Layer / File(s) Summary
Skill reference transformer utility
src/utils/command-references.ts, src/utils/index.ts, .changeset/skills-only-references.md
Adds COMMAND_TO_SKILL_REFERENCE and transformToSkillReferences(text), and exports getTransformerForTool(toolId, delivery); re-exports updated from utils index and changeset docs updated.
Core modules transformer integration
src/core/init.ts, src/core/update.ts, src/core/workspace/skills.ts
Replace inline transformer selection with getTransformerForTool(tool.value, delivery) when generating SKILL.md so transformer choice is delivery- and tool-aware across init, update (main + legacy), and workspace skill generation.
Test coverage and validation
test/utils/command-references.test.ts, test/core/init.test.ts, test/core/update.test.ts, test/core/workspace/skills.test.ts
Unit tests validate mapping, edge cases, and transformer selection; integration tests assert generated SKILL.md files contain /openspec- references and do not contain /opsx: when delivery: 'skills'.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Fission-AI/OpenSpec#627: Addresses command-reference transformation for OpenCode (/opsx:/opsx-) using a transformer mechanism similar to this PR.
  • Fission-AI/OpenSpec#626: Centralizes transformer usage for SKILL.md generation; related by hooking into the same generation flow.
  • Fission-AI/OpenSpec#950: Modifies transformer logic for tools like pi; related to tool-specific transformer selection.

Suggested reviewers

  • TabishB
  • alfred-openspec

"I hop with glee through code and strings,
Rewriting refs to proper things.
From /opsx: the old trail parts—
Now /openspec- fills skillly hearts. 🥕"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: use skill references in SKILL.md for skills-only delivery' accurately and concisely describes the primary change: fixing the transformer used in SKILL.md generation for skills-only delivery mode.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from issues #881 and #879: added transformToSkillReferences() with 11-entry /opsx:* to /openspec-* mapping, wired transformer at all generateSkillContent sites, added comprehensive unit and integration tests.
Out of Scope Changes check ✅ Passed All changes directly support the stated objectives: command-references utility updates, transformer wiring in init/update/workspace skills, test coverage. No unrelated refactoring or scope creep detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/utils/command-references.ts (1)

22-26: ⚖️ Poor tradeoff

Sync burden: mapping duplicated across files.

The comment warns that COMMAND_TO_SKILL_REFERENCE must stay in sync with WORKFLOW_TO_SKILL_DIR in two other locations. This creates a maintenance risk: if one copy is updated without updating the others, skill references will break at runtime. Consider consolidating these mappings into a single source of truth (e.g., exporting WORKFLOW_TO_SKILL_DIR from a shared module and deriving the skill reference map from it).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/command-references.ts` around lines 22 - 26, The duplicate mapping
risk: consolidate the source of truth by exporting WORKFLOW_TO_SKILL_DIR from a
single shared module and derive COMMAND_TO_SKILL_REFERENCE from that exported
mapping instead of maintaining separate copies; update code that currently
defines COMMAND_TO_SKILL_REFERENCE (and the local copies of
WORKFLOW_TO_SKILL_DIR) to import the shared WORKFLOW_TO_SKILL_DIR and build the
command-to-skill map (e.g., compute COMMAND_TO_SKILL_REFERENCE by mapping
keys/values from WORKFLOW_TO_SKILL_DIR) so only one mapping needs to be
maintained.
src/core/init.ts (1)

540-546: ⚡ Quick win

Extract duplicated transformer selection logic into a helper function.

The transformer selection conditional appears identically in 5 locations across 3 files. This violates DRY and creates maintenance risk: if the logic needs to change (e.g., adding a new delivery mode or tool-specific behavior), all 5 sites must be updated consistently.

Extract this logic into a shared helper function in src/utils/command-references.ts:

♻️ Proposed refactor
/**
 * Selects the appropriate command-reference transformer based on tool and delivery mode.
 * `@param` toolId - The AI tool identifier (e.g., 'claude', 'opencode', 'pi')
 * `@param` delivery - The delivery mode ('skills', 'commands', or 'both')
 * `@returns` The transformer function or undefined
 */
export function getTransformerForTool(
  toolId: string,
  delivery: 'skills' | 'commands' | 'both'
): ((text: string) => string) | undefined {
  if (toolId === 'opencode' || toolId === 'pi') {
    return transformToHyphenCommands;
  }
  if (delivery === 'skills') {
    return transformToSkillReferences;
  }
  return undefined;
}

Then replace each of the 5 duplicated blocks with:

const transformer = getTransformerForTool(tool.value, delivery);
// or for workspace/skills.ts:
const transformer = getTransformerForTool(tool.value, profileContext.delivery);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/init.ts` around lines 540 - 546, Duplicate transformer-selection
logic used in multiple places should be pulled into a helper; create a function
getTransformerForTool(toolId: string, delivery: 'skills' | 'commands' | 'both')
that returns transformToHyphenCommands when toolId === 'opencode' || toolId ===
'pi', returns transformToSkillReferences when delivery === 'skills', and
otherwise returns undefined, then replace the inline conditional in
src/core/init.ts (the const transformer assignment) and the four other
occurrences with calls to getTransformerForTool(tool.value, delivery) (or
getTransformerForTool(tool.value, profileContext.delivery) where appropriate) so
all sites use the single shared implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/core/init.ts`:
- Around line 540-546: Duplicate transformer-selection logic used in multiple
places should be pulled into a helper; create a function
getTransformerForTool(toolId: string, delivery: 'skills' | 'commands' | 'both')
that returns transformToHyphenCommands when toolId === 'opencode' || toolId ===
'pi', returns transformToSkillReferences when delivery === 'skills', and
otherwise returns undefined, then replace the inline conditional in
src/core/init.ts (the const transformer assignment) and the four other
occurrences with calls to getTransformerForTool(tool.value, delivery) (or
getTransformerForTool(tool.value, profileContext.delivery) where appropriate) so
all sites use the single shared implementation.

In `@src/utils/command-references.ts`:
- Around line 22-26: The duplicate mapping risk: consolidate the source of truth
by exporting WORKFLOW_TO_SKILL_DIR from a single shared module and derive
COMMAND_TO_SKILL_REFERENCE from that exported mapping instead of maintaining
separate copies; update code that currently defines COMMAND_TO_SKILL_REFERENCE
(and the local copies of WORKFLOW_TO_SKILL_DIR) to import the shared
WORKFLOW_TO_SKILL_DIR and build the command-to-skill map (e.g., compute
COMMAND_TO_SKILL_REFERENCE by mapping keys/values from WORKFLOW_TO_SKILL_DIR) so
only one mapping needs to be maintained.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c67c585-1070-4587-8421-be46f4b1dcbb

📥 Commits

Reviewing files that changed from the base of the PR and between 1b06fdd and 45f3e56.

📒 Files selected for processing (10)
  • .changeset/skills-only-references.md
  • src/core/init.ts
  • src/core/update.ts
  • src/core/workspace/skills.ts
  • src/utils/command-references.ts
  • src/utils/index.ts
  • test/core/init.test.ts
  • test/core/update.test.ts
  • test/core/workspace/skills.test.ts
  • test/utils/command-references.test.ts

…rTool

Address CodeRabbit review: the tool/delivery transformer selection was
duplicated at five call sites across init.ts, update.ts, and
workspace/skills.ts. Extract it into a documented helper in
command-references.ts with unit tests locking the selection matrix
(opencode/pi precedence, skills-only delivery, default).

Generated with Claude (Cowork) using claude-fable-5; verified with
eslint, tsc, and targeted vitest suites (147 tests passing).
@mc856

mc856 commented Jun 10, 2026

Copy link
Copy Markdown
Author

Pushed 4ef4c48 addressing the CodeRabbit review: extracted the duplicated transformer selection into getTransformerForTool() in command-references.ts (with JSDoc and unit tests locking the selection matrix), replacing all five call sites.

On consolidating the WORKFLOW_TO_SKILL_DIR copies: agreed in principle, but deriving the map in src/utils from src/core/profile-sync-drift.ts would invert the utils ← core layering, and moving the canonical map into utils touches profile-sync-drift.ts typing and init.ts beyond this bugfix's scope. Happy to do it as a follow-up PR if maintainers agree.

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.

[Fix] Add transformToSkillReferences for skills-only delivery mode [Bug] Skills-only delivery emits /opsx:* command references

1 participant