返回 last30days-skill
test_topic_shape.py
根目录 / tests / test_topic_shape.py
1 """U1 - deterministic name distiller and junk-shape classifier.
2
3 topic_shape is the stdlib-only, pure-function foundation for discovery's
4 content-worthy topic naming: distill_topic_name turns a listing title (+
5 optional snippet) into a short, ordered, searchable phrase, and is_junk_shape
6 flags help-me questions, beginner asks, and personal musings that should never
7 become topics. Titles below marked "real run" are verbatim from the motivating
8 2026-07 discovery run.
9 """
10
11 from lib import topic_shape
12
13 # Real run: long news headline whose subject entity ("Gemma 4") must survive.
14 GEMMA_TITLE = (
15 "Google is updating Gemma 4's chat templates, bringing major fixes to "
16 'tool calling and reducing "laziness", and enabling Flash Attention 4 '
17 "on Hopper GPUs"
18 )
19
20 # Real run: anecdote framing that must not leak into the name.
21 COWORKER_TITLE = (
22 "My coworker let an AI agent handle Slack replies while he was "
23 '"unavailable." It did not go well.'
24 )
25
26
27 # ---------------------------------------------------------------- naming ----
28
29
30 def test_distill_prefers_digit_bearing_entity_phrase():
31 name = topic_shape.distill_topic_name(GEMMA_TITLE)
32 assert "gemma 4" in name.lower()
33 assert len(name.split()) <= 6
34 # No sentence scaffolding: the verb-phrase framing must be gone.
35 assert "is updating" not in name.lower()
36 assert '"' not in name
37
38
39 def test_distill_drops_anecdote_framing():
40 name = topic_shape.distill_topic_name(COWORKER_TITLE)
41 words = name.lower().split()
42 assert not name.lower().startswith("my coworker")
43 assert "slack" in words
44 assert "ai" in words or "agent" in words
45 assert len(words) <= 6
46
47
48 def test_distill_short_title_passes_through():
49 assert topic_shape.distill_topic_name("Agent swarms economics") == "Agent swarms economics"
50
51
52 def test_distill_show_hn_launch_title():
53 name = topic_shape.distill_topic_name("Show HN: I built an open-source agent memory layer")
54 assert name == "open-source agent memory layer"
55
56
57 def test_distill_strips_interrogative_scaffolding():
58 name = topic_shape.distill_topic_name("How do I get started with LangGraph?")
59 assert "how do i" not in name.lower()
60 assert "langgraph" in name.lower()
61
62
63 # ------------------------------------------------------------ junk: true ----
64
65
66 def test_junk_beginner_help_ask():
67 # Real run.
68 assert topic_shape.is_junk_shape("I need help starting to learn about AI AGENTS")
69
70
71 def test_junk_is_anyone_question():
72 # Real run.
73 assert topic_shape.is_junk_shape(
74 "Is anyone actually orchestrating multi-agent workflows well, or are we all duct-taping?"
75 )
76
77
78 def test_junk_everyone_musing():
79 # Real run: musing shape despite capitalized entities.
80 assert topic_shape.is_junk_shape(
81 'Everyone Is "Building AI Agents" - But Do We Mean the Same Thing?'
82 )
83
84
85 def test_junk_leading_interrogative_asks():
86 assert topic_shape.is_junk_shape("How do I get started with agent frameworks")
87 assert topic_shape.is_junk_shape("Does anyone use LangGraph in production?")
88 assert topic_shape.is_junk_shape("Can someone explain MCP servers to me")
89 assert topic_shape.is_junk_shape("where do I start with local models")
90
91
92 def test_junk_trailing_question_without_entity():
93 assert topic_shape.is_junk_shape("so are we just letting agents run wild now?")
94
95
96 def test_junk_uses_snippet_only_when_title_has_no_entities():
97 assert topic_shape.is_junk_shape(
98 "getting into local models",
99 "I'm a total beginner, where do I start?",
100 )
101 # Entity-bearing title wins over a chatty snippet.
102 assert not topic_shape.is_junk_shape(
103 "Gemma 4 tool calling fixes",
104 "need help understanding the changelog",
105 )
106
107
108 # ----------------------------------------------------------- junk: false ----
109
110
111 def test_not_junk_news_shaped_statement():
112 assert not topic_shape.is_junk_shape("Agent swarms and the new model economics")
113 assert not topic_shape.is_junk_shape(GEMMA_TITLE)
114
115
116 def test_not_junk_show_hn_launch():
117 assert not topic_shape.is_junk_shape("Show HN: I built an open-source agent memory layer")
118
119
120 def test_not_junk_question_about_named_entity():
121 assert not topic_shape.is_junk_shape("Is Gemma 4 actually good?")
122
123
124 def test_not_junk_explainer_headline_with_entity():
125 assert not topic_shape.is_junk_shape("What Gemma 4 means for local inference")
126 assert not topic_shape.is_junk_shape("Why Gemma 4 flopped on Hopper GPUs")
127
128
129 # ------------------------------------------------------------ edge cases ----
130
131
132 def test_both_functions_work_with_title_alone():
133 assert topic_shape.distill_topic_name("Gemma 4 benchmarks") == "Gemma 4 benchmarks"
134 assert topic_shape.is_junk_shape("need help with my agent setup") is True
135 assert topic_shape.is_junk_shape("Gemma 4 benchmarks") is False
136
137
138 def test_distill_lowercase_no_entity_falls_back_to_truncated_title():
139 title = "thoughts on where this is all going"
140 name = topic_shape.distill_topic_name(title)
141 assert name == "thoughts on where this is all"
142 assert topic_shape.is_junk_shape(title) is True
143
144
145 def test_cjk_title_no_crash_and_passes_through():
146 title = "大模型智能体的未来发展方向"
147 assert topic_shape.distill_topic_name(title) == title
148 assert topic_shape.is_junk_shape(title) is False
149
150
151 def test_mixed_cjk_title_extracts_latin_entity():
152 name = topic_shape.distill_topic_name("谷歌 更新 Gemma 4 聊天模板")
153 assert name == "Gemma 4"
154
155
156 def test_long_unspaced_cjk_title_capped_reasonably():
157 title = "大模型" * 60 # single unspaced 180-char run
158 name = topic_shape.distill_topic_name(title)
159 assert name
160 assert len(name) <= 80
161
162
163 def test_name_never_has_trailing_punct_or_quotes():
164 cases = [
165 'Gemma 4 benchmarks are "insane"...',
166 "Agent swarms economics?!",
167 "What is the deal with agent frameworks???",
168 GEMMA_TITLE,
169 COWORKER_TITLE,
170 ]
171 for title in cases:
172 name = topic_shape.distill_topic_name(title)
173 assert name, title
174 assert name[-1] not in ".,;:!?\"'`- ", title
175 assert '"' not in name and "“" not in name and "”" not in name, title
176
177
178 def test_very_long_single_token_title_is_capped():
179 name = topic_shape.distill_topic_name("a" * 300)
180 assert name
181 assert len(name) <= 80
182
183
184 def test_url_only_title_is_safe_and_nonempty():
185 name = topic_shape.distill_topic_name("https://news.example.com/2026/07/agent-memory-layer/")
186 assert name
187 assert len(name.split()) == 1
188 assert name[-1] not in "/?.,;:!\"'"
189
190
191 def test_blank_inputs():
192 # Sole exception to the never-empty contract: no word content anywhere.
193 assert topic_shape.distill_topic_name("") == ""
194 assert topic_shape.distill_topic_name(" ", " ") == ""
195 assert topic_shape.is_junk_shape("") is True
196 # A blank title falls back to the snippet.
197 assert topic_shape.distill_topic_name("", "Gemma 4 rollout chatter") == "Gemma 4 rollout chatter"
198
198 lines PYTHON