@@ -532,6 +532,18 @@ function () use ($projectRoot, $ddlessDirectory, &$__ddless_cake_error) {
532532// CLI mode (DDLess direct request): manual bootstrap, capture response, snapshot.
533533// ═══════════════════════════════════════════════════════════════════════════════
534534
535+ $ breakpoints = ddless_read_breakpoints ($ ddlessDirectory );
536+ $ executionStartedAt = microtime (true );
537+
538+ // Register stream wrapper BEFORE autoload — same order as proxy mode.
539+ // The wrapper must be active when Composer's autoloader is set up so that
540+ // all subsequent include/require calls go through it.
541+ if (getenv ('DDLESS_DEBUG_MODE ' ) === 'true ' ) {
542+ if (function_exists ('ddless_register_stream_wrapper ' )) {
543+ ddless_register_stream_wrapper ();
544+ }
545+ }
546+
535547require_once $ projectRoot . '/vendor/autoload.php ' ;
536548
537549$ bootstrapFile = $ projectRoot . '/config/bootstrap.php ' ;
@@ -544,8 +556,6 @@ function () use ($projectRoot, $ddlessDirectory, &$__ddless_cake_error) {
544556 exit (1 );
545557}
546558
547- $ breakpoints = ddless_read_breakpoints ($ ddlessDirectory );
548- $ executionStartedAt = microtime (true );
549559$ logDir = defined ('LOGS ' ) ? LOGS : $ projectRoot . DIRECTORY_SEPARATOR . 'logs ' ;
550560
551561$ phpWrapperReplaced = false ;
@@ -559,12 +569,10 @@ function () use ($projectRoot, $ddlessDirectory, &$__ddless_cake_error) {
559569 }
560570}
561571
562- if (getenv ('DDLESS_DEBUG_MODE ' ) === 'true ' ) {
563- $ debugModule = dirname (__DIR__ , 2 ) . '/debug.php ' ;
564- if (file_exists ($ debugModule )) {
565- require_once $ debugModule ;
566- if (function_exists ('ddless_register_stream_wrapper ' )) {
567- ddless_register_stream_wrapper ();
572+ if (getenv ('DDLESS_DEBUG_MODE ' ) === 'true ' && !empty ($ GLOBALS ['__DDLESS_INSTRUMENTED_CODE__ ' ])) {
573+ foreach (array_keys ($ GLOBALS ['__DDLESS_INSTRUMENTED_CODE__ ' ]) as $ instrumentedPath ) {
574+ if (is_file ($ instrumentedPath ) && str_ends_with ($ instrumentedPath , '.php ' )) {
575+ include_once $ instrumentedPath ;
568576 }
569577 }
570578}
@@ -576,6 +584,21 @@ function () use ($projectRoot, $ddlessDirectory, &$__ddless_cake_error) {
576584 $ app ->bootstrap ();
577585 $ app ->pluginBootstrap ();
578586
587+ // Server::run() always calls bootstrap() internally, which would re-load
588+ // plugins (DebugKit) and crash. This subclass guards against double bootstrap.
589+ $ server = new class ($ app ) extends \Cake \Http \Server {
590+ private bool $ __bootstrapped = false ;
591+ protected function bootstrap (): void {
592+ if ($ this ->__bootstrapped ) return ;
593+ parent ::bootstrap ();
594+ $ this ->__bootstrapped = true ;
595+ }
596+ public function skipBootstrap (): void {
597+ $ this ->__bootstrapped = true ;
598+ }
599+ };
600+ $ server ->skipBootstrap ();
601+
579602 $ request = \Cake \Http \ServerRequestFactory::fromGlobals ();
580603
581604 if (!empty ($ _FILES ) && class_exists ('Laminas\Diactoros\UploadedFile ' )) {
@@ -612,7 +635,6 @@ function () use ($projectRoot, $ddlessDirectory, &$__ddless_cake_error) {
612635 }
613636 }
614637
615- $ server = new \Cake \Http \Server ($ app );
616638 $ response = $ server ->run ($ request );
617639
618640 $ statusCode = $ response ->getStatusCode ();
0 commit comments