feat(toilville): Rituals hero, Contact band, and two checks copy coverage missed #123

Merged
peterswimm merged 1 commit from feat/rituals-hero-and-contact into main 2026-09-11 18:17:59 +00:00
Owner

Merge after toilville_rituals#379, which adds the attributes this emits. The attribute gate goes red until then — correctly.

Closes the last two design gaps — the Rituals hero and the Contact band — and adds two checks for bugs that copy coverage was blind to.

Rituals hero

rituals now renders as toilville/hero-product. A product page's band opens with a breadcrumb and the product lockup before its eyebrow, so _hero now takes both when the target is hero-product. Lockup parsing is factored into _lockup_product() and shared with _render_image, so there's one definition of what a lockup URL is.

Contact

  • The page no longer tells every visitor "Message received." The canvas flattens both branches of its sent/not-sent switch, so the post-submit ✓, heading and line of copy arrived as static blocks above the form. _contact_form now routes them into wish-form's success panel. The match keys on the check glyph, so a form that simply has a heading and intro above its fields is left alone.
  • _render_form_band turns a copy column beside a form column into toilville/form-band. The email address and the docs link become links, not terracotta buttons. It returns None on any shape it doesn't recognise, so the universal renderer still handles it.
  • The form is emitted with showTitle: false: the design gives it no title, and it had been rendering "Get in touch".

Two checks copy coverage couldn't make

Copy coverage splits on every tag, which is right for "did the words arrive" and blind to two things that shipped:

check what it caught, at 100% coverage
headings read as the design reads them — inline tags join without a separator, exactly as the browser concatenates them the Rituals hero read "you canprove you followed"
copy for a later state stays hidden until that state — text the canvas marks hint-placeholder-val="{{ false }}" must not render outside a hidden element Contact's "Message received." showed on every visit

Both went red on the real bugs and green on the other four pages before either fix landed. They run inside copy_coverage.py check, so the CI copy job enforces them.

A new pytest guard pins wish-form's [hidden] reset. The state check reads markup and can't see CSS, and the band's own CSS briefly kept the form on screen after sending. That one only showed up in a rendered post-submit screenshot. Verified red by dropping the rule.

TOILVILLE_RITUALS_DIR

All five copies of _sibling_rituals() now honour an explicit plugin checkout. The default lookup finds the checkout beside this repo — which may be another session's working copy. I reset one to get a current render; nothing was lost irrecoverably, but the tooling should never need that. Point it at your own worktree instead:

git -C ~/.spel/worktrees/tv-blocks checkout --detach origin/main
TOILVILLE_RITUALS_DIR=~/.spel/worktrees/tv-blocks python3 tools/wp_theme_ingestor/copy_coverage.py check

The override is load-bearing: without it, the gates resolve to the shared checkout, which is stale at 27ad30a, and report hero-product as "no such block".

Verified (against the plugin branch)

  • just check green; 294 passed, 0 skipped
  • copy coverage 100% on all five pages, and both new checks green
  • rendered the Rituals hero and Contact in its default and post-submit states, and looked at each
**Merge after toilville_rituals#379**, which adds the attributes this emits. The attribute gate goes red until then — correctly. Closes the last two design gaps — the Rituals hero and the Contact band — and adds two checks for bugs that copy coverage was blind to. ### Rituals hero `rituals` now renders as `toilville/hero-product`. A product page's band opens with a breadcrumb and the product lockup before its eyebrow, so `_hero` now takes both when the target is `hero-product`. Lockup parsing is factored into `_lockup_product()` and shared with `_render_image`, so there's one definition of what a lockup URL is. ### Contact - **The page no longer tells every visitor "Message received."** The canvas flattens both branches of its sent/not-sent switch, so the post-submit ✓, heading and line of copy arrived as static blocks above the form. `_contact_form` now routes them into `wish-form`'s success panel. The match keys on the check glyph, so a form that simply has a heading and intro above its fields is left alone. - **`_render_form_band`** turns a copy column beside a form column into `toilville/form-band`. The email address and the docs link become links, not terracotta buttons. It returns `None` on any shape it doesn't recognise, so the universal renderer still handles it. - The form is emitted with `showTitle: false`: the design gives it no title, and it had been rendering "Get in touch". ### Two checks copy coverage couldn't make Copy coverage splits on every tag, which is right for "did the words arrive" and blind to two things that shipped: | check | what it caught, at 100% coverage | |---|---| | **headings read as the design reads them** — inline tags join without a separator, exactly as the browser concatenates them | the Rituals hero read "you **canprove** you followed" | | **copy for a later state stays hidden until that state** — text the canvas marks `hint-placeholder-val="{{ false }}"` must not render outside a `hidden` element | Contact's "Message received." showed on every visit | Both went **red on the real bugs** and green on the other four pages before either fix landed. They run inside `copy_coverage.py check`, so the CI copy job enforces them. A new pytest guard pins `wish-form`'s `[hidden]` reset. The state check reads markup and can't see CSS, and the band's own CSS briefly kept the form on screen after sending. That one only showed up in a rendered post-submit screenshot. Verified red by dropping the rule. ### `TOILVILLE_RITUALS_DIR` All five copies of `_sibling_rituals()` now honour an explicit plugin checkout. The default lookup finds the checkout **beside** this repo — which may be another session's working copy. I reset one to get a current render; nothing was lost irrecoverably, but the tooling should never need that. Point it at your own worktree instead: ``` git -C ~/.spel/worktrees/tv-blocks checkout --detach origin/main TOILVILLE_RITUALS_DIR=~/.spel/worktrees/tv-blocks python3 tools/wp_theme_ingestor/copy_coverage.py check ``` The override is load-bearing: without it, the gates resolve to the shared checkout, which is stale at `27ad30a`, and report `hero-product` as "no such block". ### Verified (against the plugin branch) - `just check` green; **294 passed, 0 skipped** - copy coverage 100% on all five pages, and both new checks green - rendered the Rituals hero and Contact in its default and post-submit states, and looked at each
feat(toilville): Rituals hero, Contact band, and two checks copy coverage missed
Some checks failed
PR policy check / policy-gate (pull_request) Failing after 1s
Test Generator / lint-prose (pull_request) Successful in 1m40s
Security Scans / Trivy filesystem scan (pull_request) Successful in 1m59s
Test Generator / lint-workflows (pull_request) Successful in 2m0s
Security Scans / Gitleaks secret scan (pull_request) Successful in 2m1s
Test Generator / test (pull_request) Failing after 2m1s
UDG dist drift gate / dist/ matches dtcg + udg sources (pull_request) Successful in 24s
Copy coverage / Design copy reaching rendered HTML (pull_request) Failing after 1m42s
839c6ac57a
Rituals renders as toilville/hero-product. A product page's band opens with a
breadcrumb and the product lockup before its eyebrow, so _hero takes both when
the target is hero-product. Lockup parsing is factored into _lockup_product()
and shared with _render_image — one definition of what a lockup URL is.

Contact no longer tells every visitor "Message received.". The canvas flattens
both branches of its sent/not-sent switch, so the post-submit check, heading
and line of copy arrived as static blocks above the form. _contact_form routes
them into wish-form's success panel, keyed on the check glyph so a form that
simply has a heading and intro above its fields is left alone. The form is
emitted with showTitle false — it had been rendering "Get in touch", which the
design does not have. _render_form_band turns a copy column beside a form
column into toilville/form-band, with the email address and docs link as links
rather than terracotta buttons; it returns None on any unfamiliar shape.

Two checks in copy_coverage.py, for bugs that shipped at 100% coverage:
  * headings read as the design reads them — inline tags join with no
    separator, as the browser joins them. Caught "you canprove you followed".
  * copy for a later state stays hidden until it — text the canvas marks
    hint-placeholder-val="{{ false }}" must not render outside a hidden
    element. Caught "Message received." on every visit.
Both went red on the real bugs and green on the other four pages before the
fixes landed; they run inside `check`, so the CI copy job enforces them.

A pytest guard pins wish-form's [hidden] reset. The state check reads markup
and cannot see CSS, and the band's own CSS briefly kept the form on screen
after sending — visible only in a rendered post-submit screenshot. Verified red
by dropping the rule.

TOILVILLE_RITUALS_DIR: all five copies of _sibling_rituals() now honour an
explicit plugin checkout. The default lookup finds the checkout BESIDE this
repo, which may be another session's working copy; to get a current render I
reset one, and the tooling must never need that again. Load-bearing: without
it the gates resolve to the shared checkout, stale at 27ad30a, and report
hero-product as "no such block".

Needs toilville_rituals feat/contact-form-band merged first — the attribute
gate enforces the order.
peterswimm deleted branch feat/rituals-hero-and-contact 2026-09-11 18:17:59 +00:00
Sign in to join this conversation.
No description provided.