139 lines
7.7 KiB
Text
139 lines
7.7 KiB
Text
let d = import "defaults/state.ncl" in
|
|
|
|
{
|
|
dimensions = [
|
|
|
|
d.make_dimension {
|
|
id = "content-coverage",
|
|
name = "Bilingual Content Coverage",
|
|
description = "Parity between EN and ES content across all public routes and FTL bundles.",
|
|
current_state = "en-ahead",
|
|
desired_state = "full-parity",
|
|
horizon = 'Weeks,
|
|
states = [
|
|
d.make_state {
|
|
id = "en-ahead",
|
|
name = "English Ahead",
|
|
description = "EN content drafted for most routes; ES lags on a subset. Tracked as publication blockers, not invariant violations.",
|
|
tension = 'Medium,
|
|
},
|
|
d.make_state {
|
|
id = "full-parity",
|
|
name = "Full Parity",
|
|
description = "Every public route and FTL key exists in both EN and ES. validate-content reports zero asymmetries.",
|
|
tension = 'Low,
|
|
},
|
|
],
|
|
transitions = [
|
|
d.make_transition {
|
|
from = "en-ahead",
|
|
to = "full-parity",
|
|
condition = "validate-content mode reports route symmetry, content-file completeness, and FTL key coverage with zero gaps for ES.",
|
|
catalyst = "Site config and content directories established; validate-content mode available from the rustelo implementation declaration.",
|
|
blocker = "ES content and FTL keys not yet complete for all routes.",
|
|
horizon = 'Weeks,
|
|
},
|
|
],
|
|
},
|
|
|
|
d.make_dimension {
|
|
id = "rendering-mode",
|
|
name = "Rendering Mode Maturity",
|
|
description = "Maturity of the HTMX server-side rendering profile and optional Leptos hydration opt-in.",
|
|
current_state = "htmx-ssr",
|
|
desired_state = "dual-mode-verified",
|
|
horizon = 'Months,
|
|
states = [
|
|
d.make_state {
|
|
id = "htmx-ssr",
|
|
name = "HTMX SSR Default",
|
|
description = "All routes render via the HTMX profile with Minijinja templates and fragment swaps. Stable.",
|
|
tension = 'Low,
|
|
},
|
|
d.make_state {
|
|
id = "dual-mode-verified",
|
|
name = "Dual-Mode Verified",
|
|
description = "Selected routes opt into Leptos hydration with verified SSR/WASM parity (validate-hydration passes) alongside the HTMX default.",
|
|
tension = 'Medium,
|
|
},
|
|
],
|
|
transitions = [
|
|
d.make_transition {
|
|
from = "htmx-ssr",
|
|
to = "dual-mode-verified",
|
|
condition = "validate-hydration mode passes for hydration-opted routes: no empty HashMap in *Client components, SsrTranslator used, FTL registry populated.",
|
|
catalyst = "Rustelo rendering-profile axis (ADR-006) supports per-route profile selection.",
|
|
blocker = "No routes opted into hydration yet; hydration parity not exercised in this implementation.",
|
|
horizon = 'Months,
|
|
},
|
|
],
|
|
},
|
|
|
|
d.make_dimension {
|
|
id = "publication-readiness",
|
|
name = "Publication Readiness",
|
|
description = "Readiness of the site for production deployment: content parity, SEO criteria, hydration stability.",
|
|
current_state = "pre-production",
|
|
desired_state = "production-ready",
|
|
horizon = 'Months,
|
|
states = [
|
|
d.make_state {
|
|
id = "pre-production",
|
|
name = "Pre-Production",
|
|
description = "Site builds and serves bilingual content; publication blockers (ES parity, SEO) remain open.",
|
|
tension = 'Medium,
|
|
},
|
|
d.make_state {
|
|
id = "production-ready",
|
|
name = "Production Ready",
|
|
description = "validate-purpose-alignment passes all Hard criteria: bilingual completeness, hreflang/JSON-LD/meta, hydration stability.",
|
|
tension = 'Low,
|
|
},
|
|
],
|
|
transitions = [
|
|
d.make_transition {
|
|
from = "pre-production",
|
|
to = "production-ready",
|
|
condition = "plan-publication and validate-purpose-alignment modes report all Hard criteria satisfied; content-coverage at full-parity.",
|
|
catalyst = "Reflection modes for content, hydration, and purpose alignment available via .rustelo.ontoref/.",
|
|
blocker = "content-coverage not at full-parity; SEO infrastructure (hreflang, JSON-LD, sitemap) not fully verified.",
|
|
horizon = 'Months,
|
|
},
|
|
],
|
|
},
|
|
|
|
d.make_dimension {
|
|
id = "consumer-neutrality",
|
|
name = "Consumer Neutrality",
|
|
description = "How much of a consumer site can be expressed without rebuilding the shared rustelo-htmx-server binary — whether the binary serves N consumers from consumer-supplied config or bakes one site in.",
|
|
current_state = "neutral-framework",
|
|
desired_state = "neutral-framework",
|
|
horizon = 'Months,
|
|
states = [
|
|
d.make_state {
|
|
id = "one-site-baked",
|
|
name = "One Site Baked",
|
|
description = "site/config (routes, menus, theme, logo, languages) is compiled into the binary, so the binary is one specific site. Brand, content, templates and env are already runtime per consumer, but identity and routes are not.",
|
|
tension = 'Medium,
|
|
},
|
|
d.make_state {
|
|
id = "neutral-framework",
|
|
name = "Neutral Framework (single image)",
|
|
description = "ONE shared binary/image serves N consumers (decision 2026-06-14: sites differ in content/brand, not route structure). The route table is a baked SHARED SUPERSET (structure, kept compiled — performance, rustelo's grain); per-site SUBSTANCE — brand, content, templates, origin, logo, name, languages — is supplied at deploy via runtime config/env, no rebuild. A verifier rejects brand/content leaking into crates/server/src.",
|
|
tension = 'Low,
|
|
},
|
|
],
|
|
transitions = [
|
|
d.make_transition {
|
|
from = "one-site-baked",
|
|
to = "neutral-framework",
|
|
condition = "REACHED (2026-06-14). validate-contract green (seam · route-superset · neutral-binary · config-drift) AND every per-site SUBSTANCE knob is runtime, leaving only the SHARED route superset baked.",
|
|
catalyst = "ADR-001 (single-image deploy). All per-site substance is runtime: origin (SITE_BASE_URL env), name (SITE_NAME env), logo (consumer site.ncl [logo], read at runtime by theme::load_logo_config → site_logo global → nav/footer/home — config-driven, no env, no template hardcode), languages (SUPPORTED_LANGUAGES), brand CSS (custom.css), templates (HTMX_TEMPLATE_PATH), FTL (deferred), menus/footer (routes.ncl/footer.ncl at startup), the level-aware About head. Four hard-gate verifiers (`just validate-contract`) enforce seam, superset completeness, neutral-binary and consumer⊆superset. Verified with two consumers on one binary: ontoref + vapora each show their OWN logo from their OWN site.ncl, no rebuild.",
|
|
blocker = "None — GRADUATED 2026-06-14. Second independent consumer proven: vapora (vapora/outreach/site) served on the SHARED binary from its own dir with its own brand (vapora-logo, SITE_NAME=vapora, vapora.dev) and its OWN menu ('About Vapora' — proves manifest_config_path resolves cwd-relative to the consumer's routes.ncl, no hidden coupling), no rebuild. sufficient-verification's second realized instance is met. Residual polish only: the baked superset still carries this repo's portfolio routes (harmless extras); a real vapora deploy supplies its own content/FTL (the test reused ontoref's as skeleton).",
|
|
horizon = 'Months,
|
|
},
|
|
],
|
|
},
|
|
|
|
],
|
|
}
|