Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Fix gaps identified by the Evaluator. Generates GAP.md from evaluation.json, dispatches workers to address critical/major issues, then runs one final verify+review pass. Unlike gm-build (PLAN.md-driven), gm-fixgap is GAP.md-driven. Explicit invocation only — use /gm-fixgap.
.claude/skills/randallliuxin-gm-fixgap/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-10 | ✗→✓ | ▲ Improved | 333% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 265% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 394% | 0% |
| case-20 | ✗→✓ | ▲ Improved | 679% | 0% |
| case-22 | ✗→✓ | ▲ Improved | 486% | 0% |
$ARGUMENTS
You are fixing specific issues identified by the Evaluator. You read the evaluation report, generate a GAP.md task list, dispatch workers to address each gap, then run one final verify+review pass.
Loop position: /gm-fixgap is never terminal. The cycle is /gm-fixgap → /gm-verify → /gm-evaluate. Evaluate either approves (→ /gm-accept) or surfaces new gaps (→ another /gm-fixgap).
FIRST ACTION — before anything else: Write fixgap to .godotmaker/current_role.
Read .godotmaker/stage.jsonl (treat as empty if missing) — each line is {"role": X, "ts": Y}.
role == "evaluate" exists anywhere in the file OR .godotmaker/evaluation.json does not exist → STOP. Tell user to run /gm-evaluate first.evaluation.json result is "approve" → STOP. Tell the user:> "The latest evaluation was already approved. Recommended next: /gm-accept. > If you need to redo this step or have other plans, just tell me."
role == "fixgap" AND GAP.md is not at project root (already archived) → STOP. Tell the user:> "Fixgap already completed for the latest evaluation at {timestamp}. Recommended next: /gm-verify. > If you need to redo this step or have other plans, just tell me."
Then read context:
GAP.md (if present) → existing fix progress; find tasks not yet verified. If missing, Step 1 will generate it from evaluation.json (and verify_report.json)..godotmaker/evaluation.json → the source of truth for product-layer issues to fix.godotmaker/verify_report.json → mechanical-layer failures from the most recent verifyPLAN.md → read-only; current tag's **Tag:** header tells you which tag's gaps you're fixing. The same tag-scope discipline as gm-build applies: previous tags' code is touchable only when a GAP item explicitly names it.STRUCTURE.md → architecture (fixes need to respect existing system boundaries)ASSETS.md → the generated-runtime authority; for a visual task, derive each asset with tools/asset_result_registration.py --snapshotMEMORY.md index + sub-files → past decisions and known gotchasASSETS.md is the sole runtime-asset authority. For a visual task, derive the snapshot with tools/asset_result_registration.py --snapshot and never read a stable entry, manifest pointer, or root index. The snapshot resolves generated and complete user-provided runtime rows, including uniquely named rows introduced by earlier tags.
evaluation.json or a fresh verify_report.json identified. Do not add features or refactor unrelated code.references/reviewer-finding-triage.md (mandatory for critical/major; optional for minor).GAP.md tasks transition forward only:
pending → in_progress → completed → verifiedverified → pending)When you ACCEPT a reviewer finding against a verified task: Do NOT change the existing task's state. Add a NEW task (status pending) in GAP.md describing the fix. The original task stays verified. The new task goes through the full lifecycle. (REJECT or SKIP findings go to MEMORY.md instead — see references/reviewer-finding-triage.md.)
This way the state is always monotonic and the audit trail is preserved.
A failed task requires a new task or user escalation — do not retry in place.
Do NOT update PLAN.md task statuses — fixgap operates from evaluation.json gaps, not the original plan.
GAP.md may need tasks from two sources:
.godotmaker/evaluation.json — product-layer issues found by the evaluator. Always processed..godotmaker/verify_report.json — mechanical-layer failures from the most recent verify pass. Processed only when fresh.evaluation.jsonCreate one critical evaluation-source GAP task for each playable_unit.rows.* entry with result == "fail". Include the row key, test path, and evidence entries. Fix the game code or runtime path. Do not reduce the PLAN.md or e2e/ contract.
For each E2E-sourced issue, decide the repair path before writing GAP tasks:
requested_test_interface:.
/gm-evaluate when the E2E assertion or scenario is wrong.only when the evaluation evidence cites a GDD.md or PLAN.md requirement.
Copy observed_gap: and requested_test_interface: evidence entries into the GAP task when present.
GAP tasks must preserve the normal gameplay flow while satisfying the observable requirement or requested test interface.
critical_issues — must fix all (→ task IDs C1, C2, …)major_issues — fix as many as possible (→ task IDs J1, J2, …)gameplay_issues — fix only if related to a critical/major (→ G1, G2, …)minor_issues — skip unless trivialEvaluation-source visual tasks must cite the blocking finding reported by evaluation. Do not create a C/J task from a style-only or non-blocking visual finding. For blocking visual tasks, copy the relevant evaluation.json.visual_checks scene, reference, captures], latest vqa_calls[].context, and latest vqa_calls[].log into the GAP task.
verify_report.jsonRun this sub-step only if .godotmaker/verify_report.json exists, result == "fail", and its ts is later than the most recent role == "fixgap" event in stage.jsonl (or there is no prior fixgap event). Otherwise (file missing, result == "pass", or stale ts) → skip 1b; GAP.md comes from 1a only.
Translate failures into tasks using the existing C / J prefixes — verify-source tasks share the numbering pool with evaluation-source tasks. Each task carries both a classification (C/J) and an execution mode (worker / main-agent-direct / escalate-to-user); Step 3 follows the execution mode without re-classifying.
Project-code tasks (checks.<name>.result == "fail") — execution = dispatch worker (normal Worker → Verifier → Reviewer cycle):
checks.build.errors[] / checks.unit_tests.failures[] → C (compile/runtime failures block forward progress).checks.unit_tests with failed > 0 and empty failures[] → C, one task: "investigate test runner output".checks.static_check.issues[] of check == "missing_unit_test" → J (gap, not a hard block).checks.static_check.issues[] → C (project-completeness gate).checks.lint.issues[], checks.lint.format_drift → J (technical debt).static_check.issues[].check discriminator → use the raw value verbatim, default C.Config tasks (checks.<name>.result == "error", paired with tooling_notes[]):
gm-verify/SKILL.md Section B) → J, execution = main-agent-direct (apply the structured edit using the operand; Hard Rule 1 only restricts .gd/.tscn/.tres; mark verified after the next verify round confirms the crash is gone). NO worker dispatch.escalate, OR routable with missing operand, OR unknown discriminator → C, execution = escalate-to-user (surface tool + error + crashed_on and any original suggested_fallback verbatim, halt the cycle, leave pending until the user resolves it). NO worker dispatch.Each task records its origin via a Source: verify_report.json | evaluation.json line in the task block (and verify / evaluation in the Task Status table). Numbering follows insertion order — existing rows keep their numbers, new rows get the next available number per letter. Execution priority dispatches verify-source before evaluation-source regardless of number.
If GAP.md does not exist: Generate it from .claude/templates/GAP.md. Within each letter list verify-source tasks first (so they get the lower numbers), then evaluation-source. All tasks start as pending. Record both source timestamps in the header — Source Evaluation: <evaluation iteration / ts> and (when applicable) Source Verify: <verify_report ts>.
If GAP.md already exists:
Source Evaluation header differs from current evaluation.json → archive and generate a fresh one.pending rows with the next available number per letter; existing rows keep their numbers and statuses. Update the Source Verify header to the new ts.verified tasks).Backward compatibility (per-row). Apply on each row independently — interrupted upgrades leave mixed-annotated state:
Source: line or Source column entry → treat as evaluation, fill when you next touch that row.Source: as-is.Source: line and the column entry.For each non-verified task in GAP.md:
Affected files/systems)Worker-dispatch tasks only — Step 1b classified main-agent-direct and escalate-to-user tasks; handle those per their classification, not here.
references/worker-dispatch.md for the brief template.references/repair-attempt-accounting.md after every workerhandoff. Increment dispatch_count for the handoff, then classify it from the report evidence before changing any retry counter or task state.
pending.subagent_type: "worker". Max 3 in parallel with disjoint file sets via isolation: "worktree".Asset Runtime Snapshot fromreferences/worker-dispatch.md. The snapshot is tools/asset_result_registration.py --snapshot output pasted verbatim. If it fails for an asset, report its error instead of dispatching the task against an invented path.
Visual Asset Contract andVisual Self-Check from references/worker-dispatch.md.
pending → in_progress when dispatched, in_progress → completed when worker reports DONE.Unlike gm-build, fixgap does NOT batch every ≥N workers. Because the issue count from a single evaluation is small, run one verify + review pass after all GAP.md tasks reach completed.
Verifier:
references/verifier-dispatch.md for the brief templatesubagent_type: "verifier". Pass all completed workers' deliverables.Visual Verification sectionfrom references/verifier-dispatch.md, including the worker self-check result when present.
completed). Loop back to Step 3.completed → verified.If verification exposes a design constraint conflict, stop splitting it into smaller visual tasks. Record the conflict in GAP.md notes, choose the interpretation already stated by SCENES.md if clear, or escalate for a design decision.
Reviewer (after verifier passes):
references/reviewer-dispatch.md for the brief templatesubagent_type: "reviewer". Reviewer reports back; do not let it modify project files.Asset Runtime Snapshot when reviewed files use visual assets.references/reviewer-finding-triage.md into one of three options:pending task to GAP.md.The cycle ends when ALL GAP.md tasks are verified AND the most recent review round added no ACCEPTED tasks.
Move the completed GAP.md to .godotmaker/gaps/<source-evaluation-iteration>/GAP.md so the project root is clean for the next round.
Five effective production repairs, not five dispatches, are the only failure gate. Apply references/repair-attempt-accounting.md: incomplete handoffs and orchestration failures use its no-progress process, keep the task continuable, and do not consume the repair budget.
isolation: "worktree"references/worker-dispatch.md → Parallel Worker Dispatch for merge procedureMEMORY.md <- Index + cross-cutting knowledge
memory/
{system_name}.md <- Per-system details (template: .claude/templates/memory_subsystem.md)| Skill | Purpose | Path | |-------|---------|------| | gecs | ECS framework API + patterns | .claude/skills/gecs/SKILL.md | | headless-build | Compile verification | .claude/skills/headless-build/SKILL.md | | gdunit-driver | Unit test execution | .claude/skills/gdunit-driver/SKILL.md | | godot-api | Godot API reference | .claude/skills/godot-api/SKILL.md | | screenshot | Gameplay screenshot capture | .claude/skills/screenshot/SKILL.md | | visual-qa | Screenshot/reference visual checks | .claude/skills/visual-qa/SKILL.md | | mcp-driver | Runtime debugging via godot-mcp | .claude/skills/mcp-driver/SKILL.md |
Asset analysis: Dispatch an Analyst subagent (subagent_type: "analyst", see references/analyst-dispatch.md) when you need to analyze user-provided assets.
Your context window is finite. Protect it:
In your context: GAP.md status, STRUCTURE.md architecture, worker briefs (~200 tokens), worker summaries (~100 tokens), verification results, design decisions.
Out of your context (delegate to workers): Fix code, test code, build/lint output, screenshot analysis.
When context gets large: Summarize completed fixes. Reference documents by path. Write decisions to MEMORY.md for recovery after compaction.
Handoff only after runtime GAP work is complete and the remaining failure is an E2E assertion, scenario, capture, or capture-timing defect.
verified; do not archive GAP.md.Evaluator handoff note with the source evaluation, runtime evidencelocation, and failing E2E/capture location.
text python tools/append_stage_event.py fixgap --outcome=handoff --next_role=evaluate --reason=evaluator_owned_e2e
git add -A && git commit -m "chore(fixgap): evaluator handoff <Tag>".FixGap handed off E2E evidence to /gm-evaluate.After all GAP.md tasks are verified, the final reviewer added no new tasks, and GAP.md has been archived:
python tools/append_stage_event.py fixgap to append a {"role": "fixgap", "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(fixgap): <Tag>"Fixgap complete. Recommended next: /gm-verify (then re-run /gm-evaluate to confirm the gaps are closed).| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→fail | 12,265 | 7,001 | -43% | 1 | 1 | 0% | 1,419 | 4,976 | +251% | 0 | 0 | — |
case-01 | fail→fail | 5,788 | 5,460 | -6% | 1 | 1 | 0% | 275 | 4,861 | +1668% | 0 | 0 | — |
case-02 | fail→fail | 4,784 | 5,090 | +6% | 1 | 1 | 0% | 248 | 4,769 | +1823% | 0 | 0 | — |
case-03 | fail→fail | 4,827 | 5,628 | +17% | 1 | 1 | 0% | 169 | 4,906 | +2803% | 0 | 0 | — |
case-05 | pass→fail | 4,123 | 6,182 | +50% | 1 | 1 | 0% | 305 | 4,942 | +1520% | 0 | 0 | — |
case-06 | fail→fail | 9,383 | 3,635 | -61% | 1 | 1 | 0% | 1,554 | 5,011 | +222% | 0 | 0 | — |
case-07 | fail→fail | 3,975 | 8,732 | +120% | 1 | 1 | 0% | 232 | 5,274 | +2173% | 0 | 0 | — |
case-08 | fail→fail | 34,125 | 4,842 | -86% | 1 | 1 | 0% | 238 | 4,808 | +1920% | 0 | 0 | — |
case-09 | pass→pass | 7,043 | 4,157 | -41% | 1 | 1 | 0% | 1,193 | 5,345 | +348% | 0 | 0 | — |
case-10 | fail→pass | 8,675 | 3,433 | -60% | 1 | 1 | 0% | 1,204 | 5,214 | +333% | 0 | 0 | — |
case-11 | fail→fail | 7,130 | 3,865 | -46% | 1 | 1 | 0% | 1,057 | 5,217 | +394% | 0 | 0 | — |
case-12 | fail→fail | 9,651 | 3,950 | -59% | 1 | 1 | 0% | 1,368 | 5,222 | +282% | 0 | 0 | — |
case-13 | fail→fail | 11,920 | 4,527 | -62% | 1 | 1 | 0% | 1,732 | 5,348 | +209% | 0 | 0 | — |
case-14 | pass→pass | 8,520 | 8,175 | -4% | 1 | 1 | 0% | 1,229 | 5,208 | +324% | 0 | 0 | — |
case-15 | fail→fail | 12,470 | 6,620 | -47% | 1 | 1 | 0% | 2,006 | 4,992 | +149% | 0 | 0 | — |
case-16 | fail→pass | 9,112 | 7,578 | -17% | 1 | 1 | 0% | 1,372 | 5,012 | +265% | 0 | 0 | — |
case-17 | pass→pass | 5,248 | 2,705 | -48% | 1 | 1 | 0% | 818 | 5,016 | +513% | 0 | 0 | — |
case-18 | fail→fail | 6,561 | 4,634 | -29% | 1 | 1 | 0% | 1,088 | 5,506 | +406% | 0 | 0 | — |
case-19 | fail→pass | 6,833 | 4,017 | -41% | 1 | 1 | 0% | 1,030 | 5,091 | +394% | 0 | 0 | — |
case-20 | fail→pass | 4,589 | 2,907 | -37% | 1 | 1 | 0% | 651 | 5,070 | +679% | 0 | 0 | — |
case-21 | pass→pass | 8,194 | 2,817 | -66% | 1 | 1 | 0% | 1,361 | 5,036 | +270% | 0 | 0 | — |
case-22 | fail→pass | 5,969 | 3,668 | -39% | 1 | 1 | 0% | 862 | 5,052 | +486% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 14 counted toward the lift figure. The other 8 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +18 percentage points is the difference between those two pass rates over the 14 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.