@@ -361,6 +361,28 @@ namespace BML::Core {
361361 m_DiagCallback = std::move (callback);
362362 }
363363
364+ #if defined(BML_TEST)
365+ void ModuleRuntime::TestHandleHotReloadNotify (const std::string &mod_id, ReloadResult result,
366+ unsigned int version, ReloadFailure failure,
367+ ReloadRequestKind kind) {
368+ HandleHotReloadNotify (mod_id, result, version, failure, kind);
369+ }
370+
371+ void ModuleRuntime::TestBroadcastLifecycleEventForModule (const char *topic,
372+ const std::string &mod_id) const {
373+ BroadcastLifecycleEventForModule (topic, mod_id);
374+ }
375+
376+ std::vector<std::string> ModuleRuntime::TestGetLifecycleBroadcastTargets (
377+ const std::string &mod_id) const {
378+ std::vector<std::string> result;
379+ for (const auto &module : CollectLifecycleModulesForBroadcast (mod_id)) {
380+ result.push_back (module .id );
381+ }
382+ return result;
383+ }
384+ #endif
385+
364386 bool ModuleRuntime::ReloadModulesInternal (ModuleBootstrapDiagnostics &out_diag) {
365387 if (m_DiscoveredModsDir.empty ()) {
366388 out_diag.load_error .message = " Hot reload requested before discovery" ;
@@ -470,6 +492,35 @@ namespace BML::Core {
470492 }
471493 }
472494
495+ void ModuleRuntime::BroadcastLifecycleEventForModule (const char *topic,
496+ const std::string &mod_id) const {
497+ if (!m_Kernel || mod_id.empty ()) {
498+ return ;
499+ }
500+
501+ auto modules = CollectLifecycleModulesForBroadcast (mod_id);
502+ if (!modules.empty ()) {
503+ BroadcastLifecycleEvent (topic, modules);
504+ }
505+ }
506+
507+ std::vector<LoadedModuleSnapshot> ModuleRuntime::CollectLifecycleModulesForBroadcast (
508+ const std::string &mod_id) const {
509+ std::vector<LoadedModuleSnapshot> result;
510+ if (!m_Kernel || mod_id.empty ()) {
511+ return result;
512+ }
513+
514+ auto snapshot = m_Kernel->context ->GetLoadedModuleSnapshot ();
515+ for (const auto &module : snapshot) {
516+ if (module .id == mod_id && module .manifest ) {
517+ result.push_back (module );
518+ break ;
519+ }
520+ }
521+ return result;
522+ }
523+
473524 void ModuleRuntime::UpdateHotReloadRegistration () {
474525 if (!m_HotReloadEnabled || !m_HotReloadCoordinator)
475526 return ;
@@ -543,8 +594,9 @@ namespace BML::Core {
543594
544595 m_HotReloadCoordinator->SetNotifyCallback (
545596 [this ](const std::string &mod_id, ReloadResult result,
546- unsigned int version, ReloadFailure failure) {
547- HandleHotReloadNotify (mod_id, result, version, failure);
597+ unsigned int version, ReloadFailure failure,
598+ ReloadRequestKind kind) {
599+ HandleHotReloadNotify (mod_id, result, version, failure, kind);
548600 });
549601
550602 m_HotReloadCoordinator->Start ();
@@ -580,12 +632,12 @@ namespace BML::Core {
580632 }
581633
582634 // The ReloadableModuleSlot has already performed the DLL swap
583- // (UnloadCurrent → LoadVersion) including:
635+ // (UnloadCurrent -> LoadVersion) including:
584636 // - PrepareModuleForDetach gate (checks dependencies)
585637 // - DETACH entrypoint call
586638 // - CleanupModuleKernelState
587639 // - FreeLibrary old DLL
588- // - CopyDllToTemp → LoadLibrary new DLL
640+ // - CopyDllToTemp -> LoadLibrary new DLL
589641 // - ATTACH entrypoint call
590642 //
591643 // We just need to synchronize Context's loaded-module record
@@ -605,15 +657,28 @@ namespace BML::Core {
605657 return false ;
606658 }
607659
608- BroadcastLifecycleEvent (BML_TOPIC_SYSTEM_MOD_RELOAD , context. GetLoadedModuleSnapshot () );
660+ BroadcastLifecycleEventForModule (BML_TOPIC_SYSTEM_MOD_RELOAD , mod_id );
609661 CoreLog (BML_LOG_INFO , kModuleRuntimeLogCategory ,
610662 " Targeted hot reload of '%s' succeeded (version %u)" ,
611663 mod_id.c_str (), m_HotReloadCoordinator->GetModuleVersion (mod_id));
612664 return true ;
613665 }
614666
615667 void ModuleRuntime::HandleHotReloadNotify (const std::string &mod_id, ReloadResult result,
616- unsigned int version, ReloadFailure failure) {
668+ unsigned int version, ReloadFailure failure,
669+ ReloadRequestKind kind) {
670+ if (kind == ReloadRequestKind::FullRuntime) {
671+ ModuleBootstrapDiagnostics diag;
672+ if (ReloadModules (diag)) {
673+ CoreLog (BML_LOG_INFO , kModuleRuntimeLogCategory ,
674+ " Full hot reload succeeded for '%s'" , mod_id.c_str ());
675+ } else {
676+ CoreLog (BML_LOG_ERROR , kModuleRuntimeLogCategory ,
677+ " Full hot reload failed for '%s'" , mod_id.c_str ());
678+ }
679+ return ;
680+ }
681+
617682 if (result == ReloadResult::Success) {
618683 CoreLog (BML_LOG_INFO , kModuleRuntimeLogCategory ,
619684 " Hot reload notification: mod '%s' version %u, result=%d" ,
@@ -622,7 +687,7 @@ namespace BML::Core {
622687 // Try targeted single-module reload first (only updates Context state)
623688 ModuleBootstrapDiagnostics diag;
624689 if (ReloadSingleModule (mod_id, diag)) {
625- // Targeted reload succeeded — other modules were not disturbed
690+ // Targeted reload succeeded - other modules were not disturbed
626691 } else {
627692 // Fall back to full reload (e.g. module not found, Context sync failed)
628693 CoreLog (BML_LOG_WARN , kModuleRuntimeLogCategory ,
0 commit comments