From 32ffb43f6318cceae3390ce7522ca2f3be185b50 Mon Sep 17 00:00:00 2001 From: Daniel Kronovet Date: Wed, 22 Apr 2026 09:55:59 -0400 Subject: [PATCH] fix: preserve lowercase dojo. package names in defrag Add normalizePackageNames post-pass to the terminology defrag. The LLM was proper-noun-capitalizing package identifiers like dojo.unreal and dojo.unity in prose, creating a mismatch with the actual repo URLs and package names. The deterministic revert runs after the LLM output, skipping fenced code blocks, inline code spans, and link targets. Co-Authored-By: Claude Opus 4.7 --- scripts/defrag-terminology.mjs | 2 ++ scripts/lib/defrag-utils.mjs | 64 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/scripts/defrag-terminology.mjs b/scripts/defrag-terminology.mjs index 4ed6c9fb..b71bba20 100644 --- a/scripts/defrag-terminology.mjs +++ b/scripts/defrag-terminology.mjs @@ -24,6 +24,7 @@ import { callClaude, checkLinksPreserved, checkCodeRegionsPreserved, + normalizePackageNames, } from "./lib/defrag-utils.mjs"; import { join } from "path"; @@ -108,6 +109,7 @@ async function main() { ); let normalized = corrected.replace(/\n*$/, "\n"); + normalized = normalizePackageNames(normalized); if (normalized === original) { console.log(` No changes.`); diff --git a/scripts/lib/defrag-utils.mjs b/scripts/lib/defrag-utils.mjs index 51245341..d7fcf2e4 100644 --- a/scripts/lib/defrag-utils.mjs +++ b/scripts/lib/defrag-utils.mjs @@ -170,6 +170,70 @@ export function checkCodeRegionsPreserved(original, corrected) { return { ok: mismatches.length === 0, mismatches }; } +/** + * Lowercase `Dojo.` package identifiers back to `dojo.` + * in prose. Skips fenced code blocks, inline code spans, and markdown link + * targets. The LLM terminology pass tends to proper-noun these even though + * the real repo/package names are lowercase (e.g., github.com/dojoengine/dojo.unreal). + */ +export function normalizePackageNames(content) { + const PACKAGE_RE = /\bDojo\.(unreal|unity|js|c|bevy|godot)\b/g; + const lowercase = (s) => s.replace(PACKAGE_RE, (_, p) => `dojo.${p}`); + + const out = []; + let inBlock = false; + for (const line of content.split("\n")) { + if (line.trimStart().startsWith("```")) { + inBlock = !inBlock; + out.push(line); + continue; + } + if (inBlock) { + out.push(line); + continue; + } + out.push(lowercaseInProseLine(line, lowercase)); + } + return out.join("\n"); +} + +function lowercaseInProseLine(line, lowercase) { + let result = ""; + let i = 0; + while (i < line.length) { + if (line[i] === "`") { + const end = line.indexOf("`", i + 1); + if (end === -1) { + result += line.slice(i); + return result; + } + result += line.slice(i, end + 1); + i = end + 1; + continue; + } + if (line[i] === "]" && line[i + 1] === "(") { + const end = line.indexOf(")", i + 2); + if (end === -1) { + result += line.slice(i); + return result; + } + result += line.slice(i, end + 1); + i = end + 1; + continue; + } + let next = line.length; + for (let j = i; j < line.length; j++) { + if (line[j] === "`" || (line[j] === "]" && line[j + 1] === "(")) { + next = j; + break; + } + } + result += lowercase(line.slice(i, next)); + i = next; + } + return result; +} + /** * Check if any single diff hunk exceeds the size limit. */