;; ported-from: src/gate.ts @ v1.0.0 (extracted-from: bot/src/rl/train.ts @ fa686ee,
;; the candidate-file dance every per-game trainer repeated)
;;
;; Promotion gating, file side. A trainer always resumes from the strongest
;; thing it has (the promoted live checkpoint if any, else the still-improving
;; candidate) and writes back through the gate: promoted models land on the
;; live path the bots reload, unpromoted ones stay candidates. The gate
;; PREDICATES (thresholds, eval episode loops) are deliberately per-game and
;; stay in the consumer: what "beats the baseline" means is game knowledge.
(ns ardegazu.train.gate
(:require [ardegazu.train.checkpoint :as checkpoint]))
(defn resolve-model
"The promoted checkpoint if present, else the unpromoted candidate."
[model-dir game]
(let [promoted (checkpoint/load-model (checkpoint/checkpoint-path model-dir game))]
(if (some? promoted)
promoted
(checkpoint/load-model (checkpoint/candidate-path model-dir game)))))
(defn gate-promotion
"Write to <game>.json when promoted, else <game>.candidate.json; returns the path."
[model-dir game model promoted]
(let [file (if promoted
(checkpoint/checkpoint-path model-dir game)
(checkpoint/candidate-path model-dir game))]
(checkpoint/save-model file model)
file))