SI: adopt the clearer rewrite, with factual corrections; fix two build bugs it exposed

Prose: adopted the simplified rewrite for the Reproducibility preamble, SI
Text S1 and S2, and the two tables. It reads better - shorter sentences, no
shouty caps, no self-commentary in the proposition headings.

Fact-checked against the artifacts before adopting. Corrections:
- Table S2 said grounding retention used "18+ replicates per point". E2 uses
  100 lineages; 18 is the *neural* grounding sweep. (Pre-existing error,
  faithfully carried over by the rewrite.)
- The emergent parents' 0.535/0.474 are the accuracies at the LONGEST
  divergence (t_div=3200), not overall means (0.595/0.545); now qualified.
  Verified merge holds 0.954-0.956 at every divergence, residual exactly
  0.000 in both emergent conditions.
- Dropped an invented run date (2026-08-11; the run is from 2026-09-06) and
  an internal project-phase reference ("Phase 3").
- The llm_speciation duration question is no longer open - it ran, and found
  no isolation from over-training (1-12 epochs); text updated.
- Restored the confidence-weighting numbers the rewrite dropped: paired
  bootstrap contrast |rho| = -0.021, CI [-0.130, +0.059] (re-derived), plus
  the nuance that the weighting does sharpen the level contrast.
- "Minimal model" -> "biological model"; "LLM tier in progress" -> done.
- Trimmed an unverifiable citation ("neuron-identifiability approaches...")
  to the reference the bibliography actually carries.

Two rendering bugs the LaTeX version exposed, both pre-existing:
- Greek and several math symbols were absent from build.py's unicode map, so
  alpha and epsilon were rendering as missing-glyph boxes in the SI. Added
  Greek, set membership, superscripts, proper minus. Both PDFs now contain
  zero missing glyphs.
- inline() split on code spans BEFORE applying emphasis, so any italic
  containing `code` was torn into fragments - visible in the main text as a
  literal "is*" and mis-scoped italics on p. 3. Code spans are now stashed
  behind sentinels first. This fixed the manuscript, not just the SI.
- A leading markdown H1 leaked into the body as literal text; the wrapper
  supplies the title, so it is now skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BkRLcc18rwT2Lysu6PbG7v
This commit is contained in:
Giorgio Gilestro 2026-09-07 17:13:02 +01:00
parent a88289964a
commit e4804adabc
6 changed files with 167 additions and 126 deletions

View file

@ -106,9 +106,17 @@ FIGURES: dict[str, tuple[list[str], str]] = {
"between predictors are not individually significant."),
}
UNICODE = {"": "---", "": "--", "": r"\(\rightarrow\)", "": r"\(\approx\)", "": r"\(\geq\)",
"": r"\(\gtrsim\)", "×": r"\(\times\)", "·": r"\(\cdot\)", "μ": r"\(\mu\)",
"ρ": r"\(\rho\)", "": r"\(\leq\)", "": r"\(\ll\)", "": r"\(\propto\)"}
UNICODE = {
# Multi-character sequences first: esc() applies these in insertion order.
"⁽ᵏ⁾": r"\(^{(k)}\)", "⁻³": r"\(^{-3}\)", "⁻⁴": r"\(^{-4}\)",
"": "---", "": "--", "": r"\(\rightarrow\)", "": r"\(\approx\)", "": r"\(\geq\)",
"": r"\(\gtrsim\)", "×": r"\(\times\)", "·": r"\(\cdot\)", "μ": r"\(\mu\)",
"ρ": r"\(\rho\)", "": r"\(\leq\)", "": r"\(\ll\)", "": r"\(\propto\)",
# Greek and math symbols: the typewriter font has no Greek, so these must become math.
"α": r"\(\alpha\)", "β": r"\(\beta\)", "ε": r"\(\varepsilon\)", "Δ": r"\(\Delta\)",
"Σ": r"\(\Sigma\)", "": r"\(\in\)", "": r"\(\neq\)", "±": r"\(\pm\)",
"": r"\(\sim\)", "": r"\(-\)", "²": r"\(^{2}\)", "³": r"\(^{3}\)", "": r"\(^{4}\)",
}
SPECIALS = {"&": r"\&", "%": r"\%", "#": r"\#", "_": r"\_", "$": r"\$",
"~": r"\textasciitilde{}", "^": r"\textasciicircum{}"}
@ -123,19 +131,21 @@ def esc(s: str) -> str:
def inline(s: str) -> str:
parts = re.split(r"(`[^`]*`)", s)
out = []
for p in parts:
if p.startswith("`") and p.endswith("`") and len(p) >= 2:
out.append(r"\texttt{" + esc(p[1:-1]) + "}")
else:
p = esc(p)
p = re.sub(r"\[([^\]]+)\]\((https?://[^)]+)\)", r"\\href{\2}{\1}", p)
p = re.sub(r"\*\*([^*]+)\*\*", r"\\textbf{\1}", p)
p = re.sub(r"\*([^*]+)\*", r"\\emph{\1}", p)
p = re.sub(r'"([^"]+)"', r"``\1''", p)
out.append(p)
return "".join(out)
# Code spans are stashed behind sentinels *before* emphasis is applied, so that an italic or
# bold span containing `code` is still matched as one span (splitting first would break it).
codes: list[str] = []
def stash(m: re.Match) -> str:
codes.append(r"\texttt{" + esc(m.group(0)[1:-1]) + "}")
return f"\x00{len(codes) - 1}\x00"
s = re.sub(r"`[^`]*`", stash, s)
s = esc(s)
s = re.sub(r"\[([^\]]+)\]\((https?://[^)]+)\)", r"\\href{\2}{\1}", s)
s = re.sub(r"\*\*([^*]+)\*\*", r"\\textbf{\1}", s)
s = re.sub(r"\*([^*]+)\*", r"\\emph{\1}", s)
s = re.sub(r'"([^"]+)"', r"``\1''", s)
return re.sub(r"\x00(\d+)\x00", lambda m: codes[int(m.group(1))], s)
def figure_env(name: str) -> str:
@ -192,6 +202,8 @@ def convert(text: str) -> str:
emit_table(block, out)
elif first == "---" and len(block) == 1:
out.append("\\medskip\\hrule\\medskip"); out.append("")
elif first.startswith("# ") and not first.startswith("## "):
continue # document title: the wrapper supplies it
elif first.startswith("## "):
out.append(f"\\section*{{{inline(first[3:])}}}"); out.append("")
elif first.startswith("### "):