Skip to content

fix: make requirement header parsing case-insensitive#1031

Merged
TabishB merged 3 commits into
Fission-AI:mainfrom
davseby:main
May 1, 2026
Merged

fix: make requirement header parsing case-insensitive#1031
TabishB merged 3 commits into
Fission-AI:mainfrom
davseby:main

Conversation

@davseby

@davseby davseby commented May 1, 2026

Copy link
Copy Markdown
Contributor

Problem

REQUIREMENT_HEADER_REGEX and the inline seek/skip regexes use case-sensitive matching for ### Requirement:, while the ## Requirements section header is found case-insensitively (/i).

A user who writes ### requirement: Foo gets a confusing validation error during archive — "no requirement entries parsed" — with no indication that header casing is the cause.

Fix

Add the i flag to REQUIREMENT_HEADER_REGEX and all four inline regexes in requirement-blocks.ts that seek or skip ### Requirement: headers.

@davseby davseby requested a review from TabishB as a code owner May 1, 2026 09:36
@coderabbitai

coderabbitai Bot commented May 1, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Requirement header detection was made case-insensitive across parsing and validation paths, so ### Requirement: headers are matched regardless of letter casing or minor spacing variations, affecting where requirement preambles and individual requirement blocks are identified.

Changes

Cohort / File(s) Summary
Parsers: requirement block logic
src/core/parsers/requirement-blocks.ts
Made REQUIREMENT_HEADER_REGEX case-insensitive and replaced case-sensitive ^###\s+Requirement: checks with REQUIREMENT_HEADER_REGEX.test(...) in extractRequirementsSection and parseRequirementBlocksFromSection, changing block segmentation and header recognition.
Spec structure checks
src/core/parsers/spec-structure.ts
Updated the REQUIREMENT_HEADER regex in findMainSpecStructureIssues to be case-insensitive so requirement headers are detected regardless of casing.
Spec apply validation
src/core/specs-apply.ts
Adjusted MODIFIED spec validation to accept case-insensitive ### Requirement: header on the first line of mod.raw while still enforcing normalized requirement-name equality with key.
Tests
test/core/parsers/requirement-blocks.test.ts
Added tests for extractRequirementsSection and parseDeltaSpec covering canonical, mixed-case, and no-space ###Requirement: header variants and multiple-block extraction scenarios.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • TabishB
  • alfred-openspec

Poem

🐰 I hopped through specs both big and small,
Now headers answer when I call,
Upper, lower, space or none—hooray!
Requirement blocks greet me any day,
A joyful nibble, parse away! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: making requirement header parsing case-insensitive across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/core/parsers/requirement-blocks.ts`:
- Line 61: The loop boundary uses a stricter hardcoded regex
/^###\s+Requirement:/ (in the cursor/sectionBodyLines loops) which mismatches
the shared header regex /^###\s*Requirement:/ used elsewhere; update those loop
conditions to reuse the single shared predicate/regex (the existing shared
requirement header check used elsewhere in this module) instead of the hardcoded
pattern so headers like "###Requirement:" are treated consistently—replace the
inline /^###\s+Requirement:/ checks in the cursor loops with the shared
isRequirementHeader/isRequirementRegex symbol (or the canonical
/^###\s*Requirement:/) so all occurrences use the same predicate.
- Line 19: The REQUIREMENT_HEADER_REGEX in this file is currently
case-insensitive which permits headers like "### requirement:" but downstream
validators (specs-apply.ts and spec-structure.ts) expect case-sensitive headers
and thus fail; update REQUIREMENT_HEADER_REGEX to be case-sensitive (remove the
'i' flag) so it only matches the exact "Requirement" casing and stays consistent
with the header regexes used by validate/parse functions in spec-structure.ts
and specs-apply.ts, or alternatively make those other header regexes
case-insensitive to match this one—pick one consistent approach and apply it
across REQUIREMENT_HEADER_REGEX and the corresponding header regexes in
spec-structure.ts/specs-apply.ts so parsing and validation use the same casing
rules.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bae62526-8e2d-4594-bb3b-e197b04c2dd1

📥 Commits

Reviewing files that changed from the base of the PR and between 347f027 and 3c8d6e6.

📒 Files selected for processing (1)
  • src/core/parsers/requirement-blocks.ts

Comment thread src/core/parsers/requirement-blocks.ts
Comment thread src/core/parsers/requirement-blocks.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/core/parsers/requirement-blocks.ts (1)

19-45: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the requirement header grammar aligned across the parser.

This regex now accepts ###Requirement: as well as mixed-case headers, but the rest of the requirement parsing/validation path still expects the spaced form. That means this file can accept blocks that downstream code will still reject, and the new no-space regression cases lock in that wider contract.

Suggested fix
-const REQUIREMENT_HEADER_REGEX = /^###\s*Requirement:\s*(.+)\s*$/i;
+const REQUIREMENT_HEADER_REGEX = /^###\s+Requirement:\s*(.+)\s*$/i;

If you do want to support ###Requirement:, the remaining requirement regexes need the same treatment too.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/core/parsers/requirement-blocks.ts` around lines 19 - 45, The
REQUIREMENT_HEADER_REGEX was loosened to accept headers like "###Requirement:"
(no space) which misaligns with downstream parsing; restore strict grammar by
changing REQUIREMENT_HEADER_REGEX in extractRequirementsSection to require a
space after '###' (e.g. use a pattern requiring \s+ after '###') or, if you
intentionally want to accept the no-space form, update all other
requirement-related regexes/parsers in this module to match the same relaxed
grammar so parsing/validation remain consistent (update any other requirement
header/validation regexes to the same pattern).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/core/parsers/requirement-blocks.ts`:
- Around line 19-45: The REQUIREMENT_HEADER_REGEX was loosened to accept headers
like "###Requirement:" (no space) which misaligns with downstream parsing;
restore strict grammar by changing REQUIREMENT_HEADER_REGEX in
extractRequirementsSection to require a space after '###' (e.g. use a pattern
requiring \s+ after '###') or, if you intentionally want to accept the no-space
form, update all other requirement-related regexes/parsers in this module to
match the same relaxed grammar so parsing/validation remain consistent (update
any other requirement header/validation regexes to the same pattern).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f7223acd-2757-4d84-be90-f6636917ab7d

📥 Commits

Reviewing files that changed from the base of the PR and between 3c8d6e6 and d620bea.

📒 Files selected for processing (4)
  • src/core/parsers/requirement-blocks.ts
  • src/core/parsers/spec-structure.ts
  • src/core/specs-apply.ts
  • test/core/parsers/requirement-blocks.test.ts
✅ Files skipped from review due to trivial changes (2)
  • src/core/specs-apply.ts
  • src/core/parsers/spec-structure.ts

@TabishB

TabishB commented May 1, 2026

Copy link
Copy Markdown
Contributor

@davseby We've moved away from header-based archiving. What version are you on?

@davseby

davseby commented May 1, 2026

Copy link
Copy Markdown
Contributor Author

@TabishB I tried it with 1.3.1 and with the latest main commit.

Error that I receive using archive:

Validation errors in change delta specs:
  ✗ Delta sections ## MODIFIED Requirements were found, but no requirement entries parsed. Ensure each section includes at least one "### Requirement:" block (REMOVED may use bullet list syntax).
  ✗ Change must have at least one delta. No deltas found. Ensure your change has a specs/ directory with capability folders (e.g. specs/http-server/spec.md) containing .md files that use delta headers (## ADDED/MODIFIED/REMOVED/RENAMED Requirements) and that each requirement includes at least one "#### Scenario:" block. Tip: run "openspec change show <change-id> --json --deltas-only" to inspect parsed delta

Example spec.md:

## MODIFIED Requirements

### requirement: Lowercase Header
The system SHALL do something updated.

#### Scenario: Basic usage
- **WHEN** the user does X
- **THEN** the system does Y updated

@davseby

davseby commented May 1, 2026

Copy link
Copy Markdown
Contributor Author

I updated the description to better reflect the issue 🙏🏿

@TabishB TabishB added this pull request to the merge queue May 1, 2026
Merged via the queue into Fission-AI:main with commit 2d189ce May 1, 2026
9 checks passed
kaze-droid pushed a commit to kaze-droid/OpenSpec that referenced this pull request May 10, 2026
* fix: make requirement header parsing case-insensitive

* fix: add tests and cover the rest of requirement header places
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants