feat(events-crawler): widen relevance to digital-skills content - #96
Conversation
The filter missed content that is plainly on-mission because libraries
title it by product or program name rather than by the category words
the filter knew. Adds, all evidence-driven from a full capture of every
filtered source's 4-month window:
- tech(nology)? (cafe|help|support) — "One on One Technology Help" and
"Drop-in Technology Help" never matched `tech (help|support)`. This is
the largest miss, 21 rows across Surrey and NVCL, and was not in the
backlog entry that prompted this work.
- laptop help — "Windows laptop help", "Mac laptop help".
- Qualified office-suite terms — NVCL's "MS Office learn and practice:
Intro to Word". Every office word sits behind `ms`, `microsoft` or
`intro to`: the bare forms are traps the live feeds actually contain
("Excel in Your Studies", "Crossword Club", "Wordplay for Toddlers",
"PowerPoint Karaoke Night").
- open door (community|drop) — the Open Door community hub, NVCL's and
NVDPL's shared newcomer drop-in, 29 rows. Qualified so it cannot catch
"Open Door Poetry Reading" or "Open Doors Heritage Tour".
Measuring this needed an instrument, so dryrun.ts gains --no-filter (runs
the adapter against a copy of the Source with relevanceFilter off) and
--titles (one KEEP/DROP line per row). A normal dry run only shows what
already passed, while the whole question is what a new term would let in.
No adapter changes — they already read source.relevanceFilter — and the
harness stays write-free.
Measured across all 845 rows / 395 distinct titles of the seven filtered
sources: 9 distinct titles (56 rows) flip DROP -> KEEP, nothing lost. A
term here is a union alternative, so it can only add keeps.
relevance_test.ts locks in every target and its near-misses. The bare
`\bword\b` hazard was previously recorded in BACKLOG.md prose, which
cannot fail a run.
Also corrects a stale figure in BACKLOG.md: NVCL's window is 61 distinct
titles of which the filter already kept 10, not 27 keeping none. The old
measurement was truncated by MAX_PER_ORG stopping the unfiltered walk
after ~2 pages, so it only saw August storytimes, not September's
settlement programming.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedNo new commits to review since the last review. ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThe events crawler now supports broader settlement-title matching, regression tests, and dry-run inspection modes. The backlog records relevance-pass results, corrected NVCL scan statistics, deliberate exclusions, and future testing guidance. ChangesEvents crawler relevance
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@supabase/functions/events-crawler/lib/relevance.ts`:
- Line 65: Update the relevance pattern in relevance.ts at lines 65-65 to add a
left word boundary before the tech(nology)? alternative, preventing matches
within longer words such as “Biotech.” Add a DROP fixture in relevance_test.ts
at lines 87-93 covering tech embedded in a longer word.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 66a67fb4-6e3b-4f0e-9473-3a0782172d1e
📒 Files selected for processing (4)
BACKLOG.mdsupabase/functions/events-crawler/dryrun.tssupabase/functions/events-crawler/lib/relevance.tssupabase/functions/events-crawler/lib/relevance_test.ts
CodeRabbit on PR #96, valid. `tech(nology)?\s+(cafe|help|support)` matched the tail of "Biotech Help" and "Fintech Support" — both plausible titles at SFU, which is in the filtered source set. The boundary was already missing on the narrower `tech` this widened, so this fixes a pre-existing hazard rather than one the widening introduced. Unlike adding an alternative, adding `\b` NARROWS the regex, so it can drop a keep and the monotonicity argument doesn't cover it. Re-verified against the same captured corpus: still 9 distinct titles / 56 rows flipping DROP -> KEEP and 0 previously-kept titles lost, so nothing in the live feeds moves. It is hardening against titles the sources haven't produced yet. Test gains the three near-misses, marked as constructed rather than captured so the next reader doesn't go looking for them in a feed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Applied in One thing your suggestion is right about that the PR body's reasoning does not cover: adding Identical to before the change across all 845 rows / 395 distinct titles — nothing in the live feeds moves either way. It's hardening against titles the sources haven't produced yet. Added the three near-misses to // `tech` inside a longer word — the reason the alternative carries a leading `\b`.
// Constructed rather than captured: plausible SFU titles, not yet seen in a feed.
'Biotech Help',
'Fintech Support',
'Edtech Café',
|
|
@coderabbitai full review |
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai full review |
|
|
| time (UTC) | request | outcome |
|---|---|---|
| 02:07:54 | full review |
|
| 03:11 | review |
never posted (tooling error on my side) |
| 03:42:01 | review |
no-op — "Review finished" in 5s, no review object, no quota consumed ("does not re-review already reviewed commits") |
| 03:45:31 | full review |
The free-tier OSS review budget is exhausted after the #86–#96 run. This is a quota wall, not a signal about the code.
Merged anyway on Luis's explicit instruction, for time reasons — this needs to be deployed ahead of the Monday 14:00 UTC crawler cron, and the next genuine review window is ~04:41 UTC at the earliest given tonight's pattern.
Self-verification standing in for the second review:
deno test supabase/functions/events-crawler/lib/relevance_test.ts— 2/2 pass, including the three newBiotech Help/Fintech Support/Edtech CaféDROP fixtures added for exactly this findingdeno check— clean across all 17 crawler filesnpx tsc --noEmit— exit 0- The fix re-verified against the full captured corpus (845 rows / 395 distinct titles, all seven filtered sources' 4-month windows): 9 titles / 56 rows flip DROP → KEEP, 0 lost — byte-identical to the pre-fix result
That last one is the load-bearing check. Adding \b narrows the regex, so the "a union alternative can only add keeps" argument used in the PR description does not cover it — it could in principle have dropped a keep. Re-running the corpus confirms it drops nothing that any live feed currently produces; it only hardens against titles the sources haven't published yet.
Follow-up: if CodeRabbit's queue frees up, a post-merge review of 40a1ac4 against main is still worth running.
|
@coderabbitai review |
|
What & why
lib/relevance.tsmissed content that is plainly on-mission because libraries title it by product or program name rather than by the category words the filter knew. Closes theBACKLOG.mddigital-skills entry.Filter-only change plus the instrument needed to measure it. No adapter, schema, migration, cron or
next.config.tschange, and no source is enabled or disabled here.🛑 Merging this does NOT go live
The deployed function is v7, which predates this. Merging changes what a future deploy would ship. Deploy is a separate, separately-approved step.
The terms
tech(nology)?\s+(cafe|help|support)open\s+door\s+(community|drop)\bms\s+…/microsoft\s+…/intro(duction)?\s+to\s+…/\bspreadsheetlaptop\s+helpThe
technologymiss was the largest, and it was not in the backlog entry that prompted this work — the capture found it.Every office word is qualified behind
ms/microsoft/intro to. The bare forms are traps the live feeds actually contain:\bexcel\b→ "Excel in Your Studies",\bword\b→ "Crossword Club" / "Wordplay for Toddlers",\bpowerpoint\b→ "PowerPoint Karaoke Night".How this was measured
A normal dry run only shows titles that already passed, while the whole question is which rejected titles a new term lets in. So
dryrun.tsgains:--no-filter— runs the adapter against{ ...source, relevanceFilter: false }, i.e. the source's whole calendar. No adapter changes; they already readsource.relevanceFilter. The registry is copied, not mutated, and the harness has no Supabase import — still write-free.--titles— oneKEEP/DROPline per row.n/afor sources that are never filtered, so a settlement agency's rows can't be misread as excluded.Captured all seven filtered sources' full 4-month windows (
MAX_PER_ORGraised locally for the capture only —constants.tshas no diff in this PR).Result: 845 rows / 395 distinct titles → 9 distinct titles (56 rows) flip DROP → KEEP, 0 lost. Nothing else moved. A term here is a union alternative, so it can only add keeps — the entire regression surface is false positives, and there are none.
All 9 flipped titles
Forecast at the real cap of 25
So on the next deploy one live source changes: nvdpl, +9 rows.
New:
lib/relevance_test.tsThe repo has no tests today, so this is a new pattern. It earns its place:
isSettlementRelevantis a pure function shared by every filtered source, and the\bword\bhazard was previously recorded inBACKLOG.mdprose, which cannot fail a run. 26 real titles that must KEEP, 29 near-misses that must DROP — every string captured from a live feed.Backlog correction
The entry claimed NVCL's whole 4-month window was 27 titles matching none, for 0 rows. Re-measured untruncated: it is 61 distinct titles and the filter already kept 10 (an
English Cornerseries). The old figure was taken withMAX_PER_ORGat 25, which stops the unfiltered walk after ~2 pages — it only ever saw August's storytimes, not September's settlement programming. So NVCL was never going to ship 0 rows.Verification
deno test— 2/2 passdeno check— clean on all 17 crawler filesnpx tsc --noEmit— exit 0eslint— unaffected;supabase/functions/**is ignored (eslint.config.mjs:17)🤖 Generated with Claude Code
Summary by CodeRabbit