diff --git a/README.md b/README.md index b47e83d..e0e3654 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,14 @@ To learn how a project works through code walkthroughs and practical checks: Study sessions track explored areas and demonstrated understanding separately. Significant decisions are maintained as a regular project practice, with a map linking to their rationale and implementation evidence. +For a large task with independent parts, generate a prompt for Codex: + +```powershell +.\ai-rules.ps1 prompt parallel -ProjectRoot C:\path\to\project +``` + +Paste the prompt and your task into Codex. It will assess whether parallel work helps, give each writer a bounded task and separate workspace, and assign one owner to integrate and verify the result. Ordinary tasks continue as before. + ## Update rules Preview the available changes: diff --git a/ai-rules.ps1 b/ai-rules.ps1 index 106c473..7bbf52a 100644 --- a/ai-rules.ps1 +++ b/ai-rules.ps1 @@ -63,6 +63,8 @@ Agent Engineering Kit Подготовить запрос для глубокого аудита. prompt study -ProjectRoot ПУТЬ Подготовить запрос для изучения проекта. + prompt parallel -ProjectRoot ПУТЬ + Подготовить запрос для параллельной задачи. connect -ProjectRoot ПУТЬ Подготовить проект и показать изменения. connect -ProjectRoot ПУТЬ -Apply @@ -729,12 +731,12 @@ try { } } 'prompt' { - if ([string]::IsNullOrWhiteSpace($ListTarget) -or $ListTarget.ToLowerInvariant() -notin @('audit', 'connect', 'deep-audit', 'study')) { - throw "Для команды 'prompt' укажите 'connect', 'audit', 'deep-audit' или 'study'." + if ([string]::IsNullOrWhiteSpace($ListTarget) -or $ListTarget.ToLowerInvariant() -notin @('audit', 'connect', 'deep-audit', 'study', 'parallel')) { + throw "Для команды 'prompt' укажите 'connect', 'audit', 'deep-audit', 'study' или 'parallel'." } $promptName = $ListTarget.ToLowerInvariant() $promptArguments = @('-Name', $promptName) - if ($promptName -in @('connect', 'deep-audit', 'study')) { + if ($promptName -in @('connect', 'deep-audit', 'study', 'parallel')) { $resolvedProjectRoot = Resolve-ProjectRoot -Path $ProjectRoot $promptArguments += @('-ProjectRoot', $resolvedProjectRoot) } diff --git a/hub/ARCHITECTURE.md b/hub/ARCHITECTURE.md index 3a82715..e4206fe 100644 --- a/hub/ARCHITECTURE.md +++ b/hub/ARCHITECTURE.md @@ -28,7 +28,7 @@ AGENTS.md целевого проекта Подробные нормы для продукта, архитектуры и данных, реализации, качества, эксплуатации, безопасности, документации, Git, совместной работы с AI и исследований. Каталог включает их в итоговый набор, но агент читает только темы текущей задачи. -Рабочие процессы конкретных задач находятся в `workflows/` и не считаются постоянными нормативными правилами. Идентификатор `project-study` пока сохраняется для совместимости `.ai-rules/manifest.json`, но создаёт `workflows/PROJECT_STUDY.md`. Идентификатор `project-audit` подключает `workflows/PROJECT_DEEP_AUDIT.md` для отдельной задачи глубокого аудита. Ни один из этих процессов не входит в профиль и не подключается автоматически. +Рабочие процессы конкретных задач находятся в `workflows/` и не считаются постоянными нормативными правилами. Идентификатор `project-study` пока сохраняется для совместимости `.ai-rules/manifest.json`, но создаёт `workflows/PROJECT_STUDY.md`. Идентификатор `project-audit` подключает `workflows/PROJECT_DEEP_AUDIT.md` для отдельной задачи глубокого аудита. Идентификатор `parallel-delivery` подключает `workflows/PARALLEL_DELIVERY.md` для явно выбранной параллельной задачи; `prompt parallel` только печатает стартовый запрос и не меняет проект. Ни один из этих процессов не входит в профиль и не подключается автоматически. ### `profiles/` @@ -86,6 +86,8 @@ hub checkout + project manifest `AGENTS.md` остаётся канонической точкой входа проекта. В самом хабе проверяется один пилот для Claude Code: корневой `CLAUDE.md` содержит только импорт `@AGENTS.md`. Этот файл не входит в каталог, шаблоны подключения или управляемую копию и не означает массовое добавление таких файлов. +Для параллельной работы Codex первая версия использует ту же точку входа, явно выбранный `parallel-delivery` и сгенерированный `prompt parallel`. Шаблон `templates/TASK_CONTRACT.md` читается из локального хаба по пути в запросе и не копируется синхронизацией; подключённый процесс перечисляет обязательные поля и остаётся понятным без доступного хаба. Отдельный Codex Skill нужен только после наблюдения повторяющейся ручной механики, которую этот маршрут не устраняет. Штатный Agent Command Center координирует агентов, когда доступен; хаб не запускает их процессы и не ведёт собственное состояние задач. + ### `hub/` Продуктовые и архитектурные правила самого Agent Engineering Kit и решения о структуре. diff --git a/rules/AI_COLLABORATION.md b/rules/AI_COLLABORATION.md index d2a1e74..385b4f5 100644 --- a/rules/AI_COLLABORATION.md +++ b/rules/AI_COLLABORATION.md @@ -32,7 +32,15 @@ ## Параллельная работа -До параллельной работы зафиксируй владельца подзадачи, границы файлов или контракта и способ интеграции. Несколько исполнителей не меняют один контракт без координации. Один владелец отвечает за итоговую интеграцию, разрешение пересечений и общий прогон проверок. +Сначала определи общий результат и зависимости подзадач. Запускай одновременно только задачи с независимым проверяемым результатом, чьи зависимости уже выполнены и области записи не конфликтуют. Наличие свободных агентов само по себе не причина для параллельности. + +До запуска зафиксируй для каждой подзадачи владельца, область записи, зависимости и затрагиваемые общие контракты, а для всей работы — одного владельца интеграции. Общий контракт — интерфейс между подзадачами, например публичный API, тип или схема, миграция, маршрут, сетевое событие, корневая конфигурация или файл блокировки зависимостей. У каждого изменяемого общего контракта один владелец; несколько исполнителей не меняют его независимо. + +Каждый агент, изменяющий отслеживаемые файлы, получает одну конкретную задачу и один назначенный изолированный рабочий каталог. Он не использует каталог другого пишущего агента. Если используется Git, задача также получает одну назначенную ветку от известной базы; рекомендуемый способ изоляции нескольких пишущих агентов — отдельные Git worktree. Эквивалентная изоляция допустима в среде без worktree. + +Исполнители передают результаты и запросы на изменение общего контракта координатору или владельцу интеграции, а не согласовывают пересекающиеся правки друг с другом. Если нужное изменение выходит за область записи или затрагивает чужой контракт, исполнитель останавливает эту часть работы, описывает причину и затронутый контракт и ждёт нового решения. Остальную независимую работу можно продолжить. + +Один владелец интеграции объединяет результаты, разрешает пересечения, проверяет взаимодействие частей и выполняет общий набор проверок. Локальная проверка исполнителя не доказывает готовность интегрированного результата. Для ограниченного процесса используй явно выбранный рабочий процесс, если он подключён к проекту; эти инварианты действуют и без него. ## Улучшение системы после ошибок diff --git a/rules/GIT_AND_DELIVERY.md b/rules/GIT_AND_DELIVERY.md index 056de9a..0ca20a9 100644 --- a/rules/GIT_AND_DELIVERY.md +++ b/rules/GIT_AND_DELIVERY.md @@ -16,6 +16,13 @@ - Не веди обычную разработку прямо в ветке, которая объединяет работу или переключает постоянный staging/production. Исключение допустимо для явно принятого проектом процесса `direct-to-trunk`, локального репозитория без такой границы либо согласованного аварийного изменения; причина и эквивалентная проверка до переключения фиксируются явно. - Если задача началась не в той ветке, не продолжай по инерции: остановись до следующей записи или внешнего действия, сохрани чужую работу и перенеси только относящийся к задаче diff безопасным способом. +## Параллельные пишущие задачи в Git + +- Для каждой пишущей задачи зафиксируй базовую ветку и точный базовый commit до создания ветки задачи. Назначь ей одну ветку и один рабочий каталог; отдельный `git worktree` — рекомендуемый способ изоляции параллельных исполнителей. Другой пишущий исполнитель не использует этот каталог. +- Исполнитель не переключает ветку внутри назначенного worktree произвольно. Изменение базы или ветки координируется с владельцем интеграции и не переносит чужие незавершённые изменения. +- Владелец интеграции отвечает за `merge`, `rebase` или `cherry-pick` результатов в интеграционную ветку и за проверку итогового состояния. Исполнитель не интегрирует свою работу без выданных полномочий. Добавление в индекс, коммит, отправка, запрос на слияние и внешняя поставка сохраняют границы разрешения из раздела «Локальная история». +- Удаляй рабочий каталог или worktree только с разрешения владельца после проверки, что нужный результат сохранён, доступен владельцу интеграции и больше не требуется для проверок. Нельзя терять незакоммиченные или ещё не интегрированные изменения при очистке. + ## Сообщения коммитов и автоматическая проверка - Проект явно фиксирует формат сообщений коммитов и способ его проверки. Соблюдай локальный контракт; если его нет, предложи Conventional Commits как совместимый вариант, но не объявляй его универсальным требованием без решения владельца. diff --git a/rules/README.md b/rules/README.md index 8de02ee..d50ad24 100644 --- a/rules/README.md +++ b/rules/README.md @@ -18,7 +18,7 @@ | [`GIT_AND_DELIVERY.md`](GIT_AND_DELIVERY.md) | ветки, коммиты, CI/CD, релиз или внешняя операция | | [`AI_COLLABORATION.md`](AI_COLLABORATION.md) | распределение работы между человеком и AI, менторский режим | | [`RESEARCH_AND_EVIDENCE.md`](RESEARCH_AND_EVIDENCE.md) | неизвестный API, исследование, эксперимент, аудит или доказательная рекомендация | -Тематическое правило задаёт нормы для класса задач. Рабочие процессы конкретных задач находятся в [`../workflows/`](../workflows/) и не становятся постоянными нормативными правилами. Для совместимости manifest идентификатор `project-study` пока выбирает `workflows/PROJECT_STUDY.md`; отдельный идентификатор `project-audit` выбирает `workflows/PROJECT_DEEP_AUDIT.md`. Профили не подключают эти процессы автоматически. +Тематическое правило задаёт нормы для класса задач. Рабочие процессы конкретных задач находятся в [`../workflows/`](../workflows/) и не становятся постоянными нормативными правилами. Для совместимости manifest идентификатор `project-study` пока выбирает `workflows/PROJECT_STUDY.md`; `project-audit` выбирает `workflows/PROJECT_DEEP_AUDIT.md`, а `parallel-delivery` — `workflows/PARALLEL_DELIVERY.md`. Профили не подключают эти процессы автоматически. ## Приоритет правил diff --git a/scripts/check-hub.ps1 b/scripts/check-hub.ps1 index 8a8a490..8f22dc9 100644 --- a/scripts/check-hub.ps1 +++ b/scripts/check-hub.ps1 @@ -34,7 +34,10 @@ $requiredPaths = @( 'workflows/PROJECT_DEEP_AUDIT_PROMPT.md', 'workflows/PROJECT_STUDY.md', 'workflows/PROJECT_STUDY_PROMPT.md', + 'workflows/PARALLEL_DELIVERY.md', + 'workflows/PARALLEL_DELIVERY_PROMPT.md', 'templates/DECISIONS.md', + 'templates/TASK_CONTRACT.md', 'workflows/PROJECT_DEEP_AUDIT.md', 'evals/README.md', 'evals/controls.json', diff --git a/scripts/show-prompt.ps1 b/scripts/show-prompt.ps1 index 94ae260..88cc427 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')] + [ValidateSet('audit', 'connect', 'deep-audit', 'study', 'parallel')] [string]$Name, [string]$ProjectRoot @@ -32,6 +32,12 @@ switch ($Name) { } $promptPath = Join-Path $hubRoot 'workflows/PROJECT_STUDY_PROMPT.md' } + 'parallel' { + if ([string]::IsNullOrWhiteSpace($ProjectRoot)) { + throw 'ProjectRoot is required for prompt parallel.' + } + $promptPath = Join-Path $hubRoot 'workflows/PARALLEL_DELIVERY_PROMPT.md' + } } $promptDocument = Get-Content -LiteralPath $promptPath -Raw -Encoding UTF8 @@ -41,10 +47,14 @@ if (-not $promptMatch.Success) { } $prompt = $promptMatch.Groups['prompt'].Value.Trim() -if ($Name -in @('connect', 'deep-audit', 'study')) { +if ($Name -in @('connect', 'deep-audit', 'study', 'parallel')) { $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 'parallel') { + $taskContractPath = Join-Path $hubRoot 'templates/TASK_CONTRACT.md' + $prompt = $prompt.Replace('{{TASK_CONTRACT_PATH}}', $taskContractPath) + } } Write-Output $prompt diff --git a/sync/catalog.json b/sync/catalog.json index 6c64834..af87ad2 100644 --- a/sync/catalog.json +++ b/sync/catalog.json @@ -80,6 +80,12 @@ "kind": "workflow", "description": "Рабочий процесс глубокого аудита проекта с явным пространством проверки и покрытием.", "readWhen": "Только при явном выборе project-audit и задаче на глубокий системный аудит проекта." + }, + "parallel-delivery": { + "file": "workflows/PARALLEL_DELIVERY.md", + "kind": "workflow", + "description": "Рабочий процесс параллельной доставки независимых подзадач с одним владельцем интеграции.", + "readWhen": "Только при явном выборе parallel-delivery и большой задаче с независимыми частями." } }, "profiles": { diff --git a/sync/project-manifest.schema.json b/sync/project-manifest.schema.json index 0269050..68ea798 100644 --- a/sync/project-manifest.schema.json +++ b/sync/project-manifest.schema.json @@ -42,7 +42,8 @@ "ai-collaboration", "research-and-evidence", "project-study", - "project-audit" + "project-audit", + "parallel-delivery" ] } }, diff --git a/templates/README.md b/templates/README.md index 5ac208e..3a5e73f 100644 --- a/templates/README.md +++ b/templates/README.md @@ -20,6 +20,7 @@ - [`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 <путь>`. +- [`PARALLEL_DELIVERY_PROMPT.md`](../workflows/PARALLEL_DELIVERY_PROMPT.md) — оценка и запуск параллельной задачи через `ai-rules.ps1 prompt parallel -ProjectRoot <путь>`. После подключения общие правила находятся в `.ai-rules/upstream/`. Локальные `RULESET.md` и `PROJECT_RULES.md` остаются под управлением проекта. @@ -35,6 +36,7 @@ - [`RESEARCH.md`](RESEARCH.md) — проверяемое исследование; - [`PROJECT_KNOWLEDGE.md`](PROJECT_KNOWLEDGE.md) — устойчивые знания о проекте; - [`SESSION_CONTEXT.md`](SESSION_CONTEXT.md) — временная передача контекста. +- [`TASK_CONTRACT.md`](TASK_CONTRACT.md) — границы и приёмка одной параллельной подзадачи. Не создавайте документ только потому, что существует шаблон. Сначала определите читателя, задачу документа и место хранения. diff --git a/templates/SESSION_CONTEXT.md b/templates/SESSION_CONTEXT.md index 447b6c2..ddddbf3 100644 --- a/templates/SESSION_CONTEXT.md +++ b/templates/SESSION_CONTEXT.md @@ -6,6 +6,14 @@ - `<...>` +## Привязка подзадачи + +- Task ID: `<...>`; базовая ревизия: ``. +- Текущая ветка: `<...>`; назначенный workspace/worktree: `<...>`. +- Контракт подзадачи: `<ссылка и версия>`; последний проверенный commit/revision: ``. + +Не копируй сюда весь контракт подзадачи. + ## Что уже изменено - `<файл, поведение, проверка>` diff --git a/templates/TASK_CONTRACT.md b/templates/TASK_CONTRACT.md new file mode 100644 index 0000000..6d580c9 --- /dev/null +++ b/templates/TASK_CONTRACT.md @@ -0,0 +1,45 @@ +# Контракт подзадачи + +Заполняй только применимые поля. Контракт задаёт границы одной подзадачи; он не расширяет разрешения владельца на исходную задачу. + +## Идентификатор + +- Задача: ``; родительская задача: ``; владелец и роль: `<...>`. + +## Цель + +- Наблюдаемый результат: `<один результат>`. + +## База и рабочий каталог + +- Базовая ветка: `<...>`; базовый commit SHA: `<...>`. +- Назначенная ветка: `<...>`; workspace/worktree: `<...>`. + +## Зависимости + +- Предшествующие задачи: ``; уже утверждённые контракты: `<ссылка или нет>`. + +## Область работы + +- Можно изменять: `<точные файлы, каталоги или контракт>`. +- Можно читать как зависимость, но не изменять: `<...>`. + +## Общие контракты + +- `<название>` — источник истины: `<путь/версия>`; владелец: ``; изменение: `<разрешено/запрещено>`. + +## Приёмка и проверки + +- Наблюдаемые критерии: `<...>`. +- Обязательные команды или проверки: `<...>`. + +## Полномочия + +- Создать ветку: `<да/нет>`; изменить файлы: `<да/нет>`; добавить в индекс: `<да/нет>`; коммит: `<да/нет>`. +- Отправить изменения: `<да/нет>`; интегрировать: `<да/нет>`; создать запрос на слияние: `<да/нет>`; внешние действия: `<точно перечислить или нет>`. +- Неуказанное действие не разрешено. Контракт не может выдать полномочия шире исходного запроса владельца. + +## Препятствие и передача результата + +- При выходе за область записи или необходимости изменить чужой контракт останови затронутую часть, укажи требуемое изменение, причину, задачу и контракт и передай запрос координатору. +- Передача: `<результат; изменённые области; проверки и вывод; отклонения; препятствия; последний проверенный commit/revision; оставшиеся риски; действие владельца интеграции>`. diff --git a/tests/cli/test-integration.ps1 b/tests/cli/test-integration.ps1 index a4b8800..aa81569 100644 --- a/tests/cli/test-integration.ps1 +++ b/tests/cli/test-integration.ps1 @@ -92,6 +92,10 @@ try { $productRule = Get-Content -LiteralPath (Join-Path $hubRoot 'rules/PRODUCT.md') -Raw -Encoding UTF8 $projectStudyRule = Get-Content -LiteralPath (Join-Path $hubRoot 'workflows/PROJECT_STUDY.md') -Raw -Encoding UTF8 $projectAuditWorkflow = Get-Content -LiteralPath (Join-Path $hubRoot 'workflows/PROJECT_DEEP_AUDIT.md') -Raw -Encoding UTF8 + $parallelWorkflow = Get-Content -LiteralPath (Join-Path $hubRoot 'workflows/PARALLEL_DELIVERY.md') -Raw -Encoding UTF8 + $parallelPrompt = Get-Content -LiteralPath (Join-Path $hubRoot 'workflows/PARALLEL_DELIVERY_PROMPT.md') -Raw -Encoding UTF8 + $taskContract = Get-Content -LiteralPath (Join-Path $hubRoot 'templates/TASK_CONTRACT.md') -Raw -Encoding UTF8 + $sessionContext = Get-Content -LiteralPath (Join-Path $hubRoot 'templates/SESSION_CONTEXT.md') -Raw -Encoding UTF8 $reliabilityRule = Get-Content -LiteralPath (Join-Path $hubRoot 'rules/RELIABILITY_AND_OPERATIONS.md') -Raw -Encoding UTF8 $rulesReadme = Get-Content -LiteralPath (Join-Path $hubRoot 'rules/README.md') -Raw -Encoding UTF8 $agentsTemplate = Get-Content -LiteralPath (Join-Path $hubRoot 'templates/AGENTS.md') -Raw -Encoding UTF8 @@ -234,9 +238,17 @@ try { Assert-True -Condition ($projectAuditWorkflow -match 'checked-no-finding' -and $projectAuditWorkflow -match 'finding' -and $projectAuditWorkflow -match 'not-applicable' -and $projectAuditWorkflow -match 'unknown' -and $projectAuditWorkflow -match 'not-checked' -and $projectAuditWorkflow -match 'не считаются успешной проверкой') -Message 'project-audit must use an explicit coverage vocabulary without treating unknown scope as success' Assert-True -Condition ($projectAuditWorkflow -match 'каждый элемент опорного инвентаря связан с картой' -and $projectAuditWorkflow -match 'После каждого подаудита обновляй карту, очередь и реестр покрытия' -and $projectAuditWorkflow -match 'попытайся опровергнуть каждую критическую или высокорисковую находку' -and $projectAuditWorkflow -match 'не читай репозиторий подряд') -Message 'project-audit must reconcile its inventory, expand adaptively, challenge serious findings, and preserve relevant context loading' Assert-True -Condition ($catalog.topics.'project-audit'.file -eq 'workflows/PROJECT_DEEP_AUDIT.md' -and $catalog.topics.'project-audit'.kind -eq 'workflow') -Message 'project-audit catalog ID must route to the deep-audit workflow' + Assert-True -Condition ($catalog.topics.'parallel-delivery'.file -eq 'workflows/PARALLEL_DELIVERY.md' -and $catalog.topics.'parallel-delivery'.kind -eq 'workflow') -Message 'parallel-delivery must be an explicit catalog workflow' 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)" } + foreach ($section in @('Идентификатор', 'Цель', 'База и рабочий каталог', 'Зависимости', 'Область работы', 'Общие контракты', 'Приёмка и проверки', 'Полномочия', 'Препятствие и передача результата')) { + Assert-True -Condition ($taskContract -match ('(?m)^## ' + [regex]::Escape($section) + '\s*$')) -Message "task contract must contain section: $section" + } + Assert-True -Condition ($taskContract -match 'базовый commit SHA' -and $taskContract -match 'Неуказанное действие не разрешено' -and $taskContract -match 'последний проверенный commit/revision' -and $taskContract.Length -lt 3500) -Message 'task contract must stay bounded and carry base, authority, and handoff evidence' + Assert-True -Condition ($sessionContext -match 'Task ID' -and $sessionContext -match 'базовая ревизия' -and $sessionContext -match 'workspace/worktree' -and $sessionContext -match 'последний проверенный commit/revision' -and $sessionContext -match 'Не копируй сюда весь контракт') -Message 'session context must carry worker recovery pointers without duplicating its contract' + Assert-True -Condition ($parallelWorkflow -match '`blocked`' -and $parallelWorkflow -match '`parallelizable`' -and $parallelWorkflow -match 'общий набор проверок' -and $parallelWorkflow -match 'базовая ветка ушла вперёд' -and $parallelWorkflow -match 'локальные проверки исполнителей') -Message 'parallel workflow must cover dependencies, integration gate, and failure handling' foreach ($reliabilityHeading in @('Работоспособность', 'Деградация', 'Наблюдаемость', 'Жизнеспособность и готовность', 'Восстановление и инциденты', 'Производительность и предельная нагрузка', 'Область применения')) { Assert-True -Condition ($reliabilityRule -match ('(?m)^## ' + [regex]::Escape($reliabilityHeading) + '\s*$')) -Message "reliability topic must retain section: $reliabilityHeading" } @@ -260,6 +272,11 @@ 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 + $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' + $parallelMissingRootResult = Invoke-HubScript -ScriptPath $cliPath -Arguments @('prompt', 'parallel') + Assert-True -Condition ($parallelMissingRootResult.ExitCode -ne 0 -and $parallelMissingRootResult.Output -match 'ProjectRoot') -Message 'parallel prompt must require an explicit project root' $studyPromptResult = Invoke-HubScript -ScriptPath $cliPath -Arguments @('prompt', 'study', '-ProjectRoot', $promptProjectRoot) Assert-True -Condition ($studyPromptResult.ExitCode -eq 0 -and $studyPromptResult.Output -match '^Помоги мне самостоятельно разобраться в проекте' -and $studyPromptResult.Output.Contains($promptProjectRoot) -and $studyPromptResult.Output.Contains($cliPath) -and $studyPromptResult.Output -notmatch '\{\{|```') -Message 'CLI must render the study prompt with space-containing paths and no unresolved placeholders' Assert-True -Condition ($studyPromptResult.Output -match 'project-study' -and $studyPromptResult.Output -match 'неразрешённым `-Apply`' -and $studyPromptResult.Output -match 'Дождись моего ответа' -and $studyPromptResult.Output -match 'без изменения файлов') -Message 'study prompt must separate authorized setup, read-only study, and observed owner understanding' @@ -407,6 +424,7 @@ try { Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $cliProjectRoot '.ai-rules/upstream/rules/RELIABILITY_AND_OPERATIONS.md'))) -Message 'standard-product must not pull reliability without an explicit topic' Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $cliProjectRoot '.ai-rules/upstream/workflows/PROJECT_STUDY.md'))) -Message 'standard-product must not pull project-study without an explicit topic' Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $cliProjectRoot '.ai-rules/upstream/workflows/PROJECT_DEEP_AUDIT.md'))) -Message 'standard-product must not pull project-audit without an explicit topic' + Assert-True -Condition (-not (Test-Path -LiteralPath (Join-Path $cliProjectRoot '.ai-rules/upstream/workflows/PARALLEL_DELIVERY.md'))) -Message 'standard-product must not pull parallel-delivery without an explicit topic' $cliManifestPath = Join-Path $cliProjectRoot '.ai-rules/manifest.json' $cliManifest = Get-Content -LiteralPath $cliManifestPath -Raw -Encoding UTF8 | ConvertFrom-Json $currentHubRevision = $applyHubRevision @@ -523,6 +541,7 @@ try { Assert-True -Condition (Test-Path -LiteralPath (Join-Path $upstreamRoot 'rules/DOCUMENTATION.md')) -Message 'standard-product must pull documentation architecture rule' 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 (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' @@ -530,7 +549,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') -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') -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 @@ -741,7 +760,7 @@ 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') + $cleanInit = Invoke-HubScript -ScriptPath $cleanCliPath -Arguments @('init', '-ProjectRoot', $updateProjectRoot, '-Profiles', 'standard-product,learning-project', '-Topics', 'project-study,project-audit,parallel-delivery') 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 @@ -751,6 +770,7 @@ try { Assert-True -Condition ($cleanInitialApply.ExitCode -eq 0) -Message "first update -Apply must pin and synchronize the project: $($cleanInitialApply.Output)" 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' 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' @@ -761,7 +781,7 @@ try { Assert-True -Condition ($initialUpdateLockText -match '(?m)^ "source": \{$' -and $initialUpdateLockText -match '(?m)^ "profiles": \["learning-project", "standard-product"\],$' -and $initialUpdateLockText -notmatch "`r" -and $initialUpdateLockText -notmatch '(?m)^\s+"[^"]+":[ \t]{2,}') -Message 'sync must write stable compact LF JSON formatting' $updateRulesetPath = Join-Path $updateProjectRoot '.ai-rules/RULESET.md' $initialRuleset = Get-Content -LiteralPath $updateRulesetPath -Raw -Encoding UTF8 - Assert-True -Condition ($initialRuleset -match '- `standard-product`.*<почему выбран>' -and $initialRuleset -match '- `learning-project`.*<почему выбран>' -and $initialRuleset -match '- `project-study`.*<почему подключена отдельно>' -and $initialRuleset -match '- `project-audit`.*<почему подключена отдельно>') -Message 'RULESET must seed selected profile and direct topic IDs in backticks' + Assert-True -Condition ($initialRuleset -match '- `standard-product`.*<почему выбран>' -and $initialRuleset -match '- `learning-project`.*<почему выбран>' -and $initialRuleset -match '- `project-study`.*<почему подключена отдельно>' -and $initialRuleset -match '- `project-audit`.*<почему подключена отдельно>' -and $initialRuleset -match '- `parallel-delivery`.*<почему подключена отдельно>') -Message 'RULESET must seed selected profile and direct topic IDs in backticks' Assert-True -Condition (([regex]::Matches($initialRuleset, '(?m)^Нет\.$')).Count -eq 2) -Message 'RULESET must use explicit empty values for optional sections' $connectedDoctorSnapshot = Get-TreeSnapshot -Root $updateProjectRoot $connectedDoctor = Invoke-HubScript -ScriptPath $cleanCliPath -Arguments @('doctor', '-ProjectRoot', $updateProjectRoot) diff --git a/tests/policy-structure/test-portable-boundaries.ps1 b/tests/policy-structure/test-portable-boundaries.ps1 index 759bb9d..9915a9f 100644 --- a/tests/policy-structure/test-portable-boundaries.ps1 +++ b/tests/policy-structure/test-portable-boundaries.ps1 @@ -11,7 +11,7 @@ $quality = Get-Content -LiteralPath (Join-Path $hubRoot 'rules/QUALITY.md') -Raw $learningProfile = Get-Content -LiteralPath (Join-Path $hubRoot 'profiles/learning-project.md') -Raw -Encoding UTF8 $readme = Get-Content -LiteralPath (Join-Path $hubRoot 'README.md') -Raw -Encoding UTF8 -$workflowPaths = @('workflows/PROJECT_CONNECT_PROMPT.md', 'workflows/PROJECT_AUDIT_PROMPT.md', 'workflows/PROJECT_DEEP_AUDIT_PROMPT.md', 'workflows/PROJECT_STUDY_PROMPT.md', 'workflows/PROJECT_STUDY.md', 'workflows/PROJECT_DEEP_AUDIT.md') +$workflowPaths = @('workflows/PROJECT_CONNECT_PROMPT.md', 'workflows/PROJECT_AUDIT_PROMPT.md', 'workflows/PROJECT_DEEP_AUDIT_PROMPT.md', 'workflows/PROJECT_STUDY_PROMPT.md', 'workflows/PROJECT_STUDY.md', 'workflows/PROJECT_DEEP_AUDIT.md', 'workflows/PARALLEL_DELIVERY.md', 'workflows/PARALLEL_DELIVERY_PROMPT.md') foreach ($workflowPath in $workflowPaths) { if (-not (Test-Path -LiteralPath (Join-Path $hubRoot $workflowPath) -PathType Leaf)) { throw "Workflow is missing: $workflowPath" } } @@ -19,9 +19,11 @@ if (Test-Path -LiteralPath (Join-Path $hubRoot 'rules/PROJECT_STUDY.md')) { thro if (Test-Path -LiteralPath (Join-Path $hubRoot 'templates/PROJECT_CONNECT_PROMPT.md')) { throw 'Connection workflow must not remain a project template.' } if ([string]$catalog.topics.'project-study'.file -ne 'workflows/PROJECT_STUDY.md') { throw 'Compatible project-study ID must route to the workflow.' } if ([string]$catalog.topics.'project-audit'.file -ne 'workflows/PROJECT_DEEP_AUDIT.md') { throw 'Project-audit ID must route to the deep-audit workflow.' } +if ([string]$catalog.topics.'parallel-delivery'.file -ne 'workflows/PARALLEL_DELIVERY.md' -or [string]$catalog.topics.'parallel-delivery'.kind -ne 'workflow') { throw 'Parallel-delivery ID must route to the task workflow.' } foreach ($profile in $catalog.profiles.PSObject.Properties) { if ('project-study' -in @($profile.Value.topics)) { throw "Profile must not select project-study automatically: $($profile.Name)" } if ('project-audit' -in @($profile.Value.topics)) { throw "Profile must not select project-audit automatically: $($profile.Name)" } + if ('parallel-delivery' -in @($profile.Value.topics)) { throw "Profile must not select parallel-delivery automatically: $($profile.Name)" } } if ($implementation -match 'оформляются явными блоками' -or $implementation -notmatch 'точный стиль скобок.*локальным стандартом') { throw 'Portable implementation policy must preserve the invariant without selecting a brace style.' } if ($architecture -match 'настрой стабильный алиас корня|\.\./\.\./\.\./') { throw 'Portable architecture policy must not prescribe a root alias or fixed import depth.' } diff --git a/tests/sync/test-sync-plan.ps1 b/tests/sync/test-sync-plan.ps1 index 4b7ccf3..98aa037 100644 --- a/tests/sync/test-sync-plan.ps1 +++ b/tests/sync/test-sync-plan.ps1 @@ -22,16 +22,25 @@ try { if ($before -ne $after) { throw 'Get-AiRulesSyncPlan must be read-only.' } $indexEntries = @($plan.Entries | Where-Object { $_.Target -eq '.ai-rules/upstream/INDEX.md' }) if ($indexEntries.Count -ne 1 -or $indexEntries[0].Source -ne 'generated/effective-index') { throw 'Sync plan must contain one generated effective index.' } - if ($indexEntries[0].Content -notmatch 'standard-product' -or $indexEntries[0].Content -notmatch '`profile`' -or $indexEntries[0].Content -match 'project-study|project-audit') { throw 'Effective index must describe only selected profiles and effective topics.' } + if ($indexEntries[0].Content -notmatch 'standard-product' -or $indexEntries[0].Content -notmatch '`profile`' -or $indexEntries[0].Content -match 'project-study|project-audit|parallel-delivery') { throw 'Effective index must describe only selected profiles and effective topics.' } + if (@($plan.Entries | Where-Object { $_.Target -eq '.ai-rules/upstream/workflows/PARALLEL_DELIVERY.md' }).Count -ne 0) { throw 'Unselected parallel workflow must not enter the sync plan.' } if ($indexEntries[0].Sha256 -ne (Get-AiRulesSha256Text -Content $indexEntries[0].Content)) { throw 'Effective index hash must cover generated content.' } $secondPlan = Get-AiRulesSyncPlan -HubRoot $hubRoot -ProjectRoot $projectRoot if (@($secondPlan.Entries | Where-Object { $_.Target -eq '.ai-rules/upstream/INDEX.md' })[0].Content -ne $indexEntries[0].Content) { throw 'Effective index generation must be deterministic.' } + $parallelProjectRoot = Join-Path $projectRoot 'parallel project' + New-Item -ItemType Directory -Path $parallelProjectRoot | Out-Null + & $powershellExe -NoProfile -ExecutionPolicy Bypass -File (Join-Path $hubRoot 'scripts/init-project-sync.ps1') -ProjectRoot $parallelProjectRoot -Topics parallel-delivery + if ($LASTEXITCODE -ne 0) { throw 'Explicit parallel workflow fixture initialization failed.' } + $parallelPlan = Get-AiRulesSyncPlan -HubRoot $hubRoot -ProjectRoot $parallelProjectRoot + $parallelWorkflowEntries = @($parallelPlan.Entries | Where-Object { $_.Target -eq '.ai-rules/upstream/workflows/PARALLEL_DELIVERY.md' }) + $parallelIndexEntries = @($parallelPlan.Entries | Where-Object { $_.Target -eq '.ai-rules/upstream/INDEX.md' }) + if ($parallelWorkflowEntries.Count -ne 1 -or $parallelIndexEntries.Count -ne 1 -or $parallelIndexEntries[0].Content -notmatch '### `parallel-delivery`' -or $parallelIndexEntries[0].Content -notmatch '`workflow`') { throw 'Explicit parallel selection must add its workflow and route it in the effective index.' } $expectedPathComparison = if ([System.IO.Path]::DirectorySeparatorChar -eq [char]'\') { [System.StringComparison]::OrdinalIgnoreCase } else { [System.StringComparison]::Ordinal } if ((Get-AiRulesPathComparison) -ne $expectedPathComparison) { throw 'Path comparison must follow the current filesystem platform.' } $caseBoundaryAccepted = $true try { [void](Get-AiRulesSafePath -BasePath (Join-Path $projectRoot 'CaseBase') -ChildPath '../casebase/escape.md' -Label 'case boundary') } catch { $caseBoundaryAccepted = $false } if (($env:OS -eq 'Windows_NT') -ne $caseBoundaryAccepted) { throw 'Path containment must follow filesystem case sensitivity.' } - Write-Host 'Sync plan tests passed: 9 assertions.' -ForegroundColor Green + Write-Host 'Sync plan tests passed: 11 assertions.' -ForegroundColor Green } finally { if (Test-Path -LiteralPath $projectRoot) { Remove-Item -LiteralPath $projectRoot -Recurse -Force } diff --git a/workflows/PARALLEL_DELIVERY.md b/workflows/PARALLEL_DELIVERY.md new file mode 100644 index 0000000..de0fb34 --- /dev/null +++ b/workflows/PARALLEL_DELIVERY.md @@ -0,0 +1,51 @@ +# Параллельная доставка задачи + +Применяй этот процесс только для явно выбранной большой задачи. Устойчивые нормы распределения работы и Git находятся в тематических правилах `AI_COLLABORATION.md` и `GIT_AND_DELIVERY.md`, если они выбраны проектом. Образец формы одной подзадачи находится в исходном хабе: `templates/TASK_CONTRACT.md`. Подключённый проект может использовать собственную форму с теми же полями. Процесс не требует собственной очереди, службы запуска или автоматического объединения. + +## 1. Понять результат + +Координатор читает локальные инструкции, проверяет состояние Git, формулирует общий наблюдаемый результат, границы, проверки и уже выданные полномочия. Пока неизвестна цель всей задачи, делить её между исполнителями рано. Если задача короткая или неделимая, один агент выполняет её обычным способом. + +## 2. Построить зависимости + +Раздели работу на подзадачи с самостоятельным проверяемым результатом. Запиши зависимости как граф и пометь узлы: + +- `blocked` — ожидает результат или решение другой задачи; +- `ready` — зависимости выполнены, но параллельный запуск ещё не оценён; +- `parallelizable` — готова и имеет независимую область записи и фиксированные общие контракты; +- `integration-only` — выполняется владельцем интеграции после передачи результатов. + +Запускай вместе только узлы `parallelizable`. При оценке учитывай пересечение файлов, контрактов, миграций и проверок, а также затраты на объединение. Количество доступных агентов не определяет число подзадач. + +## 3. Определить общие контракты + +Найди интерфейсы между задачами и их канонические источники. Для нового общего интерфейса сначала согласуй его форму и владельца изменения. Если контракт ещё не определён, зависимые реализации остаются `blocked`; разные исполнители не придумывают его версии параллельно. Изменение контракта оформляй отдельным решением и обновляй затронутые задачи до продолжения. + +## 4. Назначить задачи и рабочие каталоги + +Создай короткий контракт каждой пишущей подзадачи по шаблону. Укажи точную базовую ревизию, область записи, зависимости, владельца общего контракта, критерии и разрешённые действия. Назначь одного владельца интеграции. Для Git подготовь отдельные ветки и изолированные рабочие каталоги; в Codex для пишущих исполнителей используй отдельные worktree, когда они доступны. Проверь, что создание каталога не перенесёт чужие изменения и что каждое действие разрешено. + +Исполнителю передай его контракт, необходимые локальные инструкции и ссылки на исходные контракты. Не передавай весь внутренний контекст координатора. Исполнитель проверяет назначенную ветку, рабочий каталог и базу до записи. Задачи только на чтение могут делить исходный каталог, если не изменяют его состояние. + +## 5. Выполнить и принять результаты + +Координатор отслеживает зависимости и препятствия. Исполнитель остаётся в своей области записи и сообщает координатору о необходимости изменения чужого контракта. По завершении он передаёт: результат, изменённые области, выполненные проверки и их вывод, отклонения от контракта, препятствия, commit/revision и оставшиеся риски. Частичный результат помечается частичным; координатор решает, обновить контракт, продолжить задачу или исключить её из интеграции. + +## 6. Проверить и интегрировать + +Независимую проверку назначай пропорционально риску; отдельный проверяющий для тривиальной задачи не обязателен. Для значимой реализации передай проверяющему контракт, diff и результаты тестов. Проверяющий по умолчанию работает только для чтения и сообщает замечания владельцу интеграции. + +Владелец интеграции сверяет результаты с контрактами и исходной базой, объединяет изменения разрешённым способом, разрешает конфликты, проверяет взаимодействие частей, затем запускает общий набор проверок на итоговой ревизии. Локальные проверки исполнителей не заменяют этот gate. После интеграции назови точную проверенную ревизию и непроверенные эффекты. + +## 7. Обработать отклонения + +- Неверное предположение исполнителя: останови затронутую часть, проверь источник истины и обнови контракт или граф зависимостей; не маскируй предположение локальной правкой. +- Изменился общий контракт: его владелец фиксирует новую версию, координатор уведомляет зависимые задачи и повторно проверяет возможность параллельной работы. +- Базовая ветка ушла вперёд: сравни старую и новую базу; владелец интеграции решает, когда и как перенести результат, затем повторяет затронутые проверки. +- Задачи пересеклись: останови запись в пересекающуюся область, назначь одного владельца и обнови контракты; объединение не считается автоматическим разрешением смыслового конфликта. +- Исполнитель закончил часть задачи: сохрани проверенный результат и явно отметь невыполненные критерии; не объявляй весь узел готовым. +- Проверки прошли отдельно, но упали после интеграции: владелец интеграции расследует взаимодействие на итоговой ревизии, назначает исправление и повторяет затронутый и общий gate до заявления о готовности. + +## 8. Передать решение владельцу и очистить + +Покажи итоговый diff, проверенную ревизию, результаты проверок и оставшийся риск. Внешние действия выполняй только в уже разрешённых границах; перед неразрешёнными отправкой, запросом на слияние, выпуском или публикацией остановись. Очищай рабочие каталоги только с разрешения владельца после подтверждения сохранности результатов и отсутствия потребности в дальнейшей проверке. Не удаляй незакоммиченные или неинтегрированные данные. diff --git a/workflows/PARALLEL_DELIVERY_PROMPT.md b/workflows/PARALLEL_DELIVERY_PROMPT.md new file mode 100644 index 0000000..3dcd3fc --- /dev/null +++ b/workflows/PARALLEL_DELIVERY_PROMPT.md @@ -0,0 +1,17 @@ +# Запуск параллельной доставки + +Используйте этот запрос в Codex, открытом в корне целевого проекта. Добавьте после него описание своей задачи. Команда печатает только текст и не подключает правила автоматически. + +## Готовый запрос + +```text +Выступи координатором задачи в проекте "{{PROJECT_ROOT}}". Мою задачу я добавлю после этого запроса. Используй Agent Engineering Kit из {{HUB_CLI_PATH}} и рабочий процесс `parallel-delivery` только если параллельная работа действительно полезна. + +1. Прочитай локальный `AGENTS.md`, выбранные правила через `.ai-rules/upstream/INDEX.md` и относящийся к задаче код. Проверь `git status`, ветку, несвязанные изменения и состояние подключения Kit. Сначала сформулируй общий наблюдаемый результат и проверки. Если задача короткая или зависимая, работай одним агентом без подключения процесса. +2. Для действительно делимой задачи проверь выбор `parallel-delivery` в manifest и объяснение в RULESET. Проверь также, доступны ли тематические правила `ai-collaboration` и `git-and-delivery` для этой задачи. Если нужного элемента нет, покажи точные изменения локальных manifest и RULESET, план синхронизации и необходимые разрешения. Не меняй управляемые файлы вручную; остановись перед неразрешённым `-Apply`. После применения проверь `doctor` и `status` и прочитай подключённый workflow целиком. +3. Построй граф зависимостей с состояниями `blocked`, `ready`, `parallelizable`, `integration-only`. Найди общие контракты, их источники истины и владельцев. Если контракт новый, определи его до запуска зависимых исполнителей. Подготовь короткие контракты подзадач по шаблону "{{TASK_CONTRACT_PATH}}": владелец, точная база, область записи, зависимости, общие контракты, критерии, проверки и полномочия. +4. Предложи безопасный набор параллельных исполнителей, назначь каждому пишущему агенту отдельную ветку и workspace/worktree и назначь одного владельца интеграции. Передай исполнителю его контракт и нужные локальные инструкции, а не весь свой внутренний контекст. Используй штатные средства Codex (Agent Command Center) для координации, если они доступны; не создавай собственный менеджер агентов. +5. До запуска проверь, что задачи и действия охвачены моим запросом и локальными правилами. Остановись только перед действиями, требующими отдельного невыданного разрешения. Сбор результатов, независимая проверка по риску, интеграция и общий набор проверок выполняются по `PARALLEL_DELIVERY.md`. Исполнители не отправляют изменения и не интегрируют их самостоятельно. + +В итоге покажи граф задач, владельцев и рабочие каталоги, результаты и отклонения, итоговую проверенную ревизию, проверки и оставшиеся риски. Не выполняй commit, push, merge, PR, выпуск или публикацию без соответствующего разрешения. +```