Mods tab bug fixes:
- mod_manager: fix wrong kwargs in set_enabled_mods, fix scan dir to use
mods/ subdir instead of server root, migrate old string-list format to
dict format on read
- service: replace dead server_mods SQL JOIN with get_enabled_mods()
call through the mod_manager capability; pass is_server_mod to
build_mod_args
- mods_router: accept list[EnabledModEntry] objects (name + is_server_mod)
instead of bare strings
Client/server mod split:
- Mods now stored as list[{"name": str, "is_server_mod": bool}]; old
string-list format auto-migrated on read
- is_server_mod=true routes to -serverMod= arg; false to -mod= arg
- ModList UI: amber Client/Server badge in selected pane; toggle button
in split-pane selector
Directory scaffold:
- process_config: adds "mods" to dir layout; provides get_dir_readme()
with per-directory README.txt content
- file_utils: ensure_server_dirs() gains readme_provider kwarg; writes
README.txt idempotently if absent
- service.create_server: passes readme_provider via hasattr probe
- main.py startup: backfills all existing servers with correct subdirs
and README files (idempotent)
Docs: API.md and FRONTEND.md updated for new mod schema and types
Test __init__.py files added for pytest discovery
- FieldSchema gains optional `advanced` boolean flag
- ConfigEditor reads schema at top level and passes sectionSchema as prop
- ConfigSectionForm filters out advanced fields by default; "Show advanced"
toggle reveals them without entering edit mode
- Profile (Difficulty) section shows an inline banner when
forced_difficulty is not "Custom", guiding users to the right setting
- All 173 frontend tests pass; tsc clean
- Add per-mission params to rotation (MissionRotationItem.params); falls
back to default_mission_params, then omits entirely if both empty
- Add key-value widget to ConfigEditor for default_mission_params field
- Add MissionParamsEditor component for editing param key/value/type rows
- Bump config schema to 1.1.0 with migration from 1.0.0
- Add normalize_section() to Protocol and ArmaConfigGenerator for
read-time backfill of old stored rows
- Set Arma3 BasicConfig and ProfileConfig defaults from basic.cfg /
Administrator.Arma3Profile
- Document 3 known Mods tab bugs in CLAUDE.md for next-session fix
- Fix logfiles_router and thread_registry to resolve .rpt log files
from Path(server["exe_path"]).parent/server/ instead of the languard
data dir, which never contained log files — log list and live tail
both now work correctly
- Rewrite get_ui_schema() in config_generator to cover all ~80 fields
across all 5 sections (server/basic/profile/launch/rcon) with proper
toggle/select/number/password/tag-list/hidden widgets and labels;
missions field is hidden (managed by Missions tab)
- Add formatSelectDisplay() to ConfigEditor so select fields show
descriptive text (e.g. "0 - Never") instead of raw numbers in view mode
- Add ToggleDisplay for boolean fields (Enabled/Disabled with indicator dot)
- Add section tab labels and descriptions to ConfigEditor
- Add MissionList UX hints and dynamic Add/In Rotation button labels
- Add "hidden" to FieldSchema widget union type
- Update API.md, ARCHITECTURE.md, CLAUDE.md, FRONTEND.md, MODULES.md,
THREADING.md to document log path fix and schema coverage
- Backend: add terrain field to Arma3MissionManager.list_missions()
- Backend: add missions field to ServerConfig Pydantic model
- Backend: add GET /missions/rotation and PUT /missions/rotation endpoints
- Frontend: Mission type gains terrain field; new MissionRotationEntry type
- Frontend: useServerMissionRotation and useUpdateMissionRotation hooks
- Frontend: useUploadMission updated to accept File[] with sequential upload
- Frontend: MissionList redesigned with Available Missions + Mission Rotation sections
- Frontend: per-file upload progress tracking, terrain badges, difficulty select
- Tests: 5 new tests; fixed existing useUploadMission test for File[] API; 141 pass
- Backend: add Arma3ConfigGenerator.get_ui_schema() with widget hints per field
- Backend: add ServerService.get_config_schema() and GET /config/schema endpoint
- Frontend: add FieldSchema/ConfigSchema types + useServerConfigSchema hook
- Frontend: new TagListEditor component for dynamic string-list editing
- Frontend: ConfigEditor now routes each field to correct widget (text/number/password/textarea/select/toggle/tag-list)
- Frontend: password fields have show/hide toggle; toggles render as checkbox; tag-list uses TagListEditor
- Tests: 8 new tests covering hook and TagListEditor; all 136 tests green
- Add STEP_FIELDS constant mapping each step to its required fields
- Extract trigger() from useForm and call it on Next click
- Only advance to next step when trigger() returns true, blocking
silent failures where invalid data could reach the Review step
- Add CreateServerPage.test.tsx with 8 tests covering step navigation,
validation blocking, happy path, and submit mutation
- Update CLAUDE.md: mark /servers/new Complete, remove resolved bug
- Mark implementation plan as completed
- Scaffold Vite + React 19 + TypeScript strict project
- Neumorphic dark design system (Tailwind v3, amber/orange LED accents)
- Zustand stores for auth (persist) and UI state (notifications, sidebar)
- TanStack Query v5 hooks for server CRUD operations
- WebSocket hook with reconnection backoff and query invalidation
- Components: StatusLed, Sidebar, ServerCard, LoginPage, DashboardPage
- Protected routing with auth guard
- Axios client with JWT interceptor and 401 redirect
- 68 tests across 11 test files (89% statement coverage, 90% function coverage)
- TDD workflow: RED validated, GREEN achieved, coverage verified