diff --git a/docs/explanations/2026-07-17-explanation-byox-ladder.html b/docs/explanations/2026-07-17-explanation-byox-ladder.html new file mode 100644 index 00000000..71d80df4 --- /dev/null +++ b/docs/explanations/2026-07-17-explanation-byox-ladder.html @@ -0,0 +1,366 @@ + + +
+ + +How python_pkg/byox_ladder turns the build-your-own-x README into two ranked, offline HTML pages.
build-your-own-x
+ is a hugely popular README: a curated list of ~360 step-by-step tutorials for re-creating technologies
+ from scratch — a 3D renderer, a Git, a database, an operating system. The README groups guides under
+ 30 category headings like #### Build your own `Regex Engine`, and each guide is one bullet:
* [**Go**: _Building a BitTorrent client from the ground up_](https://blog.jse.li/posts/torrent/)
+ The task was to sort all of this from easiest to hardest. This commit adds a small, + self-contained tool that does exactly that and emits two browsable pages: a category ladder + (the 30 headings) and a guide ladder (every individual tutorial), each grouped into four + difficulty tiers — Beginner, Intermediate, Advanced, Expert — plus an Unsorted bucket.
+It lives in testsAndMisc, a monorepo with strict gates: all Python must sit under
+ python_pkg/, hit 100% branch coverage, and pass ruff (select=ALL),
+ mypy, pylint 10/10, and bandit. Those gates shaped the design as much as the feature did — more on that in
+ the Code section.
The heart of the change is one question: how do you assign a difficulty to a single guide? + The naïve answer — give every guide a unique rank from 1 to 360 — is a trap. There's no honest signal that + says tutorial #147 is harder than #148. So the design deliberately refuses that false precision and uses a + two-part rule instead:
+ +rank×10 + nudge. Sorting by score keeps whole tiers
+ contiguous.Because the nudge is always under 1 and the tier gap is 10 per rank, language can reorder guides + inside a tier but can never move one across a tier line. An operating-system guide is Expert whether + it's written in C or Python; the language just decides which OS guide you might reach for first.
+ + + + +Pick a category and a language. Watch the score, the tier, and where this guide lands among the other + languages in the same category. Notice the tier badge only changes when the category changes.
+ +This widget runs the real scoring logic from parse_guides.py —
+ the same CATEGORIES and LANG_EFFORT tables, the same
+ min()-of-languages nudge, the same rank×10 + nudge score.
parse_guides.pyThe parser walks the README line by line, tracking the current category header, and turns each guide + bullet into a record. Two small pure functions carry the difficulty model:
+def lang_effort(langs):
+ # the EASIEST listed language wins — you'd pick your best one
+ values = [LANG_EFFORT.get(l.lower(), DEFAULT_EFFORT) for l in langs]
+ return min(values) if values else DEFAULT_EFFORT
+
+# inside parse_guide_line(...):
+rank, tier = CATEGORIES.get(category, (UNSORTED_RANK, "unsorted"))
+score = round(rank * 10 + lang_effort(langs), 2)
+ A guide with an unknown category falls through to UNSORTED_RANK = 99 and the
+ "unsorted" tier — that's how the repo's own "Uncategorized" bucket is kept honest instead of
+ being force-fit into a difficulty tier.
build_pages.pyThe guide page is a template with a placeholder. The builder inlines the parsed data as a JS constant and + wraps everything in a minimal HTML skeleton so the file opens straight from disk:
+payload = json.dumps(guides, separators=(",", ":")).replace("</", "<\\/")
+content = template.replace(MARKER, f"const GUIDES = {payload};")
+return standalone(content) # adds <!doctype html>…</html>
+ The replace("</", "<\\/") guard matters: the data is dropped inside a
+ <script> tag, and any literal </script> in a tutorial title would
+ otherwise close the block early. Everything is inlined — no fonts, no CDN, no network — so the page works
+ offline and in your OS light/dark theme.
A Makefile chains the pipeline; the fetched README and guides.json are
+ gitignored derived artifacts, while the built *-ladder.html pages are committed as the runnable
+ output. Re-running make build reproduces byte-identical HTML — the sign of a deterministic build.
build: guides.json
+ python3 build_pages.py
+guides.json: byox-readme.md parse_guides.py
+ python3 parse_guides.py
+byox-readme.md:
+ curl -fsSL "$(README_URL)" -o byox-readme.md
+
+ Because the code lives under python_pkg/, the repo's fail_under=100 gate applies.
+ The two functions with branches — lang_effort (empty vs non-empty) and the parse/build error
+ paths — are each exercised from both sides. lang_effort([]) is called directly to cover the
+ else branch that normal input can't reach.
The monorepo rejects any code commit that lacks a validated evidence JSON (intent, scope,
+ verification with real command output, rollback), and a contract JSON once a change spans
+ four or more code files. One line was also added to .pre-commit-config.yaml to exclude the
+ generated guide page from codespell, since it inlines upstream titles verbatim — including a genuine
+ spelling slip carried over from one of the upstream tutorial titles.
Five questions on the reasoning behind the change. Click to reveal.
+ +/explain-diff · adapts Geoffrey Litt's "understanding is the
+ bottleneck" idea. Diagrams and the widget run the change's real logic.7 explanations · interactive walkthroughs of notable changes, newest first.
+8 explanations · interactive walkthroughs of notable changes, newest first.