agentleFS
AirMileAirMile/claude-config/skills/game-optimize/SKILL.md

game-optimize

Skill0 starsChanged 4 months agoMITView on GitHub

Optimize Godot metrics via parallel worktree experiments. Use with /game-optimize.

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

11 rules. About 0 are common, 4 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    No required input. Config interactively in PHASE 1 or via resume.

    line 22
  2. Very specific:

    Update on completion: .project/project.json → push to optimization_runs[].

    line 37
  3. Very specific:

    No Godot → exit with "game-optimize requires Godot 4.x.

    line 97
  4. Distinctive:

    No GUT → warn that default gate does not work.

    line 105
  5. Very specific:

    Read .project/project.json for stack info and previous optimization_runs[].

    line 121
  6. Very specific:

    Default references/gates/gut-green.sh → copies script that runs GUT headless:

    line 255
  7. Distinctive:

    No GUT → copies no-op gate with warning.

    line 262
  8. Very specific:

    Write runs/0000.json and initialize tree.json (see dev-optimize PHASE 3).

    line 298
  9. Very specific:

    Mark run-start: write run_started_at = now_iso to spec.json (for wallclock cap in PHASE 4).

    line 317
  10. Very specific:

    Read references/subagent-brief.md template (game version).

    line 327
  11. Distinctive:

    AI winrate determinism: ensure the seed in the benchmark is fixed, otherwise score noise is too large for meaningful comparison.

    line 430

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Optimize

Autonomous improvement loop for Godot 4.x: define metric → spawn parallel subagents in worktrees → keep improvements, discard regressions → loop until stall.

Trigger: /game-optimize or /game-optimize [auto]

Inspired by the evo-hq/evo autoresearch pattern, integrated with .project/ and GUT testing. No external dependency.

Input

No required input. Config interactively in PHASE 1 or via resume.

Output

.project/optimize/{run-id}/
├── spec.json          # metric, gate, scope, baseline, parameters
├── tree.json          # nodes (id, parent, branch, score, status, hypotheses)
├── runs/{NNNN}.json   # per-round result
├── benchmark.tscn     # Godot benchmark scene (generated from template)
├── benchmark.gd       # Godot benchmark script (parses SCORE= line)
├── gate.sh            # default: GUT testsuite headless
└── branches.txt       # cleanup list for abort

Update on completion: .project/project.json → push to optimization_runs[].

Process

Phase tracking — first action of the skill: call TaskCreate with these 7 items (status pending), then use TaskUpdate to set in_progress at the start and completed at the end of each phase. During context compaction the task list stays visible — no risk of forgotten phases.

  1. PHASE 0: Pre-flight
  2. PHASE 1: Define Metric
  3. PHASE 2: Instrument Benchmark
  4. PHASE 3: Baseline Run
  5. PHASE 4: Optimize Loop
  6. PHASE 5: Pick Winner
  7. PHASE 6: Sync + Report

PHASE 0: Pre-flight

Todo: call ToolSearch query="select:TaskCreate,TaskUpdate" first — both tools are deferred and unusable without their schemas. Then call TaskCreate with the 7 phase items (see above). Mark PHASE 0 → in_progress via TaskUpdate. If the tools didn't resolve, skip seeding and continue.

Capture git baseline:

mkdir -p .project/session .project/optimize
find .project/session -maxdepth 1 -name "active-optimize-*.json" -mtime +1 -delete 2>/dev/null
git rev-parse HEAD > .project/session/pre-skill-sha.txt

Ensure .gitignore covers optimize artifacts (idempotent):

GITIGNORE=".project/.gitignore"
touch "$GITIGNORE"
ensure_pattern() {
  grep -qxF "$1" "$GITIGNORE" || echo "$1" >> "$GITIGNORE"
}
ensure_pattern "optimize/*/worktrees/"
ensure_pattern "session/active-optimize-*.json"
ensure_pattern "session/pre-skill-sha.txt"

Prevents full repo-checkouts (worktrees) or local session state from accidentally ending up in a commit.

Git safety:

  1. git status --porcelain empty? Otherwise AskUserQuestion (Auto-mode: stash):
    • "Stash changes (Recommended)" / "Abort"
  2. Detect default branch (see shared/SKILL-PATTERNS.md Git Safety Gates).
  3. BASE_SHA=$(git rev-parse HEAD).

Detect Godot:

Cross-platform path detection via paths.yaml:

# Windows: /c/Godot/Godot_v4.4.1-stable_win64.exe
# macOS:   /Applications/Godot.app/Contents/MacOS/Godot
# Linux:   godot4 (assume in PATH)
GODOT_BIN="${GODOT_BIN:-$(command -v godot4 || command -v godot)}"
"$GODOT_BIN" --version 2>/dev/null

No Godot → exit with "game-optimize requires Godot 4.x. Set GODOT_BIN env var or add to PATH."

Detect GUT:

test -d addons/gut && echo "GUT installed" || echo "GUT not found, gate disabled"

No GUT → warn that default gate does not work; user must define their own gate or accept that tests will not catch subagent regressions.

Resume detection + Auto-mode + active signal: see identical to dev-optimize PHASE 0.

Auto-mode defaults (game-specific):

Decision pointDefault
Metric choiceFPS (default)
Subagents per round3
Budget per subagent5 iterations
Stall threshold5 rounds
Winner-mergeTop branch automatically

Project context (skip if not exists):

Read .project/project.json for stack info and previous optimization_runs[].

PHASE 1: Define Metric

Todo: mark PHASE 0 → completed, PHASE 1 → in_progress.

On resume: skip.

AskUserQuestion 1 — what to optimize? (Auto-mode: FPS; two sequential modals, 4-option cap per shared/SKILL-PATTERNS.md § Modal Option Cap; show modal 2 only if "More →" is picked)

header: "Metric"
question: "What do you want to optimize?"
options:
  - label: "FPS in stress scene (Recommended)"
    description: "Average FPS at N entities/sprites. Higher is better."
  - label: "Frame time"
    description: "ms per frame in a fixed benchmark scene. Lower is better."
  - label: "Memory footprint"
    description: "MB peak (Performance.MEMORY_STATIC). Lower is better."
  - label: "More →"
    description: "AI win-rate, Pathfinding speed"
multiSelect: false
header: "Metric"
question: "What do you want to optimize?"
options:
  - label: "AI win-rate"
    description: "% wins of AI in M simulated matches. Higher is better."
  - label: "Pathfinding speed"
    description: "ms for N paths on a fixed map. Lower is better."
multiSelect: false

(Custom option via "Other" → ask follow-up: scene path + score extraction line.)

AskUserQuestion 2 — direction (Auto-mode: minimize for frame-time/memory/pathfinding, maximize for FPS/winrate):

header: "Direction"
options:
  - label: "Lower is better (minimize)"
  - label: "Higher is better (maximize)"
multiSelect: false

AskUserQuestion 3 — scope (Auto-mode: entire scripts/):

header: "Scope"
question: "Which directories may subagents modify?"
options:
  - label: "scripts/ (Recommended)"
    description: "GDScript only, scenes intact"
  - label: "scripts/ + scenes/"
    description: "Allow scene edits (riskier)"
  - label: "scripts/ + addons/{name}"
    description: "Custom subset"
  - label: "Custom paths"
multiSelect: false

AskUserQuestion 4 — loop parameters (Auto-mode: defaults). The choice also determines which subagent model is used:

header: "Parameters"
options:
  - label: "Conservative: 3 agents × 5 iter, stall 5, 60min cap, sonnet (Recommended)"
    description: "Cheap and fast."
  - label: "Standard: 5 agents × 5 iter, stall 5, 90min cap, sonnet"
  - label: "Aggressive: 8 agents × 8 iter, stall 8, 180min cap, opus"
    description: "Much more compute and more expensive model — only for long, difficult runs."
multiSelect: false

Mapping (same as dev-optimize):

Choicesubagentsbudgetstallwallclockmodel
Conservative35560 minsonnet
Standard55590 minsonnet
Aggressive888180 minopus

For Godot, benchmark time is often higher (Godot import cache, scene load) — wallclock cap is therefore relatively more important than with dev-optimize.

AskUserQuestion 5 — benchmark parameters (per metric):

MetricQuestionDefault
FPSNumber of entities in stress scene?1000
frame_timeRun duration (seconds)?10
memoryRun duration (seconds) for peak measurement?30
ai_winrateNumber of simulated matches?100
pathfindingNumber of paths + map name (from scenes/maps/)?1000 + selection

Write .project/optimize/{run-id}/spec.json (see dev-optimize for full schema, including max_wallclock_minutes, subagent_model, run_started_at). Replace benchmark_cmd with:

"benchmark_cmd": "$GODOT_BIN --headless --path . res://.project/optimize/{run-id}/benchmark.tscn --quit-after 120"

gate_cmd:

"gate_cmd": "bash .project/optimize/{run-id}/gate.sh"

PHASE 2: Instrument Benchmark

Todo: mark PHASE 1 → completed, PHASE 2 → in_progress.

Step 1 — copy benchmark template (Godot scene + script):

One universal scene references/benchmarks/benchmark.tscn (Node with script-ref) + per-metric GDScript:

MetricScript template
fpsreferences/benchmarks/fps-stress.gd
frame_timereferences/benchmarks/frame-time.gd
memoryreferences/benchmarks/memory.gd
ai_winratereferences/benchmarks/ai-winrate.gd
pathfindingreferences/benchmarks/pathfinding.gd

Workflow:

  1. Copy benchmark.tscn → .project/optimize/{run-id}/benchmark.tscn. Substitute {RUN_ID} in the path of the ExtResource so the script path is correct.
  2. Copy chosen <metric>.gd → .project/optimize/{run-id}/benchmark.gd. Substitute placeholders ({ENTITY_COUNT}, {DURATION_FRAMES}, {SCENE_TO_LOAD}, etc.) with user-chosen values from AskUserQuestion 5.

Templates print one line SCORE=<float> to stdout via print() before get_tree().quit(). Skill parses the last SCORE= line from Godot stdout.

Step 2 — gate script:

Default references/gates/gut-green.sh → copies script that runs GUT headless:

#!/bin/bash
"$GODOT_BIN" --headless --path . -s addons/gut/gut_cmdln.gd -gtest_dirs=test/ -gexit

No GUT → copies no-op gate with warning.

Step 3 — review + edit:

AskUserQuestion (Auto-mode: Run as-is):

header: "Scripts"
question: "Is benchmark.gd and gate.sh correct?"
options:
  - label: "Run as-is (Recommended)"
  - label: "Edit first"
  - label: "Abort"
multiSelect: false

chmod +x on gate.sh.

PHASE 3: Baseline Run

Todo: mark PHASE 2 → completed, PHASE 3 → in_progress.

cd "$(git rev-parse --show-toplevel)"

# Gate first
if ! bash .project/optimize/{run-id}/gate.sh; then
  echo "BASELINE GATE FAIL: fix GUT tests first"
  exit 1
fi

# Benchmark — capture stdout, parse SCORE
RAW=$("$GODOT_BIN" --headless --path . res://.project/optimize/{run-id}/benchmark.tscn --quit-after 120 2>&1)
BASELINE=$(echo "$RAW" | grep -E '^SCORE=' | tail -1 | cut -d= -f2)

Write runs/0000.json and initialize tree.json (see dev-optimize PHASE 3).

Display + cost estimate (same calculation as dev-optimize PHASE 3 — see there for the formulas). Godot benchmark times are often higher (first run per worktree has import-cache overhead of 30-60s), take that into account in the estimate.

BASELINE: {metric} = {score} ({direction})
GUT: {pass}/{total} tests green.

COST ESTIMATE (worst-case):
- {subagents} agents × {budget} iter × {stall} rounds = {TOTAL_ITERS} agent-iterations
- ~{PER_ITER_SECONDS}s per iteration ({BENCHMARK_SECONDS}s benchmark + {GATE_SECONDS}s gate + 30s import)
- Estimated time: ~{TOTAL_MINUTES} min (capped at {max_wallclock_minutes} min)
- Estimated cost: ~${TOTAL_DOLLARS} ({subagent_model})

AskUserQuestion (Auto-mode: if TOTAL_DOLLARS > 10 OR TOTAL_MINUTES > 120 → abort):

Identical option set as dev-optimize: Continue / Reduce budget / Abort.

Mark run-start: write run_started_at = now_iso to spec.json (for wallclock cap in PHASE 4).

PHASE 4: Optimize Loop

Todo: mark PHASE 3 → completed, PHASE 4 → in_progress.

Identical loop mechanics as dev-optimize PHASE 4 (select parents → spawn subagents in worktrees → collect → stall check → continue prompt).

Difference — subagent brief:

Read references/subagent-brief.md template (game version). Extra context:

  • Godot binary path (from GODOT_BIN)
  • GUT tests must stay green (gate)
  • GDScript-specific pitfalls (see references/gdscript-pitfalls.md)

Brief extra clause:

Work in worktree {EXP_PATH}.
GDScript-only changes unless scope also includes scenes/.
Performance hypotheses (FPS/frame-time):
  - Object pooling
  - Signal-vs-poll patterns
  - PackedArray instead of Array
  - Add static typing
  - LOD via visibility/process_mode
  - Batch draw calls
AI hypotheses (winrate):
  - Heuristic weight tuning
  - Decision tree pruning
  - Lookahead depth
Run benchmark per iteration:
  $GODOT_BIN --headless --path . {benchmark.tscn} --quit-after 120
Parse SCORE= line.

Worktree-naming: optimize/{run-id}/exp_{short-id} (identical to dev-optimize).

Result aggregation: identical to dev-optimize.

PHASE 5: Pick Winner

Todo: mark PHASE 4 → completed, PHASE 5 → in_progress.

Identical to dev-optimize PHASE 5: show top-3, AskUserQuestion, keep branch, clean up losers.

PHASE 6: Sync + Report

Todo: mark PHASE 5 → completed, PHASE 6 → in_progress.

Append to .project/project.json → optimization_runs[] (schema in shared/DASHBOARD.md section optimization_runs):

{
  "run_id": "{run-id}",
  "skill": "game-optimize",
  "metric": "{metric}",
  "direction": "{direction}",
  "baseline": {baseline},
  "final": {best_score},
  "improvement_pct": {pct},
  "rounds": {N},
  "experiments_kept": {total_kept},
  "experiments_discarded": {total_discarded},
  "winner_branch": "optimize/{run-id}/winner",
  "stopped_reason": "{reason}",
  "date": "{ISO}"
}

stopped_reason values: stall | wallclock | user | no_improvement. Append-only — dedup on run_id.

Clean up session files (pre-skill-sha.txt, active-optimize-{run-id}.json).

Display report:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GAME-OPTIMIZE COMPLETE: {run-id}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Metric:        {metric} ({direction})
Baseline:      {baseline}
Final:         {best_score}
Improvement:   {improvement_pct}%
Rounds:        {N}
Experiments:   {kept} kept / {discarded} discarded
Winner:        {winner_branch}

TOP 3 HYPOTHESES (kept):
  1. "..." (Δ {x})
  2. "..." (Δ {y})
  3. "..." (Δ {z})

Next steps:
  1. git checkout {winner_branch} → inspect changes in Godot editor
  2. Open project in editor to validate visually (no visual regression)
  3. /core-commit → on approval merge branch via PR
  4. /game-optimize → another run with a different metric

Todo: Apply the Next-Step Clipboard Offer (binary Ja/Nee) — read '.claude/skills/shared/NEXT-STEP-OFFER.md'. Recommended command: /game-ship {feature} → re-verify after optimizations.

Todo: mark PHASE 6 → completed.

Edge Cases

  • No GUT installed: gate is no-op. Subagents can introduce broken logic without detection. Strictly limit scope or skip game-optimize until GUT is set up.
  • Headless rendering does not work (some hosts): add --audio-driver Dummy --rendering-driver opengl3. For vello-based shaders: use forward_plus with lower resolution.
  • Benchmark timeout: Godot sometimes hangs. Skill wraps command in timeout 180s.
  • Worktree + Godot import cache: each worktree gets its own .godot/ cache. First run of a worktree is slower (import). Acceptable: amortizes over budget iterations.
  • AI winrate determinism: ensure the seed in the benchmark is fixed, otherwise score noise is too large for meaningful comparison. Subagent brief must emphasize this.
  • Cross-platform path issues: res:// paths work cross-platform, OS paths in shell scripts must go through paths.yaml or env var.

Rationale

Same as dev-optimize: no external evo-hq-cli dep, full control, seamless integration with .project/ and GUT. Domain differences (Godot CLI instead of npm, scenes instead of bundle, GUT instead of vitest) are only in benchmark/gate templates and subagent brief — the loop mechanics are identical.

Why standalone? Game optimization is measurement-driven, not feature-build. Works on existing scenes/scripts, not on a feature in DOING status.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.