v0.5.0a1 The Sentinel: plugin-enabled scanning, adaptive engine hardening, and preflight green#22
Conversation
Body commit: enable plugin-driven scanning with safe-harbor allowlist via plugins config keep core rules always active with robust fallback when entry points are unavailable optimize parallel Phase B by skipping rule engine re-run during link collection validate workers input early with clear error messages and aligned docstrings add and update tests for plugin loading, config parsing, and worker validation fix mypy typing issue in scanner to pass nox preflight verify examples matrix: positive fixtures pass, negative security/broken fixtures fail as expected (cherry picked from commit 647f92f)
There was a problem hiding this comment.
Pull request overview
Finalizes the v0.5.0a1 “Sentinel” milestone by making rule/plugin scanning deterministic and allowlist-driven, tightening runtime validation, and reducing redundant work in the parallel + link-validation path.
Changes:
- Added
plugins = [...]allowlist support to configuration and rule engine construction/loading. - Optimized parallel “validate links” Phase B to collect links without re-running rule checks.
- Added fail-fast validation for invalid
workersvalues and updated docs/changelog messaging accordingly.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_rules.py | Adds coverage for plugin allowlist behavior and no-op engine construction when unused. |
| tests/test_parallel.py | Adds regression test for clear workers validation error. |
| tests/test_integration_finale.py | Updates plugin listing tests to cover unloadable entry points and core fallback ordering. |
| tests/test_config.py | Adds parsing tests for plugins in zenzic.toml and pyproject.toml. |
| src/zenzic/models/config.py | Introduces ZenzicConfig.plugins allowlist field. |
| src/zenzic/core/scanner.py | Builds rule engine with core/custom/selected plugins; validates workers; Phase B avoids rule re-checks. |
| src/zenzic/core/rules.py | Adds PluginRegistry for discovery/loading and core fallback behavior; refactors list_plugin_rules(). |
| README.md | Notes release-track clarification (0.4.x abandoned, 0.5.x stabilization). |
| README.it.md | Adds Italian release-track clarification note. |
| docs/it/about/index.md | Adds “Changelog” card and release-track policy blurb. |
| docs/about/index.md | Adds “Changelog” card and release-track policy blurb. |
| CHANGELOG.md | Documents new plugins config key and adds explicit “0.4.x (abandoned)” section. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| """ | ||
| from zenzic.core.exceptions import PluginContractError # deferred: avoid circular import | ||
|
|
||
| requested = [pid.strip() for pid in plugin_ids if pid.strip()] |
There was a problem hiding this comment.
load_selected_rules() preserves duplicates from plugin_ids (e.g., plugins = ["acme", "acme"]), which will load/instantiate the same entry point multiple times and can introduce unnecessary overhead or duplicated side effects. Consider de-duplicating requested while preserving order before resolving/loading entry points.
| requested = [pid.strip() for pid in plugin_ids if pid.strip()] | |
| requested: list[str] = [] | |
| seen: set[str] = set() | |
| for pid in plugin_ids: | |
| cleaned = pid.strip() | |
| if cleaned and cleaned not in seen: | |
| seen.add(cleaned) | |
| requested.append(cleaned) |
| --- | ||
|
|
||
| Storico completo delle release e policy della linea attiva. | ||
| La linea 0.4.x e stata abbandonata; la stabilizzazione attiva e 0.5.x. |
There was a problem hiding this comment.
Italian copy: "La linea 0.4.x e stata abbandonata; la stabilizzazione attiva e 0.5.x." is missing accents/grammar (e.g., "è stata", "è 0.5.x" / "è la 0.5.x"). Please correct to avoid typos in published docs.
| La linea 0.4.x e stata abbandonata; la stabilizzazione attiva e 0.5.x. | |
| La linea 0.4.x è stata abbandonata; la stabilizzazione attiva è la 0.5.x. |
Summary
This PR finalizes the Sentinel milestone for v0.5.0a1 by closing the remaining blocker and stabilizing runtime, performance, and release quality gates.
What was delivered
Plugin-enabled scanning (Safe Harbor fully implemented)
Added explicit plugin allowlist support in project configuration.
Rule loading is now deterministic:
Core rules are always active.
Custom regex rules are loaded from configuration.
External plugin rules are loaded only when explicitly listed.
Added robust core fallback behavior for environments where entry-point metadata is not available.
Parallel Phase B optimization
In the parallel + validate links path, Phase B now performs link collection without re-running rule checks.
This removes redundant compute and reduces overhead on larger documentation trees.
Robustness and UX improvements
Added clear fail-fast validation for worker values.
Updated scanner documentation text to match actual execution behavior and constraints.
Fixed final typing issue detected by mypy in preflight.
Quality and release readiness
Full preflight pipeline passes.
Test suite passes with coverage above required threshold.
Examples were verified end-to-end and classified by expected behavior.
Changelog and release-track messaging were aligned:
0.4.x documented as abandoned exploratory line.
0.5.x documented as active stabilization line.
Configuration and behavior impact
New plugin allowlist behavior enables strict user control over third-party rule activation.
Existing projects without plugin configuration continue to work with core rules enabled.
Invalid worker values now return immediate, clear validation errors.
Validation performed
nox preflight: pass
ruff check and format check: pass
mypy: pass
pytest: pass
coverage threshold: pass
Examples verification matrix
Example Result Expected Notes
examples/broken-docs Fail Fail Negative fixture with intentionally broken and unsafe links
examples/i18n-standard Pass Pass Healthy i18n fixture
examples/mkdocs-basic Pass Pass Healthy MkDocs baseline fixture
examples/security_lab Fail Fail Security fixture with traversal and absolute-path violations
examples/vanilla Pass Pass Healthy engine-agnostic fixture
examples/zensical-basic Pass Pass Healthy Zensical fixture
Examples status summary:
Expected Pass confirmed: 4 out of 4
Expected Fail confirmed: 2 out of 2