Skip to content

fix: harden requirement extraction and rescore visibility - #15

Merged
pashawkola33 merged 1 commit into
mainfrom
fix/extractor-hygiene-rescore-visibility
Aug 10, 2026
Merged

pashawkola33 merged 1 commit into
mainfrom
fix/extractor-hygiene-rescore-visibility

Conversation

@pashawkola33

Copy link
Copy Markdown
Owner

Summary

  • Removes false REST/Go evidence while preserving production-confirmed technical REST contexts.
  • Adds SpringBoot/Spring-Boot canonicalization and JVM extraction.
  • Keeps Postgres → PostgreSQL explicitly deferred until scoring semantics are redesigned.
  • Makes technology extraction ordering deterministic.
  • Allows requirement-only drift to enter the guarded rescore plan.
  • Makes every changed ExtractedRequirements field visible before WRITE.
  • Adds plan/report consistency guards.

Production evidence

  • The read-only evidence audit found no hidden Java/Spring core recovery (core_recovery_rows = 0), so this PR is extraction fidelity only and changes no scoring weight.
  • REST follow-up inspection showed 5 of 9 previously "unqualified" REST rows were genuine technical evidence: OO, MVC, REST, HTTP/REST, REST/JSON, APIs (REST). Those are now retained.
  • Rest Assured rows and the rest of the stack remain negative, including the Selenium, Cucumber, BDD, Rest Assured and CI/CD tools list — the list delimiter never matches a bare space, so Rest followed by a word is never a list item.
  • No production mutation was performed. No preview, no rescore, no deploy.

Verification

  • DeterministicRequirementExtractorTest: 114 passed
  • com.jobpilot.matching.**: 55 passed in the final focused run
  • Additional focused regression set previously passed: 61 (JobProcessorTest, ManualJobUrlServiceTest, LeverJobSourceTest, ResumeTruthValidatorTest, ResumeGenerationServiceTest, EligibilityConfigurationTest, BrowserFallbackServiceTest)
  • git diff --check clean
  • No Docker, no Playwright, no production execution. CI performs the full verification.

Important operational note

  • Do not run production PREVIEW/WRITE until this PR is merged.
  • The first fresh preview may contain one-time TECHNOLOGIES ordering normalization: extraction order was previously salted per JVM run (Map.copyOf), and is now stable. Sets are unchanged on those rows; only the order is.
  • EXPECTED_CHANGED_COUNT must come only from the fresh post-merge production preview, never from a design estimate.
  • Known stale seniority requirement drift (documented as ~28 rows in docs/scoring-calibration-analysis.md A1.4) now enters the plan as requirement-only changes and will render as SENIORITY="JUNIOR"->"UNKNOWN". It must be reviewed and accepted explicitly before WRITE — it is the majority of the write and is unrelated to extractor hygiene.

Out of scope — unchanged

Scoring weights, bands, blockers, penalties, screening, workflow, MATCH-first Mini App ranking, Telegram, ingestion adapters, database schema, migrations, production configuration. ScoreRescorePlanFingerprint is untouched; fingerprint, row locking and all existing write guards keep their semantics.

🤖 Generated with Claude Code

Extraction hygiene, all deterministic and scoring-neutral by construction:

- Technology extraction order is now stable. Map.copyOf salts its iteration
  order per JVM run, so identical text produced differently ordered technology
  lists and ExtractedRequirements record equality was unstable across runs.
  Nothing depended on that while rescore membership compared scores only.
- REST is extracted only from qualified evidence: the API/service/endpoint/
  controller forms, RESTful, JAX-RS, Spring REST, the technical shorthands
  HTTP/REST, REST/JSON and APIs (REST), after an explicit technical introducer,
  and as a complete item in a delimited technology list. The list delimiter is
  never a bare space, which is what keeps "Rest Assured" and "the rest of the
  stack" negative.
- Go is extracted only from unambiguous spellings or from a delimited language
  list with a recognised neighbour that terminates as a list item, so ordinary
  English "go" no longer counts as evidence.
- SpringBoot and Spring-Boot canonicalise to Spring Boot; JVM becomes its own
  canonical term, in no skill list and not a programming language.
- Postgres -> PostgreSQL stays deliberately deferred to the scoring redesign,
  pinned by a regression test, because PostgreSQL is an equally weighted
  backend skill today.

Rescore preview visibility:

- Plan membership follows either persisted projection, not the score alone.
  The write transaction already re-persisted requirements whenever they
  differed, so requirement-only drift was being written without ever appearing
  in a preview.
- The preview reports scoreChanged, requirementsChanged, requirementsOnly,
  changedPlan and unchanged counts, and names every differing
  ExtractedRequirements field with sanitized, bounded old and new values.
  Raw values are compared before any display conversion, so two values that
  share a truncated prefix cannot be reported as equal.
- ScoreRescorePlan asserts its entry count against the report, so a write can
  never touch a row the preview did not account for. Fingerprint, locking and
  the existing guards are unchanged.

Focused regression tests cover every REST and Go case, the aliases, the
deferral, the 15-field requirement diff and the plan/report invariants.

No scoring weights, bands, blockers, screening, workflow, Mini App ranking,
schema or configuration were changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pashawkola33
pashawkola33 merged commit 6f3efe5 into main Aug 10, 2026
4 checks passed
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