Пишите промпт как исполняемую спецификацию
Сильный промпт не обязан быть длинным. Он обязан отделять цель, факты, границы, процедуру, проверку и отчёт. Такая структура уменьшает пространство скрытых догадок и делает ответ пригодным для аудита. В companion-проекте промпт собирается из контракта детерминированно - одним и тем же кодом, а не на глаз.
export function buildVerifiedChangePrompt(contract: TaskContract, repository: RepositoryMap): string {
const relevantEntries = repository.entries
.filter((entry) => contract.contextPaths.some((path) => entry.path === path || entry.path.startsWith(`${path}/`)))
.map((entry) => `${entry.path} [${entry.kind}, ${entry.bytes} bytes]`);
return [
"# Goal",
contract.goal,
"",
"# Context",
relevantEntries.length > 0 ? bullets(relevantEntries) : bullets(contract.contextPaths),
"",
"# Allowed write scope",
bullets(contract.allowedWritePaths),
"",
"# Constraints",
bullets(contract.constraints),
"",
"# Procedure",
"1. Read the relevant implementation, tests, and repository instructions.",
"2. Explain the root cause and propose a file-level plan before editing.",
"3. Make the smallest coherent patch inside the allowed write scope.",
"4. Run the acceptance checks and inspect the final diff.",
"5. Stop and ask if credentials, destructive actions, network access, or wider scope are required.",
"",
"# Done when",
bullets(contract.acceptanceChecks),
"",
"# Final report",
"List changed files, commands with exit codes, observed evidence, and residual risks. Do not claim success without evidence."
].join("\n");
}За сборкой стоят семь секций, и у каждой одна работа: Goal - что должно измениться для пользователя; Context - какие файлы, ошибки и тесты являются источниками; Allowed write scope - где разрешено менять код; Constraints - совместимость и запреты; Procedure - нужно ли сначала исследовать и показать план; Done when - команды и ожидаемые сигналы; Final report - diff, exit codes, доказательства и остаточный риск.
Собрать такой промпт по частям и увидеть, какой секции не хватает, помогает конструктор.
Соберите контрактный промпт
# Goal Воспроизведи и исправь наблюдаемый дефект без обхода проверки. # Context Назови paths, symbols, symptom и канонический пример. # Allowed write scope Пиши только в явно названный файл. # Constraints Не добавляй dependency и не меняй public API без отдельного согласования. # Procedure Сначала исследуй и покажи file-level plan. Затем сделай минимальный patch. # Done when Focused regression test, затем full check. # Final report Changed files, exact commands, exit codes, evidence и residual risks.
Отдельно - об отрицательных границах. "Не меняй публичный API, не добавляй dependency, не трогай миграции" не заменяет цель, но отсекает несколько дешёвых обходных путей. Граница должна отражать реальный риск; список из десятков общих запретов только размывает внимание.
Опасный шаблон. "Сделай как лучше, запусти всё необходимое и не задавай вопросов" одновременно расширяет scope, скрывает права и запрещает остановку. Это не автономность, а отсутствие контракта.
Промпт задаёт форму. Наполняет её контекст - но не весь репозиторий, а ровно то, что меняет решение.