fix(T-33): alert when the curator matches none of the repos it was given - #28
Merged
Merged
Conversation
An empty curation was logged as "⏭️ No repos curated — skipping send and save." and treated as a quiet day. It cannot be one: collectTopRepos returns null when nothing is trending and never an empty array, so curateOrNotify always receives at least one repo. An empty result can only mean the curator matched none of them. That happens in mergeSummaries, which drops any repo the model did not echo back by exact name. Only prose in the prompt asks for exact names, and the response stays schema-valid either way — so the retry loop never saw it. curateNode retries on a parse error or a schema mismatch, and this is neither. An empty curation is now a retryable error carrying the exact name the model failed to match, so the existing retry and alert machinery applies. Verified against three ordinary reformattings: owner dropped attempts=2 curated=null → notifyError fires title-cased attempts=2 curated=null → notifyError fires whitespace padded attempts=2 curated=null → notifyError fires exact (control) attempts=1 curated 2 Previously every one of those was attempts=1 with no digest and no alert. A model that corrects its names on the retry now recovers and the digest goes out. The dead `!curated.length` branch in curateOrNotify is removed — runCuratorGraph now returns null or a non-empty array. Closes #27 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F5CmYPdQcMeLzzJc3iDQ2u
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F5CmYPdQcMeLzzJc3iDQ2u
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.
Closes #27
The bug
An empty curation was logged at info level as a routine skip:
It cannot be a routine skip.
collectTopReposreturnsnullwhen nothing is trending and never an empty array, socurateOrNotifyalways receives at least one repo. An empty result can only mean the curator matched none of them — total failure, classified as a non-event.The failure comes from
mergeSummaries, which drops any repo the model did not echo back by exact name. Only prose in the prompt asks for that, andwithStructuredOutputkeeps the response schema-valid either way — so the retry loop never saw it.curateNoderetries on a JSON parse error or a schema mismatch, and this is neither.Net effect on an unattended morning run: no digest, no rows, no alert, no retry — and it looks identical in the logs to a genuinely quiet day.
The fix
An empty curation is now a retryable error carrying the exact name the model failed to match, so the retry and alert machinery that already exists applies to it. One condition in
curateNode; no new plumbing.The dead
!curated.lengthbranch incurateOrNotifyis removed, sincerunCuratorGraphnow returnsnullor a non-empty array. The comment that asserted the false premise is corrected.Verification
Ran the real
mergeSummariesand the realrunCuratorGraphagainst three ordinary LLM reformattings:next.js(owner dropped)curated=null→ alertVercel/Next.js(title-cased)curated=null→ alert" vercel/next.js "(padded)curated=null→ alertRecovery also works. When the model corrects itself on the retry, the digest goes out instead of vanishing:
pnpm test— 73 pass (2 new),pnpm tscandpnpm format:checkcleanDeliberately not in scope
A partial mismatch still shrinks the digest silently. Issue #27 explicitly excludes it, and it may well be acceptable behaviour — worth deciding separately rather than bundling here.
🤖 Generated with Claude Code