feat(grantrecs): grant-history join + daily opportunity projection (#1218)#1237
Open
paulalbert1 wants to merge 1 commit into
Open
feat(grantrecs): grant-history join + daily opportunity projection (#1218)#1237paulalbert1 wants to merge 1 commit into
paulalbert1 wants to merge 1 commit into
Conversation
…1218) Step 3 (app) — extend the reverse funding matcher with grant history: deriveGrantSignals() attaches esiEligible / yearsSinceDegree / fundingStatus per researcher (funding via the canonical isFundingActive NCE-grace rule; ESI dated from the terminal research/clinical degree, not the latest credential). Adds the ESI blurb clause, a funding-status filter, funding + 'Also in their Grants for me' row badges, and two CSV columns. The cross-ref is a cheap MySQL-only topic-affinity top-N over the open-opportunity corpus (same status/deadline gate the forward matcher uses, so closed/past-due opps can't over-claim); validated against the real forward matcher in scripts/funding-crossref-compare.ts (100% top-10 agreement, past-due guard clean). Step 2 (cdk) — standalone daily etl:dynamodb schedule (06:30 UTC) so newly-published opportunities stop 404-ing while the nightly is blocked at etl:ed (#443). Creation-gated on a new opportunityProjectionScheduleEnabled flag (staging on, prod off), modeled on the curationBackup schedule: task -> retry -> catch -> state machine -> rule -> cadence alarm. Tests: +grant-signal/ESI/funding/CSV unit coverage; cdk staging rules 8->9 + projection schedule test + prod-absence test (130 cdk tests). Operator deploys: cdk deploy Sps-Etl-staging (Step 2) + app image roll (Step 3).
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.
Funding matcher: grant-history join + daily opportunity projection (#1218)
Two related follow-ups from
docs/funding-matcher-redesign-handoff.md, bundled under the #1218 umbrella. Review only — do not merge.Step 3 — grant-history join (app)
Extends the reverse matcher ("rank researchers for this opportunity") with each scholar's grant/degree history:
deriveGrantSignals()(pure, unit-tested) →esiEligible/yearsSinceDegree/fundingStatus, attached post-ranking.fundingStatususes the canonicalisFundingActive(12-month NCE grace), so it agrees with the profile's "Active funding" badge — not a bespokeendDate >= now.esiEligibledates from the terminal research/clinical degree (PhD/MD/…), not the most recent credential, so a later MPH/cert doesn't falsely reset the ESI clock.researcherBlurb; funding-status filter dropdown; funding + "Also in their Grants for me" row badges; two new CSV columns.opportunitiesInTopMatches): a cheap MySQL-only topic-affinity top-N over the open-opportunity corpus — gated to the same status/deadline the forward matcher uses, so a closed/past-due opp (reachable via the unfiltered browse list) can never over-claim "in their Grants for me." Validated against the real forward matcher inscripts/funding-crossref-compare.ts: 100% top-10 agreement, past-due guard clean.Step 2 — daily opportunity projection (cdk)
etl:dynamodb(DynamoDB→MySQLopportunityprojection) is a nightly step but sits afteretl:ed, which #443 blocks — so the nightly aborts before reaching it and newly-published opportunities 404 until re-projected by hand.etl:dynamodbschedule (06:30 UTC) inSps-Etl, mirroring the curation-backup pattern (task → retry → catch → state machine → rule → cadence alarm).opportunityProjectionScheduleEnabledflag: stagingtrue, prodfalse(prod creates no resources until the corpus is published / Staging Session B: populate data + build search index #443 lands and the nightly reaches the step again, at which point the stopgap retires).Review & verification
tsc+eslintclean.etl-stack130 tests green; staging snapshot updated; prod synth creates zero projection resources (creation-gated).Deploy (operator, gated — not in this PR)
cdk deploy Sps-Etl-stagingto activate the daily schedule.Accepted residuals