Skip to main content

Zenzic vs. Proofreader

Zenzic does not care about your writing style.

Whether you use hyphens or asterisks for lists, whether your lines are 80 or 120 characters long, whether you prefer sentence case or title case in headings — none of these are Zenzic's domain. These are matters of personal or team preference. They do not threaten your project's stability, your users' safety, or your CI pipeline's reliability.

Excellent tools like markdownlint, vale, and prettier govern the aesthetics of prose. Zenzic governs Structural Integrity and Security. These are not competing concerns — they occupy orthogonal categories.


The Integrity Filter

Every rule that ships in the Zenzic Core must pass a three-dimensional admission test. We call this The Integrity Filter: a rule enters Zenzic if and only if it defends one of these three dimensions.

Dimension 1 — Structural Integrity

"Does this rule prevent a broken user experience?"

A documentation project is a graph of interconnected resources. When a node in that graph disappears — a file is renamed, a heading changes its anchor, a directory is restructured — every reference pointing to that node becomes a ghost. The user follows the link and lands on a 404. The CI pipeline succeeds. The damage is invisible at build time.

Structural Integrity rules catch these breaks before the build runs:

  • Orphan pages: An orphan page is a Markdown file present on disk but absent from the site navigation declared in your build engine's configuration file. Because these pages are unreachable by users navigating the site structure, Zenzic reports them to keep you in control.
  • Comprehensive link checking: Zenzic's link validation analyses all Markdown references, including text links, images, reference-style links, and same-page anchors.
Finding CodeNameWhat it catches
Z101LINK_BROKENDead internal links — file not found
Z102ANCHOR_MISSINGLinks to headings that no longer exist
Z106CIRCULAR_LINKCircular link cycles — structural telemetry, not a defect (see architectural rationale)
Z107CIRCULAR_ANCHORSelf-referential anchor links
Z108EMPTY_LINK_TEXTEmpty or whitespace-only link labels
Z401MISSING_DIRECTORY_INDEXDirectories without a reachable index.md
Z402ORPHAN_PAGEFiles unreachable from any navigation path
Z404CONFIG_ASSET_MISSINGAssets declared in config that do not exist on disk

Dimension 2 — Hardened Security

"Does this rule protect your infrastructure or secrets?"

Documentation source is untrusted input. It is written by humans, accepted from external contributors, and processed by build pipelines that may hold access to production credentials. A single leaked API key in a Markdown file — committed in a rush, pushed to a public repository — is a supply-chain incident, not an editorial oversight.

Security rules are non-suppressible by design. Exit codes 2 and 3 bypass --exit-zero and fail-on-error: false unconditionally:

Finding CodeNameWhat it catchesExit
Z201CREDENTIAL_SECRETCredentials, API keys, tokens in any source line2
Z202PATH_TRAVERSALSystem path escape in a link or config value3
Z203PATH_TRAVERSAL_SUSPICIOUSRelative traversal patterns escaping the docs root3

See Exclusion Zone and The Zenzic Trinity for the complete exit code contract.


Dimension 3 — Technical Accessibility

"Does this rule ensure that third-party tools can consume your source?"

Markdown is an input format: it is consumed by build engines, syntax highlighters, snippet validators, and CI quality gates. Some structural properties that appear cosmetic at first glance carry hard technical consequences for downstream tooling.

The canonical example is Z505: UNTAGGED_CODE_BLOCK: a fenced code block with no language specifier renders as plain text in most engines. More critically, it prevents snippet validation and breaks syntax highlighting coverage measurement. The absence of a language tag is not a style preference — it is a missing machine-readable contract between the author and every tool in the pipeline.

Finding CodeNameWhat it catches
Z505UNTAGGED_CODE_BLOCKFenced blocks with no language specifier
Z503SNIPPET_ERRORCode snippets that fail to parse
Z106CIRCULAR_LINKLink cycles — structural telemetry; documentation forms an interconnected Knowledge Graph where cycles are expected (see architectural rationale)
Z108EMPTY_LINK_TEXTLinks whose label is empty or whitespace-only

The Node.js Tax and Architectural Independence

You might ask: why does Zenzic implement Z505 (Untagged Code Blocks) when linters like markdownlint already detect this?

The answer is Pillar 2: Zero Subprocesses.

Traditional Markdown linters require a full Node.js runtime and hundreds of megabytes of node_modules. For a Python-based DevOps pipeline, a security-conscious enterprise, or any team running CI in a minimal container, this dependency creates friction: additional toolchain configuration, runtime version pinning, and transitive supply-chain exposure. We call this the Node.js Tax — the hidden overhead of requiring a second runtime stack just to validate documentation structure.

Without Zenzic With Zenzic
───────────────────── ─────────────────────────
npm install uvx zenzic check all
node_modules/ ~300 MB (zero persistent install)
Node ≥ 18 required Python 3.10+ required
npm audit surface Zero transitive risk

By providing core structural checks in pure Python, Zenzic enables professional-grade documentation quality without leaving your primary technology stack. Zenzic is not designed to replace every linter in your pipeline — but for structural integrity, security, and technical accessibility in CI, it is the only one you need.


What Zenzic Explicitly Does Not Do

The boundary of what Zenzic rejects is as important as what it enforces. This table is permanent. If a proposed rule does not pass The Integrity Filter, it does not ship.

CategoryExamplePosition
Line lengthLines exceeding 80 or 120 characters✗ Not a structural concern
List marker style* vs - vs 1.✗ Aesthetic preference
Heading casingSentence case vs. Title Case✗ Editorial choice
Spell checkingTypos and grammar errors✗ Delegate to vale
Link text phrasing"Click here" vs. descriptive anchor text✗ Guideline, not a gate
Trailing whitespaceExtra spaces at line endings✗ Auto-fixed by formatters
Prose consistencyUniform use of terminology✗ Domain-specific — use vale

These categories are not beneath Zenzic — they are outside its mandate. Zenzic enforces the structure. Everything else is editorial sovereignty.


Zenzic works best as one layer in a quality stack, not as a replacement for the entire tooling ecosystem:

LayerToolWhat it enforces
StructuralZenzicBroken links, orphans, secrets, path traversal
StylemarkdownlintList markers, heading levels, code fence format
ProsevaleGrammar, terminology, style guides
FormatprettierConsistent whitespace and indentation

Configure each as an independent CI step. Zenzic's exit code contract is the non-negotiable gate; the others can be advisories depending on your team's maturity model.


Further Reading