From 81af5854df74603c5aab9eebb64b80269f0899fc Mon Sep 17 00:00:00 2001 From: Davide Cappellini Date: Tue, 22 Sep 2026 23:46:56 +0200 Subject: [PATCH] FIX an incomplete commit: TMHORIZON was admitted unconditionally at HEAD MY ERROR. `aed579b` committed `ModularBot.nim` (which wires the new gun as id 15) and `guns/tm_horizon.nim`, but I staged only three files and left job-72's RACK REGISTRATION behind in the working tree. Consequence at HEAD: - `common_libs/gun_harness/selector.nim` still had the 15-entry rack table (ids 0..14) with no TMHORIZON name, so - `TR_RACK_TMHORIZON` was never read (a silent no-op), and - id 15 is PAST the table, and `rackAdmitted` documents "an id past the membership table is admitted" -> **TMHORIZON was admitted unconditionally**. So the committed default rack was `Pattern + TMHORIZON`, not the intended `Pattern only`, and the gun could not be switched off by env at HEAD. This was caught by a live A/B job that had to work around it with `GUN_RACK_DISABLE=15`. FIX (this commit): the rack table goes to 16 entries with `TMHORIZON` appended at id 15 defaulting to `rmOff`, plus the two tests whose length literals follow it (`test_rack_membership` 15->16, `test_tm_pattern_registration` 15->16). `DefaultRackMembership` is again Pattern-only with every other gun `off`. NOTE ON SCOPE: `selector.nim` in the working tree also contains a CONCURRENT job's power-policy threading (an `enemyEnergy` parameter). That work is still in flight and is deliberately NOT included here - only the three rack hunks were staged. The remainder stays unstaged for its own commit. The lesson, recorded because it has bitten twice tonight in different forms: a change is not committed until its registration/table counterpart is, and `git add` of a hand-picked file list is exactly how a half-change ships. --- common_libs/gun_harness/selector.nim | 9 +++++---- common_libs/tests/test_rack_membership.nim | 4 ++-- common_libs/tests/test_tm_pattern_registration.nim | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/common_libs/gun_harness/selector.nim b/common_libs/gun_harness/selector.nim index c784948..a9dd2b3 100644 --- a/common_libs/gun_harness/selector.nim +++ b/common_libs/gun_harness/selector.nim @@ -44,10 +44,10 @@ import virtual_bullets # transition the radar uses. const - RackGunNames*: array[15, string] = [ + RackGunNames*: array[16, string] = [ "HEADON", "LINEAR", "TSETLIN", "CIRCULAR", "GUESSFACTOR", "PATTERN", "WALLBOUNCE", "ACCEL", "STOPSHOT", "DISPLACE", "AVGLEAD", "DECAYGF", - "KNN", "TMSELECT", "TMPATTERN"] + "KNN", "TMSELECT", "TMPATTERN", "TMHORIZON"] RackEnvPrefix* = "TR_RACK_" ## SHIPPED DEFAULT: `onlyPattern`. Pattern (id 5) is admitted in both racks; ## every other gun is `off`. The selection mechanism is untouched and remains @@ -57,7 +57,7 @@ const ## it never spawns a virtual bullet unless explicitly enabled, so the shared ## VirtualTracker ring head — and every other gun's learning order — is ## unchanged. - DefaultRackMembership*: array[15, RackMembership] = [ + DefaultRackMembership*: array[16, RackMembership] = [ rmOff, # 0 HEADON — off (measured: worst over-selected gun) rmOff, # 1 LINEAR — off rmOff, # 2 TSETLIN — off @@ -72,7 +72,8 @@ const rmOff, # 11 DECAYGF — off rmOff, # 12 KNN — off rmOff, # 13 TMSELECT — off - rmOff] # 14 TMPATTERN — off (already shipped off; TM pattern gun) + rmOff, # 14 TMPATTERN — off (already shipped off; TM pattern gun) + rmOff] # 15 TMHORIZON — off (horizon-based TM corrector; expected to lose) proc parseRackMembership*(value: string): RackMembership = ## Parse a `TR_RACK_` value. Empty / unknown values fall back to the diff --git a/common_libs/tests/test_rack_membership.nim b/common_libs/tests/test_rack_membership.nim index 95ea0de..38a1369 100644 --- a/common_libs/tests/test_rack_membership.nim +++ b/common_libs/tests/test_rack_membership.nim @@ -164,8 +164,8 @@ proc testDefaultsOnlyPattern() = let loaded = loadRackMembership() check "defaults: with a clean environment loadRackMembership() == shipped table", loaded == DefaultRackMembership - check "defaults: RackGunNames covers the shipped 15-gun rack", - RackGunNames.len == 15 and DefaultRackMembership.len == 15 + check "defaults: RackGunNames covers the shipped 16-gun rack", + RackGunNames.len == 16 and DefaultRackMembership.len == 16 proc testFloorRespectsAdmission() = ## The FLOOR path (`bestRate <= 0` or below the floor rate) historically fell diff --git a/common_libs/tests/test_tm_pattern_registration.nim b/common_libs/tests/test_tm_pattern_registration.nim index 692e9d8..f447059 100644 --- a/common_libs/tests/test_tm_pattern_registration.nim +++ b/common_libs/tests/test_tm_pattern_registration.nim @@ -62,7 +62,7 @@ proc seedOldRack(t: var VirtualTracker, targetId: int) = # ── registration table ──────────────────────────────────────────────────────── proc testTable() = - check "rack: RackGunNames has 15 entries", RackGunNames.len == 15 + check "rack: RackGunNames has 16 entries", RackGunNames.len == 16 check "rack: the new gun is named TMPATTERN at id 14", RackGunNames[TmPatternId] == "TMPATTERN" check "rack: the new gun defaults to `off`",