sbom/gen-sbom.mjs | ROOT=. DIST=dist node …/gen-sbom.mjs | $ROOT (lockfiles live here), $SBOM_LOCKFILES (comma list, default package-lock.json), $SBOM_NAME, $SBOM_NAMESPACE_BASE, $SBOM_CREATORS. Reads flake.lock if present. Emits $DIST/sbom.spdx.json. |
sbom/check-sbom.mjs | ROOT=. DIST=dist node …/check-sbom.mjs | Same $ROOT/$DIST. Fails closed unless pinned-set ⊆ SBOM ⊆ pinned-set and (optionally) the in-toto attestation reconciles. |
shacl-runner.mjs | node …/shacl-runner.mjs <shapes.ttl> <htmlDir> | The SHACL shapes file stays in the site (its structured-data contract) + the built-HTML dir. Optional $SHACL_CONTEXT (custom offline JSON-LD context; default schema.org). Fails unless every JSON-LD block conforms: true. |
seo-gate.mjs | node …/seo-gate.mjs [distDir] | $DIST. Optional $SEO_ERROR_PAGE, $SEO_DEPLOY_SIDECARS. Enforces canonical/title/description uniqueness + self-consistency, robots.txt (RFC 9309), sitemap, internal links. |
axe-gate.mjs | node …/axe-gate.mjs [distDir] | $DIST. Optional $AXE_PAGES (comma list, default: every *.html in dist), $AXE_TAGS (default wcag2a,wcag2aa,wcag21a,wcag21aa,wcag22aa), $AXE_IMPACT_THRESHOLD (minor/moderate/serious/critical, default serious), $AXE_RUNNER (playwright (CI, needs playwright + @axe-core/playwright + npx playwright install chromium) | tezcatl (macOS WebKit, local)), $AXE_REPORT (write the JSON report). Serves dist over an ephemeral origin (so assets resolve), runs axe-core per page, and fails closed on any violation at/above the threshold. The emitted report's axe: { serious, critical } envelope is exactly what conformance-report's a11y.axe-serious-critical criterion consumes — a clean run is what lets a site honestly assert it. |
vuln-gate.mjs | node …/vuln-gate.mjs [projectDir] | $VULN_ROOT (lockfile lives here, default .). Optional $VULN_OMIT_DEV (true→production deps only, default true), $VULN_THRESHOLD (highest tolerated known critical/high, default 0), $VULN_REPORT (write the JSON report). Runs npm audit and fails closed when the known critical/high count exceeds the threshold. The report's vulns: { knownCriticalOrHighVulns } envelope is what conformance-report's security.no-critical-vulns criterion consumes. |
html-validator-gate.mjs | node …/html-validator-gate.mjs [distDir] | $HTML_DIST. Optional $HTML_PAGES (comma list, default: every *.html), $HTML_THRESHOLD (default 0), $HTML_REPORT. Runs vnu (the Nu Html Checker, a self-contained Java jar — needs a JRE) --errors-only over the built pages and fails closed above the threshold. The report's htmlValidator: { errors } envelope is what conformance-report's html.validator-clean criterion consumes. |
baseline-gate.mjs | node …/baseline-gate.mjs [cssGlob] | $BASELINE_CSS (default dist/**/*.css). Optional $BASELINE_TARGET (widely/newly, default widely), $BASELINE_REPORT. Maps the shipped CSS to web-features Baseline data (via stylelint-plugin-use-baseline — headless, no browser) and fails closed when the site-wide status is below target. A feature behind an @supports query is a tested fallback and doesn't count against it. The report's baseline: { status, fallbackTested } envelope is what conformance-report's compatibility.baseline criterion consumes. |
palette-gate.mjs | node …/palette-gate.mjs <tokens.(json|css)> <pairings.json> | Two inputs the consumer supplies: a token map (a DTCG tokens.json — primitive→semantic aliases resolved — or a tokens.css of --name: #hex custom properties) and a pairings.json declaring the fg/bg pairs that actually co-occur ({ "pairings":[{fg,bg,kind,size?,weight?,name?}], "categorical":[…], "thresholds":{…} }; kind ∈ text|large-text|ui, fg/bg are token names or literal #hex). Runs static colour-palette analysis — zero-dep, every primitive computed by hand: (1) CVD-safe contrast — simulates each colour under deuteranopia/protanopia/tritanopia (Machado-2009 matrices), recomputes the WCAG ratio per pair under each, and flags any pair dropping below AA, plus categorical collapse (CIEDE2000 ΔE below $PALETTE_COLLAPSE_DELTAE, default 10) post-transform; (2) APCA — implements APCA-W3 ~0.1.9, reports Lc per text pair against a font-size/weight-aware (or baseline $PALETTE_MIN_LC_TEXT 60 / $PALETTE_MIN_LC_LARGE 45) minimum, alongside the WCAG-2 ratio (complement, not replacement); (3) non-text contrast — kind:'ui' pairs require ≥3:1 (WCAG 2.2 SC 1.4.11). Thresholds are config-driven (pairings.json thresholds ⊕ $PALETTE_MIN_RATIO_{TEXT,LARGE,UI}) and it fails closed on any failure. $PALETTE_REPORT writes the per-pair JSON (WCAG ratio · APCA Lc · per-CVD ratios · pass/fail per check). The report's palette: { cvdSafe, apcaBaseline, nonTextContrast } envelope is what a future palette.* criterion consumes. |
jargon-gate.mjs | node …/jargon-gate.mjs [distDir] [--strict] | $JARGON_DIST. Optional $JARGON_ALLOWLIST (comma list of accepted terms), $JARGON_MIN_LENGTH (default 3), $JARGON_THRESHOLD (default 0, for --strict), $JARGON_REPORT. Flags undefined jargon in the prose: words not in a 275k-word English dictionary (compounds/possessives atomized first) that the page does not define via <abbr title>, <dfn>, or a <dl> glossary — for W3C COGA / WCAG 3.1.3 Unusual Words and for AI readers. WARN-only by default; --strict fails closed. Report carries a plainLanguage: { undefinedJargon, glossaryPresent } envelope (for a future cognitive.plain-language criterion). |
typography-gate.mjs | node …/typography-gate.mjs <type-tokens.(json|css)> [config.json] | Token Accessibility suite. Type tokens (DTCG $type:"typography" recipes or .bs-text-* CSS) + a config.json declaring which styles are body ({ "body":["body"], "thresholds":{…} }). Static checks, each mapped to a SC: body line-height ≥ 1.5 (1.4.12); text-spacing achievability — spacing/line-height in overridable relative units, never px-pinned (1.4.12); min font-size — body ≥ ~16px (warn) / ≥ ~12px hard floor (error) + modular-scale sanity (1.4.4); weight×size legibility — thin weight (≤200) at small size → error, plus a requiredApcaLc cross-link to the palette gate (1.4.3/1.4.8). Fails closed on any error; $TYPO_REPORT writes the JSON. |
target-size-gate.mjs | node …/target-size-gate.mjs <config.json> | Token Accessibility suite. A config.json where the consumer declares which tokens are interactive targets ({ "targets":[{name,width,height|size,exception?,reason?}], "tokens":{…}, "thresholds":{minPx,aaaPx} }). Enforces target ≥ 24×24px (2.5.8 AA → error below) and reports ≥ 44×44px (2.5.5 AAA) status; honours the 2.5.8 inline/essential/user-agent/spacing exceptions with an audit reason. No target tokens → coverage:"none" (vacuous pass + gap note). $TARGET_REPORT writes the JSON. |
opacity-contrast-gate.mjs | node …/opacity-contrast-gate.mjs <tokens.(json|css)> <usages.json> | Token Accessibility suite — the cross-cutting guard. Token map + a usages.json declaring "opacity applied to a foreground" usages ({ "usages":[{fg,bg,opacity,kind,name?}], "opacityTokens":{…}, "thresholds":{…} }; opacity is 0..1 or a {token} ref). Composites fg over bg (Porter-Duff source-over) at the stated alpha and requires the effective WCAG contrast ≥ floor (4.5 text / 3 large/ui — 1.4.3/1.4.11), reporting both nominal and effective ratio so the drop is visible. Translucent-over-unknown-backdrop usages are flagged for review, not passed. Catches the bounded.tools opacity regression class. $OPACITY_REPORT writes the JSON. |
likeness-gate.mjs | node …/likeness-gate.mjs <tokens.(json|css)> [config.json] | Token Accessibility suite. Two CIEDE2000 checks over the colour tokens: near-duplicate tokens (ΔE < ~2 ⇒ perceptually identical ⇒ consolidate candidate — warning, escalatable) and confusable categoricals (consumer-declared distinct sets that collapse under normal vision or deuteranopia/protanopia/tritanopia — error; supports 1.4.1). Config: { "categorical":[{name,members}], "ignore":[…], "thresholds":{dupDeltaE,collapseDeltaE,dupSeverity} }. $LIKENESS_REPORT writes the JSON. |
pairing-extractor.mjs | node …/pairing-extractor.mjs <tokens.(json|css)> <style1.css> [style2.css …] | Token Accessibility suite — coverage engine. Derives the real fg×bg pairings from actual stylesheet usage (resolves var(--token)/literal colours; pairs by same-rule co-occurrence → ancestor-selector containment → root surface, tagged rule/surface/root confidence), unions any declared $PAIRING_DECLARED pairings in, scores every pair through the palette check, and emits a pairing matrix (WCAG · APCA Lc · per-CVD ratios) to $PAIRING_MATRIX (Markdown) / $PAIRING_REPORT (JSON). No DOM ⇒ a reviewed superset (over-generates safely); report-only unless $PAIRING_GATE=1. Removes the hand-maintained pairings list that let the opacity bug slip. |
token-a11y.mjs | node …/token-a11y.mjs <token-a11y.json> | Token Accessibility suite — unified runner (ck-token-a11y). One token-a11y.json drives every member (palette · pairing · typography · targetSize · opacity · likeness) over one token map and fails closed if any fails. See TOKEN-A11Y.md for the standard. $TOKEN_A11Y_REPORT writes the aggregate JSON. |
readability-gate.mjs | node …/readability-gate.mjs <corpus.json> [--strict] | The corpus is an input the site assembles from its copy: a JSON array of {id,text} or an {id:text} map. Optional $READABILITY_THRESHOLDS, $READABILITY_MIN_WORDS, $READABILITY_KNOWN_ACRONYMS. WARN-only unless --strict. |
ai-readability-gate.mjs | node …/ai-readability-gate.mjs [distDir] | Re-proves lone's semantic.ai-readability at build time: emits {llmsTxtPresent, linksResolve, markdownSiblings} — checks llms.txt exists, its internal links resolve (and none hit $AIR_PRIVATE paths), and every content page has a Markdown sibling ($AIR_SIBLING_SUFFIX, default .md; $AIR_SIBLING_IGNORE defaults to 404). Fail-closed ($AIR_STRICT=0 to report only); $AIR_REPORT writes the evidence JSON. Static only — the Accept: text/markdown content-negotiation half is served-edge behaviour, probe it with ck-http-probe. |
commonmark-runner.mjs | node …/commonmark-runner.mjs <renderer.mjs> [fixtures.json] | The site's markdown renderer module (export renderMarkdown, or set $COMMONMARK_RENDER_EXPORT). Default fixtures pin a safe CommonMark subset + 4 hostile-HTML escapes; a site with a different renderer supplies its own fixtures.json. |
semantic/gate.ts | deno run --allow-read --allow-net …/gate.ts | Built HTML in $SEMANTIC_DIR (default dist/blog); $SEMANTIC_SELECTOR (subject node, default article). Imports jsr:@bounded-systems/lone; any error-severity finding fails CI. |
conformance-report.mjs | import { buildConformanceReport, renderConformanceReport } from "…/gates/conformance-report.mjs" | The site's evidence — loneFindings (the semantic gate's DOM findings, or null when no DOM was blessed → those criteria report not-assessed) + an external-evidence envelope whose fields it gathers from its own gates (jsonLdShacl, sbom, contentDigests, slsaProvenance, …). renderConformanceReport(report, { evidenceHref }) → a class-based HTML fragment; the consumer wraps it in its template and supplies per-criterion evidence URLs. Zero-dep; the conformance MODEL is a Node port of jsr:@bounded-systems/lone@0.4's conformance() in gates/conformance/. |