# PR #837 Lookback — feat(kernel): route proportional-decrease through construction proposals This lookback documents the design rationale, implementation details, and verification results for routing the proportional-decrease diagnostic path through typed `ConstructionProposal` objects. ## Rationale & Design Choices ### 1. Attaching `proposals` to `ProblemFrame` We introduced the `proposals` field (`tuple[ConstructionProposal, ...]`) directly on the `ProblemFrame` class. This allows the frame representation to carry its candidate construction traces, linking surface evidence to the construction-affordance catalog in a self-contained manner. ### 2. Integration in `build_problem_frame` To avoid circular imports and keep `ProblemFrameBuilder` clean, the proposals are attached in `build_problem_frame()` via a two-pass assembly: 1. Build the initial `ProblemFrame` with basic attributes. 2. Call `assess_contracts()` on the initial frame to retrieve `ContractAssessment` objects. 3. For each assessment whose candidate organ maps to a catalog family (via `get_contract_family_id()`), construct a `ConstructionProposal` via `make_proposal()`. 4. Recreate the `ProblemFrame` with the proposals tuple attached using `dataclasses.replace()`. ### 3. Exposing Public Accessors We added the public helper `get_contract_family_id(candidate_organ: str) -> str | None` in `generate/problem_frame_contracts.py`. This avoids exposing the private mapping dict `_CONTRACT_REGISTRY` to external modules or test suites. ### 4. Scope & Boundary Clarification PR #837 attaches assessment-backed proposal traces to `ProblemFrame` as a diagnostic trace. It does *not* make construction proposals drive relation binding or contract assessment, which remain decoupled at this stage. ## Tests Added We introduced a dedicated test file `tests/test_proportional_decrease_proposal.py` covering: - **Proposal trace existence**: Verifies that a `proportional_change.decrease_to_fraction` proposal is generated for proportional-decrease cases. - **Exact evidence spans**: Asserts that proposal evidence spans correctly slice the original problem text. - **Catalog alignment**: Verifies the proposal family ID, relation type, and candidate organ align with the catalog definition using public accessors. - **Diagnostic-only constraints**: Validates that the underlying family has `diagnostic_only=True` and `serving_allowed=False`. - **Blocked case handling**: Asserts that `FINAL_VALUE_CONFUSER` (a final-value question instead of a decrease-delta question) still produces a proposal trace but has a blocked status (not `"closed"`) and identifies `delta_decrease_target_unbound`. - **Confuser exclusion**: Verifies that `AFFINE_CONFUSER` produces no proportional-decrease proposal trace. ## Verification Results - All 54 tests pass successfully. - Parity of adequacy metrics verified: - Train runnable contracts remain `2` (`0005`, `0046`). - Holdout runnable contracts remain `0`. - Serving counts verified: - Train: `30 correct / 20 refused / 0 wrong` (wrong_ids: `[]`) - Holdout: `5 correct / 495 refused / 0 wrong` (wrong_ids: `[]`)