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.
This commit is contained in:
2026-09-22 23:46:56 +02:00
parent 9ba932d1b1
commit 81af5854df
3 changed files with 8 additions and 7 deletions
+2 -2
View File
@@ -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
@@ -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`",