- subsystem-compile.py: авто-валидация через subprocess к subsystem-validate.py
(вместо powershell.exe + .ps1), без проброса кода возврата — паритет с сиблингами
- resolve_v8path (12 db/epf .py): резолв каталога платформы по ОС (1cv8 без .exe
на *nix), авто-поиск /opt/1cv8/*; ibcmd только явным путём, 1cv8c убран
- сообщения об ошибках платформо-нейтральные (ps1+py), коммент-заглушка PY-only в .ps1
- runner.mjs (v0.5): loadV8Context кросс-платформенный (1cv8/ibcmd без .exe)
- тесты: stdoutContains маркер валидатора (#26), негативный кейс db-update/error-bad-v8dir
- синхронный бамп версий ps1+py всех затронутых навыков
Fixes#26, #27
Co-Authored-By: Korolev Pavel <korolev.vrn@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Приводим авторский контент (.ps1/.psm1/.py/.mjs/.md/.json, пин .bsl)
к единому LF и закрепляем политикой в .gitattributes. Инструмент правки
всегда пишет LF, поэтому единый LF убирает EOL-шум в диффах, ложные
срабатывания blame и налог на ручную синхронизацию CRLF-файлов.
BOM на .ps1 сохранён (git с eol=lf меняет только CR<->LF, BOM не трогает).
Данные 1С (*.xml) и бинарники под нормализацию не берём.
Гейт: PS-порт 459/459, Python-порт 459/459, web-test E2E 22/22 (с пересборкой стенда).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Синхронизация §1B с улучшенным текстом хука (ветка feat/support-guard-hooks):
вместо общего списка всех вариантов — текст под конкретную причину
(capability-off / locked / not-removed) с подставленным реальным путём и
точными командами support-edit. Понятно модели вне контекста.
- Все 16 навыков-мутаторов (оба рантайма): Assert-EditAllowed /
assert_edit_allowed строят сообщение по $code/code причины отказа.
- Терминология «редактирование» (как у платформы 1С).
- Версии заголовков подняты в обоих рантаймах.
- EOL/BOM каждого файла сохранены; deny-тесты 16/16 на PS и PY.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Замыкает петлю issue #23: после отказа support-guard модель может
легитимно включить редактирование. support-edit правит правила поддержки
в Ext/ParentConfigurations.bin выгрузки (только XML; в ИБ — полной загрузкой):
-Path <путь> -Set editable|off-support|locked (пообъектно или корень)
-Path <путь> -Capability on|off (возможность изменения)
Path-based, симметрично гарду — модель берёт путь прямо из отказа.
Реализация: regex-замена in-place по разобранному формату bin (round-trip
байт-в-байт; парсер подтверждён consumed=100% на корпусе acc/erp/K=7).
При выключенной возможности (G=1) пообъектный -Set отказывает с подсказкой
«сначала -Capability on» (явные шаги). Включение возможности ставит всё на
замок (вендорские флаги «не редактировать» в выгрузке недоступны — массовой
разблокировки нет; non-goal). Оба порта дают байт-в-байт идентичный bin.
Диагностика support-guard (32 файла, 16 мутаторов × 2 порта) теперь печатает
готовую команду support-edit под конкретный отказ.
Тесты: фикстуры g0/g1 + кейсы set-editable/off-support/предусловие/capability
со снапшотами bin; зелёные на PowerShell и Python. Все 16 мутаторов +
support-edit зелёные на обоих рантаймах.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Контракт Assert-EditAllowed (дословная копия из meta-edit, оба порта)
добавлен в 13 навыков-мутаторов. Всем единый вызов require=editable —
«кого проверять» решает не навык, а walk-up по файловой системе от пути
цели:
- целевой файл имеет root-uuid → его f1 (правка существующего элемента);
- иначе ближайший вверх <dir>.xml с uuid → f1 владельца (добавление
дочернего: форма/реквизит/макет к объекту);
- иначе корень Configuration.xml → f1 корня (новый объект верхнего уровня).
Это воспроизводит семантику поддержки 1С автоматически, поэтому один и
тот же навык проверяет разное по состоянию дампа: skd-compile/mxl-compile/
form-compile в существующий макет/форму → f1 этого элемента (modify), в
несуществующий → f1 владельца. Проверено обоими сценариями.
Навыки: form-edit, form-add, form-compile, skd-edit, skd-compile, cf-edit,
subsystem-edit, subsystem-compile, interface-edit, template-add, help-add,
mxl-compile, role-compile. Диагностика через [Console]::Error.WriteLine +
exit 1 (как в эталоне). Версии подняты в обоих портах.
Проверено: deny на обоих портах (крафт-фикстуры на копиях, корпус не
тронут); все 16 навыков-мутаторов зелёные на PowerShell и Python
(264 кейса). BOM сохранён везде.
Follow-up (в upload-плане): пред-существующий баг help-add
Detect-FormatVersion (Substring на кириллице, до гарда, не связан);
авторезолв пути в meta-edit; per-skill committed deny-тесты.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace literal `.claude/skills/<owner>/...` paths in SKILL.md with the
`${CLAUDE_SKILL_DIR}` variable that Claude Code substitutes at invocation
time. Same-skill references become `${CLAUDE_SKILL_DIR}/<rest>`,
cross-skill references (erf-* → epf-*) become
`${CLAUDE_SKILL_DIR}/../<other>/<rest>`. All paths now wrapped in double
quotes to handle install locations with spaces.
This unblocks plugin-mode installation: literal `.claude/skills/...`
paths fail when the skill is loaded from `~/.claude/plugins/cache/...`
or from a personal `~/.claude/skills/` install. Drop-in mode continues
to work because Claude Code resolves the variable in all install scopes.
Verified via pilot:
- Project drop-in (cc-1c-skills repo)
- Personal `~/.claude/skills/cf-info/`
- Plugin via `/plugin marketplace add <local-path>`
Scope: 61 SKILL.md, 125 path replacements (8 cross-skill).
Scripts unchanged — they already use \$PSScriptRoot and ../<sibling>
patterns that resolve correctly under the bundled cache layout.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
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>
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>
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>
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>
Script logic fixes (PY mirroring PS1):
- skd-compile: fix (?i) regex flag placement for Python 3.11+
- mxl-compile: handle list-of-lists row format (PS1 silently ignores)
- subsystem-compile: add "objects" → "content" synonym alias
- role-compile: add "rights" → "objects" synonym alias
- meta-compile: sort HTTP/Web service method/operation iteration
- form-edit: insert ChildItems after Events/AutoCommandBar (not at end)
- mxl-compile: sort colWidthMap iteration in both PS1 and PY for
deterministic format indices
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Skill fixes (all ps1+py, version bumped to v1.1):
- role-compile: accept "rights" as synonym for "objects"
- subsystem-compile: accept "objects" as synonym for "content"
- form-add: resolve directory path to .xml (like meta-validate)
- form-info: resolve directory path to Ext/Form.xml (like form-validate)
- mxl-compile: support absolute OutputPath (IsPathRooted check)
- meta-remove: exit 1 when object not found; v1.1
- cfe-patch-method: accept plural type names (Catalogs → Catalog)
Test fixes:
- basic-role.json: use canonical "objects" key
- basic.json (subsystem): use canonical "content" key
- catalog-form.json: fix outdated DSL format
- New synonym test cases for role-compile and subsystem-compile
- error-not-found.json: expect error (exit 1)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Without reconfiguring stderr, Cyrillic error messages appear garbled
on Windows (cp1251 default). Mirrors the existing stdout fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Python on Windows defaults to cp1251 for piped stdout, which cannot
handle Unicode box-drawing characters used in info/analysis output.
Added sys.stdout.reconfigure(encoding="utf-8") to all 59 Python scripts.
Tested on real config data: epf-init, epf-validate, cf-info, cf-validate,
meta-info, form-info, role-info, skd-info, subsystem-info — all passing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add cross-platform Python alternatives alongside existing PowerShell
scripts. PS1 remains the default runtime; Python is opt-in via switch
scripts. All parameters are identical between runtimes.
New files:
- 58 Python scripts in .claude/skills/*/scripts/*.py
- scripts/switch-to-python.py and switch-to-powershell.py
- docs/python-porting-guide.md
- __pycache__/ added to .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bash on Windows strips backslashes in unquoted paths, causing
"file not found" errors. Forward slashes work cross-platform.
Also fix pwsh → powershell.exe in epf-init and epf-add-form.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>