Merge driver declines to resolve dates on BOM-prefixed pages (generator tolerates BOM) #6

Closed
opened 2026-09-14 14:55:41 +02:00 by kristofferopsahl · 0 comments

Summary

The generator and the merge driver disagree about whether a UTF-8 BOM can appear on a page.

wiki-index.py reads pages with encoding="utf-8-sig", so a BOM-prefixed page is explicitly supported and indexes fine. wiki-merge-updated.py works in binary and detects frontmatter with:

frontmatter = bool(lines and lines[0].rstrip(b"\r\n") == b"---")

On a BOM-prefixed page lines[0] is b"\xef\xbb\xbf---", so frontmatter is never True and no date conflict on that page is ever resolved.

Reproduction

Verified against main (499a1c1a), marker size 7:

printf '\xef\xbb\xbf---\ndescription: d\nupdated: 2026-09-10\n---\n\n# Page\n' > base.md
sed 's/2026-09-10/2026-09-12/' base.md > ours.md
sed 's/2026-09-10/2026-09-14/' base.md > theirs.md
cp ours.md a.md
bash .claude/scripts/wiki-merge-updated.sh base.md a.md theirs.md 7
# exit=1, one conflict left standing

Without the BOM the identical case resolves to updated: 2026-09-14, exit 0.

Severity

Low, and it fails safe — the conflict is left for review rather than resolved wrongly. Reporting it because the two halves of the toolchain hold different assumptions, so whichever is wrong will drift further over time. Either the driver should skip a leading BOM when locating frontmatter, or the generator should not advertise BOM tolerance.

Also, cosmetic

render() builds category headings with category.replace("-", " ").capitalize(). Since str.capitalize() lowercases the remainder, an auto-discovered category directory named saf-t renders as Saf t. .title(), or capitalising only the first character, would preserve intent.

Context

Reported by the downstream team whose index corruption prompted a35c203b. We have now replaced our own local implementation with yours — it fixed four real defects in ours: an H1 taken from inside a code fence, a date conflict silently resolved inside a documentation example outside frontmatter, a deliberate backwards revert overridden, and CRLF destroyed by text-mode writes. The --diff3 ancestor check and binary IO are the parts we had no answer for. Thank you.

## Summary The generator and the merge driver disagree about whether a UTF-8 BOM can appear on a page. `wiki-index.py` reads pages with `encoding="utf-8-sig"`, so a BOM-prefixed page is explicitly supported and indexes fine. `wiki-merge-updated.py` works in binary and detects frontmatter with: ```python frontmatter = bool(lines and lines[0].rstrip(b"\r\n") == b"---") ``` On a BOM-prefixed page `lines[0]` is `b"\xef\xbb\xbf---"`, so `frontmatter` is never `True` and no date conflict on that page is ever resolved. ## Reproduction Verified against `main` (`499a1c1a`), marker size 7: ```bash printf '\xef\xbb\xbf---\ndescription: d\nupdated: 2026-09-10\n---\n\n# Page\n' > base.md sed 's/2026-09-10/2026-09-12/' base.md > ours.md sed 's/2026-09-10/2026-09-14/' base.md > theirs.md cp ours.md a.md bash .claude/scripts/wiki-merge-updated.sh base.md a.md theirs.md 7 # exit=1, one conflict left standing ``` Without the BOM the identical case resolves to `updated: 2026-09-14`, exit 0. ## Severity Low, and it fails **safe** — the conflict is left for review rather than resolved wrongly. Reporting it because the two halves of the toolchain hold different assumptions, so whichever is wrong will drift further over time. Either the driver should skip a leading BOM when locating frontmatter, or the generator should not advertise BOM tolerance. ## Also, cosmetic `render()` builds category headings with `category.replace("-", " ").capitalize()`. Since `str.capitalize()` lowercases the remainder, an auto-discovered category directory named `saf-t` renders as `Saf t`. `.title()`, or capitalising only the first character, would preserve intent. ## Context Reported by the downstream team whose index corruption prompted `a35c203b`. We have now replaced our own local implementation with yours — it fixed four real defects in ours: an H1 taken from inside a code fence, a date conflict silently resolved inside a documentation example outside frontmatter, a deliberate backwards revert overridden, and CRLF destroyed by text-mode writes. The `--diff3` ancestor check and binary IO are the parts we had no answer for. Thank you.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kristofferopsahl/auto-llm-wiki#6
No description provided.