ADR-0174 Phase 3a — substrate for held-hypothesis lookback.
Score unchanged at 3/47/0 (this PR is correctly-engineered
infrastructure; eval impact gated on ADR-0163.x recognizer expansion
documented in the follow-up brief).
Adds generate/comprehension/lookback.py:
- VALID_REFINEMENT_KINDS, VALID_UNRESOLVED_SLOTS — closed sets
contracted with reader_trace consumer
- PronounResolution refinement dataclass (pronoun + resolved_to +
evidence_source, all validated)
- Refinement Union (Phase 3b will widen with CompoundClauseExpansion)
- ReevaluateResult dataclass with admit/eliminate consistency
- reevaluate(hypothesis, refinement) operator — applies refinement,
re-runs check_constraints, returns refined Hypothesis or None.
- _rebuild_candidate_with_resolved_actor — rebuilds
CandidateOperation / CandidateInitial replacing the semantic actor
field (op.actor / initial.entity) while preserving matched_actor_token
/ matched_entity_token as the pronoun (so grounding still passes
against the held statement's source span).
Modifies generate/recognizer_match.py:
- _try_extract_discrete_count_anchor: pronoun-subject statements now
emit anchors with subject_role=<pronoun> + requires_pronoun_resolution
marker, rather than refusing at the _REFUSED_SUBJECT_TOKENS check.
The other narrowness layers (clause split, verb whitelist) still
refuse; only the pronoun layer changes.
Modifies generate/math_candidate_graph.py:
- After inject_from_match, when any parsed_anchor carries
requires_pronoun_resolution, the candidates are held as Hypothesis
objects with unresolved=('actor_pronoun',). The lookback path then
resolves via the existing _discourse_prior_subjects map and runs
PronounResolution refinements through reevaluate. Resolved
hypotheses flow into per_sentence_choices as if the regex parser
had produced them; unresolved hypotheses drop cleanly (refusal-
preferring). Emits 'lookback' JSON trace events with
outcome ∈ {admitted, eliminated, no_antecedent}.
Tests:
- tests/test_adr_0174_phase3_lookback.py — 17 acceptance tests
covering operator semantics on Operation/Initial, dataclass
invariants, closed-set constants, end-to-end wiring on synthetic
problems, and wrong=0 preservation on train_sample.
Phase 3.1 follow-up brief:
- docs/handoff/PHASE-3.1-FOLLOWUP-RECOGNIZER-EXPANSION.md documents
the empirical finding that the train_sample bottleneck is
verb-coverage (recognizer scope, ADR-0163.x) not lookback
(ADR-0174 scope). 11 verbs identified for HITL contemplation pass.
Recommends sequencing: Phase 3a now (substrate), ADR-0163.x verb
expansion next, Phase 3b after coverage matures.
Acceptance verified:
- 17/17 Phase 3a tests pass
- 95/95 existing tests pass (Phase 1 + Phase 2 + brief_11 + reader_phase2)
- Smoke 67/67, packs 141/141, lanes 8/8
- wrong=0 preserved, score unchanged 3/47/0 (intentional per brief)
Stacks on Phase 2 (PR #420). Rebases onto main after #416 + #420 land.