v2.6.2 — config editor UI/UX fix
UI/UX release. Fixes the /config page so the Apply button actually works and surfaces enum-style settings as dropdowns instead of free-text inputs. No data migration. No config changes. No API contract changes.
Fixed
/config"Save Changes" button is no longer dead. The Quick Settings panel calledsaveConfigForm()andreloadConfig()— neither function was defined anywhere, so the button silently no-op'd and the panel rendered "Loading schema..." forever. Replaced with a real form-based editor whose Apply button PUTs a nested payload to/api/configand reloads from server on success.- YAML scalar emitter now escapes backslashes correctly. CodeQL #35/#36:
replace(/"/g, '\\"')left literal\untouched, so a value likefoo\"barwould have prematurely terminated the scalar. Now escapes\first, then". coerce()no longer overwrites numeric settings with 0 on empty input. Clearing a number field now reverts the change rather than queuing0, which was the previous (silent, surprising) behavior.- YAML parser correctly handles list values (e.g.
synthesis.tier_filter) when the YAML uses the indentedkey:\n - itemform. Stack frames now carryparentObj/parentKeyso the first list child can convert the optimistically-created{}into[]and append correctly.
Added
- Form-based config editor with dropdowns.
/confignow renders a grouped settings form alongside the YAML editor. Known enum fields (backend,embedding.provider,llm.provider,llm.local_backend,logging.level,synthesis.default_format,governance.pii.action) render as<select>controls. Restart-required leaves get a "restart required" badge sourced from the same set the server uses, so the UI warning is never out of sync with the server's classification. GET /api/config/metaendpoint. Single source of truth for the UI's "restart required" badge — eliminates server/UI drift on_RESTART_REQUIRED_FIELDS. Both UIs fetch on load with hardcoded fallback for offline-server safety.- WAI-ARIA Tabs pattern completed on
/config:aria-selected,aria-controls,role=tabpanel,aria-labelledby, rovingtabindex, and arrow-key navigation (Left/Right/Home/End). - Pending-changes counter and Revert button. The form tracks dirty fields by dotted path, builds a single nested payload on Apply, and shows
N pending change(s) (M need restart)next to the buttons. - YAML editor accepts both YAML and JSON (was JSON-only despite the label) and skips redacted
***secrets so they aren't PUT back as literal strings.
Tests
31 passed, 2 skipped (was 24 + 2 in 2.6.1). New coverage: enum round-trip for restart-required + live fields, multi-section nested payload from a single Apply, /api/config/meta shape and auth, list-value PUT round-trip, and an HTML regression guard proving the dead saveConfigForm/reloadConfig handlers are gone.
Install: pip install --upgrade zettelforge==2.6.2
Full changelog: https://github.com/rolandpg/zettelforge/blob/master/CHANGELOG.md