docs(research): synthesis of game, state and primitives; next iteration
Join the three evidence sources that were kept apart, and extract the useful
result: each source independently decides what belongs in code and what belongs
to the model, and every serious bug we have found broke one of those rules.
* Game mechanism -> arithmetic and rules belong in CODE
* Internal state -> anything directly readable or writable belongs in CODE
* TypeSafe -> judgements go to the MODEL, in the primitive matching the
answer's shape
* never blocked in boss fights -> game mechanism (arithmetic left to the model)
* card quality asked as a Noul -> primitives (a spectrum forced into yes/no)
* indices read from the wrong array -> internal state
The counter-example is kept too: the Score we tried for fight-level planning was
unusable, so the rule is "match the primitive to the shape, and verify" rather
than "use Score more".
Also records the ordered plan (measurement first, then re-run, then primitives,
then deck composition), the continual-learning design, and why it is blocked:
with 0 wins in 37 runs the reward has no gradient, so training would fit the bug
rather than the game.
This commit is contained in:
parent
f249349dd8
commit
65fe1171cd
2 changed files with 357 additions and 3 deletions
|
|
@ -18,6 +18,9 @@ guess, it says so.
|
|||
| 05 | [Failure modes](05-failure-modes.md) | Every infinite loop found live, with its fix |
|
||||
| 06 | [Decision architecture](06-decision-architecture.md) | The three-layer design and why the split is where it is |
|
||||
| 07 | [Run log](07-run-log.md) | Results per run, with seeds and outcomes |
|
||||
| 08 | [What actually wins](08-what-actually-wins.md) | Why the web meta is unusable, and the measured cause of 9 run losses |
|
||||
| 09 | [TypeSafe best practice](09-typesafe-best-practice.md) | Doc-by-doc gap analysis: what we match, what measurement killed, what is missing |
|
||||
| 10 | [Synthesis and next iteration](10-synthesis-and-next-iteration.md) | Game + state + primitives joined; the three rules; the planned iteration and refactor |
|
||||
|
||||
Architecture summary lives in [`../DESIGN.md`](../DESIGN.md).
|
||||
|
||||
|
|
@ -28,6 +31,15 @@ Architecture summary lives in [`../DESIGN.md`](../DESIGN.md).
|
|||
3. Record the **date** and the **game build** (`v0.107.1` today). Both move.
|
||||
4. When a finding is later disproved, do not delete it. Mark it superseded
|
||||
and say what replaced it. The wrong turn is often the useful part.
|
||||
5. **Re-measure numbers before you copy them.** Test counts, latencies and run
|
||||
totals in these docs have gone stale more than once. The suites print their
|
||||
own totals; use those, not a figure quoted from an earlier session.
|
||||
|
||||
> Worked example: a hand-off summary recorded `29` and `118` assertions.
|
||||
> Re-running the suites showed `50` and `131`, and the difference was two
|
||||
> regression sections that already existed in the files. The stale numbers
|
||||
> would have gone into this index unchallenged. Run the suite; do not trust
|
||||
> the summary.
|
||||
|
||||
## Environment these notes were taken on
|
||||
|
||||
|
|
@ -57,11 +69,12 @@ Then restart the game. Mods load only at process start.
|
|||
|
||||
## Testing
|
||||
|
||||
Two suites, both offline. Run them before every session.
|
||||
Three suites, all offline. Run them before every session.
|
||||
|
||||
```bash
|
||||
python3 test_brain.py # 54 assertions — structural / programmatic
|
||||
python3 test_facts.py # 29 assertions — arithmetic and parsing
|
||||
python3 test_brain.py # 131 assertions — structural / programmatic
|
||||
python3 test_facts.py # 50 assertions — arithmetic and parsing
|
||||
python3 test_run.py # 21 assertions — the decision log and its joins
|
||||
```
|
||||
|
||||
`test_brain.py` is the important one for catching usage bugs. It asserts that
|
||||
|
|
@ -69,6 +82,12 @@ every `state_type` produces an action **legal for that state**, that every
|
|||
action the decision layer can emit is declared somewhere, and that every
|
||||
fallback respects its own inputs. It needs no model and no running game.
|
||||
|
||||
`test_run.py` drives `main()` end to end with a fake `sts2` and a stub client,
|
||||
so it pins the decision log without a network: a model decision's row carries
|
||||
that decision's answers, and a decision that asked nothing logs `jev: null`
|
||||
rather than inheriting the previous step's. Removing the reset before each
|
||||
`decide()` makes it fail.
|
||||
|
||||
It was added after a session in which four separate infinite loops and three
|
||||
hardcoded fallbacks were found by hand. Most of them would have been caught
|
||||
here.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue