Commit Graph
1870 Commits
Author SHA1 Message Date
69745af336 fix(cfe-borrow): картинка элемента копируется только по голому имени файла
Значение xr:Abs и имя элемента с разделителем пути или «..» пропускаются
с предупреждением: иначе чтение и запись уходили за пределы Items, а порты
расходились на имени со «/». Источник-каталог больше не принимается за файл
картинки в PS-порте (как и в py).

Кейсы: предупреждение о картинке, которой нет в источнике; повторное
заимствование проверяет и вывод «Preserved existing».

Co-Authored-By: AndromanPro <AndromanPro@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 19:28:57 +03:00
651065093e fix(cfe-borrow): картинки элементов заимствованной формы переносятся файлами
Form.xml заимствованной формы ссылается на встроенные картинки элементов
(<xr:Abs>Picture.png</xr:Abs>), а сами файлы Ext/Form/Items/<Элемент>/<Файл>
в расширение не попадали — платформа отвергала загрузку: «Файл не найден».

Поведение сверено с Конфигуратором (8.3.27, формы УТ):
- Picture кнопок, RowsPicture/HeaderPicture/ValuesPicture таблиц и полей
  картинки остаются в обеих частях формы, файлы копируются байт в байт;
- у PictureDecoration картинка любого вида выбрасывается из обеих частей,
  без файла и без заимствования общей картинки.

Навык копирует ровно те файлы, на которые ссылается итоговый скелет формы
(ссылка xr:Abs -> Items/<имя владельца>/<файл>, точно на 666 ссылках корпуса).
Уже лежащий в расширении файл не перезаписывается. Оба порта, v1.38.

Раннер тестов пишет и сверяет двоичные файлы эталона побайтно: текстовый путь
через UTF-8 портил картинку, и сверка испорченного с испорченным проходила.

Проблема и первое решение — PR #102.

Co-Authored-By: AndromanPro <AndromanPro@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 18:37:32 +03:00
Nick ShirokovandClaude Opus 5.5 b95dcd8f13 fix(meta-edit): remove-* у обычного объекта без элемента свойства-списка — отказ
add/set на файле без элемента уже отказывали («файл не из выгрузки платформы?»),
а remove печатал WARN и выходил с кодом 0. У заимствованного объекта отсутствие
элемента по-прежнему значит «удалять нечего» — предупреждение.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 17:44:51 +03:00
Nick ShirokovandClaude Opus 5.5 0ff848784e fix(meta-edit): ключ свойства в любом регистре — в XML каноническое имя
ps1 сопоставлял ключ свойства без учёта регистра, но при создании элемента писал
тег как подан: registerRecords у заимствованного документа давал <registerRecords>,
и meta-validate его пропускал. py сравнивал точно и на том же входе отказывал.

Ключ свойства объекта и дочернего элемента теперь сводится к каноническому имени
(ключи веток modify — name/type/synonym… — впереди списка свойств), дальше в обоих
портах только оно. Попутно: py при переименовании сравнивал синоним с разбивкой
старого имени с учётом регистра и не обновлял авто-синоним «ИНН»; сравнение теперь
без учёта регистра, как в ps1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 17:31:28 +03:00
Nick ShirokovandClaude Opus 5.5 2fc5659b47 fix(meta-edit): modify.properties не создаёт элемент свойства-списка в обход проверок
modify.properties создавал отсутствующий элемент до Set-ComplexProperty, и решение
Get-ListPropertyElement обходилось: пустой список дописывал <RegisterRecords/>
заимствованному объекту, а у обычного объекта без элемента не было отказа.
Свойство-список теперь уходит в Set-ComplexProperty до create-if-missing.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 17:10:56 +03:00
Nick ShirokovandClaude Opus 5.5 cfd2d1be50 fix(meta-edit): отказ вместо предупреждения, когда операция не выполнена
WARN с кодом 0 означал «не смог»: в пакетном прогоне это выглядело как успех.
Теперь предупреждение остаётся только там, где нужное уже есть (элемент уже
добавлен, удалять нечего, позиция after/before не найдена — добавлено в конец).
Остальное — ошибка в stderr и код 1: неизвестный ключ или операция, неверный
формат, недопустимый у типа ребёнок, изменение несуществующего элемента, формы и
макеты (их делают form-add/template-add).

Отказ атомарен: побочные файлы (таблица внешнего источника, модуль команды,
предопределённые) пишутся после основного XML, так что отказ посреди определения
не оставляет на диске ни одного изменения.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 16:50:51 +03:00
51bcc503b0 fix(meta-edit): свойства-списки у заимствованного объекта и не своего типа (#99)
У заимствованного объекта расширения в Properties только изменённые свойства.
add-registerRecord и прочие add-*/set-* над списками не находили элемент, печатали
WARN, файл не меняли и выходили с кодом 0.

- Движения заимствованного документа: отсутствующий RegisterRecords создаётся.
- Прочие списки у заимствованного объекта — отказ. Проверено на 8.3.27: Owners и
  RegisteredDocuments платформа контролирует на равенство основной конфигурации
  (расширение не применяется), BasedOn/InputByString/DataLockFields и движения
  последовательности молча выбрасывает при загрузке.
- Свойство, которого у типа объекта нет (движения у справочника), — отказ; раньше
  modify.properties дописывал его, и meta-validate это пропускал.
- У обычного объекта отсутствие элемента — отказ вместо WARN.
- reference/properties.md: типы объектов в таблице — по выгрузкам ERP, БП, УТ, УНФ.
- verify-snapshots: двухэтапная загрузка и по params.extensionPath кейса.

Co-Authored-By: Roman Syuzyov <rsyuzyov@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 16:41:14 +03:00
Nick ShirokovandClaude Opus 5.5 5d1b5cdf74 fix(meta-edit, epf-validate): у внешней обработки/отчёта нет команд объекта и модуля менеджера (#108)
Платформа выбрасывает Command из внешней обработки/отчёта при сборке
(«не является подчиненным»), а Ext/ManagerModule.bsl — вовсе без
сообщения; epf-build при этом сообщает об успехе. Цепочка молча теряла
написанное: meta-edit добавлял команду, epf-validate её пропускал.

meta-edit: внешние типы внесены в таблицу допустимых детей — команду
не добавляет, предупреждает. epf-validate: Command и ManagerModule.bsl —
ошибки с пояснением.

Refs #108

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 15:20:06 +03:00
Nick ShirokovandClaude Opus 5.5 372510bbc4 fix(meta-edit): внешнюю обработку/отчёт проверять epf-validate (#108)
Автопроверка после правки жёстко звала meta-validate, который
ExternalDataProcessor/ExternalReport не знает: корректная правка
заканчивалась «Unrecognized metadata type». Валидатор теперь выбирается
по типу объекта. В py-порту stdout сбрасывается перед запуском
валидатора — его вывод больше не обгоняет строки meta-edit.

verify-snapshots: кейс meta-edit с setup none собирается epf-build,
а не грузится пустой конфигурацией, где обработку платформа не видит.

Fixes #108

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 14:59:54 +03:00
Nick ShirokovandClaude Opus 5.5 68a2a11a6c fix(web-publish): сохранять все адреса Listen глобального блока
Перезапись брала адрес только из первой строки Listen: при привязке
к loopback по обоим стекам (127.0.0.1 + [::1]) повторная публикация
молча выбрасывала IPv6-строку. Теперь сохраняются все адреса блока
(повторы схлопываются), меняется только порт; URL — по первому.

Refs #107

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 14:36:09 +03:00
Nick ShirokovandClaude Opus 5.5 933414f2e6 fix(web-info, web-publish): Listen с адресом привязки
web-info брал первое число строки Listen: при `Listen 127.0.0.1:19081`
порт выходил 127, URL и проверка TCP были ложными. Теперь разбирается
`Listen [host:]port [proto]` (включая IPv6 в скобках), сначала в своём
глобальном блоке; явный адрес идёт в URL и в пробу порта.

web-publish при перезаписи глобального блока сохраняет адрес привязки,
вписанный вручную, — повторная публикация больше не открывает loopback
на все интерфейсы; URL в выводе строятся по нему. Стандартный Listen
комментируется целой строкой (раньше `Listen 0.0.0.0:80` превращался
в мусор, а `Listen [::]:80` оставался активным).

Refs #107

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 14:27:18 +03:00
Nick ShirokovandClaude Opus 5.5 614206bc5c fix(db-repo, stub-db-create): временные файлы без фиксированных имён
Списки объектов и отчёт db-repo лежали в общем временном каталоге под
постоянными именами: параллельный запуск молча подменял список, по которому
модель перевыгружает устаревшие исходники, а при отказе платформы навык мог
напечатать отчёт предыдущего запуска. Имена получают случайный суффикс —
путь и так печатается в вывод.

Логи /Out базы-заглушки переехали в каталог самой базы: он уникален на запуск
и удаляется вместе с ней, чужой или устаревший лог в вывод не попадёт.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:59:42 +03:00
Nick ShirokovandClaude Opus 5.5 eb1796ef94 fix(db-*, epf-*): ошибка до запуска платформы не выдаётся за успех
Временный каталог брался из $env:TEMP, которой вне Windows нет. Join-Path
падал на привязке параметра внутри try/finally без catch: try прерывался,
finally отрабатывал, и скрипт выходил с кодом 0 — платформа не запускалась,
постусловие не проверялось (#106).

- временный каталог — [IO.Path]::GetTempPath() (на Windows тот же путь);
- верхнеуровневый trap { … exit 1 } в 15 скриптах db-*/epf-*, запускающих
  платформу: любая необработанная ошибка даёт код 1 и печатает место;
- уборка временного каталога в finally не падает на пустом пути;
- гард check-ps-portability.mjs держит оба правила.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 13:53:51 +03:00
Nick ShirokovandClaude Opus 5.5 317dce6d9f test(epf-build): кейсы подсказок configSrc — на любой ОС
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 21:31:35 +03:00
Nick ShirokovandClaude Opus 5.5 d44da2704e docs(epf-build, erf-build): проверка перед сборкой — про действия, без externalCheck
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 21:27:30 +03:00
Nick ShirokovandClaude Opus 5.5 636344666d feat(epf-build): общие модули конфигурации в проверке исходников через configSrc
Проверка исходников идёт в конфигурации-заглушке, где общих модулей не было:
обработка с кодом БСП не собиралась без -Checks off.

- stub-db-create -ConfigSrc: общие модули, к которым обращается код, получают
  пустых двойников с флагами контекста из выгрузки; неизвестные имена не
  угадываются
- epf-build -ConfigSrc, по умолчанию configSrc базы из .v8-project.json
- подсказки к «Переменная не определена (X)»: модуль не в том контексте /
  модуля нет в configSrc / выгрузка не передана (с -ConfigSrc и -Checks off)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-25 21:21:28 +03:00
Nick ShirokovandClaude Opus 5.5 b43d4050a6 fix(epf-bsp-add-command): Модификатор обязателен для ЗагрузкаДанныхИзФайла
Полное имя справочника-приёмника; без него команда не привязана
к справочнику в мастере загрузки.

Refs #82

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANXwbMUhuRFSCsq2RgmTTm
2026-09-24 20:20:56 +03:00
Nick ShirokovandClaude Opus 5.5 16345eb83d fix(epf-bsp-add-command): типы команд и сигнатуры обработчиков по контракту БСП
- убран несуществующий ТипКомандыСценарийВБезопасномРежиме(), добавлен
  ТипКомандыЗагрузкаДанныхИзФайла() с шаблонами трёх процедур загрузки;
  список типов помечен исчерпывающим, указана применимость к видам
- СозданиеСвязанныхОбъектов: серверный ВыполнитьКоманду с СозданныеОбъекты
  (4 параметра) — также в epf-bsp-init
- клиентские обработчики: Печать для печатных форм, вариант для создания
  связанных объектов

Refs #82

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANXwbMUhuRFSCsq2RgmTTm
2026-09-24 19:56:38 +03:00
Nick ShirokovandClaude Opus 5.5 43c8f50592 test(platform-epf): обработчик команды в фикстуре
Команда формы объявлена с действием, а процедуры в модуле не было —
epf-build проверяет исходники с -HandlersExistence и отменял сборку.
Обработчик вставляется в модуль формы; добавлена проверка, что он
пережил сборку и разборку.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANXwbMUhuRFSCsq2RgmTTm
2026-09-24 19:10:12 +03:00
Nick ShirokovandClaude Opus 5.5 647c633a9b fix(db-load-xml): -AllExtensions с загрузкой частями — отказ на обоих движках
Ветка ibcmd молча игнорировала список и загружала все расширения целиком.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANXwbMUhuRFSCsq2RgmTTm
2026-09-24 18:08:20 +03:00
Nick ShirokovandClaude Opus 5.5 80618f0b93 fix(db-load-git): предупреждать об удалениях, которые загрузка частями не применит
Удалённый объект уходит из базы, только если в списке его владелец и в
составе владельца объекта уже нет; удалённый файл-часть (модуль, Ext/)
загрузка частями не удаляет никогда. Скрипт классифицирует удаления:
применимые — [note], остальные — [ВНИМАНИЕ] с причиной; если загружать
нечего, а неприменимые удаления есть — код 1. git diff с --no-renames,
чтобы старый путь переименования был виден. -AllExtensions отвергается
на обоих движках: частями грузится одно расширение за раз.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANXwbMUhuRFSCsq2RgmTTm
2026-09-24 18:08:20 +03:00
Nick ShirokovandClaude Opus 5.5 f98e7e9e81 fix(db-dump-xml): Changes без тихой полной перевыгрузки, инкремент в ibcmd
- -update без -force: при другой версии формата — отказ с подсказкой
  про -Mode Full, а не молчаливая перезапись всего дерева в новом формате.
- Первая выгрузка режимом по умолчанию: в каталог без выгрузки (пусто,
  только .git/README) — полностью; выгрузка без ConfigDumpInfo.xml — ошибка.
- ibcmd: Changes через --sync; Full в непустой каталог — через временный
  каталог и копирование поверх, как пишет конфигуратор; ошибка копирования
  даёт код 1. UpdateInfo с -AllExtensions отвергается, а не выгружает всё.
- py-порт печатает вывод ibcmd, как PS.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANXwbMUhuRFSCsq2RgmTTm
2026-09-24 18:08:20 +03:00
Nick ShirokovandClaude Opus 5.5 ce7238792e test(runner): шаг preRun git для кейсов с репозиторием
Кейсы навыков, читающих изменения из git, строят репозиторий шагом
{ "git": [...] }. Общая реализация для runner.mjs и verify-snapshots.mjs
в tests/common/git-step.mjs — настройки машины на фикстуру не влияют.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANXwbMUhuRFSCsq2RgmTTm
2026-09-24 18:08:20 +03:00
Nick ShirokovandClaude Opus 5 bd10ec08b6 test(form-decompile): осмысленное имя второго параметра в dl-parameter-title-case
Параметр звался СуммаДокумента и сравнивался с кодом справочника: имя пришло из кейса
реквизита, где оно нужно ради авто-вывода «Сумма документа», а здесь заголовок задан
явно и от имени не зависит. Теперь КодОрганизации — запрос читается.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SSyRNwSiuAAEQCLSCUGEzQ
2026-09-22 20:54:18 +03:00
Nick ShirokovandClaude Opus 5 7ebb749143 test(form-decompile): осмысленный запрос в кейсе dl-parameter-title-case
Кейс сравнивал числовые литералы со строковыми параметрами
(«ГДЕ 1 = &ОрганизацииВЕТИС» при "type": "string") и обходился без таблицы.
На проверяемое поведение это не влияет — навык заголовки читает, а текст запроса
переносит строкой, и платформа при загрузке конфигурации запрос не разбирает
(verify-snapshots проходил и на прежнем варианте). Но кейс читают как образец,
поэтому запрос теперь нормальный: динамический список над справочником, строковые
параметры сравниваются со строковыми полями.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SSyRNwSiuAAEQCLSCUGEzQ
2026-09-22 20:47:33 +03:00
Nick ShirokovandClaude Opus 5 9d07b2e20f fix(form-decompile): не терять заголовок-пробел у параметра динамического списка
Ветка параметра читала заголовок обычным Get-LangText, который схлопывает whitespace-only
в пустую строку; ветка реквизита давно читает его через Get-LangTextWS. Заголовок-пробел —
им гасят подпись — превращался в "" , а компилятор трактует пустую строку как отсутствие
ключа и подставляет авто-вывод из имени: " " молча становилось «Организации ВЕТИС».
Тот же класс, что и потерянный регистр, соседняя ветка той же функции.

В корпусе (13891 узел dcssch:title в четырёх типовых) платформа не пишет ни пустой,
ни whitespace-only заголовок, поэтому на разборе чужих выгрузок правка ничего не меняет —
она чинит наш собственный раундтрип compile → decompile → compile.

Кейс dl-parameter-title-case расширен вторым параметром с заголовком-пробелом; на исходной
версии падает в обоих портах. Снэпшоты приняты платформой (verify-snapshots, 3/3).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SSyRNwSiuAAEQCLSCUGEzQ
2026-09-22 20:42:20 +03:00
Nick ShirokovandClaude Opus 5 df47d4d34f test(check-inline-drift): взять авто-вывод заголовка title_from_name под гвард
Title-FromName/title_from_name продублирован в form-compile и form-decompile: компилятор
пишет заголовок, которого нет в DSL, а декомпилятор на этом же выводе решает, можно ли
заголовок опустить. В комментарии копия заявлена «ТОЧНЫМ зеркалом», но ничем не держалась.
Разъедутся копии — заголовок либо теряется, либо дублируется, и в обоих случаях текст на
форме меняется молча, без ошибки платформы.

Эталон варианта — form-compile: компилятор авторитетен, декомпилятор его зеркалит. Тело
копии приведено к эталону без смены поведения (разбиение строк в ps1; в py — выражение
вместо индексного цикла и `not parts` вместо `len(parts) == 0`; `p.isupper()` и
`p == p.upper()` расходятся только на частях без буквенных символов, а после двух
разделяющих регулярок такая часть недостижима).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SSyRNwSiuAAEQCLSCUGEzQ
2026-09-22 20:06:46 +03:00
cf02c69ff5 fix(form-decompile): не терять заголовок, отличающийся от авто-вывода только регистром
Заголовок реквизита формы и параметра динамического списка опускается, если равен
авто-выводу из имени: компилятор восстановит его сам. Сравнение было
регистронезависимым (в ps1 -eq/-ne, в py зеркалящий их _ps_ieq), поэтому
«Организации ВетИС» при имени ОрганизацииВЕТИС считался равным авто-выводу
«Организации ВЕТИС», выпадал из DSL, и обратная сборка молча меняла текст на форме.

Эталон сравнения — не PowerShell, а компилятор: он пишет заголовок как есть, значит
опускать можно только при побайтовом совпадении. В ps1 этого не даёт и -ceq — он
культурный, мягкий перенос и NFD-разложение для него ничего не весят, и порты
разошлись бы между собой. Сравнение идёт через [string]::Equals(..., Ordinal),
что и есть зеркало питоновского ==. _ps_ieq больше не нужен и удалён.

Два регресс-кейса: реквизит формы (регистр + невидимый мягкий перенос) и параметр
динамического списка. Оба падают на исходной версии в обоих портах.

Найдено на типовой конфигурации: Документ.ИсходящаяТранспортнаяОперацияВЕТИС.ФормаСписка.

Co-Authored-By: Шпаков Антон Александрович <shpakov.anton.job@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SSyRNwSiuAAEQCLSCUGEzQ
2026-09-22 20:06:32 +03:00
Nick ShirokovandClaude Opus 5 38c26f319d chore(template-add): синхронизировать версию PS-порта с py
В предыдущем коммите бампнулся только py-порт: ps1 остался v1.26 при py v1.27.
Правила «версия в обоих файлах» набор тестов не проверяет — расхождение видно
только глазами в шапке.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 19:01:35 +03:00
Nick ShirokovandClaude Opus 5 dc470a3803 fix(template-add,help-add): закрыть находки ревью по коду языка и странице
help-add терял текст справки. Отказ смотрит только на Help.xml, а страница может
пережить его (удалённый дескриптор, частичная выгрузка, справка, сделанная руками):
тогда запись шла безусловно и стирала содержимое с кодом 0 и рапортом [OK].
Теперь существующая страница сохраняется, создаётся только дескриптор — та же
защита, что уже стоит в template-add. Прежняя оценка «в help-add потери данных нет»
была неверной: она опиралась на чтение кода, а не на замер.

Код языка: регулярка пропускала имена устройств Windows. При -Lang nul py-порт
молча писал <Page>nul</Page> и пустой каталог с кодом 0 (страница уходила в NUL),
а PS падал исключением — то есть порты ещё и расходились. Якоря \A…\z вместо ^…$:
последние в обоих языках допускают перевод строки в конце.

Проверка вынесена в Test-LangCode / is_valid_lang и внесена в реестр
check-inline-drift: inline-блок гард не видел, а копий у него две.

Плюс мелочи оттуда же: мёртвый дизъюнкт в $pageExists убран; полумигрированное
дерево (дескриптор есть, старый Ext/Template.html остался рядом) теперь получает
предупреждение, а не молчание; существование страницы в py сверяется без учёта
регистра — иначе на Linux -Lang RU писал бы вторую страницу мимо дескриптора.

Четыре кейса на каждый сценарий. Существующие эталоны не сдвинулись.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 18:50:58 +03:00
Nick ShirokovandClaude Opus 5 c619da4a0a fix(help-add): валидация кода языка до записи
-Lang брался как есть и шёл и в текст XML, и в имя файла страницы. Измерено на
обоих портах: `-Lang "../../beyond"` писал beyond.html двумя уровнями выше
каталога Ext/Help и клал <Page>../../beyond</Page> в дескриптор, а `-Lang ""`
давал скрытый файл «.html» и пустой <Page></Page>. Оба случая — код возврата 0
и рапорт об успехе, то есть отказ платформы был бы тихим.

Проверка — дословная копия той, что появилась в template-add: навыки автономны,
но формат «дескриптор + страница» у них общий, и расходиться копиям незачем.

Дефект не регрессия, он был до текущей ветки; замечен при ревью соседней правки.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 18:34:39 +03:00
Nick ShirokovandClaude Opus 5 69175a7a63 fix(template-add): не терять содержимое страницы при добавлении языка
Ревью вскрыло два дефекта во вчерашней ветке добавления языка — оба
воспроизведены руками.

1. Миграция старой раскладки шла ДО проверки дубля языка. При дефолтном -Lang ru
   (самый вероятный способ повторно позвать навык на старом макете) Template.html
   уже был перенесён, затем срабатывал отказ «страница ru уже существует» — и
   дескриптор не записывался вовсе. Макет оставался разобранным: страница есть,
   дескриптора нет, платформа такую раскладку снова молча игнорирует. Печатавшийся
   при этом [WARN] «создан дескриптор» был неправдой.

2. Файл страницы писался безусловно, а проверялся только список <Page> в
   дескрипторе. При рассинхроне (страница на диске есть, в дескрипторе нет —
   в том числе после дефекта 1) содержимое затиралось пустым скелетом с кодом 0.

Теперь ветка сначала разбирает состояние целиком и только потом пишет, файл
страницы не перезаписывается никогда: существующая страница подхватывается, в
дескриптор дописывается <Page>. Старая раскладка с -Lang ru — это не коллизия,
а ровно тот случай, ради которого миграция и нужна. Состояние, где есть и
Template.html, и Template/ru.html, навык не разруливает сам: отказ до изменений.

Плюс валидация -Lang: код языка идёт и в текст XML, и в имя файла, поэтому пустое
значение давало файл «.html» с пустым <Page></Page>, а разделитель пути — запись
мимо Ext/Template. Оба отказа платформы были бы тихими.

Четыре новых кейса закрывают каждый сценарий; паритет портов сверен побайтово.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 17:41:25 +03:00
Nick ShirokovandClaude Opus 5 04563a6973 feat(template-add): добавление страницы макета на втором языке
Повторный вызов на существующем макете безусловно отказывал, поэтому второй язык
приходилось добавлять руками — дописывать <Page> в дескриптор и заводить файл
страницы. Случай не редкий: в выгрузке ERP 54 макета из 70 двуязычные.

Теперь при -TemplateType HTML существующий макет — повод добавить страницу, а не
отказать. Порядок <Page> — по коду языка (в ERP так во всех 54). Версия формата
берётся из самого дескриптора, чтобы правка чужой выгрузки не меняла формат.
Метаданные макета и ChildObjects не трогаются: перезапись сменила бы UUID.

Отказ остался там, где он по делу: тот же язык повторно, нехтмловый макет под тем же
именем, любой не-HTML тип.

Макет в старой раскладке (Ext/Template.html) мигрируется с громким [WARN]: платформа
такую раскладку игнорирует, то есть состояние и так нерабочее, а создать её могла
только версия навыка без -Lang — значит это страница на языке по умолчанию.

Проверено на 8.3.27.1859: двуязычный макет доходит до базы и возвращается обратно
байт в байт — и дескриптор, и обе страницы. Попутно измерено: страницу на языке,
не объявленном в Languages/, платформа принимает — поэтому состав языков не проверяем.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 17:19:57 +03:00
Nick ShirokovandClaude Opus 5 b8b8140e3b fix(help-add): парные <meta> и <link> в странице справки
Скелет страницы писал самозакрывающиеся <meta …/> и <link …/>. Платформа пишет их
парными: на 400 страницах справки из выгрузки acc_8.3.27 — 400 раз </meta>, нулей нет.
Расхождение безвредно для загрузки, но даёт лишний дифф при первом сохранении
страницы в Конфигураторе.

Замечено при разборе раскладки HTML-макета: template-add берёт скелет отсюда же.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 16:45:57 +03:00
1e94b9236f fix(template-add): HTML-макет в платформенной раскладке
Навык создавал Templates/<Макет>/Ext/Template.html. Платформа такой файл молча
игнорирует: загрузка проходит без ошибок и предупреждений, а макет в базе пустой.

HTML-макет платформа хранит парой, как справку: дескриптор Ext/Template.xml со
списком страниц и сама страница Ext/Template/<язык>.html (картинки — в _files/).
Раскладка снята с выгрузки acc_8.3.27: 136 HTML-макетов из 136, дескриптор во всех
байт в байт одинаков. Шапка страницы — в виде редактора платформы (одной строкой,
парный </meta>), чтобы первое сохранение в Конфигураторе не давало диффа.

Язык страницы задаётся параметром -Lang (дефолт ru) — как в help-add.
Вывод навыка теперь различает содержимое и дескриптор: «Содержимое» указывает на
страницу, иначе правка ушла бы в дескриптор.

Проверено на 8.3.27.1859: LoadConfigFromFiles + UpdateDBCfg + обратная выгрузка —
текст макета доходит до базы и возвращается байт в байт, дескриптор тоже.
Контроль — тот же макет в старой раскладке: в выгрузке из базы тела нет вовсе.
EPF: epf-build → epf-dump — раскладка возвращается с содержимым.

Диагноз и раскладка — из PR #98.

Co-Authored-By: Roman Syuzyov <rsyuzyov@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 16:45:50 +03:00
Nick ShirokovandClaude Opus 5 6eaf3211cc feat(db-load-xml,db-load-git): предупреждать о полной загрузке при Configuration.xml в списке
Список частичной загрузки задаёт объекты метаданных: вместе с объектом платформа грузит
его дочерние объекты (формы, макеты) и файлы Ext/. Configuration.xml — объект
«Конфигурация», поэтому его наличие в списке даёт полную загрузку конфигурации, а не
перечисленных объектов. В db-load-git он попадает в список из диффа сам, без участия
пользователя.

Замерено на обоих движках (1cv8 и ibcmd): правило одинаково.

- SKILL.md обоих навыков: строка про цену Configuration.xml в списке;
- хинт в выводе обеих веток движка;
- два кейса на срабатывание и на отсутствие ложного срабатывания.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 14:37:21 +03:00
Nick ShirokovandClaude Opus 5 77836f7ada perf(tests): verify-snapshots отсеивает external-кейсы до копирования выгрузки
Кейс на `setup: external:` платформой не проверяется никогда — решение об этом
стояло в Step 7, а Step 0 до него успевал скопировать всю выгрузку типовой
конфигурации в рабочий каталог. Результат копирования тут же выбрасывался:
ни один шаг между Step 0 и Step 7 на вердикт для таких кейсов не влияет.

Цена была видна на глаз: 10 кейсов real-* у meta-info занимали 166-235 секунд
каждый, то есть около 32 минут чистого копирования ERP и БП. Прогон по навыку
стал 2 мин 53 с против ~35 минут при том же результате: 36 прошли, 0 упало,
те же 10 external пропущены с той же причиной. В репозитории таких кейсов 38.

Решение перенесено к остальным ранним пропускам, до Step 0. Обе ветки
сохранены: недоступная выгрузка (её нет на маке) по-прежнему даёт СКИП, а не
падение, доступная — passed с noPlatformReason. Ставшие недостижимыми блоки в
Step 0 и Step 7 удалены, caseProvidedConfig сузился до fixture:.

Фикстурные кейсы не затронуты — прогон meta-validate до и после совпадает
(17 прошли, 0 упало, 13 пропущено).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 20:07:37 +03:00
Nick ShirokovandClaude Opus 5 dd0ad18076 fix(meta-compile,meta-validate): «только единственным» касается и характеристики
Правило было уже реальности: Конфигуратор не даёт включить характеристику в
составной тип вместе ни с каким другим типом — в том числе с другой
характеристикой. Предупреждение теперь ловит и DefinedType.X, и
Characteristic.X.

Корпус подтверждает даже чище, чем для определяемого типа: 1741 характеристика
единственным типом и 0 в составных (у определяемого было 6500 против 1).
Уровень прежний — предупреждение: загрузчик такое принимает, проверено
загрузкой в базу.

Голых метатипов это не касается: DocumentRef + CatalogRef — обычный составной
тип, 525 вхождений в поставляемых ERP и БП.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 19:54:29 +03:00
Nick ShirokovandClaude Opus 5 0db3656c9c fix(meta-compile,meta-validate): в типе значения ПВХ допустим только определяемый тип
Условие было шире реальности: предупреждение пропускало и Characteristic.X.
В дереве выбора типа значения ПВХ характеристики нет вовсе — тип значения
характеристики не может быть значением характеристики. Единственное множество,
которое Конфигуратор там предлагает, — ОпределяемыйТип.

Уровень прежний: платформа такую конфигурацию грузит (проверено загрузкой в
базу), поэтому предупреждение, а не отказ. В корпусе erp+acc ни один из 24 ПВХ
множеств в типе значения вообще не использует.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 19:48:06 +03:00
Nick ShirokovandClaude Opus 5 24b1aa9ee1 fix(meta-compile,meta-validate): правки по второму ревью
Три находки, все воспроизведены:

1. Счётчик членов составного типа не видел форму с локальной xmlns:
   тип из чужого пространства имён пишется как <v8:Type xmlns:mxl="…">, а
   регулярка требовала '>' сразу за именем тега. В итоге на одном и том же
   файле meta-compile молчал, а meta-validate предупреждал — навыки
   расходились в оценке одного содержимого. Радиус: оба порта.
2. Report-OK проверки 23 печатался безусловно — то есть сразу после
   собственного ERROR, и раздувал счётчик проверок в итоговой строке.
   Соседние проверки (21, 22) так не делают.
3. ToString() копировал весь буфер вывода на каждый реквизит: O(n^2) на
   крупном объекте. В файле уже есть ranged-перегрузка ровно для этого
   (Emit-TypeContent). py-порт был изначально корректен — он режет список.

Добавлен кейс на тип с локальной xmlns: без него находка 1 вернулась бы
незамеченной, потому что обычный составной тип её не показывает.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 19:28:46 +03:00
Nick ShirokovandClaude Opus 5 1481e58bfc feat(meta-compile,meta-validate): проверки на тип-множество там, где его не принимают
Запрет неочевидный, а отказ платформы приходит поздно и одной строкой из
Конфигуратора. Три уровня строгости, все замерены загрузкой в базу на
8.3.24.1691, а не выведены из документации:

- ОШИБКА — множество в составе определяемого типа. Платформа отвергает файл
  целиком («ОпределяемыйТип.<Имя> - Недопустимый тип»); проверено на
  ОпределяемыйТип, Характеристика, ЛюбаяСсылка и голых ссылках, контрольный
  вариант с обычным CatalogRef.<Имя> принят. Отсюда и ноль таких узлов в
  корпусе — это запрет, а не совпадение.
- ПРЕДУПРЕЖДЕНИЕ — голый метатип в типе значения ПВХ. Загрузка проходит, но
  Конфигуратор такой тип не предлагает: в дереве выбора СправочникСсылка и
  ДокументСсылка — папки без флажка, а ЛюбаяСсылки там нет вовсе. Плюс AnyRef
  раундтрипом возвращается как AnyIBRef, то есть молча меняется.
- ПРЕДУПРЕЖДЕНИЕ — определяемый тип одним из составного. Конфигуратор даёт
  выбрать его только единственным, но отказывать нельзя: в корпусе erp+acc
  6500 единственных против 1 составного, и этот один лежит в типовой ERP
  (Документ.НачислениеИСписаниеБонусныхБаллов.Баллы — два определяемых типа
  подряд). Навык не вправе отказаться собрать то, что поставляет 1С.

В meta-compile состав множеств берётся опросом самого эмиттера, а не второй
копией его регулярок: список видов живёт в Emit-TypeContent, и копия
разъехалась бы с ним молча.

Развёртка по 3428 объектам ERP: ровно 2 срабатывания, оба на том самом
реальном составном реквизите. Ложных нет.

Предупреждения пишутся прямо в stderr, а не через Write-Warning: в PS 5.1 тот
уходит не в тот поток (конвенция из cf-init), и до проверки они не доезжали.

Оба кейса-предупреждения проверены платформой — она эти конфигурации грузит,
что и подтверждает выбор «предупреждение, а не отказ».

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:45:16 +03:00
Nick ShirokovandClaude Opus 5 079a177cf4 docs(meta-compile): откат правки reference/code.md
Правка нарушала два наших правила сразу. Фраза «русские имена принимаются
наравне с английскими» описывала прощающий ввод — его документировать нельзя,
иначе модель получает развилку вместо одной каноничной формы. Замечание «в
выгрузке ERP так задана треть подписок» — про наше исследование, а не про
использование навыка: следов фикса в инструкции не держим.

Формы источника остаются описанными в docs/meta-dsl-spec.md, а круг
«вывод meta-info → вход meta-compile» держит check-typeset-coverage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:21:08 +03:00
Nick ShirokovandClaude Opus 5 e9d45984dc fix(meta-info,meta-compile,+5): правки по ревью — регистр, BOM, голый менеджер, порог
Семь находок ревью, все подтверждены воспроизведением:

1. Голый менеджер в источниках печатался по-английски: карта объектных видов
   применялась только к форме с точкой, а meta-compile пишет «cfg:DocumentManager»
   обычным v8:Type. Восемнадцать добавленных *Manager-записей были недостижимы.
   Суффикс «(все)» ему не ставится — это сам тип менеджера, а не класс объектов.
2. Новые регулярки прощающего ввода расходились между портами: -replace в
   PowerShell регистронезависим, re.sub — нет. «ДокументОбъект (Все)» проходил в
   ps1 и падал в py. Добавлен re.IGNORECASE — это задокументированная ловушка
   портирования, и она же снова сработала.
3. В шесть py-портов попал BOM (перекодировка при бампе версии), и перед
   «#!/usr/bin/env python3» он ломает shebang на POSIX. Снят там, где его не было
   в HEAD; в mxl-compile.py он был изначально и оставлен.
4. Правило со стрелкой из Resolve-TypeStr убрано. form-compile режет тип по [|+]
   ДО резолвера, поэтому строка глоссария «A -> B | C» молча превращалась в
   составной тип «A | C» вместо одного A. Половина строки, принятая за тип, —
   хуже громкого отказа. Остались суффикс «(все)» и счётчик «— типов: N».
5. py-порт meta-info не переиспользовал общий климб до корня конфигурации:
   правка тогда молча не применилась, и порты разошлись по структуре.
6. Found выставлялся до разбора состава определяемого типа: падение внутри
   давало «состав пуст» — ложь вместо «файл типа не разобран».
7. Порог сворачивания источников считался по сумме множеств и явных типов, а
   сворачивались только явные: пять множеств плюс один тип прятали этот тип, а
   шесть типов без множеств давали «и ещё» после пустоты. Порог теперь по числу
   явных типов, «и ещё» убрано как ложное.

Плюс формы источника подписки описаны в reference самого навыка: раньше они
были только в docs/meta-dsl-spec.md, а навык обязан быть самодостаточным.

Добавлен кейс на голого менеджера — без него находка 1 вернулась бы незамеченной.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:14:27 +03:00
Nick ShirokovandClaude Opus 5 510c9163e3 fix(meta-info): кейс на множество в определяемом типе — фикстура вместо невалидной конфигурации
verify-snapshots отверг кейс: «ОпределяемыйТип.Любой - Недопустимый тип».
Спросил платформу — v8:TypeSet внутри определяемого типа запрещён вообще, и не
только AnyRef: отвергнуты также голый CatalogRef, Characteristic.X и вложенный
DefinedType.X, при том что контрольный вариант с обычным CatalogRef.X принят.
Замерено на 8.3.24.1691 загрузкой в базу. Отсюда и ноль таких узлов в корпусе —
это не совпадение, а запрет.

Комментарий в обоих портах утверждал обратное («платформа допускает») — правда
записана, факт добавлен в docs/meta-dsl-spec.md.

Сам разбор v8:TypeSet в выводе определяемого типа оставлен: meta-info читалка,
и рукотворный файл с таким узлом она обязана показать честно, а не потерять его
молча вместе с правдивым счётчиком. Кейс переведён на рукотворную фикстуру с
объявленной причиной пропуска платформенной проверки.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:53:46 +03:00
501f7a2c4f test(meta-info): кейсы на множества типов — подписки, реквизиты, пороги
Покрытия не было вообще: ни одного кейса ни на подписку на событие, ни на
определяемый тип. Поэтому дефект и жил — тесты были зелёными всё время.

Добавлено девять кейсов:
- источники-множества в full/overview/brief (класс «все», определяемый тип,
  явный тип) — основа взята из PR #96, эталоны под наш формат;
- определяемого типа нет в выгрузке: сказано прямо, а не молчанием;
- односоставный псевдоним в типе реквизита — главный по частоте случай в
  реальных выгрузках (7575 вхождений из 8841 в ERP);
- определяемый тип выше порога: вместо состава счётчик и команда раскрытия —
  этот кейс держит решение «не раскрывать», без него регрессия вернула бы
  шестисотстрочный вывод;
- голый метатип в типе реквизита: суффикс «(все)» против конкретного типа;
- определяемый тип, содержащий множество: счётчик «Типы (N)» его не теряет;
- явных источников больше порога: overview сворачивает их в счётчик.

Фикстуры строятся навыками через preRun, чтобы эталоны не плавали по uuid.

Co-Authored-By: Шпаков Антон Александрович <shpakov.anton.job@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:42:48 +03:00
Nick ShirokovandClaude Opus 5 31086773ee docs(meta-dsl-spec): голый объектный метатип в разделе «Тип-множество»
Раздел знал только ссылочные метатипы, хотя meta-compile объектные эмитит
правильно, а источники подписок на событие построены именно на них: в
erp_8.3.24 так задана треть подписок. Дописаны объектные виды, наборы записей
и ConstantValueManager, отмечено, что прочие менеджеры множеством не являются,
и зафиксирован суффикс «(все)» в выводе meta-info.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:35:19 +03:00
Nick ShirokovandClaude Opus 5 1d8a6f2f58 test: гард check-typeset-coverage — вывод meta-info замыкается на вход meta-compile
Связь «прочитал вывод → подал на вход» держалась на честном слове и рвалась
молча в обе стороны: meta-info печатал метки, которых нет в словаре
meta-compile (33 из 41), а в карте meta-info не было видов, которые
meta-compile эмитит, — и они печатались по-английски посреди русского вывода.
Снэпшоты этого не видят: кейсы читают и компилируют по отдельности, круг не
замыкая.

Инвариант строгий в одну сторону: каждая метка читалки обязана быть ключом в
typeSynonyms у meta-compile и вести ровно в тот же канон. Обратное неверно
намеренно — компилятор знает формы, которых читалка не печатает. Заодно гард
сверяет objectTypeMap и refTypeMap между портами навыка: переводы — часть
вывода, и расхождение портов дало бы разный текст на один и тот же файл.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:35:19 +03:00
Nick ShirokovandClaude Opus 5 74e88e75c2 feat(meta-compile,meta-edit,form-compile,form-edit,mxl-compile,skd-compile,skd-edit): вывод meta-info принимается на входе
Вывод читающего навыка модель несёт обратно в компилятор, а тот его не
понимал. Из 41 метки, которую печатает meta-info, в словаре typeSynonyms не
было 33: «ДокументОбъект.Заказ» из источников подписки meta-compile отвергал с
«Неизвестный тип», хотя сам же печатал эту форму через meta-info. Не
принимались и «ПВХСсылка.ВидыСубконто», и «Характеристика.Виды» — при том что
Characteristic.Xxx описан в спеке как штатная форма DSL.

Добавлены русские имена объектных типов, менеджеров и наборов записей.
Аббревиатуры (ПВХ/ПВР, РС/РН/РБ/РР) приняты наравне с полными именами: вывод
навыка сокращает долгие виды, чтобы в списке на сорок реквизитов не терялось
имя объекта, и раз он их печатает — обязан принимать.

В Resolve-TypeStr снимаются хвосты, которые дописывает глоссарий meta-info:
суффикс «(все)», счётчик «— типов: N» и раскрытие после стрелки. Срезаются
только эти известные формы — круглые скобки заняты параметризованными типами
вроде Число(15,2), слепой срез сломал бы их.

Функция под гардом check-inline-drift, поэтому правка синхронна во всех семи
навыках и обоих портах.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:34:49 +03:00
7cbc8e9b7f fix(meta-info): множества типов (v8:TypeSet) показываются как тип
Источники подписки на событие читались только из v8:Type. Если источник задан
множеством — определяемым типом или целым классом «все документы» — строки
«Источники» не было вовсе, и подписка выглядела так, будто ни на что не
срабатывает. В erp_8.3.24 так задана треть подписок: 151 из 492 вообще без
v8:Type, в acc_8.3.24 — 126 из 443.

Тот же дефект в типах реквизитов, и там он чаще. Вхождений
v8:TypeSet>cfg:DefinedType в Catalogs/Documents/InformationRegisters/
AccumulationRegisters ERP — 8841, из них 7575 (86%) указывают на определяемый
тип ровно с одним членом. АвансовыйОтчет печатал «Сумма
ОпределяемыйТип.ДенежнаяСуммаНеотрицательная», и было не видно, что это
Число(15,2): имя выглядит как ссылочный тип. Голый метатип-категория
(«ДокументСсылка» без точки = любой документ) отличался от конкретного
«ДокументСсылка.Заказ» только наличием точки посреди длинного имени.

Правило одно на все места: имя множества стоит в строке типа, а раскрытие —
ровно одной записью на уникальное множество, глоссарием в конце вывода.
Раскрывать в строке нельзя дважды: псевдоним повторяется в объекте десятками
раз (в АвансовомОтчете — 12), а в корпусе есть определяемые типы на 596 типов —
вывод упёрся бы в постраничник и съел хвост объекта. Выше порога
composedTypeThreshold вместо состава идут счётчик и готовая команда раскрытия.
Голый метатип получает суффикс «(все)»: разница становится словом, а не
пунктуацией. Характеристика ПВХ помечена как набор, определяемый данными, —
из выгрузки её состав не берётся в принципе.

Попутно того же класса:
- объектные типы (DocumentObject.X, *RecordSet.X, *Manager.X) печатались
  по-английски в выводе определяемого типа и по-русски в источниках подписки —
  одно понятие двумя видами; в карту добавлены недостающие виды, включая
  ConstantValueManager и ChartOfCalculationTypesObject;
- собственный вывод определяемого типа читал только v8:Type и молча терял
  v8:TypeSet — счётчик «Типы (N)» врал;
- корень конфигурации ищется климбом до Configuration.xml, общим с проверкой
  поддержки, а не фиксированным «на два уровня выше»;
- состав определяемого типа кэшируется по имени;
- нечитаемый файл типа назван нечитаемым, а не отсутствующим.

Проверено корпусом: 5129 прогонов по erp_8.3.24 и acc_8.3.24 в трёх режимах,
каждое расхождение с эталоном до правки классифицировано, необъяснённых нет.
Паритет портов — 5129 из 5129, 103912 строк совпали.

Проблему и замеры по подпискам сообщил автор PR #96.

Co-Authored-By: Шпаков Антон Александрович <shpakov.anton.job@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:34:27 +03:00
Nick ShirokovandClaude Opus 5 77c797e6d0 fix(db-repo,db-load-cf,epf-build): объявления цепочки v8path выше точки вызова
PowerShell ищет функцию в момент вызова и видит только уже выполнившиеся
объявления. В трёх навыках блок Find-V8Project/Test-SamePath/Find-ProjectDatabase
оказался ниже строки, где отрабатывает Find-ProjectV8Path: CommandNotFoundException
уходил в stderr, результат становился $null, и выбор платформы по записи базы молча
откатывался на корневой v8path. Порты .py не задеты — Python связывает имя при
вызове, так что расхождение PS↔PY было бы тихим.

Гард check-ps-define-before-call.mjs проверяет порядок объявлений во всех .ps1,
где отрабатывает эта цепочка (15 навыков), и на прежнем состоянии даёт ровно те
три диагностики. Кейс db-repo/v8path-from-database ловит тот же дефект поведением.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 21:16:22 +03:00