x4-debug
Read and summarize the active X4 profile's debug.txt, filtering known-benign noise and surfacing only real mod errors. Use after an in-game test, or when the user asks what went wrong or to check the
SKILL.md.claude/skills/x4-debug/SKILL.md
GitHub<!-- GENERATED by tools/x4validate/scripts/gen-agent-trees.py from agent/. Do not edit: regenerate. -->
Read the active profile's debug log and report only REAL errors.
Run the tool first, do not hand-roll the triage. uv run --python 3.13 x4debug triage [log] resolves the log
the same way this skill does, states its mtime and whether a NEW GAME marker is present.
Without that marker the session is UNKNOWN (menu or save load). It buckets every [=ERROR=] line by mod, by script, by engine subsystem, and by
unclassified residue. Its rows are required to sum to the lines read.
A hand-rolled grep | sort | uniq -c pass cannot tell you what it dropped. That is not a
hypothetical: the parser underneath this skill silently discarded 44% of a real log for two weeks,
and the most consequential defect in that log sat in the discarded part.
Then, for any mod the log names:
uv run --python 3.13 x4debug crosscheck <deployed-mod>— a per-item diff of the ops the engine SKIPPED against the ops x4validate predicted would fail. Three buckets, never two totals: agreed, predicted-only (a stale prediction, or an op that never ran), and observed-only, which is a blind spot in the validator and should be reported as one.uv run --python 3.13 x4debug baseline— archive the log with a content fingerprint, so the NEXT launch can be diffed against this one instead of against a remembered number.
Never compare two logs by their totals. Compare per bucket and per item; a net-zero change is the shape a real regression hides in.
Locating the log. Resolve it, never hard-code it: $X4_DEBUGLOG, else
$X4_PROFILE/debug.txt, else ask. If neither is configured the profile lives at
Windows Documents\Egosoft\X4\<profile-id>\ and Linux ~/.config/EgoSoft/X4/<profile-id>/. x4validate --paths prints what the toolkit resolves. A profile
folder is a numeric id; if several exist, confirm which is active rather than guessing — a stale
profile's log will look plausible and be months old, so check the file's mtime before trusting
it.
How to classify a line
Work in this order. The goal is a short list of things that are actually broken, not a transcript.
1. Benign by category — do not report:
Failed to verify the file signature(error 13/14) — normal for every unsigned mod.LibraryLoadout()/ConstructionPlan()errors naming an extension id that is not installed — the player's saved loadouts/blueprints referencing a mod they no longer have. Unrelated to the mod under test.- Errors whose root cause is vanilla data rather than any mod. Prove it before dismissing: the
claim "vanilla does this too" needs a
reference\check, not an assumption.
2. Known-benign specifics — consult, don't memorize. The catalogue of which mods currently produce known-harmless volume, and why, lives in KNOWLEDGEBASE.md → "Debug triage". Read it at triage time. It is dated and revisable; this skill is not the place for it, because a mod list changes and a skill that names mods goes quietly stale and starts suppressing real findings.
3. Expected-and-correct — do not report as a regression:
- An upstream mod's failing
<replace>still logs even when a load-last overlay supplies the value afterwards: the upstream op runs first and fails regardless. Judge such fixes by the effective value (x4effective who-sets), not by the log line disappearing. - A mod's own ambiguous selector (
Multiple matching nodes ... Skipping) when an overlay is deliberately supplying the content instead.
4. Everything else is a finding. Focus on [=ERROR=] and [=WARNING=]. Group by mod/source,
quote each with line numbers, and name the likely cause: XML parse error, missing/unresolved
reference, unknown event or property, or a missing required attribute. For version-shift symptoms,
cross-check the Version Migration Map in KNOWLEDGEBASE.md.
Comparing two logs
Check each log for the NEW GAME marker (grep -c "Universe generation begins"). Its absence
does not prove a save load: menu startup also lacks it. Raw error counts are not comparable
between confirmed new games and unmarked sessions — compare per-category presence/absence
instead, and retain any independently confirmed session type alongside the log.
Reporting
Summarize: total real errors, grouped by source, highest-severity first. Say explicitly what you filtered and why, so the user can challenge a filter.
A mod that loads without crashing is NOT necessarily correct — call out silent reference
failures, and remember the log only lists failures: an op that silently did nothing successfully
never appears. Pair the log with x4validate (which models what the engine sees) rather than
treating a quiet log as proof.
Deferrals
If the user has explicitly deferred a known-noisy source, collapse it to a single counted line — but record the deferral with its reason and date in the KB or registry, never as a standing instruction here. A deferral written into a skill outlives the decision that justified it: one such line survived the mod being uninstalled and kept telling every session to ignore errors that could no longer occur.