@@ -4241,12 +4241,13 @@ def get_quantum_healing_context(self) -> dict:
42414241 }
42424242
42434243class omnipkg:
4244-
4244+
42454245 def __init__(self, config_manager: ConfigManager, minimal_mode: bool = False):
42464246 """
42474247 Initializes Omnipkg with optional minimal mode for lightweight commands.
42484248
42494249 Args:
4250+ config_manager: The configuration manager instance.
42504251 minimal_mode: If True, skips database/cache initialization for commands
42514252 that only need config access (swap, version, etc.)
42524253 """
@@ -4257,64 +4258,62 @@ def __init__(self, config_manager: ConfigManager, minimal_mode: bool = False):
42574258 if not self.config:
42584259 if len(sys.argv) > 1 and sys.argv[1] in ['reset-config', 'doctor']:
42594260 pass
4260- else:
4261- raise RuntimeError('OmnipkgCore cannot initialize: Configuration is missing or invalid.')
4262-
4263- # 🎯 CRITICAL FIX: Set these IMMEDIATELY like multiversion_base
4264- # These are used by check_package_installed_fast during preflight
4265- self.env_id = self._get_env_id()
4266- self.multiversion_base = Path(self.config['multiversion_base'])
4267- self.site_packages_root = Path(self.config['site_packages_path']) # 🎯 ADD THIS!
4268-
4269- # Minimal initialization for lightweight commands
4270- if minimal_mode:
4271- self.interpreter_manager = InterpreterManager(self.config_manager)
4272- safe_print(_('✅ Omnipkg core initialized (minimal mode).'))
4273- return # EXIT EARLY
4274- self._self_heal_omnipkg_installation()
4261+ elif not minimal_mode:
4262+ raise RuntimeError('OmnipkgCore cannot initialize: Configuration is missing or invalid.')
4263+
4264+ # --- CORE ATTRIBUTES (Needed early) ---
42754265 self.env_id = self._get_env_id()
42764266 self.multiversion_base = Path(self.config['multiversion_base'])
4277- self.cache_client = None
4278- self._cache_connection_status = None
4279- self.initialize_pypi_cache()
4280- self._check_and_run_pending_rebuild()
4267+ self.site_packages_root = Path(self.config['site_packages_path'])
42814268 self._info_cache = {}
4282- self._prime_loader_cache()
42834269 self._installed_packages_cache = None
42844270 self.http_session = http_requests.Session()
4285- self.multiversion_base.mkdir(parents=True, exist_ok=True)
4271+ self.cache_client = None
4272+ self._cache_connection_status = None
4273+
4274+ # --- PHASE 1: INITIALIZE MANAGERS ---
4275+ # These are needed by almost all commands, including minimal ones.
4276+ self.interpreter_manager = InterpreterManager(self.config_manager)
4277+
4278+ # Minimal mode exits here. Commands like 'swap' or 'list python' now have what they need.
4279+ if minimal_mode:
4280+ safe_print(_('✅ Omnipkg core initialized (minimal mode).'))
4281+ return
4282+
4283+ # --- PHASE 2: FULL INITIALIZATION FOR HEAVY COMMANDS ---
4284+ # Connect to the cache (Redis or SQLite)
42864285 if not self._connect_cache():
42874286 sys.exit(1)
4288- # --- ADD THE MIGRATION LOGIC HERE ---
4289- # V2 MIGRATION: Automatically upgrade legacy global keys to be environment-aware.
4290- migration_flag_key = f'omnipkg:env_{self.env_id}:migration_v2_env_aware_keys_complete'
4291-
4292- # We check the flag *before* the expensive scan.
4293- if not self.cache_client.get(migration_flag_key):
4294- # Check if there are any old keys that *need* migrating.
4295- # We use scan_iter for performance, only needing to find one key.
4296- old_keys_iterator = self.cache_client.scan_iter('omnipkg:pkg:*', count=1)
4297- if next(old_keys_iterator, None):
4298- self._perform_redis_key_migration(migration_flag_key)
4299- else:
4300- # No old keys found, so we can just set the flag.
4301- self.cache_client.set(migration_flag_key, 'true')
4302- # --- END MIGRATION LOGIC ---
4303- self.interpreter_manager = InterpreterManager(self.config_manager)
4304- self.hook_manager = ImportHookManager(str(self.config.get('multiversion_base')), config=self.config, cache_client=None)
4305- self.bubble_manager = BubbleIsolationManager(self.config, self)
43064287
4288+ # Now that we have a cache, initialize other managers that depend on it.
4289+ self.hook_manager = ImportHookManager(str(self.config.get('multiversion_base')), config=self.config, cache_client=self.cache_client)
4290+ self.bubble_manager = BubbleIsolationManager(self.config, self) # <-- CRITICAL: Now exists before rebuild
4291+
4292+ # --- PHASE 3: POST-INITIALIZATION AND SELF-HEALING ---
4293+ # These tasks may depend on the fully initialized managers.
4294+ self._self_heal_omnipkg_installation()
4295+ self.initialize_pypi_cache()
4296+
4297+ # Run database migrations
43074298 migration_flag_key = f'omnipkg:env_{self.env_id}:migration_v2_env_aware_keys_complete'
43084299 if not self.cache_client.get(migration_flag_key):
43094300 old_keys_iterator = self.cache_client.scan_iter('omnipkg:pkg:*', count=1)
43104301 if next(old_keys_iterator, None):
43114302 self._perform_redis_key_migration(migration_flag_key)
43124303 else:
43134304 self.cache_client.set(migration_flag_key, 'true')
4305+
43144306 migration_v3_flag_key = f'{self.redis_env_prefix}migration_v3_install_type_complete'
43154307 if not self.cache_client.get(migration_v3_flag_key):
43164308 self._perform_v3_metadata_migration(migration_v3_flag_key)
43174309
4310+ # Proactively build the loader cache if needed.
4311+ self._prime_loader_cache()
4312+
4313+ # CRITICAL: Run the pending rebuild check LAST, after everything is initialized.
4314+ self._check_and_run_pending_rebuild()
4315+
4316+ # Finally, load the import hooks.
43184317 self.hook_manager.load_version_map()
43194318 self.hook_manager.install_import_hook()
43204319 safe_print(_('✅ Omnipkg core initialized successfully.'))
0 commit comments