## ADDED Requirements ### Requirement: Сущности ядра DI Ядро DI MUST определять сущности `Scope`, `Module`, `Binding`, `BindingResolver`, `Disposable`, `CherryPickObserver` и их роли. #### Scenario: Декларация базовых сущностей - **WHEN** разработчик использует публичный API ядра - **THEN** сущности `Scope`, `Module`, `Binding`, `Disposable`, `CherryPickObserver` доступны и описывают контракт DI ### Requirement: Жизненный цикл Scope `Scope` MUST поддерживать жизненный цикл открытия, использования и корректного закрытия с освобождением ресурсов. #### Scenario: Открытие root scope - **WHEN** вызывается открытие root scope - **THEN** создается корневой контейнер для регистраций и резолва #### Scenario: Открытие named subscope - **WHEN** открывается именованный subscope - **THEN** subscope наследует bindings родителя и может переопределять зависимости #### Scenario: Закрытие subscope - **WHEN** вызывается закрытие subscope - **THEN** subscope удаляется из дерева, а связанные ресурсы освобождаются #### Scenario: Путь scope и разделитель - **WHEN** scope открывается по иерархическому пути с разделителем - **THEN** создается цепочка subscopes по каждому сегменту пути #### Scenario: Пустой scopeName - **WHEN** scope открывается с пустым именем - **THEN** возвращается root scope ### Requirement: Установка и удаление модулей `Scope` MUST поддерживать установку и удаление `Module`, а их bindings MUST становиться доступными сразу после установки. #### Scenario: Установка модуля - **WHEN** модуль установлен в scope - **THEN** его bindings доступны для resolve/tryResolve #### Scenario: Сброс модулей - **WHEN** модули сброшены - **THEN** bindings модулей не доступны для резолва в этом scope ### Requirement: Типы bindings `Binding` MUST поддерживать прямые инстансы, синхронные провайдеры, асинхронные провайдеры и провайдеры с параметрами, а также именованные bindings. #### Scenario: Именованные bindings - **WHEN** зарегистрированы два bindings одного типа с разными именами - **THEN** resolve с указанным именем возвращает соответствующую реализацию #### Scenario: Параметризованный provider - **WHEN** binding зарегистрирован с провайдером, принимающим параметры - **THEN** resolve с параметрами использует переданные аргументы для создания экземпляра ### Requirement: Семантика резолва и fallback Резолв MUST искать зависимость в текущем scope и, при отсутствии, подниматься к родительским scope. #### Scenario: Fallback к родителю - **WHEN** зависимость отсутствует в текущем scope, но есть в родительском - **THEN** резолв выполняется через родительский binding ### Requirement: Синхронный и асинхронный резолв `Scope` MUST предоставлять синхронный и асинхронный резолв и их nullable‑варианты. #### Scenario: Resolve (sync) - **WHEN** вызывается `resolve()` для существующей зависимости - **THEN** возвращается экземпляр или выбрасывается ошибка при отсутствии #### Scenario: TryResolve (sync) - **WHEN** вызывается `tryResolve()` для отсутствующей зависимости - **THEN** возвращается `null` без исключения #### Scenario: Resolve (async) - **WHEN** вызывается `resolveAsync()` для зависимости с async‑провайдером - **THEN** возвращается `Future` с экземпляром #### Scenario: TryResolve (async) - **WHEN** вызывается `tryResolveAsync()` для отсутствующей зависимости - **THEN** возвращается `null` без исключения ### Requirement: Ошибки несоответствия sync/async Резолв MUST выбрасывать ошибки при несоответствии sync/async режима. #### Scenario: ResolveSync для async‑инстанса - **WHEN** binding зарегистрирован как async‑инстанс или async‑provider, а вызывается `resolveSync` - **THEN** выбрасывается ошибка с указанием использовать async‑резолв ### Requirement: Управление Disposable `Scope` MUST отслеживать экземпляры, реализующие `Disposable`, и вызывать `dispose()` при закрытии scope. #### Scenario: Автоматическое освобождение - **WHEN** scope закрывается - **THEN** все `Disposable` в scope и дочерних scope освобождаются ### Requirement: Детекция циклов зависимостей Ядро DI MUST поддерживать локальную и глобальную детекцию циклов. #### Scenario: Локальный цикл - **WHEN** локальная детекция включена и резолв обнаруживает цикл - **THEN** резолв завершается ошибкой цикла #### Scenario: Глобальный цикл - **WHEN** глобальная детекция включена и цикл пересекает scope - **THEN** резолв завершается ошибкой цикла ### Requirement: Наблюдатель событий (Observer) Ядро DI MUST предоставлять наблюдателя, получающего события регистрации, резолва, ошибок, lifecycle и диагностики. #### Scenario: События lifecycle - **WHEN** scope открывается, модули устанавливаются и зависимости резолвятся - **THEN** observer получает соответствующие уведомления ### Requirement: Ошибки и сообщения об ошибках При критических сбоях резолва ядро MUST выбрасывать ошибку с понятным сообщением, а для tryResolve MUST не бросать исключения. #### Scenario: Ошибка отсутствующей зависимости - **WHEN** вызывается `resolve()` для незарегистрированной зависимости - **THEN** выбрасывается ошибка с сообщением о невозможности резолва #### Scenario: Ошибка цикла - **WHEN** обнаружен цикл зависимостей - **THEN** выбрасывается ошибка с указанием цепочки #### Scenario: Отсутствующие параметры для параметризованного binding - **WHEN** binding зарегистрирован с `toProvideWithParams`, но резолв вызывается без `params` - **THEN** выбрасывается ошибка о необходимости передать параметры ### Requirement: Точки расширения Ядро DI MUST предоставлять точки расширения через пользовательский `Module` и `CherryPickObserver`. #### Scenario: Пользовательский Module - **WHEN** разработчик создает свой `Module` - **THEN** он может зарегистрировать bindings и контролировать регистрацию #### Scenario: Пользовательский Observer - **WHEN** разработчик передает кастомный observer - **THEN** он получает все DI‑события и может интегрировать внешние логеры/метрики