v1.12.0
Исправлено
- 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(и unifiedsearch()) дополняют индексные результаты 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. Логика — новый общий utilbsl_knowledge._merge_proc_continuations, склеивающий продолжения сигнатуры в одну логическую строку с учётом строковых литералов и hard-cap (20 строк / 2000 символов). - Opportunistic live-fill в
extract_proceduresдля индексированных путей: если индекс пропустил multi-line процедуру (старый builder), live-парсер дополняет результат с тем же shape, включая enrichmentoverridden_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-scanbsl_index._iter_metadata_xml_files(тот же layout-discovery: CFCat/Obj/Ext/<Type>.xml→ CF siblingCat/Obj.xml→ CF sibling-only для EventSubscriptions → EDTCat/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-rowsfind_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_objectsmerge 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_objectsfull-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) < limitguard, что был во втором раунде в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