Skip to content

fix(events-crawler): stricter relevance for NVCL and Capilano - #100

Merged
ltanafranca1004 merged 2 commits into
mainfrom
fix/relevance-strict-nvcl-capilano
Aug 10, 2026
Merged

fix(events-crawler): stricter relevance for NVCL and Capilano#100
ltanafranca1004 merged 2 commits into
mainfrom
fix/relevance-strict-nvcl-capilano

Conversation

@ltanafranca1004

@ltanafranca1004 ltanafranca1004 commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Why

Savar's 2026-08-09 review of the widened relevance output flagged that NVCL's and Capilano's generic tech-help content is too broad — "Drop-in technology help", "Windows/Mac laptop help", "MS Office: Intro to Word/Excel". His reasoning: the audience already knows how to use a smartphone/laptop, so generic tech-help doesn't serve them the way immigration/settlement content does. Confirmed with him directly, including dropping the MS Office / spreadsheet suite — not an assumption.

His guidance was explicit: don't loosen uniformly across all orgs — a stricter filter for specific organizations is fine. A plain revert of last week's loosening (PR #96) can't work, because the main offender term technology help is shared with Surrey (21 rows across Surrey + NVCL), and no one flagged Surrey.

What

A per-source strict filter:

  • lib/relevance.ts splits the single union into CORE_TERMS (status/settlement, language, employment, finance, housing, named programs, health) + DIGITAL_LITERACY_TERMS. isSettlementRelevant(title, { strict }) uses CORE only under strict. Alternation order doesn't affect .test(), so the default union is byte-equivalent to before.
  • Source.strictRelevance (lib/types.ts) gates it, set on nvcl + capilano (lib/sources.ts).
  • All 7 adapters + dryrun.ts forward the flag; dryrun --list / --titles now reflect strict.

Also folds in the latent left-word-boundary fixes from BACKLOG (a global hardening, opposite failure direction — titles the filter wrongly keeps): a leading \b on lease, rental, tenant, resume, plus renting (swallowed by "parenting") which the original sweep missed. Zero live incidence today.

Evidence

Captured every filtered source's whole 4-month window with dryrun.ts --no-filter --titles (cap raised locally), before vs after:

Source Flips
nvcl 13 rows KEEP→DROP — all 6 distinct digital titles; keeps English Corner ×3, newcomer circletime, Open door community hub
capilano 0 (its one on-mission item, the International Student Orientation, matches a core term)
westvan, vpl, sfu, nvdpl, surrey 0

The \b fixes produced 0 flips on any source (zero live incidence). Regex alternative-set diff: 84 before → 84 after, only the 5 \b changes moved — nothing lost in the split.

Tests / checks

  • deno test lib/relevance_test.ts4/4 pass (2 new strict tests + boundary DROP fixtures paired with real-word keeps).
  • deno check clean. (supabase/functions is excluded from the Next tsc/eslint gates.)

Scope / deploy

  • Code-only. Does not deploy the edge function or activate the crawler — nvcl/capilano are not live in production yet (deployed function predates PR feat(events-crawler): enable NVCL and Capilano #97). Deployment/activation stays the separate Savar-coordinated shared-infra step.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added configurable strict relevance filtering for event sources.
    • Enabled stricter filtering for NVCL and Capilano to prioritize settlement-related events.
    • Updated dry-run results to show each source’s relevance-filtering mode.
  • Bug Fixes

    • Improved title matching with proper word boundaries.
    • Prevented unrelated words containing housing or resume terms from being incorrectly classified as relevant.
    • Added support for additional relevant housing terminology.
  • Tests

    • Expanded coverage for strict filtering, boundary matching, housing terms, and digital-literacy events.

Savar's 2026-08-09 review flagged that NVCL's and Capilano's generic
tech-help content (Drop-in technology help, Windows/Mac laptop help,
MS Office: Intro to Word/Excel) is too broad — it teaches skills the
audience already has, unlike immigration/settlement content. Confirmed
with him directly, including dropping the MS Office / spreadsheet suite.

Rather than revert last week's loosening globally (the technology-help
term is genuine, wanted content at Surrey, which no one flagged), add a
per-source STRICT filter: relevance.ts splits into CORE_TERMS and
DIGITAL_LITERACY_TERMS, and isSettlementRelevant(title, { strict }) uses
CORE only. Sources opt in via Source.strictRelevance, set on nvcl +
capilano. The default union is byte-equivalent to before, so the other
sources are unaffected.

Verified with dryrun --no-filter --titles over every filtered source's
whole window (cap raised locally): NVCL drops 6 distinct digital titles
(13 rows) and keeps its 5 genuine ones (English Corner x3, newcomer
circletime, Open door community hub); Capilano unchanged; the other five
filtered sources have zero flips.

Also folds in the latent left-word-boundary fixes from BACKLOG (a global
regex hardening, opposite failure direction): a leading \b on lease,
rental, tenant, resume — plus renting (swallowed by "parenting"), which
the original sweep missed. Zero live incidence, so zero flips on any
source; locked in relevance_test.ts as DROP fixtures paired with
real-word keeps. Re-verified the alternative set: only these 5 \b changes
moved, nothing dropped in the split.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
web-app Ready Ready Preview Aug 10, 2026 12:39am

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: de24d185-3200-4059-a36e-9b948bc60987

📥 Commits

Reviewing files that changed from the base of the PR and between 3ad4b00 and 9c5697d.

📒 Files selected for processing (2)
  • supabase/functions/events-crawler/lib/relevance.ts
  • supabase/functions/events-crawler/lib/relevance_test.ts

Walkthrough

The crawler now supports per-source strict relevance filtering. NVCL and Capilano use settlement-only matching. Relevance terms include word boundaries, and tests cover accent folding, substring false positives, and strict-mode behavior.

Changes

Relevance filtering

Layer / File(s) Summary
Relevance matching and validation
supabase/functions/events-crawler/lib/relevance.ts, supabase/functions/events-crawler/lib/relevance_test.ts
The matcher separates settlement and digital-literacy terms, adds strict mode, and applies word boundaries. Tests cover accent folding, substring rejection, and strict-mode results.
Source configuration and crawler integration
supabase/functions/events-crawler/lib/types.ts, supabase/functions/events-crawler/lib/sources.ts, supabase/functions/events-crawler/adapters/*, supabase/functions/events-crawler/dryrun.ts
Sources can configure strict relevance. NVCL and Capilano enable it. Adapters and dry-run output pass and display the setting.
Backlog validation record
BACKLOG.md
The backlog records strict-filtering results, resolved word-boundary findings, the renting case, fixtures, and corpus verification.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • UnifyCN/web-app#84: Introduced the relevance logic and adapter call sites extended by this change.
  • UnifyCN/web-app#99: Documented the relevance false-positive issues addressed by the boundary fixes.
  • UnifyCN/web-app#94: Introduced the Capilano integration updated for strict relevance.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: stricter relevance filtering for NVCL and Capilano.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/relevance-strict-nvcl-capilano

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 76: Remove or qualify the bare literacy term in CORE_TERMS within
supabase/functions/events-crawler/lib/relevance.ts:76-76 so STRICT_RELEVANCE_RE
excludes digital-literacy titles while preserving intended qualified matches.
Add a Digital Literacy title to STRICT_FLIP in
supabase/functions/events-crawler/lib/relevance_test.ts:168-190 to verify the
strict-mode behavior.
🪄 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: 36af5db0-7b7f-4e84-8489-c7ea8282c8c9

📥 Commits

Reviewing files that changed from the base of the PR and between 451fc7a and 3ad4b00.

📒 Files selected for processing (13)
  • BACKLOG.md
  • supabase/functions/events-crawler/adapters/bibliocommons.ts
  • supabase/functions/events-crawler/adapters/capilano.ts
  • supabase/functions/events-crawler/adapters/communico.ts
  • supabase/functions/events-crawler/adapters/livewhale.ts
  • supabase/functions/events-crawler/adapters/nvcl.ts
  • supabase/functions/events-crawler/adapters/surrey.ts
  • supabase/functions/events-crawler/adapters/tribe.ts
  • supabase/functions/events-crawler/dryrun.ts
  • supabase/functions/events-crawler/lib/relevance.ts
  • supabase/functions/events-crawler/lib/relevance_test.ts
  • supabase/functions/events-crawler/lib/sources.ts
  • supabase/functions/events-crawler/lib/types.ts

Comment thread supabase/functions/events-crawler/lib/relevance.ts Outdated
…iteracy"

CodeRabbit caught a completeness gap in strict mode: bare `literacy` in
CORE_TERMS (kept for Family/Adult reading literacy) also matches "Digital
Literacy", so STRICT_RELEVANCE_RE would re-admit exactly the digital-literacy
content strict is meant to drop. Latent — no such title in the current
NVCL/Capilano windows, so the corpus diff didn't surface it — but real.

Add a `(?<!digital\s)` guard to the term. The default filter still keeps
"Digital Literacy" via its own `digital literacy` term, so default verdicts are
unchanged (re-verified: zero flips on every non-strict source, NVCL still 13,
identical to the pre-fix capture). Lock both directions in relevance_test.ts:
"Digital Literacy Basics" as a STRICT_FLIP, "Adult Literacy Program" as a
STRICT_KEEP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ltanafranca1004

Copy link
Copy Markdown
Collaborator Author

Addressed the literacy finding in 9c5697d — valid catch. Bare literacy (kept for Family/Adult reading literacy) also matched "Digital Literacy", so the strict regex would have re-admitted the very digital-literacy content strict is meant to drop. Latent only (no such title in the current NVCL/Capilano windows), but real.

Fix: added a (?<!digital\s) guard to the term. The default filter still keeps "Digital Literacy" via its own digital literacy term, so default verdicts are unchanged — re-verified over every filtered source's whole window: zero flips on all non-strict sources, NVCL still 13, byte-identical to the pre-fix capture. Locked both directions in relevance_test.ts ("Digital Literacy Basics" → STRICT_FLIP, "Adult Literacy Program" → STRICT_KEEP).

@ltanafranca1004

Copy link
Copy Markdown
Collaborator Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ltanafranca1004
ltanafranca1004 merged commit 9cb586b into main Aug 10, 2026
4 checks passed
@ltanafranca1004
ltanafranca1004 deleted the fix/relevance-strict-nvcl-capilano branch August 10, 2026 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant