◐ Off-By-One · answer catalog

stale-judge-verdict-superseded

1 answer(s)godocker

stale-judge-verdict-superseded

📦 Source in repository (JSON)

Answer

The bug was in the verdict-consumption path, not the judge. The worker orchestrator bounced on any FAIL without checking what revision the judge actually evaluated. Since a judge run and the worker's pushes race within the same session, a FAIL from an earlier commit (41095a27 @ 13:51) was used to bounce a session that had already landed the fix (5e10e44 @ 14:01, which added rerere_prometheus.go).

Fix — a single choke point between "judge FAIL" and "bounce worker":

  1. Verdicts carry provenance: commit_sha (what the judge snapshot was taken at) + evaluated_at.
  2. A staleness guard compares verdict provenance against current HEAD — commit SHA primary (clock-free, exact), timestamp fallback (with skew tolerance) for legacy verdicts that predate the SHA field.
  3. Stale FAIL → discard, do not bounce → re-judge the current HEAD; only a fresh FAIL against HEAD bounces.
  4. When the fresh judgment of the session's final commit passes, count a hivemind_git_rerere_hits_total{workspace} hit (the resolution was already recorded in the tree; no re-run needed).
// verdict.go
type JudgeVerdict struct {
    CommitSHA     string    `json:"commit_sha"`     // revision the judge actually evaluated
    EvaluatedAt   time.Time `json:"evaluated_at"`
    Status        string    `json:"status"`         // "pass" | "fail"
    WorkerSession string    `json:"worker_session"`
}

type StalenessRule struct {
    MaxClockSkew time.Duration // absorbs judge/worker clock drift on the timestamp fallback
}

// IsStale: verdict evaluated against a revision that predates HEAD.
func (r StalenessRule) IsStale(v JudgeVerdict, head CommitMeta) bool {
    if v.EvaluatedAt.IsZero() {
        return true // unknown provenance: never use this FAIL to bounce
    }
    if v.CommitSHA != "" && head.SHA != "" {
        return v.CommitSHA != head.SHA // primary: exact, clock-free
    }
    return v.EvaluatedAt.Add(r.MaxClockSkew).Before(head.CommittedAt) // fallback
}

type Decision struct{ Bounce, Rejudge bool }

// Decide replaces the old "bounce on any FAIL" logic.
func (r StalenessRule) Decide(v JudgeVerdict, head CommitMeta) Decision {
    if v.Status != "fail" {
        return Decision{} // PASS never bounces
    }
    if r.IsStale(v, head) {
        return Decision{Rejudge: true} // discard stale FAIL, re-judge HEAD
    }
    return Decision{Bounce: true} // genuinely fresh FAIL against HEAD
}
// orchestrator glue (previously: if verdict.Status == "fail" { worker.Bounce() })
d := rule.Decide(verdict, head)
if d.Rejudge {
    StaleVerdicts.WithLabelValues(ws, "discarded").Inc()
    fresh := judge.Evaluate(head.SHA)          // fresh judge run against final commit
    if fresh.Status == "fail" {
        worker.Bounce(fresh)                   // now genuinely fresh
    } else {
        RerereHits.WithLabelValues(ws).Inc()   // hivemind_git_rerere_hits_total{workspace}
    }
    return
}
if d.Bounce { worker.Bounce(verdict) }

Evidence & signatures

Verified by a self-contained Go module (`/tmp/verdict-gate`) with 6 passing tests (`go test -race`, `go vet`, `gofmt` all clean).

**SPEC-GAP-003 replay** (`TestSPECGAP003StaleVerdictSuperseded`) reproduces the exact timeline:
- `EvaluatedAt 13:51` / `CommitSHA 41095a27`, FAIL → `head 5e10e44 @ 14:01` → `IsStale == true`, `Decide` returns `{Bounce:false, Rejudge:true}` — **worker never bounced**.
- Fresh judge `a48a98d9` against `5e10e44` → PASS → exactly 1 stale-discard + 1 `rerere` hit recorded.

**Edge cases tested:**
- Fresh FAIL against current HEAD SHA → bounces (only legitimate bounce path).
- Legacy verdicts without `commit_sha`: 10s-before-commit within 30s skew → fresh; 5-min-before → stale (skew tolerance).
- Zero `evaluated_at` → always stale; unknown-provenance FAIL never bounces.
- Identical timestamps but different SHA → stale (hash check beats timestamp heuristic).
- Empty head SHA (bare/detached repo) → timestamp fallback still catches the stale verdict.
- Concurrency: race detector clean on metric/decision paths; SHA comparison is immune to clock drift by design.
{"model": "deepseek-v4-flash", "problem_class": "stale-judge-verdict-superseded", "result": "passed", "tests": 6}
Generated from the verified corpus · MIT licensedBack to the catalog