Skip to content

v1.12.0

Choose a tag to compare

@github-actions github-actions released this 11 May 16:36
· 17 commits to master since this release

Исправлено

  • Issue #14: видимость объектов и модулей расширений из main-сессии.
    • find_module / find_by_type теперь возвращают модули из соседних расширений (../cfe/... относительные пути) когда сессия открыта на main конфигурации.
    • find_attributes / find_predefined / parse_object_xml резолвят как объекты с .bsl модулями, так и XML-only объекты расширения (Subsystems, EventSubscriptions, ChartsOfCharacteristicTypes без <Synonym>).
    • search_methods / search_objects / search_regions / search_module_headers (и unified search()) дополняют индексные результаты live-данными из расширений; shape результата зеркалит IndexReader (rank=None для методов, prefixed Категория: Синоним для объектов). search_objects("") (alphabetical listing — публичный контракт IndexReader) тоже включает ext-синонимы.
    • find_attributes(name=...) / find_predefined(name=...) name-only (без object_name) сканируют _extension_metadata_xml после того как индекс возвращает [] — раньше name-only был index-authoritative и пропускал ext. То же поведение для search(query, scope="attributes"|"predefined").
    • read_procedure(ext_path, name) / extract_procedures(ext_path) принимают пути с префиксом ../cfe/... и читают расширение внутренне (через _ext_resolve_safe + _ext_read_file, multi-root). find_callers_context / find_register_writers / find_custom_modifications / analyze_document_flow (ObjectModule + ManagerModule) / safe_grep / extract_queries / code_metrics теперь тоже используют _ext_read_file для путей из _index_state — раньше read падал с PermissionError (silent skip), и ext-файлы попадали в prefilter, но не в финальный результат.
    • Sandbox-инвариант сохраняется: пользовательский read_file('../cfe/...') / grep / glob_files по-прежнему PermissionError. Видимость расширений добавлена только в high-level BSL-хелперы.
  • Multi-line процедуры/функции (Процедура X(a,\n b,\n c)): extract_procedures / read_procedure / индексер (bsl_index._parse_procedures_from_lines) теперь корректно находят и возвращают line/end_line. Логика — новый общий util bsl_knowledge._merge_proc_continuations, склеивающий продолжения сигнатуры в одну логическую строку с учётом строковых литералов и hard-cap (20 строк / 2000 символов).
  • Opportunistic live-fill в extract_procedures для индексированных путей: если индекс пропустил multi-line процедуру (старый builder), live-парсер дополняет результат с тем же shape, включая enrichment overridden_by из индекса. Кейс закрывается сразу после обновления пакета — без обязательного rlm-bsl-index index update.

Изменено

  • Sandbox.__init__(extension_paths=...) — новый kwarg для проброса абсолютных путей соседних расширений (только при current.role == MAIN). Передаётся в make_bsl_helpers(extension_paths=...); в make_helpers(...) НЕ пробрасывается — generic-хелперы остаются strict base-only.
  • make_bsl_helpers(extension_paths=...) — новая опциональная side-структура: _extension_paths_set, _extension_root_for, _extension_metadata_xml (locator для всех XML/MDO ext-объектов вкл. без synonym), _extension_synonyms (синонимы с RU-префиксом для search_objects). _ensure_index рефакторен на _load_main_into_index_state() + _load_extensions_into_index_state() — extension pass всегда после main (важно для индексных main-сессий).
  • bsl_index._collect_object_synonyms рефакторен на общий path-scan bsl_index._iter_metadata_xml_files (тот же layout-discovery: CF Cat/Obj/Ext/<Type>.xml → CF sibling Cat/Obj.xml → CF sibling-only для EventSubscriptions → EDT Cat/Obj/Obj.mdo → Subsystems recursive). DRY-инвариант: bsl_helpers extension pass и indexer видят один и тот же набор файлов.
  • Стратегия Step 5 EXTENSIONS обновлена синхронно в slim (STRATEGY_SECTIONS["workflow"]), full (_STRATEGY_HEADER), динамическом блоке _extension_strategy, рецепте расширения в _BUSINESS_RECIPES и NOTE рецепта get_overrides: явное указание что read_file/grep/glob_files на '../' дают PermissionError, но high-level helpers (read_procedure, extract_procedures, parse_object_xml, find_attributes, find_predefined, search) принимают пути расширений напрямую.
  • _resolve_object_xml вынесен общий helper _xml_candidates(object_name); вызывает _ensure_index() в начале — чтобы прямой parse_object_xml('Catalogs/ExtOnly') (минуя find_module) тоже находил ext-кандидаты.
  • find_attributes / find_predefined получили auto-resolve через _resolve_object_name_from_extension_metadata(object_name) — возвращает канонический (cat, "cat/Name") из _extension_metadata_xml, защищая от case-mismatch между аргументом и metadata.
  • Soft warning при extension pass с >5000 BSL-файлов (без обрезания).
  • _live_search_objects поддерживает пустой query (alphabetical listing по (category, object_name) — паритет с IndexReader.search_objects("")); поле _live_attributes_in_extensions/_live_predefined_in_extensions итерируют _extension_metadata_xml и делегируют в существующую per-object ветку find_attributes/find_predefined через parse_metadata_xml + _ext_read_file. find_attributes/find_predefined вызывают _ensure_index() в начале при наличии настроенных extension_paths — чтобы name-only path получил готовый _extension_metadata_xml (cheap idempotent call).
  • Поле source_file в live-rows find_attributes/find_predefined — теперь возвращается путь к ext XML (source_file=resolved для атрибутов, source_file=candidate_path для предопределённых). Без этого search(query, scope="attributes"|"predefined") мапил path=row.get("source_file","") в пустую строку, и AI-агент не мог навигировать к ext-файлу.
  • search_objects merge BEFORE truncation — раньше после индексного результата проверялся len(result) < limit, и на saturated main индексе (50+ синонимов) ext-строки теряли все слоты. Теперь ext всегда добавляются в полный merge, потом slice. Для empty-query (alphabetical listing) merged-set пересортируется по (category, object_name), чтобы ext-объекты с алфавитно-ранними именами появились в результате (паритет с IndexReader.search_objects("") ORDER BY ... LIMIT). Для substring-search применяется тот же 4-уровневый ранкинг что и в IndexReader.search_objects (exact object_name → prefix → synonym substring → category fallback): merge index+ext → re-rank всё → sort (rank, category, object_name) → slice. Это значит ext-объект с точным совпадением имени (rank=0) занимает слот в топ-50 даже если main вернул 50 rank-2 совпадений по синониму (codex round 3).
  • _live_search_objects full-scan для non-empty query (codex round 4) — убран early-break на limit для substring-поиска. Раньше при 60+ ext-объектах с совпадением по синониму exact-name match на 60-й позиции в скан-порядке терялся ДО reranking'а в search_objects. Теперь, как и IndexReader.search_objects (см. явный комментарий в bsl_index.py:7003-7005 — "No SQL LIMIT — Python ranking needs ALL matches to guarantee exact name (rank 0) is never lost"), live сканирует ВСЕ ext-синонимы, отдаёт их в search_objects, а 4-уровневый ранкер слайсит правильно. Empty-query путь сохраняет alphabetical-sort-then-slice как раньше.
  • Anti-starvation merge для всех остальных search_ и find_attrs/find_predefined (codex round 5)* — search_methods / search_regions / search_module_headers и name-only ветки find_attributes / find_predefined имели тот же len(result) < limit guard, что был во втором раунде в search_objects. На индексах с насыщенным main результатом ext live-данные дропались. Введены два общих хелпера в замыкании make_bsl_helpers:
    • _rank_merge_ext_into_main(main, ext, query, name_keys, dedup_keys, limit) — 3-уровневый ранк по списку name_keys (round 6): row получает BEST (lowest) ранк среди всех перечисленных полей. Это зеркалит контракт IndexReader.get_object_attributes (фильтр attr_name OR attr_synonym) и get_predefined_items (item_name OR item_synonym) — ext row, нашедшийся по русскому синониму, теперь тоже может получить rank 0 (exact) / 1 (prefix) и попасть в верх merge'а вместо rank-2 хвоста. Применён в search_methods (("name",)), search_regions (("name",)), find_attributes (("attr_name", "attr_synonym")), find_predefined (("item_name", "item_synonym")).
    • _reserve_merge_ext_into_main(main, ext, dedup_keys, limit, quota_ratio=5) — для хелперов без явного name-поля (search_module_headers): резервирует min(len(ext), max(1, limit // 5)) слотов под ext, обрезая хвост main. Это даёт ext visibility на любых saturation-условиях.
  • Full-scan live helpers (без early break)_live_search_methods, _live_search_regions, _live_search_module_headers, _live_attributes_in_extensions, _live_predefined_in_extensions теперь сканируют все ext-файлы/метаданные без раннего обрезания. Per-object find_attributes/find_predefined внутри _live_attributes_in_extensions/_live_predefined_in_extensions вызываются с limit=max(limit, 1000) чтобы исключить per-object truncation. Slice выполняется только на верхнем уровне в merge-хелперах.

Тесты

  • Новые: tests/test_helpers_extension.py (find_module/find_by_type/find_attributes/find_predefined/parse_object_xml для CF ext с bare-name resolve, case-insensitive, sandbox security, регрессия overrides + main-only без расширений), tests/test_search_extension.py (live-fallback в search_* с проверкой shape ключей и XML-only объектов), tests/test_parse_multiline_signature.py (merge_continuations + indexer + live parser + live-fill в extract_procedures с overrides enrichment).
  • Расширен tests/test_strategy_data.py: добавлены ассерты что фраза про high-level helpers и PermissionError присутствует и в slim, и в full Step 5, и в _extension_strategy, и в рецепте расширения.

Обратная совместимость

  • BUILDER_VERSION = 12 — без bump. Существующие индексы рабочие; для подхвата индексных multi-line методов после рестарта достаточно rlm-bsl-index index update, но это опционально (live-fill закрывает кейс сразу).
  • Sandbox(...) без extension_paths (как и make_bsl_helpers(...) без extension_paths) ведут себя как раньше: extension visibility отключена, sandbox base-only.

Полный список изменений: CHANGELOG.md