Skip to content

fix: use parseFrontmatter instead of an unbounded title: regex in 4 more places - #578

Merged
nashsu merged 1 commit into
nashsu:mainfrom
chuenchen309:fix/frontmatter-title-sibling-sites
Jul 15, 2026
Merged

fix: use parseFrontmatter instead of an unbounded title: regex in 4 more places#578
nashsu merged 1 commit into
nashsu:mainfrom
chuenchen309:fix/frontmatter-title-sibling-sites

Conversation

@chuenchen309

Copy link
Copy Markdown
Contributor

Follow-up to #577

While fixing the same bug pattern in wiki-graph.ts (#577), I found the identical unbounded regex reimplemented in 4 more places:

content.match(/^---\n[\s\S]*?^title:\s*["']?(.+?)["']?\s*$/m)

Anchored only at the opening ---, with the lazy [\s\S]*? never required to stop at the closing ---. A page whose frontmatter has no title — but whose body happens to contain a later line starting with title: (plain prose, not YAML) — gets that body line misread as the title.

The blast radius differs per site:

  • embedding.ts (extractEmbeddingTitle): the bogus title gets prepended to every chunk's embedding text, silently corrupting the semantic vectors sent to the embedding model for that page.
  • sweep-reviews.ts (buildWikiIndex): the bogus title is added to the wiki index's byTitle set, which pageExists() checks to decide whether a missing-page review should auto-resolve — a body line that happens to match a still-missing page's name can falsely mark that review as resolved, silently hiding a real gap from the user.
  • ingest.ts (2 sites): the bogus title is passed to embedPage(), same corruption as the embedding.ts site.

Fix

This codebase already has a correct, actively-used frontmatter parser — src/lib/frontmatter.ts's parseFrontmatter(), built on js-yaml, already used in 10+ other files including ingest.ts itself at two other call sites. Rather than re-patch the regex 4 more times, I switched all 4 sites to use parseFrontmatter() instead.

Exported extractEmbeddingTitle and buildWikiIndex (previously module-private) so they're directly unit-testable, matching the existing @internal — exported for tests only pattern already used for extractJsonObject in sweep-reviews.ts.

Testing

  • Added regression tests for extractEmbeddingTitle (embedding.test.ts) and buildWikiIndex (new sweep-reviews-build-wiki-index.test.ts). Confirmed both fail against the pre-fix regex and pass with parseFrontmatter.
  • Ran the full npm run test:mocks suite (1643 passed) and npm run typecheck (clean).

Disclosure: I used an AI coding assistant (Claude) to help identify this bug pattern and draft the fix. I independently confirmed parseFrontmatter was already the established convention elsewhere in the codebase (including inside ingest.ts itself) before choosing to switch these sites to it rather than just patching the regex in place, verified each site's exact blast radius, and ran the full local test suite plus typecheck before opening this PR.

…ore places

extractEmbeddingTitle (embedding.ts), buildWikiIndex (sweep-reviews.ts),
and two sites in ingest.ts each reimplemented their own frontmatter
title extraction with:

    content.match(/^---\n[\s\S]*?^title:\s*["']?(.+?)["']?\s*$/m)

Anchored only at the opening `---`, with the lazy [\s\S]*? never
required to stop at the closing `---`. A page whose frontmatter has no
title -- but whose body happens to contain a later line starting with
"title:" (plain prose, not YAML) -- gets that body line misread as the
title. This is the same bug already found and fixed in wiki-graph.ts's
extractTitle/extractType (a separate open PR).

The blast radius differs per site:
- embedding.ts: the bogus title gets prepended to every chunk's
  embedding text, silently corrupting the semantic vectors sent to the
  embedding model for that page.
- sweep-reviews.ts: the bogus title is added to the wiki index's
  byTitle set, which pageExists() checks to decide whether a
  "missing-page" review should auto-resolve -- a body line that
  happens to match a still-missing page's name can falsely mark that
  review as resolved, silently hiding a real gap.
- ingest.ts (x2): the bogus title is passed to embedPage(), same
  corruption as the embedding.ts site.

This codebase already has a correct, actively-used frontmatter parser
(src/lib/frontmatter.ts's parseFrontmatter, built on js-yaml, used in
10+ other files including ingest.ts itself at two other call sites).
Switch all 4 buggy sites to use it instead of re-deriving frontmatter
fields with a fragile regex.

Exported extractEmbeddingTitle and buildWikiIndex (previously
module-private) so they're directly unit-testable, matching the
existing @internal-exported-for-tests pattern already used for
extractJsonObject in sweep-reviews.ts.

Added regression tests for extractEmbeddingTitle (embedding.test.ts)
and buildWikiIndex (new sweep-reviews-build-wiki-index.test.ts).
Confirmed both fail against the pre-fix regex and pass with
parseFrontmatter. Ran the full test:mocks suite (1643 passed) and
typecheck (clean).

Disclosure: I used an AI coding assistant (Claude) to help identify
this bug pattern and draft the fix. I independently confirmed
parseFrontmatter was already the established convention elsewhere in
the codebase (including inside ingest.ts itself) before choosing to
switch these sites to it rather than just patching the regex in place,
verified each site's exact blast radius, and ran the full local test
suite plus typecheck before opening this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@nashsu
nashsu merged commit dd35921 into nashsu:main Jul 15, 2026
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.

2 participants