diff --git a/backend/packages/harness/deerflow/utils/file_conversion.py b/backend/packages/harness/deerflow/utils/file_conversion.py index f51b47caa..5c5a28235 100644 --- a/backend/packages/harness/deerflow/utils/file_conversion.py +++ b/backend/packages/harness/deerflow/utils/file_conversion.py @@ -279,7 +279,11 @@ def extract_outline(md_path: Path) -> list[dict]: if title: outline.append({"title": title, "line": lineno}) - if len(outline) >= MAX_OUTLINE_ENTRIES: + if len(outline) > MAX_OUTLINE_ENTRIES: + # We collected one heading beyond the limit, which proves the + # document genuinely has more than MAX_OUTLINE_ENTRIES headings. + # Drop that extra entry and append the truncation sentinel. + outline.pop() outline.append({"truncated": True}) break except Exception: diff --git a/backend/tests/test_file_conversion.py b/backend/tests/test_file_conversion.py index 4c2189bc2..407b8ae12 100644 --- a/backend/tests/test_file_conversion.py +++ b/backend/tests/test_file_conversion.py @@ -422,6 +422,15 @@ class TestExtractOutline: assert len(outline) == 5 assert not any(e.get("truncated") for e in outline) + def test_no_truncation_sentinel_at_exact_limit(self, tmp_path): + """A document with exactly MAX_OUTLINE_ENTRIES headings is not truncated.""" + lines = [f"# Heading {i}" for i in range(MAX_OUTLINE_ENTRIES)] + md = tmp_path / "exact.md" + md.write_text("\n".join(lines), encoding="utf-8") + outline = extract_outline(md) + assert len(outline) == MAX_OUTLINE_ENTRIES + assert not any(e.get("truncated") for e in outline) + def test_blank_lines_and_whitespace_ignored(self, tmp_path): """Blank lines between headings do not produce empty entries.""" md = tmp_path / "spaced.md"