一键导入
deep-analysis
Investigate a game from raw logs, trace bugs to source code, and file detailed issues. Use for deeper debugging than export-only analysis.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Investigate a game from raw logs, trace bugs to source code, and file detailed issues. Use for deeper debugging than export-only analysis.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Debug a failing golden test from GitHub Actions logs and fix the root cause without papering over nondeterminism.
Repo-specific validation and PR instructions for mage-bench.
Find Magic cards for compact golden-test scenarios using existing repo goldens, curated references, and Scryfall search recipes.
Analyze exported game files to assess gameplay, model decisions, and likely bugs without raw logs. Use for quick game triage.
Write or update low-noise golden prompt tests in tests/, including minimal decks, replay scripts, and golden regeneration.
Create a new game export schema version, migration module, and related tests.
| name | deep-analysis |
| description | Investigate a game from raw logs, trace bugs to source code, and file detailed issues. Use for deeper debugging than export-only analysis. |
Deep analysis of game logs — reads all raw log files, traces bugs to source code, and files detailed issues. For quick triage, use /fast-analysis instead.
Determine which game to analyze:
If the user specified a game ID (e.g. game_20260211_080409), claim it before doing any analysis:
uv run python -m magebench.cli.analysis.claim_games --type deep {game_id}
If the claim fails, stop instead of analyzing an already-claimed game.
If the user said "most recent" or similar, find the latest:
uv run python -m magebench.cli.list_recent_games
Then claim the resolved game ID with uv run python -m magebench.cli.analysis.claim_games --type deep {game_id}.
If the user mentioned a config name (e.g. "round-robin-commander", "jumpstart-dumb", "modern-staller"), use the corresponding symlink:
uv run python -m magebench.cli.list_recent_games --config {config}
where {config} might be round-robin-commander, jumpstart-dumb, modern-staller, etc. Check what symlinks exist with --symlinks. Then claim the resolved game ID with claim_games.py --type deep.
If no game specified at all, claim the most recent unanalyzed game:
uv run python -m magebench.cli.analysis.claim_games --type deep --count 1
Set GAME_DIR=~/.mage-bench/logs/{game_id}.
If the full log directory doesn't exist but the game export exists in website/public/games/ (.json, .json5, .json.gz, or .json5.gz), tell the user the full logs aren't available and offer to run a fast analysis from the export instead. Stop here unless the user wants the fast analysis.
If website/public/games/${GAME_ID}.json5, .json5.gz, .json, or .json.gz exists (either on the current branch or generatable from the logs), extract a quick overview before diving into raw logs:
uv run python -m magebench.cli.game_gz_bootstrap ${GAME_ID}
This gives you a roadmap — you'll know which players had errors, roughly when, and what to look for in the raw logs.
Bootstrap caveat: game_gz_bootstrap.py currently overcounts failed tool calls because it substring-matches normal fields like required, and its auto-export fallback still checks ~/mage-bench-logs instead of ~/.mage-bench/logs. Treat its failure count as advisory and run uv run python -m magebench.cli.export_game ${GAME_ID} manually if the export is missing.
JSON5 caveat: many current exports are *.json5 with trailing commas, so ad-hoc python -c 'import json; ...' inspection will fail. Prefer repo tools (extract_decisions.py, game_gz_bootstrap.py) or parse directly with pyjson5.
Check the errors array first: The export may contain an errors field with critical issues surfaced from the per-player error logs (loop detection, uncaught exceptions, short ID collisions). These are high-signal bug indicators — always check and call them out before diving into raw logs.
Check for existing annotations: If the export has an annotations array, blunder analysis has already been run. Reference these annotations to guide your investigation — they identify specific decisions that were likely mistakes and explain why.
Retry caveat: if an annotation claims a timeout/default choice on GAME_CHOOSE_CHOICE, verify it against raw *_llm.jsonl. magebench.cli.export_game can currently record the first failed choose_action attempt and drop the later successful retry into a blank follow-up decision, which makes the annotation look like a timeout when the model actually recovered.
Crash-accounting caveat: if a player's export summary says toolCallsFailed=0 but the game clearly ended on a bad tool call, compare the tail of *_llm.jsonl and *_pilot.log. A final llm_response with no matching tool_call usually means the MCP request crashed before it could be logged. Those pilot-only crashes currently do not surface into export errors unless they also hit *_errors.log.
Check the decisions array: If the export has a decisions array, use extract_decisions.py to view structured decision records with board state, available choices, reasoning, and what happened next. Pass the export path, not just the game ID (for example: uv run python -m magebench.cli.analysis.extract_decisions website/public/games/${GAME_ID}.json5). This is often more useful than manually correlating events across log files.
Read config.json and game_meta.json — understand who played, what models/decks were used, and the game outcome (winner, turn count, life totals).
issue-query
Use parallel agents to analyze different log types simultaneously.
Pay particular attention to chat messages — they're the most human-readable signal about what went wrong. XMage sends game-state information, error messages, and rule explanations through chat. Players also chat when confused or stuck. Always read chat messages early and use them to guide your investigation of other log files.
player_chat events from game_events.jsonl (jq 'select(.type=="player_chat")' game_events.jsonl). Look for XMage system messages about illegal actions, failed spell resolutions, mana payment problems, and rule enforcement. Look for player messages that reveal confusion or frustration. Chat messages often point directly at the root cause before you even open error logs.*_errors.log files. Look for Java exceptions (NPE, IndexOutOfBounds, ClassCast), MCP tool failures, and stack traces. Note the exact filename and line numbers.*_pilot.log files. Look for LLM decision failures, repeated tool call patterns (loops), models sending wrong parameters, empty responses, and context trimming warnings. Pay close attention to what models complain about in their reasoning/thinking traces — when a model says "this doesn't make sense", "the tool returned wrong data", or "why can't I cast this", those are often smoking guns for real platform bugs rather than model confusion. Also check for personality infection: if the reasoning/thinking is full of in-character narrative (dramatic monologues, villain speeches, valley-girl speak) instead of game analysis, the chat personality is bleeding into gameplay decisions. Note the personality and flag affected decisions.
*_bridge.jsonl CHATMESSAGE lines and in game_meta.json decklists before filing a controller-assignment bug. Expressive personalities can confidently invent ownership bugs after they forget who cast the spell.*_llm_trace.jsonl against the structured MCP/export payload. This catches renderer bugs where the raw JSON has the needed field (for example incoming_attackers) but the prompt text shown to the model omits it.not found in current choices happens shortly after LLM request timed out after 120s, compare the late *_llm_trace.jsonl prompt against the current *_llm.jsonl tool-call result. If the bad ID was legal in the timed-out prompt but invalid at the later game_seq, localize it to pilot timeout/cancellation handling (pilot.py + pilot_recovery.py) rather than model hallucination.*_llm_trace.jsonl tells the model pass with answer=false, localize that stale instruction to the pilot state-bridge text in src/magebench/pilot/pilot.py, not to the live bridge tool schema.Stack: [Ability -> {'name': 'Player (you)', ...}], compare *_llm.jsonl / *_llm_trace.jsonl against exported snapshots. If the export has source_card / ability_text, localize the bug to bridge stack serialization plus decision_renderer.py, not the underlying game state.get_oracle_text(card_name=...) returns Card not found in database for normal cards but later get_oracle_text(object_id=...) succeeds for the same board, treat it as a bridge bug, not model confusion. Localize it to BridgeOracleTextService using CardRepository.findCard(name), and inspect the bridge startup path in BridgeClient that skips bulk card scanning.Bridge MCP HTTP server did not start ... (rc=1), inspect the embedded log tail or matching *_mcp.log before blaming the model. A common pre-game failure is the Java bridge dying during startup (for example BridgeClient.loadDeck() rejecting a generated .dck file such as line 1 NAME:...), so the HTTP port never opens.*_bridge.jsonl files. Look for repeated identical MCP calls (loop signatures), failed actions, "Index out of range" errors, and action sequences that suggest confusion (e.g., cast → cancel → cast → cancel).
GAME_CHOOSE_ABILITY shows descriptions like 1. ... but respond_with still says choice=0, choice=1, etc., trace the mismatch through AbilityPickerView plus BridgeCallbackHandler before classifying it as model misuse.pass_priority(until="stack_resolved") and then stalls, compare *_llm.jsonl, *_bridge.jsonl, and *_mcp.log. A final GAME_SELECT followed only by GAME_UPDATE / GAME_UPDATE_AND_INFORM plus long pendingAction=false waits means the bridge only re-checks stack_resolved while an actionable callback is pending.choose_action out-of-range diagnostic in the game directory's *_mcp.log files and classify each hit:
last_choices_response=boolean with index>=0, or negative indexlast_choices_count >= 0 with tiny last_choices_age_ms and rapid action-type flipsrg) for searching log files:
choose_action out-of-range diagnostic in $GAME_DIR with glob *_mcp.logIndex .* out of range in $GAME_DIR with glob *_errors.log or *_pilot.logInvalid structured content returned by tool in *_pilot.log. These mean the bridge returned data that doesn't match the tool's output schema — the action succeeds server-side but the model gets an error. See doc/investigating-game-logs.md for details.game_events.jsonl. Look for stalls (long gaps between events), excessive auto-passes, turn timeouts, and game flow anomalies. For targeted investigation, use python -m magebench.analysis.toolbox.game_timeline from the export — it supports --turns, --player, --mana, and -v flags to drill into specific turns or mana behavior. Caveat: some v7 exports omit snapshots[].ts, which currently makes game_timeline.py --turns ... misclassify every event as the final turn or print zero events. Fresh v8 exports without blunder annotations can also crash game_timeline.py with missing annotations because it currently uses the post-annotation loader. Sanity-check the output before relying on that filter; if it crashes, fall back to game_events.jsonl or extract_decisions.py.A single bug often shows up across multiple log files. For example, an NPE in error logs corresponds to a failed tool call in bridge logs and a confused retry loop in pilot logs. Group these into one issue, not three.
pilot): Check whether the player's chat personality is bleeding into their internal reasoning/thinking traces, causing worse gameplay decisions. This is a known antipattern where dramatic or expressive personalities (dramatist, villain, valley-girl, philosopher, etc.) cause the model to spend reasoning tokens on in-character narrative instead of board state analysis. Symptoms: reasoning full of dramatic monologue instead of game analysis; the model narrating intended plays in-character but timing out or picking wrong actions; the model interpreting normal game prompts as adversarial because the personality frames things dramatically (e.g. calling the game engine "broken" or "gaslighting"). If you see this, file an issue noting the personality, the specific decisions affected, and how the in-character reasoning led to the bad play. Analytical personalities (spike, analyst, detective) are generally clean.presets.json (each preset references a named toolset from toolsets.json). Note the model and the problematic tool so we can track patterns across games and decide whether to revoke that tool from weaker models' toolsets or design simpler alternative tools.For each code bug, read the relevant Java/Python files to identify the exact line and root cause. Include in the issue:
~/.mage-bench/logs/game_YYYYMMDD_HHMMSS/BridgeCallbackHandler.java:1407)Before filing a new issue, check whether the bug has already been fixed since the game was played. Compare the game date against recent commits:
git log --oneline --since="YYYY-MM-DD" origin/master # date of the game
If a commit clearly fixes the bug, skip filing the issue. If unsure, file it and note the possibly-relevant commit in the description.
Create issue files in issues/:
issues/p{priority}-short-kebab-summary.json5issues/blocked-short-kebab-summary.json5 only when Gregor explicitly says the issue has manual preconditions; those files should also include "blocked": true{
"title": "Short summary",
"description": "Full description with root cause analysis.\n\nEvidence:\n- ~/.mage-bench/logs/game_.../Player_errors.log: NPE at line 42\n- ~/.mage-bench/logs/game_.../Player_bridge.jsonl: repeated cast-cancel pattern\n\nSource: BridgeCallbackHandler.java:1407 — cv.getDisplayName() returns null\n\nSuggested fix: null-guard displayName before passing to StringBuilder",
"status": "open",
"priority": N,
"type": "task",
"labels": ["relevant-labels"],
"created_at": "YYYY-MM-DDTHH:MM:SS.000000-08:00",
"updated_at": "YYYY-MM-DDTHH:MM:SS.000000-08:00"
}
Priority guide:
Labels: bridge, puppeteer, pilot, spectator
Only analyze the game selected in step 1. Do not look at older games — each analysis run should be scoped to one game to keep context focused and output actionable.
Present a summary of all issues created, grouped by priority. For model-only issues, mention them in the summary but note they don't need code fixes.
Always end the summary with an explicit dataset disposition for the game:
State the disposition explicitly in the final answer and in the deep-analysis log file from Step 14, with one short reason sentence.
If you need to write any non-trivial log analysis logic (more than a simple jq one-liner), create a Python script in src/magebench/analysis/toolbox/ rather than writing throwaway one-off code. Run these scripts with uv run python -m magebench.analysis.toolbox.your_module. These scripts accumulate over time into a reusable analysis toolkit. Check what already exists in src/magebench/analysis/toolbox/ before creating something new — you may be able to reuse or extend an existing script. Key scripts already available: game_timeline.py, mcp_errors.py, mana_tapping.py, and extract_decisions.py (exposed via uv run python -m magebench.cli.analysis.extract_decisions).
If you discovered any useful jq queries, grep patterns, cross-referencing techniques, or other tricks for investigating game logs during this analysis, append them to doc/investigating-game-logs.md. Don't duplicate what's already there — read the file first.
Create a file in doc/claudes/analyses/deep/ for the game analyzed (see doc/claudes/analyses/README.md for the template). This marks the game as deep-analyzed so future runs skip it.
If you discovered new recurring patterns, useful analysis techniques, broken scripts, or better workflows during this run, update this file before finishing. This skill improves over time as more games are analyzed. Examples of things to add:
src/magebench/analysis/toolbox/Do not add issue-specific bug notes to the skill if you already filed them in issues/. The skill should capture reusable investigation technique, tooling caveats, and durable workflow guidance, not duplicate the issue tracker.