Add a theme contract gate for derived themes - #64
Merged
Conversation
A Spark-derived store theme never updates from this repo, so a fix that lands here does not reach it. The failure mode is silent: the storefront renders, apps stay installed and enabled in the dashboard, and only the events go missing. Checkout keeps working, because the platform renders the tag from its own layout, which is what hides it. theme-contract.json declares the platform integration points a derived theme must keep. scripts/check-theme-contract.py asserts them against a working copy (--root) or a live theme (--store + --theme-id, via the store admin API). The live mode is the one that matters: a store carries several theme copies, and republishing an old one silently undoes a patch applied to the active theme. The gate reads more than the tag. It masks comments, so a commented-out tag does not satisfy the contract, and it fails a child template that overrides the block without the tag, which a plain text search passes. pixels is also added to REQUIRED_BASE_BLOCKS in check-templates.py, so dropping the block from Spark itself now fails CI. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
next-devin
marked this pull request as ready for review
September 10, 2026 03:05
This repo is public. Three things in the previous commit's prose were written for an internal audience and should not have shipped here. docs/theme-contract.md named a platform source file and an internal request attribute to explain why the Theme Editor preview cannot be trusted for this check. The behaviour is what a theme author needs: the preview does not render the tracker frames, so it shows the fault whether or not the theme has it. The CHANGELOG entry and the checker's docstring carried the incident that prompted the gate, including how long a store went untracked and how it was eventually noticed. The rationale stands without it: a derived theme can stop satisfying the contract without anyone editing it, when an older working copy is republished over the active theme. No behaviour change. Gates and 78 tests still pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #63.
A Spark-derived store theme never updates from this repo, so a fix that lands here does not reach it. The failure this gate targets is silent: the storefront renders, apps stay installed and enabled in the dashboard, and only the events go missing. Checkout keeps working, because the platform renders
{% pixels %}from its own layout, which is what hides it.#63 asked whether Spark should carry something that lets a derived theme discover it is missing a required block. This is that, built around the case the issue did not anticipate: a theme that had the block, was verified, and lost it again when an older working copy was republished over it.
What is here
theme-contract.jsondeclares the integration points a derived theme must keep. One entry today:{% pixels %}inlayouts/base.html, required since 1.3.0, with the reason the gate prints on failure.scripts/check-theme-contract.pyasserts them against either a working copy or a live theme:The live mode is the one that matters. A store carries several theme copies, and republishing an old one undoes a patch applied to the active theme without touching it.
The gate reads more than the tag:
pixelsis also added toREQUIRED_BASE_BLOCKSincheck-templates.py, so dropping the block from Spark itself fails CI.Why the other two options in #63 were not taken
An upgrade note helps only at the moment someone forks. An inventory would not have caught the case that prompted this, since that theme was already in ours and already patched. Neither survives a republish.
Verification
make contractandmake verify-themepass. 78 tests pass, 11 of them new, including the child-override case and a regression test for the contract defaulting to Spark's own copy rather than the theme being checked.Run against real derived themes, the gate reproduced known-bad layouts and confirmed known-good ones, with the rendered storefront agreeing with the template read in every case. Anything it found is a store-side fix and does not belong in this repo.
Notes for review
?name=parameter is ignored and returns everything.🤖 Generated with Claude Code