Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[Architecture] Plugin boundary is leaky: clinical_compliance hard-coded into core/config/CLI/TUI, two strategy registries

Open
#723 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Active
Tech stack
python

Research direction

Start by reading app/core/plugin_registry.py, app/core/analyzer_strategies.py, and the plugin wiring called out in app/core/session.py, app/config.py, app/main.py, and app/ui/tui.py. Map the registry calls and settings flow, then define the plugin API and migrate the built in plugin and CLI/TUI contributions. Done means the acceptance criteria pass, including a sample external plugin and running without clinical_compliance.

Written by the indexing model from the issue text.

Description

architecture enhancement ready-for-human

Problem

app/core/plugin_registry.py presents a generic register_plugin(registry) extension model, but the one plugin, app/plugins/clinical_compliance, is wired into every layer by name.

Core

  • PluginRegistry.get_clustering_strategy auto-loads clinical_compliance for any name starting with "clinical" (plugin_registry.py:113-114).
  • load_plugins_from_settings loads it when the strategy is clinical or CLINICAL_SMART_RENAMING is set, and then always loads it anyway (plugin_registry.py:219-225).
  • AppSession special-cases ("clinical_tmf", "clinical_isf") and sets smart_renaming / generate_audit_report on the strategy object (session.py:249-260).

Config: CLINICAL_SMART_RENAMING and CLINICAL_GENERATE_AUDIT_REPORT are first-class core settings (config.py:196-197).

CLI: the --strategy choices are hard-coded to ["default", "generative", "clinical_tmf", "clinical_isf"] (main.py:1428), so a third-party sortify_plugin_* strategy can't be selected from the CLI.

TUI: reads #switch-clinical-renaming (tui.py:2203) and imports CROForensicModal via a module __getattr__ (tui.py:8480-8486). Meanwhile the plugin imports A11yMixin from app.ui.tui (tui_views.py:15).

Two registries for the same thing: PluginRegistry._clustering_strategies and the module-global clustering_registry in analyzer_strategies.py:3330-3363. Each one calls into the other (plugin_registry.py:97-107, analyzer_strategies.py:3350-3358).

Untyped contract

  • ClusteringStrategy is a Protocol with a 9-positional-arg generate_plan (analyzer_strategies.py:667-683).
  • Plugins get configured by mutating ad-hoc attributes (smart_renaming), and hooks are bare callables with positional args (trigger_quarantine_scan(orig_rel_path, extracted_text, base_dir), plugin_registry.py:84).

Impact

  • Adding or removing a plugin means editing core, config, CLI and TUI.
  • The clinical plugin is effectively mandatory: it's always loaded, which costs startup time.
  • External plugins (sortify_plugin_* is an allowed prefix, plugin_registry.py:11) can't get parity.

Proposed approach

  • Define a versioned plugin API in app/core/plugin_api.py with:
    • PluginManifest (name, version, strategies, settings schema fragment, CLI choices, TUI contributions)
    • a typed StrategyContext / PlanRequest dataclass instead of the 9 positional args
    • typed hook signatures.
  • Plugins contribute their own settings, namespaced under PLUGIN_SETTINGS["clinical_compliance"] or validated by a fragment the plugin supplies. Remove CLINICAL_* from core Settings.
  • Build CLI --strategy choices and TUI strategy options and switches from the registry. Remove the name-prefix auto-load and the unconditional load. Load plugins only from settings.PLUGINS (and entry points, if desired).
  • Merge clustering_registry into PluginRegistry (or the reverse), so there's one registry with built-ins registered at startup.
  • Plugins depend only on app.core.plugin_api and app.ui.a11y/widgets, never on app.ui.tui.

Acceptance criteria

  • grep -rn "clinical" app/core app/ui app/main.py app/config.py returns no plugin-specific references, excluding docs-only diagram_schema.
  • Removing app/plugins/clinical_compliance leaves the app runnable, with all non-plugin tests passing.
  • A sample external test plugin registers a strategy that appears in --strategy choices and the TUI.
Dominant language
Python
Stars
1
Forks
0
Avg merge
9h 3m
Merged PRs (30d)
361

Getting set up

  • No Dockerfile or Docker Compose file
  • Has a pull request template
  • No contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from fderuiter/sortify

All issues in fderuiter/sortify

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.