Files
llm/docs/runbooks/1c-operational-coding.md
2026-08-14 09:40:51 +03:00

279 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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, если он устарел.