Skip to content

fix(tui): don't double-render finish_scan section headings#798

Open
seanturner83 wants to merge 2 commits into
usestrix:mainfrom
seanturner83:fix/finish-renderer-double-heading
Open

fix(tui): don't double-render finish_scan section headings#798
seanturner83 wants to merge 2 commits into
usestrix:mainfrom
seanturner83:fix/finish-renderer-double-heading

Conversation

@seanturner83

Copy link
Copy Markdown
Contributor

What

The finish_scan renderer shows each section heading twice — once as its own styled label, once from the field's markdown body.

Why

FinishScanRenderer.render() prints a styled label above each field:

text.append("Executive Summary", style=FIELD_STYLE)
text.append("\n")
text.append(executive_summary)

But the finish_scan tool prompts the model to "use markdown in every field", and its own docstring example opens executive_summary with # Executive Summary. So the models reliably start each field with a # <Section> heading — and it renders on top of the styled label:

Executive Summary        ← styled label
# Executive Summary      ← the field's own markdown heading
<body>

Every section (Executive Summary / Methodology / Technical Analysis / Recommendations) doubles. Cosmetic (TUI/log only — SARIF/report artifacts are unaffected), but consistently noisy.

Fix

Strip a leading markdown heading from a field value only when it repeats that field's section label (case-insensitive), so the label shows once. Deliberately conservative:

  • a leading heading that says something else → kept (real content),
  • a value with no heading → unchanged,
  • a lone heading with no body → kept (don't strip a section to empty).

Tests

tests/test_finish_renderer.py (7): the strip helper's match / case-insensitivity / different-heading-kept / no-heading-kept / lone-heading-kept cases, plus an end-to-end assert that "Executive Summary" renders exactly once and the body survives.

🤖 Generated with Claude Code

The finish_scan renderer prints a styled section label ("Executive Summary",
"Methodology", etc.) above each field's value. But the finish_scan tool prompts
the model to "use markdown in every field" and its own example opens each field
with a `# <Section>` heading — so the models routinely start executive_summary
with `# Executive Summary`, and the heading renders twice (styled label + the
markdown heading in the body).

Strip a leading markdown heading from a field value when it just repeats that
field's section label (case-insensitive), so the label appears once. A leading
heading that says something else, a value with no heading, and a lone heading
with no body are all left untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR removes repeated Markdown headings from finish-scan sections in the TUI. The main changes are:

  • Adds a helper for matching section headings.
  • Applies heading removal to all four finish-scan fields.
  • Adds helper and end-to-end renderer tests.

Confidence Score: 4/5

The heading-removal helper needs fixes for two reachable Markdown forms before merging.

  • A heading-only field ending with a newline is rendered as empty.
  • A heading with a closing ATX marker remains duplicated.
  • Persisted reports are unaffected because the change is limited to TUI rendering.

strix/interface/tui/renderers/finish_renderer.py

Important Files Changed

Filename Overview
strix/interface/tui/renderers/finish_renderer.py Adds heading deduplication for all finish-scan fields, with edge cases around empty remainders and closing ATX markers.
tests/test_finish_renderer.py Adds focused helper and rendering tests but omits heading-only values with trailing newlines and headings with closing markers.
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
strix/interface/tui/renderers/finish_renderer.py:27-28
**Trailing Newline Erases Lone Heading**

When a field contains only `# Recommendations\n`, it passes the upstream non-empty check and matches this pattern, but the helper returns an empty string. The TUI then hides the field's only supplied content, contrary to the stated rule that a lone heading should be preserved.

```suggestion
    m = re.match(pattern, stripped, flags=re.IGNORECASE)
    remainder = stripped[m.end() :] if m else ""
    return remainder if remainder.strip() else value
```

### Issue 2 of 2
strix/interface/tui/renderers/finish_renderer.py:26
**Closing ATX Marker Defeats Deduplication**

A valid Markdown heading such as `# Executive Summary #\n\nBody` does not match because of its closing `#`. The original heading remains below the styled section label, so the duplicate heading this change targets is still displayed for that common Markdown form.

```suggestion
    pattern = rf"^#{{1,6}}\s+{re.escape(section)}(?:\s+#+)?\s*\n+"
```

Reviews (1): Last reviewed commit: "fix(tui): don't double-render finish_sca..." | Re-trigger Greptile

Comment on lines +27 to +28
m = re.match(pattern, stripped, flags=re.IGNORECASE)
return stripped[m.end() :] if m else value

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.

P1 Trailing Newline Erases Lone Heading

When a field contains only # Recommendations\n, it passes the upstream non-empty check and matches this pattern, but the helper returns an empty string. The TUI then hides the field's only supplied content, contrary to the stated rule that a lone heading should be preserved.

Suggested change
m = re.match(pattern, stripped, flags=re.IGNORECASE)
return stripped[m.end() :] if m else value
m = re.match(pattern, stripped, flags=re.IGNORECASE)
remainder = stripped[m.end() :] if m else ""
return remainder if remainder.strip() else value
Prompt To Fix With AI
This is a comment left during a code review.
Path: strix/interface/tui/renderers/finish_renderer.py
Line: 27-28

Comment:
**Trailing Newline Erases Lone Heading**

When a field contains only `# Recommendations\n`, it passes the upstream non-empty check and matches this pattern, but the helper returns an empty string. The TUI then hides the field's only supplied content, contrary to the stated rule that a lone heading should be preserved.

```suggestion
    m = re.match(pattern, stripped, flags=re.IGNORECASE)
    remainder = stripped[m.end() :] if m else ""
    return remainder if remainder.strip() else value
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

say something else — untouched.
"""
stripped = value.lstrip()
pattern = rf"^#{{1,6}}\s+{re.escape(section)}\s*\n+"

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.

P2 Closing ATX Marker Defeats Deduplication

A valid Markdown heading such as # Executive Summary #\n\nBody does not match because of its closing #. The original heading remains below the styled section label, so the duplicate heading this change targets is still displayed for that common Markdown form.

Suggested change
pattern = rf"^#{{1,6}}\s+{re.escape(section)}\s*\n+"
pattern = rf"^#{{1,6}}\s+{re.escape(section)}(?:\s+#+)?\s*\n+"
Prompt To Fix With AI
This is a comment left during a code review.
Path: strix/interface/tui/renderers/finish_renderer.py
Line: 26

Comment:
**Closing ATX Marker Defeats Deduplication**

A valid Markdown heading such as `# Executive Summary #\n\nBody` does not match because of its closing `#`. The original heading remains below the styled section label, so the duplicate heading this change targets is still displayed for that common Markdown form.

```suggestion
    pattern = rf"^#{{1,6}}\s+{re.escape(section)}(?:\s+#+)?\s*\n+"
```

How can I resolve this? If you propose a fix, please make it concise.

Two Greptile findings:
- P1: a field that is ONLY the heading + a trailing newline (e.g.
  "# Recommendations\n") matched the strip pattern and returned empty, hiding
  the field's sole content — contradicting the "keep a lone heading" intent.
  Now: if stripping leaves nothing non-whitespace, keep the original value.
- P2: the closed-ATX form "# Executive Summary #" didn't match, so its
  duplicate heading still rendered. Pattern now accepts an optional closing
  "#+" run.

+2 tests (heading-only-with-newline kept; closing-ATX stripped).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@seanturner83

Copy link
Copy Markdown
Contributor Author

Both fixed in the latest push — good catches:

  • P1 (heading-only field blanked): a field that's just # Recommendations\n matched the pattern and stripped to empty, hiding its only content. Now if stripping would leave nothing non-whitespace, the original value is kept.
  • P2 (closing-ATX): the pattern now accepts an optional trailing #+ run, so # Executive Summary # also dedupes.

Added tests for both (heading-only-with-newline preserved; closing-ATX stripped).

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.

1 participant