Skip to content

fix(templates): deduplicate apply skill and command instructions#1153

Open
Shashank200345 wants to merge 7 commits into
Fission-AI:mainfrom
Shashank200345:fix/deduplicate-skill-command-instructions
Open

fix(templates): deduplicate apply skill and command instructions#1153
Shashank200345 wants to merge 7 commits into
Fission-AI:mainfrom
Shashank200345:fix/deduplicate-skill-command-instructions

Conversation

@Shashank200345
Copy link
Copy Markdown

@Shashank200345 Shashank200345 commented Jun 1, 2026

What's this about?

I was looking into the duplication issue between skill and command
files and noticed that apply-change.ts had the instruction body
written out twice — once in getApplyChangeSkillTemplate() and
again in getOpsxApplyCommandTemplate(). They had already drifted
apart in 3 places.

What I did

Pulled the shared instructions into a single APPLY_INSTRUCTIONS
constant at the top of the file. Both functions now point to the
same string, so there's only one place to edit going forward.

How I verified it

Ran openspec init --tools claude --force and diffed the two
generated files. Before the fix there were 3 content differences.
After — only frontmatter (name, description, metadata) differs,
which is expected and correct.

Notes

This fixes apply-change.ts specifically. The same pattern can be
applied to the other workflow files (propose.ts, explore.ts, etc.)
as a follow-up if the maintainers are happy with this approach.

Summary by CodeRabbit

  • Improvements
    • Unified apply-workflow messaging so the skill and command views present the same guidance for continuing and archiving, and fixed a bullet formatting glitch for consistent rendering.
  • Tests
    • Added parity checks that normalize and compare the skill and command instruction text to ensure they remain identical across modes.

Extract shared APPLY_INSTRUCTIONS constant so skill and command
templates reference the same string. Eliminates content drift
reported in Fission-AI#1139.
@Shashank200345 Shashank200345 requested a review from TabishB as a code owner June 1, 2026 20:21
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

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: cdd74406-ffc6-4623-bf35-f2dc5aec730d

📥 Commits

Reviewing files that changed from the base of the PR and between 9e37028 and 06a5c22.

📒 Files selected for processing (1)
  • src/core/templates/workflows/apply-change.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/templates/workflows/apply-change.ts

📝 Walkthrough

Walkthrough

Extracts apply-change instruction text into getApplyInstructions(mode) and wires skill and opsx command templates to use it; updates mode-specific continue/archive references and adjusts parity-test hashes and adds a normalization parity assertion.

Changes

Apply Change Workflow Instructions

Layer / File(s) Summary
Shared instruction helper and inline updates
src/core/templates/workflows/apply-change.ts
Adds getApplyInstructions(mode) that builds the apply-change instruction text with mode-specific ${continueRef} and ${archiveRef}; replaces the blocked-state and completion lines and tidies Fluid Workflow Integration bullets.
Refactor consumers & parity tests
src/core/templates/workflows/apply-change.ts, test/core/templates/skill-templates-parity.test.ts
getApplyChangeSkillTemplate() and getOpsxApplyCommandTemplate() now source their instruction content from `getApplyInstructions('skill'

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • TabishB
  • alfred-openspec

Poem

🐇 A helper hopped in, tidy and spry,

One voice for skill and command nearby,
“Continue” or /opsx:continue on the way,
“Archive” or /opsx:archive ends the day,
The rabbit applauds — no duplicity!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% 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 directly and concisely describes the main change: deduplicating apply skill and command instructions by refactoring shared logic into a parameterized helper function.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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.

Copy link
Copy Markdown
Collaborator

@alfred-openspec alfred-openspec left a comment

Choose a reason for hiding this comment

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

Thanks for chasing this drift, the dedupe direction is useful. I’m requesting changes because the shared body now makes the generated skill recommend /opsx:continue and /opsx:archive, which regresses skills-only/non-command installs, and the template parity test currently fails because the intentional prompt hash changes were not updated.

If you keep the shared constant, please parameterize or split the invocation-specific lines so the skill path can keep skill-friendly references while the command path keeps /opsx:*; also avoid marking #1139 fixed unless we intentionally accept source-level dedupe as the first slice, since generated projects still get two full editable copies.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
test/core/templates/skill-templates-parity.test.ts (1)

32-70: ⚡ Quick win

Add a direct apply skill/command parity assertion.

These hash updates re-baseline the outputs, but they still won’t fail if the skill and command drift together and both constants get updated in the same PR. Since this change is specifically about deduplicating the apply instructions, add one focused assertion that normalizes the two mode-specific phrases and verifies getApplyChangeSkillTemplate().instructions matches getOpsxApplyCommandTemplate().content after normalization. That pins the actual contract from issue #1139 instead of only pinning snapshots.

♻️ Suggested test shape
 describe('skill templates split parity', () => {
+  it('keeps apply skill and command instructions in sync apart from mode-specific wording', () => {
+    const normalizeApplyInstructions = (value: string) =>
+      value
+        .replaceAll('`/opsx:continue`', '<continue-ref>')
+        .replaceAll('the openspec-continue-change skill', '<continue-ref>')
+        .replaceAll('You can archive this change with `/opsx:archive`.', '<archive-ref>')
+        .replaceAll('Ready to archive this change.', '<archive-ref>');
+
+    expect(
+      normalizeApplyInstructions(getApplyChangeSkillTemplate().instructions)
+    ).toEqual(
+      normalizeApplyInstructions(getOpsxApplyCommandTemplate().content)
+    );
+  });
+
   it('preserves all template function payloads exactly', () => {
🤖 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 `@test/core/templates/skill-templates-parity.test.ts` around lines 32 - 70, Add
a direct parity assertion that compares
getApplyChangeSkillTemplate().instructions to
getOpsxApplyCommandTemplate().content after normalizing mode-specific wording;
implement a small normalizer (e.g., trim, collapse whitespace, toLowerCase, and
replace or remove the differing mode-specific phrases/labels used in apply vs
opsx apply) and assert normalized(getApplyChangeSkillTemplate().instructions)
=== normalized(getOpsxApplyCommandTemplate().content) so the test fails if the
actual contract between those two templates drifts.
🤖 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 `@test/core/templates/skill-templates-parity.test.ts`:
- Around line 32-70: Add a direct parity assertion that compares
getApplyChangeSkillTemplate().instructions to
getOpsxApplyCommandTemplate().content after normalizing mode-specific wording;
implement a small normalizer (e.g., trim, collapse whitespace, toLowerCase, and
replace or remove the differing mode-specific phrases/labels used in apply vs
opsx apply) and assert normalized(getApplyChangeSkillTemplate().instructions)
=== normalized(getOpsxApplyCommandTemplate().content) so the test fails if the
actual contract between those two templates drifts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 538f213c-5750-4220-898b-d6df2164f991

📥 Commits

Reviewing files that changed from the base of the PR and between 56b5428 and c81d50e.

📒 Files selected for processing (2)
  • src/core/templates/workflows/apply-change.ts
  • test/core/templates/skill-templates-parity.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/templates/workflows/apply-change.ts

@Shashank200345
Copy link
Copy Markdown
Author

Thanks for chasing this drift, the dedupe direction is useful. I’m requesting changes because the shared body now makes the generated skill recommend /opsx:continue and /opsx:archive, which regresses skills-only/non-command installs, and the template parity test currently fails because the intentional prompt hash changes were not updated.

If you keep the shared constant, please parameterize or split the invocation-specific lines so the skill path can keep skill-friendly references while the command path keeps /opsx:*; also avoid marking #1139 fixed unless we intentionally accept source-level dedupe as the first slice, since generated projects still get two full editable copies.

Updated! The shared constant is now a parameterized function —
skill path uses skill-friendly references (openspec-continue-change
skill, "Ready to archive") while command path keeps /opsx:* references.
Parity hashes updated and all 3 parity tests pass.

@Shashank200345
Copy link
Copy Markdown
Author

Updated! Added a normalized body parity assertion that strips
mode specific phrases and asserts the two templates share the
same structure. All 4 parity tests pass.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/core/templates/workflows/apply-change.ts (1)

29-29: 💤 Low value

Consider parameterizing invocation examples in a follow-up.

Lines 29 and 40 contain hardcoded /opsx:apply examples (e.g., `/opsx:apply add-auth`, `/opsx:apply <other>`). For command mode these are correct, but for skill mode the invocation mechanism may differ. The current PR successfully parameterizes the continue/archive references (lines 64, 136), which was the stated objective. If skills are invoked differently than slash commands, consider parameterizing these examples in a follow-up to maintain consistency.

Also applies to: 40-40

🤖 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/templates/workflows/apply-change.ts` at line 29, The template in
apply-change.ts hardcodes the `/opsx:apply` invocation in inline examples (e.g.,
the strings containing "/opsx:apply add-auth" and "/opsx:apply <other>"); change
these to use a parameterized placeholder (e.g., an invocation variable like
{INVOKE_SYNTAX} or {INVOCATION} inserted into the template rendering) so the
same template works for slash-command mode and skill-mode; update all
occurrences of the literal "/opsx:apply" in apply-change.ts to reference that
placeholder (similar to the already-parameterized continue/archive references)
and ensure the rendering code supplies the correct invocation string depending
on command vs skill mode.
🤖 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/templates/workflows/apply-change.ts`:
- Line 29: The template in apply-change.ts hardcodes the `/opsx:apply`
invocation in inline examples (e.g., the strings containing "/opsx:apply
add-auth" and "/opsx:apply <other>"); change these to use a parameterized
placeholder (e.g., an invocation variable like {INVOKE_SYNTAX} or {INVOCATION}
inserted into the template rendering) so the same template works for
slash-command mode and skill-mode; update all occurrences of the literal
"/opsx:apply" in apply-change.ts to reference that placeholder (similar to the
already-parameterized continue/archive references) and ensure the rendering code
supplies the correct invocation string depending on command vs skill mode.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 250131e7-98d9-48eb-b72f-62f845e45dbb

📥 Commits

Reviewing files that changed from the base of the PR and between 1e379ca and 9e37028.

📒 Files selected for processing (1)
  • src/core/templates/workflows/apply-change.ts

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.

2 participants