Skip to content

Delta specs should be transformed when merging to not include "evolutionary" language #678

@marvingreenberg

Description

@marvingreenberg

Title: Should spec sync strip change-oriented language from main specs?


During a recent change cycle (ux-refactor-simulate-tab), we noticed that
delta specs naturally use change-oriented language that makes sense in
context — things like:

- AND no separate Monte Carlo tab exists
- THEN the API receives the same Portfolio JSON structure as before
- AND no backend API changes are required

This reads fine in the delta spec (in changes/), where the purpose is to
describe what changed. But when these deltas get synced to main specs
(via /opsx:sync or /opsx:archive), that language ends up in the
permanent spec, where it reads oddly. A main spec is supposed to describe
the current system — "what IS" — and saying "no Monte Carlo tab exists"
is a strange thing to assert as a permanent requirement. Taken to its
logical conclusion, main specs would accumulate lots of negations about
things that used to exist.

After the sync, we manually rewrote the affected scenarios:

Before (change language):
- THEN the tab navigation shows "Portfolio", "Simulate", and "Compare"
- AND no "Monte Carlo" tab exists

After (describes what IS):
- THEN the tab navigation shows exactly 3 tabs: "Portfolio", "Simulate", and "Compare"

Before:
- THEN the API receives the same Portfolio JSON structure as before
- AND no backend API changes are required

After:
- THEN the API receives a single Portfolio JSON containing both
  portfolio data and simulation assumptions

The archived delta specs still preserve the evolutionary context for
anyone who wants to understand what changed and why.


Possible approaches:

  1. Add guidance to the /opsx:sync and /opsx:archive skill prompts

    The sync/archive logic is where deltas get merged into main specs.
    Adding a step like "rewrite content to describe current system state,
    strip change-oriented language" would catch this at the right point
    in the workflow. This seems like the most natural fit since:

    • Delta spec authors SHOULD use change language (that's the point of
      ADDED/MODIFIED/REMOVED headers)
    • The transformation should happen at sync time, not authoring time
    • It's a universal principle, not project-specific
  2. Add guidance to the specs artifact instruction template

    The instruction field for the specs artifact could mention that
    scenario content should be written to stand on its own, even in
    delta specs. But this conflicts with the delta format — MODIFIED
    specs inherently reference what changed.

  3. Per-project rules in config.yaml

    Projects can add a rule like:
    rules:
    specs:
    - Main specs describe what IS, not what changed. Strip
    evolutionary language during sync.

    This works but puts the burden on each project to discover and
    configure this. It also lands in the spec authoring instructions,
    not the sync step where it matters.

Approach 1 seems like the best fit — it's where the transformation
naturally belongs, and it would benefit all openspec users without
requiring per-project configuration.

attribution - Claude Opus 4.5, in openspec --version 1.1.1

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