purge: remove ALL hardcoded model/URL defaults across 11 modules

TDD cycle (RED → GREEN):

2 new codebase-wide enforcement tests:
- test_no_getattr_with_hardcoded_model_defaults_outside_config
  Catches getattr(args, 'ai_xxx', 'HARDCODED_DEFAULT') anti-pattern
- test_no_bare_localhost_url_string_literals_outside_config
  Catches bare 'localhost:11434' string literals in non-SSOT files

Purged 24 getattr-default violations and 14 bare-URL violations across:
- compiler_engine.py: ai_telepathic_model/url defaults
- screen_identity.py: ai_telepathic_model/url defaults
- intent_resolver.py: ai_telepathic_model/url defaults (2 spots)
- semantic_evaluator.py: ai_telepathic_model/url defaults
- brain.py: ai_model/url defaults
- dm_engine.py: ai_condenser_model/url defaults
- resonance_engine.py: ai_condenser_model/url defaults
- qdrant_memory.py: ai_embedding_model/url defaults
- bot_flow.py: ai_condenser_model/url defaults
- interaction.py: ai_writer_model/url defaults
- llm_provider.py: fallback model/url 'last resort' defaults

Architecture: Config() (config.py) is the SSOT for ALL AI model config.
Every other module reads from Config().args WITHOUT default values.
If Config() is uninitialized, the system crashes (Fail Fast).

Tests: 11 new, 121 passing, 0 regressions
This commit is contained in:
2026-05-04 00:28:40 +02:00
parent c98e2caaa1
commit 720841103d
14 changed files with 131 additions and 46 deletions

View File

@@ -164,6 +164,97 @@ class TestSAEContainsNoHardcodedModelDefaults:
)
# ══════════════════════════════════════════════════════════
# 2b. NO HARDCODED MODEL/URL DEFAULTS IN ANY MODULE (codebase-wide)
# ══════════════════════════════════════════════════════════
class TestCodebaseContainsNoHardcodedModelDefaults:
"""
CODEBASE-WIDE enforcement: No Python module in GramAddict/core/ may contain
hardcoded model names or localhost URLs as getattr() default values.
The ONLY file allowed to define these defaults is config.py (the SSOT).
Every other module must read from Config().args WITHOUT providing a fallback literal.
If Config().args is missing, the system must crash (Fail Fast) — not silently
degrade to a potentially wrong model.
"""
# These are the exact default-value patterns that are FORBIDDEN outside config.py.
# They indicate a getattr(..., "ai_xxx", "HARDCODED_DEFAULT") anti-pattern.
FORBIDDEN_DEFAULT_PATTERNS = [
r'getattr\([^)]*,\s*["\']ai_[^"\']*["\']\s*,\s*["\']http://localhost:11434',
r'getattr\([^)]*,\s*["\']ai_[^"\']*["\']\s*,\s*["\']llava:',
r'getattr\([^)]*,\s*["\']ai_[^"\']*["\']\s*,\s*["\']qwen3\.',
r'getattr\([^)]*,\s*["\']ai_[^"\']*["\']\s*,\s*["\']llama3\.',
r'getattr\([^)]*,\s*["\']ai_[^"\']*["\']\s*,\s*["\']llama3\.2-vision',
r'getattr\([^)]*,\s*["\']ai_[^"\']*["\']\s*,\s*["\']nomic-embed-text',
]
# Files that are ALLOWED to have these defaults (SSOT only)
ALLOWED_FILES = {"config.py"}
def _get_all_core_python_files(self):
import os
core_dir = os.path.join(os.path.dirname(__file__), "..", "..", "GramAddict", "core")
core_dir = os.path.normpath(core_dir)
files = []
for root, _dirs, filenames in os.walk(core_dir):
for f in filenames:
if f.endswith(".py") and f not in self.ALLOWED_FILES:
files.append(os.path.join(root, f))
return files
def test_no_getattr_with_hardcoded_model_defaults_outside_config(self):
"""
No module except config.py may use getattr(args, 'ai_xxx', 'HARDCODED_DEFAULT').
The correct pattern is: getattr(cfg.args, 'ai_xxx') — no default, crash if missing.
"""
import os
violations = []
for filepath in self._get_all_core_python_files():
with open(filepath) as f:
content = f.read()
for pattern in self.FORBIDDEN_DEFAULT_PATTERNS:
matches = re.findall(pattern, content)
if matches:
basename = os.path.basename(filepath)
violations.append(f"{basename}: {len(matches)}x pattern '{pattern[:60]}...'")
assert len(violations) == 0, (
f"Found {len(violations)} file(s) with hardcoded model/URL defaults outside config.py!\n"
f"Config() is the SSOT. Remove default values from getattr() calls.\n"
+ "\n".join(f"{v}" for v in violations)
)
def test_no_bare_localhost_url_string_literals_outside_config(self):
"""
No module except config.py and llm_provider.py (routing logic) may contain
'http://localhost:11434' as a bare string literal used as a fallback value.
"""
import os
allowed = {"config.py", "llm_provider.py"}
violations = []
core_dir = os.path.join(os.path.dirname(__file__), "..", "..", "GramAddict", "core")
core_dir = os.path.normpath(core_dir)
for root, _dirs, filenames in os.walk(core_dir):
for f in filenames:
if f.endswith(".py") and f not in allowed:
path = os.path.join(root, f)
with open(path) as fh:
for i, line in enumerate(fh, 1):
if "localhost:11434" in line and not line.strip().startswith("#"):
violations.append(f"{f}:{i}: {line.strip()[:100]}")
assert len(violations) == 0, (
f"Found {len(violations)} hardcoded localhost:11434 references outside config.py/llm_provider.py!\n"
+ "\n".join(f"{v}" for v in violations)
)
# ══════════════════════════════════════════════════════════
# 3. GOAP SMART UI STABILIZATION (Poll instead of static sleep)
# ══════════════════════════════════════════════════════════