source-access · diff
git:20260730.517463e to git:20260904.5ed75bb
143 added, 50 removed. Audit A to A.
---
name: source-access
- description: Найти логическую цель 1С, восстановить адрес по пути в исходнике и безопасно исследовать снимок ресурсов через MCP Unica
- argument-hint: <sourceSet> [metadataPath|path] <resolve|inspect|locate>
+ description: Навигация по исходникам 1С логическим адресом — найти цель, прочитать узел, спуститься по ветвям, сравнить два узла. Используй когда нужно понять состав объекта, формы, роли, схемы компоновки или модуля
+ argument-hint: <объект|путь|адрес>
allowed-tools:
- Read
- Glob
---
- # /source-access — логическая навигация и чтение исходников
+ # /source-access — чтение исходников логическим адресом
## MCP routing
- - Preferred path: сначала выбери предметный writer MCP `unica`. Для точечной
- вставки BSL используй `unica.code.patch`; для формы, DCS, MXL, роли,
- подсистемы или метаданных — соответствующий `unica.*.edit` либо
- `unica.*.compile`.
- - Для поиска цели используй `unica.source.resolve` или
- `unica.source.children`. Для исследования уже выбранной цели используй
- `unica.source.resources`, затем `unica.source.read`.
- - Когда на руках физический путь — из `unica.code.search`, из диффа, из лога
- сборки — переведи его в логический адрес через `unica.source.locate`, а не
- выводи адрес из раскладки каталогов вручную. `locate` отвечает и владельцем
- файла: для модуля это его объект метаданных, для содержимого формы — сама
- форма. Отказ типизирован: `outsideSourceSet`, `notAddressable` или
- `ownerUnproven`.
- - Ресурсная группа доступна только на чтение. Изменение BSL выполняет
- `unica.code.patch`: `operation: "insert"` добавляет текст у селектора,
- `operation: "replace"` переписывает выбранный метод либо вхождение якоря.
- Он правит выбранный участок, а не переписывает модуль целиком, поэтому
- подходит и для модулей, которые не поместились бы в один запрос.
+ - Всё чтение исходников идёт одним MCP `unica`: `unica.find` ищет цель,
+ `unica.view` читает узел по адресу, `unica.search` ищет литерал в тексте BSL,
+ `unica.diff` сравнивает два узла, `unica.check` отвечает о готовности набора.
- Не вызывай внутренние MCP/CLI-адаптеры и не подменяй логическую цель
- физическим путём. Все операции идут через один MCP `unica`.
+ физическим путём.
+ - Чтение не меняет исходники. Правка BSL — `unica.code.patch`, правка
+ предметных описаний — соответствующий `unica.*.edit` либо `unica.*.compile`,
+ оба сначала с `dryRun: true`.
+ ## Адрес
+
+ ```
+ <набор исходников>:<Вид>[.<Имя>[.<Ветвь>[.<Имя>...]]]
+ ```
+
+ `main:Catalog.Валюты` — объект, `main:Catalog.Валюты.Form.ФормаЭлемента` — его
+ форма, `main:Catalog.Валюты.Module.Object.Method.ПередЗаписью` — метод модуля
+ объекта. Вид цели задаёт число сегментов: прикладное имя, совпадающее с
+ названием вида, объект в ветвь не превращает.
+
+ Префикс набора обязателен. Адрес без него отклоняется кодом `bad_value` с
+ подсказкой вызвать `unica.view {}`.
+
## Порядок работы
- 1. Выбери точный `sourceSet`. Разреши английский или русский запрос через
- `unica.source.resolve`; при исследовании дерева обойди один уровень через
- `unica.source.children`.
- - Вид цели задаёт число сегментов адреса: `Document.ЗаказКлиента` — объект,
- `Document.ЗаказКлиента.ObjectModule` — модуль. Прикладное имя, совпадающее
- с названием роли, объект в модуль не превращает.
- - Корень набора исходников адресуется отсутствием `metadataPath`, а корневые
- модули приложения — голым терминалом, например `ManagedApplicationModule`.
- - В `mode: "prefix"` неполным может быть только канонический английский
- токен: `Doc`, `Su` и `Man` работают, `Документ` работает целиком, а
- неполный псевдоним вроде `Док` отклоняется — у него нет единственной
- канонической формы.
- 2. Открой `unica.source.resources` с точным `sourceSet` и `metadataPath`, когда
- выбранная цель находится ниже корня набора исходников. Манифест сообщает
- роль, размер, хеш и профиль текста; `access` всегда содержит только `read`.
- 3. Читай ресурс через `unica.source.read` фрагментами до объявленного
- `limits.maxReadBytes`. Сохрани `snapshotId`, `resourceId`, полный `hash`,
- `bomPrefixBytes` и профиль EOL. Продвигайся на возвращённый `length`, а не
- на запрошенный `limit`: фрагмент текстового ресурса усекается до ближайшей
- границы UTF-8, поэтому он бывает короче лимита. `contentEncoding: "base64"`
- означает точные байты, а не текст, который можно молча перекодировать. У
- текстового ресурса он остаётся как минимум там, где лимит уже одного символа
- и где `offset` задан внутри многобайтового символа: `offset` адресует байты,
- а не символы. Всегда смотри на возвращённый `contentEncoding`, а не
- предполагай его.
- 4. Изменение вноси через `unica.code.patch` с `dryRun: true`, проверь diff,
- диапазоны и BSL-валидацию, и только затем повтори с `dryRun: false`.
+ 1. `unica.view {}` без аргументов — корень: наборы исходников, их формат,
+ готовность и незакрытые проверки. Отсюда берётся имя набора для префикса.
+ 2. `unica.find` переводит в адрес имя, синоним или путь к файлу исходника.
+ `kind` сужает вид, `limit` ограничивает страницу.
+ 3. `unica.view {at}` читает узел. Ответ бывает двух форм, и различать их надо
+ до чтения полей:
+ - **узел** — `props` с фактами самого узла и `branches` со счётчиками
+ дочерних коллекций;
+ - **страница коллекции** — `items`, каждый со своим `at`.
+ 4. Спускайся по адресу из `branches`, пока не дойдёшь до нужного факта.
+ Содержимое лежит в листьях: текст запроса — в `...DataSet.<Набор>.Query`,
+ текст метода — в `...Method.<Имя>.Body`, оба построчно с `line` и `text`.
- ## Предпросмотр правки
+ ### Корень
+
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": { "name": "unica.view", "arguments": { "cwd": "<workspace>" } }
+ }
+ ```
+
+ ### Поиск цели
+
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "unica.find",
+ "arguments": { "cwd": "<workspace>", "query": "Валюты", "kind": "Form" }
+ }
+ }
+ ```
+
+ Кандидат несёт `at`, `kind`, `title`, `path` и `reason` — по какому признаку он
+ найден. Пустой список с `nearest: true` означает «ближе ничего нет», а не отказ.
+
+ ### Чтение узла
+
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "unica.view",
+ "arguments": {
+ "cwd": "<workspace>",
+ "at": "main:Catalog.Валюты.Form.ФормаЭлемента"
+ }
+ }
+ }
+ ```
+
+ ### Спуск по ветви
+
+ ```json
+ {
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "unica.view",
+ "arguments": {
+ "cwd": "<workspace>",
+ "at": "main:Catalog.Валюты.Form.ФормаЭлемента.Item"
+ }
+ }
+ }
+ ```
+
+ ## Что где лежит
+
+ | Вопрос | Адрес |
+ |--------|-------|
+ | Состав формы | `<объект>.Form.<Форма>` → ветви `Item`, `Attribute`, `Event`, `Module` |
+ | Права роли | `Role.<Роль>` → ветвь `Right`, объект права в `props` со счётчиками |
+ | Схема компоновки | `<объект>.Template.<Макет>` → `DataSet` → набор → `Field`, `Query`; варианты настроек — `Setting` |
+ | Пакет XDTO | `XDTOPackage.<Пакет>` → `Namespace`, `Type`, `Property` |
+ | Подсистема | `Subsystem.<Имя>` → `Interface` → `Command` |
+ | Методы модуля | `<объект>.Module.<Роль>` → `Method`, `Region`, `Event`, `Body` |
+
+ Поддержка поставщика приходит в `props.support` объекта — читай её перед любой
+ правкой объекта на замке и решай через release-support, а не правкой напрямую.
+
+ ## Страницы
+
+ `limit` ограничивает страницу коллекции, ответ возвращает `cursor`. Курсор
+ непрозрачен и привязан к тому же вопросу: тот же адрес, тот же `limit`, та же
+ ревизия. Чужой или устаревший курсор отклоняется кодом `invalid_cursor` —
+ начинай обход заново, а не подставляй курсор от другого вызова.
+
+ ## Проекция модуля
+
+ `filter` осмыслен только для проекций модуля и только там, где он объявлен:
+
+ | Ключ | Где применим | Что делает |
+ |------|--------------|------------|
+ | `context` | `Body`, `Method` | оставляет ветку условной компиляции одного контекста: `client`, `server`, `externalConnection`, `thinClient`, `webClient` и прочие имена профиля |
+ | `public` | `Method` | оставляет только экспортные методы |
+
+ На любой другой проекции фильтр отклоняется кодом `bad_value` с названием
+ причины — это не молчаливое игнорирование.
+
+ ## Отказы
+
+ | Код | Что случилось |
+ |-----|---------------|
+ | `bad_value` | адрес без префикса набора, либо фильтр не той формы или не на той проекции |
+ | `provider_unavailable` | набор исходников не допущен рабочим пространством |
+ | `not_found` | объект не зарегистрирован в конфигурации, либо адрес не существует в профиле платформы |
+ | `invalid_cursor` | курсор чужой, просроченный или от другого вопроса |
+
+ ## Правка
+
+ Чтение и правка разделены. Изменение BSL вносит `unica.code.patch`:
+ `operation: "insert"` добавляет текст у селектора, `operation: "replace"`
+ переписывает выбранный метод либо вхождение якоря. Он правит выбранный участок,
+ а не переписывает модуль целиком, поэтому годится и для модулей, которые не
+ поместились бы в один запрос.
```json
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "unica.code.patch",
"arguments": {
"cwd": "<workspace>",
"sourceSet": "main",
"metadataPath": "CommonModule.SourceAccessExample.Module",
"operation": "replace",
"selector": { "method": "BeforeReplacement" },
"content": "Procedure BeforeReplacement()\n\t// новое тело\nEndProcedure",
"dryRun": true
}
}
}
```
После подтверждения повтори те же аргументы с `dryRun: false`; изменение
селектора или содержимого требует нового предпросмотра.