fix(events-crawler): track Surrey parse failures by layer - #98
Conversation
Closes the follow-up deferred from PR #86. `533d79e` covered only the first layer: BLOCK_MARKER no longer matching sets blocks === 0, which page 0 now logs as an error. The three regexes *downstream* of that marker still failed the same way — TITLE_LINK_RE, TIME_RE or LOCATION_RE ceasing to match skipped every chunk through a `continue` no counter reached, so candidates stayed empty while blocks stayed non-zero, `exhausted` never tripped, maxStartMs stayed 0 so `pastWindow` never tripped, and the walk burned all 20 pages before exiting through the cap warning — which reads "listings beyond the cap" when the truth is "the markup moved". Misattributed rather than silent, but just as useless. Adds per-layer StructuralMisses (title / time / location) and a page-0 diagnostic firing when title + time + location === blocks, naming each layer and its count. Relevance and window are deliberately excluded: they reject on merit, and rejecting most of a library calendar is their job. Surrey needed one thing NVCL and Capilano did not. Its address extraction sat AFTER the filters, so `structural === blocks` could never reach equality to detect a LOCATION_RE failure — relevance had already rejected ~80% of the page on merit. Moved the extraction ahead of the filters, the same call adapters/capilano.ts made for its venue, so the whole chain precedes merit-based rejection and one comparison covers it. No output change: a block failing location was dropped either way, and maxStartMs still updates before location, so walk-stop behaviour is untouched. Verified against the live feed by breaking each regex in turn — title gives (title 10, time 0, location 0), time gives (0, 10, 0), location gives (0, 0, 10). And with isSettlementRelevant temporarily forced to reject everything, the source returns 0 rows and logs zero structural errors, so a filtered-empty result stays distinguishable from a markup change. Happy path unchanged at 12 pages / 27 relevant / 25 taken. This completes the pattern across all three BLOCK_MARKER adapters. The feed parsers (bibliocommons, communico) have the same shape but a weaker case; recorded in BACKLOG.md rather than expanded into this PR. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
WalkthroughThe Surrey HTML adapter now tracks title, time, and location extraction failures before filtering. It returns these counts and logs page-0 diagnostics when all marked blocks fail structural extraction. The backlog records verification results and remaining parser gaps. ChangesSurrey adapter diagnostics
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 |
What & why
Closes the follow-up deferred from #86 (
BACKLOG.md).533d79ecovered only the first layer of Surrey's silent-failure mode:BLOCK_MARKERno longer matching setsblocks === 0, which page 0 now logs as an error.The three regexes downstream of that marker still failed the same way. If
TITLE_LINK_RE,TIME_REorLOCATION_REstops matching, every chunk is skipped through acontinueno counter reaches —candidatesstays empty whileblocksstays non-zero, soexhaustednever trips,maxStartMsstays0sopastWindownever trips, and the walk burns all 20 pages before exiting through the cap warning. That warning reads "listings beyond the cap" when the truth is "the markup moved": misattributed rather than silent, but just as useless.Diagnostics only — no behaviour change, no schema/migration/cron change, and nothing here alters what Monday's cron ingests.
The one thing that wasn't a copy of NVCL
Surrey's address extraction sat after the relevance and window filters:
So
structural === blockscould never reach equality to detect aLOCATION_REfailure — relevance had already rejected most of the page on merit. Adding counters alone would not have fixed it.The fix is to move the extraction ahead of the filters, which is the same call
capilano.ts:194-200already made for its venue:No output change: a block failing location was dropped either way, and
maxStartMsstill updates before location, so walk-stop behaviour is untouched.Verified empirically against the live feed
Each regex broken in turn, page-0 diagnostic observed:
TITLE_LINK_REmatched 10 block(s) on page 0 but extracted none of them (title 10, time 0, location 0)TIME_RE… (title 0, time 10, location 0)LOCATION_RE… (title 0, time 0, location 10)Each names the right layer with an exact count. The
LOCATION_RErow is what the reordering bought — under the old ordering that failure was undetectable.The exclusion property (the assertion that actually earns its keep): with
isSettlementRelevanttemporarily forced to reject everything, the source returns 0 rows and logs zero structural errors. A legitimately filtered-empty result stays distinguishable from a markup change — this is what would catch a wrong comparison.Regression: happy path unchanged, and no diagnostic on a healthy run.
All temporary edits were reverted and verified against file snapshots before committing;
git statusshowed only the two files in this diff.Scope
This completes the pattern across all three
BLOCK_MARKERadapters —nvcl.ts(ada14d1),capilano.ts(1f62068),surrey.ts(here).bibliocommons.ts(6 untrackedcontinues) andcommunico.ts(4, with partialunparsedDates) have the same shape but a weaker case: they parse a JSON gateway and an RSS feed, where the failure mode is a field rename rather than a theme update, and a renamed field usually breaks parsing loudly.livewhale.ts/tribe.tshave no skip-continues at all. Recorded inBACKLOG.mdrather than expanded into this PR.Verification
deno check— clean on all 17 crawler filesdeno test— 2/2 (relevance_test.ts, unaffected; run to confirm nothing broke)npx tsc --noEmit— exit 0🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Monitoring
Documentation