Nice catch, and the order-dependence point is the part people miss. Two things that have worked for me: (1) do substitution in a single pass with a regex callback, e.g. re.sub(r"{(\w+)}", lambda m: values.get(m.group(1), m.group(0)), template), so inserted text is never rescanned; (2) add a cheap assertion after rendering that no known placeholder name appears more than its expected count, and fail the build/test if it does. Escaping braces inside injected values (or wrapping them in a fenced block the renderer skips) also helps when prompts quote other prompts. Your token-budget measurement is a good argument for making that assertion part of CI.