diff --git a/data-machine.php b/data-machine.php index fc9167ce..202085c7 100644 --- a/data-machine.php +++ b/data-machine.php @@ -243,6 +243,20 @@ function () { new \DataMachine\Abilities\Handler\TestHandlerAbility(); } ); + // Deferred scaffold: during plugin activation the Abilities API is unavailable + // because init fires before the plugin file is included. A transient signals that + // the scaffold needs to run on the first normal request where abilities are ready. + add_action( + 'init', + function () { + if ( get_transient( 'datamachine_needs_scaffold' ) ) { + delete_transient( 'datamachine_needs_scaffold' ); + datamachine_ensure_default_memory_files(); + } + }, + 20 // After ability registration (priority 10). + ); + // Clean up identity index rows when posts are permanently deleted. add_action( 'before_delete_post', @@ -543,7 +557,13 @@ function datamachine_activate_for_site() { \DataMachine\Core\Database\Chat\Chat::ensure_agent_id_column(); // Ensure default agent memory files exist. - datamachine_ensure_default_memory_files(); + // During activation the Abilities API is unavailable (init already fired before + // the plugin was included via plugin_sandbox_scrape, so our init callback that + // registers abilities never ran). Set a transient so the scaffold runs on the + // first normal request where the full hook sequence fires in order. + if ( ! datamachine_ensure_default_memory_files() ) { + set_transient( 'datamachine_needs_scaffold', 1, HOUR_IN_SECONDS ); + } // Run layered architecture migration (idempotent). datamachine_migrate_to_layered_architecture(); diff --git a/inc/migrations.php b/inc/migrations.php index 3467b6a4..17bb3039 100644 --- a/inc/migrations.php +++ b/inc/migrations.php @@ -1078,12 +1078,17 @@ function datamachine_copy_directory_recursive( string $source_dir, string $targe * (via DirectoryManager::ensure_agent_files()). Existing files are never * overwritten — only missing files are recreated from scaffold defaults. * + * Returns false when the Abilities API is unavailable (e.g. during plugin + * activation where init callbacks haven't fired), so the caller can defer. + * * @since 0.30.0 + * + * @return bool True if scaffold ran, false if abilities were unavailable. */ -function datamachine_ensure_default_memory_files() { +function datamachine_ensure_default_memory_files(): bool { $ability = \DataMachine\Abilities\File\ScaffoldAbilities::get_ability(); if ( ! $ability ) { - return; + return false; } $default_user_id = \DataMachine\Core\FilesRepository\DirectoryManager::get_default_agent_user_id(); @@ -1093,6 +1098,8 @@ function datamachine_ensure_default_memory_files() { // Scaffold default context memory files (contexts/{context}.md). datamachine_ensure_default_context_files( $default_user_id ); + + return true; } /**