⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
packages/loopover-engine/src/phase7-calibration-loop.ts's normalizeCompositeWeights (lines
173-183) unconditionally substitutes the documented default weights whenever both configured
weights sum to zero or less:
if (total <= 0) return { historicalReplay: DEFAULT_CONFIG.historicalReplayWeight, prOutcome: DEFAULT_CONFIG.prOutcomeWeight };
Upstream validation (resolvePhase7CalibrationConfig, lines 232-242) only rejects negative weights
— a maintainer explicitly setting historicalReplayWeight: 0 and prOutcomeWeight: 0 passes
validation cleanly, with no warning, and is stored verbatim in the resolved config. But the moment
that resolved config reaches normalizeCompositeWeights, the explicit all-zero setting is silently
discarded and replaced with the 0.5/0.5 default (DEFAULT_CONFIG, lines 104-109) — with zero
visibility into the fact that the maintainer's explicit configuration was overridden.
This is the mirror-image defect of the sibling composers in gate-verdict-calibration.ts /
reviewer-consensus-calibration.ts / finding-severity-calibration.ts (every one of which
documents "preserve an explicit zero" as an important principle): this file preserves nothing, ever,
for the zero-sum case — it always reverts to the default with no warning. No existing test in
packages/loopover-engine/test/phase7-calibration-loop.test.ts covers
historicalReplayWeight: 0, prOutcomeWeight: 0 together.
Requirements
- Decide and implement one of two explicit fixes (do not leave this ambiguous):
- Preserve the explicit all-zero configuration (matching the "preserve explicit zero" principle
documented by this module's siblings), OR
- Keep reverting to the default, but emit a warning (via this file's existing logging/warning
mechanism used elsewhere in resolvePhase7CalibrationConfig) so the override is visible rather
than silent.
- Whichever is chosen, document the decision explicitly in a comment at the
total <= 0 branch so
a future reader does not have to re-derive the intent.
Deliverables
All three Deliverables are required in the same PR.
Test Coverage Requirements
packages/loopover-engine/** is measured by codecov/patch (99%+ target, branch-counted). The new
test must exercise the explicit-all-zero branch specifically and assert on the chosen, documented
behavior — not just that the function returns without throwing.
Expected Outcome
A maintainer who explicitly sets both phase7 calibration weights to zero either gets that
configuration honored, or is warned that it was overridden — never silently discarded with no
signal, unlike today.
Links & Resources
packages/loopover-engine/src/phase7-calibration-loop.ts:173-183 (normalizeCompositeWeights)
packages/loopover-engine/src/phase7-calibration-loop.ts:232-242
(resolvePhase7CalibrationConfig, the validation that lets an explicit zero-sum config through)
packages/loopover-engine/src/phase7-calibration-loop.ts:104-109 (DEFAULT_CONFIG)
- Contrast:
gate-verdict-calibration.ts / reviewer-consensus-calibration.ts /
finding-severity-calibration.ts, all of which document "preserve explicit zero" as an important
principle for the sibling NaN/negative-weight issue filed alongside this one
Context
packages/loopover-engine/src/phase7-calibration-loop.ts'snormalizeCompositeWeights(lines173-183) unconditionally substitutes the documented default weights whenever both configured
weights sum to zero or less:
Upstream validation (
resolvePhase7CalibrationConfig, lines 232-242) only rejects negative weights— a maintainer explicitly setting
historicalReplayWeight: 0andprOutcomeWeight: 0passesvalidation cleanly, with no warning, and is stored verbatim in the resolved config. But the moment
that resolved config reaches
normalizeCompositeWeights, the explicit all-zero setting is silentlydiscarded and replaced with the 0.5/0.5 default (
DEFAULT_CONFIG, lines 104-109) — with zerovisibility into the fact that the maintainer's explicit configuration was overridden.
This is the mirror-image defect of the sibling composers in
gate-verdict-calibration.ts/reviewer-consensus-calibration.ts/finding-severity-calibration.ts(every one of whichdocuments "preserve an explicit zero" as an important principle): this file preserves nothing, ever,
for the zero-sum case — it always reverts to the default with no warning. No existing test in
packages/loopover-engine/test/phase7-calibration-loop.test.tscovershistoricalReplayWeight: 0, prOutcomeWeight: 0together.Requirements
documented by this module's siblings), OR
mechanism used elsewhere in
resolvePhase7CalibrationConfig) so the override is visible ratherthan silent.
total <= 0branch soa future reader does not have to re-derive the intent.
Deliverables
normalizeCompositeWeights'stotal <= 0branch either preserves the explicit zero weights,or emits an explicit warning when reverting to the default — implemented, not left silent.
total <= 0branch states which behavior was chosen and why.phase7-calibration-loop.test.tsresolving a config with both weightsexplicitly
0, asserting the chosen behavior (either the weights are preserved as zero, or awarning is produced alongside the default substitution).
All three Deliverables are required in the same PR.
Test Coverage Requirements
packages/loopover-engine/**is measured bycodecov/patch(99%+ target, branch-counted). The newtest must exercise the explicit-all-zero branch specifically and assert on the chosen, documented
behavior — not just that the function returns without throwing.
Expected Outcome
A maintainer who explicitly sets both phase7 calibration weights to zero either gets that
configuration honored, or is warned that it was overridden — never silently discarded with no
signal, unlike today.
Links & Resources
packages/loopover-engine/src/phase7-calibration-loop.ts:173-183(normalizeCompositeWeights)packages/loopover-engine/src/phase7-calibration-loop.ts:232-242(
resolvePhase7CalibrationConfig, the validation that lets an explicit zero-sum config through)packages/loopover-engine/src/phase7-calibration-loop.ts:104-109(DEFAULT_CONFIG)gate-verdict-calibration.ts/reviewer-consensus-calibration.ts/finding-severity-calibration.ts, all of which document "preserve explicit zero" as an importantprinciple for the sibling NaN/negative-weight issue filed alongside this one