Agent Dev 101

Модуль 16 · Урок 16.17

Урок 16.17. Существующие проекты и монорепозитории

На этой странице
  1. Зачем это нужно
  2. Основная идея
  3. Внедрение в существующий проект
  4. Spec Kit в монорепозитории
  5. Практика
  6. Краткое резюме
  7. Вопросы для самопроверки
  8. Что дальше
  9. Источники

Зачем это нужно

Все примеры модуля до сих пор предполагали если не пустой проект, то хотя бы «наш» проект. Реальность чаще другая: кодовая база существует годами, и главный страх - что внедрение Spec Kit потребует «переписать все задокументированное» или сломает текущую работу. Вторая частая реальность - монорепозиторий, где несколько приложений и пакетов живут под одним корнем.

Два гайда документации отвечают на оба сценария: внедрение в существующий проект - пять шагов от reviewable-бейзлайна до выбора модели старения спек; монорепо - directory-scoped модель проектов и переменные из урока 16.9 в деле.

Основная идея

Для существующего проекта: не нужно воссоздавать систему из спецификаций. Инициализируйте репозиторий на месте, зафиксируйте правила, которые важны, и используйте workflow для следующего ограниченного изменения. Для монорепо: проект Spec Kit - это любой каталог с .specify/; резолюция предпочитает ближайший .specify/, поэтому монорепо держит несколько независимых проектов с собственной нумерацией фич.

Внедрение в существующий проект

Шаг 1: reviewable-бейзлайн

До инициализации закоммитьте или застэшьте текущую работу и создайте ветку для внедрения - каждый сгенерированный файл станет виден в обычном код-ревью.

Выберите ключ интеграции (урок 16.10) и выполните из корня репозитория:

bash
specify init --here --force --integration <key>

--here целит в текущий каталог; --force разрешает инициализацию в непустом каталоге и может заменить файлы на конфликтных managed-путях - используйте только после создания бейзлайна. Остальное приложение он не удаляет.

Отревьюйте diff до продолжения. Инициализация добавляет общие файлы проекта .specify/ и файлы команд/скиллов выбранной интеграции; она не переписывает приложение и не выводит спецификации существующего поведения.

Git-инициализация и ветки фич опциональны и ведутся git-расширением (specify extension add git).

Шаг 2: зафиксировать guardrails

Дальнейшие шаги иллюстрируют внедрение SDD для ограниченной фичи. Если первая задача - ремонт, после инициализации идите в quickstart багфикса (урок 16.6); для оценки предложения - quickstart оценки идей (урок 16.7); ни один не требует сначала пройти SDD.

Запустите /speckit.constitution с принципами, которые уже истинны для репозитория или явно приняты командой:

text
/speckit.constitution Preserve public API compatibility. Follow the existing
service boundaries. Every database migration must include a rollback plan.
Run the repository's established unit and integration test suites.

Источник - README репозитория, архитектурные решения, гайд контрибуций, конфигурация CI. Не изобретайте стандарты ради заполнения шаблона: конституция управляет планированием и анализом, и нереалистичные правила создают шум вместо полезных ограничений.

Шаг 3: ограниченное первое изменение

Начните с фичи или слайса модернизации, которые ревьюятся независимо. Не делайте «задокументировать всю существующую систему» первой фичей - разве что сам инвентарь и есть deliverable.

Опишите и запрошенный результат, и границы совместимости, которые обязаны сохраниться:

text
/speckit.specify Add CSV export to the existing orders page. Preserve current
filters and authorization behavior. Export only the rows visible to the signed-in
user, and do not change the existing JSON API response.

Кодовая база остается контекстом реализации. Новый spec.md определяет изменение, которое вы намерены сделать, - не ретроспективную спецификацию всего существующего поведения.

Шаг 4: планирование против репозитория

Обычный workflow (урок 16.3):

  1. /speckit.clarify - снять неопределенности поведения и требования совместимости;
  2. /speckit.plan - проверить, что предложенный дизайн переиспользует существующую архитектуру, зависимости и тестовые конвенции;
  3. /speckit.tasks, затем /speckit.analyze - консистентность до реализации;
  4. /speckit.implement - ревьюить код и артефакты вместе;
  5. /speckit.converge - найти пробелы; при добавлении задач повторять implement/converge до завершения.

Шаг 5: решить, как будут стареть спеки

После первого изменения договоритесь, как команда поддерживает артефакты завершенных фич: неизменяемые исторические каталоги; living-контракт spec.md с регенерацией производных; или обратный поток находок с последующим reconcil-ем всего набора. Модели сравниваются в уроке 16.8; maintenance-цикл каждой модели - урок 16.18.

Примеры для существующих проектов: community-walkthrough-и включают brownfield-кейсы на .NET, Java и Go/React; расширения архитектурного discovery и brownfield-бутстрапинга - в каталоге расширений (урок 16.19).

Spec Kit в монорепозитории

Проект Spec Kit directory-scoped: проект - это каталог, содержащий .specify/. Монорепо может держать несколько независимых проектов под одним корнем - у каждого свои .specify/, specs/, конституция и нумерация фич.

Резолюция корня предпочитает ближайший .specify/ над Git-toplevel: команды, запущенные внутри проекта-члена, резолвятся в него, а не в корень репо.

Раскладка репозитория отделена от проектирования интерфейсов: когда проекты взаимодействуют, используйте Contract-Driven Development (урок 16.18) для договора между ними - с одним авторитетным владельцем контракта. Проекты в одном репозитории ссылаются на контракт напрямую; в разных - потребляют версионируемый артефакт или синхронизированную копию.

Раскладка

text
my-monorepo/
├── .git/                     # один Git-репозиторий в корне
├── apps/
│   ├── web/
│   │   └── .specify/         # проект Spec Kit "web"
│   │       └── memory/constitution.md
│   └── api/
│       └── .specify/         # проект Spec Kit "api"
│           └── memory/constitution.md
└── packages/
    └── ui/
        └── .specify/         # проект Spec Kit "ui"

Каждый проект инициализируется независимо и ведет собственные specs/ с независимой нумерацией (apps/web/specs/001-…, apps/api/specs/001-…):

bash
specify init apps/web --integration claude
specify init apps/api --integration claude

Работа внутри проекта-члена

Workflow не меняется: перейдите в каталог проекта и запускайте слэш-команды - резолюция найдет ближайший .specify/:

bash
cd apps/web
# затем /speckit.specify, /speckit.plan, ... в агенте

Цели в проект-член из корня репо

Для неинтерактива и CI без cd - SPECIFY_INIT_DIR на корень проекта-члена (каталог, содержащий .specify/; относительные пути резолвятся от текущего):

bash
export SPECIFY_INIT_DIR=apps/web

Путь обязан существовать и содержать .specify/; иначе команда ошибается без fallback на текущий каталог или Git-toplevel - опечатка никогда не запишет спеки не в тот проект:

text
# SPECIFY_INIT_DIR=apps/wbe  (опечатка: нет такого каталога)
ERROR: SPECIFY_INIT_DIR does not point to an existing directory: apps/wbe

# SPECIFY_INIT_DIR=apps  (существует, но без собственного .specify/)
ERROR: SPECIFY_INIT_DIR is not a Spec Kit project (no .specify/ directory): /home/you/my-monorepo/apps

Напоминание двух осей (урок 16.9): SPECIFY_INIT_DIR выбирает проект; SPECIFY_FEATURE_DIRECTORY - фичу; они компонуются для неинтерактивного выбора обоих. Project-scoped-подкоманды CLI чтут ту же переменную:

bash
export SPECIFY_INIT_DIR=apps/web
specify workflow list          # workflows проекта apps/web
specify integration status     # интеграция проекта apps/web

Как SPECIFY_INIT_DIR достигает агента

Переменную читают shell-скрипты, вызываемые слэш-командами (get_repo_root в Bash, Get-RepoRoot в PowerShell); действует она только в окружении шелла этих скриптов. Скриптовые/CI-прогоны: экспортируйте в том же шелле, что драйвит команды, - надежно. Интерактивные агенты: доходит ли экспорт до shell-тула агента - зависит от агента; экспортируйте до запуска агента и проверьте раз (например, /speckit.specify - и убедитесь, что фича легла в specs/ нужного проекта).

Git и конституции в монорепо

Файлы проекта скоуплены к резолвленному корню, но Git-операции идут в содержащем Git work tree: при едином репозитории в корне создание веток фич создает/переключает ветки в общем корневом репо - каталоги спек остаются под выбранным проектом, а namespace веток общий на весь монорепо. Управляйте ветками и коммитами из корня или инициализируйте Git per-project для изолированных веточных namespace.

Конституции: у каждого проекта свой .specify/memory/constitution.md, /speckit.constitution правит локальный файл. Встроенного механизма наследования нет: хотите одну конституцию со ссылками на общие правила монорепо - ведите проводку сами, иначе дублируйте/синхронизируйте правила per-project.

Практика

  1. В тестовом репозитории с существующим кодом пройдите шаги 1-3: бейзлайн-ветка, specify init --here --force, конституция из фактических правил проекта, первая bounded-фича с явными границами совместимости.
  2. Разверните мини-монорепо из двух проектов (apps/web, apps/api) и проверьте изоляцию: из apps/api фичи нумеруются независимо от apps/web; из корня SPECIFY_INIT_DIR=apps/api + specify integration status показывает интеграцию api.
  3. Проверьте защиту от опечатки: SPECIFY_INIT_DIR=apps/wbe и SPECIFY_INIT_DIR=apps - убедитесь, что обе ошибки информативны и fallback отсутствует.

Краткое резюме

Внедрение в существующий проект - пять шагов: reviewable-бейзлайн (init --here --force в ветке), конституция из уже истинных правил, bounded-первая фича с границами совместимости, обычный planning-цикл против существующей архитектуры, выбор модели старения спек. Монорепо - directory-scoped: несколько независимых .specify/-проектов, резолвция к ближайшему, таргетинг из корня через SPECIFY_INIT_DIR без fallback при ошибке.

Главное из урока:

  • инициализация не переписывает приложение и не выводит спецификации существующего поведения;
  • первая фича - ограниченное изменение, не «задокументировать всё»;
  • конституция из реальных правил; выдуманные стандарты - шум для планирования;
  • в монорепо Git-namespace веток общий, если Git не инициализирован per-project;
  • наследования конституций нет - синхронизация общих правил вручную.

Вопросы для самопроверки

  1. Почему перед specify init --here --force нужна отдельная ветка? Что именно может заменить --force?
  2. Что неправильно в первой фиче «задокументировать всю существующую систему»? Когда такое допустимо?
  3. Чем spec.md bounded-фичи в существующем проекте отличается от ретроспективной спецификации системы?
  4. Как резолвция корня работает в монорепо? Почему ближайший .specify/ важнее Git-toplevel?
  5. Объясните поведение при невалидном SPECIFY_INIT_DIR. Почему отсутствие fallback - сознательное решение?
  6. Какие две проблемы монорепо решаются без встроенных механизмов (и как)?

Что дальше

Урок 16.18 закрывает жизненный цикл спецификаций после реализации: maintenance-циклы трех моделей хранения и Contract-Driven Development - договоры между компонентами до реализации каждой стороны.

Источники

Обновлено 03.10.2026