Skip to content

Skyrim Forge 5.1.0 — linting, checked against 3,000 real mods

Choose a tag to compare

@github-actions github-actions released this 15 Aug 14:39
· 23 commits to main since this release

Skyrim Forge 5.1.0

Framework linting, checked against a real reference corpus for the first time.

Forge's SPID/KID/BOS/FLM/SkyPatcher profiles were written from documentation,
with no installed mods to check them against. Pointed at 1,195 framework
configs from a live 3,000-mod load order
, the linter produced:

before after
errors 13,554 11
warnings 11,762 71
files with findings 194 (16%) 64 (5%)

The 11 remaining errors are genuine defects in third-party mods.

Every finding was triaged against the frameworks' own SKSE runtime logs, because
a distribution log outranks a static profile.

What was wrong

SkyPatcher clause values were split on commas. A value is routinely a
comma-separated form list:

filterByLLNPCs=Skyrim.esm|0x01E78D:removeFromLLs=A.esp|001DBD, A.esp|001DC8

Every form after the first was reported as unmodeled syntax — 11,730 warnings
from a single parsing error
. Rules are validated per key=value clause now.

A single-value SPID skill filter was an error. The corpus installs 13,427 of
them across skill indices 12–16, and po3_SpellPerkItemDistributor.log records
zero parse failures for any of them. One was traced end to end: Abyss's
14(20) distributed as SPEL:FE059810.

Five rows were rejected at runtime, all using skill index 0, so the observation
is kept — as an advisory. Failing 13,427 working rows to catch 5 is the worse
error, and Forge cannot currently tell them apart. It says so rather than
pretending to know.

Advisories buried everything else. A repeated note is now collapsed to one
entry per file naming the count and first line.

Five SkyPatcher categories were missingoutfit, ingestible, misc,
ingredient, projectile. All installed, all working, none in the profile.

KID keys were matched case-sensitively. Shipping mods write keyword =, and
BoobiesArmorPouch [KYWD:FF001DA3] distributes from one.

A two-field KID line was rejected as an unsupported type label. Field 2 is a
name filter there; BoobiesArmorScarf [KYWD:FF001DA5] applied at runtime.

Byte-order marks invented findings. utf-8-sig strips one. Corpus files
carry three stacked at the top, and one mid-file where two sources were
concatenated. A surviving U+FEFF stopped a comment from being a comment and
turned a valid key into an unknown one.

Kept strict

Nothing above weakens a check that catches real breakage. The 11 surviving errors
are real, including a KID line wrapped across two lines that never distributes.

Two existing tests asserted the single-value-skill rejection. Runtime disproved
them, so they now assert the evidence instead. InstalledCorpusRegressionTests
is built from the real installed lines.

Note

The version gate added in 5.0.2 caught the AI skill still advertising the 5.0
series during this bump — which is exactly what it was written for.

Validation: full repository gate PASS at 5.1.0, 142 tests, all 10 CI jobs and
CodeQL green, native helpers rebuilt reproducibly with pinned Go 1.23.2.

Still tool-validated: Skyrim gameplay and third-party GUI results remain untested
runtime gates. The corpus evidence here is stronger than that — it is drawn from
installed mods and their own runtime logs — but it is one load order, not proof
of every framework version.