Project Overview
repurpose-engine is a single-source content repurposing tool: one blog post, transcript, or voice-memo dump goes in, and six platform-native versions come out — X, LinkedIn, Reddit, newsletter, YouTube Shorts caption, and Instagram. It's built for solo/part-time creators who don't have time to manually reformat the same idea six different ways. Scope is deliberately narrow: text transformation only, no video/audio editing, no analytics, no team features.
Bug Fix or Performance Improvement
Stress-testing the content-validity gate (is_valid_content, the function that decides whether source text is even worth generating from) turned up three real bugs — and the most interesting part isn't any single one of them, it's that the fix for the first bug directly caused the second.
Punctuation-only transcript residue passed through as valid content. The original check was just bool(stripped) — any non-empty string counted as valid. Feed it a transcript that reduced to "... - -- ," after cleanup and it happily generated six platform posts out of nothing.
The fix for that bug broke emoji-only content. The obvious next step — reject anything with no real characters, via any(c.isalnum() for c in stripped) — correctly fixed the punctuation case. But emoji aren't alphanumeric either, so a legitimate reaction-only post ("🔥🔥🔥") started getting silently rejected as "empty."
Separately, the filler-word regex mishandled comma-attached tics. \blike\b correctly matched and removed the word "like," but left the trailing comma behind on discourse-marker usage ("So, like, I think..."), producing visible artifacts like "So,, I think..." in the cleaned output.
**
Code**
The final, correct validity check — accepts emoji-only content, rejects punctuation-only residue:
`-def is_valid_content(text: str) -> bool:
- """Reject empty source content before generating anything."""
- stripped = text.strip()
- return bool(stripped)
+def is_valid_content(text: str) -> bool:
+ """Reject empty/junk source content before generating anything."""
+ stripped = text.strip()
+ if not stripped:
+ return False
+ if EMOJI_RE.fullmatch(stripped):
+ return True
+ if PUNCT_ONLY_RE.match(stripped):
+ return False
+ return True`
The filler-word fix:
`FILLER_PATTERNS = [
r"\bum+\b", r"\buh+\b", r"\bahh?\b", r"\berr?\b",
r"\byou know\b", r"\bkind of\b", r"\bsort of\b",
- r"\blike\b",
+ r"\blike,\s*",
]`
Full three-commit history: zowskyy/repurpose-engine
0611a7c — naive baseline (has both bugs)
d362bb2 — fixes punctuation-only residue; introduces the emoji regression as a side effect
d76f48d — fixes the emoji regression and the filler-comma bug
My Improvements
The interesting engineering decision here isn't the final fix — it's the order the emoji check runs in. EMOJI_RE.fullmatch is checked before PUNCT_ONLY_RE.match, not after, because emoji characters are non-word characters in regex terms (\W), so a punctuation-only pattern like ^[\W]+$_ would also match a string of emoji. If the checks ran in the other order, the punctuation rule would swallow the emoji case right back into rejection — the exact bug we were trying to fix, just reintroduced by a different code path.
I verified all three bug states empirically rather than trusting my read of the code: I ran punctuation-only and emoji-only strings through each of the three historical versions of is_valid_content (naive, alnum-only, and final) and confirmed the naive version wrongly accepts punctuation, the alnum-only version wrongly rejects emoji, and only the final version gets both right. Same for the filler regex — ran a transcript with a comma-attached "like," tic through the before and after versions and confirmed the artifact ("So,,") only appears in the unfixed version.
The broader lesson, consistent with the other submission I'm making for this challenge: a fix that looks obviously correct for the case that motivated it can still be wrong for a case you didn't think to test. any*(c.isalnum())* is a completely reasonable first instinct for "reject junk text" — it's still wrong for anything Unicode that isn't a letter or digit. The value of stress-testing isn't finding the bug you already suspect; it's finding the one your fix for that bug just created.
Top comments (0)