Skip to content

[Bug] /opsx:verify reports REMOVED requirements as missing and recommends re-implementing them #1959

Description

@madd0g72

Summary

The generated /opsx:verify command and the openspec-verify-change skill do not look at which delta operation a requirement comes from. Every ### Requirement: heading in the change's delta specs is treated as behaviour that must exist in the codebase, including the ones under ## REMOVED Requirements. As a result, a removal that was implemented correctly is reported as CRITICAL, and the report recommends re-implementing the removed behaviour.

Version

@fission-ai/openspec 1.13.1, Claude Code delivery (skills + commands), spec-driven schema.

Where

In .claude/commands/opsx/verify.md and the mirrored .claude/skills/openspec-verify-change/SKILL.md:

  • Step 5, Spec Coverage: "Extract all requirements (marked with "### Requirement:")" → "Search codebase for keywords related to the requirement" → if not found: CRITICAL "Requirement not found: ", recommendation "Implement requirement X".
  • Step 6, Requirement Implementation Mapping / Scenario Coverage: the same loop over every requirement and scenario in the delta specs, with no operation filter.

The verify text never mentions ADDED / MODIFIED / REMOVED / RENAMED.

Repro

  1. Create a change whose delta spec contains only a REMOVED requirement:
    ## REMOVED Requirements
    ### Requirement: Legacy CSV export
    **Reason**: superseded by the JSON export
    **Migration**: use the JSON export
  2. Implement it by deleting the CSV export code, and tick the task.
  3. Run /opsx:verify <change>.

Expected: the requirement is verified as absent. It passes when no implementation remains, and it is flagged when the behaviour is still present.
Actual: CRITICAL: Requirement not found: Legacy CSV export, with the recommendation "Implement requirement …". An agent that follows the report restores the behaviour the change just removed.

Suggested fix

Classify each requirement by the section it appears under before running the checks:

  • ADDED / MODIFIED: the current checks. For MODIFIED, check against the modified text.
  • REMOVED: invert the check. It passes when no implementation evidence remains. It is a CRITICAL only if the behaviour is still there. Scenario-coverage checks are skipped, because a removed requirement usually carries Reason/Migration and no scenarios.
  • RENAMED: check the new name. The old name being absent is expected.

/opsx:archive and /opsx:sync already handle each operation separately, so verify is the only step in the loop that doesn't.

Activity

  1. ryandemelo commented on Sep 23, 2026

    @ryandemelo
    Contributor

    I'd like to take this one.

    Your suggested fix reads right to me, so the plan is to follow it: sort each requirement by the section it sits under before any check runs. ADDED and MODIFIED keep today's checks. REMOVED gets the inverse, so it passes once the behaviour is gone and is only critical while it is still there. RENAMED is checked under its new name. I'll open a PR shortly.

  2. added a commit that references this issue on Sep 23, 2026
    3364146
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions