os-backlog: heading parser treats # lines inside code fences as headings #650

Closed
opened 2026-09-23 18:21:40 +00:00 by jared · 1 comment
Owner

heading parsers do not skip fenced code, so # lines inside a block become false sections

Problem

Neither plugins/os-backlog/lib/backlog/issue_body/lines.rb (find_heading_matches) nor plugins/os-sdlc/lib/os_sdlc/pipeline/ticket_shape/section.rb (bodies_for) tracks fence state. A #-prefixed line inside a fenced code block (seen in #629 and #626 bodies) is read as a section heading, creating false or duplicate sections. #563 FenceMask shipped for os-aidd-lint only (plugins/os-aidd-lint/lib/aidd_lint/fence_mask.rb); the backlog and os-sdlc parsers were not covered.

Cases

  1. Given a body with a fenced block containing a # comment line, when either parser scans for headings, then that line is not counted as a heading.
  2. Given the same body with the fenced line removed, when either parser scans for headings, then it reports the same sections as case 1.

Approach

Add fence-state skipping to each parser directly. Cross-plugin sharing of FenceMask is a #699-class decision; a small local fence tracker in each parser is acceptable here.

Required work:

  1. Add fence-state skipping to Lines#find_heading_matches in plugins/os-backlog/lib/backlog/issue_body/lines.rb
  2. Add the same fence-state skipping to TicketShape::Section#bodies_for in plugins/os-sdlc/lib/os_sdlc/pipeline/ticket_shape/section.rb
  3. Extend plugins/os-sdlc/tests/model/ticket_shape_parity_test.rb and add an os-backlog IssueBody test with a fenced # not a heading case

Acceptance criteria

  1. Given a body with a fenced block containing # comment, when both parsers read it, then they report the same sections as for the body without that line.

Non-goals

Sharing one FenceMask implementation across plugins is out of scope; that is #699's decision.

Origin

  • Trigger: #643 merge verification, 2026-09-23
  • Chain: parser defect ← DESIGN (ADR-0190, ADR-0209)
  • Where: plugins/os-backlog/lib/backlog/issue_body/lines.rb, plugins/os-sdlc/lib/os_sdlc/pipeline/ticket_shape/section.rb
  • Session: 073fd763-259f-4218-95e6-e8449caae354
# heading parsers do not skip fenced code, so `#` lines inside a block become false sections ## Problem Neither plugins/os-backlog/lib/backlog/issue_body/lines.rb (`find_heading_matches`) nor plugins/os-sdlc/lib/os_sdlc/pipeline/ticket_shape/section.rb (`bodies_for`) tracks fence state. A `#`-prefixed line inside a fenced code block (seen in #629 and #626 bodies) is read as a section heading, creating false or duplicate sections. #563 FenceMask shipped for os-aidd-lint only (plugins/os-aidd-lint/lib/aidd_lint/fence_mask.rb); the backlog and os-sdlc parsers were not covered. ## Cases 1. Given a body with a fenced block containing a `# comment` line, when either parser scans for headings, then that line is not counted as a heading. 2. Given the same body with the fenced line removed, when either parser scans for headings, then it reports the same sections as case 1. ## Approach Add fence-state skipping to each parser directly. Cross-plugin sharing of FenceMask is a #699-class decision; a small local fence tracker in each parser is acceptable here. Required work: 1. Add fence-state skipping to `Lines#find_heading_matches` in plugins/os-backlog/lib/backlog/issue_body/lines.rb 2. Add the same fence-state skipping to `TicketShape::Section#bodies_for` in plugins/os-sdlc/lib/os_sdlc/pipeline/ticket_shape/section.rb 3. Extend plugins/os-sdlc/tests/model/ticket_shape_parity_test.rb and add an os-backlog IssueBody test with a fenced `# not a heading` case ## Acceptance criteria 1. Given a body with a fenced block containing `# comment`, when both parsers read it, then they report the same sections as for the body without that line. ## Non-goals Sharing one FenceMask implementation across plugins is out of scope; that is #699's decision. ## Origin - Trigger: #643 merge verification, 2026-09-23 - Chain: parser defect ← DESIGN (ADR-0190, ADR-0209) - Where: plugins/os-backlog/lib/backlog/issue_body/lines.rb, plugins/os-sdlc/lib/os_sdlc/pipeline/ticket_shape/section.rb - Session: 073fd763-259f-4218-95e6-e8449caae354
Author
Owner

Resolution

Done: both heading parsers skip lines inside code fences via a FenceStack per plugin; parity test and IssueBody test cover a fenced heading line

Evidence: commit cfdfcc30; os-backlog 245 runs 0 failures, os-sdlc 1427 runs 0 failures

Follow-ups: #699 decides whether one shared FenceMask replaces the two local FenceStack copies (open)

## Resolution **Done:** both heading parsers skip lines inside code fences via a FenceStack per plugin; parity test and IssueBody test cover a fenced heading line **Evidence:** commit cfdfcc30; os-backlog 245 runs 0 failures, os-sdlc 1427 runs 0 failures **Follow-ups:** #699 decides whether one shared FenceMask replaces the two local FenceStack copies (open)
jared closed this issue 2026-09-24 20:34:26 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jared/cc-os#650
No description provided.