agentleFS
sebnadosebnado/worldbuild-bench/skills/bench-telemetry/SKILL.md

bench-telemetry

Skill9 starsChanged 4 months agoMITView on GitHub

The REQUIRED window.__bench telemetry contract — getState, reset, getPlayerPosition, getCameraInfo, getEntities, getObjectiveStatus — with the exact shape to implement. Games without it are score-capped.

The file

We split this skill into the rules it gives an agent

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

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    All six methods exist and are functions on window.__bench.

    line 85
  2. Distinctive:

    Every method returns synchronously with JSON-serializable data (no Promises).

    line 86
  3. Distinctive:

    No method throws, in any game phase (menu, playing, won, lost).

    line 87
  4. Very specific:

    Test the contract yourself with the test_game tool — its report has a bench_contract section showing exactly which methods were found and …

    line 94

≈ “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

The window.__bench Telemetry Contract (REQUIRED)

Your game is scored by scripted probes that call window.__bench. If the object or any method is missing, the Playability Score is capped and the World Coherence Score cannot be earned. Implement it early — it is a few lines once your gameState exists — and keep it working as the game grows.

Exact shape

Attach this in your main module after the game initializes:

// js/bench.js (or inline in main.js) — wire to your real gameState
import * as THREE from 'three'; // already mapped by the scaffold's import map

export function installBench(gameState, player, camera, restartGame) {
  window.__bench = {
    // Full serializable snapshot of the game state. Plain data only —
    // no THREE objects, no functions, no cycles (it must survive JSON.stringify).
    getState() {
      return {
        phase: gameState.phase,            // 'menu' | 'playing' | 'won' | 'lost'
        score: gameState.score,
        health: gameState.player.health,
        entities: gameState.entities.length,
      };
    },

    // Restart to the initial state (same as the player pressing Restart).
    // After reset(), getState() and getPlayerPosition() must return values
    // matching a fresh load.
    reset() {
      restartGame();
    },

    // World-space player position as {x, y, z} finite numbers.
    // Return the controlled avatar/object root (or the camera focus point if
    // that better represents "where the player is").
    getPlayerPosition() {
      const p = player.root.position;
      return { x: p.x, y: p.y, z: p.z };
    },

    // Camera position + look direction, finite numbers.
    getCameraInfo() {
      const dir = new THREE.Vector3();
      camera.getWorldDirection(dir);
      return {
        position: { x: camera.position.x, y: camera.position.y, z: camera.position.z },
        direction: { x: dir.x, y: dir.y, z: dir.z },
        fov: camera.fov,
      };
    },

    // Every live gameplay entity (NPCs, pickups, interactables, etc.).
    // Empty array is valid when nothing is alive.
    getEntities() {
      return gameState.entities.map((e) => ({
        id: e.id,
        kind: e.kind,                      // short string label for the entity type
        position: { x: e.root.position.x, y: e.root.position.y, z: e.root.position.z },
      }));
    },

    // Progress toward the win condition, plus the outcome flags.
    getObjectiveStatus() {
      return {
        objective: 'complete the objective', // human-readable current objective
        progress: gameState.progress,        // 0..1 fraction toward win
        won: gameState.phase === 'won',
        lost: gameState.phase === 'lost',
      };
    },
  };
}

Rules the probes check

  • All six methods exist and are functions on window.__bench.
  • Every method returns synchronously with JSON-serializable data (no Promises).
  • No method throws, in any game phase (menu, playing, won, lost).
  • getPlayerPosition() returns finite {x, y, z} — no NaN, no infinite falling (y should not run away to -infinity).
  • The camera stays within a sane distance of the player.
  • The state returned by getState() evolves over time while playing, and reset() genuinely restores the initial state and position.

Test the contract yourself with the test_game tool — its report has a bench_contract section showing exactly which methods were found and what each returned.

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.