@@ -33,7 +33,17 @@ public function get_browser_contained_site_status( array $input ): array|WP_Erro
3333 $ cache_key = $ this ->safe_key ( (string ) ( $ input ['cache_key ' ] ?? $ recovery ['cache_key ' ] ?? $ prepared ['cache_key ' ] ?? $ input ['site_id ' ] ?? $ contained_site ['site_id ' ] ?? '' ) );
3434 $ input_hash = strtolower ( trim ( (string ) ( $ input ['input_hash ' ] ?? $ recovery ['input_hash ' ] ?? $ prepared ['input_hash ' ] ?? $ source_digest ) ) );
3535 if ( '' === $ cache_key || ! preg_match ( '/^[a-f0-9]{64}$/ ' , $ input_hash ) ) {
36- return new WP_Error ( 'wp_codebox_browser_contained_site_ref_invalid ' , 'Browser contained site status requires cache_key/site_id and a 64-character source digest. ' , array ( 'status ' => 400 ) );
36+ return new WP_Error (
37+ 'wp_codebox_browser_contained_site_ref_missing ' ,
38+ 'Browser contained site status requires a hydratable prepared runtime ref. Use prepare-new to create a preview session before opening. ' ,
39+ array (
40+ 'status ' => 400 ,
41+ 'schema ' => 'wp-codebox/browser-contained-site-status/v1 ' ,
42+ 'preview_state ' => 'hydratable-ref-missing ' ,
43+ 'reason ' => 'hydratable-ref-missing ' ,
44+ 'prepare_new_required ' => true ,
45+ )
46+ );
3747 }
3848
3949 $ prepared_ref = array (
@@ -55,9 +65,9 @@ public function preview_reuse_decision( array $input ): array|WP_Error {
5565 'reuse_current ' => 'reuse-current ' ,
5666 'reuse_live ' , 'reuse_materialized ' , 'reuse_prepared_runtime ' => 'hydrate-ref ' ,
5767 'unavailable ' => 'reload-required ' ,
58- default => 'create -new ' ,
68+ default => 'prepare -new ' ,
5969 };
60- $ reload_required = in_array ( $ action , array ( 'create -new ' , 'reload-required ' ), true );
70+ $ reload_required = in_array ( $ action , array ( 'prepare -new ' , 'reload-required ' ), true );
6171 $ identity_key = hash ( 'sha256 ' , implode ( ': ' , array ( (string ) ( $ status ['site_id ' ] ?? '' ), (string ) ( $ status ['source_digest ' ]['value ' ] ?? '' ), $ open_mode ) ) );
6272
6373 return array_filter (
@@ -72,6 +82,8 @@ public function preview_reuse_decision( array $input ): array|WP_Error {
7282 'open_mode ' => $ open_mode ,
7383 'reuse_level ' => (string ) ( $ status ['reuse_level ' ] ?? 'none ' ),
7484 'requires_materialization ' => true === ( $ status ['requires_materialization ' ] ?? false ),
85+ 'prepare_new_required ' => true === ( $ status ['prepare_new_required ' ] ?? false ),
86+ 'preview_state ' => (string ) ( $ status ['preview_state ' ] ?? '' ),
7587 'prepared_runtime_recoverable ' => true === ( $ status ['prepared_runtime_recoverable ' ] ?? false ),
7688 'live ' => true === ( $ status ['live ' ] ?? false ),
7789 'current ' => true === ( $ status ['current ' ] ?? false ),
@@ -98,7 +110,7 @@ public function open_browser_contained_site( array $input ): array|WP_Error {
98110 $ preview_boot = WP_Codebox_Browser_Task_Builder::preview_boot_config ( $ session );
99111 $ preview_lease = WP_Codebox_Browser_Task_Builder::preview_lease ( $ session );
100112 $ blueprint_ref = is_array ( $ status ['blueprint_ref ' ] ?? null ) ? $ status ['blueprint_ref ' ] : array ();
101- $ boot_contract = true === ( $ status ['success ' ] ?? false ) ? WP_Codebox_Browser_Task_Builder::validate_browser_preview_boot_contract ( $ preview_boot , $ blueprint_ref ) : array ( 'valid ' => false , 'reason ' => '' );
113+ $ boot_contract = true === ( $ status ['success ' ] ?? false ) ? WP_Codebox_Browser_Task_Builder::validate_browser_preview_boot_contract ( $ preview_boot , $ blueprint_ref ) : array ( 'valid ' => false , 'reason ' => ( string ) ( $ status [ ' preview_state ' ] ?? '' ) );
102114 $ site_id = (string ) ( $ status ['site_id ' ] ?? $ contained_site ['site_id ' ] ?? $ input ['site_id ' ] ?? '' );
103115 $ session_id = (string ) ( $ session ['session ' ]['id ' ] ?? '' );
104116 $ preview_id = (string ) ( $ contained_site ['preview_id ' ] ?? $ input ['preview_id ' ] ?? '' );
@@ -155,6 +167,8 @@ public function open_browser_contained_site( array $input ): array|WP_Error {
155167 'site_id ' => $ site_id ,
156168 'status ' => $ open_status ,
157169 'resolution ' => $ resolution ,
170+ 'preview_state ' => (string ) ( $ resolution ['reason ' ] ?? '' ),
171+ 'prepare_new_required ' => true === ( $ lifecycle ['requires_materialization ' ] ?? false ),
158172 'contained_site ' => $ opened_site ,
159173 'source_digest ' => is_array ( $ status ['source_digest ' ] ?? null ) ? $ status ['source_digest ' ] : array (),
160174 'prepared_runtime ' => is_array ( $ status ['prepared_runtime ' ] ?? null ) ? $ status ['prepared_runtime ' ] : array (),
@@ -297,7 +311,7 @@ public function boot_browser_contained_site_session( array $input ): array|WP_Er
297311 'success ' => true === ( $ session ['success ' ] ?? false ),
298312 'schema ' => 'wp-codebox/browser-contained-site-boot-result/v1 ' ,
299313 'action ' => (string ) ( $ session ['action ' ] ?? '' ),
300- 'boot ' => is_array ( $ session ['boot ' ] ?? null ) ? $ session ['boot ' ] : array (),
314+ 'preview_boot ' => is_array ( $ session ['preview_boot ' ] ?? null ) ? $ session ['preview_boot ' ] : array (),
301315 'preview_lease ' => is_array ( $ session ['preview_lease ' ] ?? null ) ? $ session ['preview_lease ' ] : array (),
302316 'contained_site ' => is_array ( $ session ['contained_site ' ] ?? null ) ? $ session ['contained_site ' ] : array (),
303317 'startup_diagnostics ' => is_array ( $ session ['startup_diagnostics ' ] ?? null ) ? $ session ['startup_diagnostics ' ] : array (),
@@ -312,7 +326,7 @@ public function preview_boot_ref( array $input ): array|WP_Error {
312326 return $ boot_result ;
313327 }
314328
315- $ boot = is_array ( $ boot_result ['boot ' ] ?? null ) ? $ boot_result ['boot ' ] : array ();
329+ $ boot = is_array ( $ boot_result ['preview_boot ' ] ?? null ) ? $ boot_result ['preview_boot ' ] : array ();
316330 $ contained_site = is_array ( $ boot_result ['contained_site ' ] ?? null ) ? $ boot_result ['contained_site ' ] : array ();
317331 $ preview_lease = is_array ( $ boot_result ['preview_lease ' ] ?? null ) ? $ boot_result ['preview_lease ' ] : array ();
318332 $ diagnostics = is_array ( $ boot_result ['startup_diagnostics ' ] ?? null ) ? $ boot_result ['startup_diagnostics ' ] : array ();
@@ -321,7 +335,7 @@ public function preview_boot_ref( array $input ): array|WP_Error {
321335
322336 $ stable_boot = array_filter (
323337 array (
324- 'schema ' => 'wp-codebox/browser-contained-site- boot/v1 ' ,
338+ 'schema ' => 'wp-codebox/browser-preview- boot-config /v1 ' ,
325339 'session_id ' => (string ) ( $ boot ['session_id ' ] ?? '' ),
326340 'site_id ' => (string ) ( $ boot ['site_id ' ] ?? '' ),
327341 'status ' => (string ) ( $ boot ['status ' ] ?? '' ),
@@ -335,19 +349,10 @@ public function preview_boot_ref( array $input ): array|WP_Error {
335349 array (
336350 'success ' => true === ( $ boot_result ['success ' ] ?? false ),
337351 'schema ' => 'wp-codebox/preview-boot-ref/v1 ' ,
338- 'boot ' => $ stable_boot ,
352+ 'preview_boot ' => $ stable_boot ,
339353 'blueprint_ref ' => $ blueprint_ref ,
340354 'preview_lease ' => $ preview_lease ,
341355 'startup_diagnostics ' => $ diagnostics ,
342- 'compatibility ' => array_filter (
343- array (
344- 'contained_site_schema ' => (string ) ( $ contained_site ['schema ' ] ?? '' ),
345- 'session_result_schema ' => (string ) ( $ boot_result ['schema ' ] ?? '' ),
346- 'legacy_contained_site ' => $ contained_site ,
347- 'legacy_session_result ' => $ boot_result ,
348- ),
349- static fn ( mixed $ value ): bool => array () !== $ value && '' !== $ value
350- ),
351356 ),
352357 static fn ( mixed $ value ): bool => array () !== $ value && '' !== $ value
353358 );
@@ -452,7 +457,7 @@ public function browser_session_response_for_input( array $session, array $input
452457 if ( false === ( $ boot_contract ['valid ' ] ?? false ) ) {
453458 return new WP_Error (
454459 'wp_codebox_browser_preview_boot_contract_invalid ' ,
455- 'Browser preview session is missing a hydratable blueprint ref. ' ,
460+ 'Browser preview sessions require a hydratable blueprint ref. Use prepare-new to create a preview session before opening or hydrating it . ' ,
456461 array (
457462 'status ' => 500 ,
458463 'schema ' => 'wp-codebox/browser-preview-boot-contract-error/v1 ' ,
@@ -490,7 +495,6 @@ public function browser_session_evidence_store( array $product_dto, array $sessi
490495 'created_at ' => gmdate ( 'c ' ),
491496 'session_id ' => $ session_id ,
492497 'preview_ref ' => is_array ( $ product_dto ['preview_ref ' ] ?? null ) ? $ product_dto ['preview_ref ' ] : array (),
493- 'preview_reference ' => is_array ( $ product_dto ['preview_reference ' ] ?? null ) ? $ product_dto ['preview_reference ' ] : array (),
494498 'preview_lease ' => is_array ( $ product_dto ['preview_lease ' ] ?? null ) ? $ product_dto ['preview_lease ' ] : array (),
495499 'preview_boot ' => is_array ( $ product_dto ['preview_boot ' ] ?? null ) ? $ product_dto ['preview_boot ' ] : array (),
496500 'blueprint_ref ' => is_array ( $ product_dto ['blueprint_ref ' ] ?? null ) ? $ product_dto ['blueprint_ref ' ] : array (),
@@ -610,6 +614,8 @@ public function browser_contained_site_status_envelope( string $cache_key, strin
610614 'algorithm ' => 'sha256 ' ,
611615 'value ' => $ input_hash ,
612616 ),
617+ 'preview_state ' => (string ) ( $ resolution ['reason ' ] ?? $ status ),
618+ 'prepare_new_required ' => 'recoverable_prepared_runtime ' !== $ status ,
613619 'prepared_runtime ' => array_filter (
614620 array (
615621 'cache_key ' => $ cache_key ,
@@ -649,7 +655,7 @@ public function browser_contained_site_lifecycle( string $status, array $resolut
649655 } elseif ( $ materialized ) {
650656 $ open_mode = 'reuse_materialized ' ;
651657 $ reuse_level = 'materialized ' ;
652- } elseif ( in_array ( $ status , array ( 'disabled ' , 'incompatible ' , 'unusable ' ), true ) ) {
658+ } elseif ( in_array ( $ status , array ( 'disabled ' , 'incompatible ' , 'unusable ' , ' hydratable_ref_missing ' , ' input_hash_mismatch ' ), true ) ) {
653659 $ open_mode = 'unavailable ' ;
654660 }
655661
@@ -701,6 +707,9 @@ public function browser_contained_site_status_from_lookup( array $lookup ): stri
701707 if ( 'hit ' === $ lookup_status ) {
702708 return 'recoverable_prepared_runtime ' ;
703709 }
710+ if ( in_array ( $ lookup_status , array ( 'expired_transient ' , 'cache_miss ' , 'input_hash_mismatch ' , 'hydratable_ref_missing ' ), true ) ) {
711+ return $ lookup_status ;
712+ }
704713
705714 if ( ! empty ( $ lookup ['invalidation ' ] ) ) {
706715 return 'incompatible ' ;
@@ -715,6 +724,10 @@ public function browser_contained_site_resolution( string $status, array $lookup
715724 if ( '' === $ reason ) {
716725 $ reason = match ( $ status ) {
717726 'recoverable_prepared_runtime ' => 'prepared-runtime-cache-hit ' ,
727+ 'expired_transient ' => 'expired-transient ' ,
728+ 'cache_miss ' => 'cache-miss ' ,
729+ 'input_hash_mismatch ' => 'input-hash-mismatch ' ,
730+ 'hydratable_ref_missing ' => 'hydratable-ref-missing ' ,
718731 'incompatible ' => 'prepared-runtime-incompatible ' ,
719732 'disabled ' => 'prepared-runtime-cache-disabled ' ,
720733 default => 'prepared-runtime-not-found-or-expired ' ,
@@ -734,8 +747,9 @@ public function browser_contained_site_resolution( string $status, array $lookup
734747 'reused ' => false ,
735748 'created ' => false ,
736749 'expired ' => 'miss ' === $ status ? null : false ,
737- 'miss ' => 'miss ' === $ status ,
738- 'incompatible ' => 'incompatible ' === $ status ,
750+ 'miss ' => in_array ( $ status , array ( 'miss ' , 'cache_miss ' ), true ),
751+ 'incompatible ' => in_array ( $ status , array ( 'incompatible ' , 'input_hash_mismatch ' ), true ),
752+ 'prepare_new_required ' => 'recoverable_prepared_runtime ' !== $ status ,
739753 ),
740754 static fn ( mixed $ value ): bool => null !== $ value && array () !== $ value && '' !== $ value
741755 );
@@ -840,7 +854,7 @@ public function browser_contained_site_facade_session( array $result, string $ac
840854 'schema ' => 'wp-codebox/browser-contained-site-session/v1 ' ,
841855 'action ' => $ action ,
842856 'contained_site ' => $ contained_site ,
843- 'boot ' => $ boot ,
857+ 'preview_boot ' => $ boot ,
844858 'preview_lease ' => $ preview_lease ,
845859 'startup_diagnostics ' => $ this ->browser_contained_site_startup_diagnostics ( $ result , $ contained_site , $ preview_lease , $ boot_contract ),
846860 'session ' => is_array ( $ result ['session ' ] ?? null ) ? $ result ['session ' ] : array (),
@@ -852,7 +866,7 @@ public function browser_contained_site_facade_session( array $result, string $ac
852866public function browser_contained_site_boot_descriptor ( array $ result , array $ contained_site , array $ preview_boot , array $ preview_lease , array $ blueprint_ref ): array {
853867 return array_filter (
854868 array (
855- 'schema ' => 'wp-codebox/browser-contained-site- boot/v1 ' ,
869+ 'schema ' => 'wp-codebox/browser-preview- boot-config /v1 ' ,
856870 'session_id ' => (string ) ( $ result ['session ' ]['session_id ' ] ?? $ result ['session ' ]['id ' ] ?? $ preview_boot ['session_id ' ] ?? '' ),
857871 'site_id ' => (string ) ( $ result ['site_id ' ] ?? $ contained_site ['site_id ' ] ?? '' ),
858872 'status ' => (string ) ( $ result ['status ' ] ?? $ contained_site ['status ' ] ?? '' ),
0 commit comments