Skip to content

Commit 2f2353e

Browse files
committed
fix(review): read the merge-readiness-promoted policy in recordGateScoreSignals (#8223)
The pure gate path applies applyMergeReadinessGate(policy) before evaluating, so a repo with mergeReadinessGateMode: block and slopGateMode unset genuinely blocks on slop via the composite promotion -- but the writer read the RAW policy and skipped the write for exactly that case, silently dropping corpus evidence. Read every field from the promoted policy, mirroring recordConfiguredGateBlockerSignals, with a composite-promotion regression test.
1 parent c540c2a commit 2f2353e

2 files changed

Lines changed: 21 additions & 6 deletions

File tree

src/rules/advisory.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,15 +1159,20 @@ export async function recordGateScoreSignals(
11591159
repoFullName: string,
11601160
prNumber: number,
11611161
): Promise<void> {
1162+
// The SAME policy transform evaluateGateCheckCore applies before its pure evaluations: the #551
1163+
// merge-readiness composite can promote slopGateMode to block, and buildSlopGateBlocker only ever sees
1164+
// the PROMOTED policy — reading the raw one here would silently drop corpus evidence for exactly the
1165+
// composite-gated case this capture exists for (mirrors recordConfiguredGateBlockerSignals above).
1166+
const effective = applyMergeReadinessGate(policy);
11621167
const store = createSignalStore(env);
11631168
const targetKey = `${repoFullName}#${prNumber}`;
11641169
const occurredAt = nowIso();
11651170
const writes: Promise<void>[] = [];
11661171

1167-
const slopMode = gateMode(policy.slopGateMode);
1168-
const slopRisk = normalizeScore(policy.slopRisk);
1172+
const slopMode = gateMode(effective.slopGateMode);
1173+
const slopRisk = normalizeScore(effective.slopRisk);
11691174
if (slopMode === "block" && slopRisk !== null) {
1170-
const slopMin = normalizeScore(policy.slopGateMinScore) ?? DEFAULT_SLOP_BLOCK_THRESHOLD;
1175+
const slopMin = normalizeScore(effective.slopGateMinScore) ?? DEFAULT_SLOP_BLOCK_THRESHOLD;
11711176
writes.push(
11721177
store
11731178
.recordRuleFired({
@@ -1184,9 +1189,9 @@ export async function recordGateScoreSignals(
11841189
);
11851190
}
11861191

1187-
const qualityMode = gateMode(policy.qualityGateMode);
1188-
const readinessScore = normalizeScore(policy.readinessScore);
1189-
const qualityMin = normalizeScore(policy.qualityGateMinScore);
1192+
const qualityMode = gateMode(effective.qualityGateMode);
1193+
const readinessScore = normalizeScore(effective.readinessScore);
1194+
const qualityMin = normalizeScore(effective.qualityGateMinScore);
11901195
if (qualityMode !== "off" && readinessScore !== null && qualityMin !== null) {
11911196
writes.push(
11921197
store

test/unit/configured-gate-blocker-signals.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,16 @@ describe("recordGateScoreSignals (#8223)", () => {
267267
expect(history.fired[0]).toMatchObject({ outcome: "below_threshold", metadata: { confidence: 0.3 } });
268268
});
269269

270+
it("fires slop under the merge-readiness composite promotion even when slopGateMode itself is unset (#551 parity)", async () => {
271+
// mergeReadinessGateMode: block promotes the slop sub-gate to block exactly as evaluateGateCheckCore's
272+
// own applyMergeReadinessGate does — the raw slopGateMode stays unset, and the write must still happen.
273+
const env = createTestEnv();
274+
await recordGateScoreSignals(env, { mergeReadinessGateMode: "block", slopRisk: 72, slopGateMinScore: 60 }, "owner/repo", 7);
275+
const history = await createSignalStore(env).queryRuleHistory("slop_gate_score", 0);
276+
expect(history.fired).toHaveLength(1);
277+
expect(history.fired[0]).toMatchObject({ outcome: "above_threshold", metadata: { confidence: 0.72 } });
278+
});
279+
270280
it("records NOTHING for slop outside block mode or with a null risk — the gate never evaluated the score", async () => {
271281
const env = createTestEnv();
272282
await recordGateScoreSignals(env, { slopGateMode: "advisory", slopRisk: 72 }, "owner/repo", 7);

0 commit comments

Comments
 (0)