docs(env): 6-block env reference + .env.example, every claim traceable
Rewrites docs/env_reference.md and ModularBot_garage/.env.example so a reader can act on the file without re-deriving anything, and so every claim in it can be checked. WHAT 177 knobs documented across a 6-block format: WHAT / VALUES / STATUS / GOTCHA / TRY. Values are the built-in defaults, so `.env.example` is behaviourally identical to a clean run. No default value changed anywhere; the only added key is TR_FIRE_LAG=0, which is real (fire_tracker.nim:164). WHY (traceability) Every STATUS line now cites the job or commit behind the claim it makes. A documented default is only useful if you can tell whether it was verified or copied by hand; the citation makes that decidable without re-running the experiment. The presence-gated list was wrong: it claimed 7 knobs, the true number is 10. Three knobs were also wrongly labelled presence-gated; they are value-based and are now documented as such. All 31 `# TRY:` example values were checked against the code that parses them, so no example is rejected when copied. VERIFICATION Round-trip (j172 probe: printEnvReport clean vs .env.example applied through the repo's own env_dotenv loader, reports diffed): 0 mismatches, 0 warnings, 0 dropped keys (177 in file, 177 seen). Re-run after this commit's comment edit, unchanged. test_tfil_commit_env 159 PASS / 0 FAIL test_env_report 25 PASS / 0 FAIL test_tfil_ring_weights 24 PASS / 0 FAIL (earlier in the series) Also drops the stale "snapshot of commit 5e32ec1" pin from .env.example: a pinned hash goes stale the moment the next commit lands, which makes the "regenerate when a default changes" instruction worse than none. The line now just says the values mirror current defaults.
This commit is contained in:
+115
-5
@@ -47,13 +47,123 @@ misled people:**
|
||||
warning at all**.
|
||||
2. **Some flags are presence-based, not value-based.** They are read with
|
||||
`existsEnv`, so **`TR_POWER_LOG=0` turns the log ON** (any value does).
|
||||
Presence-based: `TR_POWER_LOG`, `TR_RAM_LOG`, `TR_MOVEMENT_LOG`,
|
||||
`TR_RECORD_WORLDSTATE`, `TR_RADAR_FORCE_SPIN`, `TR_RADAR_SCANLOG`,
|
||||
`TR_TRACKER_PROBE`. Value-based (`0`/`false`/`off` really disable):
|
||||
`TR_ENV_REPORT`, `TR_TMHORIZON_LOG`, `TR_TMHORIZON_ACCURVE`,
|
||||
Value-based (`0`/`false`/`off` really disable): `TR_ENV_REPORT`,
|
||||
`TR_TMHORIZON_LOG`, `TR_TMHORIZON_ACCURVE`,
|
||||
`TR_TMHORIZON_RESET_ON_TARGET`, `TR_POWER_POLICY`, `TR_POWER_FINISH_KILL`,
|
||||
`TR_RAM_OPPORTUNITY`, `TR_RAM_PLAN`, `GUN_SELECTOR_POOL`,
|
||||
`TR_VBULLET_ADMIT_ONLY`.
|
||||
`TR_VBULLET_ADMIT_ONLY`, `TR_LEADGAIN_LOG`, `TR_LEARNED_LOG`,
|
||||
`TR_LEARNED_GLOBAL`, `TR_LEARNED_REAL_EVENTS`, `TR_FIRE_FIX`,
|
||||
`TR_STRAFE_FIRE_FIX`, `TR_STRAFE_ESCAPE`, `TR_STRAFE_HEAT_GRID`,
|
||||
`TR_TFIL_HEAT_TIME`, `TR_TFIL_PILLAR_ON`, `TR_TFIL_DIAG`, `TR_TFIL_NO_REV`,
|
||||
`TR_TFIL_HOLD_WHEN_TRAPPED`, `TR_TFIL_COMMIT_ARRIVAL`,
|
||||
`TR_TFIL_RING_COMMIT_ARRIVAL`, `TR_VBULLET_DEBUG`, `TR_GEO_DEBUG`,
|
||||
`TR_DEBUG_DRAW`, `TR_RESULT_LOG`.
|
||||
|
||||
### THE FULL PRESENCE-GATED LIST (j172, from `grep -rn existsEnv`)
|
||||
|
||||
The list above was **incomplete**: it was missing four knobs. The complete set,
|
||||
from `grep -rn 'existsEnv' ModularBot_garage/src common_libs | grep -v /tests/`,
|
||||
is:
|
||||
|
||||
| knob | read at | what it logs / does |
|
||||
|---|---|---|
|
||||
| `TR_POWER_LOG` | `ModularBot.nim:145` | one line per power-decision CHANGE |
|
||||
| `TR_RAM_LOG` | `ram_decision.nim:119` | one line per ram start/stop + reason |
|
||||
| `TR_MOVEMENT_LOG` | `the_floor_is_lava_ring.nim:192` | movement band / range-class changes |
|
||||
| `TR_STRAFE_LOG` | `strafe.nim:402` | one line per strafe tile pick |
|
||||
| `TR_SURF_LOG` | `wave_surfer.nim:102` | one line per wave-surfing decision |
|
||||
| `TR_FIRE_DIAG` | `ModularBot.nim:137`, `the_floor_is_lava.nim:299`, `strafe.nim:415` | per-reading fire-detection tick/raw/correction |
|
||||
| `TR_RECORD_WORLDSTATE` | `ModularBot.nim:70` | dump every observed world state |
|
||||
| `TR_RADAR_SCANLOG` | `ModularBot.nim:80` | log every radar scan tick |
|
||||
| `TR_RADAR_FORCE_SPIN` | `ModularBot.nim:79` | force the old full-360 spin radar |
|
||||
| `TR_TRACKER_PROBE` | `ModularBot.nim:86` | dump the enemy-tracker internals |
|
||||
|
||||
**For these ten, `NAME=0` turns the feature ON.** OFF means the line is ABSENT.
|
||||
That is why `.env.example` shows every one of them commented out: there is no
|
||||
"off" spelling, only absence. To disable one, delete its line.
|
||||
|
||||
Two more are read with `existsEnv` but are *not* features — `TR_ENV_FILE` (an
|
||||
empty value is the correct "use the default" spelling) and the loader's own
|
||||
`existsEnv(e.key)` conflict check.
|
||||
|
||||
**And one label is misleading:** `env_report.nim` prints `TR_TFIL_DIAG`,
|
||||
`TR_TFIL_HOLD_WHEN_TRAPPED`, `TR_TFIL_COMMIT_ARRIVAL` and
|
||||
`TR_TFIL_RING_COMMIT_ARRIVAL` through `sourceOfPresence`, but all four are read
|
||||
**by value** (`getEnvBool`) in the source. The value is always right; only the
|
||||
`(source: ...)` label is affected. Do not read that label as "presence-gated".
|
||||
|
||||
---
|
||||
|
||||
## ONE EXPERIMENT, END TO END (mirrored from `.env.example`)
|
||||
|
||||
Pick ONE knob. Here it is `TR_TFIL_ARRIVE_TICKS`; the shape is the same for
|
||||
every knob.
|
||||
|
||||
```sh
|
||||
# 1. write the arm as its own file — that is how you GUARANTEE the arm, because
|
||||
# nothing else can be applied on top of it
|
||||
cat > /tmp/arm_arrive15.env <<'EOF'
|
||||
TR_MOVEMENT=tfil
|
||||
TR_TFIL_ARRIVE_TICKS=15.0
|
||||
EOF
|
||||
|
||||
# 2. RESTART THE BOT. Env is read ONCE, at boot (module init). Editing .env
|
||||
# while the bot runs changes nothing; there is no live reload.
|
||||
cd ModularBot_garage && ./ModularBot.sh # or restart the GUI
|
||||
|
||||
# 3. CONFIRM IT TOOK EFFECT, before reading a single result line.
|
||||
# `source: .env` = your file was applied. `source: default` = it was not.
|
||||
grep '^\[env\]' /tmp/modularbot_stdout.log | grep -E 'env file|ARRIVE_TICKS'
|
||||
# [env] env file: /tmp/arm_arrive15.env (source: TR_ENV_FILE)
|
||||
# [env] TR_TFIL_ARRIVE_TICKS = 15.0 (source: .env)
|
||||
|
||||
# 4. point at the file instead of copying it into .env:
|
||||
TR_ENV_FILE=/tmp/arm_arrive15.env ./out/ModularBot
|
||||
./out/ModularBot --env-file /tmp/arm_arrive15.env
|
||||
# A file you ASKED for and that does not exist stops the bot with an error; a
|
||||
# missing default .env is silent. This is what an A/B run does: one frozen
|
||||
# binary, one env file per arm.
|
||||
|
||||
# 5. what is switched on at all:
|
||||
grep '^\[modules\]' /tmp/modularbot_stdout.log
|
||||
```
|
||||
|
||||
## SAFE TO EXPERIMENT WITH RIGHT NOW
|
||||
|
||||
The honest list is SHORT: after the recent campaign most experimental knobs are
|
||||
either never live-tested or already measured null/harmful, and `.env.example`
|
||||
says so on every one of them. These four are safe in the sense that they either
|
||||
cannot change a decision, or are the ones a measurement actually supports.
|
||||
|
||||
| knob | what changes | what to watch | a good result |
|
||||
|---|---|---|---|
|
||||
| `TR_GEO_DEBUG=on` | draw-only geometry overlay | the circles on the two tanks, each heading line | you can SEE the tile the picker chose; it cannot change a decision |
|
||||
| `TR_VBULLET_DEBUG=1` + `TR_VBULLET_DEBUG_GUN=all` | draw-only: each admitted gun's virtual bullets | travelled path, aim ring, miss vector | you can see the signal the selector ranks on; also draw-only |
|
||||
| `TR_TFIL_DIAG=on` | fills the per-pick loss histogram (tfil only) | the tfil pick log line | `sReach/sCool/sSafe/sCand` tell you where tiles are lost; provably moves no command |
|
||||
| `TR_MOVEMENT=tfil` | runs the long-shipped mover | nothing to compare against | you are reproducing an older, documented behaviour; only do it together with the `TR_TFIL_*` knobs |
|
||||
|
||||
## ALREADY REJECTED OR MEASURED NULL — WITH THE NUMBER
|
||||
|
||||
Do not re-run these by accident.
|
||||
|
||||
| knob / arm | result | where |
|
||||
|---|---|---|
|
||||
| `TR_TFIL_GEO_MODE=both-rej` + `TR_TFIL_GEO_TAU=60` | **REJECTED** live, 420 battles, 15 opponents: damage/run **-8.83**, p(sign-flip) **0.0061**, Wilcoxon p 0.011. Round wins null. Offline it did what was predicted (arrivals 4.5% -> 29.4%) and that is why it is bad: +26 px distance on 15/15, less damage. | `docs/tfil_geo_ab.md` |
|
||||
| `TR_RAM_FLOOR_ENERGY=5` | **CLEAN NULL**: **-0.018 wins/run**, p(sign-flip) **0.7676**, under a **0.1420 wins/run** MDE, 900 battles. Mechanism fired on 0.04% of ticks (~200x less than the offline ruler said). Do not re-test: more runs buy resolution on an effect that is not there. | `docs/ram_floor_exhaustion_ab.md` |
|
||||
| `TR_RAM_FLOOR_ENERGY=10/20` | measured COSTLY offline (20 blocked 24.7% of all ticks) and the zone it guards is nearly empty: only 4.8% of shots are taken below 10 energy. | same |
|
||||
| `TR_TMHORIZON_WINDOW=150` | **MEASURED HARMFUL** live: 26.5% round wins vs 49.0% for the shipped rack, p = 0.036. Keep 0. | env_reference "Measured verdicts" |
|
||||
| `TR_POWER_POLICY=0` | **MEASURED HARMFUL** live: real hit rate 10.61% -> 7.88%, p = 0.0012. | same |
|
||||
| `TR_TFIL_HEAT_TIME=1` | **MEASURED HARMFUL** live at every tau tried (3/5/9/15); tau15 alone is -22 damage/run, p = 0.046. | `docs/tfil_heat_pillar_ab.md` |
|
||||
| `TR_MOVEMENT=tfil_ring` | **MEASURED**: round wins 16/49 -> 6/49, p = 0.012. Best live hit rate of anything measured, half the survival. | same / env_reference |
|
||||
| the full `TR_RACK_*` rack | **MEASURED NEGATIVE VALUE**: Pattern ALONE beats the full 13-gun rack, p = 0.0012. Adding guns costs rounds. | `docs/gun_rack_analysis.md` |
|
||||
| `TR_TFIL_TURN_BIAS=9` + `_TURN_REF_DEG=0` | **LIVE NULL**: +0.15 wins/run, p(sign) 0.244, under a 0.30 MDE, 300 battles. | `docs/movement_campaign.md` (j145) |
|
||||
| `TR_RAM_OPPORTUNITY=on` | **MEASURED not to convert**: 0/59 opportunity -> contact. The finisher ram is the only path that converts, and it is always on. | env_reference |
|
||||
| `TR_TFIL_PILLAR_ON=1` | live-tested, and the recommendation to revert to pillar-on was **OVERRULED by the owner**: the contrast is inside the MDE (33 damage/run, 1.22 wins/run at n=10). Pillar stays removed. | `docs/tfil_heat_pillar_ab.md` |
|
||||
|
||||
> **A null is only a null at the resolution that run reached.** The frozen
|
||||
> 15-opponent panel at 14 runs/arm resolves ~0.17 wins/run and ~7.65 damage/run;
|
||||
> the j163 run resolved 0.1420 wins/run. "Clean null" here means *no effect at or
|
||||
> above that size* — not *no effect*.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user