Commit Graph

439 Commits

Author SHA1 Message Date
Nick Shirokov fb58a04700 feat(web-test): getFormState — полные reportSettings + chip-значения
На DCS-формах возвращались только настройки с явным чекбоксом «Использование» — остальные (всегда включённые) отбрасывались и пропадали из fields[]. Reference-поля с chip-контролом возвращали пустое value, потому что значение живёт в .chipsItem .chipsTitle, а не в input.value.

- DCS-группировка больше не требует наличия «Использование»; при его отсутствии setting.enabled = true (настройка всегда активна)
- При чтении input.value делается fallback на .chipsItem .chipsTitle в LABEL-родителе — через запятую, если значений несколько (первый элемент + «+N» при свёртке в UI)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 17:18:48 +03:00
Nick Shirokov a30b720c89 docs(skd-compile): SKILL.md — упростить описание @autoDates и dataParameters auto
Убрать XML-детали (useRestriction, xsi:type, <use>false</use>, <value xsi:nil>);
описывать поведение с точки зрения автора СКД, а не внутреннего представления.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 16:17:16 +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 02e9053d00 feat(cf-validate,cfe-validate,epf-validate): поддержка платформы 8.5 (issue #13)
- `CompatibilityMode`, `ConfigurationExtensionCompatibilityMode`: добавлен `Version8_5_1`
- `InterfaceCompatibilityMode`: расширен до полного списка из 7 значений (Version8_2, Version8_2EnableTaxi, Taxi, TaxiEnableVersion8_2, TaxiEnableVersion8_5, Version8_5EnableTaxi, Version8_5) — заодно учтены недостающие 8.2-значения
- Принимается `version="2.21"` в заголовке MetaDataObject
- cf-edit/reference.md: обновлена таблица допустимых значений

Genrators (form-compile, form-add, cfe-borrow и др.) уже подхватывают версию формата через Detect-FormatVersion — не трогаем.

Closes #13

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:08:27 +03:00
Nick Shirokov bd462f4cc3 fix(web-test): hasVisibleModal — handle duplicate #modalSurface
1С оставляет стейл-элемент #modalSurface (display:none) после закрытия
формы и создаёт второй при открытии новой модалки — в DOM оказывается два
элемента с одинаковым id. getElementById возвращал первый (скрытый), из-за
чего detectForm/detectForms не видели активную модалку: getFormState
выдавал form+buttons от родительской формы, а clickElement кликал мимо
или падал.

Сканируем все #modalSurface через querySelectorAll и берём первый с
offsetWidth > 0.

Воспроизводилось стабильно на СКД-расшифровке после открытия "Настройки..."
в форме отчёта.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-16 21:24:44 +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 00fafd4af5 fix(web-test): scanSpreadsheetCells — use contentFrame() instead of index-based frame mapping
Replace fragile page.frames()[iframeIdx + 1] with handle.contentFrame() for
reliable iframe-to-Playwright-Frame resolution. The old index arithmetic could
break when 1C web client accumulates extra frames during prolonged sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 18:15:05 +03:00
Nick Shirokov e30b518935 feat(skd-info): auto-resolve object directory path to DCS template
When model passes report/dataprocessor path instead of template path,
scan Templates/*.xml metadata for DataCompositionSchema type and
auto-resolve. Single match → resolve with [i] hint, multiple → list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 17:23:56 +03:00
Nick Shirokov afdfc97fb1 fix(web-test): readSpreadsheet — поддержка text-only и отчётов с числовыми шапками
Рефакторинг buildSpreadsheetMapping на 3-уровневый алгоритм.
- Level 1: якорь по DCS-кодам (К1..Кn) — детерминированный для всех ФСД-отчётов, работает независимо от формата чисел (рубли/тыс/млн).
- Level 2: якорь по форматированным числам (пробел-группировка, запятая-десятичка, ведущий минус) вместо общей проверки — голые целые (коды счетов "50", "51") больше не принимаются за данные.
- Level 3: single-row header fallback для text-only данных и query-console.

Починено:
- ФСД-отчёты с числами в групповых шапках (ДДС по счетам 50/51/52/55/57) — был fallback raw rows, теперь структурированный вывод.
- query() из consoleЗапросов для text-only результатов — был data=[], теперь корректно парсит headers/data.

E2E проверено на titan: 4 отчёта (ДС, 45, 77, Ведомость) + 5 query-кейсов. Регрессий нет.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:38:47 +03:00
Nick Shirokov 82e70d2c30 feat(skd-compile,form-compile): Phase 3 — project-level presets
- skd-compile v1.12: scan-up from OutputPath for presets/skills/skd/skd-styles.json (PS1+PY)
- form-compile presets/README.md: full preset documentation (sections, keys, enums, example)
- docs/form-guide.md: --from-object mode + project-level presets sections
- skd-compile SKILL.md: updated styles search path description

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:08:22 +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 0d31d17204 fix(form-compile): PY register list generators — array format for columns/elements
Fixed IR List and AccumReg List PY generators:
- columns: OrderedDict → list of OrderedDict (matching PS1 array format)
- table element: use 'table' key (not 'element'), 'tableAutofill' (not 'autoCommandBar'), 'None' (not 'none')
- elements: list (not OrderedDict wrapper)

PY tests: 10/12 (2 remaining CoA failures — PY CoA Item generator needs deeper rewrite from dict to list format)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:17:23 +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 b8ab791456 feat(form-compile): add --from-object support for 5 new object types
Add InformationRegister (Record/List), AccumulationRegister (List),
ChartOfCharacteristicTypes (Item/Folder/List/Choice via Catalog delegation),
ExchangePlan (Item/List/Choice via Catalog delegation),
ChartOfAccounts (Item/Folder/List/Choice with AccountingFlags + ExtDimensionTypes).

Generalize extractAttrs → extractFields with tag parameter.
Add preset defaults and erp-standard.json keys for all new types.
Bump version to v1.6 in both PS1 and PY.

Also: form-add now supports AccumulationRegister (PS1+PY).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:21:30 +03:00
Nick Shirokov 97a2ef91d5 fix(form-compile): skip ValueStorage attributes in --from-object mode
ValueStorage is a non-displayable type that cannot be bound to form
elements. Filter it out in all generators: catalog item, catalog/document
list columns, document item (unclaimed + footer).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 19:02:31 +03:00
Nick Shirokov 076bbcb9d5 feat(form-compile): add --from-object mode for auto form generation from metadata
Read 1C object XML (Document/Catalog), apply ERP preset, generate Form.xml
automatically. Supports Item/List/Choice/Folder purposes with auto-resolve
of object path and purpose from OutputPath convention. Also extends DSL
with DynamicList Settings, Table choiceMode/initialTreeView/enableDrag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 18:03:34 +03:00
Nick Shirokov 3c48451704 docs(meta-compile): add new Catalog props and multiline flag to specs
Update meta-dsl-spec.md and types-basic.md reference with:
limitLevelCount, levelCount, foldersOnTop, codeSeries,
subordinationUse, quickChoice, choiceMode, multiline flag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:00:04 +03:00
Nick Shirokov 801ceea2c0 feat(meta-compile): configurable Catalog props, owners, multiLine, fix reservedAttrNames
- Catalog: limitLevelCount, levelCount, foldersOnTop, subordinationUse,
  codeSeries, quickChoice, choiceMode now read from JSON (were hardcoded)
- Catalog owners: new `owners` array property with shorthand normalization
- Attribute MultiLine: configurable via `multiLine: true` or `| multiline` flag
- reservedAttrNames warning: now skipped for tabular/processor-tabular context
- 3 new enum validations: SubordinationUse, CodeSeries, ChoiceMode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 14:54:50 +03:00
Nick Shirokov 63de8bd27c fix(meta-compile,meta-edit,meta-validate): strict enum validation + fix RequireCalculationTypes
Normalize-EnumValue now uses 4-step logic: alias→case-insensitive→
error (if propName known)→pass-through (if unknown). Previously step 3
silently passed invalid values through to XML, causing cryptic 1C
LoadConfigFromFiles errors.

Also fixed RequireCalculationTypes→OnActionPeriod (the former never
existed in 1C; verified against ERP/ACC dumps). Added NotUsed→DontUse
alias, synced meta-edit.ps1 aliases with meta-compile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:29:46 +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 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 dc4ffa1fc8 fix(form-compile): interpolate \$script:formatVersion in <Form> header
Third victim of the d155086 single-quote regression that 037062c
missed. Both <Form> header emissions at lines 1130 and 1140 used
`X '...version="$($script:formatVersion)"...'` — single-quoted, so
the literal text `$($script:formatVersion)` landed in the output
XML instead of the detected version number.

The bug was masked for a week because:
1. form-compile runner tests weren't rerun against the broken script
   after d155086 (snapshots still showed the pre-regression
   `version="2.17"` hardcode)
2. verify-snapshots was already red on form-compile for other reasons
   (P2 XDTO errors in some cases), so nobody noticed the wholesale
   script breakage
3. The .py port uses an f-string and was never broken

Found while auditing whether 037062c was complete — the earlier grep
for `'...\$formatVersion...'` single-line patterns had missed this
because `$($script:formatVersion)` is a subexpression-in-string form
that wasn't in the grep pattern.

Fix: convert both X calls to double-quoted strings with backtick-
escaped inner quotes, matching the 037062c pattern for
role-compile/subsystem-compile. Same approach, same precedent.

Bumped form-compile.ps1 v1.2→v1.3.

Verification:
- runner --filter form-compile (PS1): 0/10 → 10/10
- runner --filter form-compile --runtime python: 10/10 (dual-port clean)
- verify-snapshots --skill form-compile: surfaced from fully-masked
  to 9/10 (only catalog-form still fails — real P2 XDTO issue, not
  \$formatVersion)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:59:26 +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 037062c728 fix(role-compile,subsystem-compile): interpolate \$formatVersion in XML output
Regression introduced by d155086 (auto-detect XML format version):
both scripts emit their root MetaDataObject element via X '...' with
single-quoted strings, which PowerShell does NOT interpolate. As a
result the literal text \$formatVersion landed in the generated XML,
and every load failed with "Неизвестная версия формата \$formatVersion".

This was masked for a week because the broken call sites aren't
version-dependent by themselves — the platform exits with code 1 on
this error, but verify-snapshots hadn't been re-run cleanly since
the offending commit (we only did a scoped role-compile smoke test
that happened to pass for unrelated reasons).

Fixed by switching both single-quoted X '...' calls to double-quoted
X "..." with escaped inner quotes. meta-compile / form-compile /
epf-add-form / help-add / template-add / interface-edit already used
here-strings or \$script:formatVersion with double-quoted wrappers
and were unaffected.

Bumped role-compile.ps1 to v1.5 and subsystem-compile.ps1 to v1.4.
verify-snapshots --skill role-compile now 8/8 green. subsystem-compile
re-verification is pending other unrelated fixes (see NEXT-STEPS.md).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:01:00 +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 afacaa5ade fix(web-test): readSpreadsheet header detection for DCS reports with account codes
- Strict isNumericVal check excludes account codes like "68/78" from being
  treated as data values (require pure digits+spaces+commas)
- Require >=2 numeric cells to identify data rows (fallback to >=1)
- Detect DCS column code rows (К1..Кn) and always prefix with group/superRow
- 3-level header support: superRow values used as prefix when group is empty
- superRow excluded from title/meta section
- Fuzzy column matching in clickElement for short codes ("К6" → "84 / К6")
- Replace newlines with spaces in cell text (innerText instead of textContent)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 19:25:37 +03:00
Nick Shirokov 73242ee60e fix(skd-compile): identity totalField shorthand treated as aggregation function
When totalField shorthand right-hand side is not a known aggregate function
(e.g. "Проверка: Проверка"), emit expression as-is instead of wrapping it
as Проверка(Проверка). Known aggregates (Сумма, Количество, etc.) still wrap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:33:36 +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 123fc41b06 fix(web-test): selection form search order and type dialog fast path
pickFromSelectionForm: swap steps 2↔3 — try Alt+F advanced search
before search input to avoid overlay blocking row clicks.
pickFromTypeDialog: scan visible rows first, fall back to Ctrl+F
only for large virtual lists. Reduces 3s hardcoded wait to ~0.2s
for common case. scanGridRows: add isGroup flag via gridListH check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:43:44 +03:00
Nick Shirokov 338faa253d feat(web-test): multi-row grid support in readTable — split merged headers
readTable now handles multi-row grids (e.g. accounting journal entries)
where a single column header spans multiple data sub-rows:
- "Субконто Дт" with 3 data cells → "Субконто Дт 1", "Субконто Дт 2", "Субконто Дт 3"
- Stacked headers (2+ at same X) matched by Y-order (e.g. "Счет Дт" / "Подразделение Дт")
- getFormState tables[].columns also expanded for consistency
- Flat/simple grids unaffected (no multi-row detection triggers)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:41:58 +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 54c04cfe76 fix(skd): Python 3.13 compatibility fixes
- skd-edit.py: fix (?i) inline regex flag → re.IGNORECASE (Python 3.13 error)
- skd-edit.py: fix "if not sv" on XML element → "sv is None" (FutureWarning)
- skd-edit.py: fix OrGroup filter crash in output description (list vs dict)
- skd-compile.py: wrap dict structure in list before iteration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:48:35 +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 6404016afb feat(skd-edit): add-selection @group= targets named StructureItemGroup
- add-selection supports @group=Name to add selection items to a named grouping instead of variant level
- Finds StructureItemGroup by dcsset:name, falls back to variant level if not found
- Document @group= in SKILL.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:35:07 +03:00
Nick Shirokov 17afd807d2 docs(skd): update SKILL.md for new features
- skd-edit: document modify-parameter, Folder() in selection, @name= in structure, OrGroup/DesignTimeValue/Format in conditionalAppearance
- skd-compile: document availableValues/denyIncompleteValues, Folder in selection, OrGroup, DesignTimeValue, Format as LocalStringType

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:32:14 +03:00
Nick Shirokov 9bfc431a6a feat(skd): @name= in set-structure, Folder in selection
- skd-edit: set-structure supports @name= for naming groupings (e.g. "Поле @name=ДанныеОтчета > details")
- skd-edit: add-selection supports Folder(Title: field1, field2) syntax for SelectedItemFolder
- skd-compile: selection supports {"folder": "Title", "items": [...]} for SelectedItemFolder
- Both generate lwsTitle, nested SelectedItemField items, and placement=Auto

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:23:18 +03:00
Nick Shirokov d755c41233 feat(skd): modify-parameter operation, availableValues/denyIncompleteValues support
- skd-edit: new modify-parameter operation — set use, denyIncompleteValues, add availableValue entries to existing parameters
- skd-compile: availableValues array and denyIncompleteValues in parameter JSON DSL
- Auto-detect DesignTimeValue type for reference values in availableValue entries

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