Commit Graph

559 Commits

Author SHA1 Message Date
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 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 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 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 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 321e426f98 docs(skd): update dsl-spec and guide for new features, fix py compat
- skd-dsl-spec: availableValues/denyIncompleteValues, Folder in selection, DesignTimeValue/OrGroup in filters, Format as LocalStringType
- skd-guide: mention new CA types, Folder, availableValues
- Fix Python 3.13: inline regex flags, element truth-testing, OrGroup desc, dict structure wrap

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:53:04 +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
Nick Shirokov 87e636f644 feat(skd): DesignTimeValue in filters, Format as LocalStringType, OrGroup in conditionalAppearance
- Auto-detect DesignTimeValue type for enum/catalog/chart-of-accounts references in filter values (both skd-edit and skd-compile)
- Treat Формат appearance parameter as v8:LocalStringType (alongside Текст/Заголовок)
- Support OrGroup in conditionalAppearance filters via " or " syntax in skd-edit shorthand
- Bump skd-edit v1.5, skd-compile v1.6

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:15:44 +03:00
Nick Shirokov ae1dcaac07 feat(web-test): detect SpreadsheetDocument state bar (stateText)
Extract info bar messages from .stateWindowSupportSurface elements
into errors.stateText — covers missing parameters, "report not
generated", "settings changed", and "generating..." states.
readSpreadsheet() now includes the state message in its error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:27:24 +03:00
Nick Shirokov d155086444 feat(skills): auto-detect XML format version from Configuration.xml
When working with existing configs dumped from newer platforms (8.3.27+),
XML files use version="2.20" instead of "2.17". Skills now detect the
version from the nearest Configuration.xml walking up the directory tree,
falling back to "2.17" if not found. This prevents format version mismatch
errors during LoadConfigFromFiles.

Updated skills (11): meta-compile, form-compile, form-add, template-add,
cfe-borrow, epf-add-form, help-add, role-compile, subsystem-compile,
interface-edit. Also fixed form-validate to accept version 2.20.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:41:53 +03:00
Nick Shirokov 940eafb8e4 fix(skd-edit): patch-query with empty replacement (delete substring)
.strip()/.Trim() in batch-splitting was stripping the trailing space
of the " => " separator, making " => " (delete) unrecognizable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:02:22 +03:00
Nick Shirokov e4dcef8c90 fix(skd-compile): DesignTimeValue, useRestriction for hidden, named structure groups
- fix: auto-detect DesignTimeValue for ПланСчетов/Справочник/Перечисление/Документ values (#9)
- fix: hidden params auto-set useRestriction=true alongside availableAsField=false (#11)
- feat: named groups in structure shorthand "ИмяГруппы[Поле] > details" (#10)
- version bump: skd-compile v1.5

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:44:14 +03:00
Nick Shirokov 08688f5cab docs(skd): update specs for hidden, valueListAllowed, drilldown, groupHeaderTemplate
- skd-dsl-spec: @valueList, @hidden, field alias, dataParameters auto, drilldown, groupName/GroupHeader
- skd-guide: new parameter flags, dataParameters auto, groupName, drilldown
- 1c-dcs-spec: valueListAllowed element, DetailsAreaTemplateParameter, groupHeaderTemplate

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:36:04 +03:00
Nick Shirokov 1bc5e8f07a feat(skd-compile): hidden, valueListAllowed, drilldown, groupHeaderTemplate, dataPath fix
- fix: calculatedField dataPath fallback from "field" key (#5)
- fix: groupHeaderTemplate vs groupTemplate, groupName support (#7)
- feat: @valueList / valueListAllowed for parameters (#4)
- feat: @hidden / hidden params + "dataParameters": "auto" (#1)
- feat: drilldown in template params — DetailsAreaTemplateParameter + appearance (#2+#3)
- fix(template-add): improved error message with path hint (#6)
- docs: SKILL.md updated with new keys and examples
- version bump: skd-compile v1.4, template-add v1.2

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:17:33 +03:00
Nick Shirokov 358830c65b feat(meta-validate): Check 10 — warn on empty registers and broken RegisterRecords refs
Add two new validations found via platform snapshot verification:
- Registers without any Dimensions/Resources/Attributes → platform rejects
- Document.RegisterRecords referencing non-existent register objects

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 20:27:18 +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 3bd69baae6 fix(form-validate): add ExternalDataProcessorObject/ExternalReportObject to valid cfg prefixes
Check 12 was flagging cfg:ExternalDataProcessorObject.X as "unrecognized cfg
prefix", but this is a valid XDTO type for external data processor (EPF) forms.
Found via snapshot verification against epf-add-form snapshots.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 19:56:47 +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
Nick Shirokov 731a652cae feat(tests): add platform verification script for skill snapshots
Runs each test case through the full pipeline: cf-init → stubs → preRun →
skill script → cf-edit → db-create → LoadConfigFromFiles → UpdateDBCfg.
Handles typed-input, args-only, standalone (SKD/MXL), and EPF skills.

Results: 118/145 pass, findings documented in debug/snapshot-verify/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 19:35:59 +03:00
Nick Shirokov dd88f78969 fix(form-compile,form-validate): warn on invalid XDTO types, add Check 12
form-compile now warns when model uses runtime types like
FormDataStructure that don't exist in XML schema. Expanded cfg:
regex to cover all 25 known prefixes.

form-validate adds Check 12 — validates all <v8:Type> values:
ERROR for known-invalid types, WARN for unrecognized bare types,
pass-through for unknown namespaced types (future-proof).

Updated SKILL.md with full type reference and invalid type warning.
Updated docs/1c-form-spec.md with missing type groups.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 18:07:07 +03:00
Nick Shirokov ff068202e3 fix(tests): update remaining snapshots with plural→singular content refs
Snapshots for subsystem-info and interface-validate still had
Catalogs.Товары from before normalization was added.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 16:48:27 +03:00
Nick Shirokov 91798e3838 feat(interface-edit): normalize command name type prefix (plural/Russian to singular)
All operations (hide, show, place, order) now auto-normalize
the first segment of command names — e.g. Catalogs.X → Catalog.X,
Справочник.X → Catalog.X.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 16:46:01 +03:00
Nick Shirokov 9620c3846a fix(subsystem): normalize content refs — plural/Russian to singular English
subsystem-compile and subsystem-edit now auto-normalize content type
prefixes (Catalogs→Catalog, Справочник→Catalog, Справочники→Catalog).
subsystem-validate detects plural forms as errors in check #6.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 16:39:17 +03:00
Nick Shirokov ffc34904c5 fix(web-test): adaptive header detection threshold for narrow spreadsheets
Hardcoded threshold of 3 non-empty cells prevented header detection in
spreadsheets with 1-2 columns (e.g. query console results). Use
Math.min(3, maxCol + 1) so narrow tables can still be parsed structurally.

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