fix(parser): refuse malformed RENAMED pairs - #1806
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. 📝 WalkthroughWalkthroughThe parser now records unpaired ChangesRENAMED Pair Integrity
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to Malformed RENAMED pairs are rejected rather than guessed, while valid rename syntax remains supported. No unresolved merge-readiness risk is identified. Sequence Diagram(s)sequenceDiagram
participant DeltaSpec
participant parseDeltaSpec
participant buildUpdatedSpec
participant validateChangeDeltaSpecs
DeltaSpec->>parseDeltaSpec: provide RENAMED entries
parseDeltaSpec-->>buildUpdatedSpec: unpairedRenames
buildUpdatedSpec-->>DeltaSpec: reject malformed rename
parseDeltaSpec-->>validateChangeDeltaSpecs: unpairedRenames
validateChangeDeltaSpecs-->>DeltaSpec: report missing counterpart
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
alfred-openspec
left a comment
There was a problem hiding this comment.
Reviewed rename pairing, validation, and archive refusal behavior and ran the focused 15-test suite locally. Malformed pairs now fail safely while valid consecutive pairs remain unchanged. Approved.
Closes #1805.
Why
parseRenamedPairswalked## RENAMED Requirementscarrying a single mutable{ from, to }and dropped whatever did not fit:FROM:overwrote an unpaired first oneTO:with no pendingFROM:was discardedFROM:was forgotten when the section endedNothing recorded any of it, and
validateChangeDeltaSpecsonly ever iteratesplan.renamed— the pairs that did form — so the validator structurally couldnot see the dropped lines. Two outcomes, both silent:
TO:written before itsFROM:yieldsno pair at all;
validatereports the change valid andarchiveexits 0having renamed nothing.
write a batch rename, listing the old names then the new ones — the second
FROMpairs with the firstTO. Archive renames a requirement the deltanever named, under a name the author wrote for a different one, and reports
→ 1as though exactly one intended rename occurred.Verified against a project built entirely by
openspec init+openspec new change: the body under the renamed header was the other requirement's body.What Changes
FROM:followed by aTO:with no secondFROM:betweenthem — the shape the documented format uses.
FROM:/TO:line that never formed a pair is recorded in a newDeltaPlan.unpairedRenamesentry (side,name, 1-basedline).validate <change>reports each one as an ERROR with its line number, sothe author learns at authoring time.
buildUpdatedSpecthrows on any unpaired entry, soarchiverefuses ratherthan applying a pairing it guessed. This is deliberate: with interleaved lines
the guessed pairing rewrites the wrong requirement, and a spec rewrite is not
something to do on a guess.
Well-formed renames are unaffected, including several consecutive pairs and the
no-bullet form.
Testing
test/core/parsers/renamed-pair-integrity.test.ts— 15 tests, written first andwatched fail (13 failed / 2 passed before, 15 passed after).
Edge cases covered:
TO:beforeFROM:; aFROM:displaced by anotherFROM:; a trailingFROM:; fully interleaved FROM/FROM/TO/TOboth report nothing
buildUpdatedSpecstill applies a well-formed rename, and throws with theoffending line number for each malformed shape
validatereports the ERROR, and leaves a well-formed rename cleanFull suite green on this branch.
Changeset
Not added. Per
.changeset/README.mdthe default path is the normal releasecadence. Worth noting for release notes if one is added: this turns a previously
silent mis-apply into a hard error, so a change carrying a malformed RENAMED
section that used to archive will now be rejected until the pairing is fixed.
Summary by CodeRabbit
FROM:orTO:entry and the required consecutive format.