## Backward-compatibility guard for the LEADGAIN rename (gun id 16). ## ## The owner's live `.env` predates the rename and carries `TR_RACK_BITBRAIN`, ## `TR_BITBRAIN_GAINS`, `TR_BITBRAIN_MEM`, `TR_BITBRAIN_LOG`. Those names used to ## address the corrector that is now called LEADGAIN, and they MUST keep working. ## ## The ADE+SBC gun that briefly owned the `TR_BITBRAIN_*` prefix (rack id 17, ## `guns/bitbrain_net.nim`) was RETIRED and removed, so there is nothing left to ## disambiguate: this gun is the SOLE owner of that namespace and ## ## * every `TR_BITBRAIN_` in the frozen `LegacyKnobEnvNames` set is an ## alias for `TR_LEADGAIN_`, unconditionally; ## * `TR_RACK_BITBRAIN` selects rack id 16, unconditionally; ## * a stale `TR_BITBRAIN_NET=1` left in a `.env` is an unrecognised ## variable — the boot report warns about it and nothing reads it. ## ## Run: nim c -r common_libs/tests/test_lead_gain_legacy.nim import std/[os, strutils] import gun_harness/virtual_bullets import gun_harness/selector import guns/lead_gain const LeadGainId = 16 var failures = 0 proc check(name: string, ok: bool) = if ok: echo "PASS: ", name else: echo "FAIL: ", name; inc failures proc clearEnv() = for suffix in LegacyKnobEnvNames: delEnv(LegacyPrefix & suffix) delEnv(NewPrefix & suffix) delEnv(LegacyRackEnvName) delEnv("TR_RACK_" & RackGunNames[LeadGainId]) delEnv("TR_BITBRAIN_NET") # ── the alias table itself ─────────────────────────────────────────────────── proc testAliasTableIsDisjoint() = ## Every legacy name must be a `TR_BITBRAIN_` whose `X` is in the frozen ## set, and the new name must be the `TR_LEADGAIN_` of the same suffix. var ok = LegacyKnobEnvNames.len == 14 var suffixes: seq[string] for s in LegacyKnobEnvNames: if s.len == 0 or s in suffixes: ok = false suffixes.add s check "table: 14 unique legacy suffixes", ok check "table: the legacy prefix is TR_BITBRAIN_", LegacyPrefix == "TR_BITBRAIN_" check "table: the new prefix is TR_LEADGAIN_", NewPrefix == "TR_LEADGAIN_" # The corrector's own live knobs must all be in the alias set, otherwise the # owner's `.env` silently stops working. for knob in [LG_MEM_ENV, LG_GAINS_ENV, LG_LOG_ENV, LG_MIN_OBS_ENV, LG_DECAY_ENV, LG_DECAY_FRAC_ENV, LG_RESET_ON_TARGET_ENV, LG_N_ENV, LG_NADE_ENV, LG_RANGE_ENV, LG_WARMUP_ENV, LG_ADAPT_ENV, LG_CALIB_ENV, LG_SEED_ENV]: let suffix = knob[NewPrefix.len .. ^1] if suffix notin LegacyKnobEnvNames: ok = false check "table: every corrector knob has a legacy alias", ok # ── the switch ─────────────────────────────────────────────────────────────── proc testNamespaceIsUnconditional() = ## There is no namespace switch any more. The ADE+SBC gun is gone, so a stale ## `TR_BITBRAIN_NET` left in an old `.env` is inert: it must neither disown ## the legacy knob aliases, nor the legacy rack knob, nor the deprecation line. clearEnv() putEnv("TR_BITBRAIN_MEM", "decay") putEnv("TR_BITBRAIN_LOG", "1") putEnv(LegacyRackEnvName, "both") var g = initLeadGainGun() check "ns: the legacy prefix is unconditional (no switch set at all)", g.memMode == lgDecay and g.logEnabled putEnv("TR_BITBRAIN_NET", "1") var g1 = initLeadGainGun() check "ns: a stale TR_BITBRAIN_NET=1 does not disown the legacy knob names", g1.memMode == lgDecay and g1.logEnabled putEnv("TR_BITBRAIN_NET", "0") var g2 = initLeadGainGun() check "ns: a stale TR_BITBRAIN_NET=0 is equally inert", g2.memMode == lgDecay putEnv("TR_BITBRAIN_NET", "1") check "ns: a stale TR_BITBRAIN_NET=1 does not disown the legacy rack knob", loadRackMembership()[LeadGainId] == rmBoth check "ns: a stale TR_BITBRAIN_NET=1 does not suppress the deprecation line", lgDeprecationLine().len > 0 clearEnv() # ── knob aliasing ──────────────────────────────────────────────────────────── proc testKnobAlias() = clearEnv() # the owner's exact .env putEnv("TR_BITBRAIN_GAINS", "1.0,0.5,0.25") putEnv("TR_BITBRAIN_MEM", "decay") putEnv("TR_BITBRAIN_LOG", "1") var g = initLeadGainGun() check "alias: TR_BITBRAIN_GAINS feeds the candidate set", g.cands == @[0.25, 0.5, 1.0] check "alias: TR_BITBRAIN_MEM=decay is honoured", g.memMode == lgDecay check "alias: TR_BITBRAIN_LOG=1 turns the log on", g.logEnabled # the new name always wins over the legacy alias putEnv("TR_LEADGAIN_GAINS", "0.5,0.75") var g2 = initLeadGainGun() check "alias: the NEW name wins when both are set", g2.cands == @[0.5, 0.75] # the legacy namespace is unconditional, even next to a stale NET switch putEnv("TR_BITBRAIN_NET", "1") delEnv("TR_LEADGAIN_GAINS") var g3 = initLeadGainGun() check "alias: a stale TR_BITBRAIN_NET=1 does NOT make the legacy names inert", g3.memMode == lgDecay and g3.logEnabled and g3.cands == @[0.25, 0.5, 1.0] # ... and then the NEW names still work putEnv("TR_LEADGAIN_MEM", "retained") var g4 = initLeadGainGun() check "alias: TR_LEADGAIN_* is always read, in both modes", g4.memMode == lgRetained clearEnv() # ── rack alias ─────────────────────────────────────────────────────────────── proc testRackAlias() = clearEnv() putEnv(LegacyRackEnvName, "both") let m = loadRackMembership() check "rack: TR_RACK_BITBRAIN=both still selects LEADGAIN (id 16)", m[LeadGainId] == rmBoth and vBulletAdmitted(LeadGainId, rm1v1, m, true) putEnv("TR_BITBRAIN_NET", "1") let m2 = loadRackMembership() check "rack: a stale TR_BITBRAIN_NET=1 no longer disowns the name — LEADGAIN (id 16) stays selected", m2[LeadGainId] == rmBoth and m2.len == NumRackGuns clearEnv() putEnv("TR_RACK_LEADGAIN", "both") putEnv(LegacyRackEnvName, "off") let m3 = loadRackMembership() check "rack: the new name wins over the legacy alias", m3[LeadGainId] == rmBoth clearEnv() # ── the deprecation line ───────────────────────────────────────────────────── proc testDeprecationLine() = clearEnv() check "depr: no legacy knobs => no deprecation line", lgDeprecationLine().len == 0 putEnv("TR_BITBRAIN_GAINS", "1.0") let line = lgDeprecationLine() check "depr: a legacy knob produces exactly one line naming the new name", line.startsWith("[depr]") and line.contains("TR_BITBRAIN_GAINS -> TR_LEADGAIN_GAINS") and line.contains(NewPrefix) putEnv("TR_BITBRAIN_NET", "1") check "depr: the line still fires with a stale TR_BITBRAIN_NET=1 present", lgDeprecationLine().len > 0 clearEnv() # ── shipped-default parity ─────────────────────────────────────────────────── proc testDefaultParity() = clearEnv() let m = loadRackMembership() var onlyPattern = true for i in 0.. 0: echo "\n", failures, " check(s) FAILED" quit(1) echo "\nAll LEADGAIN legacy-alias checks passed."