j140 rename the lead-gain corrector: BitBrain -> LEADGAIN (+ legacy TR_BITBRAIN_* aliases)
The gun at rack id 16 learned a multiplier for Pattern's lead, separately
per range band. It was called BITBRAIN and shipped a TR_BITBRAIN_* prefix,
which is why the name read as a neural network it no longer contains.
guns/bitbrain_gun.nim -> guns/lead_gain.nim (rack id 16 UNCHANGED)
RackGunNames[16] BITBRAIN -> LEADGAIN
TR_BITBRAIN_* knobs -> TR_LEADGAIN_*
[bb] log line -> [lg]
BACKWARD COMPATIBILITY is mandatory: the live .env carries
TR_RACK_BITBRAIN=both, TR_BITBRAIN_GAINS, TR_BITBRAIN_MEM=decay and
TR_BITBRAIN_LOG=1, and those must keep behaving identically. The new ADE+SBC
gun (next commit) claims the BITBRAIN name and the TR_BITBRAIN_* prefix, so
the namespace is disambiguated by ONE deterministic switch, TR_BITBRAIN_NET
(default 0):
TR_BITBRAIN_NET unset/0 -> LEGACY: the 14 frozen legacy suffixes are aliases
for TR_LEADGAIN_*, and TR_RACK_BITBRAIN still
selects rack id 16. One [depr] line on stderr
names the new spelling of each honoured knob.
TR_BITBRAIN_NET = 1 -> the TR_BITBRAIN_* names belong to the new gun.
The legacy suffix set and the new gun's knob set are DISJOINT, so no name is
ever claimed twice; the new name always wins over its alias.
Parity: shipped rack is still onlyPattern, shipped movement is still strafe.
Guards unchanged: test_env_report 25, test_rack_membership 48,
test_tm_pattern_registration 20, test_lead_gain_registration 13 (was
test_bitbrain_registration), test_bitbrain 56, test_gun_harness 39,
test_tfil_commit_env 30. New: test_lead_gain_legacy 24.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,7 @@ import movements/strafe
|
||||
import movements/wave_surfer
|
||||
import movements/learned_surfer
|
||||
import guns/tm_horizon
|
||||
import guns/bitbrain_gun
|
||||
import guns/lead_gain
|
||||
import guns/pattern_matcher
|
||||
import vbullet_draw
|
||||
import geo_overlay
|
||||
@@ -64,7 +64,7 @@ type
|
||||
shotLogPath*: string
|
||||
disabledGuns*: HashSet[int]
|
||||
tmHorizon*: TmHorizonGun
|
||||
bitbrain*: BitBrainGun
|
||||
leadGain*: LeadGainGun
|
||||
patternMatcher*: PatternMatcherGun
|
||||
|
||||
# ── helpers ──────────────────────────────────────────────────────────────────
|
||||
@@ -113,6 +113,32 @@ proc sourceOfPresence(name: string): string =
|
||||
elif existsEnv(name): "env"
|
||||
else: "default"
|
||||
|
||||
proc legacyNameFor(name: string): string =
|
||||
## The legacy `TR_BITBRAIN_<X>` alias for a `TR_LEADGAIN_<X>` knob, or "" when
|
||||
## the knob has no legacy name / the namespace now belongs to the new gun.
|
||||
if netSwitchOwnsBitbrainName(): return ""
|
||||
if not name.startsWith(NewPrefix): return ""
|
||||
let suffix = name[NewPrefix.len .. ^1]
|
||||
for s in LegacyKnobEnvNames:
|
||||
if s == suffix: return LegacyPrefix & suffix
|
||||
""
|
||||
|
||||
proc sourceOfLg(name: string): string =
|
||||
## `sourceOf`, plus credit for the legacy `TR_BITBRAIN_*` alias. Tagged
|
||||
## `legacy` so a migrated name is distinguishable from an unmigrated one.
|
||||
let legacy = legacyNameFor(name)
|
||||
if legacy.len > 0 and getEnv(name, "").len == 0 and getEnv(legacy, "").len > 0:
|
||||
if isFromEnvFile(legacy): "legacy/.env" else: "legacy"
|
||||
else:
|
||||
sourceOf(name)
|
||||
|
||||
proc sourceOfLgPresence(name: string): string =
|
||||
let legacy = legacyNameFor(name)
|
||||
if legacy.len > 0 and not existsEnv(name) and existsEnv(legacy):
|
||||
if isFromEnvFile(legacy): "legacy/.env" else: "legacy"
|
||||
else:
|
||||
sourceOfPresence(name)
|
||||
|
||||
proc disabledGunsString(guns: HashSet[int]): string =
|
||||
if guns.len == 0: return "none"
|
||||
var ids: seq[int]
|
||||
@@ -373,29 +399,34 @@ proc printEffectiveValues(ctx: EnvReportContext) =
|
||||
sourceOf("TR_TMHORIZON_RETRAIN_EVERY"))
|
||||
emit("TR_TMHORIZON_EPOCHS", $tmh.retrainEpochs, sourceOf("TR_TMHORIZON_EPOCHS"))
|
||||
|
||||
# ── the BitBrain ADE+SBC corrector ────────────────────────────────────────
|
||||
# All knobs are resolved at gun construction (`initBitBrainGun`), so the
|
||||
# context holds the real values. The network itself is only built on the first
|
||||
# `predict`, which is why `[rack]` membership is the actual enable switch.
|
||||
emit("TR_BITBRAIN_MEM", memModeName(ctx.bitbrain.memMode),
|
||||
sourceOf(BB_MEM_ENV))
|
||||
emit("TR_BITBRAIN_GAINS", bbGainsString(ctx.bitbrain.cands),
|
||||
sourceOf(BB_GAINS_ENV))
|
||||
emit("TR_BITBRAIN_N", $ctx.bitbrain.nClasses, sourceOf(BB_N_ENV))
|
||||
emit("TR_BITBRAIN_NADE", $ctx.bitbrain.nAde, sourceOf(BB_NADE_ENV))
|
||||
emit("TR_BITBRAIN_RANGE", $ctx.bitbrain.maxDeg, sourceOf(BB_RANGE_ENV))
|
||||
emit("TR_BITBRAIN_LOG", onOff(ctx.bitbrain.logEnabled),
|
||||
sourceOfPresence(BB_LOG_ENV))
|
||||
emit("TR_BITBRAIN_MIN_OBS", $ctx.bitbrain.minObs, sourceOf(BB_MIN_OBS_ENV))
|
||||
emit("TR_BITBRAIN_WARMUP", $ctx.bitbrain.warmupN, sourceOf(BB_WARMUP_ENV))
|
||||
emit("TR_BITBRAIN_ADAPT", $ctx.bitbrain.adaptEvery, sourceOf(BB_ADAPT_ENV))
|
||||
emit("TR_BITBRAIN_CALIB", $ctx.bitbrain.calibEvery, sourceOf(BB_CALIB_ENV))
|
||||
emit("TR_BITBRAIN_DECAY", $ctx.bitbrain.decayEvery, sourceOf(BB_DECAY_ENV))
|
||||
emit("TR_BITBRAIN_DECAY_FRAC", $ctx.bitbrain.decayFrac,
|
||||
sourceOf(BB_DECAY_FRAC_ENV))
|
||||
emit("TR_BITBRAIN_SEED", $ctx.bitbrain.seed, sourceOf(BB_SEED_ENV))
|
||||
emit("TR_BITBRAIN_RESET_ON_TARGET", onOff(ctx.bitbrain.resetOnTarget),
|
||||
sourceOf(BB_RESET_ON_TARGET_ENV))
|
||||
# ── the LEADGAIN per-range-band lead-gain corrector ───────────────────────
|
||||
# All knobs are resolved at gun construction (`initLeadGainGun`), so the
|
||||
# context holds the real values. `sourceOfLg`/`sourceOfLgPresence` also
|
||||
# credit the LEGACY `TR_BITBRAIN_*` alias, so a pre-rename `.env` shows up as
|
||||
# coming from the env (tagged `legacy`) instead of silently reading default.
|
||||
let lg = ctx.leadGain
|
||||
emit("TR_LEADGAIN_MEM", memModeName(lg.memMode), sourceOfLg(LG_MEM_ENV))
|
||||
emit("TR_LEADGAIN_GAINS", lgGainsString(lg.cands), sourceOfLg(LG_GAINS_ENV))
|
||||
emit("TR_LEADGAIN_N", $lg.nClasses, sourceOfLg(LG_N_ENV))
|
||||
emit("TR_LEADGAIN_NADE", $lg.nAde, sourceOfLg(LG_NADE_ENV))
|
||||
emit("TR_LEADGAIN_RANGE", $lg.maxDeg, sourceOfLg(LG_RANGE_ENV))
|
||||
emit("TR_LEADGAIN_LOG", onOff(lg.logEnabled), sourceOfLgPresence(LG_LOG_ENV))
|
||||
emit("TR_LEADGAIN_MIN_OBS", $lg.minObs, sourceOfLg(LG_MIN_OBS_ENV))
|
||||
emit("TR_LEADGAIN_WARMUP", $lg.warmupN, sourceOfLg(LG_WARMUP_ENV))
|
||||
emit("TR_LEADGAIN_ADAPT", $lg.adaptEvery, sourceOfLg(LG_ADAPT_ENV))
|
||||
emit("TR_LEADGAIN_CALIB", $lg.calibEvery, sourceOfLg(LG_CALIB_ENV))
|
||||
emit("TR_LEADGAIN_DECAY", $lg.decayEvery, sourceOfLg(LG_DECAY_ENV))
|
||||
emit("TR_LEADGAIN_DECAY_FRAC", $lg.decayFrac, sourceOfLg(LG_DECAY_FRAC_ENV))
|
||||
emit("TR_LEADGAIN_SEED", $lg.seed, sourceOfLg(LG_SEED_ENV))
|
||||
emit("TR_LEADGAIN_RESET_ON_TARGET", onOff(lg.resetOnTarget),
|
||||
sourceOfLg(LG_RESET_ON_TARGET_ENV))
|
||||
# The disambiguation switch + the deprecation line it gates, in the report so
|
||||
# an owner staring at a `[depr]` line can see exactly why it fired.
|
||||
emit("TR_BITBRAIN_NET", onOff(netSwitchOwnsBitbrainName()),
|
||||
sourceOfPresence("TR_BITBRAIN_NET"))
|
||||
let dep = lgDeprecationLine()
|
||||
if dep.len > 0: emit("legacy TR_BITBRAIN_* aliases honoured", "yes", "legacy")
|
||||
else: emit("legacy TR_BITBRAIN_* aliases honoured", "no", "default")
|
||||
|
||||
# ── Pattern match-shape + radial knobs ────────────────────────────────────
|
||||
# These are resolved lazily inside `predict` (which has not run at boot), so
|
||||
@@ -451,9 +482,14 @@ proc printModules(ctx: EnvReportContext) =
|
||||
# Guns. Rack membership IS the on/off switch: `off` = disabled, any other
|
||||
# mode = enabled in that rack.
|
||||
for i in 0..<len(RackGunNames):
|
||||
var src = sourceOf(RackEnvPrefix & RackGunNames[i])
|
||||
if src == "default" and not netSwitchOwnsBitbrainName():
|
||||
for (key, gid) in RackLegacyAlias:
|
||||
if gid == i and getEnv(key, "").len > 0:
|
||||
src = if isFromEnvFile(key): "legacy/.env" else: "legacy"
|
||||
emitModule("gun." & RackGunNames[i].toLowerAscii(),
|
||||
ActiveRackMembership[i] != rmOff,
|
||||
sourceOf(RackEnvPrefix & RackGunNames[i]),
|
||||
src,
|
||||
"rack: " & rackMembershipName(ActiveRackMembership[i]))
|
||||
|
||||
# Movement engines + the engine the tick actually runs.
|
||||
@@ -552,15 +588,26 @@ proc knownEnvNames*(): seq[string] =
|
||||
TMH_SHIFT_ENV, TMH_BIG_MULT_ENV, TMH_LOG_ENV, TMH_RESET_ON_TARGET_ENV,
|
||||
TMH_WINDOW_ENV, TMH_RESET_DROP_ENV, TMH_NSTATES_ENV, TMH_ACCURVE_ENV,
|
||||
TMH_RETRAIN_EVERY_ENV, TMH_EPOCHS_ENV,
|
||||
BB_MEM_ENV, BB_GAINS_ENV, BB_N_ENV, BB_NADE_ENV, BB_RANGE_ENV, BB_LOG_ENV,
|
||||
BB_MIN_OBS_ENV, BB_WARMUP_ENV, BB_ADAPT_ENV, BB_CALIB_ENV, BB_DECAY_ENV,
|
||||
BB_DECAY_FRAC_ENV, BB_SEED_ENV, BB_RESET_ON_TARGET_ENV,
|
||||
LG_MEM_ENV, LG_GAINS_ENV, LG_N_ENV, LG_NADE_ENV, LG_RANGE_ENV, LG_LOG_ENV,
|
||||
LG_MIN_OBS_ENV, LG_WARMUP_ENV, LG_ADAPT_ENV, LG_CALIB_ENV, LG_DECAY_ENV,
|
||||
LG_DECAY_FRAC_ENV, LG_SEED_ENV, LG_RESET_ON_TARGET_ENV, LG_NET_SWITCH_ENV,
|
||||
# LEGACY aliases of the corrector knobs above (honoured while
|
||||
# LG_NET_SWITCH_ENV is off). Registered so the tree-scan guard does not
|
||||
# flag the owner's pre-rename .env as unknown.
|
||||
"TR_BITBRAIN_GAINS", "TR_BITBRAIN_MEM", "TR_BITBRAIN_MIN_OBS",
|
||||
"TR_BITBRAIN_DECAY", "TR_BITBRAIN_DECAY_FRAC", "TR_BITBRAIN_LOG",
|
||||
"TR_BITBRAIN_RESET_ON_TARGET", "TR_BITBRAIN_N", "TR_BITBRAIN_NADE",
|
||||
"TR_BITBRAIN_RANGE", "TR_BITBRAIN_WARMUP", "TR_BITBRAIN_ADAPT",
|
||||
"TR_BITBRAIN_CALIB", "TR_BITBRAIN_SEED",
|
||||
# common_libs/bitbrain (counted-SBC library) reads these inline; job j102
|
||||
"TR_BITBRAIN_MODE", "TR_BITBRAIN_DECAY_EVERY", "TR_BITBRAIN_DECAY_SHIFT",
|
||||
]
|
||||
# rack names are constructed from the prefix + gun table, not spelled out
|
||||
for g in RackGunNames:
|
||||
result.add RackEnvPrefix & g
|
||||
# the LEGACY rack name of the renamed corrector (still honoured while
|
||||
# LG_NET_SWITCH_ENV is off — see gun_harness/selector's RackLegacyAlias)
|
||||
for (key, _) in RackLegacyAlias: result.add key
|
||||
# inline reads with no exported constant (the guard test scans for these)
|
||||
for n in [
|
||||
"GUN_SELECTOR_WINDOW", "GUN_SELECTOR_MINOBS", "GUN_SELECTOR_TIE",
|
||||
|
||||
Reference in New Issue
Block a user