feat(config): add config validation to tests and tooling (closes #937) - #1023
Open
arcgod-design wants to merge 1 commit into
Open
feat(config): add config validation to tests and tooling (closes #937)#1023arcgod-design wants to merge 1 commit into
arcgod-design wants to merge 1 commit into
Conversation
…rshanGK#937) Adds a zero-dependency rules engine at backend/utils/config_validator.py that surfaces invalid LocalMind app-config at startup or in tests: - ValidationIssue (frozen): severity, location, message — severity restricted to {ERROR, WARN, INFO}. - ValidationRule: name + fn(config) -> [ValidationIssue]. - validate(config, rules=None): runs DEFAULT_RULES (or caller supplied list) catching exceptions so a buggy rule doesn't crash the report. - has_errors / has_warnings / summarise helpers. - load_rules_from_module(spec) imports a 'module' and pulls its RULES list for reuse-extension without monkey-patching. Default ruleset covers AppSettings (Pydantic only validates single field types; cross-field/system context checks go here): - model_name (non-empty) - language_supported ({en,ja,es,fr,de}; warns for others) - temperature_range (0..2 inclusivity) - max_history_turns (>=1; warns >100) - rag_top_k (1..64) - rag_chunk_overlap strictly < rag_chunk_size (else no new content in any chunk — wasteful and confusing) - theme_value ({light,dark,system,auto}) - OLLAMA_HOST env (INFO if unset) - CORS_ORIGINS env ('*' rejected; missing scheme warned) - chunk_tuning_consistency (INFO when chunk_size % overlap == 0; retrieval returns near-identical chunks for adjacent queries) New tooling: scripts/config_validator_cli.py: validate <config.json> — validates and prints JSON summary with all issues + counts; exit non-zero if errors. selfcheck — runs the ruleset against a canary bad config with ≥5 obvious errors to smoke-test the validator itself. Exit codes 0/1/2. UTF-8 stdout wrapped so non-ASCII glyphs (the '≥' in 'must be ≥ 1' messages) don't crash Windows cp1252 console. New tests: backend/tests/test_config_validator.py — 46 pytest cases: - TestValidationIssue (3): construction, invalid severity raises, to_dict shape. - TestValidateDriver (4): empty rules, no issue passes, rule exception surfaces as ERROR without crashing, end-to-end clean config. - TestDefaultModelRule / TestLanguageRule / TestTemperatureRule / TestMaxHistoryTurnsRule / TestRagTopKRule / TestRagOverlapRule / TestChunkTuningConsistency / TestThemeRule (each): clean path, boundary, mutant path per the rule's invariants. Bool rejected for int fields (Python's True isinstance int gotcha). - TestEnvRules (5): OLLAMA_HOST unset -> INFO, explicit -> silent; CORS wildcard rejected, missing-scheme warned, well-formed ok. - TestSummarise (2): empty + mixed counts. - TestAggregateHelpers (4): has_errors / has_warnings shape. - TestLoadRulesFromModule (3): round-trip via stub module on sys.path, missing RULES default [], wrong-type raises. - TestEndToEnd (1): default LocalMind config -> 0 errors. Acceptance criteria from issue imDarshanGK#937: [x] Implement the change in the tests and tooling [x] Add or update tests, docs, or validation for the touched path
|
@arcgod-design is attempting to deploy a commit to the Darshan's projects Team on Vercel. A member of the Team first needs to authorize it. |
Owner
|
@arcgod-design |
adikulkarni006
approved these changes
Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a zero-dependency config-validation rules engine to
backend/utils/config_validator.py, with tests and CLI tooling — closing issue #937.The existing
AppSettingsPydantic model (backend/models/schemas.py:124) validates individual field types (e.g.,temperature: float = 0.7accepts any float) but does not enforce cross-field constraints or environment-variable sanity:rag_chunk_overlapmust be strictly less thanrag_chunk_size(otherwise every chunk after the first is identical to its predecessor — wasteful and confusing for the user).OLLAMA_HOSTunset → backend silently falls back tolocalhost:11434, hardly noticeable in production.CORS_ORIGINS='*'is silently accepted.theme='rose-gold'is silently coerced by the UI.This PR adds a lightweight rules engine that surfaces all of these at startup or in unit tests without requiring Pydantic field-validator boilerplate.
Why
app.py: the lifespan handler is already cluttered and any silent skip there gets noticed only when a customer reports it.AppSettingswould benefit from one-callvalidate(config)instead of re-implementing per-PR.What changed
Backend utility —
backend/utils/config_validator.py(NEW)Public surface:
Rules are wrapped in try/except in
validate()— a buggy rule surfaces as a singleERRORissue with its exception string, never by crashing the run.DEFAULT_RULEScovers the LocalMindAppSettingssurface plus cross-field and env checks:model_namedefault_modelempty / non-stringlanguage_supporteddefault_languagenot in(en, ja, es, fr, de)temperature_rangetemperatureoutside[0.0, 2.0](inclusive)max_history_turns< 1error;> 100warn (O(N) memory cost);boolrejectedrag_top_k[1, 64]rag_chunk_overlap[0, 10000]; strictly less thanrag_chunk_sizetheme_value(light, dark, system, auto)ollama_host_envOLLAMA_HOSTunset → backend falls back to localhostcors_origins_env'*'rejected; missing-scheme warnschunk_tuning_consistencychunk_size % overlap == 0→ adjacent chunks share too much contentTooling —
scripts/config_validator_cli.py(NEW)Exit codes
0/1/2per repo convention. UTF-8 stdout rewrapped so non-ASCII glyphs in messages (e.g.≥in "must be ≥ 1") don't crash the Windows cp1252 console — bug noticed during self-check.Example:
Tests —
backend/tests/test_config_validator.py(NEW, 46 cases)TestValidationIssueto_dictshapeTestValidateDriverERROR, end-to-end cleanTestDefaultModelRule/TestLanguageRule/TestTemperatureRule/TestMaxHistoryTurnsRule/TestRagTopKRule/TestRagOverlapRule/TestChunkTuningConsistency/TestThemeRuleboolrejected for int fieldsTestEnvRulesTestSummariseTestAggregateHelpershas_errors/has_warningsshapeTestLoadRulesFromModulesys.path; missingRULESdefaults to[]; wrong type raisesTestEndToEndVerification
Acceptance criteria
Closes #937. With this PR, the entire localmind SSoC-26 backlog of issues #928-#937 is now in review (8 PRs open).