chore: drop dead code, sync stale comments
- delete api/categorize.py: orphaned module, never imported. The live
pzmm-types→category mapping is _types_to_category in mlos_sort.py.
- delete api/adapters.py:_autopick_ambiguous: 5-line wrapper around
_apply_branch_rules with zero callers in current source.
- delete docs/backlog/polling-path-pz-build.md: described work that
shipped — init/06_sort_jobs_pz_build.sql plus pz_build plumbing in
jobs.create_job, app._route_to_job, and app._build_result_for_job.
- sync MAP_LINE convention comment in api/mlos_sort.py with the worker
copy (Muldraugh, KY is appended at the end, not prepended at the
front — see adapters.build_response:577).
- update init/04_required_wsids.sql header to reflect the authed-API
fetch path (HTML scrape was retired in 3a34b71).
- soften the now-stale '~14 rows' count in app._strip_path_prefix's
docstring.
This commit is contained in:
@@ -552,13 +552,6 @@ def _apply_branch_rules(
|
|||||||
|
|
||||||
# Backwards-compat shim used by existing call sites that don't yet pass
|
# Backwards-compat shim used by existing call sites that don't yet pass
|
||||||
# pz_build/input_modids. Removed once all callers migrate.
|
# pz_build/input_modids. Removed once all callers migrate.
|
||||||
def _autopick_ambiguous(mods: List[ModInfo]) -> Tuple[Set[str], List[Dict[str, Any]]]:
|
|
||||||
drop_ids, warns, _hints = _apply_branch_rules(
|
|
||||||
mods, pz_build="B42", input_modids={m.id for m in mods},
|
|
||||||
)
|
|
||||||
return (drop_ids, warns)
|
|
||||||
|
|
||||||
|
|
||||||
def build_response(
|
def build_response(
|
||||||
input_ids: List[str],
|
input_ids: List[str],
|
||||||
hit_ids: List[str],
|
hit_ids: List[str],
|
||||||
|
|||||||
@@ -131,10 +131,10 @@ class ResortRequest(BaseModel):
|
|||||||
def _strip_path_prefix(deps) -> List[str]:
|
def _strip_path_prefix(deps) -> List[str]:
|
||||||
"""Defensively normalize dep names. Strips leading backslashes (B42 path
|
"""Defensively normalize dep names. Strips leading backslashes (B42 path
|
||||||
syntax: `\\StarlitLibrary` -> `StarlitLibrary`) and trims whitespace.
|
syntax: `\\StarlitLibrary` -> `StarlitLibrary`) and trims whitespace.
|
||||||
Worker._split_csv applies this at parse time, but ~14 mod_parsed rows
|
Worker._split_csv applies this at parse time, but a handful of legacy
|
||||||
in the live DB were written before that fix landed and will only refresh
|
mod_parsed rows were written before that fix landed and will only
|
||||||
when their wsid's time_updated advances on Steam. Normalizing here keeps
|
refresh when their wsid's time_updated advances on Steam. Normalizing
|
||||||
missing-dep matching correct against legacy rows."""
|
here keeps missing-dep matching correct against legacy rows."""
|
||||||
out: List[str] = []
|
out: List[str] = []
|
||||||
for d in (deps or []):
|
for d in (deps or []):
|
||||||
s = (d or "").strip().lstrip("\\")
|
s = (d or "").strip().lstrip("\\")
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
"""Public helper for mapping pzmm content-type tags to sortof CATEGORY_ORDER.
|
|
||||||
|
|
||||||
The same mapping is also inlined in `mlos_sort.py` (both api/ and worker/
|
|
||||||
copies, deliberately — worker uses a separate venv with no FastAPI deps,
|
|
||||||
so it cannot import from api/). This module exposes the helper for
|
|
||||||
non-mlos consumers (e.g. /api/conflicts diagnostics output) without
|
|
||||||
forcing them to drag in the whole sorter module.
|
|
||||||
|
|
||||||
Source: pzmm core/mods.py:detect_mod_types ordering, mapped to sortof's
|
|
||||||
CATEGORY_ORDER buckets per docs/plans/2026-05-04-pzmm-conflict-and-typing.md
|
|
||||||
§3.4.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import Dict, List, Optional
|
|
||||||
|
|
||||||
# Items / Animations / Lua / Unknown intentionally absent — too generic to
|
|
||||||
# drive a category decision; callers should fall through to other heuristics.
|
|
||||||
_TYPE_TO_CAT: Dict[str, str] = {
|
|
||||||
"Maps": "map",
|
|
||||||
"Vehicles": "vehicle",
|
|
||||||
"Weapons": "weapon",
|
|
||||||
"Clothing": "wearable",
|
|
||||||
"Traits": "code",
|
|
||||||
"Professions": "profession",
|
|
||||||
"Recipes": "crafting",
|
|
||||||
"Tiles": "tile",
|
|
||||||
"Textures": "texture",
|
|
||||||
"Sounds": "sound",
|
|
||||||
"UI": "ui",
|
|
||||||
"Translations": "translation",
|
|
||||||
"Patch": "patch",
|
|
||||||
"Dependency": "tweaks",
|
|
||||||
"Framework": "tweaks",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def types_to_category(mod_types: List[str], name: str = "") -> Optional[str]:
|
|
||||||
"""First mod_type that maps to a sortof CATEGORY_ORDER bucket wins.
|
|
||||||
|
|
||||||
Returns the bucket name (e.g. "weapon", "vehicle"), or None when:
|
|
||||||
- mod_types is empty (manifest not yet built), or
|
|
||||||
- mod_types contains only skip-types (Items / Animations / Lua / Unknown).
|
|
||||||
|
|
||||||
The `name` arg is used for the vehicle_spawn refinement only — when a
|
|
||||||
Vehicles-tagged mod is named like "spawn zone X", the more specific
|
|
||||||
`vehicle_spawn` bucket wins over the generic `vehicle`.
|
|
||||||
"""
|
|
||||||
if not mod_types:
|
|
||||||
return None
|
|
||||||
for t in mod_types:
|
|
||||||
cat = _TYPE_TO_CAT.get(t)
|
|
||||||
if cat:
|
|
||||||
if cat == "vehicle" and name and "spawn zone" in name.lower():
|
|
||||||
return "vehicle_spawn"
|
|
||||||
return cat
|
|
||||||
return None
|
|
||||||
@@ -722,11 +722,11 @@ def sort_mods(
|
|||||||
if wid and wid not in workshop_set:
|
if wid and wid not in workshop_set:
|
||||||
workshop_seen.append(wid)
|
workshop_seen.append(wid)
|
||||||
workshop_set.add(wid)
|
workshop_set.add(wid)
|
||||||
# MAP_LINE convention: dependencies first (leftmost), dependents last
|
# MAP_LINE convention: dependencies first (leftmost), dependents next.
|
||||||
# (rightmost). Vanilla Muldraugh, KY is the ultimate base and is
|
# Vanilla Muldraugh, KY is ALWAYS appended at the very end by
|
||||||
# prepended at the very front by adapters.build_response. `order` is
|
# adapters.build_response. `order` is already topo-sorted by mod-level
|
||||||
# already topo-sorted by mod-level deps so dependencies appear before
|
# deps (require= / loadAfter= / loadBefore=), so dependencies appear
|
||||||
# their dependents — walk it forward.
|
# before their dependents — walk it forward.
|
||||||
map_folders: List[str] = []
|
map_folders: List[str] = []
|
||||||
for mod_id in order:
|
for mod_id in order:
|
||||||
for mf in by_id[mod_id].maps:
|
for mf in by_id[mod_id].maps:
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
# Backlog: polling-path `pz_build` plumbing
|
|
||||||
|
|
||||||
**Status:** parked. File a Gitea issue with this content when one comes up.
|
|
||||||
**Trigger to schedule:** a B41 user submits a collection URL or bare-uncached input AND complains about getting B42-flavored auto-picks (or audits the result and notices Rule A misfired).
|
|
||||||
|
|
||||||
## What's missing
|
|
||||||
|
|
||||||
`/api/sort`'s sync path passes `req.pz_build` into `adapters.build_response` correctly. The async path (`_route_to_job` → `expansion.run_expansion` → `_build_result_for_job`) does **not** persist `pz_build` and defaults to `"B42"` when the GET endpoint builds the final result.
|
|
||||||
|
|
||||||
A B41 user submitting a collection URL gets:
|
|
||||||
- Sync part of `/api/sort` (validation, classify) sees `pz_build=B41`.
|
|
||||||
- Job created, expansion runs.
|
|
||||||
- GET `/api/jobs/{id}` builds `result_json` via `_build_result_for_job(conn, wsids, rules_raw)` → `adapters.build_response(...)` → defaults `pz_build="B42"` → Rule A picks B42-flavored branches.
|
|
||||||
|
|
||||||
For the canonical fhqMotoriusZone/SZ-class fixtures this doesn't matter (those are coordinated, exempt from Rule A). The bug bites on truly-ambiguous multi-branch wsids like `zReApoModernArmor` (2 branches: unflavored + B42-flavored) when B41 user routes through cold drain.
|
|
||||||
|
|
||||||
## Migration sketch
|
|
||||||
|
|
||||||
Add a column to `sort_jobs`:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- /opt/sortof/init/02_sort_jobs.sql (re-run on idempotent CREATE; live DB needs ALTER)
|
|
||||||
ALTER TABLE sort_jobs ADD COLUMN IF NOT EXISTS pz_build TEXT;
|
|
||||||
```
|
|
||||||
|
|
||||||
Apply via:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo docker exec -i sortof_db psql -U sortof -d sortof -c \
|
|
||||||
"ALTER TABLE sort_jobs ADD COLUMN IF NOT EXISTS pz_build TEXT;"
|
|
||||||
```
|
|
||||||
|
|
||||||
Edit `init/02_sort_jobs.sql` to include the column in the `CREATE TABLE IF NOT EXISTS` block so fresh deploys get it.
|
|
||||||
|
|
||||||
## Plumbing checklist
|
|
||||||
|
|
||||||
1. **`/opt/sortof/api/jobs.py`** — `create_job(...)` gains `pz_build: Optional[str] = None`; INSERT writes the column. `get_job_row` returns it (no code change needed if `SELECT *`).
|
|
||||||
2. **`/opt/sortof/api/app.py`** — `_route_to_job(...)` gains `pz_build: Optional[str] = None`; passes to `jobs.create_job`. Both call sites in `sort_endpoint` (collection short-circuit and bare-uncached fork) pass `req.pz_build`.
|
|
||||||
3. **`/opt/sortof/api/app.py`** — `_build_result_for_job(conn, wsids, rules_raw)` signature gains `pz_build: Optional[str] = None`. The GET handler reads `row["pz_build"]` and passes it through. `adapters.build_response(... pz_build=...)` already accepts it.
|
|
||||||
4. **No frontend change** — `pzBuild` is already in `/api/sort` POST body.
|
|
||||||
|
|
||||||
## Acceptance criteria
|
|
||||||
|
|
||||||
- [ ] B41 user submits collection URL containing `zReApoModernArmor` (3483407987) — final `result_json.MODS_LINE` includes `zReApoModernArmor` (un-flavored), not `zReApoModernArmorB42`.
|
|
||||||
- [ ] WARNINGS includes `build-mismatch` if appropriate.
|
|
||||||
- [ ] B42 user behavior unchanged (default).
|
|
||||||
- [ ] Existing `sort_jobs` rows with NULL `pz_build` continue to work (NULL → fall back to "B42" in the build_response default).
|
|
||||||
|
|
||||||
## Why parked
|
|
||||||
|
|
||||||
- No telemetry showing cold-collection B41 traffic exists.
|
|
||||||
- DB migrations against synthetic demand bitrot between writing and shipping (function signatures drift, the DDL goes stale).
|
|
||||||
- Sync-path B41 users (the dominant case in this user base) work correctly today — Rule A fires off `req.pz_build` directly.
|
|
||||||
- Schedule when a real user hits it. The migration is small and self-contained.
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
-- Required Items scraped from each mod's Steam Workshop page (the "Required
|
-- Required Items pulled from each mod's Steam "Required Items" sidebar.
|
||||||
-- Items" section). Steam's anonymous GetPublishedFileDetails endpoint does
|
-- Originally scraped from the public Workshop HTML page (the anonymous
|
||||||
-- not include children for individual mods, so we scrape the public HTML.
|
-- GetPublishedFileDetails endpoint omits `children` for individual mods);
|
||||||
|
-- worker.fetch_required_wsids now uses authenticated IPublishedFileService/
|
||||||
|
-- GetDetails with includechildren=true and gets the same data structurally.
|
||||||
--
|
--
|
||||||
-- Use cases:
|
-- Use cases:
|
||||||
-- 1. Auto-resolving missing-dep warnings: when a cached mod_id Y is
|
-- 1. Auto-resolving missing-dep warnings: when a cached mod_id Y is
|
||||||
|
|||||||
Reference in New Issue
Block a user