clone

a hermes agent plugin for openspec: tools for spec workflows and a dashboard tab for browsing changes and specs

main
hermes-openspec / openspec / changes / archive / semantic-spec-diff-tool / specs / semantic-spec-diff / spec.md
spec.md 5.1K rendered
1# Semantic Spec Diff Delta23## ADDED Requirements45### Requirement: Shared spec parser6The plugin SHALL provide a `_parse_spec(md)` Python function that parses OpenSpec spec markdown into structured data: title, purpose, and a list of requirements, each with a name, description, and list of scenarios, each scenario with a name and steps.78#### Scenario: Parse a well-formed spec9- **GIVEN** a spec markdown file with `# Title`, `## Purpose`, `### Requirement:` headers, and `#### Scenario:` headers with `**GIVEN**`/`**WHEN**`/`**THEN**` steps10- **WHEN** `_parse_spec` is called with the markdown content11- **THEN** it returns a dict with `title`, `purpose`, and `requirements` list, where each requirement has `name`, `description`, and `scenarios`, and each scenario has `name` and `steps`1213#### Scenario: Parse a spec with no requirements14- **GIVEN** a spec markdown file with only a title and purpose, no `### Requirement:` headers15- **WHEN** `_parse_spec` is called with the markdown content16- **THEN** it returns a dict with `title`, `purpose`, and an empty `requirements` list1718#### Scenario: Parse empty or None input19- **WHEN** `_parse_spec` is called with an empty string or None20- **THEN** it returns a dict with empty `title`, empty `purpose`, and empty `requirements` list2122### Requirement: Semantic spec diff function23The plugin SHALL provide a `_semantic_spec_diff(before_md, after_md)` function that compares two parsed specs and returns a structured delta at the requirement and scenario level.2425#### Scenario: Added requirement26- **GIVEN** the after spec contains a requirement that the before spec does not27- **WHEN** `_semantic_spec_diff` is called28- **THEN** the requirement appears in `requirements.added` with its full description and scenarios2930#### Scenario: Removed requirement31- **GIVEN** the before spec contains a requirement that the after spec does not32- **WHEN** `_semantic_spec_diff` is called33- **THEN** the requirement appears in `requirements.removed` with its full description and scenarios3435#### Scenario: Modified requirement description36- **GIVEN** a requirement exists in both specs with the same name but different descriptions37- **WHEN** `_semantic_spec_diff` is called38- **THEN** the requirement appears in `requirements.modified` with `before` and `after` description fields3940#### Scenario: Scenario-level delta in modified requirement41- **GIVEN** a requirement exists in both specs with the same name but different scenarios42- **WHEN** `_semantic_spec_diff` is called43- **THEN** the modified entry includes `scenarios_added`, `scenarios_modified`, and `scenarios_removed` lists4445#### Scenario: Unchanged requirement46- **GIVEN** a requirement exists in both specs with identical descriptions and scenarios47- **WHEN** `_semantic_spec_diff` is called48- **THEN** the requirement name appears in `requirements.unchanged`4950#### Scenario: No baseline exists51- **GIVEN** the before spec is None or empty (new spec being added)52- **WHEN** `_semantic_spec_diff` is called53- **THEN** all requirements appear in `requirements.added` and the overall status is `added`5455### Requirement: openspec_spec_diff agent tool56The plugin SHALL provide an `openspec_spec_diff` tool that compares a change's delta spec against its baseline, or a worktree spec against its HEAD version, and returns the structured semantic delta plus a unified line diff fallback.5758#### Scenario: Diff a change spec against baseline59- **GIVEN** a change contains a delta spec under `openspec/changes/<change>/specs/<spec>/spec.md` and a baseline spec exists at `openspec/specs/<spec>/spec.md`60- **WHEN** an agent calls `openspec_spec_diff` with `workdir`, `spec`, and `change`61- **THEN** the tool returns the semantic delta between the change spec and the baseline spec, including overall status, requirements delta, and a `line_diff` unified diff field6263#### Scenario: Diff a worktree spec against HEAD64- **GIVEN** a baseline spec exists at `openspec/specs/<spec>/spec.md` and has been modified in the worktree65- **WHEN** an agent calls `openspec_spec_diff` with `workdir` and `spec` (no `change`)66- **THEN** the tool returns the semantic delta between the HEAD version (via git) and the worktree version6768#### Scenario: New spec with no baseline69- **GIVEN** a change contains a delta spec but no baseline spec exists70- **WHEN** an agent calls `openspec_spec_diff` with `workdir`, `spec`, and `change`71- **THEN** the tool returns status `added` with all requirements in `requirements.added` and an empty `line_diff`7273#### Scenario: Missing change spec74- **WHEN** an agent calls `openspec_spec_diff` with a `change` that does not contain the requested `spec`75- **THEN** the tool returns `ok: false` with an error explaining the change spec was not found7677#### Scenario: Filesystem-backed availability78- **GIVEN** no OpenSpec CLI binary is available79- **WHEN** Hermes registers plugin tools80- **THEN** `openspec_spec_diff` is still available because it reads spec files directly from the filesystem8182#### Scenario: Git unavailable for HEAD comparison83- **GIVEN** `openspec_spec_diff` is called without `change` (HEAD comparison mode) and git is unavailable84- **THEN** the tool returns `ok: false` with an error explaining git is required for worktree-vs-HEAD comparison