website: M3 goes live - the whole site switches to the controller's shell at once
gates / gates (push) Failing after 13m11s

Part D. Every public page now wears the controller's frame around the website's
own content. One commit, as asked: never half old, half new.

  20 pages switched (12 Hungarian incl. the hidden prices page, 8 English)
  website/preview/ deleted entirely - A, M1, M2 and M3 studies all gone
  robots.txt: the Disallow: /preview/ line removed with them
  site.css?v=22 / shell.css?v=22 on every page

PROVED before pushing, not after:
  * HEAD TAGS: title, meta description, keywords, author, robots, canonical, every
    hreflang, all seven Open Graph tags, all four Twitter tags and the JSON-LD
    captured on all 19 pages before the switch and compared after. The ONLY
    difference anywhere is the dash substitution inside the two FAQ pages'
    FAQPage JSON-LD - verified by applying the same substitution to the "before"
    copy and getting an exact match. Nothing else moved.
  * VISIBLE TEXT: identical to the live pages word for word, legal texts identical
    with no substitution permitted at all.
  * No page is left noindex (the two download pages' noindex,follow is their own,
    pre-existing and unchanged), no page mentions /preview/, every page has a
    footer, no page overflows at 390px.

THE HEAD-TAG DIFF EARNED ITS PLACE. The home page was about to ship carrying
`noindex, nofollow` from the preview, and had lost meta keywords, meta author, all
seven Open Graph tags, all four Twitter tags and the LocalBusiness JSON-LD -
because its head was hand-built while every other page carried its live one over.
The diff caught it; nothing on the rendered page would have. The generator now
uses the live head for EVERY page including the home one.

szolgaltatasok-nonpublic.html was converted too. It is in no menu and was not in
the brief's list, but leaving one page on the old chrome would have left the site
half-switched - which is the one thing part D was not allowed to do.

scripts/site_gates.py: SHELL is now the real page set; MOCKUPS is empty; gate 3's
old nav/footer loop keeps working for any page added later WITHOUT the shell, and
skips the ones that have it.
This commit is contained in:
2026-10-11 15:57:35 +02:00
parent 58e308352f
commit 6059505216
50 changed files with 2211 additions and 19185 deletions
+34 -50
View File
@@ -89,57 +89,35 @@ URL = {"index.html": "/", "alkalmazasok.html": "/alkalmazasok", "technologiak.ht
# here - BOM, emoji, nav/footer, globe structure, analytics, CDN, tokens, cache-busting, dash-lang,
# viewer, tail. BOTH this entry and the file are removed in the same commit as the switch, and the
# English twin is written then, as a twin.
NO_TWIN = {"szolgaltatasok-nonpublic.html", "404.html", "adatkezeles.html", "feltetelek.html",
os.path.join("preview", "index.html")}
NO_TWIN = {"szolgaltatasok-nonpublic.html", "404.html", "adatkezeles.html", "feltetelek.html"}
# MOCKUPS (2026-10-11) — throwaway design studies under /preview/, noindex and already covered by
# robots.txt's Disallow: /preview/. They deliberately do NOT wear the site's chrome: that is the whole
# question they exist to answer (should the website look like the box's dashboard?), so they carry the
# controller's sidebar shell instead of the website's <nav>/<footer>.
#
# They are listed here so the R-423 walk still SEES them, and they keep every check that is about
# correctness: BOM, emoji, banned strings and CDN hosts, no <style> block, cache-busting, <html lang>,
# nothing after </html>, dashboard-picture language, and the picture-viewer rules. What they are
# excluded from is exactly the three checks about site-chrome consistency, each of which a mockup
# must fail by construction:
# - gate 3 nav/footer identical to index.html (a mockup has a sidebar, not that nav)
# - gate 13 the NO_TWIN globe structure (no language globe in a Hungarian-only study)
# - gate 4 analytics (deliberate: a hidden mockup must not pollute the
# real stats, same reason as the prices page)
# DELETE THIS SET AND THE DIRECTORIES TOGETHER once the operator has picked a direction.
MOCKUPS = {os.path.join("preview", "m1", "index.html"),
os.path.join("preview", "m1", "alkalmazasok.html"),
os.path.join("preview", "m1", "mentesek.html"),
os.path.join("preview", "m1", "hogyan.html"),
os.path.join("preview", "m1", "teszteles.html"),
os.path.join("preview", "m1", "kapcsolat.html"),
os.path.join("preview", "m2", "index.html")}
MOCKUPS = set() # the design studies were deleted with website/preview/ at the M3 switch
# SHELL (2026-10-11, M3) — pages that wear the controller's frame instead of the website's
# <nav>/<footer>. They are staged under /preview/m3/ until the operator's go, and at the switch
# every live page becomes one of these. They keep every other check; what changes for them is
# WHICH block has to be identical across the set: the sidebar, not the nav and footer. Gate 3
# below does both, so there is one identity gate rather than two.
# SHELL (2026-10-11, M3) — every public page now wears the controller's frame instead of the
# website's <nav>/<footer>. Gate 3 therefore checks the SIDEBAR and the FOOTER across this set
# instead of the old nav+footer: the site is static with no build step, so the shell is
# duplicated into each page, and this is what keeps the duplication honest.
SHELL = {
os.path.join("preview", "m3", 'index.html'),
os.path.join("preview", "m3", 'alkalmazasok.html'),
os.path.join("preview", "m3", 'technologiak.html'),
os.path.join("preview", "m3", 'biztonsagimentes.html'),
os.path.join("preview", "m3", 'gyik.html'),
os.path.join("preview", "m3", 'teszteles.html'),
os.path.join("preview", "m3", 'kapcsolat.html'),
os.path.join("preview", "m3", 'letoltes.html'),
os.path.join("preview", "m3", 'adatkezeles.html'),
os.path.join("preview", "m3", 'feltetelek.html'),
os.path.join("preview", "m3", '404.html'),
os.path.join("preview", "m3", "en", 'index.html'),
os.path.join("preview", "m3", "en", 'apps.html'),
os.path.join("preview", "m3", "en", 'technology.html'),
os.path.join("preview", "m3", "en", 'backups.html'),
os.path.join("preview", "m3", "en", 'faq.html'),
os.path.join("preview", "m3", "en", 'testing.html'),
os.path.join("preview", "m3", "en", 'contact.html'),
os.path.join("preview", "m3", "en", 'download.html'),
'szolgaltatasok-nonpublic.html',
'index.html',
'alkalmazasok.html',
'technologiak.html',
'biztonsagimentes.html',
'gyik.html',
'teszteles.html',
'kapcsolat.html',
'letoltes.html',
'adatkezeles.html',
'feltetelek.html',
'404.html',
os.path.join("en", 'index.html'),
os.path.join("en", 'apps.html'),
os.path.join("en", 'technology.html'),
os.path.join("en", 'backups.html'),
os.path.join("en", 'faq.html'),
os.path.join("en", 'testing.html'),
os.path.join("en", 'contact.html'),
os.path.join("en", 'download.html'),
}
PAGES = list(TWINS) + list(TWINS.values()) + sorted(NO_TWIN) + sorted(MOCKUPS) + sorted(SHELL)
@@ -253,8 +231,14 @@ if total_emoji:
print(" emoji total: %d" % total_emoji)
# gate 3: nav + footer consistency, per language set
for lang, members, ref in (("hu", HU_PAGES, "index.html"), ("en", EN_PAGES, os.path.join("en", "index.html"))):
if ref not in pages:
# Pages still wearing the website's own <nav>/<footer>. After the M3 switch that is nothing,
# and the loop is a no-op; it stays because a page added later without the shell must still be
# checked against its language's reference rather than silently skipped.
_OLD_CHROME_HU = sorted(HU_PAGES - SHELL)
_OLD_CHROME_EN = sorted(EN_PAGES - SHELL)
for lang, members, ref in (("hu", _OLD_CHROME_HU, "index.html"),
("en", _OLD_CHROME_EN, os.path.join("en", "index.html"))):
if ref not in pages or not members:
continue
blocks = {}
for p in sorted(members, key=lambda x: (x != ref, x)):