Files
orchestrator/docs/work-items/ORCH-092/06-adr/ADR-001-developer-rebase-and-deployer-language.md

12 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-092 architecture architect accepted 2026-06-09 claude-opus-4-8

ADR-001: Ручной rebase developer и язык промпта deployer

Work Item: ORCH-092 — Промпт-аудит 6 агентов (эпилог эпика ORCH-52) Стадия: architecture Сквозная регистрация: N/A — локальное docs/prompts-only решение. Оба решения уточняют существующий канон промптов (docs/architecture/adr/adr-0021-prompt-canon-anthropic.md, README §«Слой промптов»), но не вводят ни нового QG, ни стадии, ни компонента, ни смены БД → нового global ADR не требуют. Долговечность нормативного эффекта обеспечивается анти-регресс-тестом tests/test_agent_prompts_canon.py (FR-11), а не отдельным сквозным ADR.

Статус

Accepted

Контекст

ORCH-092 — аудит 6 системных промптов .openclaw/agents/*.md. Анализ (BRD §6, TRZ §3) вынес две развилки, которые analyst намеренно не решал (зона архитектора), потребовав ADR ПЕРЕД правкой соответствующих строк:

P1-2 / FR-9 — ручной rebase developer. developer.md (<task>, шаг 2 алгоритма) предписывает git fetch origin && git rebase origin/main. Сверка кодом (BRD A-2) показала, что движок уже держит свежесть базы детерминированно и автоматически, причём двумя независимыми рубежами:

  • Срез ветки от свежего origin/main — serial-gate (ORCH-088) откладывает создание ветки со start_pipeline на момент claim analyst-job (launcher._materialize_deferred_branch, src/agents/launcher.py:421), когда origin/main уже содержит код предшественника (done ⇔ SHA-в-main, ORCH-071/073). ensure_worktree режет worktree от свежего origin/main.
  • Авторитетный pre-merge rebase под merge-leasecheck_branch_mergeable (src/qg/checks.py:697-703) на ребре deploy-staging → deploy вызывает merge_gate.auto_rebase_onto_main (src/merge_gate.py:113) всегда при premerge_rebase_always=True (дефолт, ORCH-026). Эта операция завершается git push --force-with-lease origin <branch> (src/merge_gate.py:151).

Важная асимметрия прав: авторитетный rebase движка обязан делать --force-with-lease, чтобы переписать уже запушенную историю ветки. Developer-промпту это прямо запрещено (<constraints>: « Не используй --no-verify / --force-push»). Значит ручной git rebase origin/main developer'а либо безопасен-но-бесполезен (в начале стадии ветка только что срезана от свежего main — rebase no-op), либо опасен (после первого push повторный rebase требует force-push, который developer'у запрещён) — то есть инструкция шага 2 дублирует автоматику и конфликтует с собственным запретом промпта.

P2-2 / FR-10 — язык deployer. 5 из 6 промптов на русском; deployer.md (~9.6 KB, самый большой и самый safety-critical: self-hosting, прод-рестарт 8500) — на английском. Нужно решить: унифицировать на ru ИЛИ зафиксировать исключение (en). Инвариант NFR-1 критичен: machine-verdict ключи (staging_status:/deploy_status:/security_status: + значения SUCCESS/FAILED/PASS/FAIL), shell-команды и анти-регресс-маркеры (docker exec orchestrator-staging, pr_already_merged, 8500, INFRA-WAIVED) — байт-в-байт неприкосновенны.

Решение

Сводка

D1: убрать безусловный ручной git rebase origin/main из алгоритма developer; свежесть базы — инвариант движка (serial-gate + auto_rebase под lease), а не ответственность агента. D2: оставить deployer.md на английском как явно задокументированное исключение канона; не переводить.

D1 — Developer НЕ делает ручной rebase (закрывает FR-9 / BR-9)

Шаг 2 алгоритма developer (git fetch origin && git rebase origin/main) удаляется как самостоятельная мутирующая операция. Вместо него — короткая нормативная заметка, что:

  • ветка уже срезана движком от свежего origin/main (serial-gate ORCH-088), поэтому ручная синхра на входе не нужна;
  • авторитетный догон main перед слиянием делает движок (auto_rebase_onto_main под merge-lease, ORCH-026/043) на ребре deploy-staging → deploy;
  • developer не делает git rebase / git push --force* сам (это пересекается с запретом <constraints> и с авторитетной операцией движка, использующей --force-with-lease).

Допустимо сохранить read-only git fetch origin (без rebase) — он не мутирует историю и полезен для сверки с актуальным main; но это не обязательный шаг. Главный инвариант: из алгоритма исчезает мутирующий git rebase origin/main.

Привязка: FR-9 (промпт приводится в соответствие с ADR), AC-9 (developer не нарушает no-force-push), анти-регресс — маркер «не мержи свой PR» и запрет force-push сохраняются.

D2 — Deployer остаётся на английском (закрывает FR-10 / BR-10)

deployer.md не переводится; язык остаётся английским как зафиксированное исключение из канона «остальные промпты на ru». Обоснование (в порядке веса):

  1. Минимизация регресс-поверхности на самом критичном промпте. Перевод ~9.6 KB плотного операционного текста — широкая поверхность для случайного слома verdict-ключа, маркера или shell-команды (NFR-1 — критичный инвариант). Deployer управляет прод-рестартом 8500 (групповой self-hosting риск) — здесь цена ошибки максимальна, выгода от churn — нулевая.
  2. Нулевая выгода понимания. Исполняющая модель (claude-opus-4-8) двуязычна; критичные команды, контракты, exit-code-маппинги и verdict-ключи англо-нативны — перевод вокруг них лишь добавляет риск рассинхрона «русский текст ↔ английская команда».
  3. Исключение, а не дрейф. Чтобы будущий агент не «починил» язык вслепую, исключение фиксируется нормативно: (а) запись в CLAUDE.md/README §«Слой промптов», (б) анти-регресс-тест tests/test_agent_prompts_canon.py (FR-11) допускает/ожидает EN для deployer.

D2 не отменяет FR-6: критичная рамка «NEVER restart prod 8500» поднимается/усиливается в начале deployer.md — на английском, в существующем blockquote-стиле. machine-verdict ключи и команды остаются байт-в-байт (AC-6).

Альтернативы

  • D1-альт: оставить ручной rebase «с пояснением». Отвергнуто: пояснение не снимает конфликт с запретом force-push и не устраняет дублирование авторитетной операции движка; «оставить, но объяснить почему оно безопасно» сложнее и хрупче, чем «убрать то, что движок делает лучше».
  • D1-альт: оставить как есть. Отвергнуто: BRD/TRZ явно квалифицируют это как нереализуемо-конфликтующую инструкцию (after-push rebase ⇒ нужен запрещённый force-push).
  • D2-альт: унифицировать deployer на русский. Отвергнуто: максимальный регресс-риск на самом опасном промпте при нулевой выгоде понимания; противоречит духу «docs/prompts-only, минимум изменений, NFR-1 байт-в-байт».

Последствия

  • + Developer-алгоритм перестаёт противоречить собственному запрету force-push; единственный владелец догона main — движок (один авторитетный путь, меньше гонок).
  • + Самый safety-critical промпт (deployer) не подвергается рискованному массовому переводу; NFR-1 защищён структурно.
  • + Оба решения — чисто текстовые, ревертируемы одним PR; src/** не тронут (NFR-2/NFR-3).
  • Языковая неоднородность канона (5 ru + 1 en) остаётся. Митигейшн: явная нормативная запись + тест → это документированное исключение, а не необъяснённый дрейф.
  • Теоретически developer может захотеть подтянуть main во время длинной стадии и теперь не имеет шага rebase. Митигейшн: серийность репо (ORCH-088) ограничивает расхождение main за время одной задачи; авторитетный rebase перед merge закрывает остаточное расхождение детерминированно.
  • Откат: вернуть строку git rebase origin/main в developer.md шаг 2 и (при желании) перевести deployer.mdобе правки текстовые, в одном PR, без изменения кода/схемы.

Ссылки

  • BRD: docs/work-items/ORCH-092/01-brd.md (BR-9, BR-10; §6 A-2)
  • TRZ: docs/work-items/ORCH-092/02-trz.md (FR-9, FR-10)
  • Acceptance: docs/work-items/ORCH-092/03-acceptance-criteria.md (AC-6, AC-9)
  • Канон промптов: docs/architecture/adr/adr-0021-prompt-canon-anthropic.md
  • Сверено по коду: src/merge_gate.py:113,151 (auto_rebase_onto_main + --force-with-lease), src/qg/checks.py:697-703 (check_branch_mergeable → авто-rebase при premerge_rebase_always), src/agents/launcher.py:421 (_materialize_deferred_branch, отложенный срез ветки ORCH-088)
  • Риски: docs/work-items/ORCH-092/10-tech-risks.md