feat: HellDrinx takeaways — conflict blocklist + vehicle path signal

Two narrow additions adopted from a review of HellDrinx Mod Manager
(/tmp/helldrinx-modmanager-PZ-main.zip), per
docs/plans/ (planning conversation, no spec checked in).

A. _IGNORED_FILENAMES in api/diagnostics.py — skip filenames that are
   intended merge points (PZ engine-concatenated or framework hooks)
   from /api/conflicts output. Multiple distinct sha1s for these files
   is by-design, not a conflict. Live cache had 33 providers shipping
   sandbox-options.txt with 31 distinct hashes — those would have been
   31 false-positive conflict rows on any sort spanning them.

B. Path-based Vehicles signal in worker.build_manifest_and_types —
   extended the existing scripts/vehicles[/] check with
   models_x/vehicles/ and models/vehicles/. Catches vehicle mods that
   ship 3D assets without scripts (rare but real); still requires the
   user-build's manifest to be rebuilt before mod_types reflects it.
This commit is contained in:
2026-05-06 19:20:29 +00:00
parent f8b48fbacb
commit b1471b739f
2 changed files with 38 additions and 2 deletions

View File

@@ -14,6 +14,29 @@ from typing import Dict, List, Tuple
from mlos_sort import ModInfo
# Filenames that legitimately appear across multiple mods because they're
# intended merge points — either PZ engine-merged at runtime, or framework
# extension hooks where multiple client mods coexist by design. Multiple
# distinct sha1s here is by-design, not a conflict, so we skip them in
# scan_file_conflicts. Sourced from HellDrinx Mod Manager's known false-
# positive list (backend/services/workshop.cjs); add more here as we
# encounter them.
_IGNORED_FILENAMES = {
# PZ engine-merged at load time
"sandbox-options.txt",
"fileguidtable.xml",
# Framework extension hooks (designed for many mods to override)
"mf_ismoodle.lua", # MoodleFramework hook
"kp_extrabodylocations.lua", # KP body-locations framework hook
"registries.lua", # damnlib-style registry framework
# Specific mod-side merge points
"hat_gasmask.xml",
"hat_gasmask_nofilter.xml",
"sounds_tmrremovemumble.txt",
"null.wav", # silent placeholder, deliberately shared
}
@dataclass
class FileConflict:
rel_path: str
@@ -59,7 +82,14 @@ async def scan_file_conflicts(conn, mods: List[ModInfo]) -> List[FileConflict]:
idx = order_index.get(mod_id)
if idx is None:
continue
by_path[r["rel_path"]].append((idx, mod_id, r["sha1"]))
rel_path = r["rel_path"]
# Skip known intended-merge-point filenames (engine-concatenated or
# framework hooks). These produce noisy false positives because
# multiple mods adding sandbox vars / framework hooks is by design.
basename = rel_path.rsplit("/", 1)[-1]
if basename in _IGNORED_FILENAMES:
continue
by_path[rel_path].append((idx, mod_id, r["sha1"]))
conflicts: List[FileConflict] = []
for rel, entries in by_path.items():