diff --git a/_data/post_conventions.yml b/_data/post_conventions.yml index a92475b..a6d860f 100644 --- a/_data/post_conventions.yml +++ b/_data/post_conventions.yml @@ -48,8 +48,9 @@ math: defined_macros: [llbracket, rrbracket, textsc] tags: - # Every post carries at least one: it is what _plugins/related_posts.rb joins - # posts on. A tag only one paper can have connects nothing. + # A post carries one when one names its topic: it is what + # _plugins/related_posts.rb joins posts on. A tag only one paper can have + # connects nothing. controlled: - Agentic-AI - Alignment diff --git a/_plugins/related_posts.rb b/_plugins/related_posts.rb index 2fae0c4..b49fc9e 100644 --- a/_plugins/related_posts.rb +++ b/_plugins/related_posts.rb @@ -19,8 +19,8 @@ # better than a wrong suggestion. # # That strictness depends on tags that can meet. Per-paper contribution tags -# rarely do, so each post should also carry a controlled topic tag (the list is -# `tags.controlled` in _data/post_conventions.yml) — a looser rule here is not the fix for a post with no suggestions. +# rarely do, so a post should also carry a controlled topic tag that fits it +# (the list is `tags.controlled` in _data/post_conventions.yml) — a looser rule here is not the fix for a post with no suggestions. # # Jekyll's built-in site.related_posts is either "the 10 most recent posts" or # LSI, which needs the classifier gem and a slow indexing pass. This is cheaper diff --git a/docs/writing.md b/docs/writing.md index 74520d0..2630128 100644 --- a/docs/writing.md +++ b/docs/writing.md @@ -155,11 +155,12 @@ Tags are free-form and hyphenated, and come in two layers: - **Specific tags** name the post's own contribution (`Fine-Grained-Expert-Segmentation`). Precise, but they connect nothing. -- **At least one controlled topic tag** from `tags.controlled` in - `_data/post_conventions.yml`. "Related reading" needs a shared tag, so a post - with only specific tags ships without it. +- **A controlled topic tag** from `tags.controlled` in + `_data/post_conventions.yml`, when one fits. "Related reading" needs a shared + tag, so a post with only specific tags ships without it; that is better than + a topic tag the post is not about, which suggests unrelated posts. -Add the topic tag; don't swap it for the specific ones. Reuse an existing tag +Add the topic tag that fits; don't swap it for the specific ones. Reuse an existing tag before coining one: three names for one idea leave every post with a tag no other post shares. When two tags turn out to be one, keep one and move the other to `tags.aliases`; the lint then rejects the retired name. Renaming a tag diff --git a/script/lint-posts.rb b/script/lint-posts.rb index e7cc15c..5eebc7f 100644 --- a/script/lint-posts.rb +++ b/script/lint-posts.rb @@ -185,7 +185,7 @@ def self.tags(post, spec) rules = spec["tags"] tags = Array(post.data["tags"]).map(&:to_s) found = [] - found << "1: no controlled topic tag (one of #{rules["controlled"].join(", ")})" if (tags & rules["controlled"]).empty? + found << "1: no tags" if tags.empty? tags.each do |tag| if (replacement = rules["aliases"][tag]) found << "1: tag #{tag} is retired; use #{replacement}" diff --git a/test/test_lint_posts.rb b/test/test_lint_posts.rb index 3490def..14f91a3 100644 --- a/test/test_lint_posts.rb +++ b/test/test_lint_posts.rb @@ -97,9 +97,14 @@ def test_rejects_an_unknown_topic_and_a_wrong_cover assert_finding(/cover for Paper Reviews/, lint(front: FRONT.sub("language-models.jpg", "default.jpg"))) end - def test_tags_need_a_controlled_tag_and_current_well_formed_names + def test_a_post_needs_tags_but_not_a_controlled_one + assert_finding(/no tags/, lint(front: FRONT.sub(/^tags:.*$/, "tags: []"))) + found = lint(front: FRONT.sub('"Efficient-Attention"', '"Multi-Token-Prediction"')) + refute found.any? { |f| f.include?("tag") }, found.inspect + end + + def test_tags_need_current_well_formed_names found = lint(front: FRONT.sub('"Efficient-Attention"', '"Sparse-Mixture-of-Experts", "Public-Dataset-Only Training", "Community-Detection-For-RAG"')) - assert_finding(/no controlled topic tag/, found) assert_finding(/retired; use Mixture-of-Experts/, found) assert_finding(/joined by hyphens/, found) assert_finding(/should have for/, found)