fix: harden partial 429 success, fallbacks, zh errors
Gatekeep evals / eval-floor (push) Successful in 3s
Gatekeep evals / eval-floor (pull_request) Successful in 15s
Gatekeep / gatekeep (pull_request) Failing after 1m46s

Retry HTTP 429 with backoff; keep models beyond first 3 as
fallbacks; degrade agreement when some models fail; force-high
risk only if zero usable responses. Clearer zh-CN errors/docs for
dogfood uses: ./ rebase + workflow_dispatch re-run.
This commit is contained in:
layue13 committed 2026-10-27 08:35:52 +00:00
1 parent ef13f8806a
commit c6c2d071fb
10 files changed
+193 -61

No files matched your search

+15 -5
View File
@@ -167,10 +167,22 @@ for (const m of models) {
}
}
// Prefer successful model tiers; only if every call failed, fail-closed high.
const okModels = models.filter((m) => !m.error);
const modelErrors = models.filter((m) => m.error).length;
const degraded = modelErrors > 0 || okModels.length < agreementMin;
// When some models 429/fail, lower the bar to surface usable findings from survivors
// (still require at least 1 successful model). Full fail-closed high only if zero ok.
let effectiveAgreement = agreementMin;
if (okModels.length > 0 && okModels.length < agreementMin) {
effectiveAgreement = Math.max(1, okModels.length);
}
const agreed = [];
const disputed = [];
for (const f of bucket.values()) {
if (f.models.length >= agreementMin) agreed.push(f);
if (f.models.length >= effectiveAgreement) agreed.push(f);
else disputed.push(f);
}
@@ -178,8 +190,6 @@ const bySeverity = (a, b) => (sevRank[a.severity] ?? 9) - (sevRank[b.severity] ?
agreed.sort(bySeverity);
disputed.sort(bySeverity);
// Prefer successful model tiers; only if every call failed, fail-closed high.
const okModels = models.filter((m) => !m.error);
const tierSources = okModels.length ? okModels : models;
let risk_tier = floor;
for (const m of tierSources) risk_tier = maxTier(risk_tier, m.risk_tier);
@@ -193,13 +203,13 @@ if (scanHardFail) risk_tier = maxTier(risk_tier, "high");
const openSecurityBlocking =
scanHardFail || agreed.some((f) => (f.kind === "security" || f.severity === "Critical") && f.blocking);
const modelErrors = models.filter((m) => m.error).length;
const result = {
risk_tier,
policy_floor: floor,
agreement_min: agreementMin,
effective_agreement_min: effectiveAgreement,
language,
degraded,
model_errors: modelErrors,
models_ok: okModels.length,
models: models.map((m) => ({