279 lines
17 KiB
Markdown
279 lines
17 KiB
Markdown
# 1C Operational Coding Loop
|
||
|
||
Цель: сделать помощника по 1С, который работает в темпе реальной разработки, без постоянной полной выгрузки конфигурации в XML и без обязательного 1C:EDT на первом этапе.
|
||
|
||
## Problem
|
||
|
||
Полная выгрузка конфигурации в XML медленная. 1C:EDT требует отдельной установки, настройки проекта и дисциплины синхронизации. Для оперативной разработки помощнику нужны текущие данные почти сразу:
|
||
|
||
- структура базы и конфигурации;
|
||
- доступные объекты, реквизиты, табличные части, формы и команды;
|
||
- актуальные модули BSL;
|
||
- примеры реальных данных для read-only анализа;
|
||
- постановки задач из текста, Excel-файлов и скриншотов интерфейса.
|
||
|
||
## Decision
|
||
|
||
Используем двухконтурную схему.
|
||
|
||
Быстрый контур:
|
||
|
||
- read-only SQL для диагностики, выборок и проверки данных;
|
||
- легкий 1C agent внутри базы или рядом с ней для метаданных, модулей и управляемых операций;
|
||
- локальный кеш/snapshot с коротким TTL;
|
||
- RAG поверх актуального кеша;
|
||
- генерация патчей, внешних отчетов, обработок и расширений как артефактов.
|
||
|
||
Тяжелый контур:
|
||
|
||
- XML/EDT/хранилище конфигурации для периодической полной синхронизации;
|
||
- сборка, ревью, массовый рефакторинг и долгоживущие изменения;
|
||
- финальная проверка перед переносом в production.
|
||
|
||
## Live Sources
|
||
|
||
### SQL Read-Only
|
||
|
||
SQL удобен как быстрый источник данных, но не является главным источником метаданных 1С.
|
||
|
||
Разрешено:
|
||
|
||
- read-only запросы;
|
||
- выборки для отчетов и сверок;
|
||
- оценка объемов данных;
|
||
- поиск аномалий;
|
||
- проверка результата после изменения в тестовой базе.
|
||
|
||
Запрещено:
|
||
|
||
- DML/DDL;
|
||
- изменение таблиц платформы напрямую;
|
||
- запись в production;
|
||
- хранение строк подключения и паролей в репозитории.
|
||
|
||
## 1C Storage Layers (write/read boundary)
|
||
|
||
Принцип работы со слоями конфигурации:
|
||
|
||
- `Config` и `ConfigCAS` — **active** (уже применённое в системе состояние). Для них разрешены только read-операции.
|
||
- `ConfigSave` и `ConfigCASSave` — **saved, not yet applied** (сохранённое в конфигураторе состояние). Это целевые слои для формирования изменений через адаптер.
|
||
- Base-изменения пишутся в `ConfigSave`.
|
||
- Extension-изменения пишутся в `ConfigCASSave`.
|
||
|
||
Жёсткое правило:
|
||
|
||
- Коннектор/агент не пишет в `Config`/`ConfigCAS`.
|
||
- Изменения должны идти через saved-слои и проходить сравнение `ConfigSave↔Config`, `ConfigCASSave↔ConfigCAS` до ручного/внешнего apply в production.
|
||
- Если требуется production apply, это отдельный человеческий процесс контроля и проверки.
|
||
|
||
Мини-чеклист перед передачей на manual-apply:
|
||
|
||
1. Есть актуальный compare saved-vs-active.
|
||
2. Есть report с изменениями по объектам.
|
||
3. Есть отметка «не применено» в `ConfigSave`/`ConfigCASSave`.
|
||
4. Есть rollback-план и явное human approval.
|
||
|
||
### Working-State Read Policy
|
||
|
||
Для программирования и оперативного анализа помощник должен читать последнее
|
||
сохранённое состояние конфигуратора, а не только применённую конфигурацию.
|
||
|
||
По умолчанию:
|
||
|
||
- MCP-запросы к `extension.objects.find`, `modules.search`, `code.search` и
|
||
`metadata.resolve_overrides` используют `source_state=working`;
|
||
- REST-запросы к тем же методам используют `state=working`;
|
||
- `working` означает: сначала `ConfigSave`/`ConfigCASSave`, затем active-слой
|
||
как fallback;
|
||
- результаты помечаются `activation_state`: `saved_only`, `saved_override` или
|
||
`active`.
|
||
|
||
Когда нужно сравнение:
|
||
|
||
- `source_state=applied` / `state=active` — показать только применённое;
|
||
- `source_state=all` / `state=both` — показать оба слоя и различия;
|
||
- `full_scan=true` включается только осознанно для глубокого поиска по active
|
||
`ConfigCAS`, потому что такой поиск медленнее.
|
||
|
||
Если пользователь спрашивает естественным языком вроде «выдай список всех форм
|
||
в save только имена», агент должен трактовать это как working/save-first
|
||
срез, вернуть имена saved-форм и не отбрасывать объекты `saved_only`: они могут
|
||
быть ещё не активированы и всё равно являются текущим состоянием разработки.
|
||
|
||
### Code Write Policy
|
||
|
||
Для оперативного программирования агент не должен знать SQL-нюансы: таблицы,
|
||
имена файлов, stream indexes и brace paths являются внутренней реализацией
|
||
адаптера.
|
||
|
||
Стандартный write API для агента:
|
||
|
||
- `code.write` с `module_text`/`full_text`/`code` заменяет весь модуль;
|
||
- `code.write` с `routine_name` и `routine_text` заменяет только указанную
|
||
процедуру или функцию;
|
||
- `code.write` с `old` и `new` заменяет фрагмент только если `old` найден
|
||
ровно один раз в выбранной области. Если передан `routine_name` или
|
||
canonical path до процедуры, областью является эта процедура/функция; иначе
|
||
весь текущий saved-модуль.
|
||
|
||
По умолчанию `code.write` делает безопасный `mode=plan` и не пишет в SQL.
|
||
Только явно переданный `mode=apply`, `apply_and_verify` или
|
||
`apply_and_rollback` может записать saved-state слой
|
||
(`ConfigSave`/`ConfigCASSave`); это всё равно не применение конфигурации в
|
||
runtime.
|
||
Адаптер сам выставляет save-first gates и сам выбирает физический маршрут.
|
||
Физические детали возвращаются только при `include_storage=true` для
|
||
диагностики. Ответ `code.write` всегда содержит `write_mode`: target
|
||
`saved_state`, activation_state `not_activated`, production_apply `false`.
|
||
Ответы `code.read` и `code.search` для saved-кода содержат `current_state`:
|
||
source `saved_state`, activation_state `not_activated`.
|
||
Для `code.read`: `state=working` означает save-first с fallback в active,
|
||
`state=save` читает только saved layer, `state=active` пропускает saved layer.
|
||
`state=both` читает saved и active отдельно, возвращает `layers` для обоих
|
||
слоев и `comparison.both_present` / `comparison.differs`. При `include_text=true`
|
||
верхнеуровневый `text` берется из saved-state, если он есть, иначе из active;
|
||
`text_source` показывает выбранный слой.
|
||
Для `code.search state=both` saved-совпадения идут первыми, active-слой
|
||
добирается отдельным проходом, а `counts.saved_matches` и
|
||
`counts.active_matches` показывают покрытие по слоям.
|
||
|
||
### Repository lock and first extension edit
|
||
|
||
Для изменения объекта в расширении, подключенном к хранилищу, агент сначала
|
||
использует только публичные вызовы:
|
||
|
||
```text
|
||
code.search → repository.lock.plan → repository.lock.request
|
||
→ человек захватывает объект в Конфигураторе → repository.lock.confirm
|
||
→ code.write → code.search (readback)
|
||
```
|
||
|
||
Если у extension-модуля ещё нет saved-state строки, `code.write(mode=plan)`
|
||
возвращает `needs_prepare` и
|
||
`diagnostics.next_action=confirm_repository_lock_then_apply`. Это нормальный
|
||
первый-edit маршрут: после подтверждённого lock тот же публичный `code.write`
|
||
в apply-режиме сам подготовит saved-state. Агент не передаёт `module_ref`,
|
||
`stream_index`, таблицу или имя технического файла.
|
||
|
||
Исключение: `extension_saved_state_prepare_protocol_unproven` означает, что
|
||
автоматическая подготовка запрещена. Это не доказательство того, что
|
||
расширение не сохраняли: адаптер ещё не доказал точный prepare-кодек для
|
||
наблюдаемой extension-layout. Агент не создаёт контейнер через SQL и передаёт
|
||
случай разработчикам адаптера без технических координат.
|
||
|
||
Acceptance extension write считается пройденным только при наличии в
|
||
`upo_test` отдельного extension-owned `Report` с object module и успешном
|
||
публичном `code.write(..., apply_and_rollback)` без storage-координат. Успех
|
||
base-модуля в `ConfigSave` не доказывает ветку `ConfigCAS → ConfigCASSave`.
|
||
|
||
`upo` не используется для автоматических проверочных записей. Контролируемые
|
||
`apply_and_rollback` проверки разрешены только в `upo_test`.
|
||
|
||
Для регрессии первого extension-edit используйте публичный smoke (без SQL
|
||
таблиц, key, module_ref или GUID в запросе):
|
||
|
||
```powershell
|
||
python scripts\smoke_1c_extension_saved_state_prepare.py --apply
|
||
```
|
||
|
||
Он проверяет `plan → prepare/readback → rollback → immediate plan` на
|
||
`upo_test / фс_ДоработкиОбщее / Catalog.Номенклатура`. После rollback не
|
||
должно остаться saved-state строк, а повторный план должен быть `plan_ready`.
|
||
|
||
### Safe adapter deployment
|
||
|
||
Перед Docker-обновлением скрипт развёртывания запрашивает `/health` и ждёт
|
||
`runtime.state=ready` и `runtime.active_rpc_count=0`. При остановке REST
|
||
переходит в `draining`; уже начатые запросы продолжают выполняться до пяти
|
||
минут. Не используйте `-SkipDrainCheck`, кроме аварийного случая, когда
|
||
ответственный подтвердил отсутствие активной записи.
|
||
|
||
После обновления проверяются REST `/health?base_id=upo_test` и MCP `/health`.
|
||
JSONL-аудит REST хранится в `/data/adapter-audit.jsonl`, MCP — в
|
||
`/data/mcp-audit.jsonl`; оба периодически сворачиваются в
|
||
`/data/adapter-audit-reports/latest.json` на соответствующем хосте.
|
||
|
||
Если фрагмент повторяется, агент должен передать более узкий контекст
|
||
(`routine_name`) или заменить процедуру целиком. Адаптер в такой ситуации
|
||
возвращает `ambiguous_fragment`, `scope` и `counts.occurrences`, и не
|
||
записывает.
|
||
|
||
### 1C Agent
|
||
|
||
Для актуальной структуры и кода нужен небольшой агент на стороне 1С. Он может быть реализован как внешняя обработка, расширение или опубликованный HTTP-сервис.
|
||
|
||
Минимальные функции:
|
||
|
||
- вернуть список объектов метаданных;
|
||
- вернуть описание объекта: реквизиты, табличные части, формы, команды, модули;
|
||
- искать по BSL-модулям;
|
||
- читать текст выбранного модуля;
|
||
- выполнять read-only запрос языка запросов 1С с лимитами;
|
||
- отдавать версию/дату изменения конфигурации для инвалидации кеша;
|
||
- принимать change proposal, но не применять его автоматически в production.
|
||
|
||
Если публикация HTTP-сервиса невозможна, первым вариантом может быть ручной запуск внешней обработки, которая выгружает JSON snapshot в общую папку.
|
||
|
||
## Freshness Model
|
||
|
||
Модель не должна считать кеш вечным.
|
||
|
||
- SQL read-only данные читаются по запросу.
|
||
- Metadata snapshot имеет TTL и номер версии конфигурации.
|
||
- BSL-модули кешируются с checksum.
|
||
- Перед генерацией кода под конкретный объект помощник проверяет свежесть metadata snapshot.
|
||
- Если snapshot устарел или отсутствует, помощник запрашивает обновление через agent.
|
||
|
||
## Task Intake
|
||
|
||
Задачи приходят разными форматами:
|
||
|
||
- обычный текст;
|
||
- Excel-файл с требованиями, примером отчета или справочником полей;
|
||
- скриншот формы, нарисованный макет интерфейса или ошибка;
|
||
- фрагмент BSL;
|
||
- SQL/запрос 1С;
|
||
- описание бизнес-процесса.
|
||
|
||
Обработка:
|
||
|
||
- текст идет напрямую в модель;
|
||
- Excel парсится структурно: листы, заголовки, таблицы, примечания;
|
||
- скриншоты идут через vision/OCR и превращаются в описание интерфейса, полей, команд и ошибок;
|
||
- все извлеченные требования связываются с metadata snapshot и BSL search.
|
||
|
||
## Coding Outputs
|
||
|
||
Помощник должен уметь выдавать:
|
||
|
||
- BSL-фрагмент;
|
||
- полный модуль формы/объекта/общего модуля;
|
||
- текст запроса 1С;
|
||
- схему внешнего отчета или обработки;
|
||
- proposal для расширения;
|
||
- список изменений по формам и командам;
|
||
- чеклист проверки;
|
||
- тестовые сценарии;
|
||
- rollback plan.
|
||
|
||
Для production изменения не применяются напрямую. Нормальный поток:
|
||
|
||
1. Получить актуальные метаданные и модули.
|
||
2. Сформировать change proposal.
|
||
3. Проверить синтаксис и зависимости в тестовой базе.
|
||
4. Сформировать артефакт: внешняя обработка, отчет, расширение или патч.
|
||
5. Провести ревью.
|
||
6. Перенести через согласованный 1С-процесс.
|
||
|
||
## Practical Priority
|
||
|
||
Первый рабочий MVP:
|
||
|
||
1. SQL read-only connector с валидацией политики.
|
||
2. 1C metadata snapshot через внешнюю обработку в JSON.
|
||
3. BSL module snapshot и поиск по модулям.
|
||
4. Загрузка постановки из Excel.
|
||
5. Загрузка скриншота формы/ошибки в vision-модель.
|
||
6. Генерация внешнего отчета/обработки по актуальному snapshot.
|
||
7. Smoke eval: модель не выдумывает реквизиты и просит обновить snapshot, если он устарел.
|