meta-edit · diff
git:20260901.7502a05 to git:20260910.a91d896
178 added, 228 removed. Audit A to A.
---
name: meta-edit
- description: Типизированное атомарное редактирование существующего объекта метаданных 1С по логическому адресу.
- argument-hint: <sourceSet> <metadataPath> <operations>
+ description: Типизированно изменить существующий объект метаданных 1С по логическому адресу одной транзакцией.
+ argument-hint: <at> <operations>
allowed-tools:
- Read
- Glob
---
# /unica:meta-edit — структурное редактирование метаданных
## MCP routing
- - Preferred path: use MCP `unica` tool `unica.meta.edit`.
- - Выбирайте объект только через `sourceSet + metadataPath`.
- - Передавайте непустой упорядоченный массив `operations`; все элементы одного
- вызова видят результат предыдущих и публикуются одной транзакцией.
- - Вызов по умолчанию строит preview. Передавайте `dryRun: false` только когда
- пользователь явно попросил применить изменение.
- - Успешный и предметно неуспешный `tools/call` возвращает `structuredContent`;
- `isError == !structuredContent.ok`. Проверяйте
- `structuredContent.data.validation` и вложенные диагностики;
- `content[0].text` не является вторым контрактом результата.
- - Preview возвращает нормализованные семантические
- `structuredContent.data.effects` по `operationIndex`, а не полный XML.
- - Vendor support guard выполняется внутри `unica`. Для закрытого объекта
- используйте CFE/release-support flow, а не прямую правку служебных файлов.
- - `sourceSet` — это имя набора исходников из `v8project.yaml`, а не
- константа. Получите его через `unica.view {}`; `"main"` в примерах
- ниже — иллюстрация, а не значение по умолчанию.
+ - Preferred path: use MCP `unica` tool `unica.apply` с операциями изменения
+ объекта метаданных.
+ - Объект и его коллекции называет адрес: `main:Catalog.Валюты` — сам объект,
+ `main:Catalog.Валюты.Attribute` — его реквизиты. Физический путь остаётся
+ внутренней деталью; наружу его отдаёт только аварийный `unica.resolve`.
+ - Имя набора даёт `unica.view {}`, адрес по имени — `unica.search {corpus:
+ "names"}`. `"main"` ниже только пример.
+ - Всегда сначала `dryRun: true`. Применяй `dryRun: false` только когда
+ пользователь явно попросил внести именно эту правку, и только с `ifRev` из
+ предпросмотра.
+ - Операции одного вызова упорядочены: каждая видит результат предыдущих, и
+ публикуются они одной транзакцией — либо все, либо ни одной.
+ - Читай из ответа `changed`, `effects` по порядку операций и диагностики.
+ Ответ описывает правку семантическими `effects`, а не возвращает
+ полный XML объекта.
+ - Проверка поддержки поставщика выполняется внутри `unica`. Для закрытого
+ объекта используй путь расширения, а не прямую правку служебных файлов.
+ - Что операция допустима на этом узле, объявляет сам узел: `can` в ответе
+ `unica.view {at}`.
- Поддерживаются шесть значений `op`: `setProperties`, `add`, `update`, `remove`,
- `editRelations` и `addHelp`. Для коллекционных операций задаются `collection` и
- структурные `elements` либо `names`; связи задаются через `relation`, `mode` и
- `targets`. Допустимые свойства, коллекции, виды типов и связей берите из
- опубликованной схемы операции. Общие прикладные правила находятся в
+ ## Операции
+
+ | Предмет | Операции |
+ |---|---|
+ | Свойства объекта | `props.set` |
+ | Реквизиты | `attribute.add`, `attribute.set`, `attribute.remove` |
+ | Табличные части | `tabularSection.add`, `tabularSection.set`, `tabularSection.remove` |
+ | Измерения и ресурсы | `dimension.*`, `resource.*` |
+ | Значения перечисления | `enumValue.add`, `enumValue.set`, `enumValue.remove` |
+ | Графы журнала | `column.add`, `column.set`, `column.remove` |
+ | Макеты и команды | `template.*`, `command.*` |
+ | Предопределённые элементы | `predefinedItem.add`, `predefinedItem.set`, `predefinedItem.remove` |
+ | Ссылки наружу | `relation.add`, `relation.replace`, `relation.remove` |
+ | Встроенная справка | `help.create` |
+ | Объект целиком | `object.remove` |
+
+ Допустимые свойства, коллекции, виды типов и связей берутся из опубликованной
+ схемы операции. Общие прикладные правила — в
[соглашениях по метаданным](../../references/platform/metadata-conventions.md).
- Регистрация макета — операция `add` по коллекции `templates`: элемент несёт
- `name` и необязательный `templateType` из закрытого набора `HTMLDocument`,
- `TextDocument`, `SpreadsheetDocument` (по умолчанию), `BinaryData`,
- `DataCompositionSchema`; снятие регистрации — `remove` по той же коллекции.
- Наполнение содержимого остаётся у предметных инструментов своего вида.
- Встроенная справка — операция `{"op": "addHelp", "lang"?}` (ADR-0072):
- create-only создаёт `Ext/Help.xml` и `Ext/Help/<lang>.html` владельца и
- включает `IncludeHelpInContents` его формам; повтор — отказ. Прежние
- `unica.template.add`, `unica.template.remove` и `unica.help.add` сняты и
- отвечают `unknown unica tool`.
+ **Адрес операции — сам объект**, а элемент называют `items` или `values`:
+ `attribute.add` с `at: "main:Catalog.Валюты"` и `items`, `tabularSection.set`
+ с `values`, несущим `name`. Исключение одно и оно полезное: `attribute.set` и
+ `attribute.remove` адресуют реквизит листом —
+ `main:Catalog.Валюты.Attribute.Код` — и через табличную часть:
+ `main:Catalog.Валюты.TabularSection.Курсы.Attribute.Курс`. Отдельного поля
+ области видимости при этом не нужно: область называет адрес.
- Коллекция `predefinedItems` доступна только для `Catalog`,
- `ChartOfAccounts`, `ChartOfCharacteristicTypes` и
- `ChartOfCalculationTypes`. Для неё `add` и `update` принимают typed
- `elements`, а `remove` — массив `ids`; отдельная операция не нужна.
- Общие поля элемента: `id`, `name`, `code`, `description`. Дополнительные поля
- закрыты видом владельца:
+ Регистрация макета — `template.add` с `name` и необязательным `templateType`
+ из закрытого набора `HTMLDocument`, `TextDocument`, `SpreadsheetDocument` (по
+ умолчанию), `BinaryData`, `DataCompositionSchema`; снятие регистрации —
+ `template.remove`. Наполнение содержимого остаётся у предметных инструментов
+ своего вида.
+ `help.create` создаёт `Ext/Help.xml` и `Ext/Help/<lang>.html` владельца и
+ включает `IncludeHelpInContents` его формам; повтор — отказ, операция
+ создаёт только раз.
+
+ ### Предопределённые элементы
+
+ Коллекция доступна только для `Catalog`, `ChartOfAccounts`,
+ `ChartOfCharacteristicTypes` и `ChartOfCalculationTypes`. Общие поля элемента:
+ `id`, `name`, `code`, `description`. Дополнительные поля закрыты видом
+ владельца:
+
- `Catalog`: `isFolder`;
- `ChartOfCharacteristicTypes`: `isFolder` и структурный `type` из
опубликованной схемы, не строка и не QName;
- - `ChartOfAccounts`: `accountType`, `offBalance`, `order`,
- `accountingFlags`, `extDimensionTypes`;
+ - `ChartOfAccounts`: `accountType`, `offBalance`, `order`, `accountingFlags`,
+ `extDimensionTypes`;
- `ChartOfCalculationTypes`: `actionPeriodIsBase`.
- `type` использует общий структурный `metadataType`. Для плана счетов
- `accountType` допускает `Active`, `Passive`, `ActivePassive`;
- `accountingFlags` — закрытый объект `имя: boolean`; `extDimensionTypes` —
- массив объектов с `name` и необязательными `turnover`, `accountingFlags`.
- Явно переданные пустые `{}` и `[]` очищают соответственно поддержанные
- `Flag` и `ExtDimensionType`; отсутствие поля сохраняет прежнее значение.
+ Для плана счетов `accountType` допускает `Active`, `Passive`,
+ `ActivePassive`; `accountingFlags` — закрытый объект `имя: boolean`;
+ `extDimensionTypes` — массив объектов с `name` и необязательными `turnover`,
+ `accountingFlags`. Явно переданные пустые `{}` и `[]` очищают соответственно
+ поддержанные `Flag` и `ExtDimensionType`; отсутствие поля сохраняет прежнее
+ значение.
- `add` создаёт только корневой элемент. Совпадающий UUID даёт no-op только при
- эквивалентном образе, иначе `already_exists`. `update` и `remove` находят UUID
- на любой глубине; удаление родителя удаляет всё его поддерево. Неуказанные поля
- и неизвестные XML-узлы сохраняются.
+ `predefinedItem.add` создаёт только корневой элемент. Совпадающий UUID даёт
+ no-op только при эквивалентном образе, иначе `already_exists`.
+ `predefinedItem.set` принимает `values` с изменяемыми полями,
+ `predefinedItem.remove` — `values` с одним `id`. Обе находят UUID на любой
+ глубине; удаление родителя удаляет всё его поддерево. Неуказанные поля и неизвестные
+ XML-узлы сохраняются.
- Не переносите поля снятого Meta JSON DSL по сходству имён. В частности:
+ **Читателя у предопределённых элементов на канонической поверхности пока
+ нет.** Писать их можно, а прочитать обратно этим же путём — нет; не выдавай за
+ них соседний факт.
- - один вызов изменяет один объект; batch нескольких объектов разбивается на
- отдельные `unica.meta.add`, а `meta.add.operations` атомарен только вместе с
- создаваемым объектом;
- - вложенные URL-шаблоны и методы HTTP-сервиса, операции и параметры
- Web-сервиса, расписания, реквизиты адресации, учётные признаки и ссылки без
- опубликованного relation/property-варианта не имеют типизированного writer;
- - shorthand-флаги `index`, `indexAdditional`, `nonneg`, `master`,
- `mainFilter`, `denyIncomplete`, `useInTotals` нельзя упаковывать в строку;
- - не подставляйте compound-значение в `setProperties` как строку и не создавайте
- временный `DefinitionFile`. Если схема не представляет сценарий, остановитесь
- и явно сообщите, что оставшийся шаг выполняется в Designer.
+ ### Ссылки наружу
- Тип уникального идентификатора задаётся закрытым вариантом
- `{"kind": "uuid"}`. Поле `mutationCapability: "readOnly"` из результата
- `unica.meta.info` является свойством наблюдения и никогда не передаётся во вход
- writer; неизвестный QName также нельзя копировать из XML в аргументы.
+ Владельцы справочника и движения документа меняются через `relation.replace`
+ со связью `owners` или `registerRecords`. Источник подписки заменяется той же
+ операцией со связью `source`; `targets: []` очищает список, но пустой
+ итоговый `Source` не является допустимым состоянием подписки, поэтому такой
+ запрос годится только как часть изменения, чей итог снова непуст.
- Доказанные переходы для прежних коллекций: значения перечисления добавляются
- как `collection: "enumValues"`, владельцы справочника и движения документа
- меняются через `editRelations` с `relation: "owners"` или
- `relation: "registerRecords"`. Источник подписки заменяется той же операцией с
- `relation: "source"` и только `mode: "replace"`; `targets: []` очищает список.
- Но пустой `Source` не является допустимым итоговым состоянием подписки, поэтому
- такой запрос можно использовать только как часть изменения, чей итог снова
- непуст; обычная мутация с `targets: []` отклоняется. Цели — закрытое логическое
- объединение `object`, `manager`, `recordSet`, `definedType` и `family`.
- `targets` — wire-массив набора: порядок его членов семантически незначим, и
- перестановка тех же целей является exact-byte no-op. При изменении Unica
- выпускает цели в детерминированном порядке.
+ Цели — закрытое логическое объединение `object`, `manager`, `recordSet`,
+ `definedType` и `family`. `targets` — wire-массив набора:
+ порядок его членов семантически незначим, и перестановка тех же целей
+ является exact-byte no-op. При изменении Unica выпускает цели в
+ детерминированном порядке.
+
Конфигурационные варианты передают логический `metadataPath`; Unica проверяет
регистрацию, дескриптор и совпадающий `GeneratedType` под тем же владельцем,
- что и подписка. `DefinedType` разворачивается рекурсивно, а примитивы, ссылки и
- `valueStorage` не являются логическими источниками событий.
- Скалярные свойства используйте только под PascalCase-именем и с enum-значением,
- опубликованным текущей схемой.
+ что и подписка. `DefinedType` разворачивается рекурсивно, а примитивы, ссылки
+ и `valueStorage` логическими источниками событий не являются.
- ### Изменить свойства
+ ## Границы
- ```json
- {
- "jsonrpc": "2.0",
- "method": "tools/call",
- "params": {
- "name": "unica.meta.edit",
- "arguments": {
- "cwd": "<workspace>",
- "sourceSet": "main",
- "metadataPath": "Catalog.Контрагенты",
- "operations": [
- {"op": "setProperties", "values": {"Comment": "Проверено"}}
- ],
- "dryRun": true
- }
- }
- }
- ```
+ Не переноси поля снятого Meta JSON DSL по сходству имён:
- ### Добавить типизированный реквизит
+ - один вызов изменяет один объект; несколько объектов — несколько вызовов;
+ - вложенные шаблоны URL и методы HTTP-сервиса, операции и параметры
+ веб-сервиса, расписания, реквизиты адресации и учётные признаки читаются, но
+ типизированного писателя не имеют;
+ - shorthand-флаги `index`, `indexAdditional`, `nonneg`, `master`,
+ `mainFilter`, `denyIncomplete`, `useInTotals` нельзя упаковывать в строку;
+ - не подставляй составное значение в `props.set` строкой и не заводи временный
+ файл определения.
- ```json
- {
- "jsonrpc": "2.0",
- "method": "tools/call",
- "params": {
- "name": "unica.meta.edit",
- "arguments": {
- "cwd": "<workspace>",
- "sourceSet": "main",
- "metadataPath": "Catalog.Контрагенты",
- "operations": [
- {
- "op": "add",
- "collection": "attributes",
- "elements": [
- {
- "name": "Комментарий",
- "type": {
- "variants": [
- {"kind": "string", "length": 200, "allowedLength": "variable"}
- ]
- }
- }
- ]
- }
- ],
- "dryRun": true
- }
- }
- }
- ```
+ Если схема не представляет сценарий, остановись и скажи прямо, что оставшийся
+ шаг выполняется в Конфигураторе.
- ### Изменить и удалить реквизиты табличной части
+ Скалярные свойства используй только под именем платформы в PascalCase и со
+ значением, опубликованным текущей схемой. Свойство наблюдения
+ `mutationCapability` во вход писателя не передаётся, и неизвестный QName
+ нельзя копировать из XML в аргументы.
- `scope.tabularSection` ограничивает обе операции реквизитами существующей
- табличной части, а не корневыми реквизитами документа.
+ ## MCP examples
+ ### Изменить свойства и реквизит
+
```json
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
- "name": "unica.meta.edit",
+ "name": "unica.apply",
"arguments": {
- "cwd": "<workspace>",
- "sourceSet": "main",
- "metadataPath": "Document.ЗаказПокупателя",
- "operations": [
+ "at": "main:Catalog.Валюты",
+ "ops": [
{
- "op": "update",
- "collection": "attributes",
- "scope": {"tabularSection": "Товары"},
- "elements": [
- {
- "name": "Количество",
- "synonym": "Количество товара",
- "required": true
- }
- ]
+ "op": "props.set",
+ "args": {
+ "at": "main:Catalog.Валюты",
+ "values": {"Comment": "Справочник валют"}
+ }
},
{
- "op": "remove",
- "collection": "attributes",
- "scope": {"tabularSection": "Товары"},
- "names": ["УстаревшийРеквизит"]
+ "op": "attribute.set",
+ "args": {
+ "at": "main:Catalog.Валюты.Attribute.Код",
+ "values": {"required": true}
+ }
}
],
"dryRun": true
}
}
}
```
- ### Изменить типизированную связь
+ ### Правка реквизита табличной части и удаление
```json
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
- "name": "unica.meta.edit",
+ "name": "unica.apply",
"arguments": {
- "cwd": "<workspace>",
- "sourceSet": "main",
- "metadataPath": "Document.ЗаказПокупателя",
- "operations": [
+ "at": "main:Catalog.Валюты",
+ "ops": [
{
- "op": "editRelations",
- "relation": "basedOn",
- "mode": "replace",
- "targets": [
- {"metadataPath": "Document.СчетПокупателю"}
- ]
+ "op": "attribute.set",
+ "args": {
+ "at": "main:Catalog.Валюты.TabularSection.Курсы.Attribute.Курс",
+ "values": {"required": true}
+ }
+ },
+ {
+ "op": "attribute.remove",
+ "args": {
+ "at": "main:Catalog.Валюты.TabularSection.Курсы.Attribute.Устарело"
+ }
}
],
"dryRun": true
}
}
}
```
- ### Атомарно заменить источник, событие и обработчик подписки
+ ### Предопределённые элементы
```json
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
- "name": "unica.meta.edit",
+ "name": "unica.apply",
"arguments": {
- "cwd": "<workspace>",
- "sourceSet": "main",
- "metadataPath": "EventSubscription.ОбработкаИзменений",
- "operations": [
+ "at": "main:Catalog.Валюты",
+ "ops": [
{
- "op": "setProperties",
- "values": {
- "Event": "BeforeWrite",
- "Handler": "CommonModule.ОбработчикиПодписок.ПередЗаписьюИстории"
+ "op": "predefinedItem.add",
+ "args": {
+ "at": "main:Catalog.Валюты",
+ "items": [
+ {
+ "id": "0f5f4f2a-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
+ "name": "Рубль",
+ "code": "643",
+ "description": "Российский рубль"
+ }
+ ]
}
},
{
- "op": "editRelations",
- "relation": "source",
- "mode": "replace",
- "targets": [
- {
- "kind": "recordSet",
- "metadataPath": "InformationRegister.ИсторияИзменений"
- }
- ]
+ "op": "predefinedItem.remove",
+ "args": {
+ "at": "main:Catalog.Валюты",
+ "values": {"id": "1a2b3c4d-5e6f-4708-8910-1112131415ff"}
+ }
}
],
"dryRun": true
}
}
}
```
- Для набора записей событие `BeforeWrite` передаёт `Cancel` и `Replacing`, поэтому
- обработчик выше должен быть экспортной процедурой с тремя параметрами
- `(Source, Cancel, Replacing)` в общем модуле с `Global=false`, `Server=true`.
- Unica проверяет итоговый post-image, поэтому порядок этих двух операций не
- меняет результат. Конкретный менеджер константы требует дополнительный
- `"sourceClass": "constantManager"` либо `"constantValueManager"`; у остальных
- `manager` это поле запрещено.
-
- ### Добавить, изменить и удалить предопределённые элементы
+ ### Заменить источник подписки
```json
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
- "name": "unica.meta.edit",
+ "name": "unica.apply",
"arguments": {
- "cwd": "<workspace>",
- "sourceSet": "main",
- "metadataPath": "Catalog.Валюты",
- "operations": [
- {
- "op": "add",
- "collection": "predefinedItems",
- "elements": [
- {
- "id": "c7d2e6fc-3824-4b56-b4be-ae6be4944c0e",
- "name": "ОсновнаяВалюта",
- "code": "643",
- "description": "Рубль",
- "isFolder": false
- }
- ]
- },
+ "at": "main:EventSubscription.ПриЗаписи",
+ "ops": [
{
- "op": "update",
- "collection": "predefinedItems",
- "elements": [
- {
- "id": "c7d2e6fc-3824-4b56-b4be-ae6be4944c0e",
- "description": "Российский рубль"
+ "op": "relation.replace",
+ "args": {
+ "at": "main:EventSubscription.ПриЗаписи",
+ "values": {
+ "relation": "source",
+ "targets": [
+ {
+ "kind": "recordSet",
+ "metadataPath": "InformationRegister.ИсторияИзменений"
+ }
+ ]
}
- ]
- },
- {
- "op": "remove",
- "collection": "predefinedItems",
- "ids": ["8ed9f480-f17d-4dc8-95c4-b7887e2f918a"]
+ }
}
],
- "dryRun": true
+ "dryRun": false,
+ "ifRev": "<rev из предпросмотра>"
}
}
}
```