Skip to content

forward -f can emit a duplicated frontmatter block — add an "exactly one frontmatter" post-write guard #288

Description

@quantecon-services

What happened

The forward -f recovery that resynced hoist_failure.md on lecture-python.zh-cn (zh-cn#260, 2026-08-20) prepended a fresh frontmatter block without removing the old one. The file now reads:

  • lines 1–32: the new frontmatter (------), with the current heading map;
  • lines 33–57: the old jupytext:/kernelspec:/translation: block (with a stale heading map), running to its own closing --- — but with no opening ---.

Because the second block is never opened, it is not YAML: MyST renders it as literal body text, so the published page opens with ~25 lines of garbled key-value text (including an unquoted Application: waste hoist failure rate: … line). It post-dates publish-2026aug19, so it becomes reader-visible at the edition's next publish unless hand-repaired.

A corpus-wide sweep found no second instance (145 lectures checked for top-level jupytext:/kernelspec:/translation: keys outside the first block).

Why the existing checks miss it

Same blind spot as #118's fence-wrap class: the duplicate block adds no {directive} lines, so directive-sequence/count parity passes; the document still starts with a valid frontmatter at position 0, so a frontmatter-position check passes; the H1 is intact.

Suggested guard

Post-write invariant, cheap and deterministic: exactly one frontmatter block per document, and no top-level jupytext: / kernelspec: / translation: keys outside it. This joins the two guards proposed on #118 (exactly one frontmatter at position 0; translation.title corresponds to an H1) — this case shows "at position 0" alone is not sufficient.

Found by the 2026-08-20 full-corpus audit: project-translation#50 (REPORT.md, "Structural parity").

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions