# Starlight Observatory: Luma’s training record

This model was fitted locally using **`pytoolz.wsrf.WSRFClassifier`**, reached through `import pytoolz as pt`. This is supervised imitation of an explicit training-only teacher, with one round of teacher relabeling on model-visited states. It is not reinforcement learning or learning during browser play.

## The game and learned decisions

Three constellations need three exposures each. Visibility changes continuously; clouds reduce it. Luma chooses observations, polishing, charging, or waiting for the sky.

The forest chooses the next discrete task at task boundaries. Smooth movement, action durations, goals, resource changes, and legal-action constraints are ordinary game rules in `shared/watch-worlds.js`. Gameplay uses the fitted forest; the teacher lives only in `tools/wsrf/watch-data.cjs` and is never loaded by the game page. The runtime ranks the model’s probabilities over legal actions and chooses the highest. Scores shown in the UI are the original forest probabilities, without renormalizing after this mask.

Inputs, in order: `battery, lens, bear_visibility, kite_visibility, whale_visibility, bear_exposures, kite_exposures, whale_exposures, focus_bear, focus_kite, focus_whale`. The weather selects either the `settled` or `changing` zone. The three priority inputs are one-hot (all zero means choose freely). A supply nudge changes resource features. An optional exact-task request overrides one decision if the action remains legal, after which the forest resumes. The model is not instructed by free-form text.

Actions, in order: 0: Study Little Bear, 1: Study Moon Kite, 2: Study Velvet Whale, 3: Polish the lens, 4: Recharge, 5: Watch the sky.

## Reproducible dataset and model selection

`pt.indexrng.Index("watch-and-guide-v1", backend="blake2b")` produces independent named streams for each game and split. It generates 32,000 synthetic training states, the seeds for 256 teacher days and 128 guided teacher days, 6,000 validation states, and 10,000 held-out test states. The simulation uses the checked integer-stream `pt.qrand` browser adapter for initial worlds. Each candidate adds teacher labels from 64 guided days visited by that candidate and refits. The selected model used **37,884 rows**.

The candidates have 16 or 32 trees per zone, depths 14 or 18, minimum leaf size 3, minimum split size 5, all features available, random seed 1717, and one training job. Adaptive complexity is disabled. `calibrate=True` collects OOB reputations; multiclass predictions do not use the binary probability calibrator. Zone-prior weight is zero. All fitted trees are exported, retaining class mappings and zone reputation/global blending.

Selection uses 32 solo and 32 guided validation days: maximize completed days, then minimize combined mean completion time, then maximize state accuracy, then minimize model bytes. Test data is used only after selection.

| Trees per zone | Depth | Validation teacher accuracy | Solo wins | Guided wins | Solo / guided mean time |
| --- | --- | --- | --- | --- | --- |
| 16 | 14 | 97.35% | 32/32 | 32/32 | 49.05 / 36.86 s |
| 32 | 18 | 97.57% | 32/32 | 32/32 | 49.05 / 36.86 s |

## Held-out results

| Policy / condition | Completed | Mean simulated time |
| --- | --- | --- |
| WSRF, solo | 64/64 | 51.48 s |
| WSRF, guided | 64/64 | 37.81 s |
| Teacher, solo | 64/64 | 51.49 s |
| Simple cycling baseline, solo | 64/64 | 103.64 s |

The guided scenario rotates priority and weather every 15 simulated seconds and offers help every 30 seconds. Evaluation stops at success or 240 simulated seconds. Test seeds and per-day results are stored in [the full report](training/report.json). Solo policies use the same 64 unseen seeds; guided tests use their own 64 unseen seeds. The baseline is deterministic cycling through legal actions, seeded by the world, rather than an optimized policy or independent uniform random sampler. These cozy games allow simple policies to succeed; completion is not evidence of superiority over every baseline. A lower mean time is better. In particular, the bakery’s cycling baseline is slightly faster than its learned solo policy.

The selected forest has **64 trees**, occupies **1,159,062 bytes**, and agrees with the teacher on **97.60%** of the 10,000 held-out synthetic states. Teacher agreement measures imitation, not win probability. It is measured before legal-action masking. The confusion matrix is in the report, with actual labels as rows.

Python and browser class choices matched on **67,999 cases**, including independent states, visited gameplay states, and float32 tree-threshold neighbors. Maximum absolute probability difference: `1.1102230246251565e-16` (release tolerance `1e-12`). See [the reference fixtures](training/validation.json). Simulation evaluation uses 0.1-second steps; the browser uses 0.05-second steps and has a separate real-play completion check.

## Environment, provenance, and reproduction

Recorded versions: numpy 2.5.2, pandas 3.0.5, scikit-learn 1.9.0, python 3.14.4, wsrf 8.0.0. WSRF resolves to `/home/wiliamrocha/CelestialsPartDeux/wsrf-lib/src/wsrf/classifier.py` through pytoolz. The report records upstream source hashes, arcade training/simulation source hashes, all fitted parameters, zone reputations, and model SHA-256 `239675e3560b613da9a0db92bbe70a6facebbec6047963f047ad82719b91b192`. This identifies the actual local implementation, regardless of which checkout is newest later.

From the source arcade root, with this Python environment and local pytoolz checkout available:

```sh
/home/wiliamrocha/.spenv/bin/python -B tools/wsrf/train-watch.py --game starlight-observatory
node tools/wsrf/validate.cjs games/starlight-observatory/forest.json games/starlight-observatory/training/validation.json
npm run test:watch
npm run build
```

Use `--game all` to train all six new characters. Retraining needs numpy, pandas, scikit-learn, pytoolz, WSRF, and Node; publishing the fitted games needs only the static `dist/` folder. The training entry point, common exporter, dataset generator, model, fixtures, and report are included in the static distribution. Run `npm run test:watch:browser` against a served build and Chrome’s local debugging port for controls, responsive layouts, model loading, and actual browser completion.

The outcomes above describe these recorded seeds and guidance schedule. They are not a guarantee for all possible interventions. Sharing a seed recreates the initial day; it does not replay the user’s interventions.
