# Echo Grove: training and evaluation

This game’s policy was actually fitted with **`pytoolz.wsrf.WSRFRegressor`**. It evaluates each available action separately and chooses the greatest estimated value. Training is supervised regression; a simulation or explicit puzzle/music/clue objective supplies the targets. This is not online browser training or a claim of general reasoning.

## What was learned

A musical preference score rewarding closeness to an eight-beat call, variety, small melodic jumps, and suitable note density given player mood and choir energy. The score is explicitly designed, not learned from subjective listening ratings. The phrase rhythms come from actual pytoolz.tri_xor.evolve output, with ruler data also available in the collection. Eight phrases complete a duet regardless of quality, so compare the measured harmony score rather than completion rate. Custom tapped rhythms use the same visible rhythm-distance features.

Inputs, in order: `rhythm distance, phrase density, target density, previous density, phrase repeated, melody distance, tired musicians, beat, lively priority, quiet priority, syncopation`. The browser uses the same feature code and action-availability rules as the Node simulation. The active condition chooses the `calm` or `challenge` ensemble. Unavailable actions are excluded before ranking. World updates, animations, rules, and opponent logic are coded separately from fitted forest inference.

## Training procedure

`pt.indexrng.Index("academy-eight-v2", backend="blake2b")` generates reproducible named streams for 64 initial training episodes, 16 recovery-training episodes, 16 validation episodes, 64 test episodes, and 32 guided test episodes. Initial training trajectories include a seeded exploratory move every seventh turn. The early model has 8 trees per zone and maximum depth 10. Its guided recovery trajectories are relabeled with the same target calculation and added before a refit with 24 trees per zone and depth 18. This release selected **final**, with **5,120 training action rows** and **48 total trees**.

Both candidates play the same validation seeds. Selection maximizes wins or draws, then musical quality where applicable, then minimizes mean turns. A complete tie retains the later refit. The test split is measured afterward; model fitting never uses it. The namespace was changed for the release evaluation after initial development checks. Episode seeds are independent; some small games can still revisit the same underlying states.

Parameters include minimum leaf size 2, all features available, random seed 2026, one training worker, no adaptive complexity, zero zone-prior weight, and no calibration. Full parameters are recorded in [report.json](training/report.json). Every fitted tree is exported, with float32 input traversal to match Python’s decision trees.

## Measured results

| Policy | Wins | Mean turns | Mean harmony score |
| --- | --- | --- | --- |
| Early model | 64/64 | 8.00 | 57.80 |
| Selected model | 64/64 | 8.00 | 57.80 |
| Selected model, guided | 32/32 | 8.00 | 57.97 |
| Reference strategy | 64/64 | 8.00 | 57.80 |
| Seeded random legal moves | 64/64 | 8.00 | 30.84 |

Guided episodes change priority and conditions every five turns. Mean turns includes failures, so a quickly lost game is not a faster success. For Lantern Tactics, a win means the learned golden side wins, and the report also records draws. Other games use their explicit completion goal. Random legal moves are sampled deterministically from qrand using the episode seed and turn. Reference-strategy results are strong baselines, not a guarantee that the learned policy will beat them.

Held-out action-value mean absolute error: **0.000695**. R²: **0.999994**. These describe the training objective’s numerical targets, not a probability of winning. Python and browser predictions matched within `1e-9` on **7,765 cases**, including held-out visited states and float32 neighbors around learned thresholds. Observed maximum absolute error: `0`. The fixtures are in [validation.json](training/validation.json).

The early forest is retained as `early-forest.json`. The optional brain panel compares early and selected policies on exactly the same current board, shows actual features, and traces one tree while explaining that all trees contribute to the final estimate. A priority comparison reruns inference on the same state with balanced priorities. It does not mutate the board. Decision replay stores real before/after states; continuing from a past decision creates a new branch of the current playthrough.

## Reproduction and provenance

Recorded environment: numpy 2.5.2, pandas 3.0.5, scikit-learn 1.9.0, python 3.14.4, wsrf 8.0.0. The WSRF implementation used was `/home/wiliamrocha/CelestialsPartDeux/wsrf-lib/src/wsrf/regressor.py`. The report preserves source hashes for the estimator, data generator, training script, game rules, shared model interpreter, and prepared library data. Selected model SHA-256: `bb292a7e444ad3ca860033f1ff4015ccd43e479f9a74ef0e305e3c5bff164e64`.

From the source arcade root, using the local Python environment with pytoolz and its WSRF packages available:

```sh
/home/wiliamrocha/.spenv/bin/python -B tools/academy/prepare.py
/home/wiliamrocha/.spenv/bin/python -B tools/academy/parity.py
/home/wiliamrocha/.spenv/bin/python -B tools/academy/train.py --game echo-grove
node tools/academy/validate.cjs games/echo-grove/forest.json games/echo-grove/training/validation.json
npm run test:academy
npm run test:academy:browser
npm run build
```

Use `--game all` for all eight models. `prepare.py` uses real `rail_walk`, `ruler`, `ntcomb.submasks`, `tri_xor.evolve`, and `indexrng` calls. Existing checked qrand browser arithmetic generates reproducible game variations. `parity.py` uses real `wsrf_hlib.P2Frame` and `ParityDetector`. Sudoku path validation uses real `wsrf_spn`. The prepared mathematics has its own [source receipt](../../tools/academy/math-report.json).

Normal static builds use the committed fitted models and fixtures. Netlify needs the whole `dist/` folder, including shared scripts; it needs no Python runtime, account service, or external model API. Browser tests use Chrome at phone, tablet, and desktop sizes; physical-device testing is a separate check.
