let d = import "../defaults.ncl" in d.make_mode String { id = "validate-purpose-alignment", trigger = "Validate that purpose.ncl criteria are met before production publication: bilingual completeness, SEO criteria (hreflang, JSON-LD, meta descriptions, Core Web Vitals), audience relevance, and rendering/hydration stability. A single Hard failure blocks publication.", preconditions = [ ".ontoref/ontology/purpose.ncl exists", ".ontoref/ontology/state.ncl exists", ".ontoref/ontology/gate.ncl exists", "nickel binary available on PATH", "code/site/config/ exists", ], steps = [ { id = "export-purpose", action = "Export .ontoref/ontology/purpose.ncl via nickel. Validates the PurposeFile schema and all purpose-constraints checks. Fail immediately on any structural violation.", cmd = "nickel export .ontoref/ontology/purpose.ncl", actor = 'Both, on_error = { strategy = 'Stop }, }, { id = "check-rendering-state", action = "Export state.ncl and read the rendering-mode dimension. The Hard criterion 'no-publish-during-hydration-instability' requires that no hydration-opted route regresses below the htmx-ssr baseline. Run validate-hydration; any empty-HashMap hit in a *Client component is a Hard FAIL that blocks publication.", cmd = "nickel export .ontoref/ontology/state.ncl", actor = 'Both, depends_on = [{ step = "export-purpose" }], on_error = { strategy = 'Stop }, }, { id = "check-purpose-gate-membrane", action = "Export gate.ncl and verify the 'purpose-gate' membrane exists, is active=true, and protocol='Challenge. A weakened or inactive purpose-gate is itself a Hard violation.", cmd = "nickel export .ontoref/ontology/gate.ncl", actor = 'Both, depends_on = [{ step = "export-purpose" }], on_error = { strategy = 'Stop }, }, { id = "check-bilingual-completeness", action = "For each menu-visible content section (blog, projects): diff EN vs ES content file lists. Flag any section where ES trails EN. This is the Hard criterion 'bilingual-completeness'.", cmd = "diff <(find code/site/content/en -name '*.md' 2>/dev/null | sed 's#/en/#/#' | sort) <(find code/site/content/es -name '*.md' 2>/dev/null | sed 's#/es/#/#' | sort) | head -40 || echo 'content dirs not found at code/site/content/'", actor = 'Both, depends_on = [{ step = "export-purpose" }], on_error = { strategy = 'Continue }, }, { id = "check-hreflang", action = "Audit generated HTML for the bilingual-canonical-urls criterion: verify and hreflang=\"en\" are present in the of blog and project pages, and that sitemap.xml includes both variants. Hard SEO criterion.", actor = 'Both, depends_on = [{ step = "export-purpose" }], note = "Requires a built or staged site. If none available, report UNVERIFIED (not PASS).", on_error = { strategy = 'Continue }, }, { id = "check-structured-data", action = "Audit generated HTML for the structured-data-articles criterion: verify