Health Metrics — Why 100/100 Is the Only Number That Counts
"A Safe Harbor must be able to say exactly how solid its pier is."
For your users, a broken link is a lost sale. For your team, a leaked credential is a crisis at midnight. For your brand, a score of 97 means three things you haven’t fixed yet.
Zenzic’s Quality Score is not a vanity metric. It is a deterministic 0–100 value computed from the concrete issue count across every check. Zero issues means 100/100 — a formal proof, not an estimate. No partial credit, no rounding favors, no surprises.
Find out where you stand right now:
uvx zenzic score [PATH]— no install, no config required.
What the Score Measures
The Quality Score is a weighted composite of four check categories. Each category
maps directly to a zenzic check sub-command and to the Zxxx finding codes it emits.
| Category | Command | Finding Codes | Weight |
|---|---|---|---|
| Structural Integrity | zenzic check links [PATH] | Z101, Z102, Z103, Z104, Z105, Z107 | 40 % |
| Content Excellence | zenzic check all [PATH] | Z501, Z502, Z503, Z505 | 30 % |
| Navigation & SEO | zenzic check orphans [PATH] | Z402 | 20 % |
| Brand & Assets | zenzic check assets [PATH] | Z903, Z904, Z905 | 10 % |
If any security finding is detected — Z201 (Shield), Z202, or Z203 (Blood Sentinel) — the Quality Score collapses to 0/100 unconditionally. A documentation source that is actively leaking a credential cannot receive a Quality Score.
The Quartz Penalty Table
Each finding code carries a fixed point deduction within its category. Deductions accumulate; once a category's contribution reaches zero, additional violations in that category have no further effect on the total score — this is the Category Cap.
| Code | Description | Penalty (pts) | Category |
|---|---|---|---|
| Z2xx | Security Breach | Override → 0/100 | — |
| Z503 | Snippet Syntax Error | 10.0 | Content |
| Z101 | Broken Link | 8.0 | Structural |
| Z104 | File Not Found | 8.0 | Structural |
| Z102 | Missing Anchor | 5.0 | Structural |
| Z402 | Orphan Page | 4.0 | Navigation |
| Z905 | Brand Obsolescence | 3.0 | Brand |
| Z903 | Unused Asset | 3.0 | Brand |
| Z501 | Placeholder (TODO / FIXME) | 2.0 | Content |
| Z904 | Nav Contract Error | 2.0 | Brand |
| Z105 | Absolute Path | 2.0 | Structural |
| Z502 | Short Content | 1.0 | Content |
| Z505 | Untagged Code Block | 1.0 | Content |
| Z107 | Circular Anchor | 1.0 | Structural |
| Z106 | Circular Link | 1.0 | Structural |
Category Cap Invariant
Category deductions are bounded by the category's weight:
- Structural cap: 40 pts (40% × 100)
- Content cap: 30 pts (30% × 100)
- Navigation cap: 20 pts (20% × 100)
- Brand cap: 10 pts (10% × 100)
Example: 100 × Z505 (1.0 pt each) generates 100 pts of potential deduction against the Content category — but the cap limits the actual loss to 30 pts. The other three categories remain unaffected: 70/100 total.
Score vs. Gate Separation
The Score and the fail_under threshold are independent:
- Score (the Metric): Objective quality measurement bounded by Category Caps.
fail_under(the Gate): Your enforcement policy inzenzic.toml.
A score of 70/100 with fail_under = 80 still exits 1. The Category Cap prevents
a noisy violation type from masking structural health — it does not weaken your gate.
The final 0–100 score is the sum of weighted category contributions:
Running the Score
# Compute and display the score (no file written)
zenzic score [PATH]
# Compute, display, and persist to .zenzic-score.json
zenzic score [PATH] --save
# Compute and fail if score falls below N
zenzic score [PATH] --fail-under 80
# Compare current score against the saved baseline (CI regression gate)
zenzic diff [PATH]
The snapshot is written to .zenzic-score.json at the repository root. It is a
machine-readable JSON file — commit it to your repository so zenzic diff has a
baseline to compare against.
Recommended CI pattern
# On main branch pushes: save the new baseline
- run: zenzic score --save --fail-under 80
# On pull requests: fail if score has dropped
- run: zenzic diff --threshold 0
zenzic diff exits 1 if the current score is lower than the saved baseline
(adjusted by --threshold). It does not fail if the score is stable or improving.
Quality Regression — Z504
When zenzic diff detects a score drop, it emits Z504 QUALITY_REGRESSION
as a finding. This is the only finding code that bridges the scoring layer and the
finding layer — it means: "something you changed made the score worse."
Z504 is not weighted into the score itself (that would be circular). It is the signal that communicates which commit introduced a regression.
Connection to the Three Pillars
The Quality Score is the operational proof of Zenzic's Three Pillars:
1. Lint the Source, Not the Build. The score is computed from raw Markdown source analysis — never from HTML output or a running web server. The 40% structural weight rewards a source that is internally coherent before any build step runs.
2. No Subprocesses.
compute_score() in core/scorer.py is a pure Python function — no shell calls,
no subprocess.run, no network requests. It receives a findings_counts: dict[str, int]
mapping and returns a ScoreReport. This guarantees identical results across every OS
and Python version in the CI matrix (ubuntu / windows / macos × Python 3.10–3.14).
3. Pure Functions First.
compute_score() has no side effects. save_snapshot() is the only I/O function
and it is called explicitly only when the user passes --save. The test suite
verifies score calculations with property-based tests (Hypothesis) to guarantee
mathematical invariants.
Nav Contract Integrity — Scored as Brand & Assets
The CEO's audit noted a terminological correction: what users sometimes call "Nav Isolation" is formally Nav Contract Integrity (Z904).
Z904 fires when a file declared in the engine's navigation config (e.g., a mkdocs.yml
nav: entry or a Docusaurus sidebars.ts explicit entry) does not exist on disk.
Each Z904 violation contributes to the Brand & Assets category (10%) using the
same per-code penalty as other scored findings (Z904: 2.0 pts per violation).
Safe Harbor Guarantee
When zenzic score returns 100/100, it is a formal guarantee that:
- Every internal link resolves (zero Z101/Z102/Z103/Z104/Z105)
- Every anchor reference resolves (zero Z107)
- Every page is reachable from at least one navigation entry point (zero Z402)
- Every code snippet is syntactically valid (zero Z503)
- No placeholder content exists (zero Z501)
- No untagged code blocks exist (zero Z505)
- No unused assets exist (zero Z903)
- No nav contract violations exist (zero Z904)
- No obsolete brand references exist (zero Z905)
- The Shield found no credentials in any file (zero Z201 — implicit, collapses score to 0)
This is the Sentinel Seal: the state where the documentation is structurally complete, content-clean, and security-verified.
Carry the Seal in your README: once you reach 100/100, run
zenzic score --saveand add the dynamic score badge to your project. Let contributors see the standard they’re committing to. See Official Badges for copy-paste badge URLs.