Consolidate the TSI report into one document
The four-part split existed because the single report had grown dense
and heavily cross-referenced; splitting traded that for a different
cost, which the merged read makes visible. Section numbers (§1–§9,
Appendices A–C) were already the stable identifiers, so the parts were
a packaging choice, not a structural one.
reports/tsi/tsi-report.md is now the whole report. Parts are
interleaved back into section order — §1, §2–§5, §6, §7–§8, §9 +
appendices — which is NOT concatenation order: Part 1 carried §1, §7
and §8, so appending files in sequence would have put §7–§8 ahead of
§2. Every cross-file link collapses to an internal anchor; all 47
anchors resolve, all 37 figure embeds resolve, and no line of prose was
lost (verified by diffing normalised content lines with link targets
stripped — 0 lost, additions are the new header and table of contents).
Coherence fixes the merge exposed, all artefacts of the split:
- The roadmap paragraph described "four parts (see the index)" and is
now a section-order roadmap, with its circular self-link to §1
dropped.
- §7's figure-location note pointed readers at "the other parts". It
now names the actual sections, and it was also WRONG about three
figures: fig17/fig18/fig21 are in Appendix C and figB1/figB2 in
Appendix B, not §9. It had also never been updated for fig30–fig35.
- §9's "throughout this part" is now "throughout".
README.md becomes a proper index — a section table pointing into the
one document — rather than a list of four files.
scripts/split_report.py is deleted: a one-time migration that produced
the split, now both obsolete and pointing the wrong way.
scripts/build_html.py was already broken before this change — it still
read the report from tsi-sim-pernode/, where the files stopped living
when they moved to reports/tsi/. Retargeted at reports/tsi/ and the
single document; verified end-to-end (0 broken internal anchors, 0
unrewritten .md links, 37 images in the rendered HTML). Its output is
now gitignored, as its docstring always claimed it was.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:42:03 +02:00
|
|
|
"""Render the TSI report markdown to standalone, print-friendly HTML.
|
2026-07-30 18:57:10 +02:00
|
|
|
|
Consolidate the TSI report into one document
The four-part split existed because the single report had grown dense
and heavily cross-referenced; splitting traded that for a different
cost, which the merged read makes visible. Section numbers (§1–§9,
Appendices A–C) were already the stable identifiers, so the parts were
a packaging choice, not a structural one.
reports/tsi/tsi-report.md is now the whole report. Parts are
interleaved back into section order — §1, §2–§5, §6, §7–§8, §9 +
appendices — which is NOT concatenation order: Part 1 carried §1, §7
and §8, so appending files in sequence would have put §7–§8 ahead of
§2. Every cross-file link collapses to an internal anchor; all 47
anchors resolve, all 37 figure embeds resolve, and no line of prose was
lost (verified by diffing normalised content lines with link targets
stripped — 0 lost, additions are the new header and table of contents).
Coherence fixes the merge exposed, all artefacts of the split:
- The roadmap paragraph described "four parts (see the index)" and is
now a section-order roadmap, with its circular self-link to §1
dropped.
- §7's figure-location note pointed readers at "the other parts". It
now names the actual sections, and it was also WRONG about three
figures: fig17/fig18/fig21 are in Appendix C and figB1/figB2 in
Appendix B, not §9. It had also never been updated for fig30–fig35.
- §9's "throughout this part" is now "throughout".
README.md becomes a proper index — a section table pointing into the
one document — rather than a list of four files.
scripts/split_report.py is deleted: a one-time migration that produced
the split, now both obsolete and pointing the wrong way.
scripts/build_html.py was already broken before this change — it still
read the report from tsi-sim-pernode/, where the files stopped living
when they moved to reports/tsi/. Retargeted at reports/tsi/ and the
single document; verified end-to-end (0 broken internal anchors, 0
unrewritten .md links, 37 images in the rendered HTML). Its output is
now gitignored, as its docstring always claimed it was.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:42:03 +02:00
|
|
|
Markdown is the source of truth; the HTML is a build artifact (not committed). Code blocks are
|
|
|
|
|
syntax-highlighted (codehilite + Pygments), and `.md` links are rewritten to `.html` so the
|
|
|
|
|
index and the report navigate to each other.
|
2026-07-30 18:57:10 +02:00
|
|
|
|
Report becomes the directory README; rebuild the contents block
The report is now reports/tsi/README.md, so browsing to reports/tsi/
lands on the report itself rather than on an index that points at it.
The old index carried nothing the report lacked except the note that
report-figures/ holds the figures of record (the simulator folder does
not commit its own), which is folded into §9; its section table is
superseded by the report's own contents block. The "[Index]" self-link
in the header is replaced by the simulator link the index used to carry.
The contents block was inconsistent: §2 listed subsection titles, §3 and
§6 listed bare numbers with no titles at all, and the appendices were
crammed onto one line while their subsections went unlisted. Rebuilt
from the document's actual headings so every entry has a real title,
top-level entries carry a one-line gloss, and subsections sit indented
under their parent. It now covers all 47 anchors, including B.1-B.4 and
C.1-C.2 which were previously absent.
scripts/build_html.py follows the rename (DOCS is a single document) and
still renders clean: 47 anchors, 0 broken internal links, 0 unrewritten
.md links, 37 images.
Also adds configs/countable-vs-old-paired.yaml — the paired, 20-replicate
version of the overload grid. §3.2a now rests on a paired design while
§3.2 still rests on 5 unpaired replicates, which is why its U=1 cells at
delta_max 16 and 32 sit unresolved at t ~ 0.5 against a replicate sd of
0.15. That sweep is running; the report is not yet updated from it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 12:12:03 +02:00
|
|
|
The report lives in reports/tsi/ (not in this simulator folder) as a SINGLE document, named
|
|
|
|
|
README.md so it renders as the directory landing page; figure links are relative to that
|
|
|
|
|
directory, so paths resolve as-is.
|
Consolidate the TSI report into one document
The four-part split existed because the single report had grown dense
and heavily cross-referenced; splitting traded that for a different
cost, which the merged read makes visible. Section numbers (§1–§9,
Appendices A–C) were already the stable identifiers, so the parts were
a packaging choice, not a structural one.
reports/tsi/tsi-report.md is now the whole report. Parts are
interleaved back into section order — §1, §2–§5, §6, §7–§8, §9 +
appendices — which is NOT concatenation order: Part 1 carried §1, §7
and §8, so appending files in sequence would have put §7–§8 ahead of
§2. Every cross-file link collapses to an internal anchor; all 47
anchors resolve, all 37 figure embeds resolve, and no line of prose was
lost (verified by diffing normalised content lines with link targets
stripped — 0 lost, additions are the new header and table of contents).
Coherence fixes the merge exposed, all artefacts of the split:
- The roadmap paragraph described "four parts (see the index)" and is
now a section-order roadmap, with its circular self-link to §1
dropped.
- §7's figure-location note pointed readers at "the other parts". It
now names the actual sections, and it was also WRONG about three
figures: fig17/fig18/fig21 are in Appendix C and figB1/figB2 in
Appendix B, not §9. It had also never been updated for fig30–fig35.
- §9's "throughout this part" is now "throughout".
README.md becomes a proper index — a section table pointing into the
one document — rather than a list of four files.
scripts/split_report.py is deleted: a one-time migration that produced
the split, now both obsolete and pointing the wrong way.
scripts/build_html.py was already broken before this change — it still
read the report from tsi-sim-pernode/, where the files stopped living
when they moved to reports/tsi/. Retargeted at reports/tsi/ and the
single document; verified end-to-end (0 broken internal anchors, 0
unrewritten .md links, 37 images in the rendered HTML). Its output is
now gitignored, as its docstring always claimed it was.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:42:03 +02:00
|
|
|
|
Report becomes the directory README; rebuild the contents block
The report is now reports/tsi/README.md, so browsing to reports/tsi/
lands on the report itself rather than on an index that points at it.
The old index carried nothing the report lacked except the note that
report-figures/ holds the figures of record (the simulator folder does
not commit its own), which is folded into §9; its section table is
superseded by the report's own contents block. The "[Index]" self-link
in the header is replaced by the simulator link the index used to carry.
The contents block was inconsistent: §2 listed subsection titles, §3 and
§6 listed bare numbers with no titles at all, and the appendices were
crammed onto one line while their subsections went unlisted. Rebuilt
from the document's actual headings so every entry has a real title,
top-level entries carry a one-line gloss, and subsections sit indented
under their parent. It now covers all 47 anchors, including B.1-B.4 and
C.1-C.2 which were previously absent.
scripts/build_html.py follows the rename (DOCS is a single document) and
still renders clean: 47 anchors, 0 broken internal links, 0 unrewritten
.md links, 37 images.
Also adds configs/countable-vs-old-paired.yaml — the paired, 20-replicate
version of the overload grid. §3.2a now rests on a paired design while
§3.2 still rests on 5 unpaired replicates, which is why its U=1 cells at
delta_max 16 and 32 sit unresolved at t ~ 0.5 against a replicate sd of
0.15. That sweep is running; the report is not yet updated from it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 12:12:03 +02:00
|
|
|
Run: python scripts/build_html.py --all # the report
|
Consolidate the TSI report into one document
The four-part split existed because the single report had grown dense
and heavily cross-referenced; splitting traded that for a different
cost, which the merged read makes visible. Section numbers (§1–§9,
Appendices A–C) were already the stable identifiers, so the parts were
a packaging choice, not a structural one.
reports/tsi/tsi-report.md is now the whole report. Parts are
interleaved back into section order — §1, §2–§5, §6, §7–§8, §9 +
appendices — which is NOT concatenation order: Part 1 carried §1, §7
and §8, so appending files in sequence would have put §7–§8 ahead of
§2. Every cross-file link collapses to an internal anchor; all 47
anchors resolve, all 37 figure embeds resolve, and no line of prose was
lost (verified by diffing normalised content lines with link targets
stripped — 0 lost, additions are the new header and table of contents).
Coherence fixes the merge exposed, all artefacts of the split:
- The roadmap paragraph described "four parts (see the index)" and is
now a section-order roadmap, with its circular self-link to §1
dropped.
- §7's figure-location note pointed readers at "the other parts". It
now names the actual sections, and it was also WRONG about three
figures: fig17/fig18/fig21 are in Appendix C and figB1/figB2 in
Appendix B, not §9. It had also never been updated for fig30–fig35.
- §9's "throughout this part" is now "throughout".
README.md becomes a proper index — a section table pointing into the
one document — rather than a list of four files.
scripts/split_report.py is deleted: a one-time migration that produced
the split, now both obsolete and pointing the wrong way.
scripts/build_html.py was already broken before this change — it still
read the report from tsi-sim-pernode/, where the files stopped living
when they moved to reports/tsi/. Retargeted at reports/tsi/ and the
single document; verified end-to-end (0 broken internal anchors, 0
unrewritten .md links, 37 images in the rendered HTML). Its output is
now gitignored, as its docstring always claimed it was.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:42:03 +02:00
|
|
|
python scripts/build_html.py <file.md> ... # specific docs (paths relative to reports/tsi)
|
2026-07-30 18:57:10 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import re
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
import markdown
|
|
|
|
|
from pygments.formatters import HtmlFormatter
|
|
|
|
|
|
Consolidate the TSI report into one document
The four-part split existed because the single report had grown dense
and heavily cross-referenced; splitting traded that for a different
cost, which the merged read makes visible. Section numbers (§1–§9,
Appendices A–C) were already the stable identifiers, so the parts were
a packaging choice, not a structural one.
reports/tsi/tsi-report.md is now the whole report. Parts are
interleaved back into section order — §1, §2–§5, §6, §7–§8, §9 +
appendices — which is NOT concatenation order: Part 1 carried §1, §7
and §8, so appending files in sequence would have put §7–§8 ahead of
§2. Every cross-file link collapses to an internal anchor; all 47
anchors resolve, all 37 figure embeds resolve, and no line of prose was
lost (verified by diffing normalised content lines with link targets
stripped — 0 lost, additions are the new header and table of contents).
Coherence fixes the merge exposed, all artefacts of the split:
- The roadmap paragraph described "four parts (see the index)" and is
now a section-order roadmap, with its circular self-link to §1
dropped.
- §7's figure-location note pointed readers at "the other parts". It
now names the actual sections, and it was also WRONG about three
figures: fig17/fig18/fig21 are in Appendix C and figB1/figB2 in
Appendix B, not §9. It had also never been updated for fig30–fig35.
- §9's "throughout this part" is now "throughout".
README.md becomes a proper index — a section table pointing into the
one document — rather than a list of four files.
scripts/split_report.py is deleted: a one-time migration that produced
the split, now both obsolete and pointing the wrong way.
scripts/build_html.py was already broken before this change — it still
read the report from tsi-sim-pernode/, where the files stopped living
when they moved to reports/tsi/. Retargeted at reports/tsi/ and the
single document; verified end-to-end (0 broken internal anchors, 0
unrewritten .md links, 37 images in the rendered HTML). Its output is
now gitignored, as its docstring always claimed it was.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 10:42:03 +02:00
|
|
|
# The report set lives in the repo's reports/ tree, not alongside the simulator.
|
|
|
|
|
HERE = Path(__file__).resolve().parents[5] / "reports" / "tsi"
|
Report becomes the directory README; rebuild the contents block
The report is now reports/tsi/README.md, so browsing to reports/tsi/
lands on the report itself rather than on an index that points at it.
The old index carried nothing the report lacked except the note that
report-figures/ holds the figures of record (the simulator folder does
not commit its own), which is folded into §9; its section table is
superseded by the report's own contents block. The "[Index]" self-link
in the header is replaced by the simulator link the index used to carry.
The contents block was inconsistent: §2 listed subsection titles, §3 and
§6 listed bare numbers with no titles at all, and the appendices were
crammed onto one line while their subsections went unlisted. Rebuilt
from the document's actual headings so every entry has a real title,
top-level entries carry a one-line gloss, and subsections sit indented
under their parent. It now covers all 47 anchors, including B.1-B.4 and
C.1-C.2 which were previously absent.
scripts/build_html.py follows the rename (DOCS is a single document) and
still renders clean: 47 anchors, 0 broken internal links, 0 unrewritten
.md links, 37 images.
Also adds configs/countable-vs-old-paired.yaml — the paired, 20-replicate
version of the overload grid. §3.2a now rests on a paired design while
§3.2 still rests on 5 unpaired replicates, which is why its U=1 cells at
delta_max 16 and 32 sit unresolved at t ~ 0.5 against a replicate sd of
0.15. That sweep is running; the report is not yet updated from it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 12:12:03 +02:00
|
|
|
DOCS = ["README.md"] # the report IS the directory README (renders at reports/tsi/)
|
2026-07-30 18:57:10 +02:00
|
|
|
|
|
|
|
|
CSS_BASE = r"""
|
|
|
|
|
@page { size: A4; margin: 18mm 16mm 20mm 16mm; }
|
|
|
|
|
html { -webkit-print-color-adjust: exact; }
|
|
|
|
|
body { font-family: -apple-system, "Helvetica Neue", "Arial Unicode MS", sans-serif;
|
|
|
|
|
font-size: 9.5pt; line-height: 1.45; color: #1a1a1a; max-width: 100%; margin: 0; }
|
|
|
|
|
h1 { font-size: 17pt; line-height: 1.25; border-bottom: 2px solid #333; padding-bottom: 6px; }
|
|
|
|
|
h2 { font-size: 13.5pt; margin-top: 22px; border-bottom: 1px solid #999; padding-bottom: 3px;
|
|
|
|
|
page-break-after: avoid; }
|
|
|
|
|
h3 { font-size: 11pt; margin-top: 16px; page-break-after: avoid; }
|
|
|
|
|
p, li { text-align: justify; }
|
|
|
|
|
code { font-family: "SF Mono", Menlo, monospace; font-size: 8.5pt;
|
|
|
|
|
background: #f4f4f4; padding: 0 2px; border-radius: 2px; }
|
|
|
|
|
pre { background: #f4f4f4; padding: 8px 10px; border-radius: 4px; overflow-x: hidden;
|
|
|
|
|
white-space: pre-wrap; page-break-inside: avoid; }
|
|
|
|
|
pre code { background: none; font-size: 8pt; }
|
|
|
|
|
table { border-collapse: collapse; width: 100%; font-size: 8pt; margin: 10px 0; }
|
|
|
|
|
th, td { border: 1px solid #bbb; padding: 3px 5px; text-align: left; vertical-align: top; }
|
|
|
|
|
th { background: #ececec; }
|
|
|
|
|
tr { page-break-inside: avoid; }
|
|
|
|
|
img { max-width: 100%; height: auto; }
|
|
|
|
|
figure { margin: 12px 0; text-align: center; page-break-inside: avoid; }
|
|
|
|
|
figcaption { font-size: 8pt; color: #444; text-align: justify; margin-top: 4px; padding: 0 8mm; }
|
|
|
|
|
blockquote { border-left: 3px solid #999; margin-left: 0; padding-left: 12px; color: #333; }
|
|
|
|
|
hr { border: none; border-top: 1px solid #ccc; margin: 18px 0; }
|
|
|
|
|
em { color: inherit; }
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def render(md_path: Path) -> Path:
|
|
|
|
|
body = markdown.markdown(
|
|
|
|
|
md_path.read_text(),
|
|
|
|
|
extensions=["tables", "fenced_code", "sane_lists", "codehilite", "md_in_html"],
|
|
|
|
|
extension_configs={"codehilite": {"guess_lang": False}},
|
|
|
|
|
)
|
|
|
|
|
# rewrite intra-set links so the rendered HTML navigates to .html, not .md
|
|
|
|
|
body = re.sub(r'(href="[^"]*?)\.md(#|")', r"\1.html\2", body)
|
|
|
|
|
pyg = HtmlFormatter(style="default").get_style_defs(".codehilite")
|
|
|
|
|
style = (CSS_BASE + "\n.codehilite{background:#f4f4f4;border-radius:4px;}\n"
|
|
|
|
|
".codehilite pre{background:none;margin:0;}\n" + pyg)
|
|
|
|
|
html = (f"<!DOCTYPE html><html><head><meta charset='utf-8'>"
|
|
|
|
|
f"<title>{md_path.stem}</title><style>{style}</style></head><body>\n"
|
|
|
|
|
f"{body}\n</body></html>")
|
|
|
|
|
out = md_path.with_suffix(".html")
|
|
|
|
|
out.write_text(html)
|
|
|
|
|
return out
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main() -> None:
|
|
|
|
|
ap = argparse.ArgumentParser(description="Render the TSI report markdown set to HTML")
|
|
|
|
|
ap.add_argument("docs", nargs="*", help="specific .md files (default: the whole set)")
|
|
|
|
|
ap.add_argument("--all", action="store_true", help="render the index + 4 parts")
|
|
|
|
|
args = ap.parse_args()
|
|
|
|
|
targets = DOCS if (args.all or not args.docs) else args.docs
|
|
|
|
|
for d in targets:
|
|
|
|
|
p = HERE / d
|
|
|
|
|
if not p.exists():
|
|
|
|
|
print(f"skip (missing): {d}")
|
|
|
|
|
continue
|
|
|
|
|
print(f"wrote {render(p).name}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|