Overlap checking against rejected drafts
The book on Royal Road right now is not the first attempt at these chapters. Several complete drafts came before it and were discarded, most dramatically a full second act, some sixty-five scenes, written and reviewed and then rejected outright partway through the project because the prose had leaned too heavily on an earlier, already abandoned version and had to start again from a clean brief. After that happened, the project needed a mechanical way to check for it happening again: prose that read fine on its own but had unconsciously borrowed phrasing from a version nobody wanted anymore.
What the check does
tools/overlap_check.py looks for runs of eight or more consecutive words, by default, in a newly drafted scene that also appear verbatim somewhere in the old drafts. Eight words is unlikely to be a coincidence of ordinary phrasing, but short enough to still catch a paraphrase that kept the original’s structure. Matches are reported with a reference to which old file they came from, so a real hit can be traced back to its source rather than just flagged as suspicious.
The mechanically interesting part is where the old prose lives. The discarded drafts were deleted from the working tree as part of a repository cleanup on the morning of 31 August, done so the overlap checker could run against git history instead of live files during that day’s scene-by-scene redraft, so they aren’t sitting on disk as files the tool can just read. Instead, the script pulls them from git history, reading the content as it existed at a specific pinned commit made just before the deletion. That means the check can run against material a drafting session, working normally, will never see or load into its own context. The old prose exists only so this one comparison can happen, pulled from history on demand rather than kept live in the project.
Why not just keep the drafts on disk
Keeping abandoned drafts in the working tree is the more obvious approach, and the project explicitly moved away from it. Old prose sitting in the repository is old prose a drafting session might read, deliberately or by stumbling into it while exploring the project, and reading it is close to the exact failure this tool exists to catch: contamination happens when new prose gets written with old prose too available. Pulling from a pinned git commit instead means the comparison can happen without that material ever being loaded into a session’s context at all, which is also why the project’s voice document, in the section governing what a drafting session may read, explicitly lists the deleted draft directories as ones a session should never open, alongside noting that this script is how they’re still checked without opening them.
The rule that followed the second-act rejection went further than just adding this tool: new prose written after that point was drafted from scratch, deliberately without reference to the old text even in outline form. A session drafting new scenes with old prose sitting in its own context, even unread, tends to echo it. The overlap checker is a mechanical backstop for that discipline, catching what slips through despite the rule. It doesn’t replace the rule.