Repository navigation
Report unclosed Markdown fences during audit - #202
Conversation
Co-authored-by: insisong <emmanuelisaacnsisong@gmail.com>
Review at edf44d0I reproduced #199 on main and on this head using the issue's chapter: Should fix 1. The new README sentence overstates the check ( "The audit reports 2. The #199 asked for this docstring to be corrected along with the README. It still says the graph, the audit and the page agree, and that the site draws an unclosed fence as plain text. Something like: """Return ``lines`` with fenced blocks and HTML comments blanked.
This is how the graph and the audit agree on which headings and links an
article has. A fence without a closing line is read as plain text, so it
hides nothing here. A one-article page draws it the same way, but a chapter
page can pair it with a later article's fence, so the audit reports it as
``unclosed-code-fence``.
"""3. A line that starts with inline code in triple backticks becomes a failing error (
FENCE = re.compile(r"^ {0,3}(`{3,}(?=[^`]*$)|~{3,})")With it, both layouts audit clean, the edge comes back, the four test files above pass, and audit output on the three real blueprints is unchanged. 4. Read the article once, in The new line reads the file a second time without the @dataclass(frozen=True, slots=True)
class _ArticleShape:
statement: str
has_depends_section: bool
#: The one-based source line of the first fence that never closes.
unclosed_fence: int | None = None
def _read_article(path: Path) -> _ArticleShape:
...
parts = _article_parts(text)
lines = text.splitlines()
start = _frontmatter_end(lines)
unclosed = _first_unclosed_fence(lines[start:])
return _ArticleShape(
statement=parts.statement,
has_depends_section=any(section.title.casefold() == "depends on" for section in parts.sections),
unclosed_fence=None if unclosed is None else start + unclosed + 1,
) if article.unclosed_fence is not None:
findings.append(
AuditFinding(
article_path,
"unclosed-code-fence",
f"code fence opened on line {article.unclosed_fence} never closes",
)
)In def first_unclosed_fence(lines: list[str]) -> int | None:
"""Return the index of the first fence line that never closes, if any."""
openers: set[int] = set()
_mask_fences_and_comments(lines, set(), unclosed_fence_is_text=True, unclosed_openers=openers)
return min(openers, default=None)This version reports only the first opener. With several, the current message reads Test gaps 5. No test puts the fence in a chapter README ( Both new tests use a formalizable leaf, so changing the check to def test_audit_reports_an_unclosed_code_fence_in_a_chapter_article(tmp_path: Path) -> None:
# A chapter's README heads its chapter page, so its open fence swallows the leaves below it.
blueprint = tmp_path / "blueprint"
_coverage(blueprint)
_article(blueprint, "chapter/result.md", declaration="theorem")
readme = blueprint / "roadmap" / "chapter" / "README.md"
readme.write_text("# Chapter\n\n```text\nsketch\n", encoding="utf-8")
assert ("unclosed-code-fence", "code fence opened on line 3 never closes") in _finding_map(blueprint)[
"roadmap/chapter/README.md"
]Nits
Checked, no change needed
Posted by PR swarm: PR Swarm Lead |
Co-authored-by: insisong <emmanuelisaacnsisong@gmail.com>
|
Addressed the review in signed commit
Validation: |
Brings in main at 76e486d: the CI audit probe that runs no project code (#190), the atlas release and library dependencies on Lean 4.34.1 (#211), the project inspect cleanup (#174), lakefile.lean precedence (#189), roadmap symlink refusal and the bounded parent walk (#197), unclosed-fence audit findings (#202), migrate article-ids --write (#191), and complete scopes and container boxes (#196). Conflicts: - autoform_cli/README.md: main's description of --write, with this branch's "The runtime" in place of "Runtime v3", since the runtime schema here is v4. - autoform_cli/graph_pages.py: the explorer pages stay as they are here, with no per-node focus pages or Mermaid full page, so main's focus_views and container_nodes calls, its drawn statuses and its focus-page loop go; the explorer legend already leaves containers out. The project lead takes main's count, the items its scopes count, and main's "items" wording. - autoform_cli/graph_views.py: ViewNode carries main's complete flag and this branch's catalog, summary, lean, area and internal count. Project, nested-scope and node-level container nodes are all built by main's _scope_node, extended with this branch's fields and rolled-up status, and full_view takes main's containers argument with this branch's title and summary. Main's target rule, a leaf that declares something or is marked not ready, becomes is_scope_target, which also keeps catalogs out; scope members, completion and status rings all use it, and checked catalogs still count apart. The unused _leaf_descendant_map goes. - autoform_cli/mermaid.py: a container's tooltip gives main's scope summary and a checked catalog's still says "inventory checked"; the vault legend leaves out containers, as on main, and keeps only formalizable leaves, as here. - autoform_cli/render.py: main's _FENCE, which opens no backtick fence whose info string holds a backtick, beside this branch's _MARKDOWN_LINK, which allows brackets inside a label. - skills/roadmap/SKILL.md: this branch's existing-repository paragraph with main's instruction to run article-ids --write. Adopting main's scope rule needed three changes without a textual conflict. The explorer payload's member_count and its bubble size use item_count, so a scope's "N items" counts what its status rows count, inventory row included. autoform-visualize falls back to a scope's first article from group_nodes rather than its first member, since members are now only targets. Four tests now expect a node-level container's members to be the container, a fully proved scope to draw as scope_complete, the project lead to say "1 item", and the atlas fixture's counts to match its members.
Test the frontmatter, inline-backtick and render fence fixes from #202
…ebookresearch#202 Each test fails with its fix reverted. The audit frontmatter test and the masker test that were meant to cover two of them passed either way, and render.py's fence pattern had no test.
Fixes #199
autoform auditnow reportsunclosed-code-fencewith the opening source line whenever an article contains a fence that reaches EOF. The detection reuses the existing Markdown masking pass, so audit diagnostics and graph parsing keep the same fence and comment semantics.The README now distinguishes single-article parsing from chapter-page corruption, and regression coverage verifies both the finding and the bundled example.
Validation:
uv run pytest -q tests/test_audit.py(65 passed)uv run ruff check autoform_cli servers testsuv run pytest -q(2020 passed, 58 skipped, 1 xfailed)make check-examplegit diff --checkCo-authored-by: insisong emmanuelisaacnsisong@gmail.com