diff --git a/packages/loopover-miner/lib/self-review-context.ts b/packages/loopover-miner/lib/self-review-context.ts index 847643dfa..06625052d 100644 --- a/packages/loopover-miner/lib/self-review-context.ts +++ b/packages/loopover-miner/lib/self-review-context.ts @@ -172,7 +172,7 @@ export function applyLiveGateThresholdsToManifest( const gate = { ...manifest.gate }; if (typeof fields.confidence_floor === "number") { const floorScore = Math.max(0, Math.min(100, Math.round(fields.confidence_floor * 100))); - if (typeof gate.readinessMinScore === "number" && floorScore > gate.readinessMinScore) { + if (typeof gate.readinessMinScore !== "number" || floorScore > gate.readinessMinScore) { gate.readinessMinScore = floorScore; } } diff --git a/test/unit/miner-self-review-context.test.ts b/test/unit/miner-self-review-context.test.ts index 834188d4c..c2a0dfd84 100644 --- a/test/unit/miner-self-review-context.test.ts +++ b/test/unit/miner-self-review-context.test.ts @@ -725,6 +725,19 @@ describe("live gate thresholds probe (#6487)", () => { expect(overlaid.gate.sizeMaxFiles).toBe(3); }); + it("REGRESSION (#10338): adopts a live confidence floor when static readiness is unset", () => { + const base = parseFocusManifestContent("gate:\n duplicates: block\n", "repo_file"); + expect(base.gate.readinessMinScore).toBeNull(); + + const overlaid = applyLiveGateThresholdsToManifest(base, { + confidence_floor: 0.91, + scope_cap_files: null, + scope_cap_lines: null, + }); + + expect(overlaid.gate.readinessMinScore).toBe(91); + }); + it("applyLiveGateThresholdsToManifest raises readinessMinScore and prefers live scope caps", () => { const base = parseFocusManifestContent("gate:\n readiness:\n mode: block\n minScore: 70\n size:\n mode: block\n maxFiles: 20\n maxLines: 500\n", "repo_file"); const overlaid = applyLiveGateThresholdsToManifest(base, {