Repository navigation
refactor(intrinsics): requirement_check migration — loud schema-mismatch, no more silent False (Epic #929 Phase 1) #1138
Description
Parent epic: #929
Design proposal: PR #1080
Phase: 1 (Wave 3 — start after 1.A merges)
Depends on: 1.A (and 0.2 for catalogue deduplication background)
Independent of: 1.B, 1.D, 2.1
⚠️ Pre-flight dependency: PR #1078 must be merged before starting this issue. It adds canned I/O test data forrequirement-checkanduncertaintyformatters that this issue's tests build on.
Problem
requirement_check and requirement_check_to_bool currently route through the old API. PR #1008 is the canonical evidence of silent schema drift: the output changed from {"requirement_likelihood": 0.9} to {"requirement_check": {"score": 0.9}} upstream, and requirement_check_to_bool returned False for every call until someone noticed.
Current state (verified main 2026-05-21): requirement_check_to_bool uses the post-#1008 schema req_dict["requirement_check"]["score"] and returns False with a warning on schema mismatch — still a silent failure mode.
Agreed design
Follows the per-helper-file migration template from PR #1080. File-specific deltas:
- Output contract: post-fix: move test_huggingface.py to granite4.1; and small rag intrinsic … #1008 shape
{"requirement_check": {"score": float}}. Implementer confirms against current weights. - Schema-mismatch is loud here. This helper is the design's worked example — callers must see
AdapterSchemaMismatchErrorimmediately, not silently-wrong booleans. requirement_check_to_boolstops returning silentFalseon parse failure — it propagatesAdapterSchemaMismatchError. This is an intentional breaking change.- Catalogue deduplication: by the time this issue is worked, 0.2 will have collapsed the
requirement_check/requirement-checkduplicate. This issue resolves whichever canonical entry the role-based lookup (from 1.A) surfaces.
Scope
mellea/stdlib/components/intrinsic/— whereverrequirement_checklivesmellea/stdlib/requirements/requirement.py—requirement_check_to_bool- Tests covering both functions
Out of scope
Other helpers (1.B, 1.D), auto-bumping catalogue revision, catalogue deduplication (0.2).
Acceptance criteria
-
requirement_check(...)constructs via newAdaptertypes (noIntrinsicAdapter(...)) -
requirement_check(...)acceptsmodel_options: dict | None = None -
requirement_checkhas a declared output contract in its docstring -
requirement_check_to_bool(...)returnsboolon happy path -
requirement_check_to_bool(...)propagatesAdapterSchemaMismatchErroron schema-break — NOT silentFalse - Synthetic output
{"requirement_check": {"score": 0.9}}parses correctly - Synthetic output
{"requirement_likelihood": 0.9}(pre-fix: move test_huggingface.py to granite4.1; and small rag intrinsic … #1008 shape) raisesAdapterSchemaMismatchError - Existing happy-path tests pass
-
ruff format,ruff check,mypyclean
Test plan
Common per-helper tests (see template in 929-issue-plan.md). Plus:
test_requirement_check_to_bool_raises_on_schema_mismatch— replaces silentFalsewith explicitAdapterSchemaMismatchError(regression test for fix: move test_huggingface.py to granite4.1; and small rag intrinsic … #1008 behaviour; name it after fix: move test_huggingface.py to granite4.1; and small rag intrinsic … #1008)test_pre_1008_schema_raises— specifically:{"requirement_likelihood": 0.9}input raises
Breaking changes
requirement_check_to_boolno longer returns silentFalseon parse failure — now raisesAdapterSchemaMismatchError. Callers that wrap this intry/excepttreating failure as "requirement not met" must update. Surface in changelog.
References
- PR docs: design proposal for adapter lifecycle (#929) — review channel, do not merge #1080 §14.1 Easier RCA for failed requirements #2 (silent schema drift worked example)
- PR fix: move test_huggingface.py to granite4.1; and small rag intrinsic … #1008 — the original schema flip
- Jake req 4
- update intrinsic tests #1029 — open (close when PR fix: intrinsic tests and add some safeguards for future adapters changes #1078 merges; fix: intrinsic tests and add some safeguards for future adapters changes #1078 is the pre-flight for this issue)
Activity
planetf1 commentedon Jun 11, 2026
This issue uses vocabulary that has been superseded by the agreed Epic #929 glossary. Please use the following terms in any new work related to this issue:
The canonical definitions are now in the project glossary and were established as part of #1192. Python symbol names (
IntrinsicAdapter,fetch_intrinsic_metadata, etc.) keep their current names until Phase 1 (#1136) and Phase 4 (#1144).feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
fix(adapters): validate technology before warning; document _find_ada…
docs(adapters): update adapter.py docstrings to reflect Phase 1 shim …
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
fix(adapters): validate technology before warning; document _find_ada…
docs(adapters): update adapter.py docstrings to reflect Phase 1 shim …
docs(intrinsics): address code review feedback on rag.py migration
feat(intrinsics): shim old adapters onto Adapter dataclass; call_intr…
docs(intrinsics): address code review feedback on rag.py migration
refactor(intrinsics): migrate rag.py to new Adapter types (Epic gener…
refactor(intrinsics): requirement_check_to_bool raises on schema mism…
refactor(intrinsics): requirement_check_to_bool raises on schema mism…