Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions _data/post_conventions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions _plugins/related_posts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions docs/writing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion script/lint-posts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
9 changes: 7 additions & 2 deletions test/test_lint_posts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down