The ADR-0191 completeness guard (added after WAVE-A) requires aggregating
initials to expose every consumed source token via
`consumed_value_tokens`, so it can confirm no source quantity was
silently dropped. The WAVE-A "each weighing" injector predates the guard
and left that field empty, so for every "<Subject> <verb> M <outer>, each
... N <unit>" reading the guard computed required={M, N} vs
consumed={M*N} and refused as "incomplete reading: source quantities
[M, N] not consumed". This silently regressed the entire WAVE-A
capability — the canary `test_lilibeth_canary_solves_end_to_end` has been
red on main (it failed byte-identically on f79b647; the smoke gate does
not collect this dedicated test file, so it merged green originally).
Fix: populate `consumed_value_tokens=(count_a_token, count_b_token)` on
the composed initial — exactly the contract the day-enumeration and
embedded-quantifier aggregators already satisfy.
wrong==0 preserved: the two tokens genuinely ARE the multiplicands of the
emitted value; the guard remains refusal-only. Serving frozen: this
shape does not occur in train_sample, so the fix is serving-neutral.
Evidence:
- tests/test_wave_a_multiplicative_aggregation_injector.py: 11 passed
(was 1 failed) incl. test_wrong_zero_preserved (full train_sample eval,
wrong==0).
- core test --suite packs: 141 passed (was 1 failed, 140 passed).
- core test --suite smoke: 67 passed.
- scripts/verify_lane_shas.py: lanes 8/8 match pinned SHAs — the
train_sample_v1 serving SHA is byte-identical, proving zero serving
count change.
PR checklist:
- Capability: restores WAVE-A multiplicative-aggregate reading regressed
by ADR-0191.
- Invariant: wrong==0 (completeness guard stays refusal-only; tokens are
true multiplicands).
- Lane: core test --suite packs / smoke + lane-SHA gate (8/8).
- No hidden normalization, stochastic fallback, approximate recall, or
unreviewed mutation.
- Trust boundary: none widened — internal candidate provenance only.