fix: live rendering defects, dead scaffolding, and a tag taxonomy that starved related posts - #67
Merged
Conversation
/categories/ rendered "Agentic Ai". The page title-cased each word through Liquid's `capitalize`, which uppercases the first letter and lowercases the rest — so an acronym in a category name was destroyed. index.html and _layouts/post.html render the same value correctly with a one-line `replace`, which is now all this page does too: the 15-line word loop is gone, and with it the bug it existed to cause. /insights/ printed "Insights" as an <h1> (from _layouts/page.html) and then again as an <h2> on the next line. /paper-reviews/ never did this, which is what showed the heading was unnecessary rather than load-bearing. No inbound anchor referenced the id. /paper-reviews/ was also the last page emitting raw category values as heading ids (`id="Language-Models"`), against the slugify convention documented in docs/tech-doc.md §3. Nothing links to those anchors, so html-proofer could not catch the drift.
Every post is a Paper Review (28) or an Insight (7), so two of the six nav links led to "this space will fill up soon", and both pages sat in sitemap.xml offering search engines a listing with nothing on it. They keep their URLs and their content; they lose `main_nav` and gain `sitemap: false`. Their front matter records which two keys to restore, and nav_order 2 and 4 are deliberately left vacant so restoring is a one-line change when the first post of either type lands. Also drops the <h2> that repeated each page's own title, as on /insights/.
Two values that must change with the theme were pinned to light: - `<meta name="theme-color" content="#ffffff">` was unconditional, so a mobile browser kept a white address bar above a #0d1117 page. - `<meta name="color-scheme" content="light">` was too, which tells the UA to render its own widgets — scrollbar, the search field's clear button, form controls — light against that same dark page. color-scheme moves into _sass/_dark.scss keyed off data-theme, since only the stylesheet knows which theme is live and the inline bootstrap already sets the attribute before first paint. theme-color has no CSS equivalent, so the bootstrap updates it on load and the toggle updates it on click; the bootstrap had to move below the meta tag it now needs to find. Also deletes a comment claiming theme-color was "declared at top of <head> with prefers-color-scheme media queries". There were no media queries, and there is no OS-preference branch anywhere — dark is opt-in only. css/main.scss carried the same false claim about why _dark.scss is imported last.
All three translation pairs share a date exactly, so Jekyll's page.previous — which walks raw date order — sent the newest Korean post's "← Previous" to that same article in English. Verified on the live site before the change. related_posts.rb already knew both rules this needs (skip the translation twin, never cross languages), so the adjacency lives there rather than duplicating the language default in a Liquid loop: `page.adjacent_older` / `page.adjacent_newer` replace page.previous / page.next in _layouts/post.html. The shared predicate is extracted as `eligible?` and both callers use it. It steps *past* an ineligible neighbour instead of dropping the link, so the newest Korean post still gets a previous post — the AgentCore piece — and the English data-architecture post now navigates to an English neighbour instead of Korean. 9 tests cover it, including the identical-date case that produced the defect.
Each of these was identified in an earlier pass, and each time the *documentation about it* got fixed instead of the thing itself: - `_layouts/archive.html` — nothing has ever set `layout: archive`. - `simple_jekyll_search:` in _config.yml — simple-jekyll-search is a browser script and cannot read _config.yml, so the exclude list excluded nothing. Its only remaining reference was the doc noting it does nothing. A comment now records why the block is absent. - `exclude: circle.yml, stackbit.yaml` — neither file exists in the repo. - footer.html's `page.custom_js` loop — no page has ever set it; pages needing an extra asset use `head_extra`, as search.md does. - footer.html's conditional on site.ga_tracking_id — its entire body was a comment saying the tracking lives in head.html. The replacement comment in footer.html is an HTML comment that names no tag delimiters, because Liquid tokenizes tags inside comments too: naming one in prose opens it for real and fails the build. That cost two builds to learn.
The workflow triggered on pushes to main alone, so the four gates — plugin tests, build, html-proofer, validate-site — reported on a bad change only once it had already landed. Nine PRs merged in one day were each validated post-merge. The blast radius was bounded (deploy needs: build, so a failure meant no deploy rather than a broken site) but main was left red. Adds a pull_request trigger on main and skips the two publishing steps — artifact upload and the deploy job — for PR events.
Tags described one paper's contribution each — "Dependency-Aware-Tree-Traversal", "Leiden-Algorithm-For-Text" — which is a precise paper index and a useless graph: 220 of 264 tags were used by exactly one post. Since _plugins/related_posts.rb requires a *shared* tag, 11 posts shipped with no "Related reading" block, among them RAPTOR, GraphRAG, LightRAG and Zep — four graph-retrieval papers with not one tag in common. The Insights cluster failed the same way by calling one topic three names: Agentic-Architecture, Agentic-Patterns, Agentic-Infrastructure. The fix belongs in the data, not the ranking rule. Loosening the rule to relate on category alone is what put LLaMA under DeepSeek-V3 with nothing in common, and that strictness was asked for deliberately. Nine topic tags, each landing on 3-8 posts: Agentic-AI, Alignment, DeepSeek, Knowledge-Graph, Llama, Mixture-of-Experts, Multimodal-Models, Reasoning-Models, Retrieval-Augmented-Generation. Also folds MCP into Model-Context-Protocol, which were the same tag spelled two ways. Nothing is removed, so no live /tags/ anchor moves. All 35 posts now get suggestions (31 with a full three), where 11 got none. Ordering is unaffected: score is shared-tag count, so posts that share a specific tag still outrank posts sharing only the topic. The two Llama posts' wrapped `tags:` blocks are normalised to one line, matching the other 33.
- Both READMEs and docs/tech-doc.md §3 gain the two-layer tag convention, with the controlled topic list and the reason it exists. - The nav table drops the two empty sections and explains the vacant nav_order slots, so the gap does not read as an oversight. - The dark-mode row names the two theme-dependent values that live outside CSS. - The CI section documents the pull_request trigger. - Corrected two stale claims: search.json is 3.2 MB / 991 KB gzip (measured), not 2.7 MB / 786 KB, and the `simple_jekyll_search.exclude` block it described as inert is now gone rather than merely inert. - Added the known search limitation: the index is the full body but the result card shows only a fixed 40-word head snippet, so a match deep in a long post is invisible and unhighlighted.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A fresh adversarial pass over the areas the last round did not touch — the four
listing pages,
search.json/search.js, the CI trigger, and the tag vocabulary.Findings were verified against the live site with real requests, not inferred.
Two defects that were live in production
/categories/rendered "Agentic Ai". The page title-cased each word throughLiquid's
capitalize, which uppercases the first letter and lowercases therest.
index.htmland_layouts/post.htmlrender the same value correctlywith a one-line
replace. Deleting the 15-line loop removes the bug and thecode that caused it.
Three of the four listing pages printed their own title twice —
<h1>Insights</h1>followed by
<h2>Insights</h2>./paper-reviews/never did, which is whatshowed the heading was not load-bearing. Same defect class as the leading
#removed from 35 posts last round.
The highest-leverage finding: the tag layer
Tags described one paper's contribution each, so 220 of 264 were used by
exactly one post.
related_posts.rbrequires a shared tag, so 11 postsshipped with no "Related reading" at all — including RAPTOR, GraphRAG, LightRAG
and Zep, four graph-retrieval papers with not one tag in common. The Insights
cluster failed the same way by calling one topic three names
(
Agentic-Architecture/Agentic-Patterns/Agentic-Infrastructure).Fixed in the data, not the ranking rule — loosening the rule is what once put
LLaMA under DeepSeek-V3 with nothing in common. Nine topic tags, each on 3–8
posts, added on top of the existing ones. Nothing removed, so no live
/tags/anchor moves.
All 35 posts now get suggestions (31 with a full three), where 11 got none.
Ordering is unaffected: score is shared-tag count, so a shared specific tag still
outranks a shared topic tag.
Also fixed
translation pairs share a date, so
page.previoussent the newest Koreanpost's "← Previous" to that same article in English. Moved into
related_posts.rb, which already knew both rules (skip the twin, don't crosslanguages); it now steps past an ineligible neighbour instead of dropping the
link. 9 new tests.
theme-colorandcolor-schemewere both pinned to light, so a mobile address bar stayed whiteabove a
#0d1117page and UA widgets rendered light. Also removed a commentclaiming
theme-colorusedprefers-color-schememedia queries — there werenone, and dark is opt-in only.
_layouts/archive.html(nothing sets
layout: archive), the inertsimple_jekyll_search:block, twoexclude:entries for files that don't exist, and two no-op conditionals infooter.html. The last pass fixed the docs about these instead of removingthem.
pull_requesttrigger, so thefour gates ran only after a push to main; nine PRs merged in one day were each
validated post-merge. Now runs on PRs, with publishing steps skipped.
(7), so two of six nav links led to "this space will fill up soon" and both
pages sat in the sitemap. URLs kept;
main_navdropped,sitemap: falseadded,with the restore instructions in each file's front matter.
Hypotheses checked and dropped
Raw TeX in search snippets (0 of 35); prev/next chronological direction (correct);
dark-mode FOUC (already bootstrapped before paint);
head_extraunrendered (itis rendered); hero image bloat (116 KB); Bourbon/Neat's ~120 vendored partials
(mixin-only, emit no CSS — not dead weight).
Corrections to earlier claims
search.jsonis 3.2 MB / 991 KB gzip, measured — the docs said 2.7 MB /786 KB. And the tag counts are 264 distinct / 220 singletons, not the
250/210 first reported: the two Llama posts use a wrapped
tags:block that asingle-line grep had skipped, so the problem was slightly worse than stated.
Known limitation, now documented rather than fixed
Search indexes the full body but the result card shows a fixed 40-word head
snippet, so a match at character 50,000 is invisible and unhighlighted. Fixing it
needs a match-centred snippet, outside the library's template.
Verification
All four gates green on the final tree: 82 tests / 136 assertions, clean
build,
HTML-Proofer finished successfully,All checks passed(16 checks).Each change was also confirmed in the rendered output — "Agentic AI", no
duplicated titles, nav down to four links, the two pages absent from
sitemap.xml,color-schemecompiled for both themes, the Korean data post's"Previous" now the AgentCore piece, and the four graph-RAG papers recommending
each other.
One regression was caught mid-work by
validate-site.shitself: my explanatorycomments contained the literal string
<h1>, which the "exactly one h1 per page"check counts in the served markup. Rewritten as Liquid comments that ship nothing.