Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ dmypy.json
.cache/
zenzic_report/ # Optional HTML report exports from zenzic
.zenzic_cache/ # Reserved for a future linter cache
# Local score snapshotcommit intentionally on main to share a team baseline
# Zenzic quality scoresderived local metadata, never committed
.zenzic-score.json

# ────────────────────────────────────────────────────────────────────────────
Expand Down
44 changes: 0 additions & 44 deletions .zenzic-score.json

This file was deleted.

50 changes: 50 additions & 0 deletions CHANGELOG.it.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,56 @@ Le versioni seguono il [Versionamento Semantico][semver].

---

## [0.4.0-rc5] — 2026-04-01 — Sync Sprint: Zensical v0.0.31+ e Parallelismo API

> **Sprint 10.** `ZensicalAdapter` viene sincronizzato con lo schema ufficiale
> Zensical v0.0.31+ (`[project].nav`). Il parsing nav ora supporta tutte le varianti
> (stringa, pagina con titolo, sezione annidata). La classificazione route diventa
> nav-aware (`ORPHAN_BUT_EXISTING` quando una pagina esiste ma non e elencata nella nav
> esplicita). `map_url()` rispetta `use_directory_urls = false`. La documentazione viene
> allineata in EN/IT e nasce `examples/zensical-basic/` come riferimento canonico.

### Aggiunto

- **Nuovo esempio `examples/zensical-basic/`** — progetto minimo completo con:
`zensical.toml` in formato v0.0.31+ (`[project]`), `zenzic.toml` con
`engine = "zensical"`, nav annidata e link relativi puliti.

- **Sezioni documentali sul parallelismo (rc5)** — aggiunte in
`docs/architecture.md` e `docs/usage/advanced.md`: modello shared-nothing con
`ProcessPoolExecutor`, soglia pratica di convenienza (~200 file), vincoli tecnici
sulla picklability delle regole custom.

- **Sezioni di coesistenza adapter (EN/IT)** — aggiornati
`docs/configuration/adapters-config.md` e `docs/it/configuration/adapters-config.md`
con la logica quando coesistono `mkdocs.yml` e `zensical.toml`: prevale sempre
`build_context.engine` (nessun auto-switch silenzioso).

### Modificato

- **`ZensicalAdapter`** — inizializzazione arricchita con stato nav pre-calcolato:
`_nav_paths`, `_has_explicit_nav`, `_use_directory_urls`.

- **`get_nav_paths()`** — ora legge correttamente da `[project].nav` e supporta nav
ricorsiva (stringhe, dict titolo->pagina, dict titolo->lista annidata).

- **`classify_route()`** — ora restituisce `ORPHAN_BUT_EXISTING` quando e presente
una nav esplicita e il file non compare nella nav.

- **`tests/sandboxes/zensical/zensical.toml`** — migrato al formato `[project]`
con nav esplicita.

- **Guide migrazione EN/IT** — aggiornati gli snippet `zensical.toml` in
`docs/guide/migration.md` e `docs/it/guide/migration.md` al formato v0.0.31+.

### Corretto

- **Compatibilita schema nav Zensical** — rimossa la dipendenza dal formato legacy
`[nav].nav` con coppie `{title, file}`; ora aderiamo allo schema ufficiale
`[project].nav`.

---

## [0.4.0-rc4] — 2026-03-31 — Virtual Site Map, UNREACHABLE_LINK e Rilevamento Collisioni di Routing

> **Sprint 8.** Zenzic acquisisce l'emulazione del motore di build: la Virtual Site Map (VSM)
Expand Down
81 changes: 80 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,89 @@ Versions follow [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [0.4.0-rc4] — 2026-04-01 — Ghost Route Support, VSM Rule Engine & Content-Addressable Cache

## [0.4.0-rc5] — 2026-04-01 — The Sync Sprint: Zensical v0.0.31+ & Parallel API

> **Sprint 10.** `ZensicalAdapter` is fully synchronised with Zensical v0.0.31+.
> The legacy `[site]`/`[nav].nav` schema is replaced by the canonical `[project].nav`
> format. Navigation parsing now supports all three entry forms (plain string, titled page,
> nested section) recursively. `classify_route()` gains nav-aware orphan detection.
> `map_url()` honours `use_directory_urls = false`. The parallel scan API is stabilised
> and documented with explicit pickling requirements for custom rules.
> `examples/zensical-basic/` is introduced as the canonical Zensical reference project.
> All Zensical TOML snippets in `docs/` are updated to the v0.0.31+ schema.

### Added

- **`examples/zensical-basic/`** — new canonical example project for `engine = "zensical"`.
Contains a `zensical.toml` using `[project].nav` with all three nav entry forms, a
`zenzic.toml` with `engine = "zensical"`, and a complete `docs/` tree with clean
relative links. `zenzic check all` on this example exits 0.

- **`_extract_nav_paths()`** (`zenzic.core.adapters._zensical`) — new pure helper that
recursively extracts `.md` file paths from a Zensical nav list. Handles plain strings
(`"page.md"`), titled pages (`{"Title" = "page.md"}`), and nested sections
(`{"Section" = [...]}`). External URLs are silently skipped.

- **Nav-aware `classify_route()`** — when an explicit `[project].nav` is declared in
`zensical.toml`, files absent from the nav list are now classified
`ORPHAN_BUT_EXISTING` instead of `REACHABLE`. Zensical serves every file (filesystem
routing), but the sidebar is the user-visible navigation: files outside the nav are
effectively invisible.

- **`use_directory_urls` support** in `ZensicalAdapter.map_url()` — reads
`[project].use_directory_urls` from `zensical.toml`. When `false`, files are mapped
to flat `.html` URLs (`/page.html`) instead of directory URLs (`/page/`). Default
remains `true`, matching Zensical's own default.

- **Parallelism section in `docs/usage/advanced.md`** — documents
`scan_docs_references_parallel`, the performance crossover point (~200 files),
the absence of a `--parallel` CLI flag in rc5, and the **pickling requirements** for
custom `BaseRule` subclasses.

- **Parallelism section in `docs/architecture.md`** — describes the shared-nothing
`ProcessPoolExecutor` model, the immutability contract on workers, and the performance
threshold with honest numbers.

- **Engine coexistence section in `docs/configuration/adapters-config.md`** (EN + IT) —
documents behaviour when both `mkdocs.yml` and `zensical.toml` are present. Clarifies
that `build_context.engine` is always authoritative; no auto-detection occurs.

- **`ZensicalAdapter` nav format reference in `docs/configuration/adapters-config.md`**
(EN + IT) — full TOML examples of all three nav entry forms, route classification rules
with and without explicit nav, and `use_directory_urls` documentation.

### Changed

- **`ZensicalAdapter.__init__`** — pre-computes `_nav_paths`, `_has_explicit_nav`, and
`_use_directory_urls` at construction time from `[project]` in `zensical.toml`.
`get_nav_paths()` is now an O(1) attribute read.

- **`ZensicalAdapter` docstring** — updated from legacy `[nav].nav = [{title, file}]`
schema to the v0.0.31+ `[project].nav = [...]` format.

- **`tests/sandboxes/zensical/zensical.toml`** — migrated from flat key schema to
`[project]` scope. Added a three-entry `nav` list (`index.md`, `features.md`,
`api.md`) to exercise orphan detection in integration tests.

- **`docs/guide/migration.md`** and **`docs/it/guide/migration.md`** — Phase 3 example
`zensical.toml` updated from legacy `[site]`/`[nav].nav` to `[project].nav` format.

### Fixed

- **`ZensicalAdapter.get_nav_paths()`** previously read `[nav].nav` using `{title, file}`
key format — a schema that was never part of the official Zensical spec. Fixed to read
`[project].nav` using the actual v0.0.31+ format.

- **`ZensicalAdapter.classify_route()`** previously returned `REACHABLE` for all
non-private files regardless of nav declaration. Fixed to return `ORPHAN_BUT_EXISTING`
when an explicit nav is declared and the file is absent from it.

---

## [0.4.0-rc4] — 2026-04-01 — Ghost Route Support, VSM Rule Engine & Content-Addressable Cache

>
> **Sprint 9.** The Virtual Site Map (VSM) becomes the single source of truth for the Rule
> Engine. MkDocs Material Ghost Routes are resolved without false orphan warnings.
> The `VSMBrokenLinkRule` validates links against routing state rather than the filesystem.
Expand Down
7 changes: 7 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ Thank you for your interest in contributing to Zenzic!

Zenzic is a documentation quality tool — a linter and strict build wrapper for MkDocs sites. Contributions that improve detection accuracy, add new check types, or improve CI/CD integration are especially welcome.

## Mission

Zenzic is not just a linter. It is a long-term safety layer for documentation teams that
depend on open, auditable source files. We preserve validation continuity across engine
changes (MkDocs 1.x, Zensical, and future adapters) so projects keep control over their
data and quality process regardless of ecosystem churn.

---

## Quick start
Expand Down
16 changes: 15 additions & 1 deletion README.it.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ fallback, nessuna supposizione.

---

## Novita RC5 (v0.4.0-rc5)

- **Sync Zensical v0.0.31+**: `ZensicalAdapter` legge ora la nav da `[project].nav`
(schema TOML ufficiale), incluse sezioni annidate.
- **Routing nav-aware**: con nav esplicita, i file presenti su disco ma assenti dalla nav
vengono classificati `ORPHAN_BUT_EXISTING`.
- **Parita URL**: `map_url()` rispetta `[project].use_directory_urls = false`
(`/pagina.html`) oltre al default directory-style (`/pagina/`).
- **Parallelismo API documentato**: modello shared-nothing con `ProcessPoolExecutor`,
note oneste sull'overhead e requisiti di picklability per regole custom.
- **Nuovo esempio canonico**: `examples/zensical-basic/` allineato agli snippet documentati.

---

## 📖 Documentazione

- 🚀 **[Guida Utente][docs-it-home]**: Installazione, comandi CLI e tutti i controlli disponibili.
Expand Down Expand Up @@ -235,7 +249,7 @@ non segnalare mai i file tradotti come orfani.
## Changelog & Note di Rilascio

- 📋 [CHANGELOG.md](CHANGELOG.md) — storico completo delle modifiche (inglese)
- 📋 [changelog.it.md](changelog.it.md) — storico delle modifiche in italiano
- 📋 [CHANGELOG.it.md](CHANGELOG.it.md) — storico delle modifiche in italiano
- 🚀 [RELEASE.md](RELEASE.md) — manifesto di rilascio v0.4.0 (inglese)
- 🚀 [RELEASE.it.md](RELEASE.it.md) — manifesto di rilascio v0.4.0 (italiano)

Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ absolute links are a hard error, and if you declare `engine = "zensical"` you mu

---

## RC5 Highlights (v0.4.0-rc5)

- **Zensical v0.0.31+ sync**: `ZensicalAdapter` now reads navigation from
`[project].nav` (official TOML schema), including nested sections.
- **Nav-aware routing**: with explicit nav, files present on disk but absent from nav are
classified as `ORPHAN_BUT_EXISTING`.
- **URL mode parity**: `map_url()` now respects `[project].use_directory_urls = false`
(`/page.html`) and default directory URLs (`/page/`).
- **Parallel scan API documented**: shared-nothing `ProcessPoolExecutor` model,
honest overhead notes, and picklability requirements for custom rules.
- **New canonical example**: `examples/zensical-basic/` mirrors the documented TOML
schema and migration flow.

---

## 📖 Documentation

Zenzic provides an extensive, engineering-grade documentation portal:
Expand Down
11 changes: 11 additions & 0 deletions docs/about/philosophy.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ or any future generator — can run `zenzic check all` continuously against both
simultaneously. A project that has not yet decided on a build engine can still validate its
documentation quality today, using Vanilla mode with zero configuration.

As of early 2026, the MkDocs 2.0 direction publicly discussed by ecosystem maintainers includes
large compatibility breaks (plugin removal, theming model changes, config format shift). Zenzic's
position is intentionally conservative and user-protective:

- MkDocs 1.x projects remain first-class citizens in Zenzic.
- Existing `mkdocs.yml` structures are validated as source contracts, not as runtime promises.
- Unknown or future YAML keys are treated with tolerant parsing, not hard failures.

In practice, this means a team can defer migration decisions without losing quality gates.
Zenzic keeps the verification layer alive while the ecosystem around it evolves.

---

## The frictionless sentinel
Expand Down
40 changes: 39 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,45 @@ I/O operations, called at process start and end respectively by the CLI layer.

---

## Lifecycle overview
## Parallel scan (v0.4.0-rc5)

The Three-Phase Pipeline is pure by design: `_scan_single_file` takes a file path and
returns an `IntegrityReport` with zero shared state. This makes it trivially
parallelisable.

```mermaid
flowchart LR
classDef node fill:#0f172a,stroke:#38bdf8,stroke-width:2px,color:#e2e8f0
classDef worker fill:#0f172a,stroke:#10b981,stroke-width:2px,color:#e2e8f0
classDef io fill:#0f172a,stroke:#4f46e5,stroke-width:2px,color:#e2e8f0

MAIN["Main process\nbuilds RuleEngine\nlists .md files"]:::node
W1["Worker 1\n_scan_single_file\n(page_A.md)"]:::worker
W2["Worker 2\n_scan_single_file\n(page_B.md)"]:::worker
WN["Worker N\n_scan_single_file\n(page_Z.md)"]:::worker
SORT["Sorted merge\nby file_path"]:::node
OUT["list[IntegrityReport]"]:::io

MAIN -->|"pickle(config, engine)"| W1 & W2 & WN
W1 & W2 & WN --> SORT
SORT --> OUT
```

**Shared-nothing architecture:** `config` and `rule_engine` are serialised by `pickle`
when dispatched to each worker. Every worker operates on an independent copy — there is
no shared memory, no lock, no race condition.

**Immutability contract:** workers must not mutate `config`. All scan functions honour
this contract. Rules that write to shared state (e.g. a counter in a class variable)
violate the Pure Functions Pillar and will produce non-deterministic results in parallel
mode.

**Threshold for parallelism benefit:** process-spawn overhead is ~200–400 ms on a cold
Python interpreter. The crossover point where parallelism beats sequential scanning is
approximately 200 files on an 8-core machine. For smaller repos, use
`scan_docs_references` (sequential).

---

```mermaid
flowchart LR
Expand Down
11 changes: 10 additions & 1 deletion docs/assets/stylesheets/extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,20 @@
}
}

/* On medium desktop widths, prioritise native header controls (language, search, source). */
@media screen and (max-width: 76.234375em) {
.zz-home-nav {
display: none;
}
}

.zz-home-nav {
display: flex;
align-items: center;
gap: 0.25rem;
margin: 0 auto;
margin-left: 1rem;
margin-right: auto;
min-width: 0;
}

.zz-home-nav__link {
Expand Down
Loading
Loading