Skip to content

[Bug]: gate predictor under-reports the missing-linked-issue blocker on mergeReadiness:block repos #1446

Description

@philluiz2323

Summary

The pre-submission gate predictor (buildPredictedGateVerdict, src/rules/predicted-gate.ts) tells a contributor a PR will pass, while the live gate one-shot auto-closes it, on a repo whose public .gittensory.yml sets gate.mergeReadiness: block and leaves gate.linkedIssue unset. The predictor's whole contract is to compute the same verdict the live gate would, so this false optimism directly causes the loss it exists to prevent.

Area

MCP

Expected behavior

The composite merge-readiness gate forces the linked-issue sub-gate to block — applyMergeReadinessGate (src/rules/advisory.ts) sets linkedIssueGateMode = composite when mergeReadinessGateMode is on. The live review path collects linked-issue evidence whenever merge-readiness is enabled:

// src/queue/processors.ts — shouldCollectLinkedIssueEvidence
return settings.requireLinkedIssue || settings.linkedIssueGateMode !== "off" || mergeReadinessGateEnabled(settings);

so the live gate creates the missing_linked_issue finding and FAILS the PR. The predictor must surface the same finding under mergeReadiness so its verdict matches.

Actual behavior

The predictor derives the flag from gate.linkedIssue alone:

const requireLinkedIssue = gate.linkedIssue !== null && gate.linkedIssue !== "off";

On a mergeReadiness:block repo with linkedIssue unset (→ null), requireLinkedIssue is false, so addPullRequestFindings never creates the missing_linked_issue finding (advisory.ts: if (pr.linkedIssues.length === 0 && requireLinkedIssue)). evaluateGateCheck then runs with linkedIssueGateMode forced to block by the merge-readiness override but has no finding to act on, and the predictor returns success. The contributor sees green via gittensory_predict_gate, submits, and the live gate auto-closes the PR.

Reproduction

Predict a gate for a repo manifest { gate: { mergeReadiness: "block" } } with a PR body that links no issue (linkedIssues: []) and no matching issue in the snapshot → the predictor returns conclusion: "success" with no missing_linked_issue blocker, whereas the live gate fails on exactly that blocker.

Validation

Fix derives requireLinkedIssue from the merge-readiness term as well, mirroring shouldCollectLinkedIssueEvidence. Covered by test/unit/predicted-gate.test.ts; the new regression test fails before the fix (predicts success) and passes after, and the no-gate arm pins the false/false branch. Full local npm run test:ci green.

Metadata

Metadata

Assignees

No one assigned

    Labels

    slopAI slop and/or attempts to game additional points via manipulation or alt profiles.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions