Releases: humanmade/block-runner
Release list
0.9.1
This patch improves the agent skill's guidance for working in existing WordPress projects.
- Adds concise construction examples covering persistence, reuse, dependency ownership, registration, and build wiring.
- Connects project discovery to the new reference and removes duplicated instructions.
- Corrects the guide's outdated description of 0.9.0 as unreleased.
- Fixes release receipt validation for 0.9 patch versions.
CLI and library behavior are unchanged. The release workflow runs the automated release matrix before publishing to npm's latest tag.
Block Runner 0.9.0
Block Runner 0.9.0 adds registered WordPress block authoring alongside the existing native-block content workflow.
Your agent proposes the structure, editable fields, and styling. Block Runner previews the exact plan, requires confirmation, then generates source around native WordPress InnerBlocks. The package makes no model calls and adds no Tailwind runtime to the generated block.
- Source-bound proposals preserve authored content, supported styles, local assets, and licensed fonts.
- Generate a standalone plugin or integrate with a supported existing WordPress plugin.
- The shipped skill inspects the current project, follows its conventions, asks only unresolved questions, and provides a developer handoff when automatic integration is unsupported.
- Wesper 0.0.3 supplies site context and normalized theme presets.
Install or update:
npm install block-runner@latest
npx block-runner skill --installRequires Node.js ^20.19.0 || ^22.13.0 || >=24.0.0. Generated-plugin proof targets WordPress 7.1.
The release workflow checks the exact candidate's package, skill installers, generated plugin, and WordPress editor/frontend behavior before publishing to npm with provenance. The narrow native WordPress editor accessibility exceptions remain explicit in the raw evidence. Owner acceptance uses the reported prior testing; it is not independent accessibility certification.
The separate registered-block model benchmark remains unscored. Existing page-content benchmark results do not measure registered-block authoring.
See the changelog for the full changes.
v0.8.0 — cross-harness agent skill
Full Changelog: v0.7.1...v0.8.0
v0.7.1 — the guide now says where the blocks go
Fixed
- The guide now says where the blocks go. It stopped at "here is valid markup", leaving an
agent holding correct output with no instruction on what to do with it — so a request like
"add a pricing section to my site" ended in improvisation.GUIDE.md§5 covers the three
endings: write it where the user asked, offer to write it through an available WordPress
connection, or show it with the paste instruction. Including the one users get wrong —
block markup must go into the Code editor (Ctrl+Shift+Alt+M), not the visual editor,
which turns it into a mess and reads as the tool being broken.
No code changes; the CLI and library are identical to 0.7.0.
v0.7.0 — Block Runner ships a skill
Block Runner now ships a skill. Agents get markedly better conversions when told how to
use the tool, so the instructions travel with the package instead of being rediscovered by
every consumer.
npx block-runner skill # print the guide — nothing installed or written
npx block-runner skill --install # install it as a skillMeasured on the project's own 53-fixture benchmark, the guide takes the corpus from 28 to
97, with 0 invalid and 0 fallbacks. Those figures come from a controlled harness rather than
a live session, so treat them as a ceiling.
Added
- The skill, shipped in the package and readable by any harness.
skill/GUIDE.mdis the
content;skill/SKILL.mdis a thin wrapper over it.skill --installwrites both into
.claude/skills/block-runner/, with--dirfor harnesses that keep skills elsewhere. The
guide covers which command to reach for, the block mappings per section type, the
validate/fix loop, and how to fail safely without stranding the user. assemble— build blocks from a described structure, not from markup. The command the
skill drives. Give it an intent tree (JSON naming which blocks go where) and it builds the
result withcreateBlock, so the output cannot be invalid. Describing a structure suits a
model far better than authoring block markup, which is where invalid output comes from.
Also available asassemble/extractIntent/realizelibrary exports.- A hint when a conversion falls back. A
convertrun that drops to Custom HTML now says
so on stderr and inreport.hint, pointing at the path that usually handles that input
cleanly. It is advisory: it never affects the exit code, the summary counts, or--strict.
Changed
- Media resolution and brand-token repair are shared by every path.
convertand
assemblenow run the same finalization, so a tree built from intent resolves images and
maps colours onto theme presets exactly as a converted one does.
Notes
--stylingand--css-outdo not apply toassembleand are rejected with an explanation:
an intent tree carries structure and content, never the source CSS. Useconvertwhen the
styling matters.- Malformed or empty intent input is a hard failure (exit
1) naming what went wrong, rather
than a successful run that produced nothing. convert,validate, andfixare unchanged. Verified by running the benchmark at the
previous release and at this one: identical scores across all 53 fixtures.
0.6.0 — CSS to native block styles
Until now the converter read only background-image and discarded every other CSS declaration in silence. A <div style="padding:64px;background:#f5f5f5"> produced a correct block tree with none of its design, and nothing said so.
Added
- CSS maps onto blocks as native, editable styling — from inline
styleattributes and single-class<style>rules. Padding lands in the spacing control, colours in the colour picker. Inline outranks class rules;!importantand shorthand resets are honoured as CSS defines them. - A
stylingceiling:strict·relaxed·open.strictkeeps only values that snap onto theme presets,relaxed(default) keeps exact values on the block,openalso preserves CSS no block attribute can express by classing the block and emitting a stylesheet. Config or--styling. --css-out/report.sidecarCssfor whatopenproduces.--styling openwithout a sink is an error — a level that quietly discarded the CSS it promised to keep would be worse than not offering it.- Every declaration is accounted for: mapped, consumed by the structural rules, or dropped — with the input line and the authoring selector, so warnings point upstream (
max-width: 600px in .hero). text-align, viastyle.typography.textAlign.- WordPress 7.1
minWidth, gated on the block opting in.text-shadowis recognised and refused: it is Global-Styles-only in 7.1, so a per-block value would render CSS the editor gives no control over — the warning points attheme.json. - Capability gating against the real target site. With a wesper
--contextmanifest, styling is admitted only where the pinned block library and the site's own block registry agree, so degradation across WordPress versions is measured rather than hardcoded.
Fixed
- Background images follow the CSS cascade, not first match. An image a later declaration replaced or removed no longer becomes cover media — the structural rules and the styling ledger now read a style attribute through the same parser.
Changed
@wordpress/block-editoris now a direct pinned dependency. It was already present transitively and governs the emitted markup, so it belongs in the pin rather than resolved by chance.
179 tests. Full notes in CHANGELOG.md.
v0.5.1
Changed
- Stop shipping sourcemaps.
dist/*.js.mapwere ~340KB of the published tarball and served no purpose for consumers. Dropping them roughly halves the package (packed 128.6 kB → 52 kB, unpacked 542KB → 202KB) and avoids leaking local build paths.
v0.5.0 — traditional-content coverage & inline-SVG crash fix
The layer between generated content and WordPress just got much broader coverage — and stopped crashing on inline SVG.
Fixed
- Inline SVG (and any foreign element) no longer crashes conversion. An
<svg>/MathML node anywhere threwclassName.split is not a functionand aborted the whole run with no output. Foreign elements now route to Custom HTML, and a per-rule error boundary guarantees no single node can abort a run.
Added
- Native-block coverage for traditional content:
<table>→core/table(colspan/rowspan/scope +<caption>),<blockquote>→core/quote,<pre><code>/<pre>→core/code/core/preformatted,<hr>→core/separator,<video>/<audio>→core/video/core/audio(+<track>),<details>→core/details, YouTube/Vimeo<iframe>→core/embed, multi-image<figure>→core/gallery, with a<figure>dispatcher for captions. - Atomic enclosing-unit fallback. When a block's rich text holds content the editor can't keep (inline SVG/iframe, block-level markup), the whole enclosing block falls back to Custom HTML with a warning at the offending node. Decorative empty inline hooks are stripped so blocks stay native; empty semantic elements (
id/href/datetime/aria-*) fall back instead of being lost.
Security
- Hardened URL sanitization: control-char/whitespace-obfuscated
javascript:/vbscript:and executable<iframe srcdoc>are stripped. - Exact-hostname embed matching over HTTPS, so lookalike domains (
notyoutube.com) can't be rewritten into a trustedcore/embed.
Codex Review
2 review passes. Final: all actionable findings resolved.
- ✅ Addressed: embed lookalike-domain trust-boundary bypass — exact-hostname URL parsing.
- ✅ Addressed:
data:/control-char URL schemes in rich text — normalized + rejected. - ✅ Addressed: silent loss of gallery images / table captions / video tracks / mixed-figure content — all carried or preserved via group.
- ✅ Addressed: semantic empty inline elements stripped — now fall back to Custom HTML.
- ✋ By design: presentational attributes (class/style/preload) are shed for clean native blocks, consistent with every existing rule; content-bearing attributes are carried.
Full transcript: .git/codex-review-main.log (local).
0.4.1
0.4.1 — cut unused media WASM (~155MB)
Headless convert/validate never uses Gutenberg’s editor media pipeline, but
@wordpress/block-library still pulled in @wordpress/vips + wasm-vips.
Changes
- Override those packages to empty stubs when block-runner is the install root
postinstallprune removes them when block-runner is a nested dependency
(npm ignores nestedoverrides)
Measured consumer install
| Size | |
|---|---|
| 0.4.0 | ~501 MB |
| 0.4.1 | ~346 MB |
npm install block-runner@0.4.10.4.0
0.4.0 — dependency refresh & zero audit findings
Dependencies
@wordpress/blocks14.15 → 15.23,@wordpress/block-library9.26 → 10.1jsdom24 → 29,commander12 → 15- Dev:
vitest2 → 4,tsup8.5,tsx4.23,typescript5.9 - Overrides:
uuid@11.1.1,esbuild@0.28.1
Security
npm audit→ 0 vulnerabilities (was 18: 1 critical, 1 high, 16 moderate)
Notes
- Requires Node ≥20 (unchanged from 0.3.x)
- Full test suite green against the new Gutenberg headless stack
npm install block-runner@0.4.0