Skip to content

refactor(core): eliminate 3 core→infrastructure layer violations via ports-and-adapters - #135

Merged
cdeust merged 3 commits into
mainfrom
refactor/core-layer-violations
Jul 14, 2026
Merged

refactor(core): eliminate 3 core→infrastructure layer violations via ports-and-adapters#135
cdeust merged 3 commits into
mainfrom
refactor/core-layer-violations

Conversation

@cdeust

@cdeust cdeust commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Fixes #126.

Les 3 modules core/ important infrastructure/ corrigés à la racine (ports-and-adapters, pas de déplacement cosmétique) :

  • wiki_axis_registry : port reverse-DI extrait (configure_default_wiki_root(provider)) — le seul point impur était un singleton important WIKI_ROOT ; câblé une fois dans main.py.
  • wiki_classifier : idem (configure_user_rules_provider(provider)).
  • wiki_schema_loader : vrai split port-and-adapter — les dataclasses/parsers PURS restent en core (importés par 3 autres modules core — un déménagement aurait créé 3 NOUVELLES violations), l'I/O (walk disque) déménage en infrastructure/wiki_schema_reader.py. Dead code _load_folder() supprimé au passage.

Critère de fermeture prouvé : grep -rn "from mcp_server.infrastructure" mcp_server/core/ → vide (était 3 lignes). Suite complète : 5137/5137 verte. ruff clean.

Signalé (hors périmètre, tracés) : issue #134 pour les 2 fichiers >500 lignes préexistants (wiki_classifier 916, wiki_axis_registry 705) ; et une dérive doc de docs/module-inventory.md (la table dit infra↛core alors que infra→core est le pattern établi et permis par §2.2).

🤖 Generated with Claude Code

cdeust and others added 3 commits July 15, 2026 01:05
…stry

core/wiki_axis_registry.get_registry() imported infrastructure.config.WIKI_ROOT
directly — a core->infrastructure layer violation (issue #126). load_axis_registry()
already took wiki_root as a plain parameter and stayed pure; only the lazy
process-wide singleton hardcoded the infra import.

Add configure_default_wiki_root(provider) — core declares the shape of what it
needs (a zero-arg callable), the composition root supplies the real value. No
provider configured falls back to seed-only defaults (still correct, just without
user wiki/_schema/ overrides).

Test updated: test_reset_registry_picks_up_new_user_file now monkeypatches the
injected _WIKI_ROOT_PROVIDER instead of infrastructure.config.WIKI_ROOT directly.

Part of #126.

Co-Authored-By: Claude <noreply@anthropic.com>
core/wiki_classifier._load_user_rules() imported infrastructure.config.WIKI_ROOT
and called the infrastructure-backed wiki schema loader directly — a
core->infrastructure layer violation (issue #126).

Add configure_user_rules_provider(provider) — core declares that it needs a
zero-arg callable returning the parsed classifier rules; the composition root
wires it to the real infrastructure-backed loader. No provider configured falls
back to the hardcoded classification defaults, same as a load failure already did.

Tests added: provider defaults to empty when unconfigured, provider result is
used and cached (called exactly once per cache lifetime) when configured — via
monkeypatch.setattr on the module global, not the public setter, so state never
leaks into the surrounding regression tests in this file.

Part of #126.

Co-Authored-By: Claude <noreply@anthropic.com>
…O adapter

core/wiki_schema_loader.py imported infrastructure.wiki_store.{list_pages,read_page}
at module level to walk the wiki root on disk — a core->infrastructure layer
violation (issue #126), unlike the other two #126 modules this one is genuinely
I/O, not a lazy-singleton default that can be reverse-DI'd behind a provider.

Port-and-adapter split:
- core/wiki_schema_loader.py keeps the pure data model (KindDefinition,
  ClassifierRule, ViewDefinition, TriggerDefinition, WikiRegistry) and the pure
  str -> dataclass parsers (renamed parse_kind/parse_rules_table/parse_view/
  parse_trigger, dropping the leading underscore now that infrastructure calls
  them across the module boundary). Zero I/O remains in this file.
- infrastructure/wiki_schema_reader.py (new) is the adapter: walks
  wiki/_kinds|_rules|_views|_triggers/ via Path.rglob/read_text and drives the
  core parsers to build a WikiRegistry. load_registry() lives here now.
- Dropped _load_folder(): dead code (only _load_folder_direct was ever called),
  found while moving the loader — not carried into the new adapter.

Composition-root wiring: KindDefinition/ClassifierRule stay importable from core
(draft_synthesizer.py, draft_curator.py, wiki_rule_engine.py depend on the pure
types only, unaffected). The 4 handlers that call load_registry
(wiki_curate/synthesize/refine/view) now import it from
infrastructure.wiki_schema_reader. mcp_server/__main__.py wires both this
issue's reverse-DI ports (wiki_axis_registry.configure_default_wiki_root,
wiki_classifier.configure_user_rules_provider) to the real WIKI_ROOT /
load_registry values once at server boot — the single place core's declared
needs meet infrastructure's implementations.

docs/module-inventory.md: added the new infrastructure/wiki_schema_reader.py entry.

Closes the issue's grep criterion:
  grep -rn "from mcp_server.infrastructure" mcp_server/core/  → empty

Fixes #126.

Co-Authored-By: Claude <noreply@anthropic.com>
@cdeust
cdeust force-pushed the refactor/core-layer-violations branch from 90b76ec to 731e38c Compare July 14, 2026 23:07
@cdeust
cdeust merged commit 018c76d into main Jul 14, 2026
14 checks passed
@cdeust
cdeust deleted the refactor/core-layer-violations branch July 14, 2026 23:23
pull Bot pushed a commit to asleekgeek/Cortex that referenced this pull request Jul 15, 2026
Cuts 13 commits ahead of v4.14.1: core→infrastructure layer-violation
cleanup via reverse-DI ports-and-adapters (cdeust#135), check_setup MCP tool +
/preflight command (cdeust#115, cdeust#119, cdeust#133), XDG-aware embedding cache_folder
(cdeust#132), project settings catalogue + headless CI regimes (cdeust#131), devcontainer
with prewarmed models (cdeust#129), optional OTLP telemetry (cdeust#128), stale docs/
module-count fixes (cdeust#130, cdeust#121), CLAUDE.md refactor (cdeust#125), Windows
postInstall dispatch fix (cdeust#117). No retrieval-path code touched.

Pre-tag guard on the exact release tree (git_sha 018c76d, isolated
ephemeral pgvector container via benchmarks/reproduce.sh --no-ablation):
LongMemEval MRR 0.9166/R@10 0.9820 (matches v4.14.1, no regression); LoCoMo
3-run mean MRR 0.8009/R@10 0.9146 (vs v4.14.1's 3-run mean 0.7984/0.9142,
an improvement within noise); BEAM MRR 0.5437/R@10 0.7139 (within v4.14.1's
established intra-day variance band). All 4 gated floors PASS (tolerance
0.005) — unlike v4.14.1 where LoCoMo MRR failed the absolute floor on its
3-run mean, 4.14.2's mean clears it by -0.0041. Evidence:
benchmarks/results/repro/20260715-v4.14.2-pretag/.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 violations de couche core→infrastructure : wiki_axis_registry, wiki_classifier, wiki_schema_loader

1 participant