---
name: merge-change
description: Merge change artifacts into product documentation with lifecycle tracking. Use when specs are ratified and ready to merge.
---

# merge-change

Apply completed change artifacts into existing product-level documentation.

## When to Use

When `specs-status` is `ratified` or `merging`, merge the change's artifacts (functional.md, requirements, technical.md, infra.md, integration.feature.md) into the product's living documentation. The PreToolUse hook validates this state; the PostToolUse hook auto-transitions `ratified → merging` on invocation.

## Inputs

**Input**: `$0` is the change name. If empty, check conversation context.

- **Change path**: Derived as `openspec/changes/<change-name>/`
- **Product path**: Read from `.openspec.yaml` `product` field — a bare directory name resolved under `openspec/` (set during `new-change`)

If not provided, detect from context:
- Change path: most recently ratified or in-progress change
- Product path: fall back to directory matching the product name under `openspec/`

## Step 0: Validate state and resolve product

Read `specs-status` and verify it is `ratified` or `merging` (redundant with hook gate, but serves as instruction-level safety):

```bash
current=$("${CLAUDE_PLUGIN_ROOT}/scripts/change_status.sh" read "openspec/changes/$0" specs-status)
```

If not `ratified` or `merging`, inform the user what state the change is in and what needs to happen first. The PostToolUse hook auto-transitions `ratified → merging` on skill invocation, so by the time this runs, status will be `merging`.

Read the product path from `.openspec.yaml`:

```bash
product=$("${CLAUDE_PLUGIN_ROOT}/scripts/change_status.sh" read "openspec/changes/$0" product)
```

If empty, fall back to context detection (scan `openspec/` for a directory matching the change context). If ambiguous, ask the user. Use the resolved product path throughout the merge process.

## Process

1. Read change artifacts to determine which files have substantive content
2. Dispatch one Sonnet subagent per artifact type that has changes (use Task tool with `model: "sonnet"`)
3. Each subagent reads: change artifact + existing product artifact + merge rules below
4. Each subagent writes: updated product artifact
5. Present summary of all changes to user for review

### Subagent Dispatch Pattern

```
Task tool (sonnet):
  description: "Merge <artifact-type> into product"
  prompt: |
    Read the change artifact at <change-path>/<file>
    Read the existing product artifact at <product-path>/<file>
    Apply the merge rules below, then write the updated file.

    CRITICAL: When transferring names, identifiers, slugs, tags, or code references
    from source artifacts, copy them exactly. Never reconstruct from memory.

    [artifact-specific merge rules from below]
```

Dispatch all subagents in parallel — they operate on independent files.

If merge rules require user triage (e.g., Out of Scope items), the orchestrating agent must complete triage BEFORE dispatching the affected subagent. Ask each triage item individually — never batch multiple items into one question.

## Merge Rules by Artifact Type

### functional.md

Read the change's functional.md and the product's functional.md.

- **Capabilities**: New capabilities from the change → append to product Capabilities list
- **Scope**: Change scope additions → append to product Scope section
- **Out of Scope**: (individual question per item) Triage each item with the user; NEVER ASK MULTIPLE OUT-OF-SCOPE ITEMS IN ONE QUESTION:
  - Permanent boundary → add to product Out of Scope
  - Temporary gap → add to product Current Limitations
  - Future intent → add to product Planned Future Work
- **Known Risks**: Change risks → append to product Known Risks. Remove risks that the change resolved.
- **Overview**: Integrate change "What Changes" content into product Overview. The product Overview describes the full system, not just the latest change.
- **Current Limitations**: Review change for resolved limitations → remove from product Current Limitations

### requirements (per capability file)

Read the change's `requirements/<slug>/requirements.feature.md` and the product's equivalent.

- **ADDED rules/scenarios**: Append to product's `## Requirements` section under the matching Feature
- **MODIFIED rules/scenarios**: Replace the matching `@slug:Y` or `@slug:Y.Z` block in the product file with the updated version from the change
- **REMOVED rules**: Delete the matching `@slug:Y` block from the product file
- **RENAMED rules**: Update `@slug` tags throughout the product file

If the change adds a new capability (new file), create the product file from the template and populate with the ADDED content.

Strip delta headers (ADDED/MODIFIED/REMOVED/RENAMED) — product files use flat `## Requirements` structure.

### technical.md

Read the change's technical.md and the product's technical.md.

- **Context**: Merge relevant context additions. Remove outdated context.
- **Objectives**: Change objectives may not be product objectives. Only add if they represent permanent system goals. Most change objectives are transient.
- **Architecture diagrams**: Update to reflect the new system state. Diagrams should show current architecture, not change diffs.
- **Components**: New components → append. Modified components → update in place.
- **Interfaces**: New interfaces → append. Modified interfaces → update in place.
- **Decisions**: Append new decisions with `[change-slug]` provenance tag. Do not modify existing decisions — they are historical records.
- **Risks**: Append new risks. Remove risks that the change mitigated.

### infra.md

Read the change's infra.md and the product's infra.md.

- **Deployment**: Merge deployment changes into product Deployment section. Update environment configs, rollout strategy to reflect current state.
- **Testing Strategy**: Add new test patterns and coverage mappings. Update the requirements coverage table with new `@slug:Y.Z` entries.
- **Observability**: Append new logging, metrics, and alert definitions.
- **Migration**: Do NOT merge migration content — it's change-specific, not product-level.

### integration.feature.md

Read the change's integration.feature.md and the product's equivalent.

Apply same rules as requirements:
- **ADDED scenarios**: Append to product's `## Integration Scenarios` section
- **MODIFIED scenarios**: Replace matching `@integration:Y.Z` block
- **REMOVED scenarios**: Delete matching block

Strip delta headers. Product file uses flat `## Integration Scenarios` structure.

## Edge Cases

### First merge into empty product

If the product directory doesn't exist or a specific artifact file is missing:
1. Create from the product schema template (greenfield or brownfield)
2. Then apply the change content as if merging into an empty document
3. The subagent receives: template + change artifact

### Change modifies unknown capability

If a change modifies a capability not present in product docs:
- Flag to user: "Change modifies `<slug>` which doesn't exist in product docs"
- Ask: create it from the change content, or skip?

### Change removes a capability

If a change removes a capability entirely:
- Confirm with user before removing from all product docs
- Remove: capability from functional.md, requirements file, component/interface references in technical.md, coverage mappings in infra.md

### Conflicting content

If the change contradicts existing product docs (e.g., a decision that conflicts with an existing one):
- Flag the conflict to the user
- Present both versions
- Let the user decide which to keep

## Verification

After all subagents complete:
1. Confirm all dispatched subagents wrote their files
2. Read back every updated product artifact (read all files in parallel in one message)
3. Cross-check each updated artifact against the original change artifact:
   - Verify names, identifiers, slugs, and tags were transcribed exactly (not paraphrased or substituted)
   - Verify no content from the change was dropped or truncated
   - Verify no content from the existing product artifact was accidentally removed
   - Verify delta headers (ADDED/MODIFIED/REMOVED/RENAMED) were stripped where required
4. If any discrepancy is found, fix the file directly — do not re-dispatch a subagent
5. Present a summary: which files were updated, key changes per file, any corrections made in step 4
6. Ask user to review before considering the merge complete

## Completion

After the user approves the merge, write the terminal status:

```bash
"${CLAUDE_PLUGIN_ROOT}/scripts/change_status.sh" write "openspec/changes/$0" specs-status merged
```

Report the new state and suggest next steps based on `code-status`:
- If `code-status: implemented` or `n/a` → both tracks terminal, suggest `Skill(tokamak:archive-change, args: "$0")`
- If `code-status: ready` or `in-progress` → suggest `Skill(tokamak:implement-change, args: "$0")` to complete implementation first
