Commit Graph

83 Commits

Author SHA1 Message Date
Nick Shirokov 42b96bbd21 feat(cf-*): set-home-page + drill-down -Section home-page + form-ref валидация
- cf-edit: новая операция set-home-page перезаписывает Ext/HomePageWorkArea.xml.
  DSL принимает template (OneColumn/TwoColumnsEqualWidth/TwoColumnsVariableWidth),
  left/right с записями форм (строка или объект form/height/visibility/roles).
  Тихая нормализация ссылок: русские типы, 3-сегмент → авто-Form, файловые пути
- cf-info: краткая HP-сводка (template + счётчики) в overview/full, детальный
  вид через -Section home-page (alias -Name) с раскладкой и переопределениями ролей
- cf-validate: Check 9 — валидация ссылок на формы из HomePageWorkArea и
  Default*Form свойств; битая ссылка → error
- reference.md: убран реализационный шум (canonical sort, авто-нормализация форм,
  panelDef detail, секция авто-валидации); путь src/ в примерах вместо репо-специфичных

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 19:13:18 +03:00
Nick Shirokov 336dade274 feat(cf-edit): операция set-panels для раскладки панелей
JSON-DSL уровня имён: алиасы sections/open/favorites/history/functions
для платформенных uuid, объект {group:[...]} для стека (даёт <group>-
вложенность как у Конфигуратора), несколько записей в одной стороне =
соседние теги (рядом). Файл Ext/ClientApplicationInterface.xml
перезаписывается полностью; panelDef для всех 5 панелей пишется всегда.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:03:57 +03:00
Nick Shirokov 3c3ed2ff46 feat(cf-init): генерить Ext/ClientApplicationInterface.xml с ERP-дефолтом
Без этого файла веб-клиент 1С рендерит секции icon-only (без подписей),
а web-test их не видит. Дефолтная раскладка как в типовых ERP/БП ≥ 8.3.24:
панель открытых сверху, панель разделов слева; функций/избранного/истории
объявлены через panelDef но не размещены.

Расширил docs/1c-configuration-spec.md § 4.2 моделью раскладки и таблицей
UUID 5 платформенных панелей. Обновил снапшоты cf-init под новый файл.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 16:43:39 +03:00
Nick Shirokov d75b4d96ca fix(verify-snapshots): структурные зависимости с preRun и ChartOfAccounts
getStructuralDeps теперь сканирует все inputs (caseData.input + preRun.input),
а не только верхний — без этого регистры, созданные через preRun, оставались
без документа-регистратора и платформа отвергала конфиг с
«Ни один из документов не является регистратором».

Добавлен случай ChartOfAccounts: при maxExtDimensionCount>0 (или непустых
extDimensionAccountingFlags) и без явной ссылки extDimensionTypes
автоматически создаётся стаб ChartOfCharacteristicTypes и линкуется через
meta-edit modify-property уже после preRun. Для этого getStructuralDeps
возвращает теперь { deps, hostEdits }, а в основной поток добавлен Step 3.5
(host-level structural edits).

InformationRegister с writeMode=Subordinate/RecorderSubordinate тоже
получает документ-регистратор.

Полный прогон verify-snapshots: 193/193.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 20:12:12 +03:00
Nick Shirokov 704fbc9f28 feat(verify-snapshots): платформенная верификация mxl-compile
Готовый Template.xml оборачивается в исходники EPF: epf-init создаёт
скелет, template-add регистрирует SpreadsheetDocument-макет, MXL копируется
поверх дефолтного, далее epf-build реально проверяет, что платформа
принимает разметку. mxl-compile убран из STANDALONE_SKILLS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 16:59:06 +03:00
Nick Shirokov cd74afa5e0 feat(verify-snapshots): платформенная верификация template-add и help-add
После main-скрипта определяется тип артефакта в workDir: Configuration.xml
→ обычная загрузка конфигурации, иначе по корню *.xml выбирается ветка
epf-build (.epf для ExternalDataProcessor, .erf для ExternalReport). Для
кейсов с cf-init теперь configDir переустанавливается на workDir, так что
конфиг действительно грузится в БД, а не пропускается.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 16:42:00 +03:00
Nick Shirokov 370873511d feat(verify-snapshots): платформенная верификация epf-init и erf-init
EPF_SKILLS превращён из «skip» в реальную сборку через epf-build —
строится .epf или .erf по расширению из map. Имя источника берётся
из caseData.params.name. erf-init добавлен в DEFAULT_SKILLS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 15:25:20 +03:00
Nick Shirokov 9ced410d8f feat(verify-snapshots): платформенная верификация skd-edit
skd-edit добавлен в SKD_PLATFORM_VERIFY — результат заворачивается в ERF и
собирается через epf-build, как уже сделано для skd-compile. Резолвер пути
шаблона теперь учитывает params.templatePath (фолбэк: outputPath, Template.xml).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 15:09:38 +03:00
Nick Shirokov 204a262746 feat(verify-snapshots): реальная платформенная проверка skd-compile
До сих пор для skd-compile (как и других STANDALONE_SKILLS)
verify-snapshots просто запускал скрипт и помечал PASS — без
платформенной нагрузки. Опасный пробел: можно было закоммитить
snapshot, который 1С Designer не примет.

Теперь для skd-compile snapshot оборачивается во внешний отчёт
(erf-init --WithSKD), Template.xml подменяется на сгенерированный
кейсом, и запускается erf-build. Платформа парсит схему — если
принимает, кейс PASS; если отклоняет, в errors попадает её stderr.
Ссылочные типы (CatalogRef.X и т.п.) не требуют реальной базы:
epf-build сам поднимает временную stub-конфигурацию.

Если v8 недоступен — мягкий skip с пометкой "no v8 context".

Замер: 21 кейс x ~5s avg = ~110s на полный verify-snapshots
--skill skd-compile. Все 21 текущих кейса проходят — значит каждый
snapshot гарантированно платформо-валиден.

Аналогичная обёртка для mxl-compile / role-compile — отдельной
задачей по образцу.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 18:56:13 +03:00
Nick Shirokov 576f6dda8a feat(skd-compile): многоязычный title/presentation (объектная форма)
Везде, где DSL принимает title/presentation, теперь поддерживается
объектная форма с языками: "title": { "ru": "...", "en": "..." }.
Строка по-прежнему работает как ru-only.

Покрыто: field title, calculatedField title, parameter title/presentation,
settingsVariant title/presentation (root и в structure-items),
availableValue title/presentation, userSettingPresentation в filter/dataParameter,
mltext-значения в conditionalAppearance.appearance (ключи Текст/Заголовок/Формат).

Реализация:
- Хелпер emit_mltext / Emit-MLText расширен — принимает string|dict и
  итерирует по языкам.
- 8 inline-блоков LocalStringType в каждом скрипте заменены на вызовы
  хелпера (унификация — побочный эффект, бенефит на будущее).
- На входе сняты str()/"$()" коэрции для title/presentation, чтобы dict
  доходил до хелпера живым.

- SKILL.md: одна строка про объектную форму title.
- tests: новый snapshot-кейс multi-lang-title (5 узлов с ru+en).
- Версия v1.21.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 18:30:37 +03:00
Nick Shirokov 1a5b788305 feat(skd-compile): составной тип поля valueType (массив типов)
В объектной форме поля DataSet ключ "type" теперь принимает массив:
"type": ["CatalogRef.A", "CatalogRef.B"] — генерирует несколько <v8:Type>
внутри одного <valueType>. Типичный паттерн в ERP для полей-расшифровок
с составным ссылочным типом.

Shorthand остаётся одно-типовым (без перегрузки). Квалификаторы
((N)/(D,F)) применяются к каждому элементу массива независимо.

- skd-compile.ps1/py: Emit-ValueType/emit_value_type диспатчат на
  Emit-SingleValueType при строке или итерируют при массиве; field-парсер
  сохраняет массив, не приводя к строке. Версия v1.20.
- SKILL.md: один абзац после описания типов.
- tests: новый snapshot-кейс field-multi-type на 3 ссылочных типа.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 18:04:49 +03:00
Nick Shirokov b39da27d20 docs(skd-compile): описать presentationExpression и appearance на поле
В DSL skd-compile уже поддерживались ключи presentationExpression и
appearance в объектной форме поля DataSet, но в SKILL.md они не были
задокументированы — фичи существовали де-факто, но обнаружить их можно
было только чтением скрипта.

Заодно зафиксирован детерминизм порядка ключей appearance: PS5.1
hashtable не сохраняет порядок вставки, из-за чего PS- и PY-рантаймы
давали разный XML на одном входе. Заменено на [ordered]@{}.

- SKILL.md: новый блок «Дополнительные ключи объектной формы» в разделе «Поля»
- skd-compile.ps1/py: appearance = [ordered]@{} вместо @{}, версия v1.19
- tests: новый snapshot-кейс field-appearance-and-presentation,
  проходит на обоих рантаймах

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 17:57:04 +03:00
Nick Shirokov eda7279de0 fix(skd-info): -Mode full на схеме без DataSetQuery
Show-Query/show_query при отсутствии DataSetQuery делал exit 1, что
обрывало full режим после Show-Overview — секции fields/resources/
params/variant пользователь не видел. Теперь в full проверяем наличие
Query-набора и при отсутствии печатаем "(no query datasets)" и
продолжаем. Прямой -Mode query сохраняет прежнее поведение.

Воспроизводилось на схемах-приёмниках с одним DataSetObject
(например, ЖурналОшибок в ERP).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 16:38:57 +03:00
Nick Shirokov b7fbede819 fix(tests): починить pre-existing фейлы integration и skd-* snapshots
- build-config/build-epf: заменить runtime-тип FormDataStructure на корректный *Object.XXX
- platform-cfe/config/epf: form-compile принимает -OutputPath (путь до Form.xml), не -FormPath
- skd-edit/info/validate: перегенерированы snapshots после feat(skd-compile) denyIncompleteValues=true (3729b63)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 15:48:23 +03:00
Nick Shirokov bdc38caffa refactor(form-add): объединить с epf-add-form, удалить специфичный навык
form-add теперь покрывает и объекты конфигурации, и standalone EPF/ERF
source tree (тип определяется из корневого XML, маппинг типов уже был).

Изменения form-add scaffold:
- Module.bsl: пустые регионы вместо скелета процедуры ПриСозданииНаСервере
- Form.xml: убран <Events> (раньше привязывал OnCreateAtServer к процедуре)
- Form.xml: <SavedData>true</SavedData> теперь условный — ставится для
  Catalog/Document/etc (стандарт ERP, 99% форм), не ставится для
  DataProcessor/Report/External* (где у объекта нет состояния)

Это согласуется с workflow: form-compile перегенерирует Form.xml целиком,
поэтому привязки в scaffold могут стать orphan; пустые регионы +
без Events — корректная стартовая точка, которую form-edit/form-compile
наполняют атомарно.

Удалён навык epf-add-form (директория + тесты), вызовы заменены на
form-add в integration-тестах, в кейсах epf-validate/help-add, в
description epf-init/epf-bsp-init, в docs и README.

Перегенерированы snapshot'ы 5 навыков (form-add, form-compile,
form-edit, form-info, form-validate). Платформенная верификация в 1С 8.3.24
прошла для всех 9 кейсов form-add.

Bump form-add v1.3 → v1.4.
2026-04-25 15:26:54 +03:00
Nick Shirokov 3729b63b89 feat(skd-compile): @autoDates — дефолты use=Always + denyIncompleteValues=true
Производные &НачалоПериода/&КонецПериода требуют заполненный период,
поэтому сам параметр теперь по умолчанию получает use=Always и
denyIncompleteValues=true. В объектной форме явные значения перекрывают.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:24:22 +03:00
Nick Shirokov 54d47aadad feat(skd-compile): dataParameters auto — копирование value всех типов (ЕРП-паттерн)
Раньше "auto" копировал только variant для StandardPeriod, остальные типы
теряли значение по умолчанию. Теперь:

- value задан (не-Custom для StandardPeriod) → value + use=true (implicit),
  правильный xsi:type: boolean/decimal/dateTime/string, DesignTimeValue для
  ссылочных типов.
- value отсутствует или StandardPeriod=Custom → <use>false</use>
  + <value xsi:nil="true"/>.

Соответствует тому, как 1С Designer и ЕРП-отчёты персистят
SettingsParameterValue. Тест auto-data-parameters расширен покрытием
decimal/string/ref/nil.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:13:04 +03:00
Nick Shirokov 3f23be8219 feat(skd-compile): @autoDates — НачалоПериода/КонецПериода вместо ДатаНачала/ДатаОкончания
Канонический паттерн БСП в Титан/ЕРП-отчётах использует имена
НачалоПериода/КонецПериода (~10:1 по частоте). Выражения
&Период.ДатаНачала/&Период.ДатаОкончания сохранены — это обращение
к внутренним полям StandardPeriod.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:51:22 +03:00
Nick Shirokov f5dd677ac8 fix(tests): cf-info/config-with-objects — preRun через meta-compile
Тест сломался с 0d5d345 (ужесточение cf-edit add-childObject: теперь требует, чтобы файл объекта существовал на диске). Там были пофикшены 4 теста cf-edit, но этот кейс cf-info с тем же паттерном в preRun пропустили.

Заменил cf-edit add-childObject на три meta-compile (Catalog.Товары, Document.Заказ, Enum.Статусы) — те сами регистрируют объекты в Configuration.xml и создают файлы. Snapshot перегенерирован.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:08:37 +03:00
Nick Shirokov be74d224be feat(skd-compile): dataParameters auto — наследовать variant для StandardPeriod
Для параметров типа StandardPeriod в режиме "dataParameters": "auto" эмитируется <dcscor:value> с variant из дефолта параметра (Custom, если не задан) — как это делает 1C Designer при сохранении SettingsParameterValue для периодов.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 21:00:58 +03:00
Nick Shirokov 1b46eb4d85 feat(skd-compile): parameters — title и presentation как синонимы
- parameter принимает presentation как синоним title (1C UI показывает
  подпись параметра как "Представление" — модель по аналогии пишет presentation)
- availableValues[] принимает title как синоним presentation (обратная
  ошибка: модель пишет title по аналогии с самим параметром)

Обе формы пишутся в один и тот же XML-узел. Версии: skd-compile v1.13 → v1.14.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:37:00 +03:00
Nick Shirokov 1cea9e794e feat(skd-compile,skd-edit): calculatedFields — shorthand и объектные синонимы
- skd-compile v1.13: Parse-CalcShorthand теперь понимает "[Title]:type=expr#flags"
  (синхронно со skd-edit). Emit-CalcFields принимает name как синоним
  field/dataPath и строковую форму useRestriction ("#noField #noFilter ...").
- skd-edit v1.11: #restrict парсится по known-names pattern — исключает ложные
  срабатывания на # внутри строковых литералов в выражении.

Закрывает три ловушки из upload/bug-skd-compile-calculated-field-datapath.md,
где модель писала name вместо field и строковый useRestriction по аналогии
с shorthand-флагами.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 20:31:14 +03:00
Nick Shirokov aedf6df674 fix(form-compile,meta-compile): PY ChartOfAccounts generators — list format + AccountingFlag name extraction
- form-compile.py: rewrite generate_chart_of_accounts_item_dsl and
  generate_chart_of_accounts_folder_dsl from dict-format to list-format
  (array of OrderedDict), matching PS1 canonical output
- meta-compile.py/ps1: extract flag['name'] from AccountingFlags and
  ExtDimensionAccountingFlags dicts instead of stringifying the whole object
- Update snapshots with clean flag names (Валютный/Количественный)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:55:33 +03:00
Nick Shirokov 2206c4cf3e fix(form-compile): convert new generators from dict to array DSL format
Root cause: new generators (IR, AccumReg, CoA, CCOCT/EP wrappers) used
OrderedDict for elements/columns, but PS1 compiler expects array format.
ConvertTo-Json→ConvertFrom-Json wraps dict into single PSCustomObject,
not iterable array — so ChildItems were empty.

Converted all new generators to array format matching existing
Document/Catalog patterns: elements=@(), columns=@().

Also fixed CCOCT/EP wrapper inject logic to iterate array elements
instead of dict keys.

PS1: 12/12, PY: 8/12 (minor case/autofill differences in PY port).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:11:55 +03:00
Nick Shirokov 8a9f285da9 fix(form-compile): port bugfixes to Python — Number/Date in lists, UserVisible for Ref
Port PS1 bugfixes to Python:
- Document List: add Номер + Дата as first columns
- Hidden Ref: userVisible=false instead of visible=false (both Catalog and Document lists)
- Emitter: support <UserVisible><xr:Common>false</xr:Common></UserVisible>
- Add userVisible to KNOWN_KEYS

Note: new_field_element calls in Python were already correct (no Bug 1 equivalent).
Python snapshots updated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:55:56 +03:00
Nick Shirokov e5e3f199f2 fix(form-compile): empty forms, missing Number/Date in lists, UserVisible for Ref
Three bugs fixed in --from-object PS1 generators:

1. New-FieldElement called with wrong positional args in IR Record and CoA Item
   generators — hashtable passed as attrName instead of individual fields.
   Result: elements became "System.Collections.Hashtable" → compiler dropped them
   → empty forms. Fixed with named parameters.

2. Document List form missing Number/Date standard columns — only custom
   attributes were shown. Added Номер + Дата as first two columns.

3. Hidden Ref column used Visible=false (element completely hidden from
   "Customize form"). Changed to UserVisible=false so users can enable Ref
   and add sub-columns via dot notation. Matches ERP Контрагенты pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:34:45 +03:00
Nick Shirokov 3ee715939b test(form-compile): regression tests for new --from-object types
8 test cases covering InformationRegister (Record periodic/nonperiodic, List),
AccumulationRegister (List), ChartOfCharacteristicTypes (Item),
ExchangePlan (Item), ChartOfAccounts (Item, List).

All 12 tests pass on both PS1 and Python runtimes with form-validate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:21:46 +03:00
Nick Shirokov a41897a966 test(form-compile): regression tests for --from-object mode
4 snapshot tests: catalog item/list (Валюты-like) + document item/list
(АктВВР-like). Verified against platform 1C 8.3.24. Register
form-compile-from-object in verify-snapshots DEFAULT_SKILLS.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:40:12 +03:00
Nick Shirokov d1e770c843 test(form-edit): declare Поле1 in preRun form-compile attributes
add-element and add-group-with-fields built their baseline form with an
InputField whose DataPath pointed to "Поле1", but "Поле1" was never
declared as a form attribute. runner.mjs snapshot diffing accepted the
output, but verify-snapshots caught the real XDTO error at load time:
"Неверный путь к данным: Поле1".

Add the missing attribute to both preRun form-compile inputs and
regenerate snapshots (the new attribute takes id=5, so form-edit's added
"Поле2" now lands at id=6).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:03:34 +03:00
Nick Shirokov e3069ceb36 fix(form-compile): throw on known invalid attribute types
KNOWN_INVALID_TYPES (FormDataStructure, FormDataCollection, FormDataTree,
etc.) was checked but only produced a Write-Warning/print warning — the
script still emitted the bad <v8:Type> into Form.xml, which XDTO later
rejected with a cryptic load-time error. Turn the warning into a hard
throw so misuse is caught at compile time with the correct hint.

Reveals two broken test cases that shipped invalid forms:
- form-compile/catalog-form: main attribute was FormDataStructure, fixed
  to CatalogObject.Товары (what ERP's reference catalog forms actually
  use with the cfg: prefix).
- form-info/overview: preRun form-compile used the same wrong type, fixed
  the same way; snapshot regenerated.

Bumps form-compile to v1.4 on both runtimes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:03:24 +03:00
Nick Shirokov 0b2c09f8d9 fix(verify-snapshots): support case fixture setup and workDir cwd
Two harness gaps that masked real issues and leaked stray files:

1. Case-level `setup: "fixture:<name>"` was ignored — runner.mjs handled
   it, verify-snapshots did not. skd-edit/add-drilldown silently failed
   with "File not found: Template.xml" because the fixture never reached
   workDir. Added Step 0 fixture copy mirroring runner.mjs behavior.

2. `skillConfig.cwd === "workDir"` was ignored — main skill always ran
   with cwd=REPO_ROOT. mxl-compile cases pass relative -OutputPath
   "Template.xml", which landed in the repo root on every run. Plumb cwd
   through execSkill and set mainCwd from skillConfig.cwd.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:03:11 +03:00
Nick Shirokov 0d5d3451ff fix(cf-edit): reject add-childObject when object file is missing
cf-edit add-childObject was a low-level XML-manipulation operation
with no file-existence validation — callers could register a reference
to any Type.Name in Configuration.xml's ChildObjects without the
underlying file existing on disk. Platform then refused to load:
"Файл объекта не существует".

The 4 failing tests (add-objects, remove-object, add-default-role,
set-default-roles) all used this operation with fake references in
either main input or preRun, and had no way to pass verify-snapshots
because the cf-init-ed config had no actual object files.

User observation: this is the tests being wrong, not the skill.
meta-compile/role-compile/subsystem-compile already auto-register
every new object in Configuration.xml as part of their normal flow
(meta-compile.ps1:2949-3068, role-compile.ps1:667-747,
subsystem-compile.ps1:430-506). Nobody should be calling cf-edit
add-childObject to create a new object — they should be calling the
profile skill. cf-edit add-childObject is only for rare recovery
scenarios: rolled-back Configuration.xml with intact object files,
re-import from DB dump that clobbered the root but left srcfiles.

Changes:

1. cf-edit.ps1/py: Do-AddChildObject now checks that the target file
   exists at {ConfigDir}/{PluralDir}/{Name}.xml before registering.
   On miss, exits 1 with a message that names the expected path and
   points the user at the right skill (/meta-compile, /role-compile,
   or /subsystem-compile depending on type). TYPE_TO_DIR mapping for
   all 44 metadata types covers irregular plurals (FilterCriteria,
   BusinessProcesses, ChartsOfAccounts, ChartsOfCharacteristicTypes,
   ChartsOfCalculationTypes).

2. Tests: 4 existing cases rewritten to build realistic fixtures via
   meta-compile/role-compile preRun (both skills auto-register, so
   the resulting Configuration.xml already references the preRun
   objects). add-objects now exercises the round-trip recovery
   scenario: meta-compile creates Catalog.Товары and Document.ПриходТоваров
   (auto-registered) → cf-edit remove-childObject un-registers both
   (files remain) → main run re-registers via add-childObject. This
   tests exactly the rollback-recovery use case the operation exists for.

3. New add-missing-errors case: negative test with expectError:
   "Object file not found". Verifies the new hard-error path.

4. verify-snapshots.mjs: added symmetric expectError handling (runner.mjs
   already had it at line 514). If caseData.expectError is set,
   expect skill to fail; check stderr substring match; skip db-load
   and mark passed. Without this, negative tests would go red in
   verify-snapshots even though runner.mjs accepts them.

5. SKILL.md / reference.md: documented the new constraint and the
   redirection to profile skills. Kept mention of legitimate use case
   (rollback recovery).

Bumped cf-edit.ps1/py v1.0→v1.1.

Verification:
- runner --filter cf-edit (PS1): 2/6 → 7/7 (6 positive + 1 negative)
- runner --filter cf-edit --runtime python: 7/7 (dual-port clean)
- verify-snapshots --skill cf-edit: 2/6 → 7/7

With this landed P3 from debug/snapshot-verify/NEXT-STEPS.md is closed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 20:18:05 +03:00
Nick Shirokov 7a8f437e77 test(subsystem-compile): cover bottom-up -Parent flow; hide children shortcut
The bottom-up flow (compile child with -Parent pointing at parent's
XML — skill creates the real child file AND registers it in parent's
ChildObjects) has been the documented canonical way to build nested
subsystems since forever. It's in SKILL.md Примеры:58 and implemented
in subsystem-compile.ps1:430-506. But zero test cases exercised it —
all 7 pre-existing cases used the top-down `children: [...]` shortcut
that aa93031 made honest with stubs.

Two problems with the status quo:

1. A model reading SKILL.md saw `"children": ["ДочерняяА", "ДочерняяБ"]`
   right in the main JSON-definition example and took it as the
   canonical way to create nested structure. It's a trap — the
   shortcut creates placeholder stubs with empty Synonym/Content that
   the model almost never actually wants. The natural flow (one
   subsystem-compile call per real subsystem) wasn't visible where
   the model looks first.

2. The canonical flow had no test safety net — nothing caught regressions
   in the register-in-parent code path (lines 430-506).

Fix, minimal surface:

- SKILL.md: remove `"children": [...]` from the JSON-definition example.
  Leave the `-Parent` example in the Примеры section (already there).
  The children field stays fully supported in the scripts (aa93031 stub
  behavior unchanged) for legacy JSON — just not advertised.

- New test case `nested-parent.json`: preRun compiles "Продажи" parent,
  main run compiles "Настройки" child with `-Parent Subsystems/Продажи.xml`.
  Verifies the real bottom-up flow: snapshot shows full child file with
  real Synonym/Explanation AND parent's `<ChildObjects>` updated to
  reference the child. verify-snapshots confirms platform accepts it.

- Runner plumbing: `_skill.json` gains `{ "flag": "-Parent", "from":
  "workPath", "field": "parent", "optional": true }`. Required extending
  both `tests/skills/runner.mjs` and `tests/skills/verify-snapshots.mjs`
  (they each have their own copy of buildArgs) to support `optional: true`
  on workPath mappings — otherwise existing cases without params.parent
  would get the flag pushed with an empty value.

Verification:
- runner --filter subsystem-compile (PS1): 8/8 (was 7/7 +1)
- runner --filter subsystem-compile --runtime python: 8/8 (dual-port clean)
- verify-snapshots --skill subsystem-compile: 8/8

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 19:15:07 +03:00
Nick Shirokov 6805b9da02 fix(subsystem-edit): write stub XML on add-child operation
Do-AddChild / do_add_child added `<Subsystem>Name</Subsystem>` to the
parent's `<ChildObjects>`, but never wrote the corresponding
`Subsystems/{Parent}/Subsystems/{Name}.xml` file. Same silent-drop
pattern that bit subsystem-compile (aa93031): platform used to swallow
the missing-file reference, `-StrictLog` now surfaces it as "Файл
объекта не существует" and fails add-child on load.

Both ports now mirror the subsystem-compile fix:
- Write-ChildSubsystemStub / write_child_subsystem_stub helpers
  duplicated from subsystem-compile (per memory rule "skills are
  autonomous, duplication acceptable")
- format_version read from loaded XmlDoc root (no need to walk up
  to Configuration.xml — we already have the parent XML in memory)
- Stub creation guarded by Test-Path / os.path.exists so a pre-existing
  real child file is never clobbered

Bumped subsystem-edit.ps1 v1.1→v1.2 and subsystem-edit.py v1.1→v1.2.

Verification:
- verify-snapshots --skill subsystem-edit: 3/4 → 4/4
- runner --filter subsystem-edit (PS1): 4/4
- runner --filter subsystem-edit --runtime python: 4/4 (dual-port drift clean)

With this landed P1 from debug/snapshot-verify/NEXT-STEPS.md is fully
closed: subsystem-compile 7/7, subsystem-edit 4/4, interface-edit 4/4,
role-compile 8/8, meta-compile 30/30.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:49:40 +03:00
Nick Shirokov aa93031a3f fix(subsystem-compile): write stub XML for declared children
When a subsystem definition includes `children: [...]`, the parent XML
was emitted with `<ChildObjects><Subsystem>Name</Subsystem></ChildObjects>`
refs, but the referenced `Subsystems/{Parent}/Subsystems/{Child}.xml`
files were never created. Before 96d1dea (-StrictLog) the platform
silently dropped the refs on load (exit 0), so verify-snapshots showed
these cases green. With the new strict log parsing, `full` and
`with-children` started failing on "Файл объекта не существует".

Both PS1 and PY ports now emit a minimal valid child subsystem stub
(full MetaDataObject, empty Synonym/Content/ChildObjects) via new
Write-ChildSubsystemStub / write_child_subsystem_stub helpers. Stub
creation is guarded by Test-Path / os.path.exists, so a subsequent
compile of the same child via -Parent does not get clobbered, and
re-running the parent compile is idempotent. Дубли в children[]
дедуплицируются через seen-set.

Also removed the "Что генерируется" section from SKILL.md — filesystem
layout is covered by the OutputDir param + [OK] stdout lines; the
section was noise for model consumers.

Bumped subsystem-compile.ps1 v1.4→v1.5 and subsystem-compile.py
v1.3→v1.5 (PY caught up with PS1 version pin).

Verification:
- verify-snapshots --skill subsystem-compile: 5/7 → 7/7
- runner --filter subsystem-compile (PS1): 7/7
- runner --filter subsystem-compile --runtime python: 7/7 (dual-port drift clean)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:38:03 +03:00
Nick Shirokov 9cbda1989a test(meta-compile/document-journal): preRun creates documents with referenced attributes
Journal column references require the referenced document attribute to
actually exist at load time. Previously the test DSL relied on the
verify-snapshots stub mechanism, which creates minimal Document stubs
without the specific attributes the column refs point to → load failed
with "Неизвестный объект метаданных - Document.ПриходнаяНакладная.Attribute.Склад".
This was listed as D5 in the 2026-04-05 FINDINGS log ("low priority,
complex to implement").

Now the test case declares preRun steps that create both documents
with the exact attributes its journal columns reference (Склад on one,
Контрагент on both). Column "Контрагент" gained explicit references
(was a shorthand string before) because the platform rejects journal
columns without at least one reference at load time.

Regenerated the snapshot (gained Documents/ subtree from preRun output).
verify-snapshots --skill meta-compile is now 30/30 green with -StrictLog.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:00:34 +03:00
Nick Shirokov d34ddd41ff fix(meta-compile): strip FillFrom/FillValue/DataHistory for non-Info register attributes
Custom attributes on AccumulationRegister, AccountingRegister and
CalculationRegister do NOT support FillFromFillingValue, FillValue or
DataHistory — platform logs "Неверное свойство объекта метаданных" and
silently drops them. InformationRegister DOES support these properties
(verified against erp_8.3.24 dump for both variants).

Split the single "register" Emit-Attribute context into:
  - register-info  → emits the three properties (InformationRegister)
  - register-other → skips them (Accum/Acc/Calc)

Chart* context already handled by 3ba6072 remains as-is. Extended the
exclusion list in Emit-Attribute to cover register-other symmetrically
for FillFromFillingValue, FillValue and DataHistory.

Updated snapshots:
  - accounting-register: removed the 3 bad lines on Содержание attribute
  - accumulation-register/calculation-register: added test attributes
    to exercise the register-other path and regenerate snapshots cleanly

Closes the silent-rejection class #4 from upload/form-baseline/gotchas.md,
now caught by verify-snapshots -StrictLog on the E2E platform load.

Bumped meta-compile.ps1 + .py to v1.8.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:00:12 +03:00
Nick Shirokov 96d1dea552 fix(db-load-xml): surface silent platform rejections + opt-in -StrictLog
Platform writes load-time property/type/enum rejections ("Неверное
свойство объекта метаданных", "Неизвестное имя типа" и т.п.) into the
/Out log but still exits with code 0, silently dropping the offending
metadata. db-load-xml now parses the log for these patterns and prints
a yellow "[warning] N rejection(s)" block to stdout so users (and the
model) can see them immediately.

Exit code still mirrors the platform by default — we don't second-guess
its verdict. With the new -StrictLog switch, rejection patterns are
elevated to exit code 1, which is the mode verify-snapshots.mjs uses
for honest E2E verdicts. All three db-load-xml call sites in the
verifier (main config, CFE base, CFE extension) now pass -StrictLog.

Found while investigating upload/form-baseline/gotchas.md #4 where AR
attribute emission was wrong but verify-snapshots showed green because
the old exit-code-only check missed the silent drops.

Bumped db-load-xml.ps1 + .py to v1.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 17:59:50 +03:00
Nick Shirokov 83b289de32 feat(skd): canonical @autoDates pattern + new params operations + use preservation
Fix-pack from skills-improvements-v4 feedback addressing 6 issues found
during real-world ФСД report development.

skd-compile (v1.10 → v1.11):
- @autoDates: emit canonical БСП pattern for ДатаНачала/ДатаОкончания —
  with title, useRestriction=true, value 0001-01-01T00:00:00, expression.
  Removed availableAsField=false so БСП creates two separate Start/End
  fields in the quick settings panel (was rendering as a single picker).
- StandardPeriod value: always emit v8:startDate/v8:endDate to match how
  1C Designer saves the schema (avoids spurious diff on first re-save).
- parameter shorthand: support [Title] syntax mirroring add-field.

skd-edit (v1.9 → v1.10):
- modify-filter / modify-dataParameter: preserve <use> when @off/@on not
  explicitly set (was silently stripping <use>false</use>). Tristate
  parser: None=don't touch, False=@off, True=@on.
- modify-parameter: support [Title] for setting/replacing <title>.
- rename-parameter: new operation "OldName => NewName" — atomically
  renames parameter, updates &Name references in expressions of other
  parameters (full identifier match only), and dcscor:parameter entries
  in dataParameters of all variants. Query text is not touched.
- reorder-parameters: new operation "Name1, Name2, ..." — partial list,
  named params go first in given order, rest preserve original order.
- StandardPeriod value: same v8:startDate/v8:endDate fix as compile.

Tests: 4 new test cases (rename-parameter, reorder-parameters,
modify-parameter-title, modify-dataParameter-preserves-use).
48/48 passing on both PowerShell and Python runtimes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 21:22:40 +03:00
Nick Shirokov 384e68cab4 fix(skd-compile): object-form structure, OrGroup string items, useRestriction alias
- Default structure item type to 'group' when omitted; accept groupFields as alias for groupBy
- Parse string shorthand items inside OrGroup/AndGroup/NotGroup filter recursion
- Accept useRestriction key (object form { field: true }) alongside restrict array
- Deduplicate SelectedItemAuto in skd-edit add-selection
- Update SKILL.md with object structure and useRestriction docs
- Add test cases for all 4 fixes

skd-compile v1.9→v1.10, skd-edit v1.8→v1.9

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 14:54:38 +03:00
Nick Shirokov 46e065adb9 feat(skd-edit): add-drilldown operation for connecting DrillDown to DCS template resources
Adds DetailsAreaTemplateParameter + Расшифровка appearance binding
to all named templates for each specified resource. Comma-separated
value list, idempotent, nesting-aware template scan.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:36:50 +03:00
Nick Shirokov fdfe4ac2f4 fix(skd-edit): parse #restriction flags in add-calculated-field shorthand
Previously #noFilter/#noOrder/#noGroup flags were included verbatim in
<expression> instead of generating <useRestriction>. Now parsed and
handled identically to add-field.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 19:34:55 +03:00
Nick Shirokov e2924c4ae0 fix(skd-compile): remove spurious vMerge flag from source cells in template DSL
The vertical merge flag (ОбъединятьПоВертикали) was incorrectly placed on
both the source cell (with content) and continuation cells ("|"). 1C only
expects it on continuation cells. Removed startsVMerge logic from both
PS1 and PY scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 16:49:56 +03:00
Nick Shirokov d3520a8945 fix(skd-edit): modify-parameter availableValue parsing and formatting bugs
Fix 3 bugs in modify-parameter: (1) first availableValue rendered as raw
text when combined with other kv pairs in same batch entry, (2) presentation
values with spaces truncated by \S+ regex, (3) denyIncompleteValues/use
inserted without line breaks. Root cause: if/else on rest.startsWith
missed availableValue when preceded by other keys. Also fix namespace-aware
element lookup using LocalName/local_name instead of SelectSingleNode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 21:34:04 +03:00
Nick Shirokov e731bde7f0 feat(skd-compile): horizontal cell merge ">" in template DSL
Add ">" cell syntax for horizontal merge (ОбъединятьПоГоризонтали),
analogous to "|" for vertical merge. Enables two-level headers with
colspan in DCS templates. Also fix PY decimal formatting (30.0 → 30).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 20:41:47 +03:00
Nick Shirokov 9727635e5d test(skd): add snapshot tests for new features
- skd-edit: conditionalAppearance with DesignTimeValue/OrGroup/Format
- skd-edit: modify-parameter with use/denyIncompleteValues/availableValue
- skd-edit: set-structure @name= + add-selection Folder() @group=
- skd-compile: availableValues/denyIncompleteValues + Folder in selection
- Fix xsi namespace in @group= XPath query

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:42:12 +03:00
Nick Shirokov 3ba6072660 fix(meta-compile): strip FillFromFillingValue/FillValue/DataHistory for Chart* attributes
ChartOfAccounts, ChartOfCharacteristicTypes, ChartOfCalculationTypes
attributes don't support FillFromFillingValue, FillValue, DataHistory
properties — platform rejects them with "Неверное свойство объекта
метаданных". Add "chart" context to Emit-Attribute to skip these.

Found via platform snapshot verification (Finding A1).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:11:47 +03:00
Nick Shirokov 20adf4f463 fix(tests): correct ExternalDataProcessorObject→DataProcessorObject in config-context DSLs
Fix test DSLs that used ExternalDataProcessorObject (EPF type) for
DataProcessors inside configurations. Also fix: chart-of-accounts
(remove maxExtDimensionCount without ПВХТ), calculation-register
(remove actionPeriod without infrastructure), document-multiple-tabparts
(remove registerRecords referencing non-existent register),
role-compile/explicit-rights (add dimensions to empty InformationRegister).

Regenerated all affected snapshots.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:10:49 +03:00
Nick Shirokov d5aacc9e60 fix(form-validate): context-aware Check 12 — ExternalDataProcessorObject is error in config
Detect config vs EPF context by walking up from FormPath looking for
Configuration.xml. ExternalDataProcessorObject/ExternalReportObject are
valid in EPF/ERF but cause XDTO exception in configuration context.

- EPF forms: no warning (ExternalDataProcessorObject is correct)
- Config forms: ERROR with hint to use DataProcessorObject/ReportObject
- Fix test DSLs: compiled-form, table-form used wrong External* type

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:01:24 +03:00
Nick Shirokov b0fdc32053 feat(tests): verify-snapshots v0.3 — CFE support, preRun ref scanning, full coverage
- Add two-stage CFE pipeline: load base config → load extension
- Scan preRun inputs for type refs (fixes D3: meta-edit/add-ts-attribute)
- Support args-only cases (cf-init, form-add, epf-init, template-add, etc.)
- Add InformationRegister stubs with dimension (fixes D6)
- Results: 134/145 verified (16 new CFE cases all pass)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 19:43:42 +03:00