Skip to content

bug(tracker-tools): extractSection uses 'mi' flags causing $ to truncate section content to one line #6

@ElliotDrel

Description

@ElliotDrel

Bug

In bin/tracker-tools.cjs, extractSection() extracts a named section from a markdown body using regex:

function extractSection(body, headerPattern) {
  const re = new RegExp(
    `^#{2,4}\s+(?:[^\n]*?${headerPattern}[^\n]*)\n([\s\S]*?)(?=^#{2,4}\s|$)`,
    'mi'  // <-- BUG: 'm' flag makes $ match end-of-every-line
  );
  const match = body.match(re);
  return match ? match[1].trim() : null;
}

The 'm' flag in 'mi' causes $ in the lookahead (?=^#{2,4}\s|$) to match the end of every line. Since [\s\S]*? is lazy, it stops after the first character that satisfies $ (i.e., end of line 1). The section content captured is always a single line — stripping all remaining content from the section.

Impact

  • compile-report could not extract Activity, Status Summary, or other sections from result files — producing empty/partial report output
  • update-tracker could not extract the ## Tracker Updates section — so status_summary:, history_entry:, goal:, new_duplicate: directives were never found and no tracker changes were applied
  • Combined with issue bug(tracker-tools): sectionRe uses 'm' flag causing $ to match end-of-every-line in applyTrackerUpdates #5 (sectionRe bug), this meant update-tracker was completely non-functional: it couldn't find the tracker section to update AND couldn't extract the updates to apply

Fix

Remove 'm', keep 'i', and change the anchor from ^ to (?:^|\n) so the header match still anchors to line starts:

function extractSection(body, headerPattern) {
  const re = new RegExp(
    `(?:^|\n)#{2,4}\s+(?:[^\n]*?${headerPattern}[^\n]*)\n([\s\S]*?)(?=\n#{2,4}\s|$)`,
    'i'  // 'i' only — $ now means end-of-string; (?:^|\n) handles line starts
  );
  const match = body.match(re);
  return match ? match[1].trim() : null;
}

Root Cause Pattern

Both this bug and #5 share the same root cause: using the 'm' multiline flag with a $ anchor in a lookahead where the intent is end-of-string, not end-of-line. In multiline mode, $ matches after every newline, allowing lazy [\s\S]*? to stop after the first line.

Status

Fixed in session on 2026-05-07.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions