-
Notifications
You must be signed in to change notification settings - Fork 0
Tooling
All scripts live in bin/ at the monorepo root. They accept a positional theme name, default to the cwd if it contains a theme.json, and most support --all to operate on every theme. Every script also responds to --help.
# Run the full check suite against one theme
python3 bin/check.py obel --quick
python3 bin/check.py chonk --quick
# Run it against every theme
python3 bin/check.py --all --quick
# Rebuild a theme's INDEX.md
python3 bin/build-index.py obel
# Inspect tokens
python3 bin/list-tokens.py --theme obel colors
cd obel && python3 ../bin/list-tokens.py colors # cwd-detected
# Clone Obel into a new theme variant (sibling of obel/ inside the monorepo)
python3 bin/clone.py acme| Script | What it does |
|---|---|
check.py |
Runs every project check (JSON, PHP, blocks, tokens, AI fingerprints, contrast, hex/important allow-lists, …). Use this before every commit. Pass --visual to also run the snap-gated visual regression sweep. |
build-index.py |
Regenerates a theme's INDEX.md (token map, template list, block style list). |
validate-theme-json.py |
Validates a theme's theme.json block names against the live Gutenberg + WooCommerce sources. |
list-templates.py |
Prints every template the theme could ship and the URL it serves. |
list-tokens.py |
Inspects design tokens defined in theme.json. |
clone.py |
Scaffolds a new sibling theme from Obel with the names rewritten. |
seed-playground-content.py |
Populates <theme>/playground/{content,images}/ from the canonical W&O source, rewriting image URLs to point at the new theme. |
sync-playground.py |
Inlines playground/*.php into every theme's playground/blueprint.json and rewrites the importWxr URL to the per-theme content.xml. |
personalize-microcopy.py |
Re-runnable, idempotent voice pass. Rewrites every cloned-from-Obel visible string into the target theme's brand voice using a per-theme substitution map; refuses to start if any replacement would cascade. Required after clone.py so check_all_rendered_text_distinct_across_themes passes. |
build-theme-screenshots.py |
Generates the WP-admin Themes-card screenshot.png for one theme (or --all) by cropping the latest snap baseline (or fresh tmp/snaps/ shot) to the WordPress 1200×900 spec. Required after every clone.py so check_theme_screenshots_distinct doesn't fail on the byte-identical Obel placeholder. |
build-redirects.py |
Regenerates docs/<theme>/<page>/index.html short URLs that GH Pages serves at demo.regionallyfamous.com/. |
append-wc-overrides.py |
Generates and appends WooCommerce override CSS chunks (the sentinel-bracketed Phase A through Phase K chunks) into each theme's theme.json styles.css. Re-runnable; idempotent. |
install-hooks.py |
Wires core.hooksPath to .githooks/ and smoke-tests the gate so the local pre-commit + pre-push checks fire on every commit and push. Run once on a fresh clone. |
snap.py |
Visual-snapshot framework. Boots WordPress Playground locally for a theme, captures Playwright screenshots + DOM heuristics + axe-core a11y + INSPECT measurements + scripted interactive flows across every (route × viewport) defined in bin/snap_config.py, diffs against committed baselines under tests/visual-baseline/, and emits a tiered pass / warn / fail gate. Subcommands: doctor, shoot, serve, diff, baseline, report, check. See Visual Snapshots. |
snap-vision-review.py |
Pixel-level design critique. Hands each snap PNG + the theme's design-intent.md rubric to Claude, receives vision:* findings (overpowered hero, flat hierarchy, content orphans, etc.), and merges them into *.findings.json so they triage identically to axe violations. Daily $ budget tracked in tmp/vision-spend.jsonl. |
lint.py |
Single-entry runner for ruff format --check, ruff check, mypy, plus a node --check smoke on the blocks validator. Parallelizable; CI uses the same entry. |
Scripts that together form the five-stage factory: Ideate → Design → Verify → Self-heal → Ship. See the How it works overview.
| Script | What it does |
|---|---|
concept_seed.py |
The concept catalogue — one Python list of concept recipes (palette hex, typography, voice tags) that drives the public concept queue. |
paint-mockup.py |
Turns a concept seed into the two-view browser mockup PNG at a fixed 1376×768 aspect. Emits an AI-image prompt deterministically interpolated from the concept's palette + typography + tags (never hand-written). |
concept-to-spec.py |
Distills a concept into a machine-readable tmp/specs/<slug>.json ready for design.py. Default path uses an LLM for voice/typography choices; --no-llm is a deterministic fallback. |
design.py |
The deterministic spine. Two subcommands: build --spec X.json runs the structural phases (clone Obel → swap tokens → seed Playground → sync blueprint → first check.py pass) and exits 0 when the theme renders. dress <slug> runs the content-fit phases (photos, microcopy, front-page restructure, vision review, check --phase all) and exits 0 only when green. |
design-batch.py --from-concepts |
N-at-a-time wrapper around design.py. Pulls unbuilt concepts from concept_seed.py, builds each in its own branch, auto-pushes and opens a PR with --auto merge enabled. Embeds verify-theme.py verdicts in the PR body. |
design-watch.py |
Human-friendly observer. Writes a live STATUS.md to the worktree as design.py / design-batch.py works, with per-phase timings and a ranked list of current blockers. Pass --auto-unblock to invoke the self-healing loop. |
design_unblock.py |
Self-healing loop. Classifies blockers into stable categories (microcopy-duplicate, hover-contrast, photo-collision, vision-overpowered, …), builds an evidence packet (relevant file slices + the exact rule that fired + rendered screenshot), hands it to Claude under strict guardrails (no edits outside the theme slug, no !important), applies the proposed patch, and re-runs the affected verification ladder. Every attempt is recorded to repair-attempts.jsonl for audit. |
verify-theme.py --strict |
Reproduces CI's theme gate locally against a pushed branch. Reports branch-ready / static-check / snap-shoot / evidence-check phases as JSON or markdown. |
visual-matrix.py |
Resolves "is this PR adding a brand-new theme?" from git — consumed by the vision-reviewed required for new themes gate in CI. |
triage.py |
Fast issue-triage helper. Reads the latest findings.json tree and prints a ranked list of the loudest fixes pending, bucketed by theme. |
audit-concepts.py |
Cross-checks mockups/ against bin/concept_seed.py::CONCEPTS and the GH Pages concept queue. Surfaces drift (a concept without a mockup, or vice versa). |
check-concept-similarity.py |
Flags near-duplicate concepts via perceptual hashing, with human-approved pairs allowlisted in bin/concept-similarity-allowlist.json. |
build-concept-meta.py |
Builds <slug>.meta.json sidecars for every concept from the concept seed. |
build-theme-status.py |
Rebuilds docs/themes/index.html (the shipping dashboard) from every theme's readiness.json. |
| Script | What it does |
|---|---|
build-redirects.py |
Regenerates docs/<theme>/<page>/index.html short URLs that GH Pages serves at demo.regionallyfamous.com/. Also regenerates the concept queue docs/concepts/index.html from mockups/ and preserves the human-authored .md files in PRESERVED_FILES. |
build-brand-assets.py |
Rasterizes docs/favicon.svg to PNG/ICO and renders the Open Graph share card. |
build-snap-gallery.py |
Regenerates docs/snaps/ (the retina baseline gallery) from the committed tests/visual-baseline/ tree. |
sync-wiki.py |
Mirrors docs/*.md into the GitHub wiki as Title-Case pages, rewriting ./other-doc.md links to wiki page links and ../AGENTS.md references to absolute GitHub URLs. Refreshes Home.md + _Sidebar.md. Dry-run by default; pass --apply to commit + push. |
bin/check.py is the load-bearing single command:
python3 bin/check.py --all # every static check, every theme
python3 bin/check.py --all --quick # skip slow checks (link probes, etc.)
python3 bin/check.py --visual # also run snap-gated visual sweep
python3 bin/check.py chonk # one theme
python3 bin/check.py chonk --visual --visual-scope=quick # smoke testStatic checks include (non-exhaustive):
-
theme.jsonis valid JSON and every block name resolves against the live Gutenberg + WooCommerce block registries. - No
!importantoutside the explicitly allow-listed sentinel-bracketed chunks. - No raw hex colors outside the palette (with the same allow-list mechanism for intentional gradient stops).
- Color palette meets WCAG AA contrast (4.5:1 normal text, 3:1 non-text) against every base/surface combination.
- Hover/focus states stay legible (the "accent collapses to invisible against base" footgun).
- WC card surfaces aren't horizontally zero-padded (the GRID_FIX regression).
- WC totals blocks have explicit padding (Phase H is intact).
- Distinctive chrome present (no theme falls back to plain WC defaults).
-
INDEX.mdis in sync with currenttheme.json. - No AI fingerprints (the "I cannot fulfill" / "as a language model" sweep) in any rendered template.
- No two themes ship identical
screenshot.pngbytes (check_theme_screenshots_distinct— fires when a freshly-cloned theme still has Obel's placeholder; fix by re-runningbin/build-theme-screenshots.py <theme>). - No two themes ship the same user-visible string (
check_all_rendered_text_distinct_across_themes); the WC microcopy maps must also be distinct across themes (check_wc_microcopy_distinct_across_themes). - Every theme's Playground blueprint has its content payload seeded (
check_playground_content_seeded). - The
comments.htmltemplate-part renders onecore/comments-title(no hand-typed second<h3>Comments</h3>) andplayground/wo-configure.phpships thecomment_author_emailbackfill so identicons hash distinctly.
bin/check.py runs in three places, each closing a different bypass:
-
.githooks/pre-commit— runs the gate on everygit commit. -
.githooks/pre-push— re-runs the gate AND abin/append-wc-overrides.pydrift check on everygit push(catches--no-verifycommits). -
.github/workflows/check.yml— server-side, on every PR and push tomain(authoritative).
The local hooks only fire if git config core.hooksPath points at .githooks/; that's not on by default for a fresh clone, so run python3 bin/install-hooks.py once after cloning.
When in doubt, read the failure message — every check explains what it found and links to the file path / line / rule that fired.
Fifty on GitHub · Live demos · GPL-2.0-or-later · Block-only WooCommerce themes, zero CSS files, zero JS, zero build step