Skip to content

feat: v0.5.0a1 "The Sentinel" — Integration Finale & Obsolescence-Free#20

Merged
PythonWoods-Dev merged 1 commit intomainfrom
release/0.5.0a1
Apr 2, 2026
Merged

feat: v0.5.0a1 "The Sentinel" — Integration Finale & Obsolescence-Free#20
PythonWoods-Dev merged 1 commit intomainfrom
release/0.5.0a1

Conversation

@PythonWoods-Dev
Copy link
Copy Markdown
Contributor

@PythonWoods-Dev PythonWoods-Dev commented Apr 2, 2026

  • ISSUE Hybrid Configuration Support (pyproject.toml) #5: pyproject.toml support via [tool.zenzic] (Priority 2 in load chain)
  • Add zenzic plugins list CLI command (zenzic.rules entry-point discovery)
  • Add scan_docs_references(verbose=True) performance telemetry
  • Add PluginRuleInfo dataclass + list_plugin_rules() discovery function
  • Purge all legacy aliases: RuleEngine, scan_docs_references_parallel, scan_docs_references_with_links — no backward-compat shims
  • Drop CHANGELOG.it.md; unify version history in CHANGELOG.md (English)
  • Update commands.md (EN + IT): document plugins list, remove --jobs phantom flag
  • Update developers/plugins.md (EN + IT): danger admonition for global mutable state, zenzic plugins list verification example
  • Update README.md + README.it.md: v0.5.0a1 highlights, pyproject.toml config
  • Update CHANGELOG.md BREAKING CHANGES: aliases deleted (not deprecated)
  • Tests: +20 new tests (556 total, 0 failed)

Description

Closes #

Type of change

  • Bug fix
  • New feature (new adapter, check, Shield pattern, CLI flag)
  • Documentation update
  • Performance improvement
  • Refactor (no behaviour change)
  • Test coverage

The Zenzic Way — mandatory checklist

Zenzic's Core is built on three non-negotiable design pillars. Every PR that touches src/
must satisfy all that apply.

1. Source-first

  • This change operates on raw source files only — it does not call mkdocs build,
    import a documentation framework, or depend on generated HTML or build artefacts.

2. No subprocesses

  • No subprocess.run, os.system, or equivalent shell calls have been added to the
    linting path (src/zenzic/core/).
  • Any new parsers use pure Python stdlib (e.g. tomllib, json, yaml.safe_load,
    compile()).

3. Pure functions

  • Core validation logic is deterministic and side-effect-free: no file I/O, no
    network access, no global state mutations inside pure functions.
  • I/O is confined to CLI wrappers and scanner edges, not to validator or checker modules.

Quality gates

  • nox -s tests passes (all existing tests green, coverage ≥ 80%).
  • New behaviour is covered by tests — happy path and at least one failure case.
  • nox -s lint and nox -s typecheck pass (ruff check + mypy --strict).
  • nox -s preflight passes end-to-end (includes zenzic check all --strict self-dogfood).
  • REUSE/SPDX headers are present on every new file (nox -s reuse).

- ISSUE #5: pyproject.toml support via [tool.zenzic] (Priority 2 in load chain)
- Add zenzic plugins list CLI command (zenzic.rules entry-point discovery)
- Add scan_docs_references(verbose=True) performance telemetry
- Add PluginRuleInfo dataclass + list_plugin_rules() discovery function
- Purge all legacy aliases: RuleEngine, scan_docs_references_parallel,
  scan_docs_references_with_links — no backward-compat shims
- Drop CHANGELOG.it.md; unify version history in CHANGELOG.md (English)
- Update commands.md (EN + IT): document plugins list, remove --jobs phantom flag
- Update developers/plugins.md (EN + IT): danger admonition for global mutable
  state, zenzic plugins list verification example
- Update README.md + README.it.md: v0.5.0a1 highlights, pyproject.toml config
- Update CHANGELOG.md BREAKING CHANGES: aliases deleted (not deprecated)
- Tests: +20 new tests (556 total, 0 failed)
@PythonWoods-Dev PythonWoods-Dev requested a review from Copilot April 2, 2026 12:45
@PythonWoods-Dev PythonWoods-Dev merged commit 2ea2c9f into main Apr 2, 2026
21 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets the v0.5.0a1 “The Sentinel” release, consolidating scanning APIs into a single adaptive entry point, adding [tool.zenzic] support in pyproject.toml, and introducing plugin rule discovery + a zenzic plugins list CLI surface, alongside accompanying docs/tests and version bumps.

Changes:

  • Unify reference scanning into scan_docs_references(..., workers=..., validate_links=...) -> (reports, link_errors) with adaptive parallelism and optional telemetry.
  • Add pyproject.toml config fallback ([tool.zenzic]) behind zenzic.toml priority; bump version to 0.5.0a1.
  • Add plugin rule discovery (PluginRuleInfo, list_plugin_rules) and a zenzic plugins list CLI command; update docs/tests accordingly.

Reviewed changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
uv.lock Bumps locked project version and constrains httpx to <1.0.
tests/test_rules.py Updates engine tests for AdaptiveRuleEngine + pickle contract error coverage.
tests/test_references.py Updates scanner calls to unpack (reports, link_errors) and removes legacy alias usage.
tests/test_parallel.py Migrates “parallel” tests to unified scan_docs_references(..., workers=...) behavior.
tests/test_integration_finale.py Adds integration coverage for plugin listing and telemetry output.
tests/test_config.py Adds tests for [tool.zenzic] pyproject loading + priority over zenzic.toml.
tests/test_cli.py Updates CLI mocks/patches to the unified scan entry point.
src/zenzic/models/references.py Updates IntegrityReport docs to reference AdaptiveRuleEngine.
src/zenzic/models/config.py Implements config loading priority chain incl. pyproject fallback.
src/zenzic/main.py Registers new plugins Typer sub-app.
src/zenzic/core/scanner.py Unifies scan entry point, adds adaptive parallelism + telemetry, removes legacy parallel/with-links entry points.
src/zenzic/core/rules.py Introduces AdaptiveRuleEngine eager pickle validation + plugin discovery (list_plugin_rules).
src/zenzic/core/exceptions.py Adds PluginContractError to the exception hierarchy.
src/zenzic/cli.py Adds zenzic plugins list command and routes checks through unified scan API.
src/zenzic/init.py Version bump to 0.5.0a1.
README.md Updates release highlights and documents new config priority chain.
README.it.md Updates Italian highlights and changelog references.
pyproject.toml Version bump + adds zenzic.rules entry-point for core rule.
docs/usage/commands.md Documents zenzic plugins list.
docs/usage/advanced.md Updates programmatic API docs to unified scan function and adaptive engine.
docs/it/usage/commands.md Italian docs for zenzic plugins list.
docs/it/usage/advanced.md Italian docs for unified scan API and adaptive engine.
docs/it/developers/plugins.md Adds Italian plugin-rule contract documentation.
docs/it/developers/index.md Links to new Italian plugin docs.
docs/it/configuration/index.md Documents config priority chain incl. pyproject fallback (IT).
docs/it/architecture.md Documents adaptive engine architecture (IT).
docs/developers/plugins.md Adds English plugin-rule contract documentation.
docs/developers/index.md Links to new English plugin docs.
docs/configuration/index.md Documents config priority chain incl. pyproject fallback (EN).
docs/architecture.md Documents adaptive engine architecture (EN).
CHANGELOG.md Adds v0.5.0a1 entry incl. breaking changes and new features.
CHANGELOG.it.md Removes Italian changelog file per “single source” changelog policy.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# Shield-as-firewall guarantee (no URLs from compromised files).
secure_scanners_b: list[ReferenceScanner] = []
for md_file in md_files:
_report_b, secure_scanner_b = _scan_single_file(md_file, config, rule_engine)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the parallel+validate_links path, Phase B calls _scan_single_file(md_file, config, rule_engine) just to collect ref_maps. Passing rule_engine re-runs rule checks and triggers an extra full-file read per doc (since _scan_single_file reads the file again for rules), which makes this pass heavier than intended. Consider calling _scan_single_file with rule_engine=None (or adding a dedicated “collect scanners only” helper) so link registration doesn’t re-run rules.

Suggested change
_report_b, secure_scanner_b = _scan_single_file(md_file, config, rule_engine)
_report_b, secure_scanner_b = _scan_single_file(md_file, config, None)

Copilot uses AI. Check for mistakes.
Comment on lines +829 to +830
exceeds the parallelism benefit. Override with ``workers=N`` to force a
specific pool size regardless of file count.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring says “Override with workers=N to force a specific pool size regardless of file count”, but the implementation still requires len(md_files) >= ADAPTIVE_PARALLEL_THRESHOLD to enter the parallel path. Either adjust the wording, or change the use_parallel condition so callers can explicitly force parallel mode for smaller repos when desired.

Suggested change
exceeds the parallelism benefit. Override with ``workers=N`` to force a
specific pool size regardless of file count.
exceeds the parallelism benefit. Override with ``workers=N`` to select a
specific pool size when parallel mode is active.

Copilot uses AI. Check for mistakes.
Comment on lines +849 to +854
workers: Number of worker processes for parallel mode.
``1`` (default) always uses sequential execution.
``None`` lets ``ProcessPoolExecutor`` pick based on
``os.cpu_count()``. Any value other than ``1``
activates parallel mode when the file count is at or
above :data:`ADAPTIVE_PARALLEL_THRESHOLD`.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workers is documented as accepting any value other than 1 to activate parallel mode, but passing 0 or a negative number will raise a ValueError inside ProcessPoolExecutor with a fairly opaque message. It would be safer to validate workers up-front (e.g., allow None or >= 1, otherwise raise a clear ValueError).

Copilot uses AI. Check for mistakes.
Comment on lines +145 to +162
## Enabling plugins

Core rules (registered under `zenzic.rules` by Zenzic itself) are always
active. External plugin rules must be explicitly enabled in `zenzic.toml`
under the `plugins` key:

```toml
# zenzic.toml
[build_context]
engine = "mkdocs"

plugins = ["no-internal-hostname"]
```

Only plugins listed here will be loaded. Installing a package that registers
rules under `zenzic.rules` without listing it in `plugins` has no effect —
this is intentional **Safe Harbor** behaviour: you always know exactly which
rules are active in your project.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section documents enabling third-party rule plugins via a plugins = [...] key in zenzic.toml, but the current ZenzicConfig / BuildContext models don’t define a plugins field and the scanner only builds the rule engine from config.custom_rules (it doesn’t load/enable entry-point rules for scanning). Either implement the config field + loading logic, or update the docs to reflect the current behavior (discovery/inspection only).

Copilot uses AI. Check for mistakes.
Comment on lines +151 to +168
## Abilitare i plugin

Le regole core (registrate sotto `zenzic.rules` da Zenzic stesso) sono sempre
attive. Le regole plugin esterne devono essere esplicitamente abilitate in
`zenzic.toml` sotto la chiave `plugins`:

```toml
# zenzic.toml
[build_context]
engine = "mkdocs"

plugins = ["no-internal-hostname"]
```

Solo i plugin elencati qui verranno caricati. L'installazione di un pacchetto
che registra regole sotto `zenzic.rules` senza elencarlo in `plugins` non ha
effetto — questo è il comportamento intenzionale del **Safe Harbor**: sai sempre
esattamente quali regole sono attive nel tuo progetto.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qui si documenta l’abilitazione dei plugin tramite plugins = [...] in zenzic.toml, ma i modelli ZenzicConfig / BuildContext attuali non espongono alcun campo plugins e lo scanner costruisce il motore regole solo da config.custom_rules (non carica/abilita regole da entry-point per la scansione). Serve implementare il campo + la logica di caricamento, oppure allineare la documentazione al comportamento reale (solo discovery/ispezione).

Copilot uses AI. Check for mistakes.
`PluginContractError` immediately — before any file is scanned.
- **`zenzic.rules` entry-point group**: core rules (`VSMBrokenLinkRule`) are
registered as first-class plugins. Third-party packages can extend Zenzic by
registering under the same group and enabling their plugin ID in `zenzic.toml`.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The highlights mention that third-party rules can be enabled via their plugin ID in zenzic.toml, but the current config models don’t define a plugins field and the scanner’s rule-engine construction only uses custom_rules. This makes the README claim misleading unless plugin enablement/loading is implemented elsewhere.

Suggested change
registering under the same group and enabling their plugin ID in `zenzic.toml`.
registering under the same group; Zenzic automatically discovers all installed rule plugins.

Copilot uses AI. Check for mistakes.
Comment on lines +171 to 172
rule_findings: Issues raised by the AdaptiveRuleEngine (custom rules and
plugin-registered rules). Empty when no rules are configured.
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IntegrityReport.rule_findings is described as including “plugin-registered rules”, but the scanner currently builds the rule engine only from config.custom_rules and there’s no visible path that loads entry-point rules into rule_findings. Either adjust this docstring, or wire plugin rules into the scan so the report can actually contain them.

Suggested change
rule_findings: Issues raised by the AdaptiveRuleEngine (custom rules and
plugin-registered rules). Empty when no rules are configured.
rule_findings: Issues raised by the AdaptiveRuleEngine (configured/custom
rules). Empty when no rules are configured.

Copilot uses AI. Check for mistakes.
@PythonWoods-Dev PythonWoods-Dev deleted the release/0.5.0a1 branch April 2, 2026 17:27
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.

2 participants