v1.10.0
Добавлено
get_object_full_structure(name)— агрегирующий хелпер: метаданные + ТЧ + реквизиты + предопределённые + раскрытые перечисления + список форм за один вызов вместо 3-5. Заменяет цепочкуparse_object_xml + find_attributes + find_predefined + find_enum_values. Работает поверх существующих таблицobject_attributes,predefined_items,object_synonyms,enum_values,form_elements. При отсутствии индекса — fallback на live XML с пометкой_meta.index_used=False(в этом режиме доступны синонимы ТЧ, не индексируемые в v12). Закрывает сценарий D1 из e2e-тестов 2026-04.find_call_hierarchy(name, direction='callers', depth=1..3)— транзитивные вызывающие 2-3 уровня в одном вызове (вместо итерацииfind_callers_context). Использует существующийidx_calls_callee(без bump индекса).direction='callees'/'both'пока не поддержано — возвращает структурированный error-dict с hint, без traceback. Закрывает D2 (частично).- Anti-duplicate detection в
Sandbox._wrap_helpers— session-wide: при повторном вызове хелпера с идентичными аргументами в ответеrlm_executeпоявляется секцияduplicates: [{call: seq, prev_call: seq, helper: name}]. Cross-execute дубли тоже видны — состояние не обнуляется на каждыйexecute(). Возвращаемые значения хелперов не меняются. Закрывает C3. is_postablehint вfind_register_movements— при пустом итоговом результате (code_registers + erp_mechanisms + manager_tables + adapted_registers == []) helper делает live-чтениеDocument.postingчерезparse_object_xmlи приPosting=Denyвозвращаетis_postable: false+hint.UseSelectivelyНЕ помечается непроводимым. Закрывает B1.parse_metadata_xmlрасширен на извлечение атрибутаpostingдля документов (CF child-tag<Posting>+ EDT attributeposting=).event_filter+limitвfind_event_subscriptions— при заданномlimitвозврат становится top-level dict{subscriptions, total, returned, has_more}; defaultlimit=Noneсохраняет прежний контрактlist[dict]. Серверная SQL-фильтрация поeventчерезIndexReader.get_event_subscriptions(event_filter=...). Закрывает C1.- 2 новых BR-домена:
«перечисления»,«ввод на основании»,«структура объекта». Расширен домен«ссылки»(find_defined_types). 18+ новых алиасов (движения,проводки,posting,макеты,печатные формы,enum,статусы,карточка объекта,формы,register movementsи др.). bsl_helpbridge к_BUSINESS_RECIPES/_RECIPE_ALIASES—help('движения'),help('как проводится документ'),help('структура объекта')и т.п. теперь возвращают рецепты доменов (не только helper-recipes).- Recipes для
find_register_writers,detect_extensions,find_ext_overrides,get_object_full_structure,find_call_hierarchy. Расширены recipesfind_attributes,find_predefined,get_index_info,read_procedure. Уfind_callersтеперь явно прописан компактный режим (3 поля vs 7 уfind_callers_context, идентичный поиск под капотом) — добавлена пара в DISAMBIGUATION + recipe. - DISAMBIGUATION-секция в strategy:
get_object_full_structurevsanalyze_object,find_call_hierarchyvsfind_callers_context,find_register_movementsvsfind_register_writers/analyze_document_flow,parse_object_xmlvsfind_attributes,searchvssearch_X,read_procedure±include_overrides.
Изменено
_resolve_object_xml— жёсткая проверка пути с нормализацией base. При несуществующем.mdo/.xmlпути сначала отрезает расширение и пробует кандидаты для нормализованного base (<base>/<seg>.mdo,<base>/Ext/<XML>.xml,<base>.xml,<base>.mdo, glob). Раньше возвращался AS-IS — мусорныеDocuments/X.mdo/X.mdo.mdoмогли строиться через старую ветку. Теперь FileNotFoundError содержит явную подсказку про директорию. Закрывает A1.- Sandbox
_add_error_hints— добавлены ветки дляread_procedure(XML-only объекты вроде КОДСобытия + подсказка проextract_procedures(path)) и расширенный hint дляparse_object_xml(фейковые.mdo-пути авто-нормализуются). Закрывает A2/A3. - Step 4 ANALYZE в стратегии расширен с разбивкой INSTANT (
find_register_writers,find_register_movements,find_event_subscriptions,find_scheduled_jobs,find_roles,find_defined_types,find_enum_values,get_object_full_structure) / HYBRID (find_functional_options) / LIVE (find_based_on_documents,find_print_forms,analyze_object,analyze_document_flow). - Step 0 UNDERSTAND переписан: «If a BUSINESS RECIPE section appears below — follow it. No recipe? → analyze_subsystem».
- Step 2 READ — добавлено уточнение по контракту
read_procedure: «str | None. None = имя неточное или у объекта только XML — звониextract_procedures(path).» - Step 3 TRACE — добавлен
find_call_hierarchy(name, direction='callers', depth=2). - Recipe-рецепт
проведение— добавлен шагпроверить is_postable+event_filterдля подписок +find_call_hierarchy('ОбработкаПроведения', depth=2). - Server
rlm_executedocstring — упрощён, убрано устаревшее перечисление хелперов. Полный список агент получает вrlm_start.strategyчерезbuild_helpers_table(динамика). Удалён мёртвыйRLM_EXECUTE_DESCRIPTIONизbsl_knowledge.py.
Обратная совместимость
- Индекс не меняется (BUILDER_VERSION=12 как в v1.9.x) — миграция не требуется, fresh build не нужен.
find_event_subscriptionsбезlimit(default) сохраняет прежнийlist[dict]контракт. Top-level dict — только при явно заданномlimit.read_procedureосталсяstr | None.find_register_movementsвсегда возвращает поляcode_registers/modules_scanned/...; новыеis_postable/posting/hintпоявляются только при пустом результате для непроводимого документа.find_callersостался — внутренняя логика поиска не менялась (та же обёртка надfind_callers_context, идентичные fast path и FS-fallback). В реестре теперь позиционируется как «compact mode» того же поиска.
Перенесено в parking lot (требует bump индекса в следующем релизе)
parse_formрасширения (FormParameters, DataPath, иерархия элементов).find_register_writersрасширение наRegisterRecords.X.Add()/СоздатьНаборЗаписей().find_call_hierarchy(direction='callees'/'both')— упирается в отсутствиеidx_calls_caller(осознанно вырезан ради -56 МБ на ERP).
Исправлено после второго прогона e2e (Тест ДО3 fix, 2026-05-02)
- BUG-8 (MEDIUM) —
find_event_subscriptions(event_filter='string')молча игнорировал фильтр. Сигнатураlist[str]не enforced, Python итерировал голую строку посимвольно ('BeforeWrite' → ['B','e','f',...]), и каждый одно-символьный substring-matcher ловил почти все события — фильтр де-факто отключался (на тестовом проекте: 95 подписок с 14 разными events). Защитная нормализация в двух точках:bsl_helpers.find_event_subscriptionsиIndexReader.get_event_subscriptions— голая строка автоматически оборачивается в[строка], пустая строка трактуется какNone(без фильтра). Сигнатура расширена доlist[str] | str | None. Recipe и DISAMBIGUATION обновлены: указано чтоlist[str]рекомендован, но строка теперь тоже принимается. - BUG-9 (LOW) —
find_based_on_documentsнаходит только прямые связи, упуская обратный обход. Хелпер парсил толькоManagerModule.ДобавитьКомандыСозданияНаОснованиииObjectModule.ОбработкаЗаполнениясамого документа. Для документов без этих процедур (типичный кейс — Письма: уВходящееПисьмонет команд создания, ноЗадача/ПоручениедекларируютДокументСсылка.ВходящееПисьмов своихОбработкаЗаполнения)can_create_from_hereоставался пустым. Добавлен обратный обход (lazy fallback, срабатывает только если прямой обход дал пустойcan_create_from_here): черезglob_files('Documents/*/Ext/ObjectModule.bsl')сканируются ObjectModule других документов, регекспДокументСсылка.<doc_name>ищется вОбработкаЗаполнения, найденные документы добавляются вcan_create_from_hereс маркеромvia='back_scan'. Прямые записи остаются без этого поля (контракт не сломан).
Исправлено после первого прогона e2e (Тест ДО3, 2026-05-02)
- BUG-4 (HIGH) —
_resolve_object_for_full_structureтеряет exact-match за substring close-match первого источника. Регрессия test02:get_object_full_structure('Согласование')возвращал реквизиты регистратст_СогласованиеЗаявокСБ(substring match черезLIKE '%name%'вget_object_attributes), а не БизнесПроцесс «Согласование», у которого был exactobject_nameвobject_synonyms. Каскад переработан в strict-cascade: Pass 1 проходит все 4 источника (object_attributes→search_objects→get_enum_values→find_module), проверяя только exact-match; Pass 2 — live glob по категориям (всегда exact, имя файла = name); Pass 3 — close-match fallback из любого непустого источника в исходном порядке (сохраняет старое поведение для случаев когда индексер положил объект под близким именем, в т.ч. enum через substringget_enum_values('Статус') → СтатусыЗаказов). - BUG-5 (HIGH) — Sandbox-hint при
KeyErrorот чужого контракта. Агент применял паттернfind_attributes(r['attr_name']) к новомуget_object_full_structure(r['name']) и получалKeyError: 'attr_name', тратил 1-2 calls на retry.Sandbox._add_error_hintsтеперь при наличииKeyError+get_object_full_structureв коде + bad-key из множестваattr_name/attr_synonym/attr_type/attr_kindподсказывает правильный контракт (name/synonym/type,dimensions/resourcesдля регистров). - BUG-5b/5c (MEDIUM/LOW) — recipe
get_object_full_structureявно предупреждает о различии ключей сfind_attributesи содержит пример для регистров. Первой строкой recipe — блок «КЛЮЧИ В РЕЗУЛЬТАТЕ ОТЛИЧАЮТСЯ от find_attributes»; добавлен пример итерацииdimensions/resourcesдляAccumulationRegister(агент применял attribute-template к регистрам, видел пустыеattributesи докладывал «'?' вместо имён»). - BUG-6 (LOW, план 3.1) —
analyze_document_flowобогащёнbased_on/print_forms+ top-levelis_postable/hint. Для непроводимого документа (Posting=Deny) при пустомregister_movementsтеперь top-levelis_postable=False+hint(агент не лезет внутрьregister_movements);find_based_on_documents/find_print_formsвызываются безусловно с graceful-degrade try/except (для проводимых документов это полезные данные сценария «ввод на основании»). Контрактregister_movementsсохранён. - BUG-7 (LOW) — DISAMBIGUATION для путей
parse_object_xmlиRoles. Добавлены пары:parse_object_xml(path)— путь к директории (Documents/Xпредпочтительно; явный CF/EDT тоже допустим;Documents/X/Document.xmlбезExt/— ошибка);parse_object_xml('Roles/X')vsfind_roles(object_name)— для прав доступа всегдаfind_roles, не сырая XML.
Полный список изменений: CHANGELOG.md