From bf17e5a7aa245f2fd095e920af08048d2711b8f4 Mon Sep 17 00:00:00 2001 From: Dmitry Afonasenko Date: Thu, 1 Oct 2026 19:48:37 +0500 Subject: [PATCH] feat(architecture): add minimal project bootstrap --- README.md | 8 +++ ai-rules.ps1 | 8 +-- hub/ARCHITECTURE.md | 2 + profiles/standard-product.md | 1 + rules/ARCHITECTURE_AND_DATA.md | 21 ++++++-- rules/IMPLEMENTATION.md | 1 + rules/README.md | 2 +- scripts/check-hub.ps1 | 1 + scripts/show-prompt.ps1 | 13 ++++- sync/README.md | 2 + sync/catalog.json | 8 ++- sync/project-manifest.schema.json | 1 + templates/AGENTS.md | 2 + templates/ARCHITECTURE.md | 24 +++++++-- templates/PROJECT_RULES.full.md | 12 +++++ templates/PROJECT_RULES.md | 2 + templates/README.md | 1 + tests/cli/test-integration.ps1 | 31 +++++++++-- workflows/PROJECT_AUDIT_PROMPT.md | 2 +- workflows/PROJECT_BOOTSTRAP.md | 81 +++++++++++++++++++++++++++++ workflows/PROJECT_CONNECT_PROMPT.md | 3 +- 21 files changed, 208 insertions(+), 18 deletions(-) create mode 100644 workflows/PROJECT_BOOTSTRAP.md diff --git a/README.md b/README.md index e0e3654..8a81ecd 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,14 @@ Copy the generated prompt into the AI agent working on that project. The agent w Then return to your normal project work. You do not need to learn how the kit works or select rule files manually. +For a new product, start with a small architecture before implementing its first scenario: + +```powershell +.\ai-rules.ps1 prompt bootstrap -ProjectRoot C:\path\to\project +``` + +Paste the prompt with your goal and first scenario. The agent chooses where code belongs, creates only the needed parts, and checks the important dependency boundaries. Connecting an existing project does not restructure its code. + For a deep project audit later, generate a dedicated prompt: ```powershell diff --git a/ai-rules.ps1 b/ai-rules.ps1 index 7bbf52a..9a9eb69 100644 --- a/ai-rules.ps1 +++ b/ai-rules.ps1 @@ -65,6 +65,8 @@ Agent Engineering Kit Подготовить запрос для изучения проекта. prompt parallel -ProjectRoot ПУТЬ Подготовить запрос для параллельной задачи. + prompt bootstrap -ProjectRoot ПУТЬ + Выбрать первоначальную архитектуру нового проекта. connect -ProjectRoot ПУТЬ Подготовить проект и показать изменения. connect -ProjectRoot ПУТЬ -Apply @@ -731,12 +733,12 @@ try { } } 'prompt' { - if ([string]::IsNullOrWhiteSpace($ListTarget) -or $ListTarget.ToLowerInvariant() -notin @('audit', 'connect', 'deep-audit', 'study', 'parallel')) { - throw "Для команды 'prompt' укажите 'connect', 'audit', 'deep-audit', 'study' или 'parallel'." + if ([string]::IsNullOrWhiteSpace($ListTarget) -or $ListTarget.ToLowerInvariant() -notin @('audit', 'connect', 'deep-audit', 'study', 'parallel', 'bootstrap')) { + throw "Для команды 'prompt' укажите 'connect', 'audit', 'deep-audit', 'study', 'parallel' или 'bootstrap'." } $promptName = $ListTarget.ToLowerInvariant() $promptArguments = @('-Name', $promptName) - if ($promptName -in @('connect', 'deep-audit', 'study', 'parallel')) { + if ($promptName -in @('connect', 'deep-audit', 'study', 'parallel', 'bootstrap')) { $resolvedProjectRoot = Resolve-ProjectRoot -Path $ProjectRoot $promptArguments += @('-ProjectRoot', $resolvedProjectRoot) } diff --git a/hub/ARCHITECTURE.md b/hub/ARCHITECTURE.md index 57fee76..1682698 100644 --- a/hub/ARCHITECTURE.md +++ b/hub/ARCHITECTURE.md @@ -51,6 +51,8 @@ AGENTS.md целевого проекта Инструкции для ограниченного процесса: подключения, первичного аудита или учебного изучения проекта. Workflow применяется только по явной команде или выбранному совместимому идентификатору и не становится нормой для всех задач проекта. +Первоначальный выбор обязан состояться по `ARCHITECTURE_AND_DATA.md` до существенной реализации новой развиваемой области. Всегда читаемый `standard-product`, тема реализации и `INDEX` ведут к этому условию; локальный контракт затем определяет место нового кода. [`PROJECT_BOOTSTRAP.md`](../workflows/PROJECT_BOOTSTRAP.md) содержит только стартовый процесс, три архетипа и запрос `prompt bootstrap` в одном файле. `project-bootstrap` выбирается явно и не входит в композицию профилей. Подключение нового проекта предлагает следующий шаг, существующего — фиксирует разрыв без реализации или рефакторинга. Если процесс не установлен, краткий контракт архитектурного правила остаётся достаточным для первоначального выбора. + ### `sync/` и управляемая копия `sync/catalog.json` задаёт разрешённые значения `topics`, `profiles` и их зависимости. Файл `.ai-rules/manifest.json` выбирает состав, а `.ai-rules/lock.json` хранит точную версию и SHA-256. diff --git a/profiles/standard-product.md b/profiles/standard-product.md index b6a82dc..55c7f8e 100644 --- a/profiles/standard-product.md +++ b/profiles/standard-product.md @@ -9,6 +9,7 @@ - Единица работы — минимальный сквозной сценарий от входа пользователя или оператора до наблюдаемого результата. - Каждая поставка имеет самостоятельный проверяемый пользовательский, эксплуатационный или защитный результат. Инфраструктурная работа допустима отдельно, если устраняет названный риск или создаёт проверяемую возможность для ближайшего сценария. - Техническая работа связана с текущим пользовательским результатом, операционным риском или явно названной обязанностью совместимости. +- До первой существенной реализации нового продукта или крупной подсистемы без границ прочитай раздел «Первоначальная архитектура» темы `architecture-and-data` по `INDEX.md`. В существующей области используй локальный контракт размещения кода; подключение Kit само по себе не запускает перестройку. ## Рекомендуемые локальные документы diff --git a/rules/ARCHITECTURE_AND_DATA.md b/rules/ARCHITECTURE_AND_DATA.md index e573ac0..3b31273 100644 --- a/rules/ARCHITECTURE_AND_DATA.md +++ b/rules/ARCHITECTURE_AND_DATA.md @@ -11,17 +11,32 @@ - Для существенных модулей назови допустимое направление зависимостей, разрешённые точки входа и запрещённые связи. Например: `UI → прикладной сервис → репозиторий`; конкретная схема зависит от проекта. - Архитектурное правило должно ограничивать наблюдаемый риск, а не предписывать каждую деталь реализации. Внутри проверяемых границ сохраняй свободу выбора решения. -- Устойчивые ограничения по слоям, импортам, схемам, именованию и размеру модулей по возможности закрепляй линтером, анализатором зависимостей или структурным тестом. Сообщение проверки объясняет нарушенную границу и способ исправления. +- В развиваемом проекте после выбора устойчивых границ агент обязан закрепить наиболее важные разрешённые и запрещённые связи линтером, анализатором зависимостей или структурным тестом до завершения первого сквозного сценария. Используй существующий инструмент либо небольшой локальный скрипт; тяжёлая зависимость без необходимости не нужна. Сообщение проверки объясняет нарушенную границу и способ исправления. +- Проверка должна наблюдать реальные пути зависимостей проекта, включая используемые алиасы, реэкспорты и статические динамические импорты. Докажи, что разрешённый случай проходит, а представительное нарушение отклоняется; проверка пустого каталога не защищает границу. Назови команду и место запуска в обычном наборе проверок; CI подключай в пределах задачи. Если автоматизация недоступна, запиши конкретное ограничение и следующую проверку, но не объявляй границу механически защищённой. - Не автоматизируй непроверенное предпочтение. Если один и тот же архитектурный дрейф повторяется, устраняй не только частный случай: уточни правило, проверку или обратную связь, которые предотвращают повторение. ## Организация кода и импортов -- В новом нетривиальном проекте до накопления функций определи минимальные границы модулей, их ответственности, точки входа и направление зависимостей для первых реальных сценариев. Не создавай слои для гипотетического роста, но и не складывай независимые UI, прикладную оркестрацию, доменные правила и доступ к данным в один стартовый файл. -- Модуль, компонент и каталог группируются по связной ответственности и причинам совместного изменения. Большой файл, смешение представления с независимым поведением или десятки несгруппированных соседних файлов — сигнал проверить границы, но не основание для механического деления по числу строк или файлов. +- Модуль, компонент и каталог группируются по связной ответственности и причинам совместного изменения. Код одной возможности остаётся рядом с ней, включая её UI, независимую логику и узкие тесты; общие интеграционные проверки могут оставаться отдельно. +- Корень исходников содержит точки входа и архитектурные области, а не россыпь независимой прикладной логики. Общая папка компонентов не заменяет владельцев самостоятельных сценариев. В общую область выноси фактически переиспользуемый или по природе общесистемный код; она не знает конкретные возможности. +- Точка композиции собирает зависимости, маршруты и экраны. Она не должна заодно владеть несколькими самостоятельными экранами, сетевым доступом и независимыми расчётами. Локальные обработчики и состояние одного связного компонента не требуют отдельного слоя. +- При заметном росте файла или перед добавлением существенной функции в файл с несколькими независимыми причинами изменения агент обязан проверить ответственности: назвать владельцев поведения и решить, сохранить связный файл либо выделить самостоятельную границу в затронутой области. Несвязанный долг фиксируй отдельно. Большой связный файл допустим; число строк или файлов не заменяет эту проверку. - Формат фреймворка не отменяет разделение ответственностей. Например, Vue SFC может совместно хранить `template`, локальный `script` и локальные `style`, пока они обслуживают один связный компонент; самостоятельные сценарии, доменная логика, сетевое взаимодействие и доступ к постоянному хранилищу получают подходящую границу вне компонента экрана. - Проект выбирает устойчивый способ импортов, соответствующий его языку, размеру и инструментам. Если принят алиас или публичная точка входа, одно и то же отображение действует во всех реально используемых средах: проверке типов, сборке, выполнении, тестах, линтере и редакторе. - Относительные импорты подходят внутри одной локальной границы. Переходы через несколько модулей или слоёв не должны обходить установленное направление зависимостей; конкретный предел глубины и способ проверки задаются локальной архитектурной политикой. +## Первоначальная архитектура + +До существенной реализации нового развиваемого проекта, крупного package/application или подсистемы без установленных границ агент обязан выбрать минимальную архитектуру для первых реальных сценариев. Несколько сценариев, UI с данными и внешним доступом либо независимые причины изменения требуют выбора сразу, а не после накопления долга. Количество файлов не является критерием. + +Зафиксируй в локальном архитектурном контракте тип проекта, первые сценарии, выбранный архетип, области и их владельцев, направление зависимостей, точки композиции, маршрут размещения нового кода, сознательно отсутствующие слои и условия пересмотра. Несколько абзацев в `PROJECT_RULES` или существующей карте достаточно; отдельный документ не обязателен. После выбора этот контракт ограничивает дальнейшие изменения. + +Выбери один стартовый архетип: пользовательский frontend с локальными возможностями; сервис с независимыми сценариями и адаптерами; библиотека/CLI с минимальным техническим ядром. Имена каталогов зависят от проекта. Создавай каталог только вместе с реальным кодом его ответственности, без пустых слоёв на будущее. Пошаговый запуск и примеры архетипов доступны через `project-bootstrap` или команду хаба `prompt bootstrap`; они читаются только при первоначальном выборе. Если процесс не установлен или хаб недоступен, выполни этот краткий контракт и проверку границ из раздела выше, не откладывая выбор. + +Одноразовый скрипт, экспериментальный файл, минимальный воспроизводитель, очень маленький прототип или небольшой CLI с одной связной обязанностью могут остаться компактными без модульного каркаса и отдельного архитектурного guard. Назови причину и триггер возврата: превращение в развиваемый продукт, второй самостоятельный сценарий или новая независимая граница. Прототип уже запланированного продукта не является автоматическим исключением. + +У существующей области сначала используй действующие границы. Подключение правил не создаёт архитектуру, guard и не разрешает рефакторинг: отсутствие контракта фиксируется как разрыв. При обычной feature-задаче читай локальный маршрут размещения кода и затронутые решения, а не все стартовые архетипы. + ## Целевое состояние и переход - Перед значимой реструктуризацией исследуй всю затронутую область: фактические зависимости, владельцев поведения, причины совместных изменений и уже наблюдаемый дрейф. Размер каталога или файла является сигналом, а не самостоятельным доказательством плохой архитектуры. diff --git a/rules/IMPLEMENTATION.md b/rules/IMPLEMENTATION.md index 0006a72..508e294 100644 --- a/rules/IMPLEMENTATION.md +++ b/rules/IMPLEMENTATION.md @@ -3,6 +3,7 @@ ## Изменение кода - Сначала проследи затронутый сценарий и его контракты, затем меняй минимальную связанную область. +- До добавления нового кода найди его владельца и место по локальному архитектурному контракту. Для нового развиваемого проекта или крупной подсистемы без границ сначала выполни раздел «Первоначальная архитектура» в `ARCHITECTURE_AND_DATA.md`; обычная feature-задача использует уже выбранную структуру. - Если дефект или требование может повторяться в похожих экранах, компонентах, операциях или состояниях, до исправления найди семантически аналогичные места во всём затронутом сценарии. Не ограничивай поиск совпадением имени файла, селектора или текста. - Для найденных мест отдели общую причину от внешне похожих независимых случаев. Используй общий механизм только при общем контракте; иначе исправь подтверждённые случаи отдельно. В согласованных границах обработай все подтверждённые вхождения, а оставшиеся явно перечисли как непроверенные или вынесенные за границы задачи. - Перенос, замена или удаление поведения завершены, когда прослежены прежние точки входа и потребители, для каждого выбран результат: удалить, перенаправить, мигрировать либо осознанно сохранить. Проверь доступность нового пути и отсутствие незапланированного старого. diff --git a/rules/README.md b/rules/README.md index d50ad24..0c55438 100644 --- a/rules/README.md +++ b/rules/README.md @@ -9,7 +9,7 @@ | Документ | Когда обязателен | | --- | --- | | [`PRODUCT.md`](PRODUCT.md) | продуктовая функция, требования, UI-текст или приоритизация | -| [`ARCHITECTURE_AND_DATA.md`](ARCHITECTURE_AND_DATA.md) | модели, границы модулей, хранение, API, миграции | +| [`ARCHITECTURE_AND_DATA.md`](ARCHITECTURE_AND_DATA.md) | до существенной реализации нового развиваемого проекта или подсистемы без границ; размещение кода, модели, хранение, API, миграции | | [`IMPLEMENTATION.md`](IMPLEMENTATION.md) | изменение кода, конфигурации или зависимостей | | [`QUALITY.md`](QUALITY.md) | до реализации для выбора приёмки; проверка и передача изменения | | [`RELIABILITY_AND_OPERATIONS.md`](RELIABILITY_AND_OPERATIONS.md) | эксплуатация сервиса, деградация, восстановление либо риск производительности или предельной нагрузки | diff --git a/scripts/check-hub.ps1 b/scripts/check-hub.ps1 index 8f22dc9..0bf0874 100644 --- a/scripts/check-hub.ps1 +++ b/scripts/check-hub.ps1 @@ -30,6 +30,7 @@ $requiredPaths = @( 'profiles/README.md', 'templates/README.md', 'workflows/PROJECT_CONNECT_PROMPT.md', + 'workflows/PROJECT_BOOTSTRAP.md', 'workflows/PROJECT_AUDIT_PROMPT.md', 'workflows/PROJECT_DEEP_AUDIT_PROMPT.md', 'workflows/PROJECT_STUDY.md', diff --git a/scripts/show-prompt.ps1 b/scripts/show-prompt.ps1 index 88cc427..5dbae4a 100644 --- a/scripts/show-prompt.ps1 +++ b/scripts/show-prompt.ps1 @@ -1,7 +1,7 @@ [CmdletBinding()] param( [Parameter(Mandatory = $true)] - [ValidateSet('audit', 'connect', 'deep-audit', 'study', 'parallel')] + [ValidateSet('audit', 'connect', 'deep-audit', 'study', 'parallel', 'bootstrap')] [string]$Name, [string]$ProjectRoot @@ -38,6 +38,12 @@ switch ($Name) { } $promptPath = Join-Path $hubRoot 'workflows/PARALLEL_DELIVERY_PROMPT.md' } + 'bootstrap' { + if ([string]::IsNullOrWhiteSpace($ProjectRoot)) { + throw 'ProjectRoot is required for prompt bootstrap.' + } + $promptPath = Join-Path $hubRoot 'workflows/PROJECT_BOOTSTRAP.md' + } } $promptDocument = Get-Content -LiteralPath $promptPath -Raw -Encoding UTF8 @@ -47,10 +53,13 @@ if (-not $promptMatch.Success) { } $prompt = $promptMatch.Groups['prompt'].Value.Trim() -if ($Name -in @('connect', 'deep-audit', 'study', 'parallel')) { +if ($Name -in @('connect', 'deep-audit', 'study', 'parallel', 'bootstrap')) { $resolvedProjectRoot = (Resolve-Path -LiteralPath $ProjectRoot).Path $cliPath = Join-Path $hubRoot 'ai-rules.ps1' $prompt = $prompt.Replace('{{PROJECT_ROOT}}', $resolvedProjectRoot).Replace('{{HUB_CLI_PATH}}', $cliPath) + if ($Name -eq 'bootstrap') { + $prompt = $prompt.Replace('{{BOOTSTRAP_WORKFLOW_PATH}}', $promptPath) + } if ($Name -eq 'parallel') { $taskContractPath = Join-Path $hubRoot 'templates/TASK_CONTRACT.md' $prompt = $prompt.Replace('{{TASK_CONTRACT_PATH}}', $taskContractPath) diff --git a/sync/README.md b/sync/README.md index 2bf10b5..d204ea2 100644 --- a/sync/README.md +++ b/sync/README.md @@ -16,6 +16,8 @@ После применения проект использует собственную копию правил и не зависит от доступности хаба. +`project-bootstrap` — необязательный идентификатор рабочего процесса в существующем массиве `topics`. Он не меняет manifest/lock schema и не добавляется профилями. Для нового развиваемого проекта его можно выбрать явно; `prompt bootstrap` также позволяет прочитать процесс прямо из хаба. `connect` и `update` управляют теми же файлами правил, не создают архитектурный skeleton или guard и не меняют код проекта. + ## Файлы проекта | Файл | Владелец | Назначение | diff --git a/sync/catalog.json b/sync/catalog.json index 562d104..03558fe 100644 --- a/sync/catalog.json +++ b/sync/catalog.json @@ -19,7 +19,7 @@ "file": "rules/ARCHITECTURE_AND_DATA.md", "kind": "rule", "description": "Архитектурные границы, источники истины, данные, API и миграции.", - "readWhen": "При изменении архитектурных границ, данных, API, хранилища или миграций." + "readWhen": "До существенной реализации нового развиваемого проекта или крупной подсистемы без границ; при размещении нового кода, изменении архитектуры, данных, API, хранилища или миграций." }, "implementation": { "file": "rules/IMPLEMENTATION.md", @@ -81,6 +81,12 @@ "description": "Рабочий процесс глубокого аудита проекта с явным пространством проверки и покрытием.", "readWhen": "Только при явном выборе project-audit и задаче на глубокий системный аудит проекта." }, + "project-bootstrap": { + "file": "workflows/PROJECT_BOOTSTRAP.md", + "kind": "workflow", + "description": "Первоначальный выбор минимальной архитектуры, размещения кода и механической защиты границ.", + "readWhen": "При явном выборе project-bootstrap и создании развиваемого проекта или крупной подсистемы без границ; не при обычной feature-задаче." + }, "parallel-delivery": { "file": "workflows/PARALLEL_DELIVERY.md", "kind": "workflow", diff --git a/sync/project-manifest.schema.json b/sync/project-manifest.schema.json index 68ea798..32f9653 100644 --- a/sync/project-manifest.schema.json +++ b/sync/project-manifest.schema.json @@ -43,6 +43,7 @@ "research-and-evidence", "project-study", "project-audit", + "project-bootstrap", "parallel-delivery" ] } diff --git a/templates/AGENTS.md b/templates/AGENTS.md index fefffc1..cf365d5 100644 --- a/templates/AGENTS.md +++ b/templates/AGENTS.md @@ -16,6 +16,8 @@ Читай выбранный профиль целиком. Не читай весь каталог `.ai-rules/upstream/` и все темы без связи с задачей. +При создании развиваемого проекта или крупной подсистемы без архитектурного контракта найди по `INDEX.md` тему `architecture-and-data` и начни с первоначального выбора. Если тема не подключена, обозначь необходимое расширение набора; не начинай существенную реализацию без границ. Для обычного изменения используй локальный маршрут размещения кода, без чтения всех стартовых архетипов. + Пути к документации проекта указаны в `.ai-rules/PROJECT_RULES.md`. По индексу и заголовкам найди нужную область, прочитай её разделы карты проекта и записи решений, затем связанные источники. Не читай всю карту или каталог `docs/` для узкой задачи. ## Где менять правила diff --git a/templates/ARCHITECTURE.md b/templates/ARCHITECTURE.md index 14fe1f9..d0535aa 100644 --- a/templates/ARCHITECTURE.md +++ b/templates/ARCHITECTURE.md @@ -8,6 +8,14 @@ - `<...>` +## Первоначальный выбор и области + +- Тип проекта и первые реальные сценарии: `<...>`. +- Выбранный архетип и причина: ``. +- Функциональные области и уровни: `<реально нужные владельцы UI, прикладного поведения, данных и внешнего доступа>`. +- Точки композиции: `<где собираются зависимости и экраны>`. +- Сознательно отсутствуют: `<слои без текущей ответственности>`. + ## Фактическая архитектура ```text @@ -29,13 +37,22 @@ - Разрешённые точки входа: `<...>`. - Запрещённые связи: `<...>`. +## Где размещать новый код + +| Ответственность | Владелец и путь | +| --- | --- | +| UI и логика конкретной возможности | `<её локальная область>` | +| Внешний доступ | `<адаптер этой области либо общий клиент>` | +| Действительно общий код | `<общесистемная область и основание общности>` | +| Новая возможность / композиция | `<место нового модуля / точка сборки>` | + ## Механическая проверка границ -| Ограничение | Проверка | Где запускается | +| Ограничение | Команда и механизм | Подтверждение и запуск | | --- | --- | --- | -| `<направление импорта / схема / именование / другое>` | `<линтер, анализатор или структурный тест / не установлена>` | `<локально, CI / не установлено>` | +| `<устойчивая запрещённая связь или состав корня>` | `<линтер, анализатор или структурный тест / не установлена>` | `<разрешённый случай проходит; нарушение отклоняется; обычные проверки, CI при наличии>` | -Не добавляй проверку только ради заполнения таблицы. Отсутствующий механизм фиксируется как разрыв и создаётся отдельной задачей. +При подключении существующего проекта отсутствующая проверка остаётся разрывом. При первоначальной реализации развиваемого проекта создай проверку принятых границ в той же задаче по `architecture-and-data`, а не ради заполнения таблицы. ## Целевое направление @@ -49,3 +66,4 @@ - `<Что ещё не решено.>` - `<Какой второй сценарий или риск заставит пересмотреть архитектуру.>` +- `<Как вводить новую границу постепенно и удалить ненужный слой с проверкой потребителей; не сохранять слой только из-за шаблона.>` diff --git a/templates/PROJECT_RULES.full.md b/templates/PROJECT_RULES.full.md index 2edf9d3..afef84e 100644 --- a/templates/PROJECT_RULES.full.md +++ b/templates/PROJECT_RULES.full.md @@ -31,6 +31,18 @@ ## Структура проекта - `<../каталог или модуль>` — `<локальная ответственность>`. +- Первоначальный выбор: `<тип, первые сценарии, выбранный архетип; ссылка на канонический контракт / не установлен>`. +- Зависимости и композиция: `<разрешённые направления, точки входа, запрещённые связи и точка сборки / не установлены>`. + +| Новый код | Владелец и точный путь | +| --- | --- | +| UI и прикладная логика одной возможности | `<локальная область возможности>` | +| Внешний доступ | `<локальный либо общесистемный адаптер>` | +| Общий UI, тип или вычисление | `<подтверждённый общий владелец; иначе оставить локально>` | +| Новая самостоятельная возможность | `<новый feature/module по действующему контракту>` | +| Композиция приложения | `<точка сборки зависимостей и экранов>` | + +Сознательно отсутствующие слои и триггеры роста: `<...>`. Механическая проверка границ: `<команда, ограничения и место запуска / не установлена>`. ## Документация и маршрутизация контекста diff --git a/templates/PROJECT_RULES.md b/templates/PROJECT_RULES.md index 8521bb7..b4e8043 100644 --- a/templates/PROJECT_RULES.md +++ b/templates/PROJECT_RULES.md @@ -18,6 +18,8 @@ - `<Значимые каталоги, канонические документы и узкие маршруты чтения для разных задач.>` - Карта проекта: `<ссылка и разделы по областям / не установлена>`; карта решений: `<ссылка; читать записи затронутой области / не установлена>`. +- Архитектурный контракт: `<ссылка на раздел / кратко: тип, первые сценарии, архетип, области, зависимости, точка композиции, отсутствующие слои и условия пересмотра / не установлен>`. +- Где размещать новый код: ``. ## Граница документации diff --git a/templates/README.md b/templates/README.md index 3a5e73f..ffcee4e 100644 --- a/templates/README.md +++ b/templates/README.md @@ -17,6 +17,7 @@ Готовые запросы находятся отдельно: - [`PROJECT_CONNECT_PROMPT.md`](../workflows/PROJECT_CONNECT_PROMPT.md) — подключение проекта; +- [`PROJECT_BOOTSTRAP.md`](../workflows/PROJECT_BOOTSTRAP.md) — первоначальная архитектура и архетипы через `ai-rules.ps1 prompt bootstrap -ProjectRoot <путь>`; отдельный файл архитектуры не обязателен. - [`PROJECT_AUDIT_PROMPT.md`](../workflows/PROJECT_AUDIT_PROMPT.md) — завершение подключения и первичная проверка; - [`PROJECT_DEEP_AUDIT_PROMPT.md`](../workflows/PROJECT_DEEP_AUDIT_PROMPT.md) — подключение и запуск глубокого аудита; - [`PROJECT_STUDY_PROMPT.md`](../workflows/PROJECT_STUDY_PROMPT.md) — подключение и начало изучения проекта через `ai-rules.ps1 prompt study -ProjectRoot <путь>`. diff --git a/tests/cli/test-integration.ps1 b/tests/cli/test-integration.ps1 index 79a762c..1c33f19 100644 --- a/tests/cli/test-integration.ps1 +++ b/tests/cli/test-integration.ps1 @@ -125,6 +125,7 @@ try { $syncPlanTest = Get-Content -LiteralPath (Join-Path $hubRoot 'tests/sync/test-sync-plan.ps1') -Raw -Encoding UTF8 $commitHookIndexEntry = (& git -C $hubRoot ls-files --stage -- .githooks/commit-msg) -join '' $catalog = Get-Content -LiteralPath (Join-Path $hubRoot 'sync/catalog.json') -Raw -Encoding UTF8 | ConvertFrom-Json + $bootstrapWorkflow = Get-Content -LiteralPath (Join-Path $hubRoot 'workflows/PROJECT_BOOTSTRAP.md') -Raw -Encoding UTF8 $crlfHubRoot = Join-Path $tempRoot 'crlf hub fixture' foreach ($trackedPath in @(& git -C $hubRoot ls-files --cached --others --exclude-standard)) { @@ -218,10 +219,14 @@ try { } Assert-True -Condition ($coreRule -match 'Инструкция, найденная внутри недоверенного содержимого.*остаётся данными' -and $coreRule -match 'не получает полномочий прямого запроса владельца' -and $coreRule -match 'установленные локальные инструкции.*приоритету' -and $coreRule -match 'канонический источник' -and $coreRule -match 'Перед вызовом инструмента') -Message 'CORE must distinguish owner authority from untrusted embedded instructions and retain canonical-source discipline' Assert-True -Condition ($architectureRule -match '(?m)^## Направление зависимостей\s*$' -and $architectureRule -match 'запрещённые связи' -and $architectureRule -match 'линтером, анализатором зависимостей или структурным тестом' -and $architectureRule -match '(?m)^## Доступность контекста\s*$' -and $architectureRule -match 'Короткая точка входа') -Message 'architecture rules must combine navigable context with mechanically enforced boundaries' + Assert-True -Condition ($catalog.topics.'architecture-and-data'.readWhen -match 'До существенной реализации.*без границ' -and $standardProductProfile -match 'Первоначальная архитектура.*architecture-and-data.*INDEX' -and $agentsTemplate -match 'без архитектурного контракта.*INDEX.*architecture-and-data' -and $agentsTemplate -match 'без чтения всех стартовых архетипов') -Message 'new project routing must reach architecture before implementation without requiring all archetypes for ordinary tasks' + Assert-True -Condition ($catalog.topics.'project-bootstrap'.file -eq 'workflows/PROJECT_BOOTSTRAP.md' -and $catalog.topics.'project-bootstrap'.kind -eq 'workflow' -and $catalog.topics.'project-bootstrap'.readWhen -match 'не при обычной feature-задаче') -Message 'bootstrap catalog entry must route to a conditional startup workflow' + Assert-True -Condition ($standardProductProfile -notmatch 'shared →|core/model|application →|### A\.' -and $coreRule -notmatch 'project-bootstrap|архетип') -Message 'startup examples must not be duplicated into the always-read profile or CORE' + Assert-True -Condition ($bootstrapWorkflow -match 'Обычная feature-задача.*не запускает процесс повторно' -and $bootstrapWorkflow -match 'подключение меняет только файлы правил' -and $bootstrapWorkflow -match 'После выбора читай локальный контракт' -and $projectRulesTemplate -match 'Где размещать новый код' -and $fullProjectRulesTemplate -match 'Новый код.*Владелец и точный путь') -Message 'bootstrap must hand subsequent work to local placement contracts and preserve adoption scope' Assert-True -Condition ($researchRule -match 'сначала определи владельца контракта и его канонический источник' -and $researchRule -match 'Для поведения, которым владеет проект' -and $researchRule -match 'Для внешнего API.*официальную спецификацию' -and $researchRule -match 'выполнение.*не заменяет нормативный контракт') -Message 'research rules must select normative evidence by contract ownership and separate actual behavior from the contract' Assert-True -Condition ($projectConnectPrompt -match 'минимальный набор профилей и тем' -and $projectConnectPrompt -match 'Остановись перед `-Apply`' -and $projectConnectPrompt -match 'не выполняй `commit`, `push`' -and $projectConnectPrompt -match '\{\{PROJECT_ROOT\}\}' -and $projectConnectPrompt -match '\{\{HUB_CLI_PATH\}\}') -Message 'project connect prompt must guide minimal selection, explicit approval, and external-action boundaries' Assert-True -Condition ($projectAuditPrompt -match 'Этап 1 — завершение подключения' -and $projectAuditPrompt -match 'явно сообщи, что подключение завершено' -and $projectAuditPrompt -match 'Этап 2 — проверка только для чтения' -and $projectAuditPrompt -match 'После этого не меняй файлы проекта' -and $projectAuditPrompt -match '`satisfied`, `gap`, `not applicable` или `unknown`' -and $projectAuditPrompt -match 'отдельные задачи на исправление, но не выполняй их') -Message 'project audit prompt must separate adoption changes from the read-only project review' - Assert-True -Condition ($projectAuditPrompt -match 'похожие сценарии, экраны и операции' -and $projectAuditPrompt -match 'не исправлен ли только один вариант' -and $projectAuditPrompt -match 'путь нового разработчика' -and $projectAuditPrompt -match 'Большой файл считай только сигналом' -and $projectAuditPrompt -match 'повторяющиеся разрывы по классам') -Message 'project audit prompt must compare analogous scenarios, assess human onboarding, and group repeated gaps by system layer' + Assert-True -Condition ($projectAuditPrompt -match 'похожие сценарии, экраны и операции' -and $projectAuditPrompt -match 'не исправлен ли только один вариант' -and $projectAuditPrompt -match 'путь нового разработчика' -and $projectAuditPrompt -match 'Большой файл сам по себе не доказывает разрыв.*независимых причин изменения' -and $projectAuditPrompt -match 'повторяющиеся разрывы по классам') -Message 'project audit prompt must compare analogous scenarios, assess responsibilities during human onboarding, and group repeated gaps by system layer' $agentFacingText = @($agentsTemplate, $rulesetTemplate, $projectConnectPrompt, $projectAuditPrompt, $projectDeepAuditPrompt, $projectAuditWorkflow, (Get-Content -LiteralPath (Join-Path $hubRoot 'src/EffectiveIndex.psm1') -Raw -Encoding UTF8), (Get-Content -LiteralPath (Join-Path $hubRoot 'sync/catalog.json') -Raw -Encoding UTF8)) -join "`n" Assert-True -Condition ($agentFacingText -notmatch '(?i)project-owned|initializer|managed-файл|effective-набор|profiles и topics|проектный status|\brevision\b|AI-агент|AI-инструмент|\bUI\b') -Message 'agent-facing text must avoid unnecessary English words in Russian prose' $userReadme = @($rootReadme -split '(?m)^## Kit development\s*$', 2)[0] @@ -241,6 +246,7 @@ try { foreach ($profile in $catalog.profiles.PSObject.Properties) { Assert-True -Condition ('project-audit' -notin @($profile.Value.topics)) -Message "profile must not select project-audit automatically: $($profile.Name)" Assert-True -Condition ('parallel-delivery' -notin @($profile.Value.topics)) -Message "profile must not select parallel-delivery automatically: $($profile.Name)" + Assert-True -Condition ('project-bootstrap' -notin @($profile.Value.topics)) -Message "profile must not select bootstrap automatically: $($profile.Name)" } foreach ($section in @('Идентификатор', 'Цель', 'База и рабочий каталог', 'Зависимости', 'Область работы', 'Общие контракты', 'Приёмка и проверки', 'Полномочия', 'Препятствие и передача результата')) { Assert-True -Condition ($taskContract -match ('(?m)^## ' + [regex]::Escape($section) + '\s*$')) -Message "task contract must contain section: $section" @@ -271,6 +277,14 @@ try { $deepAuditPromptResult = Invoke-HubScript -ScriptPath $cliPath -Arguments @('prompt', 'deep-audit', '-ProjectRoot', $promptProjectRoot) Assert-True -Condition ($deepAuditPromptResult.ExitCode -eq 0 -and $deepAuditPromptResult.Output -match '^Подготовь и проведи глубокий аудит проекта' -and $deepAuditPromptResult.Output -match 'опорного инвентаря' -and $deepAuditPromptResult.Output.Contains($promptProjectRoot) -and $deepAuditPromptResult.Output.Contains($cliPath) -and $deepAuditPromptResult.Output -notmatch '\{\{|```') -Message 'CLI must print a project-specific deep-audit prompt with the inventory route' $studyPromptSnapshot = Get-TreeSnapshot -Root $promptProjectRoot + $bootstrapPromptResult = Invoke-HubScript -ScriptPath $cliPath -Arguments @('prompt', 'bootstrap', '-ProjectRoot', $promptProjectRoot) + Assert-True -Condition ($bootstrapPromptResult.ExitCode -eq 0 -and $bootstrapPromptResult.Output -match '^Подготовь первоначальную архитектуру проекта' -and $bootstrapPromptResult.Output.Contains($promptProjectRoot) -and $bootstrapPromptResult.Output.Contains($cliPath) -and $bootstrapPromptResult.Output.Contains((Join-Path $hubRoot 'workflows/PROJECT_BOOTSTRAP.md')) -and $bootstrapPromptResult.Output -notmatch '\{\{|```') -Message 'bootstrap prompt must resolve project and workflow paths, including spaces, without wrappers or placeholders' + Assert-True -Condition ((Get-TreeSnapshot -Root $promptProjectRoot) -eq $studyPromptSnapshot) -Message 'rendering bootstrap must not initialize the project or generate a skeleton' + $bootstrapMissingRoot = Invoke-HubScript -ScriptPath $cliPath -Arguments @('prompt', 'bootstrap') + Assert-True -Condition ($bootstrapMissingRoot.ExitCode -ne 0 -and $bootstrapMissingRoot.Output -match 'ProjectRoot') -Message 'bootstrap must require an explicit project root' + $bootstrapUnknownRoot = Join-Path $tempRoot 'missing bootstrap project' + $bootstrapUnknownRootResult = Invoke-HubScript -ScriptPath $cliPath -Arguments @('prompt', 'bootstrap', '-ProjectRoot', $bootstrapUnknownRoot) + Assert-True -Condition ($bootstrapUnknownRootResult.ExitCode -ne 0 -and -not (Test-Path -LiteralPath $bootstrapUnknownRoot)) -Message 'bootstrap must reject a missing root without creating it' $parallelPromptResult = Invoke-HubScript -ScriptPath $cliPath -Arguments @('prompt', 'parallel', '-ProjectRoot', $promptProjectRoot) Assert-True -Condition ($parallelPromptResult.ExitCode -eq 0 -and $parallelPromptResult.Output -match '^Выступи координатором задачи' -and $parallelPromptResult.Output.Contains($promptProjectRoot) -and $parallelPromptResult.Output.Contains($cliPath) -and $parallelPromptResult.Output.Contains((Join-Path $hubRoot 'templates/TASK_CONTRACT.md')) -and $parallelPromptResult.Output -notmatch '\{\{|```') -Message 'CLI must render the parallel prompt with resolved paths and no Markdown wrapper' Assert-True -Condition ($parallelPromptResult.Output -match 'parallel-delivery' -and $parallelPromptResult.Output -match 'blocked.*ready.*parallelizable.*integration-only' -and $parallelPromptResult.Output -match 'неразрешённым `-Apply`' -and $parallelPromptResult.Output -match 'одного владельца интеграции') -Message 'parallel prompt must route explicit selection, dependencies, integration ownership, and Apply boundary' @@ -541,6 +555,7 @@ try { Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $upstreamRoot 'workflows/PROJECT_STUDY.md'))) -Message 'sync must not copy project-study without an explicit selection' Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $upstreamRoot 'workflows/PROJECT_DEEP_AUDIT.md'))) -Message 'sync must not copy project-audit without an explicit selection' Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $upstreamRoot 'workflows/PARALLEL_DELIVERY.md'))) -Message 'sync must not copy parallel-delivery without an explicit selection' + Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $upstreamRoot 'workflows/PROJECT_BOOTSTRAP.md'))) -Message 'standard-product sync must not copy bootstrap without explicit selection' Assert-True -Condition (Test-Path -LiteralPath (Join-Path $upstreamRoot 'rules/RELIABILITY_AND_OPERATIONS.md')) -Message 'sync must copy explicitly selected reliability topic' Assert-True -Condition (Test-Path -LiteralPath $lockPath) -Message 'apply must create lock' Assert-True -Condition ((Get-Content -LiteralPath (Join-Path $projectRoot 'AGENTS.md') -Raw -Encoding UTF8).Trim() -eq '# Local agent rules') -Message 'apply must not overwrite local AGENTS.md' @@ -548,7 +563,7 @@ try { Assert-True -Condition ([System.IO.File]::ReadAllText($rulesetPath) -eq $rulesetBeforeSync) -Message 'apply must not overwrite nested RULESET.md' Assert-True -Condition ([System.IO.File]::ReadAllText($projectRulesPath) -eq $projectRulesBeforeSync) -Message 'apply must not overwrite nested PROJECT_RULES.md' $managedIndex = Get-Content -LiteralPath $managedIndexPath -Raw -Encoding UTF8 - Assert-True -Condition ($managedIndex -match 'показывает, какие правила читать' -and $managedIndex -match 'Подключённые темы и процессы' -and $managedIndex -match 'Вид: `core`' -and $managedIndex -match 'Вид: `profile`' -and $managedIndex -match 'Вид: `rule`' -and $managedIndex -match 'standard-product' -and $managedIndex -match 'reliability-and-operations' -and $managedIndex -notmatch 'project-study|project-audit|parallel-delivery') -Message 'effective index must contain selected routing metadata without unselected workflows' + Assert-True -Condition ($managedIndex -match 'показывает, какие правила читать' -and $managedIndex -match 'Подключённые темы и процессы' -and $managedIndex -match 'Вид: `core`' -and $managedIndex -match 'Вид: `profile`' -and $managedIndex -match 'Вид: `rule`' -and $managedIndex -match 'standard-product' -and $managedIndex -match 'reliability-and-operations' -and $managedIndex -notmatch 'project-study|project-audit|parallel-delivery|project-bootstrap') -Message 'effective index must contain selected routing metadata without unselected workflows' Assert-True -Condition ($managedIndex -notmatch "`r" -and ([System.IO.File]::ReadAllBytes($managedIndexPath)[0..2] -join ',') -ne '239,187,191') -Message 'effective index must use LF and UTF-8 without BOM' $lock = Get-Content -LiteralPath $lockPath -Raw -Encoding UTF8 | ConvertFrom-Json @@ -759,7 +774,11 @@ try { $updateProjectRoot = Join-Path $tempRoot 'update apply project' New-Item -ItemType Directory -Path $updateProjectRoot | Out-Null - $cleanInit = Invoke-HubScript -ScriptPath $cleanCliPath -Arguments @('init', '-ProjectRoot', $updateProjectRoot, '-Profiles', 'standard-product,learning-project', '-Topics', 'project-study,project-audit,parallel-delivery') + New-Item -ItemType Directory -Path (Join-Path $updateProjectRoot 'src') | Out-Null + $existingAppPath = Join-Path $updateProjectRoot 'src/App.vue' + [System.IO.File]::WriteAllText($existingAppPath, '', (New-Object System.Text.UTF8Encoding($false))) + $existingSourceSnapshot = Get-TreeSnapshot -Root (Join-Path $updateProjectRoot 'src') + $cleanInit = Invoke-HubScript -ScriptPath $cleanCliPath -Arguments @('init', '-ProjectRoot', $updateProjectRoot, '-Profiles', 'standard-product,learning-project', '-Topics', 'project-study,project-audit,parallel-delivery,project-bootstrap') Assert-True -Condition ($cleanInit.ExitCode -eq 0) -Message "clean CLI init must pass: $($cleanInit.Output)" $updateManifestPath = Join-Path $updateProjectRoot '.ai-rules/manifest.json' $renamedSourceManifest = Get-Content -LiteralPath $updateManifestPath -Raw -Encoding UTF8 | ConvertFrom-Json @@ -770,6 +789,12 @@ try { Assert-True -Condition (Test-Path -LiteralPath (Join-Path $updateProjectRoot '.ai-rules/upstream/workflows/PROJECT_STUDY.md')) -Message 'sync must copy explicitly selected project-study workflow' Assert-True -Condition (Test-Path -LiteralPath (Join-Path $updateProjectRoot '.ai-rules/upstream/workflows/PROJECT_DEEP_AUDIT.md')) -Message 'sync must copy explicitly selected project-audit workflow' Assert-True -Condition (Test-Path -LiteralPath (Join-Path $updateProjectRoot '.ai-rules/upstream/workflows/PARALLEL_DELIVERY.md')) -Message 'sync must copy explicitly selected parallel-delivery workflow' + $managedBootstrapPath = Join-Path $updateProjectRoot '.ai-rules/upstream/workflows/PROJECT_BOOTSTRAP.md' + Assert-True -Condition ((Test-Path -LiteralPath $managedBootstrapPath) -and (Get-NormalizedSha256 -Path $managedBootstrapPath) -eq (Get-NormalizedSha256 -Path (Join-Path $cleanHubRoot 'workflows/PROJECT_BOOTSTRAP.md'))) -Message 'explicit bootstrap selection must copy the exact workflow through normal synchronization' + $bootstrapIndex = Get-Content -LiteralPath (Join-Path $updateProjectRoot '.ai-rules/upstream/INDEX.md') -Raw -Encoding UTF8 + Assert-True -Condition ($bootstrapIndex -match 'project-bootstrap' -and $bootstrapIndex -match 'workflows/PROJECT_BOOTSTRAP\.md' -and $bootstrapIndex.Contains([string]$catalog.topics.'project-bootstrap'.readWhen)) -Message 'selected bootstrap must be discoverable with its conditional routing in the generated index' + Assert-True -Condition ((Get-TreeSnapshot -Root (Join-Path $updateProjectRoot 'src')) -eq $existingSourceSnapshot -and -not (Test-Path -LiteralPath (Join-Path $updateProjectRoot 'scripts'))) -Message 'init and update with bootstrap must preserve existing application code and must not generate guards or refactor it' + Assert-True -Condition ((Get-NormalizedSha256 -Path (Join-Path $updateProjectRoot 'AGENTS.md')) -eq (Get-NormalizedSha256 -Path (Join-Path $cleanHubRoot 'templates/AGENTS.md')) -and (Get-NormalizedSha256 -Path (Join-Path $updateProjectRoot '.ai-rules/PROJECT_RULES.md')) -eq (Get-NormalizedSha256 -Path (Join-Path $cleanHubRoot 'templates/PROJECT_RULES.md'))) -Message 'initial connection must seed updated local routing templates without managed copies of project architecture' Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $updateProjectRoot '.ai-rules/upstream/rules/RELIABILITY_AND_OPERATIONS.md'))) -Message 'project-study selection must not pull reliability implicitly' $updateLockPath = Join-Path $updateProjectRoot '.ai-rules/lock.json' diff --git a/workflows/PROJECT_AUDIT_PROMPT.md b/workflows/PROJECT_AUDIT_PROMPT.md index cddfd5e..9af1be2 100644 --- a/workflows/PROJECT_AUDIT_PROMPT.md +++ b/workflows/PROJECT_AUDIT_PROMPT.md @@ -25,7 +25,7 @@ 7. Для каждого значимого пункта используй один точный статус: `satisfied`, `gap`, `not applicable` или `unknown`. Подтверди вывод файлом, настройкой, командой или наблюдаемым поведением. 8. Проверь архитектурные границы, источники истины, безопасность данных и ИИ-инструментов, публичность документов, проверки проекта, правила сообщений коммитов и основной язык текста. 9. Сравни похожие сценарии, экраны и операции. Проверь, не исправлен ли только один вариант и не нужен ли общий механизм или парная проверка. -10. Оцени путь нового разработчика: точку входа, запуск, карту архитектуры, источники истины, поиск места изменения и команды проверки. Большой файл считай только сигналом. Разрыв есть, если файл смешивает несвязанные задачи или требует читать лишний контекст. +10. Оцени путь нового разработчика: точку входа, запуск, карту архитектуры, источники истины, маршрут размещения нового кода и команды проверки границ. Большой файл сам по себе не доказывает разрыв; проверь несколько независимых причин изменения. У существующего проекта отсутствие контракта или guard фиксируй без рефакторинга. Для нового развиваемого проекта укажи отдельный первоначальный выбор через `prompt bootstrap` до существенной реализации. 11. Если команда хаба доступна, выполни `doctor` и `status`. Остальные проверки запускай только тогда, когда они не меняют исходные файлы и не оставляют временные данные. В результате покажи: diff --git a/workflows/PROJECT_BOOTSTRAP.md b/workflows/PROJECT_BOOTSTRAP.md new file mode 100644 index 0000000..50f30d5 --- /dev/null +++ b/workflows/PROJECT_BOOTSTRAP.md @@ -0,0 +1,81 @@ +# Первоначальная архитектура проекта + +## Когда применять + +Применяй при создании развиваемого проекта, крупного package/application или подсистемы без установленных границ. Обычная feature-задача использует локальный контракт и не запускает процесс повторно. Для одноразового кода действуют исключения раздела «Первоначальная архитектура» темы `architecture-and-data`. + +Обязанность раннего выбора задана архитектурным правилом. Этот процесс помогает выполнить её; архетипы ниже — стартовые модели, а не дополнительный нормативный слой или обязательные имена каталогов. + +## Запуск и контекст + +В хабе выполни `prompt bootstrap -ProjectRoot <путь>` и передай запрос агенту вместе с целью и первым сценарием. Команда только печатает запрос. Можно также явно выбрать `project-bootstrap` через `-Topics` при подключении нового проекта; ни один профиль не устанавливает процесс автоматически. В подключённом проекте изменение состава проходит обычный план и разрешённый `-Apply`, без ручной правки upstream или lock. + +`prompt connect` распознаёт новый проект и предлагает этот следующий шаг, но само подключение меняет только файлы правил. У существующего проекта отсутствующие границы остаются разрывом для отдельной задачи; bootstrap не разрешает перестройку соседних модулей. + +Прочитай локальные инструкции и релевантные правила архитектуры, реализации, качества и документации. В неподключённом проекте используй их из указанного хаба; установка правил не является условием чтения. После выбора читай локальный контракт и решения затронутой области, без повторного чтения всех архетипов. + +## 1. Определить сценарии и масштаб + +Проверь Git, существующий код, настройки и команды проверки. Назови первый сквозной результат, ближайшие реальные сценарии, владельцев состояния и внешние границы. Отдели новый проект от установленной архитектуры и эксперимент с одной обязанностью от запланированного продукта. Не проектируй гипотетические функции. + +## 2. Выбрать один архетип + +| Тип | Начальная модель | Когда усложнять | +| --- | --- | --- | +| Пользовательский frontend | Композиция → локальные возможности → общий код | Модель, состояние или адаптер имеют независимый контракт либо нужны нескольким областям | +| Сервис / интеграционная система | Сценарии → contracts/model; adapters → contracts | Самостоятельная capability получает модуль; локальные уровни появляются по ответственности | +| Библиотека / CLI | Связное ядро; координация и adapters при реальных внешних границах | Второй сценарий, иной adapter или самостоятельный публичный контракт | + +### A. Пользовательский frontend + +Пример областей: `app/` для композиции, `features/` для сценариев, `shared/` для подтверждённо общего кода. Импорты: `app → features → shared`, также `app → shared`; запрещены `shared → features/app` и `features → app`. Переходы между возможностями получают явные точки входа по локальному контракту; универсальный запрет не требуется. + +Одной возможности достаточно `features/comparison/Comparison.vue`. При самостоятельных расчётах подходит `features/comparison/ui/Comparison.vue` и `features/comparison/model/comparison.ts` с локальным тестом. Не создавай заранее `api/model/ui/hooks/types/utils` в каждой возможности. + +Общий API-клиент может находиться в `shared/api/`, клиент одной возможности — рядом с ней. Общая модель, `services`, `stores` и route adapters появляются только с реальным владельцем; модель не зависит от UI и хранилища. Не выноси каждый локальный `computed` или обработчик из компонента. Корневые entrypoints делегируют самостоятельные сценарии их владельцам. + +### B. Сервис / backend + +Пример областей: `core/model`, `core/application`, `core/contracts`, `infrastructure/` и `modules//`. Core содержит общие предметные правила и сценарии, contracts/ports — внешние зависимости; infrastructure реализует конкретные HTTP, messaging и persistence adapters. Точка композиции создаёт adapters и передаёт их application через contracts. + +Импорты: `application → contracts/model`, `infrastructure → contracts/model`; core не импортирует infrastructure и presentation. Поток выполнения «сценарий вызывает adapter» не означает импорт конкретного adapter в core. Предметная модель не определяется Telegram, HTTP или БД. + +Самостоятельный модуль может иметь локальные `application/model/infrastructure/presentation`, только когда каждый нужен. Общий core не становится складом capabilities. Один обработчик без независимой модели не требует всех слоёв. + +### C. Библиотека / CLI + +Связная библиотека может остаться несколькими файлами рядом с публичной точкой входа. Для инструмента с независимыми вычислениями и вводом/выводом подходит `core/`, `application/`, `adapters/`: application использует core и необходимые контракты, adapters реализуют внешний доступ, entrypoint собирает зависимости. Core не знает CLI parsing и конкретную файловую/сетевую реализацию. Не вводи ports и пустые уровни в CLI с одной обязанностью. + +## 3. Записать локальный контракт + +До существенной реализации кратко запиши тип, первые сценарии, один архетип, области и владельцев, разрешённые зависимости и точки входа, запрещённые связи, точку композиции и отсутствующие слои. Укажи причину выбора и условие пересмотра по действующему правилу документации. + +Контракт позволяет найти место для UI и логики одной возможности, внешнего доступа, общего кода, новой возможности и композиции. Достаточно нескольких абзацев в `PROJECT_RULES` или существующей карте; отдельный документ по шаблону нужен только при самостоятельной роли. Не дублируй контракт в двух документах. + +## 4. Создать минимальный skeleton и guard + +Создавай каталоги вместе с кодом ответственности первого сценария. Будущие области пока могут оставаться записью в контракте. Не добавляй пустые папки, framework scaffolder или собственный движок анализа зависимостей. + +Выбери важнейшие устойчивые ограничения: например, запрет `shared → features/app`, `core → infrastructure/presentation` или allowlist корневых entrypoints. Используй существующий линтер либо небольшой script/structural test. Проверь разрешённый импорт и представительное нарушение на изолированной фикстуре; учитывай реальные способы импортов и возвращай ненулевой exit code с понятным сообщением при нарушении. Субъективную связность файла не заменяй числовым лимитом. + +Добавь команду в обычные проверки, CI — если это входит в задачу. Успешная проверка пустого дерева не доказывает защиту. При недоступном механизме назови ограничение и незавершённую часть bootstrap. + +## 5. Реализовать и проверить первый сквозной сценарий + +Проведи результат через выбранных владельцев, проверь основной путь и значимый отказ по риску. Запусти guard на реальном skeleton. Убедись, что у нового кода есть понятное место, композиция делегирует независимое поведение, нет пустых слоёв, разрешённый и запрещённый случаи проверены. Отделяй результат от commit, push и публикации. + +## 6. Пересматривать по причинам изменения + +Пересмотри стартовую гипотезу при новой capability, реальном повторном использовании, новом adapter, усложнении жизненного цикла состояния или повторяющемся дрейфе. Выделяй одну границу за раз с сохранением поведения, переносом потребителей и обновлением guard и контракта. Удаляй ненужный слой с проверкой импортов и публичных потребителей; шаблон не оправдывает его сохранение. Основания пересмотра и удаления средств организации ведутся по действующему правилу документации. + +## Готовый запрос + +```text +Подготовь первоначальную архитектуру проекта в "{{PROJECT_ROOT}}" и реализуй первый сквозной сценарий из моей задачи. + +Прочитай процесс "{{BOOTSTRAP_WORKFLOW_PATH}}" и релевантные правила из хаба рядом с "{{HUB_CLI_PATH}}", затем локальные инструкции проекта. Проверь Git и сохрани несвязанные изменения. Если цель или первый сценарий не указаны, собери доступный контекст и уточни недостающее до зависимой реализации. + +Выбери один минимальный архетип, запиши локальный контракт размещения кода и зависимостей, создай только необходимые части, добавь и проверь архитектурный guard, затем проверь первый сквозной результат. Для существующей области используй установленную архитектуру; не выполняй автоматический рефакторинг. Обычное подключение Kit не входит в реализацию и не расширяет её границы. Не выполняй неразрешённый -Apply, commit, push или публикацию. + +Покажи выбранные границы, отсутствующие слои, точные команды и результаты проверок, непроверенное и условия пересмотра. Не объявляй механическую защиту подтверждённой без разрешённого и запрещённого примеров. +``` diff --git a/workflows/PROJECT_CONNECT_PROMPT.md b/workflows/PROJECT_CONNECT_PROMPT.md index 08a3f15..2a8bc93 100644 --- a/workflows/PROJECT_CONNECT_PROMPT.md +++ b/workflows/PROJECT_CONNECT_PROMPT.md @@ -9,11 +9,12 @@ Действуй по шагам: 1. Проверь `git status`, локальные инструкции, основные точки входа, настройки и команды проверки. Сохрани несвязанные изменения владельца. -2. Выбери минимальный набор профилей и тем. Объясни выбор простыми словами и назови точные идентификаторы для `-Profiles` и `-Topics`. Не добавляй правило только потому, что оно есть в хабе. +2. Выбери минимальный набор профилей и тем. Объясни выбор простыми словами и назови точные идентификаторы для `-Profiles` и `-Topics`. Не добавляй правило только потому, что оно есть в хабе. Для нового развиваемого проекта без архитектурного контракта предложи явно выбрать `architecture-and-data` и `project-bootstrap` (тему архитектуры не дублируй, если она входит в профиль). Для существующего проекта отсутствие контракта зафиксируй как разрыв, без автоматического добавления bootstrap. 3. Если `.ai-rules/manifest.json` отсутствует, выполни `connect -ProjectRoot "{{PROJECT_ROOT}}"` с выбранными `-Profiles` и `-Topics`. Если проект уже подключён, выполни эту команду без изменения состава правил. 4. Покажи созданные локальные файлы, предложенную версию хаба и файлы правил, которые будут добавлены или изменены. Отдельно скажи, что останется нетронутым. 5. Остановись перед `-Apply` и запроси одно явное разрешение на применение показанных изменений. 6. После разрешения повтори ту же команду с `-Apply`. Проверь результат командами `doctor` и `status`, затем покажи `git diff` проекта. +7. Для нового проекта укажи следующий отдельный шаг: `{{HUB_CLI_PATH}} prompt bootstrap -ProjectRoot "{{PROJECT_ROOT}}"` вместе с целью и первым сценарием. Подключение не создаёт skeleton, guard и не реализует продукт. Последующая разработка начинает с первоначального выбора по архитектурному правилу даже без установленного процесса. Не выходи за эти границы: - не редактируй `.ai-rules/upstream/` вручную;