一键导入
gm-verify
Mechanical verification of the built game: headless build, unit tests, lint, static checks. Explicit invocation only — use /gm-verify.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Mechanical verification of the built game: headless build, unit tests, lint, static checks. Explicit invocation only — use /gm-verify.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Generate a new Godot game project with standardized ECS structure and tooling. Use when starting a new game: "create a project", "set up a new game", "scaffold", "initialize", "new project", "start building", "let's make it". Triggers after game-planner produces a confirmed plan, or when the user provides a game name + genre directly. Even for simple requests like "make me a new Godot project", use this skill to ensure proper ECS structure. Creates directory structure, project.godot, CLAUDE.md, gecs World setup, addon stubs, and template source files based on the game plan or user input.
Evaluate the current tag's quality: enforce the playable-closed-loop gate, maintain a single cross-tag e2e/ suite that always reflects the current game (add tests for new mechanics, prune tests for mechanics this tag deliberately removed), and reason about gameplay quality. Independent from the build process — fresh perspective on the final product. Explicit invocation only — use /gm-evaluate.
Reviews Godot Animation implementation for known pitfalls. Triggers AFTER implementation, when code involves AnimationPlayer, AnimationTree, AnimatedSprite2D, SpriteFrames, AnimationNodeStateMachine, BlendSpace, OneShot, callback_mode_process, or animation playback control (play/travel/start). Do NOT use this skill for planning or teaching — only for post-implementation review.
Run gdUnit4 unit tests and parse results into structured output. Use this skill after writing or modifying code to verify correctness via unit tests, when diagnosing test failures, or when writing new test files. Triggers: "run tests", "test fails", "write a test", any gdUnit4/unit test mention. Supports both GDScript (.gd) and C# (.cs) test files.
Asset stage manager. Reads current-tag ASSETS.md gaps, accepts user-provided assets, plans visual production units, dispatches asset-producer subagents, collects reports, updates ASSETS.md and the asset-generation manifest. Explicit invocation only - use /gm-asset.
Scaffold a new Godot project: project.godot + addons + base directories + e2e/conftest.py + initial git commit. Lifetime-once role — runs only on fresh projects. Explicit invocation only — use /gm-scaffold.
| 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 |
$ARGUMENTS
You are performing mechanical verification of a built Godot game project. This is a non-creative, checklist-driven process.
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.
Read .godotmaker/stage.jsonl (treat as empty if missing) — each line is {"role": X, "ts": Y}.
role == "build" AND no event with role == "fixgap" exists anywhere in the file → STOP. Tell user to run /gm-build first.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."
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:
godot_path from .claude/godotmaker.yaml; falls back to
plain godot from PATH. A missing or broken binary surfaces as a
tooling_notes[].suggested_fallback = "escalate" entry.<godot_path> --headless --quit and writes blocking Godot diagnostics
to checks.build.errors[].<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.checks.lint as pass with format_drift: null. Do NOT
re-enable here.checks.static_check to
python tools/check_project.py <project_dir> --build --ecs --tests --plan --mcp.Before writing the report, validate. Block on any of these:
result / ts / checks /
tooling_notes is missingchecks.{build,unit_tests,lint,static_check}
entries is absentresult == "pass" but tooling_notes is non-empty — re-run or escalatechecks.unit_tests.passed + .failed == 0 — spot-check by running the gdUnit4 command directly with --report-directory <temp>tooling_notes entry whose crashed_on looks unrelated to the
failing checkIf 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.
You produce two outputs:
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})
…}
.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 fail / error makes overall fail. tooling_notes alone never makes overall fail — the error it pairs with does.
ts — UTC ISO 8601 at the moment you write the file. Consumers compare it against their own last-event timestamp for freshness.
All array fields are required (possibly empty []). Do not omit them.
Per-check result — pass / fail are project-content. warn is non-blocking diagnostic noise (lint style drift or gdUnit warnings such as orphan nodes when every assertion passed). error means the tool itself crashed and the project's actual state is unknown for this check; pair error with exactly one tooling_notes entry. Consumers fix error via config, NOT project code.
format_drift — object when gdformat --check reports drift; null otherwise.
suggested_fallback + matching operand — the producer fills the operand so the consumer can act deterministically:
suggested_fallback | Required operand |
|---|---|
exclude_file | crashed_on (already required on every note) |
scope_narrow | narrowed_command (replacement command, e.g. "gdlint src/") |
add_gdlintrc_rule | rule_name (e.g. "class-name") |
skip_check | check_name (e.g. "missing_unit_test") |
escalate | — (none) |
Producer rule: if you cannot fill the required operand for a non-escalate fallback, emit escalate instead.
Consumer rule (open-enum forward-compat): a missing required operand or an unknown suggested_fallback value MUST be treated as escalate (surface to user, do NOT auto-fix). Never crash.
When the script's JSON has result: "fail":
.godotmaker/verify_report.json./gm-build if the last state-changing event was build, /gm-fixgap if it was fixgap.verify event to stage.jsonl — only PASS records a stage event.When the script's JSON has result: "pass":
.godotmaker/verify_report.json. (Field rules apply: tooling_notes == [], all checks.*.result ∈ {pass, warn} — the script enforces these but spot-check them once more before writing.)python tools/append_stage_event.py verify to append a {"role": "verify", "ts": "<server-generated UTC>"} line to .godotmaker/stage.jsonl. Do NOT hand-write the JSON or the timestamp — the helper exists so the timestamp comes from the system clock, not your own output.git add -A && git commit -m "chore(verify): <Tag>"Verify complete. Recommended next: /gm-evaluate