Skip to content

### Requirement: inside a fenced code block is parsed as a real requirement #1348

Description

@HerbertGao

Summary

extractRequirementsSection (src/core/parsers/requirement-blocks.ts) splits the ## Requirements section into blocks by scanning line-by-line for ### Requirement: headers (REQUIREMENT_HEADER_PREFIX). The scan is not fence-aware: a ### Requirement: line inside a fenced code block (a documentation example) is treated as a real requirement header. This cuts the block mid-fence, promotes the fenced example into a phantom requirement, and emits a dangling ``` in any rebuilt output (e.g. on archive).

Language-agnostic — reproduces with English-only specs.

Reproduction

A ## Requirements section whose body contains a fenced example that itself shows a ### Requirement: line:

## Requirements

### Requirement: Real
The system SHALL do the real thing.

Example of how to author a requirement:

```markdown
### Requirement: Example
The system SHALL be an example only.
```

#### Scenario: ok
- **WHEN** x
- **THEN** y

Parsing yields two requirements (Real and the fenced Example) instead of one, and the code fence is broken across the split. On archive, the rebuilt spec contains a phantom ### Requirement: Example and an unbalanced fence.

Expected

A ### Requirement: inside a fenced code block is documentation, not a requirement, and should be ignored by the block splitter — exactly as #### Scenario: inside a fence is handled by the scenario parser.

Root cause

Both the preamble scan and the per-block boundary scan test REQUIREMENT_HEADER_PREFIX with no fence mask:

// preamble
while (cursor < body.length && !REQUIREMENT_HEADER_PREFIX.test(body[cursor])) { ... }
// per-block boundary
while (cursor < body.length && !REQUIREMENT_HEADER_PREFIX.test(body[cursor]) && !/^##\s+/.test(body[cursor])) { ... }

Suggested fix

Build a code-fence mask over the section body once (the codebase already has a buildCodeFenceMask helper used by the scenario parser) and gate the header test on !fenceMask[i], mirroring the fence-aware handling already applied to #### Scenario: parsing.


Found while hardening a downstream fork; reproduces on upstream with English-only specs, so filing here rather than carrying a fork-local patch.

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