warnings
SkillDev toolsPrint the complete, untruncated list of issues from a Millennium Dawn validator, optionally filtered to one category. Use when the user asks for all warnings/errors from a validator, e.g. "/warnings events unreferenced-triggered-only". Args: validator name, optional category, optional "errors"/"warnings"/"staged".
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the warnings skill
What this skill tells your AI
The instructions your AI receives, as published by millenniumdawn/millennium-dawn in .claude/skills/warnings/SKILL.md and read by ahel’s review.
Print every issue a validator reports, with no truncation.
The validators' console output caps each category at 50 findings and then prints
... and N more (full list in the JSON sidecar). This skill reads the sidecar instead, so
the list is always complete. /validate remains the command for a summarized suite run.
Requested arguments: $ARGUMENTS
Grammar (all optional, order-independent): <validator> [category] [errors|warnings] [staged]
Step 1 — resolve the validator
Map the name to tools/validation/validate_<name>.py, converting - to _. Accept
events, validate_events, validate_events.py, and focus-tree/focus_tree alike.
Valid names:
agency-upgrades ai-equipment ai-navy ai-roles cosmetic-tags decisions defines
events factions file-paths focus-tree gfx-references history ideas localisation
mios mod-descriptors modifiers on-actions oob-units scripted-gui
scripted-localisation scripted-params set-variables simplifications style
unused-scripted unused-textures variables
If the arguments name no validator, call AskUserQuestion before running anything.
Offer: events, focus-tree, decisions, ideas as options, plus
"All validators (full dump)". The automatic "Other" choice covers the rest of the list.
Never guess a validator.
If the name is not in the list, print the list and stop. Run nothing.
Step 2 — run the validator
One validator (append --staged when the staged token is present):
python tools/validation/validate_<name>.py --path . --no-color -o "<scratchpad>/warnings-<name>.txt"
The run writes warnings-<name>.json alongside the .txt. That sidecar is the input for
step 3 — it holds every finding, uncapped.
gfx-references skips its unused-sprite check unless --report-unused is passed. Append
that flag when the requested category is unused-sprite, unused-sprite-case,
duplicate-sprite or case-variant-sprite. For the latter three, also set
MD_GFX_HIDE_UNUSED=1 so the ~6.7k orphan warnings stay out of the report.
All validators:
python tools/validation/run_all_validators.py --path . --no-color --format json -o "<scratchpad>/warnings-all.json"
Suite entries carry an extra validator field; single-validator entries do not.
These scans take minutes. Do not add a timeout below 600000.
Step 3 — dump the sidecar
Pass the category and severity filters as arguments, empty string for "no filter". Severity
is error when the errors token is present, warning when warnings is present, empty
otherwise (both).
python - "<json path>" "<category or empty>" "<severity or empty>" <<'PY'
import json, sys
p, cat, sev = sys.argv[1], sys.argv[2], sys.argv[3]
data = json.load(open(p, encoding="utf-8"))
issues = data["issues"] if isinstance(data, dict) else data
if cat: issues = [i for i in issues if i.get("category") == cat]
if sev: issues = [i for i in issues if i.get("severity") == sev]
print(f"TOTAL {len(issues)}")
for n, i in enumerate(issues, 1):
loc = i.get("file", "")
if loc and i.get("line"): loc += f":{i['line']}"
tag = "E" if i.get("severity") == "error" else "W"
print(f"{n}. [{tag}] " + (f"{loc} - " if loc else "") + i.get("message", ""))
PY
When no category was given, get the index with the same file:
python - "<json path>" <<'PY'
import collections, json, sys
data = json.load(open(sys.argv[1], encoding="utf-8"))
issues = data["issues"] if isinstance(data, dict) else data
c = collections.Counter((i.get("category", "?"), i.get("severity", "?")) for i in issues)
agg = collections.defaultdict(lambda: [0, 0])
for (cat, sev), n in c.items(): agg[cat][0 if sev == "error" else 1] += n
for cat, (e, w) in sorted(agg.items(), key=lambda kv: -sum(kv[1])):
print(f"{sum((e, w)):6d} {e:5d}E {w:5d}W {cat}")
PY
Step 4 — present
Copy the command's stdout through verbatim inside one fenced block.
- Lead with the total and which validator/category it came from, and name the current branch.
- Category given → the flat numbered list, nothing else.
- No category → the index first, then the full list beneath it.
- Never truncate, summarize, sample, re-order, or re-word a line, and never write "and N more". Removing the 50-cap is the entire purpose of this skill. A long list stays long.
Then state these caveats:
- A warning is not automatically a bug. Reference-scanning categories such as
unreferenced-triggered-onlyonly grep.txtundercommon/,events/, andhistory/, so an event fired from a.gui, a scripted GUI, or an unresolved interpolated ID reads as unreferenced. Each entry needs a look before anything is deleted. - Counts drift with the worktree, since the scans re-read the working tree on every run. Report the count from the run just performed; never reuse a number from earlier in the conversation.
- Say so explicitly when
--stagedwas applied, so a short list is not mistaken for a clean repo.
Signals
- GitHub stars
- 122
- Forks
- 84
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
warnings- Source
- github.com/millenniumdawn/millennium-dawn