From da716f866b79aa34d7b16c16aeefe47997141247 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Sun, 21 Jun 2026 15:12:28 -0400 Subject: [PATCH] Support canonical php-transformer site artifact schema --- .../docs/consumer-prs/examples/README.md | 2 +- ...atic-site-importer-transformer-adapter.php | 75 +++---------------- .../docs/consumer-prs/static-site-importer.md | 10 +-- .../wrappers/static-site-importer.md | 33 ++++---- .../src/ArtifactCompiler/ArtifactCompiler.php | 2 +- php-transformer/tests/contract/run.php | 3 + php-transformer/tests/migration/examples.php | 9 ++- 7 files changed, 43 insertions(+), 91 deletions(-) diff --git a/php-transformer/docs/consumer-prs/examples/README.md b/php-transformer/docs/consumer-prs/examples/README.md index bfa5ee3..e552a6c 100644 --- a/php-transformer/docs/consumer-prs/examples/README.md +++ b/php-transformer/docs/consumer-prs/examples/README.md @@ -9,7 +9,7 @@ Use them with the release playbooks in `php-transformer/docs/consumer-prs/`: | `html-to-blocks-converter-wrapper.php` | `chubes4/html-to-blocks-converter` | Preserve `html_to_blocks_*` helpers while delegating HTML conversion to `HtmlTransformer`. | | `block-format-bridge-wrapper.php` | `chubes4/block-format-bridge` | Preserve `bfb_*` functions and capability/report shapes while delegating supported conversions to `FormatBridge`. | | `block-artifact-compiler-wrapper.php` | `chubes4/block-artifact-compiler` | Preserve BAC functions and summaries while delegating artifact compilation to `ArtifactCompiler`. | -| `static-site-importer-transformer-adapter.php` | `chubes4/static-site-importer` | Keep importer workflows product-owned while mapping transformer results into current BFB/BAC-compatible reports. | +| `static-site-importer-transformer-adapter.php` | `chubes4/static-site-importer` | Keep importer workflows product-owned while consuming canonical transformer results through an SSI-owned adapter. | Before using an example in a release branch: diff --git a/php-transformer/docs/consumer-prs/examples/static-site-importer-transformer-adapter.php b/php-transformer/docs/consumer-prs/examples/static-site-importer-transformer-adapter.php index a1da1fa..f453d37 100644 --- a/php-transformer/docs/consumer-prs/examples/static-site-importer-transformer-adapter.php +++ b/php-transformer/docs/consumer-prs/examples/static-site-importer-transformer-adapter.php @@ -56,16 +56,16 @@ public function convert_fragment( string $html, array $options = array() ): arra } /** - * Compile a website artifact bundle and return SSI's current BAC result shape. + * Compile a site artifact bundle and return the canonical transformer result shape. * - * @param array $artifact Website artifact input. + * @param array $artifact Site artifact input. * @param array $options Compiler options retained for future transformer support. - * @return array BAC-compatible compiler result envelope. + * @return array Canonical transformer result envelope. */ public function compile_website_artifact( array $artifact, array $options = array() ): array { unset( $options ); - return $this->transformer_result_to_bac_result( ( new ArtifactCompiler() )->compile( $artifact )->toArray() ); + return ( new ArtifactCompiler() )->compile( $artifact )->toArray(); } /** @@ -85,19 +85,19 @@ public function blocks_to_html( array|string $blocks, array $options = array() ) } /** - * Summarize the BAC-compatible result shape SSI records in import reports. + * Summarize the canonical transformer result shape SSI records in import reports. * - * @param array $compiled BAC-compatible compiler result envelope. + * @param array $compiled Canonical transformer result envelope. * @return array Compact report summary. */ public function summarize_result( array $compiled ): array { - $artifacts = isset( $compiled['wordpress_artifacts'] ) && is_array( $compiled['wordpress_artifacts'] ) ? $compiled['wordpress_artifacts'] : array(); - $block_tree = isset( $artifacts['block_tree'] ) && is_array( $artifacts['block_tree'] ) ? $artifacts['block_tree'] : array(); - $block_types = isset( $artifacts['block_types'] ) && is_array( $artifacts['block_types'] ) ? $artifacts['block_types'] : array(); - $components = isset( $artifacts['components'] ) && is_array( $artifacts['components'] ) ? $artifacts['components'] : array(); - $files = isset( $artifacts['files'] ) && is_array( $artifacts['files'] ) ? $artifacts['files'] : array(); + $blocks = isset( $compiled['blocks'] ) && is_array( $compiled['blocks'] ) ? $compiled['blocks'] : array(); + $block_tree = $this->block_tree_report( $blocks ); + $block_types = isset( $compiled['block_types'] ) && is_array( $compiled['block_types'] ) ? $compiled['block_types'] : array(); + $components = isset( $compiled['components'] ) && is_array( $compiled['components'] ) ? $compiled['components'] : array(); + $files = isset( $compiled['assets'] ) && is_array( $compiled['assets'] ) ? $compiled['assets'] : array(); $diagnostics = isset( $compiled['diagnostics'] ) && is_array( $compiled['diagnostics'] ) ? $compiled['diagnostics'] : array(); - $source = isset( $compiled['input']['source_report'] ) && is_array( $compiled['input']['source_report'] ) ? $compiled['input']['source_report'] : array(); + $source = isset( $compiled['source_reports']['artifact'] ) && is_array( $compiled['source_reports']['artifact'] ) ? $compiled['source_reports']['artifact'] : array(); return array( 'schema' => isset( $compiled['schema'] ) ? (string) $compiled['schema'] : '', @@ -115,57 +115,6 @@ public function summarize_result( array $compiled ): array { ); } - /** - * @param array $result TransformerResult::toArray() output. - * @return array BAC-compatible compiler result envelope consumed by SSI. - */ - private function transformer_result_to_bac_result( array $result ): array { - $source_report = isset( $result['source_reports']['artifact'] ) && is_array( $result['source_reports']['artifact'] ) ? $result['source_reports']['artifact'] : array(); - $entry_path = isset( $source_report['entry_path'] ) ? (string) $source_report['entry_path'] : ''; - $provenance = isset( $result['provenance'][0] ) && is_array( $result['provenance'][0] ) ? $result['provenance'][0] : array(); - $blocks = isset( $result['blocks'] ) && is_array( $result['blocks'] ) ? $result['blocks'] : array(); - $serialized = isset( $result['serialized_blocks'] ) ? (string) $result['serialized_blocks'] : ''; - - return array( - 'schema' => 'block-artifact-compiler/result/v1', - 'status' => isset( $result['status'] ) ? (string) $result['status'] : 'failed', - 'input' => array( - 'schema' => isset( $source_report['schema'] ) ? (string) $source_report['schema'] : 'block-artifact-compiler/website-artifact/v1', - 'entry_path' => $entry_path, - 'entrypoints' => isset( $source_report['entrypoints'] ) && is_array( $source_report['entrypoints'] ) ? $source_report['entrypoints'] : array(), - 'file_count' => (int) ( $source_report['file_count'] ?? 0 ), - 'accepted_count' => (int) ( $source_report['accepted_count'] ?? 0 ), - 'rejected_count' => (int) ( $source_report['rejected_count'] ?? 0 ), - 'bytes' => (int) ( $source_report['bytes'] ?? 0 ), - 'files_by_kind' => isset( $source_report['files_by_kind'] ) && is_array( $source_report['files_by_kind'] ) ? $source_report['files_by_kind'] : array(), - 'files_by_role' => isset( $source_report['files_by_role'] ) && is_array( $source_report['files_by_role'] ) ? $source_report['files_by_role'] : array(), - 'files_by_mime' => isset( $source_report['files_by_mime'] ) && is_array( $source_report['files_by_mime'] ) ? $source_report['files_by_mime'] : array(), - 'original_schema' => isset( $source_report['original_schema'] ) ? (string) $source_report['original_schema'] : '', - 'source_report' => $source_report, - ), - 'wordpress_artifacts' => array( - 'block_markup' => $serialized, - 'blocks' => $blocks, - 'block_tree' => $this->block_tree_report( $blocks ), - 'block_types' => isset( $result['block_types'] ) && is_array( $result['block_types'] ) ? $result['block_types'] : array(), - 'components' => isset( $result['components'] ) && is_array( $result['components'] ) ? $result['components'] : array(), - 'documents' => isset( $result['documents'] ) && is_array( $result['documents'] ) ? $result['documents'] : array(), - 'files' => isset( $result['assets'] ) && is_array( $result['assets'] ) ? $result['assets'] : array(), - ), - 'provenance' => array( - 'source_hash' => isset( $provenance['source_hash'] ) ? (string) $provenance['source_hash'] : (string) ( $source_report['source_hash'] ?? '' ), - 'source' => '' !== $entry_path ? $entry_path : 'website_artifact', - ), - 'diagnostics' => isset( $result['diagnostics'] ) && is_array( $result['diagnostics'] ) ? $result['diagnostics'] : array(), - 'bfb_report' => array( - 'status' => isset( $result['status'] ) ? (string) $result['status'] : 'failed', - 'serialized_blocks' => $serialized, - 'diagnostics' => isset( $result['diagnostics'] ) && is_array( $result['diagnostics'] ) ? $result['diagnostics'] : array(), - 'fallbacks' => isset( $result['fallbacks'] ) && is_array( $result['fallbacks'] ) ? $result['fallbacks'] : array(), - ), - ); - } - /** * @param array> $blocks Parsed blocks. * @return array diff --git a/php-transformer/docs/consumer-prs/static-site-importer.md b/php-transformer/docs/consumer-prs/static-site-importer.md index 7eae340..0f9d843 100644 --- a/php-transformer/docs/consumer-prs/static-site-importer.md +++ b/php-transformer/docs/consumer-prs/static-site-importer.md @@ -134,7 +134,7 @@ final class Static_Site_Importer_Transformer_Adapter { public function compile_website_artifact( array $artifact, array $options = array() ): array { if ( class_exists( ArtifactCompiler::class ) ) { - return $this->to_bac_result( ( new ArtifactCompiler() )->compile( $artifact )->toArray() ); + return ( new ArtifactCompiler() )->compile( $artifact )->toArray(); } return function_exists( 'bac_compile_website_artifact' ) ? bac_compile_website_artifact( $artifact, $options ) : array(); @@ -164,15 +164,15 @@ final class Static_Site_Importer_Transformer_Adapter { } ``` -The copyable, linted version in `docs/consumer-prs/examples/static-site-importer-transformer-adapter.php` includes the full `TransformerResult` to BAC result mapper. SSI should keep that mapper local so product reports stay stable while transformer internals evolve. +The copyable, linted version in `docs/consumer-prs/examples/static-site-importer-transformer-adapter.php` returns the canonical transformer result envelope and includes summary helpers SSI can adapt into product-owned import reports. ## Public Function And Call Mapping | Current Static Site Importer surface | Current dependency | Adapter target | Phase-1 behavior | | --- | --- | --- | --- | | `Static_Site_Importer_Theme_Generator::import_theme()` | `bfb_convert_fragment()`, `bfb_convert()`, and conversion reports | `Static_Site_Importer_Transformer_Adapter::convert_fragment()` / `blocks_to_html()` | Keep import result and quality report shape unchanged. | -| `Static_Site_Importer_Theme_Generator::import_website_artifact()` | `bac_compile_website_artifact()` | `compile_website_artifact()` | Map transformer result arrays into existing BAC-compatible import args and report payloads. | -| `Static_Site_Importer_Source_Page::from_wordpress_document_artifact()` | BAC document artifact fields | Transformer document artifact fields through BAC-compatible mapper | Keep accepted document artifact fields stable. | +| `Static_Site_Importer_Theme_Generator::import_website_artifact()` | `bac_compile_website_artifact()` | `compile_website_artifact()` | Consume canonical transformer result arrays and map them into product-owned import args and report payloads. | +| `Static_Site_Importer_Source_Page::from_wordpress_document_artifact()` | BAC document artifact fields | Transformer document artifact fields through SSI-owned mapper | Keep accepted document artifact fields stable. | | `static-site-importer/import-theme` ability | Theme generator return array | Adapter hidden behind theme generator | Keep input and output schemas stable. | | `static-site-importer/import-website-artifact` ability | BAC compile result and theme generator | Adapter hidden behind ability callback | Keep ability contract stable and report transformer metadata only inside reports. | | `wp static-site-importer import-theme` | Ability output | Ability output unchanged | Keep CLI flags and JSON shape stable. | @@ -269,7 +269,7 @@ Run and compare these fixtures before changing adapter defaults: | --- | --- | --- | | `wordpress-is-dead` | `tests/smoke-wordpress-is-dead-fixture.php` and `tests/fixtures/wordpress-is-dead` | Legacy versus adapter import report, fallback count, generated templates/parts, navigation, CSS bridge output, visual/semantic targets. | | `mixed-source-site` | `tests/smoke-mixed-source-fixture.php`, `tests/smoke-mixed-source-link-rewrites.php`, and `tests/fixtures/mixed-source-site` | Source-document counts, Markdown page creation, skipped MDX diagnostics, rewritten links, conversion fragment keys. | -| `website-artifact-bundle` | `tests/fixtures/website-artifact-bundle/artifact.json` | BAC result envelope fields, `wordpress_artifacts` mapping, provenance, diagnostics, summary fields, materialized CSS/JS/file artifacts. | +| `website-artifact-bundle` | `tests/fixtures/website-artifact-bundle/artifact.json` | Canonical result envelope fields, `serialized_blocks`, assets, provenance, diagnostics, summary fields, materialized CSS/JS/file artifacts. | ## Blockers To Resolve Upstream First diff --git a/php-transformer/docs/consumer-prs/wrappers/static-site-importer.md b/php-transformer/docs/consumer-prs/wrappers/static-site-importer.md index 399421b..30c9122 100644 --- a/php-transformer/docs/consumer-prs/wrappers/static-site-importer.md +++ b/php-transformer/docs/consumer-prs/wrappers/static-site-importer.md @@ -7,7 +7,7 @@ | Current Static Site Importer path | Current dependency | Target dependency | | --- | --- | --- | | `Static_Site_Importer_Theme_Generator::import_theme()` | `bfb_convert()` for fragment/page/template conversion | Adapter service that calls `FormatBridge`/`HtmlTransformer` and returns the old serialized block strings until the report schema changes. | -| `Static_Site_Importer_Theme_Generator::import_website_artifact()` | `bac_compile_website_artifact()` and `bac_summarize_result()` | Adapter service that calls `ArtifactCompiler` and translates `TransformerResult` into the existing import report fields. | +| `Static_Site_Importer_Theme_Generator::import_website_artifact()` | `bac_compile_website_artifact()` and `bac_summarize_result()` | Adapter service that calls `ArtifactCompiler` and consumes the canonical `TransformerResult` envelope. | | Conversion report recording | BFB and BAC result envelopes | A `TransformerResult` to import-report mapper owned by Static Site Importer. | | CLI/ability output | Static Site Importer result arrays | No direct transformer exposure; keep CLI and ability contracts stable. | @@ -44,24 +44,23 @@ The adapter should be the only Static Site Importer class that knows whether the ### `compile_website_artifact()` -`compile_website_artifact()` returns the current BAC result envelope, not the raw `TransformerResult` envelope. That keeps `Static_Site_Importer_Theme_Generator::import_website_artifact()` and `record_website_artifact_compiler_result()` stable while php-transformer becomes the compiler implementation. +`compile_website_artifact()` returns the canonical `TransformerResult` envelope from `ArtifactCompiler::compile()`. Static Site Importer should map that envelope into product-owned import reports locally instead of preserving BAC-shaped schema names in the transformer integration boundary. -| BAC result key | TransformerResult source | +| Result key | TransformerResult source | | --- | --- | -| `schema` | Literal `block-artifact-compiler/result/v1`. | +| `schema` | Literal `blocks-engine/php-transformer/result/v1`. | | `status` | `status`. | -| `input` | `source_reports.artifact`, preserving `entry_path`, counts, file maps, original schema, and nested `source_report`. | -| `wordpress_artifacts.block_markup` | `serialized_blocks`. | -| `wordpress_artifacts.blocks` | `blocks`. | -| `wordpress_artifacts.block_tree` | Adapter-derived compact block count/depth report. | -| `wordpress_artifacts.block_types` | `block_types`. | -| `wordpress_artifacts.components` | `components`. | -| `wordpress_artifacts.documents` | `documents`. | -| `wordpress_artifacts.files` | `assets`. | -| `provenance.source_hash` | First transformer provenance row `source_hash`, falling back to `source_reports.artifact.source_hash`. | -| `provenance.source` | Artifact `entry_path`, falling back to `website_artifact`. | +| `source_reports.artifact.schema` | Literal `blocks-engine/php-transformer/site-artifact/v1`. | +| `source_reports.artifact` | Entry path, counts, file maps, original schema, source hash, and input summary. | +| `serialized_blocks` | Serialized block output. | +| `blocks` | Parse-block-compatible arrays. | +| `block_types` | Block type artifacts. | +| `components` | Component candidates. | +| `documents` | Source document artifacts. | +| `assets` | Normalized asset manifest. | +| `provenance` | Transformer provenance rows. | | `diagnostics` | `diagnostics`. | -| `bfb_report` | Compact status, serialized blocks, diagnostics, and fallbacks for current SSI report payloads. | +| `fallbacks` | Fallback rows for unsupported or partial transforms. | ### `blocks_to_html()` @@ -78,8 +77,8 @@ Use these Static Site Importer fixtures to compare the legacy BFB/BAC path again | Fixture | SSI reference | Adapter surfaces | Acceptance focus | | --- | --- | --- | --- | | `wordpress-is-dead` | `tests/fixtures/wordpress-is-dead`, exercised by `tests/smoke-wordpress-is-dead-fixture.php` | `convert_fragment()`, `blocks_to_html()` | Multi-page HTML import, header/footer extraction, navigation rewriting, CSS preservation, zero empty HTML fallback regressions, visual/semantic comparison target reporting. | -| `mixed-source-site` | `tests/fixtures/mixed-source-site`, exercised by `tests/smoke-mixed-source-fixture.php` and `tests/smoke-mixed-source-link-rewrites.php` | `convert_fragment()` for HTML fragments, BAC-compatible document/report mapping for Markdown documents | Markdown page creation, skipped MDX diagnostics, link rewrites away from `.md`, source-document report counts. | -| `website-artifact-bundle` | `tests/fixtures/website-artifact-bundle/artifact.json` | `compile_website_artifact()`, `summarize_result()` | BAC-compatible result envelope, `wordpress_artifacts.block_markup`, materializable CSS/JS/file artifacts, provenance, diagnostics, and import-report summary fields. | +| `mixed-source-site` | `tests/fixtures/mixed-source-site`, exercised by `tests/smoke-mixed-source-fixture.php` and `tests/smoke-mixed-source-link-rewrites.php` | `convert_fragment()` for HTML fragments, transformer document/report mapping for Markdown documents | Markdown page creation, skipped MDX diagnostics, link rewrites away from `.md`, source-document report counts. | +| `website-artifact-bundle` | `tests/fixtures/website-artifact-bundle/artifact.json` | `compile_website_artifact()`, `summarize_result()` | Canonical result envelope, `serialized_blocks`, materializable CSS/JS/file artifacts, provenance, diagnostics, and import-report summary fields. | The adapter PR should include an old-versus-adapter report table for these fixtures before switching the adapter default to transformer-backed conversion. diff --git a/php-transformer/src/ArtifactCompiler/ArtifactCompiler.php b/php-transformer/src/ArtifactCompiler/ArtifactCompiler.php index a771b04..2b2fa2b 100644 --- a/php-transformer/src/ArtifactCompiler/ArtifactCompiler.php +++ b/php-transformer/src/ArtifactCompiler/ArtifactCompiler.php @@ -11,7 +11,7 @@ final class ArtifactCompiler { - private const INPUT_SCHEMA = 'blocks-engine/php-transformer/site-artifact/v1'; + public const INPUT_SCHEMA = 'blocks-engine/php-transformer/site-artifact/v1'; /** * @param array $artifact diff --git a/php-transformer/tests/contract/run.php b/php-transformer/tests/contract/run.php index 3371a38..ba9e98c 100644 --- a/php-transformer/tests/contract/run.php +++ b/php-transformer/tests/contract/run.php @@ -145,11 +145,14 @@ function serialize_blocks(array $blocks): string $simple = $compiler->compile( array( + 'schema' => ArtifactCompiler::INPUT_SCHEMA, 'generated_html' => '

Hello artifact

', ) )->toArray(); TransformerResult::assertCanonicalEnvelope($simple); $assert('success' === $simple['status'], 'simple artifact compiles successfully', (string) $simple['status']); +$assert(ArtifactCompiler::INPUT_SCHEMA === ($simple['source_reports']['artifact']['schema'] ?? ''), 'artifact report exposes canonical site artifact schema'); +$assert(ArtifactCompiler::INPUT_SCHEMA === ($simple['source_reports']['artifact']['original_schema'] ?? ''), 'canonical site artifact input schema is accepted and preserved'); $assert('index.html' === ($simple['source_reports']['artifact']['entry_path'] ?? ''), 'generated HTML becomes an index entry'); $assert(str_contains((string) $simple['serialized_blocks'], ''), 'HTML is preserved as serialized block markup'); $assert('hero' === ($simple['components'][0]['name'] ?? ''), 'component candidates are exposed'); diff --git a/php-transformer/tests/migration/examples.php b/php-transformer/tests/migration/examples.php index 2f57907..af0ddf7 100644 --- a/php-transformer/tests/migration/examples.php +++ b/php-transformer/tests/migration/examples.php @@ -116,13 +116,14 @@ $assert( 'html' === ( $fragment['from'] ?? '' ) && 'blocks' === ( $fragment['to'] ?? '' ), 'SSI adapter returns BFB-compatible conversion direction' ); $assert( 'main:index.html' === ( $fragment['scope']['source_id'] ?? '' ), 'SSI adapter preserves fragment scope' ); $compiled = $adapter->compile_website_artifact( array( 'generated_html' => '

Hello

' ) ); -$assert( 'block-artifact-compiler/result/v1' === ( $compiled['schema'] ?? '' ), 'SSI adapter compiles website artifact to BAC schema' ); -foreach ( array( 'block_markup', 'blocks', 'block_tree', 'block_types', 'components', 'documents', 'files' ) as $key ) { - $assert( array_key_exists( $key, $compiled['wordpress_artifacts'] ?? array() ), "SSI adapter BAC mapping includes {$key}" ); +$assert( 'blocks-engine/php-transformer/result/v1' === ( $compiled['schema'] ?? '' ), 'SSI adapter compiles site artifact to canonical transformer result schema' ); +$assert( 'blocks-engine/php-transformer/site-artifact/v1' === ( $compiled['source_reports']['artifact']['schema'] ?? '' ), 'SSI adapter reports canonical site artifact input schema' ); +foreach ( array( 'serialized_blocks', 'blocks', 'block_types', 'components', 'documents', 'assets' ) as $key ) { + $assert( array_key_exists( $key, $compiled ), "SSI adapter canonical result includes {$key}" ); } $summary = $adapter->summarize_result( $compiled ); $assert( isset( $summary['block_count'] ), 'SSI adapter summarizes compiler result' ); -$html = $adapter->blocks_to_html( (string) ( $compiled['wordpress_artifacts']['block_markup'] ?? '' ) ); +$html = $adapter->blocks_to_html( (string) ( $compiled['serialized_blocks'] ?? '' ) ); $assert( '' !== trim( $html ), 'SSI adapter renders blocks to HTML' ); PHP );