Skip to content

fix(engine): preserve an explicit all-zero phase7 composite weighting - #8680

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
kai392:fix/critical-issue-phase7-allzero-weights
Jul 25, 2026
Merged

fix(engine): preserve an explicit all-zero phase7 composite weighting#8680
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
kai392:fix/critical-issue-phase7-allzero-weights

Conversation

@kai392

@kai392 kai392 commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Fixes #8644

Root cause

normalizeCompositeWeights (packages/loopover-engine/src/phase7-calibration-loop.ts) reverted a config with both composite weights explicitly 0 back to the 50/50 default, silently. That total <= 0 branch is reachable only when both weights were deliberately set to 0: finiteNonNegative floors any invalid/negative input to a positive default, which can't sum to 0. So a 0 total is an operator's explicit "disable composite weighting" signal, not a degraded input — and overriding it back to 50/50 loses that intent with no trace.

Fix (chose Requirements option 1 — preserve the explicit zero)

Return { historicalReplay: 0, prOutcome: 0 } at the branch, with a comment documenting the decision and why. This matches the "preserve explicit zero" principle the sibling calibration composers already follow.

Downstream this is safe and already-handled: {0,0} leaves weightTotal at 0, which the existing combinedAccuracy guard renders as null — the same state reached today when no source contributes, not a new untested path. I chose this over option 2 (warn but keep defaulting) because the result's weights field makes the preserved zeros directly observable/testable, whereas config.warnings isn't surfaced on the loop result — and preserving the operator's intent is the stronger fix.

Tests

  • Package-native (packages/loopover-engine/test/phase7-calibration-loop.test.ts, the deliverable's named file): resolves an explicit all-zero config, asserts the weights are preserved as {0,0} and the composite is null. Full engine suite: 713 pass / 0 fail.
  • Root-vitest mirror (test/unit/phase7-calibration-loop-weights.test.ts): the package-native node:test suite runs under the engine workspace, not the root run Codecov grades, so — per the test(calibration): make signal-tracking's real coverage visible to Codecov #8438 precedent — this imports from packages/loopover-engine/src/index (source, not dist) and exercises both arms of the total <= 0 branch. This is what gives codecov/patch coverage of the changed line.

Validation

  • lcov scoped to phase7-calibration-loop.ts: every changed line and both branches covered via the root mirror
  • npm run typecheck clean; oxlint clean on the changed lines (the one warning is a pre-existing control-char regex at line 169, outside this diff)
  • No engine/src twin of this file exists (no parity mirror needed); branch cut from current main (c5cc6c4c); git diff --check clean

@kai392
kai392 requested a review from JSONbored as a code owner July 25, 2026 23:35
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

normalizeCompositeWeights silently reverted a config with both composite
weights explicitly set to 0 back to the 50/50 default. That branch is
reachable only when both weights were deliberately 0 (invalid inputs floor to
a positive default), so it's an explicit "disable composite weighting" signal,
not degraded input. Preserve {0,0} — matching the sibling composers'
preserve-explicit-zero principle — which yields a null composite downstream
rather than overriding the operator's intent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.78%. Comparing base (c5cc6c4) to head (7bce0b7).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8680      +/-   ##
==========================================
+ Coverage   93.76%   93.78%   +0.01%     
==========================================
  Files         797      797              
  Lines       79454    79454              
  Branches    24070    24070              
==========================================
+ Hits        74504    74515      +11     
+ Misses       3565     3563       -2     
+ Partials     1385     1376       -9     
Flag Coverage Δ
backend 95.05% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ges/loopover-engine/src/phase7-calibration-loop.ts 52.40% <100.00%> (+8.02%) ⬆️

... and 1 file with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 25, 2026
@loopover-orb

loopover-orb Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-25 23:55:36 UTC

3 files · 1 AI reviewer · no blockers · readiness 98/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This fixes a real bug: normalizeCompositeWeights (phase7-calibration-loop.ts:177-193) previously silently reverted an explicit {historicalReplayWeight:0, prOutcomeWeight:0} config back to the 50/50 default because it only checked `total <= 0`. The trace holds — by the time weights reach normalizeCompositeWeights via the resolvePhase7CalibrationConfig path, invalid/negative inputs are already floored to the 0.5 default upstream (resolvePhase7CalibrationConfig, e.g. `replayWeight !== undefined && replayWeight >= 0 ? replayWeight : DEFAULT_CONFIG.historicalReplayWeight`), so total<=0 is only reachable via an explicit {0,0}. Returning {0,0} instead of the default is safe downstream since weightTotal=0 already renders combinedAccuracy as null via the existing guard (computePhase7CalibrationLoop, weightTotal<=0 branch) — no new state is introduced. Tests in both the package-native suite and the root-vitest mirror exercise the real path through resolvePhase7CalibrationConfig and computePhase7CalibrationLoop and correctly assert {0,0} weights and a null composite, plus the unchanged positive-weight branch.

Nits — 5 non-blocking
  • The claim in the code comment that the branch is reachable 'ONLY' via an explicit 0/0 config technically depends on callers going through resolvePhase7CalibrationConfig; computePhase7CalibrationLoop also accepts a pre-built Phase7CalibrationConfig directly (input.config && "phase7LoopEnabled" in input.config), which bypasses that upstream floor to 0.5 — a caller passing a raw config with negative/NaN weights would also hit this branch, so the comment's wording is slightly stronger than the code guarantees.
  • The inline comment at phase7-calibration-loop.ts:178-186 is quite long (8 lines) for a single return statement; could be trimmed to the core rationale (explicit-zero preserved, downstream null-composite guard already handles it) without losing the why.
  • Neither new test explicitly asserts autonomyIncreasePermitted/holdReasons for the phase7LoopEnabled+{0,0}+both-sources-otherwise-valid case (falls into the existing 'no_combined_calibration_signal' hold path) — not required for this fix, but would round out the coverage story for the operator-facing effect of disabling composite weighting.
  • Consider tightening the comment's phrasing from 'reachable ONLY when both weights were explicitly 0' to note it depends on the resolvePhase7CalibrationConfig entry point, per the nit above.
  • Optionally add one assertion in either new test for autonomyIncreasePermitted/holdReasons under the {0,0} case so the operator-visible consequence (no autonomy increase, hold reason) is documented alongside the weights/combinedAccuracy assertions.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #8644
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 149 registered-repo PR(s), 78 merged, 7 issue(s).
Contributor context ✅ Confirmed Gittensor contributor kai392; Gittensor profile; 149 PR(s), 7 issue(s).
Improvement ✅ Minor risk: clean · value: minor
Linked issue satisfaction

Addressed
The PR implements option 1 exactly as required: normalizeCompositeWeights now returns {historicalReplay: 0, prOutcome: 0} at the total<=0 branch with an explicit comment documenting the decision and rationale, matching the sibling composers' 'preserve explicit zero' principle.

Review context
  • Author: kai392
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, Cuda, JavaScript, Kotlin, Perl, TypeScript, Vue
  • Official Gittensor activity: 149 PR(s), 7 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 056c3d7 into JSONbored:main Jul 25, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(engine): phase7-calibration-loop silently overrides an explicit all-zero weight config with no warning

2 participants