From 5b85ff8fc465060ff21bddda276c0f2c0c695d69 Mon Sep 17 00:00:00 2001 From: Noel Tock Date: Tue, 15 Sep 2026 09:09:55 +0700 Subject: [PATCH] chore: prepare 0.9.7 with Wesper 0.4.1 --- CHANGELOG.md | 6 ++++ dev/test/context.test.ts | 49 +++++++++++++++++++++++++++++--- dev/test/styles.test.ts | 60 ++++++++++++++++++++++++++++++++++++++++ package-lock.json | 12 ++++---- package.json | 4 +-- 5 files changed, 119 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5bd309..5990c18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 0.9.7 — 2026-09-15 + +- Update Wesper to 0.4.1, retaining compatibility with optional ownership and taxonomy evidence and partial collection warnings. +- Reuse WordPress between sequential proof cases while retaining each artifact installation and browser check. +- Run focused CI checks for allowlisted documentation and demo updates pushed to main. + ## 0.9.6 — 2026-09-14 - Point the package homepage to the Block Runner website on Accelerate. diff --git a/dev/test/context.test.ts b/dev/test/context.test.ts index 8fa1348..ac0b718 100644 --- a/dev/test/context.test.ts +++ b/dev/test/context.test.ts @@ -1,7 +1,44 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; +import type { SiteContext } from 'wesper'; -const collect = vi.fn(async () => ({ contextVersion: 1 })); -const stringifyManifest = vi.fn(() => '{"ok":true}\n'); +const collectedContext = { + $schema: 'https://humanmade.github.io/wesper/schemas/site-context-v1.schema.json', + contextVersion: 1, + site: { environment: 'local', isMultisite: false }, + provenance: { + collectedAt: '2026-09-15T00:00:00.000Z', + collector: 'wp-cli', + collectorVersion: '0.2.3', + sourceHash: 'sha256:fixture', + partial: true, + }, + blocks: { + types: [{ + name: 'acme/catalog', + attributes: {}, + supports: {}, + source: 'plugin', + owner: { status: 'unknown', reason: 'scan_incomplete' }, + }], + }, + contentModel: { + postTypes: [{ + name: 'product', + taxonomies: ['product_cat'], + fields: [], + owner: { status: 'unknown', reason: 'incomplete_registration_trace' }, + }], + taxonomies: [{ + name: 'product_cat', + objectTypes: ['product'], + owner: { status: 'unknown', reason: 'incomplete_registration_trace' }, + }], + }, + warnings: [], +} satisfies SiteContext; + +const collect = vi.fn(async () => collectedContext); +const stringifyManifest = vi.fn((_context: SiteContext) => '{"ok":true}\n'); vi.mock('wesper', () => ({ collect, stringifyManifest })); @@ -44,10 +81,14 @@ describe('collectSiteContext', () => { ); }); - it('returns the stringified manifest', async () => { + it('passes newer optional ownership and taxonomy associations to Wesper unchanged', async () => { const result = await collectSiteContext({}); - expect(stringifyManifest).toHaveBeenCalledWith({ contextVersion: 1 }); + expect(stringifyManifest.mock.calls[0]?.[0]).toBe(collectedContext); + expect(collectedContext.contentModel).toMatchObject({ + postTypes: [{ name: 'product', taxonomies: ['product_cat'], owner: { status: 'unknown' } }], + taxonomies: [{ name: 'product_cat', objectTypes: ['product'], owner: { status: 'unknown' } }], + }); expect(result).toBe('{"ok":true}\n'); }); }); diff --git a/dev/test/styles.test.ts b/dev/test/styles.test.ts index 79b33f5..673c5dc 100644 --- a/dev/test/styles.test.ts +++ b/dev/test/styles.test.ts @@ -1,3 +1,6 @@ +import { mkdtempSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import path from 'node:path'; import { describe, expect, it } from 'vitest'; import { convert } from '../../src/index.js'; import type { RuleContext } from '../../src/types.js'; @@ -7,6 +10,13 @@ import { expandShorthand, parseInlineStyle } from '../../src/styles/parse.js'; const warningsOf = (items: Awaited>['items']) => items.filter((item) => item.status === 'warning').map((item) => item.reason); +function writeContext(manifest: unknown): string { + const directory = mkdtempSync(path.join(tmpdir(), 'block-runner-context-')); + const contextPath = path.join(directory, 'site.context.json'); + writeFileSync(contextPath, JSON.stringify(manifest)); + return contextPath; +} + describe('inline style parsing', () => { it('expands box shorthands with CSS 1-4 value semantics', () => { expect(expandShorthand('padding', '10px')).toEqual([ @@ -904,6 +914,56 @@ describe('styling — capability source', () => { expect(report.output).toContain('padding-top:8px'); }); + it('does not block conversion for additive collector relationships and a partial block warning', async () => { + const context = writeContext({ + contextVersion: 1, + site: { environment: 'local', isMultisite: false }, + provenance: { + collectedAt: '2026-09-15T00:00:00.000Z', + collector: 'wp-cli', + collectorVersion: '0.2.3', + sourceHash: 'sha256:fixture', + partial: true, + }, + blocks: { + types: [{ + name: 'core/group', + attributes: {}, + supports: { spacing: { padding: true } }, + source: 'core', + owner: { status: 'unknown', reason: 'scan_incomplete' }, + providesContext: { 'acme/productId': 'productId' }, + }], + }, + contentModel: { + postTypes: [{ + name: 'product', + taxonomies: ['product_cat'], + owner: { status: 'unknown', reason: 'incomplete_registration_trace' }, + }], + taxonomies: [{ + name: 'product_cat', + objectTypes: ['product'], + owner: { status: 'unknown', reason: 'incomplete_registration_trace' }, + }], + }, + warnings: [ + { + code: 'blocks.provides_context_attribute_missing', + severity: 'warning', + surface: 'blocks.types.core/group.providesContext.acme/productId', + message: 'Block "core/group" provides context "acme/productId" from "productId", but the registered block attributes do not include it.', + coverage: 'partial', + }, + ], + }); + + const report = await convert(`
Text
`, { context }); + + expect(report.ok).toBe(true); + expect(report.output).toContain('padding-top:8px'); + }); + it('fails rather than widening back to the pin when an explicit context is unreadable', async () => { const report = await convert(`
Text
`, { context: 'dev/test/fixtures/does-not-exist.json', diff --git a/package-lock.json b/package-lock.json index 2b858b3..d862e63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "block-runner", - "version": "0.9.6", + "version": "0.9.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "block-runner", - "version": "0.9.6", + "version": "0.9.7", "hasInstallScript": true, "license": "GPL-2.0-or-later", "dependencies": { @@ -22,7 +22,7 @@ "postcss": "8.5.26", "react": "18.3.1", "react-dom": "18.3.1", - "wesper": "0.0.3" + "wesper": "0.4.1" }, "bin": { "block-runner": "dist/cli.js" @@ -14094,9 +14094,9 @@ } }, "node_modules/wesper": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wesper/-/wesper-0.0.3.tgz", - "integrity": "sha512-hGfq/xA+IC+qJ+y0VMrUegngqZN7+yPtlVgOEs7fdJaOpuceTo8iJX3tGTXxgAn0C5JWhrIBZq6lwQBXAuWM4g==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/wesper/-/wesper-0.4.1.tgz", + "integrity": "sha512-JP76chbI4xjb9CRR+RVH9RbeUPf/HkCeYmngnR6nCKtyG+DeLZsoIqlun41Sy+LT8KWrtckT2zhLftA7hsrIRw==", "license": "GPL-2.0-or-later", "dependencies": { "commander": "^14.0.3", diff --git a/package.json b/package.json index a8fedb0..6cb7d59 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "block-runner", - "version": "0.9.6", + "version": "0.9.7", "description": "The layer between generated content and WordPress \u2014 convert what AI, agents, and design tools emit into clean, valid, native Gutenberg blocks, and validate every result. CLI + library.", "type": "module", "license": "GPL-2.0-or-later", @@ -102,7 +102,7 @@ "postcss": "8.5.26", "react": "18.3.1", "react-dom": "18.3.1", - "wesper": "0.0.3" + "wesper": "0.4.1" }, "devDependencies": { "@playwright/test": "1.61.1",