Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/sync-specs-main-spec-format.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fission-ai/openspec": patch
---

Show the main spec format in the sync-specs skill so agents stop leaving delta operation headers (`## ADDED/MODIFIED Requirements`) in `openspec/specs/` — merged main specs with those headers parse as 0 requirements in `openspec view` (#1120).
5 changes: 5 additions & 0 deletions openspec/specs/specs-sync-skill/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ The agent SHALL reconcile main specs with delta specs using the delta operation
- **WHEN** delta spec exists for a capability not in main specs
- **THEN** create new main spec file at `openspec/specs/<capability>/spec.md`

#### Scenario: Merged main spec keeps canonical structure
- **WHEN** the agent writes a main spec during sync
- **THEN** every requirement lives under a single `## Requirements` section
- **AND** the main spec contains no delta operation headers (`## ADDED/MODIFIED/REMOVED/RENAMED Requirements`)

### Requirement: Skill Output
The skill SHALL provide clear feedback on what was applied.

Expand Down
22 changes: 22 additions & 0 deletions skills/openspec-sync-specs/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ This is an **agent-driven** operation - you will read delta specs and directly e
- Create `<planningHome.root>/openspec/specs/<capability>/spec.md`
- Add Purpose section (can be brief, mark as TBD)
- Add Requirements section with the ADDED requirements
- Follow the **Main Spec Format Reference** below

5. **Show summary**

Expand Down Expand Up @@ -116,6 +117,26 @@ The system SHALL do something new.
- TO: `### Requirement: New Name`
```

**Main Spec Format Reference**

Main specs are what the delta merges INTO. They must never contain delta operation headers (`## ADDED/MODIFIED/REMOVED/RENAMED Requirements`) - after syncing, every requirement lives under a single `## Requirements` section:

```markdown
# <capability> Specification

## Purpose
Short description of what this capability does and why it exists.

## Requirements

### Requirement: New Feature
The system SHALL do something new.

#### Scenario: Basic case
- **WHEN** user does X
- **THEN** system does Y
```

**Key Principle: Intelligent Merging**

Unlike programmatic merging, you can apply **partial updates**:
Expand Down Expand Up @@ -144,6 +165,7 @@ Main specs are now updated. The change remains active - archive when implementat
**Guardrails**
- Read both delta and main specs before making changes
- Preserve existing content not mentioned in delta
- Never copy a delta file into a main spec as-is - merge its content so the main spec keeps the Main Spec Format Reference structure, with no delta operation headers
- If something is unclear, ask for clarification
- Show what you're changing as you go
- The operation should be idempotent - running twice should give same result
44 changes: 44 additions & 0 deletions src/core/templates/workflows/sync-specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ ${STORE_SELECTION_GUIDANCE}
- Create \`<planningHome.root>/openspec/specs/<capability>/spec.md\`
- Add Purpose section (can be brief, mark as TBD)
- Add Requirements section with the ADDED requirements
- Follow the **Main Spec Format Reference** below

5. **Show summary**

Expand Down Expand Up @@ -118,6 +119,26 @@ The system SHALL do something new.
- TO: \`### Requirement: New Name\`
\`\`\`

**Main Spec Format Reference**

Main specs are what the delta merges INTO. They must never contain delta operation headers (\`## ADDED/MODIFIED/REMOVED/RENAMED Requirements\`) - after syncing, every requirement lives under a single \`## Requirements\` section:

\`\`\`markdown
# <capability> Specification

## Purpose
Short description of what this capability does and why it exists.

## Requirements

### Requirement: New Feature
The system SHALL do something new.

#### Scenario: Basic case
- **WHEN** user does X
- **THEN** system does Y
\`\`\`

**Key Principle: Intelligent Merging**

Unlike programmatic merging, you can apply **partial updates**:
Expand Down Expand Up @@ -146,6 +167,7 @@ Main specs are now updated. The change remains active - archive when implementat
**Guardrails**
- Read both delta and main specs before making changes
- Preserve existing content not mentioned in delta
- Never copy a delta file into a main spec as-is - merge its content so the main spec keeps the Main Spec Format Reference structure, with no delta operation headers
- If something is unclear, ask for clarification
- Show what you're changing as you go
- The operation should be idempotent - running twice should give same result`,
Expand Down Expand Up @@ -232,6 +254,7 @@ ${STORE_SELECTION_GUIDANCE}
- Create \`<planningHome.root>/openspec/specs/<capability>/spec.md\`
- Add Purpose section (can be brief, mark as TBD)
- Add Requirements section with the ADDED requirements
- Follow the **Main Spec Format Reference** below

5. **Show summary**

Expand Down Expand Up @@ -268,6 +291,26 @@ The system SHALL do something new.
- TO: \`### Requirement: New Name\`
\`\`\`

**Main Spec Format Reference**

Main specs are what the delta merges INTO. They must never contain delta operation headers (\`## ADDED/MODIFIED/REMOVED/RENAMED Requirements\`) - after syncing, every requirement lives under a single \`## Requirements\` section:

\`\`\`markdown
# <capability> Specification

## Purpose
Short description of what this capability does and why it exists.

## Requirements

### Requirement: New Feature
The system SHALL do something new.

#### Scenario: Basic case
- **WHEN** user does X
- **THEN** system does Y
\`\`\`

**Key Principle: Intelligent Merging**

Unlike programmatic merging, you can apply **partial updates**:
Expand Down Expand Up @@ -296,6 +339,7 @@ Main specs are now updated. The change remains active - archive when implementat
**Guardrails**
- Read both delta and main specs before making changes
- Preserve existing content not mentioned in delta
- Never copy a delta file into a main spec as-is - merge its content so the main spec keeps the Main Spec Format Reference structure, with no delta operation headers
- If something is unclear, ask for clarification
- Show what you're changing as you go
- The operation should be idempotent - running twice should give same result`
Expand Down
6 changes: 3 additions & 3 deletions test/core/templates/skill-templates-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const EXPECTED_FUNCTION_HASHES: Record<string, string> = {
getContinueChangeSkillTemplate: 'acc07a489a30192b4bf2bbdc587a889478fbf6fffbbc9353c7775c4ca1ec5011',
getApplyChangeSkillTemplate: '0f5a15fc7fb9ad6059a5643d0e01365d27642637a4aaebf182f9eabb45348197',
getFfChangeSkillTemplate: '20ebb682ba89809a100cd4985c074908df5bada2bd649ca1b0f4059a63a1c728',
getSyncSpecsSkillTemplate: 'dc07ea0312687f3edc602329c889dbbab737c6d79327eb7a723553d346b43433',
getSyncSpecsSkillTemplate: '32c3169e1ee0345a174c0bacb8fd16db73477cc006d8cedbedc6077233c5461b',
getOnboardSkillTemplate: 'e871d8ce172bb805ae62a7611aee7a3154d89414f427ad5ef31721c903f13002',
getOpsxExploreCommandTemplate: '37e53590aae7ac6621d4393aa80a5b8af21881323887fa924ed329199fda27e0',
getOpsxNewCommandTemplate: '57c600cce318d16b9b4308a18d0d983ea3c0673034e606a7cceec07b4c705e87',
Expand All @@ -51,7 +51,7 @@ const EXPECTED_FUNCTION_HASHES: Record<string, string> = {
getOpsxFfCommandTemplate: 'b859b1955cda6012877ae7f9ec6980e468f2e949a3838dfcdebc17209d133749',
getArchiveChangeSkillTemplate: 'a8f1d9cb06c20c7335ac35826dd09bfadead75ef6d624d359912734f74232cbc',
getBulkArchiveChangeSkillTemplate: 'f675122bce3ef583b245352abedecf50ff4043e45bea6bac091885f83c7b6362',
getOpsxSyncCommandTemplate: '98b20e00da5c588ff83ed6e6f0e959dfc540349090fb3f5792ea030d099b8169',
getOpsxSyncCommandTemplate: '68dc44c9be2ec1ef719a4ed59830e5a0bc74c3ba6113070650266e1b0d153071',
getVerifyChangeSkillTemplate: 'cab4db01b5d2b1243d63d90c53747d8b39e488c60f76eba3fe8b994467f69267',
getOpsxArchiveCommandTemplate: '9d14e1ea23ae8be8971fafa1d6a4d4717a8a7b922b6e76c6fb07aa568a420632',
getOpsxOnboardCommandTemplate: '0673f34a0f81fd173bcfb8c3ac83e2b1c617f7b7564e24e5298d3bd5665a05a9',
Expand All @@ -70,7 +70,7 @@ const EXPECTED_GENERATED_SKILL_CONTENT_HASHES: Record<string, string> = {
'openspec-continue-change': 'bdb8bbb6a768a741b05256effbc284d65ac6a45360b59c24b94198792d3d0ebf',
'openspec-apply-change': '09c0e1cdf5ccc82416d0969d6bd715cc70616bdbc3531358a5c36057f78be55a',
'openspec-ff-change': '0c82830cd9bc98f86eb56b63ddaabe2bf5d35fe25b6c40a7059311aee2c8acac',
'openspec-sync-specs': 'b3f694ab81956d05126b089fe82dea78dec21788978bb9651485f996aee96740',
'openspec-sync-specs': 'd1bcd420bf8fb55a13f58a2857e6ebde58eb6f9e721a3bf6876bd9f640a63859',
'openspec-archive-change': '4679a077d34016bf38f0d0aa5432b53ea83ae82c2c5fec6dcb7dc15571ee8ac6',
'openspec-bulk-archive-change': '545b9528df52fbb0b4898405b42a2ce10416678d469d20cf597d022fa6e16e3b',
'openspec-verify-change': '57693d22940f06080c6cf8d590ac2f48240d4a5e9ce7074dacd0f8d3c9945afa',
Expand Down
Loading