mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
chore(training): promote stage-4 retry2 to medium and open stage 5
20260816-2126-gen5-s4-handling-retry2 exhausted its three attempts and missed only the 0.80 training goal-rate floor, at 0.7731. Every evaluation gate passed: 65-22-13 versus promoted/easy.json, 87% non-draw against an 80% floor, 12.6% physical-side imbalance against a 20% ceiling, and both handling telemetry floors clear. The round improved the goal rate monotonically across attempts (0.537 -> 0.683 -> 0.773) and the checkpoint plays well by hand, so close Stage 4 by human override. Promote it to Game/bots/promoted/medium.json. Medium and Hard both point at the new policy: Hard stays a label-only duplicate until a stronger one earns hard.json, which keeps the tiers monotonic rather than leaving Hard weaker than Medium. generation5_state.json flips that log entry to "pass" with a decision_override block preserving the original verdict and reasoning, and advances to Stage 5 attempt 1. This is what passing_entry() needs to resolve Stage 5's resume checkpoint and evaluation reference, and what league_pool() will need at Stage 6; --skip-to-next-stage would advance the stage without marking anything as passing and die immediately. generation5.sh now pulls before launching. Each stage ends in commit_progress()'s push, which fails and kills the run hours in if the box is behind origin.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -11,14 +11,18 @@ extends Control
|
||||
|
||||
const BOTS_DIR := "res://bots"
|
||||
|
||||
# All three tiers deliberately point at the same promoted checkpoint at its
|
||||
# full trained capability. The labels are placeholders until genuinely
|
||||
# stronger models are promoted as medium.json/hard.json; difficulty is not
|
||||
# simulated with reaction delay or action noise in the meantime.
|
||||
# Every tier runs its promoted checkpoint at full trained capability —
|
||||
# difficulty is a genuinely different policy, never the same policy
|
||||
# handicapped with reaction delay or action noise. Easy and Medium are now
|
||||
# distinct models (medium.json beats easy.json 65-22-13 head-to-head); Hard
|
||||
# still points at medium.json, the strongest promoted policy, and stays a
|
||||
# label-only duplicate until a stronger one earns hard.json. Keep the tiers
|
||||
# monotonic: never leave a lower tier pointing at a stronger model than the
|
||||
# one above it.
|
||||
const DIFFICULTIES := [
|
||||
{"name": "Easy", "model": "res://bots/promoted/easy.json", "reaction_ticks": 8, "action_noise": 0.0},
|
||||
{"name": "Medium", "model": "res://bots/promoted/easy.json", "reaction_ticks": 8, "action_noise": 0.0},
|
||||
{"name": "Hard", "model": "res://bots/promoted/easy.json", "reaction_ticks": 8, "action_noise": 0.0},
|
||||
{"name": "Medium", "model": "res://bots/promoted/medium.json", "reaction_ticks": 8, "action_noise": 0.0},
|
||||
{"name": "Hard", "model": "res://bots/promoted/medium.json", "reaction_ticks": 8, "action_noise": 0.0},
|
||||
]
|
||||
|
||||
@onready var difficulty_dropdown: OptionButton = %DifficultyDropdown
|
||||
|
||||
+35
-5
@@ -164,7 +164,14 @@ flat files there, never touching subdirectories.
|
||||
actually referenced by the shipped game — currently `easy.json` (promoted
|
||||
2026-08-08 from generation 4's `20260806-1939-curric-s3-gauntlet`; this is
|
||||
the 320M-step MultiDiscrete policy and the foundation for the planned
|
||||
generation-5 curriculum below) and `reference-grounded.json` (added for
|
||||
generation-5 curriculum below), `medium.json` (promoted 2026-08-17 from
|
||||
generation 5's `20260816-2126-gen5-s4-handling-retry2` — Stage 4 attempt 3,
|
||||
which the pipeline recorded as a *fail* on the 80% training-goal-rate gate at
|
||||
0.7731, but which beats `easy.json` 65-22-13 in the 100-episode paired
|
||||
evaluation, 87% non-draw and 12.6% physical-side imbalance, both inside the
|
||||
Stage-4 bars; promoted by hand on gameplay feel, so its recorded
|
||||
`decision: "fail"` in `generation5_state.json` is expected and not a
|
||||
bookkeeping error) and `reference-grounded.json` (added for
|
||||
generation 4 — a copy of generation 3's `curric-s5-aggression`, made before
|
||||
the flat `Game/bots/` dump was scrapped for the redesign, kept as the
|
||||
strongest grounded-era artifact and the fixed yardstick generations 1-3 were
|
||||
@@ -174,10 +181,12 @@ promoted file is never touched by training scripts, never overwritten by a
|
||||
same-named future export, and never disturbed by pruning old experiment
|
||||
files from the flat dump.
|
||||
|
||||
Until distinct `medium.json` and `hard.json` policies earn promotion, the
|
||||
three menu tiers all run this same `easy.json` policy at its full trained
|
||||
cadence (`reaction_ticks=8`, `action_noise=0`). The tiers are labels only;
|
||||
the game does not manufacture difficulty gaps by handicapping this model.
|
||||
Easy and Medium are now genuinely different policies. Hard still points at
|
||||
`medium.json` and remains a label-only duplicate until a stronger policy earns
|
||||
`hard.json`. Every tier runs at full trained cadence (`reaction_ticks=8`,
|
||||
`action_noise=0`) — the game does not manufacture difficulty gaps by
|
||||
handicapping a model. When promoting, keep the tiers monotonic: a lower tier
|
||||
must never point at a policy that beats the tier above it.
|
||||
|
||||
To promote a new bot into a tier: copy the chosen `Game/bots/<experiment>.json`
|
||||
to `Game/bots/promoted/<tier>.json` (overwriting the old one), and note the
|
||||
@@ -609,6 +618,27 @@ that fades to zero by 3m altitude. Its scoring gates deliberately run before
|
||||
Stage 5: becoming upright is not progress if the resulting policy stops
|
||||
finishing goals. Stage 5 adds moving high-ball intercept
|
||||
starts aimed toward real goals rather than a standalone air-touch reward.
|
||||
|
||||
**Stage 4 was closed by human override on 2026-08-17**, not by the automatic
|
||||
gate. `20260816-2126-gen5-s4-handling-retry2` exhausted all three attempts and
|
||||
the pipeline recorded `decision: "fail"`, on the training goal-rate floor alone
|
||||
(0.7731 vs 0.80). Every other gate passed — 65-22-13 versus
|
||||
`promoted/easy.json`, 87% non-draw against the 80% floor, 12.6% physical-side
|
||||
imbalance against the 20% ceiling, and both handling telemetry floors clear
|
||||
(`upright_fraction` 0.772 vs 0.45, `forward_motion_fraction` 0.315 vs 0.25) —
|
||||
and the round's three attempts improved the training goal rate monotonically
|
||||
(0.537 → 0.683 → 0.773). The same checkpoint also plays well enough by hand to
|
||||
have been promoted to `medium.json`. `generation5_state.json` therefore has
|
||||
that log entry's `decision` flipped to `"pass"` with a `decision_override`
|
||||
block recording the original verdict and reasoning, and `stage_index`/
|
||||
`attempt`/`status` advanced to Stage 5 attempt 1 — which is what
|
||||
`passing_entry()` needs to resolve Stage 5's resume checkpoint and evaluation
|
||||
reference, and what `league_pool()` will later need at Stage 6. Prefer this
|
||||
edit over `--skip-to-next-stage`: that flag advances `stage_index` without
|
||||
marking anything as passing, so the run dies immediately with `RuntimeError:
|
||||
No passing generation-5 stage index 0`. Note that retry2 already clears Stage
|
||||
5's own 0.75 goal-rate floor; the 0.80 Stage-4 figure was always the stricter
|
||||
of the two.
|
||||
Stage 6's `league` opponent mode samples a historical exported policy at each
|
||||
episode reset. Each later stage preserves the preceding shaping and adds one
|
||||
new difficulty.
|
||||
|
||||
@@ -14,6 +14,13 @@ if tmux has-session -t "$SESSION" 2>/dev/null; then
|
||||
exec tmux attach -t "$SESSION"
|
||||
fi
|
||||
|
||||
# Stage start and resume point both come from committed state, and each stage
|
||||
# ends in commit_progress()'s `git push` — which fails, killing the run after
|
||||
# hours of training, if the box is behind origin. Pull before starting, same as
|
||||
# next_run.sh. Aborts here (set -e) on a dirty tree or a conflict, which is the
|
||||
# point: fix it before spending the compute, not after.
|
||||
git pull --rebase
|
||||
|
||||
tmux new-session -d -s "$SESSION" -n curriculum \
|
||||
".venv/bin/python generation5.py $*; echo; echo '=== generation5.py exited — press Enter to close ==='; read"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"stage_index": 0,
|
||||
"attempt": 2,
|
||||
"status": "blocked",
|
||||
"stage_index": 1,
|
||||
"attempt": 0,
|
||||
"status": "in_progress",
|
||||
"log": [
|
||||
{
|
||||
"stage_index": 0,
|
||||
@@ -249,7 +249,15 @@
|
||||
"win_rate_a": 0.65
|
||||
}
|
||||
],
|
||||
"decision": "fail"
|
||||
"decision": "pass",
|
||||
"decision_override": {
|
||||
"date": "2026-08-17",
|
||||
"original_decision": "fail",
|
||||
"original_failures": [
|
||||
"rollout/goal_rate=0.7731 < 0.8000"
|
||||
],
|
||||
"reason": "Human override. Only miss was the training goal-rate floor, at 0.7731 vs 0.80; every evaluation gate passed (65-22-13 vs promoted/easy.json, 87% non-draw, 12.6% physical-side imbalance) and the goal rate improved monotonically across all three attempts (0.537 -> 0.683 -> 0.773). Also promoted to Game/bots/promoted/medium.json on the same evidence. Stage 5 resumes from this checkpoint."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user