@@ -41,6 +41,7 @@ import {
4141} from "./auto-tune" ;
4242import { computeGateEval } from "./parity" ;
4343import { LOOPOVER_NATIVE_SOURCE } from "./parity-wire" ;
44+ import { computeBlendedRuleGateEval , rulesBelowClosePrecisionFloor } from "./rule-gate-eval" ;
4445
4546/** PURE: parse the PR number an "Reverts #N / Reverts owner/repo#N" body refers to (GitHub's revert PRs).
4647 * Mirrors reviewbot runtime.ts parseRevertedPrNumber. Returns undefined when the body isn't a revert. */
@@ -219,6 +220,46 @@ export function createFlagStore(env: Env): FlagStore {
219220 } ;
220221}
221222
223+ // #7986: which deterministic rule codes currently sit below their OWN measured close-precision floor
224+ // (rulesBelowClosePrecisionFloor over computeBlendedRuleGateEval, #7984) — a cheap, cron-refreshed cache of an
225+ // otherwise-expensive fleet-wide aggregate, reusing system_flags (a generic key/value table, not booleans-only
226+ // despite its FlagStore-facing name above) so no schema change is needed. Mirrors the SAME "expensive compute
227+ // on a cron tick, cheap single-row read at decision time" split isHoldOnly/isCloseHoldOnly already use for the
228+ // project-level breaker flags. FAIL-SAFE: a read error, missing row, or unparseable value degrades to an EMPTY
229+ // set — exactly #7986's own "insufficient/unavailable data defaults to keeping the exemption" rule, never the
230+ // opposite direction (a read failure must never spuriously revoke every rule's exemption at once).
231+ const UNTRUSTWORTHY_RULE_CODES_FLAG_KEY = "rule_untrustworthy_codes:global" ;
232+
233+ /** Read the cron-cached set of rule codes currently below their close-precision floor. See this constant's own
234+ * doc comment above for the fail-safe contract. */
235+ export async function readUntrustworthyRuleCodes ( env : Env ) : Promise < ReadonlySet < string > > {
236+ try {
237+ const row = await env . DB . prepare ( "SELECT value FROM system_flags WHERE key = ?" )
238+ . bind ( UNTRUSTWORTHY_RULE_CODES_FLAG_KEY )
239+ . first < { value : string } > ( ) ;
240+ if ( ! row ?. value ) return new Set ( ) ;
241+ const parsed : unknown = JSON . parse ( row . value ) ;
242+ if ( ! Array . isArray ( parsed ) ) return new Set ( ) ;
243+ return new Set ( parsed . filter ( ( code ) : code is string => typeof code === "string" ) ) ;
244+ } catch {
245+ return new Set ( ) ;
246+ }
247+ }
248+
249+ /** Write the cron-computed set of rule codes currently below their close-precision floor, replacing whatever
250+ * was cached before (this is a SNAPSHOT, not an append-only log — a code that recovers or that no longer has
251+ * a large enough sample must disappear from the set on the next tick, not linger). Best-effort: a write
252+ * failure is swallowed, matching every other cron-tick cache write in this module — the NEXT tick will retry,
253+ * and until then {@link readUntrustworthyRuleCodes} keeps serving the last successfully-written snapshot. */
254+ async function writeUntrustworthyRuleCodes ( env : Env , codes : readonly string [ ] ) : Promise < void > {
255+ await env . DB . prepare (
256+ "INSERT OR REPLACE INTO system_flags (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)" ,
257+ )
258+ . bind ( UNTRUSTWORTHY_RULE_CODES_FLAG_KEY , JSON . stringify ( [ ...codes ] ) )
259+ . run ( )
260+ . catch ( ( ) => undefined ) ;
261+ }
262+
222263// ── review_audit append (the canonical eval/parity store) ───────────────────────────────────────────────────
223264
224265/** The target_id the gate-decision writer (parity-wire.ts) stamps — `project#pr`. The pr_outcome/reversal rows
@@ -766,6 +807,16 @@ export async function runSelfTuneBreaker(env: Env): Promise<void> {
766807
767808 await runBreakerPassForReport ( flags , plainPass . report , plainPass . engagedHoldonly , plainPass . engagedClosehold , nowMs , "" ) ;
768809 await runBreakerPassForReport ( flags , minerPass . report , minerPass . engagedHoldonly , minerPass . engagedClosehold , nowMs , "miner_" ) ;
810+
811+ // #7986: refresh the per-rule track-record cache the concrete-evidence breaker exemption reads
812+ // (readUntrustworthyRuleCodes) -- SAME window, pooled cross-project (a rule's trustworthiness is a
813+ // property of the rule, not of any one repo it happened to trip). Independent of the two passes above:
814+ // a failure here must not prevent (and does not roll back) the merge/close breaker engagement that just
815+ // completed -- computeBlendedRuleGateEval and writeUntrustworthyRuleCodes are both already fail-safe on
816+ // their own, so no extra try/catch is needed beyond this function's own outer one.
817+ const ruleReport = await computeBlendedRuleGateEval ( env , { days : BREAKER_EVAL_WINDOW_DAYS , nowMs, source : LOOPOVER_NATIVE_SOURCE } ) ;
818+ const untrustworthyCodes = rulesBelowClosePrecisionFloor ( ruleReport . rows ) . map ( ( row ) => row . ruleCode ) ;
819+ await writeUntrustworthyRuleCodes ( env , untrustworthyCodes ) ;
769820 } catch ( error ) {
770821 console . warn (
771822 JSON . stringify ( {
0 commit comments