Skip to content
Automation
Skill

/gm-verify

Mechanical verification of the built game: headless build, unit tests, lint, static checks. Explicit invocation only — use /gm-verify.

From plugin
godotmaker
55941 skills7 agents15 hooks

Claude Code

$ npx -y skills add RandallLiuXin/GodotMaker --skill gm-verify --agent claude-code

SKILL.md

gm-verify.SKILL.md
name: gm-verify
description: |
  Mechanical verification of the built game: headless build, unit tests, lint, static checks.
  Explicit invocation only — use /gm-verify.
disable-model-invocation: true

GodotMaker Verify

$ARGUMENTS

You are performing mechanical verification of a built Godot game project. This is a non-creative, checklist-driven process.

Session Setup

**FIRST ACTION — before anything else:** Write `verify` to `.godotmaker/current_role`.

**Permission:** Read-only with three exceptions — you may write `.godotmaker/current_role`, append to `.godotmaker/stage.jsonl`, and write `.godotmaker/verify_report.json`. Verify never modifies game code or planning docs.

Resume Check

Read `.godotmaker/stage.jsonl` (treat as empty if missing) — each line is `{"role": X, "ts": Y}`.

  • If **no event with `role == "build"` AND no event with `role == "fixgap"`** exists anywhere in the file → STOP. Tell user to run `/gm-build` first.
  • If the **last event** has `role == "verify"` → STOP. Tell the user:

> "Verify already ran at {timestamp} with no state-changing event since. Recommended next: /gm-evaluate. > If you need to redo this step or have other plans, just tell me."

  • Otherwise → proceed (verify is naturally re-invoked after each build/fixgap cycle).

Run the checks

From the project root:

python tools/run_verify.py

`run_verify.py` wraps the four mechanical checks (build / unit tests / lint / static check) and prints a JSON document matching `Output Format` Section B to stdout. Capture stdout.

What the script does:

  • Resolves the selected runtime from `.godotmaker/config.yaml`, then reads

`godot_path` from that runtime's `godotmaker.yaml`: `.claude/` for Claude Code, `.agents/` for Codex, `.opencode/` for OpenCode, or `.pi/` for Pi. Older projects without an `agent` field use runtime-directory detection and then the Claude Code default. If no value is configured, it falls back to plain `godot` from PATH. A missing or broken binary surfaces as a `tooling_notes[].suggested_fallback = "escalate"` entry.

  • Runs `<godot_path> --headless --quit` and writes blocking Godot diagnostics

to `checks.build.errors[]`.

  • Runs `<godot_path> --headless ... res://addons/gdUnit4/bin/GdUnitCmdTool.gd

--ignoreHeadlessMode --add res://test/ --report-directory <temp>` and parses the generated JUnit XML into `checks.unit_tests.{passed, failed, failures[]}`. Stdout is diagnostic fallback only.

  • Stubs `checks.lint` as `pass` with `format_drift: null`. Do NOT

re-enable here.

  • Delegates `checks.static_check` to

`python tools/check_project.py <project_dir> --build --ecs --tests --plan --mcp`.

  • Exit code 0 = ran to completion (per-check pass/fail is in the JSON).

Sanity-check the script output

Before writing the report, validate. Block on any of these:

  • JSON does not parse, or any of `result` / `ts` / `checks` /

`tooling_notes` is missing

  • Any of the four `checks.{build,unit_tests,lint,static_check}`

entries is absent

  • `result == "pass"` but `tooling_notes` is non-empty — re-run or escalate
  • `checks.unit_tests.passed + .failed == 0` — spot-check by running the gdUnit4 command directly with `--report-directory <temp>`
  • Any `tooling_notes` entry whose `crashed_on` looks unrelated to the

failing check

If any block fires, diagnose by running the implicated command yourself, then either re-run `run_verify.py` or surface the issue verbatim to the user. Do NOT silently rewrite the script's output.

Output Format

You produce **two outputs**:

A. Human-readable report (chat)

Build this from the JSON the script returned — do not re-run any command for the chat side.

## Verification Report

### Build
Result: PASS | FAIL
{If FAIL, one line per checks.build.errors[] entry: `- {file}:{line}: {message}` (file/line may be empty)}

### Unit Tests
Result: PASS | FAIL
{N passed, M failed}
{If FAIL, one line per checks.unit_tests.failures[]: `- {test}: {message}`}

### Lint
Status: SKIP (gdtoolkit disabled — ROADMAP R-112)

### Static Check
Result: PASS | FAIL
{If FAIL, one line per checks.static_check.issues[]: `- {check}: {detail}`}

### Overall: PASS | FAIL

{If tooling_notes is non-empty, append:
## Tooling Notes
- {tool}: {error} (suggested_fallback: {suggested_fallback})
…}

B. Machine-readable report (`.godotmaker/verify_report.json`)

Write this file every run (PASS or FAIL). `/gm-build` and `/gm-fixgap` read it on their next invocation to translate failures into pending tasks.

Schema:

{
  "result": "pass | fail",
  "ts": "<UTC ISO 8601 timestamp, e.g. 2026-05-07T14:23:00Z>",
  "checks": {
    "build": {
      "result": "pass | fail | error",
      "errors": [
        {"file": "src/foo.gd", "line": 42, "message": "Identifier 'bar' not declared"}
      ]
    },
    "unit_tests": {
      "result": "pass | warn | fail | error",
      "passed": 624,
      "failed": 0,
      "failures": [
        {"test": "test_player_input::test_jump", "message": "expected 10, got 0"}
      ],
      "warnings": [
        "Found 4 possible orphan nodes."
      ]
    },
    "lint": {
      "result": "pass | warn | fail | error",
      "issues": [
        {"file": "src/foo.gd", "rule": "max-line-length", "message": "line too long"}
      ],
      "format_drift": {
        "file_count": 92,
        "command": "gdformat src/ test/ scenes/"
      }
    },
    "static_check": {
      "result": "pass | fail | error",
      "issues": [
        {"check": "missing_unit_test", "detail": "s_level_up_overlay has no test"}
      ]
    }
  },
  "tooling_notes": [
    {
      "tool": "gdlint",
      "crashed_on": "src/foo.gd",
      "error": "NotImplementedError at gdtoolkit/linter/class_checks.py:144",
      "suggested_fallback": "exclude_file",

      "narrowed_command": null,
      "rule_name": null,
      "check_name": null
    }
  ]
}

Field rules:

  • **Top-level `result`** — `"pass"` iff every `checks.*.result` ∈ {`pass`, `warn`}. Any
Read more
@randallliuxin
Ships withgodotmaker

Autonomous text-to-game pipeline for Godot, powered by Claude Code,Codex,Opencode

55941 skills7 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
559
Star history of RandallLiuXin/GodotMaker on GitHub, a chart by star-history.com

Other skills on godotmaker.

platform-strip

platform-strip

Generate non-pixel-art, horizontally repeatable platform strips from real image sources as fixed Texture2D cells or AtlasTexture…

More skills from other plugins.

agent-builder

agent-builder

Load immediately after an Agent intent, before the first agent_builder_* call. Governs how you create, configure, test, and…

n8n10d209k
@n8n-io@n8n-ioInstall Skill
browser-use

browser-use

Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…

@browser-use@browser-useInstall Skill
agent-browser

agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…

@vercel-labs-2@vercel-labs-2Install Skill
add-anydoc

add-anydoc

Add local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when…

@nanocoai@nanocoaiInstall Skill

Questions about gm-verify.

Which coding agents can use gm-verify?
gm-verify installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.