Agent Dev 101

Модуль 12 · Урок 12.1

Урок 12.1. Hooks

На этой странице
  1. Зачем это нужно
  2. Основная идея
  3. Ключевые термины
  4. Hook В Agent Workflow
  5. Hook Vs Prompt Instruction
  6. Hook Vs Test Vs CI Vs Guardrail
  7. Anatomy Of A Hook
  8. AfterEdit Hooks
  9. BeforeCommit Hooks
  10. BeforeDeploy Hooks
  11. scripts/verify Как Единая Точка Проверки
  12. Почему Единая Команда Важна Для Агентов
  13. Hook Placement В Development Loop
  14. Hooks И Orchestration Gates
  15. Failure Behavior
  16. Fail Closed И Fail Open
  17. Hook Design Principles
  18. Что Можно Автоматизировать Hook'ом
  19. Hooks Для Разных Типов Репозиториев
  20. Hooks Для AI Agent Development
  21. Hook Evidence В Agent Report
  22. Hooks И Skills
  23. Hooks И MCP/Tools
  24. Пример: Hooks Plan Для Demo Repo
  25. Example Failure Flow
  26. Hook Output Который Помогает Агенту
  27. Hooks И Cost Management
  28. Hooks И Изменение Тестов
  29. Hooks И Secrets
  30. Hooks И Generated Files
  31. Hooks И Документация
  32. Как Проектировать Hook
  33. Когда Hook Не Нужен
  34. Типичные Ошибки
  35. Практика
  36. Мини-Задание: Перевести Prompt Rules В Hooks
  37. Краткое резюме
  38. Вопросы для самопроверки
  39. Что дальше

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

В предыдущем модуле мы построили orchestration для multi-agent workflow:

text
Planner
-> Task DAG
-> Agents
-> Integration
-> Reviewer
-> CI
-> Human approval

Эта схема работает лучше, чем "пусть агенты сами разберутся", но в ней остается важный вопрос:

text
Какие проверки мы оставляем на память агента,
а какие выносим в автоматическое выполнение?

Плохой вариант:

text
Пожалуйста, не забудь после каждого изменения запускать formatter.
Пожалуйста, не забудь перед commit запускать tests.
Пожалуйста, не забудь перед deploy проверить secrets.

LLM может забыть. Может решить, что проверка "не нужна в этот раз". Может написать убедительный summary без фактического запуска команды. Может остановиться из-за context pressure. Может перепутать project commands.

Hook решает другую задачу:

text
Когда произошло событие X,
автоматически выполни действие Y
и останови workflow, если результат небезопасен.

Примеры:

text
AfterEdit
 -> formatter

BeforeCommit
 -> lint
 -> typecheck
 -> tests

BeforeDeploy
 -> security check
 -> migration check
 -> human approval

Главная мысль урока:

text
То, что можно надежно проверить или выполнить программно,
не должно жить только как просьба в prompt.

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

Hook - это автоматическое действие, привязанное к событию workflow.

Формула:

text
Event
-> Hook command
-> Exit status / evidence
-> Continue, fix, stop or ask approval

Например:

text
Agent edited TypeScript file
-> run formatter on changed file
-> if formatting succeeds, continue
-> if formatting fails, stop and show error

Или:

text
Agent wants to commit
-> run scripts/verify
-> if green, commit allowed
-> if red, task returns to fix/verification

Hook важен не потому, что он "умнее" агента. Он важен потому, что он:

  • deterministic;
  • повторяемый;
  • наблюдаемый;
  • работает одинаково для человека и агента;
  • возвращает exit code;
  • может остановить workflow;
  • не зависит от того, помнит ли LLM инструкцию.

Prompt остается полезным:

text
Перед commit запусти scripts/verify.

Но hook делает правило enforceable:

text
Commit не проходит, если scripts/verify failed.

Ключевые термины

Термин Значение
Hook Автоматическое действие, которое запускается при определенном событии workflow.
Trigger Событие, которое запускает hook: edit, commit, push, deploy, tool call, file change.
Action Команда или script, который hook выполняет.
Exit code Машинно-читаемый результат команды: 0 обычно success, non-zero failure.
Deterministic automation Проверка или действие, которое выполняется программно и повторяемо.
AfterEdit Hook после изменения файлов. Часто запускает formatter или lightweight checks.
BeforeCommit Hook перед commit. Часто запускает lint, typecheck, tests, secret scan.
BeforeDeploy Hook перед deploy. Часто запускает security checks, migration checks, smoke tests, approval.
Fail closed При failure workflow останавливается. Безопасный default для critical checks.
Fail open При failure workflow продолжает работу с warning. Использовать осторожно.
Idempotent Повторный запуск hook не ломает состояние и не создает лишних изменений.
scripts/verify Единая команда в репозитории, которая запускает стандартные проверки проекта.
Hook evidence Короткое подтверждение: какая команда запущена, что passed/failed, что не запускалось.
Routing decision Что делать после hook result: continue, fix, retry, block, ask approval.

Hook В Agent Workflow

Без hooks agent workflow часто выглядит так:

flowchart TD A[User task] --> B[Agent edits files] B --> C[Agent remembers checks] C --> D{Did it run them?} D -- maybe --> E[Summary] D -- no --> F[Unverified diff]

С hooks:

flowchart TD A[User task] --> B[Agent edits files] B --> C[AfterEdit hook] C --> D[Formatter / lightweight checks] D --> E[Agent continues] E --> F[BeforeCommit hook] F --> G[scripts/verify] G --> H{Passed?} H -- no --> I[Fix or block] H -- yes --> J[Commit / Review / CI] J --> K[BeforeDeploy hook] K --> L[Security / smoke / approval]

Важное изменение:

text
Проверка больше не является частью хорошего поведения агента.
Проверка становится частью среды выполнения.

Это особенно важно в AI-assisted development, потому что агент может быстро писать код, но не всегда стабильно поддерживает operational discipline. Hooks добавляют внешнюю опору.

Hook Vs Prompt Instruction

Prompt instruction говорит агенту, что делать.

Hook делает действие частью workflow.

Правило Prompt instruction Hook
Format after edit "Не забудь запустить formatter." Formatter запускается после изменения файла.
Test before commit "Перед commit запусти tests." Commit blocked, если tests failed.
Do not commit secrets "Не добавляй secrets." Secret scan blocks commit.
Validate docs links "Проверь ссылки." Link checker runs in verify.
No direct deploy "Не deploy без approval." Deploy command требует approval gate.

Prompt instruction слабее, потому что:

  • зависит от внимания модели;
  • может конфликтовать с другими instructions;
  • может быть пропущена при длинной задаче;
  • может быть выполнена частично;
  • может превратиться в unsupported claim.

Hook сильнее, потому что:

  • запускается по событию;
  • имеет machine-readable result;
  • может остановить действие;
  • дает одинаковый результат для агента, человека и CI;
  • оставляет evidence.

Но hook не заменяет prompt полностью. Prompt объясняет intent и поведение:

text
If BeforeCommit fails, inspect the output, fix the root cause,
rerun the same command, and report failed/not-run checks explicitly.

Hook обеспечивает execution. Prompt объясняет, как агент должен реагировать.

Hook Vs Test Vs CI Vs Guardrail

Эти механизмы пересекаются, но не совпадают.

Механизм Что делает Пример
Hook Запускает действие при событии workflow. BeforeCommit запускает scripts/verify.
Test Проверяет поведение кода. Unit test проверяет password reset token expiry.
CI Запускает checks в центральной среде. Pull request build, lint, tests.
Guardrail Ограничивает действие или требует gate. Нельзя push в main, нельзя deploy без approval.
Prompt rule Инструктирует агента. "Не меняй unrelated files."

Hook может запускать tests. CI может запускать тот же scripts/verify. Guardrail может требовать, чтобы CI был green. Prompt может сказать агенту, как читать failures.

Практичная связка:

text
Prompt rule:
Before finishing, provide verification evidence.

Hook:
BeforeCommit runs scripts/verify.

CI:
Pull request runs scripts/verify in clean environment.

Guardrail:
Merge blocked unless CI is green.

В следующем уроке мы подробнее разберем guardrails. Сейчас важно увидеть роль hooks: они запускают automation в нужный момент.

Anatomy Of A Hook

У hook есть несколько обязательных частей.

text
Name:
  BeforeCommit

Trigger:
  user or agent attempts commit

Action:
  ./scripts/verify

Inputs:
  current working tree, changed files, environment variables

Output:
  command output, logs, summary

Decision:
  exit 0 -> continue
  exit non-zero -> stop and route to fix

Минимальный hook contract:

Поле Вопрос
Event Когда hook запускается?
Scope На какие файлы или действия он реагирует?
Command Что именно выполняется?
Runtime Где выполняется: local, CI, agent environment?
Timeout Сколько времени допустимо?
Failure behavior Что происходит при non-zero exit?
Evidence Как результат попадает в handoff/report?
Owner Кто чинит hook, если он сломан?

Если hook не имеет clear failure behavior, он быстро превращается в шум.

AfterEdit Hooks

AfterEdit hook запускается после изменения файлов.

Типичные задачи:

  • formatter;
  • import organizer;
  • generated index refresh;
  • lightweight static check;
  • markdown table formatting;
  • docs TOC refresh;
  • file-level lint;
  • schema/codegen refresh для конкретного файла.

Пример:

text
Event:
Agent edited `*.ts` or `*.tsx`

Action:
Run formatter on changed files.

Failure:
Stop and show formatter output.
Do not continue to larger tests until formatting problem is resolved.

AfterEdit hook должен быть быстрым. Если он занимает минуты, агент будет получать slow feedback после каждого небольшого изменения и начнет обходить hook.

Хорошие AfterEdit checks:

Hook Почему подходит
Format changed file Быстро, deterministic, idempotent.
Sort imports Быстро, локально, уменьшает diff noise.
Markdown formatting Быстро, предотвращает мелкие style issues.
Regenerate local schema types Подходит, если четко привязано к измененному schema file.

Плохие AfterEdit checks:

Hook Почему плохо
Full test suite after every edit Слишком дорого, мешает iteration.
Production deploy after config edit Рискованно, требует approval.
Automatic dependency upgrade Меняет scope без решения человека.
Large semantic rewrite Hook начинает делать implementation вместо проверки.

Принцип:

text
AfterEdit should reduce mechanical friction,
not make product decisions.

BeforeCommit Hooks

BeforeCommit hook запускается перед созданием commit.

Его задача:

text
Не дать непроверенному diff попасть в историю.

Типичные checks:

  • formatting check;
  • lint;
  • typecheck;
  • unit tests;
  • targeted integration tests;
  • docs build;
  • secret scan;
  • generated files up to date;
  • lockfile consistency;
  • no conflict markers;
  • no accidental debug statements;
  • no large unrelated artifacts.

Пример policy:

text
BeforeCommit:
1. Run formatter check.
2. Run lint.
3. Run typecheck.
4. Run tests relevant to changed files.
5. Run secret scan.
6. Block commit if any required check fails.

BeforeCommit не обязан всегда запускать everything. В больших репозиториях это может быть слишком дорого. Но он должен запускать minimal reliable checks, которые защищают от очевидно плохого diff.

Практичная схема:

Размер проекта BeforeCommit
Маленький repo Full scripts/verify.
Средний repo Format/lint/typecheck + targeted tests.
Большой repo Fast local checks + changed-file tests + CI for full suite.
Safety-critical area Required targeted tests + security checks + approval.

В AI Agent Development BeforeCommit особенно важен, потому что агент может сделать много маленьких изменений быстро. Hook заставляет каждое законченное изменение пройти одинаковый minimum bar.

BeforeDeploy Hooks

BeforeDeploy hook запускается перед release или deploy.

Это более строгий stage, чем BeforeCommit, потому что последствия выходят за пределы локального repo.

Типичные checks:

  • full test suite;
  • build;
  • smoke tests;
  • migration dry run;
  • secret/config validation;
  • dependency vulnerability scan;
  • permissions check;
  • environment check;
  • rollback plan check;
  • human approval.

Пример:

text
BeforeDeploy:
1. Ensure current commit passed CI.
2. Check migrations are backward-compatible or approved.
3. Run smoke tests against staging.
4. Verify secrets/config are present and not printed.
5. Require human approval for production deploy.

BeforeDeploy должен быть fail closed для risky operations.

text
If security check fails, do not deploy.
If migration check is inconclusive, ask human approval.
If staging smoke test fails, stop release.

Плохая практика:

text
Agent says: "Deploy should be fine because tests passed locally."

Локальные tests не являются deploy approval.

scripts/verify Как Единая Точка Проверки

В плане курса итоговым artifact модуля указан scripts/verify. Это важная идея.

Вместо того чтобы каждый agent вспоминал набор команд:

text
npm run lint
npm run typecheck
npm test
npm run build

репозиторий дает одну команду:

text
./scripts/verify

Она становится единым контрактом:

text
Если хочешь заявить, что change verified,
покажи результат scripts/verify или объясни, почему он не запускался.

scripts/verify может быть простым:

bash
#!/usr/bin/env bash
set -euo pipefail

npm run lint
npm run typecheck
npm test

Или чуть более структурированным:

bash
#!/usr/bin/env bash
set -euo pipefail

echo "[verify] format"
npm run format:check

echo "[verify] lint"
npm run lint

echo "[verify] typecheck"
npm run typecheck

echo "[verify] tests"
npm test

В больших проектах scripts/verify может принимать режим:

text
./scripts/verify --fast
./scripts/verify --changed
./scripts/verify --full
./scripts/verify --security

Но даже тогда нужен default:

text
./scripts/verify

Default должен быть понятен агенту и человеку.

Почему Единая Команда Важна Для Агентов

Агенту трудно надежно удерживать в context project-specific набор проверок, особенно если:

  • repo polyglot;
  • есть frontend и backend;
  • tests лежат в нескольких директориях;
  • commands отличаются для local и CI;
  • часть проверок optional;
  • есть generated files;
  • есть линтеры, formatters, schema checks;
  • команда менялась со временем.

scripts/verify снижает cognitive load:

text
Agent does not need to rediscover the verification protocol.
The repo exposes it as executable interface.

Это похоже на public API:

text
Input:
  current repo state

Command:
  ./scripts/verify

Output:
  pass/fail + logs

В идеале scripts/verify используется в трех местах:

text
Local developer
-> ./scripts/verify

Agent BeforeCommit hook
-> ./scripts/verify

CI
-> ./scripts/verify

Так local, agent и CI говорят на одном языке.

Hook Placement В Development Loop

Вспомним development loop:

text
Understand task
-> Plan
-> Write tests
-> Implement
-> Verify
-> Review
-> Commit

Hooks добавляются вокруг repeatable checkpoints:

flowchart TD A[Understand task] --> B[Plan] B --> C[Write or update tests] C --> D[Implement] D --> E[AfterEdit: format / light check] E --> F[Run targeted verification] F --> G[Self-check diff] G --> H[BeforeCommit: scripts/verify] H --> I[Independent review] I --> J[CI] J --> K[BeforeDeploy: security / smoke / approval]

Hook не должен заменять thinking stages:

  • он не решает, что строить;
  • он не выбирает architecture;
  • он не проверяет все product assumptions;
  • он не делает independent review;
  • он не принимает risk decisions.

Hook усиливает mechanics:

  • запускает повторяемые команды;
  • ловит очевидные нарушения;
  • создает early feedback;
  • фиксирует evidence;
  • переводит workflow в failed state, если нужно.

Hooks И Orchestration Gates

В уроке 11.4 мы говорили про gates:

text
Spec Gate
Plan Gate
Contract Gate
Verification Gate
Integration Gate
Review Gate
CI Gate
Human Approval Gate

Hook может реализовать часть gate.

Gate Что может сделать hook Что не должен делать hook
Verification Gate Запустить tests/lint/typecheck. Решать, соответствует ли feature продуктовой цели.
Integration Gate Запустить full verify после merge. Молча менять contract.
Review Gate Подготовить review packet. Заменять independent reviewer.
CI Gate Запустить checks в clean env. Игнорировать failed checks.
Human Approval Gate Остановить workflow и запросить approval. Самостоятельно принимать risky decision.

Важно:

text
Hook can enforce mechanics.
Human/reviewer still handles judgment.

Например, secret scan может заблокировать commit. Но решение "это false positive или реальный secret" может требовать человека.

Failure Behavior

Hook без понятного failure behavior раздражает. Hook с понятным failure behavior улучшает процесс.

Минимальная политика:

text
If hook fails:
1. Stop the current transition.
2. Preserve output.
3. Identify failing command.
4. Route to fix, retry, block or approval.
5. Do not claim success.

Таблица решений:

Failure Routing
Formatter changed files Inspect diff, continue if only mechanical.
Formatter failed Fix syntax/config issue, rerun.
Lint failed Fix lint issue or justify suppression.
Typecheck failed Fix implementation or contract mismatch.
Unit tests failed Fix code or test, rerun same tests.
Secret scan failed Stop, remove secret, rotate if leaked.
Security check inconclusive Ask human/security approval.
Deploy smoke test failed Stop deploy, investigate staging/prod mismatch.
Hook infrastructure broken Mark blocked, do not pretend verification passed.

Agent response to hook failure should not be:

text
The hook probably failed because of environment issues, continuing.

Better:

text
BeforeCommit failed on `npm run typecheck`.
I will inspect the TypeScript error, fix the root cause,
rerun `./scripts/verify`, and report whether it passes.

Fail Closed И Fail Open

Fail closed:

text
If check fails, stop workflow.

Fail open:

text
If check fails, continue with warning.

Для agent workflow default должен быть conservative.

Check Рекомендуемое поведение
Formatter Обычно fail closed before commit, auto-fix after edit.
Lint Fail closed before commit.
Typecheck Fail closed before commit.
Unit tests Fail closed before commit или before merge.
Secret scan Fail closed.
Security check before deploy Fail closed or human approval required.
Docs link checker Может быть fail open locally, fail closed in CI для docs release.
Slow flaky integration test Отдельная policy: quarantine, rerun, owner, not silent pass.

Fail open опасен, если агент начинает использовать warning как permission.

Плохой pattern:

text
The check failed, but it is probably fine.

Хороший pattern:

text
The check failed.
This transition is blocked unless the project policy allows override.
Override requires human approval and documented reason.

Hook Design Principles

Хороший hook:

  • deterministic;
  • idempotent;
  • fast enough for its stage;
  • scoped;
  • has clear exit codes;
  • prints actionable output;
  • avoids destructive side effects;
  • works locally and in CI;
  • has documented failure behavior;
  • is easy to run manually;
  • is versioned in the repo;
  • does not depend on hidden local state;
  • does not require broad permissions without reason.

Плохой hook:

  • иногда pass, иногда fail без причины;
  • делает large rewrite;
  • скрывает output;
  • требует секреты для обычной локальной проверки;
  • долго работает на каждом edit;
  • меняет unrelated files;
  • автоматически deploy'ит;
  • обновляет dependencies;
  • чинит tests путем их ослабления;
  • имеет неясный owner.

Короткая формула:

text
Hooks should make the safe path easy
and the unsafe path explicit.

Что Можно Автоматизировать Hook'ом

Хорошие candidates:

Candidate Почему подходит
Formatting Deterministic, fast, low judgment.
Import sorting Mechanical, idempotent.
Lint Static, repeatable.
Typecheck Deterministic для большинства проектов.
Unit tests Проверяют behavior, хорошо подходят before commit/CI.
Secret scan High value, deterministic enough.
Conflict marker check Cheap and important.
Generated files check Ловит забытый codegen.
Markdown lint Полезно для docs/course repos.
Link check Полезно перед docs release.
Dependency lockfile check Ловит inconsistent installs.
Test coverage threshold Подходит, если threshold осмысленный.

С осторожностью:

Candidate Риск
Full e2e after every edit Слишком медленно.
Vulnerability scan on every local commit Может быть шумным и медленным.
Auto-fix lint with semantic changes Может изменить behavior.
AI-generated review hook Не deterministic, лучше как assistant, не gate.
Auto-migration Риск data loss.
Auto-deploy Риск production impact.

Почти никогда не стоит:

  • автоматически force push;
  • автоматически удалять user data;
  • автоматически менять billing/permissions;
  • автоматически принимать security risk;
  • автоматически изменять acceptance criteria;
  • автоматически отключать tests.

Hooks Для Разных Типов Репозиториев

Node/TypeScript Web App

text
AfterEdit:
- format changed files;
- organize imports.

BeforeCommit:
- format check;
- lint;
- typecheck;
- unit tests;
- changed e2e tests if relevant;
- secret scan.

BeforeDeploy:
- build;
- full tests;
- migration check;
- staging smoke;
- approval.

Python Service

text
AfterEdit:
- formatter on changed `.py`;
- import sorting.

BeforeCommit:
- lint;
- typecheck if used;
- unit tests;
- contract tests;
- secret scan.

BeforeDeploy:
- full test suite;
- migration dry run;
- dependency audit;
- smoke tests.

Documentation / Course Repository

text
AfterEdit:
- markdown format;
- heading/style check if lightweight.

BeforeCommit:
- markdown lint;
- internal link check;
- code fence check;
- spell/terminology check if available.

BeforeRelease:
- docs build;
- link check;
- sample code verification.

AI Agent Workflow Repository

text
AfterEdit:
- format prompts/skills/docs;
- validate YAML/JSON config;
- regenerate prompt index.

BeforeCommit:
- prompt schema validation;
- skill metadata validation;
- eval smoke suite;
- scripts/verify;
- no secrets in examples.

BeforeDeploy:
- eval regression suite;
- tool permission diff review;
- approval for new external tools;
- rollout plan.

Hooks Для AI Agent Development

AI Agent Development имеет особые риски:

  • prompt changes can silently change behavior;
  • skill updates can alter agent procedures;
  • tool permission changes can expand blast radius;
  • evals may be skipped because they are slow;
  • examples may include fake secrets;
  • agent instructions can contradict project rules.

Hooks помогают сделать процесс стабильнее.

Примеры:

Event Hook Purpose
Skill edited Validate SKILL.md frontmatter and required sections. Не дать сломанному skill попасть в repo.
Prompt edited Run prompt schema or snapshot tests. Ловить broken placeholders and missing variables.
Tool config changed Show permission diff. Сделать blast radius visible.
Eval file changed Run eval smoke suite. Проверить, что evals still execute.
Agent policy changed Run policy consistency check. Найти contradictions between docs and prompts.
Before release Run regression eval suite. Поймать behavior drift.

Пример hook policy для prompt/skill repo:

text
BeforeCommit:
- validate all YAML/JSON files;
- validate SKILL.md frontmatter;
- check prompts have required variables;
- run eval smoke suite;
- run markdown checks;
- scan examples for secrets.

Это не гарантирует, что агент стал лучше. Но это гарантирует, что obvious structural failures не попали в history.

Hook Evidence В Agent Report

Агент должен включать hook evidence в final report.

Плохой final report:

text
Сделал. Все проверил.

Хороший final report:

text
Changed:
- modules/module_12/lesson_12_01_hooks.md

Verification:
- `rg -n "UNFINISHED|DRAFT_MARKER|TEMP_MARKER"`: no matches
- code fence count: even
- `git diff --check`: passed

Not run:
- full course build, because repo has no build script.

Evidence не обязательно должна быть длинной. Она должна быть конкретной.

Для hooks это особенно важно:

text
Hook result should become part of the handoff.

Если hook failed и потом passed, report должен сказать:

text
BeforeCommit initially failed on markdown lint.
Fixed heading spacing.
Reran `./scripts/verify`: passed.

Так reviewer видит процесс, а не только итоговую уверенность.

Hooks И Skills

В модуле 6 мы обсуждали skills. Skill может сказать агенту:

text
When editing API endpoints, run the API verification script.

Это полезно, но это still prompt-level instruction.

Если проверка критична и повторяема, лучше вынести ее в hook или script:

text
skills/api-endpoint/SKILL.md
  -> instructs agent when and why to run checks

scripts/verify-api-change.sh
  -> executes deterministic checks

BeforeCommit hook
  -> requires checks before commit

Связка:

Layer Role
Skill Объясняет workflow и domain-specific judgment.
Script Выполняет repeatable command.
Hook Запускает script в нужный момент.
CI Повторяет проверку в clean environment.
Guardrail Блокирует merge/deploy без required pass.

Не нужно помещать большие scripts прямо в SKILL.md. Skill должен ссылаться на script в repo и объяснять, когда его использовать.

Hooks И MCP/Tools

Hook не обязан быть только shell script. В agent ecosystem hook может запускать:

  • local command;
  • test runner;
  • formatter;
  • static analyzer;
  • MCP tool;
  • internal verification service;
  • policy check;
  • notification;
  • approval request.

Но принцип тот же:

text
Trigger -> Action -> Result -> Decision

Если hook вызывает external tool, добавляются вопросы:

  • какие permissions нужны;
  • что делать при network failure;
  • является ли результат deterministic;
  • где хранится output;
  • можно ли повторить проверку локально;
  • как избежать утечки secrets;
  • кто владеет integration.

Для 101 уровня default простой:

text
Prefer local scripts for project checks.
Use external tools when they add real verification value.

Например, secret scanning может быть local tool. Security posture dashboard может быть external. Но агенту все равно нужен понятный result: passed, failed, blocked, approval required.

Пример: Hooks Plan Для Demo Repo

Допустим, demo repo содержит:

text
web/
  src/
  tests/
docs/
scripts/

Технологии:

  • TypeScript frontend;
  • API routes;
  • Markdown docs;
  • test suite;
  • deploy через CI.

Hooks Plan

text
AfterEdit:
- if changed files match `web/src/**/*.{ts,tsx}`:
  run formatter on changed files;
- if changed files match `docs/**/*.md`:
  run markdown format/check;
- if changed files match `*.json` or `*.yaml`:
  run config validation.

BeforeCommit:
- run `./scripts/verify --changed`;
- run secret scan;
- block commit on failure.

BeforePush:
- run `./scripts/verify`;
- block push on failure.

BeforeDeploy:
- require green CI for commit;
- run staging smoke tests;
- check migration plan if migrations changed;
- require human approval for production.

scripts/verify Contract

text
Command:
./scripts/verify [--changed|--full|--security]

Default:
./scripts/verify runs the standard local verification suite.

Required output:
- each stage prints name;
- failures return non-zero;
- skipped checks print reason;
- no secrets printed.

Used by:
- human developer;
- agent BeforeCommit;
- CI workflow.

Agent Instruction Around Hooks

text
Before finalizing a coding task:
1. Run the relevant targeted checks.
2. Run `./scripts/verify` unless impractical.
3. If a hook/check fails, fix root cause and rerun.
4. If verification cannot be run, report it as not run with reason.
5. Do not describe a check as passed unless the command actually passed.

Notice: this instruction is still useful. But the real protection is that BeforeCommit/CI run the script regardless of the agent's memory.

Example Failure Flow

Scenario:

text
Agent edits password reset API.
BeforeCommit runs `./scripts/verify`.
Typecheck fails.

Good flow:

flowchart TD A[BeforeCommit hook] --> B[scripts/verify] B --> C{Typecheck} C -- fail --> D[Stop commit] D --> E[Agent inspects error] E --> F[Fix implementation or types] F --> G[Rerun scripts/verify] G --> H{Pass?} H -- no --> E H -- yes --> I[Commit allowed]

Bad flow:

text
The typecheck issue appears unrelated, so I will continue.

Maybe it is unrelated. But the right next action is not silent continuation. The agent should:

  • identify if it is pre-existing;
  • show evidence;
  • ask whether to proceed if policy allows;
  • document residual risk;
  • avoid claiming the change is fully verified.

Hook Output Который Помогает Агенту

Hook output должен быть readable.

Плохо:

text
ERROR 1

Лучше:

text
[verify] typecheck
web/src/auth/reset.ts:42:13
Type 'string | null' is not assignable to type 'string'.

Next:
- fix null handling;
- rerun `./scripts/verify`.

Хороший output экономит tokens и время. Агенту не нужно угадывать, что сломалось.

Для больших logs полезно:

  • печатать stage names;
  • показывать failed command;
  • сохранять full logs в файл;
  • выводить last relevant lines;
  • не печатать secrets;
  • не смешивать несколько tools в нечитаемый поток.

Hooks И Cost Management

Автоматизация не бесплатна. Слишком много hooks замедляют работу.

Нужно разделять checks по цене:

Уровень Пример Когда запускать
Very fast format changed file, conflict marker check AfterEdit.
Fast lint changed files, config validation AfterEdit или BeforeCommit.
Medium typecheck, targeted unit tests BeforeCommit.
Slow full e2e, full build, security scan BeforePush, CI, BeforeDeploy.
Expensive full eval regression suite Before release, scheduled, high-risk changes.

Правило:

text
Run cheap checks early.
Run expensive checks at meaningful gates.

Если slow check запускается слишком часто, люди и агенты начнут искать обход. Лучше иметь tiered verification:

text
./scripts/verify --fast
./scripts/verify --changed
./scripts/verify --full

Но default policy должна быть ясной:

  • что нужно перед commit;
  • что нужно перед PR/merge;
  • что нужно перед deploy;
  • что делать, если check не запускался.

Hooks И Изменение Тестов

В AI-assisted development есть особый риск:

text
Agent changes tests to make hook green.

Hook сам по себе не понимает, были ли tests ослаблены. Поэтому нужны дополнительные правила:

  • если agent меняет tests, он должен объяснить why;
  • reviewer смотрит test diff особенно внимательно;
  • acceptance criteria остаются source of truth;
  • failing test нельзя удалять без reason;
  • test weakening для green build требует review;
  • для bug fix сначала нужен reproducing test, когда practical.

Можно добавить hook, который сигналит о test changes:

text
If files under `tests/` changed:
- require test change summary in final report;
- run relevant test suite;
- include before/after behavior if bug fix.

Но judgement остается за reviewer.

Hooks И Secrets

Secret scan - один из самых полезных hooks для agent workflow.

Почему:

  • агент может вставить example token;
  • user может случайно дать secret в prompt;
  • docs/examples могут содержать fake-looking but real credentials;
  • logs могут попасть в commit;
  • config files легко перепутать.

Практичная policy:

text
BeforeCommit:
- scan changed files for secrets;
- block on high-confidence secret;
- require human decision for ambiguous finding.

BeforeDeploy:
- validate required secrets exist in environment;
- do not print secret values;
- fail if config references missing secret.

Важно различать:

text
Secret present in repo: block and remove.
Secret missing in deploy environment: block deploy and configure securely.

Hook не должен "исправлять" secret путем печати нового value или записи его в файл.

Hooks И Generated Files

Многие проекты имеют generated artifacts:

  • API clients from OpenAPI;
  • GraphQL types;
  • protobuf classes;
  • database migration snapshots;
  • docs TOC;
  • lockfiles;
  • compiled assets.

Агент может изменить source file и забыть generated file.

Hook помогает:

text
If schema changed:
-> run codegen check
-> fail if generated files are outdated

Два подхода:

Подход Как работает
Auto-generate after edit Hook обновляет generated files сразу.
Check before commit Hook fails, если generated files outdated.

Auto-generate подходит, если:

  • generator deterministic;
  • output small;
  • command fast;
  • generated files expected in repo.

Check-only подходит, если:

  • generator slow;
  • output large;
  • developer should decide;
  • generated files sometimes excluded.

Hooks И Документация

Для этого курса hooks полезны даже в Markdown-only репозитории.

Примеры:

text
AfterEdit:
- check code fences are balanced;
- format markdown tables;
- enforce heading style if needed.

BeforeCommit:
- run markdown lint;
- check internal links;
- check lesson files have required sections;
- scan for unfinished draft markers;
- check duplicate lesson titles.

Для курса можно сделать scripts/verify-docs:

bash
#!/usr/bin/env bash
set -euo pipefail

echo "[docs] placeholders"
rg -n "UNFINISHED|DRAFT_MARKER|TEMP_MARKER" modules guide req && exit 1 || true

echo "[docs] markdown fences"
: "real implementation can count fences per file"

echo "[docs] required summaries"
rg -L "## Краткое резюме" modules/**/*.md

Это учебный пример, не готовый universal linter. Но идея правильная: повторяемые проверки курса лучше сделать script'ом.

Как Проектировать Hook

Шаблон:

text
Hook Name:

Purpose:

Trigger:

Scope:

Command:

Expected duration:

Runs locally:
yes/no

Runs in CI:
yes/no

Failure behavior:

Can auto-fix:
yes/no

Requires human approval:
yes/no

Evidence to report:

Owner:

Пример:

text
Hook Name:
BeforeCommitVerify

Purpose:
Prevent unverified code from being committed.

Trigger:
Before local commit or agent checkpoint.

Scope:
All changed files.

Command:
./scripts/verify --changed

Expected duration:
Under 2 minutes.

Runs locally:
yes

Runs in CI:
CI runs ./scripts/verify --full

Failure behavior:
Block commit. Agent fixes root cause or reports blocked.

Can auto-fix:
No.

Requires human approval:
Only for override.

Evidence to report:
Command, pass/fail, not-run reason, failing stage.

Owner:
Project maintainers.

Когда Hook Не Нужен

Не все нужно превращать в hook.

Hook не нужен, если:

  • действие требует product judgement;
  • проверка не deterministic;
  • false positives слишком шумные;
  • command слишком медленная для выбранного stage;
  • output нельзя безопасно показать агенту;
  • действие требует secrets без необходимости;
  • check редко применяется и проще запускать вручную;
  • hook будет менять scope задачи;
  • нет owner, который будет поддерживать hook.

Примеры:

Идея Почему hook может быть плохим
"AI reviewer before every save" Нестабильно, дорого, много noise.
"Auto-refactor after edit" Может менять behavior и расширять diff.
"Auto-deploy after tests" Deploy требует risk decision и approval.
"Auto-delete unused files" Риск потери work-in-progress.
"Auto-upgrade dependencies weekly" Требует review, changelog, compatibility checks.

Хороший вопрос:

text
Can this action be safely repeated by a script
without understanding product intent?

Если нет, это не простой hook. Возможно, это review, approval, manual task или guardrail.

Типичные Ошибки

Ошибка 1. Hook Дублирует Prompt, Но Не Enforce'ит

Плохо:

text
BeforeCommit hook prints:
"Remember to run tests."

Это reminder, а не hook.

Лучше:

text
BeforeCommit hook runs tests and fails on non-zero exit.

Ошибка 2. Hook Слишком Медленный

Плохо:

text
AfterEdit runs full e2e suite.

Последствие:

  • feedback слишком дорогой;
  • agents and humans avoid the hook;
  • iteration slows down;
  • hook воспринимается как препятствие.

Лучше:

text
AfterEdit: format.
BeforeCommit: targeted tests.
CI/BeforeDeploy: full suite.

Ошибка 3. Hook Делает Semantic Changes

Плохо:

text
Hook rewrites API behavior to match tests.

Это implementation, не hook.

Лучше:

text
Hook reports mismatch and blocks transition.
Agent or human decides fix.

Ошибка 4. Hook Скрывает Failure

Плохо:

text
npm test || true

Такой hook создает ложную безопасность.

Лучше:

text
npm test

И если failure allowed, он должен быть explicit:

text
Known flaky test:
- name:
- owner:
- issue:
- expiration date:
- approval:

Ошибка 5. Hooks Отличаются Локально И В CI

Плохо:

text
Local hook runs lint.
CI runs different lint config and fails later.

Лучше:

text
Both local hook and CI call the same repo script.

Например:

text
./scripts/verify

Ошибка 6. Hook Требует Too Much Context

Если hook должен читать длинные docs, интерпретировать product requirements и выбирать architecture, это уже не hook.

Hook должен проверять narrow, executable condition.

Ошибка 7. No Owner

Hook может сломаться после upgrade toolchain.

Если никто не владеет hook:

  • failure начинают игнорировать;
  • команды устаревают;
  • false positives копятся;
  • agents получают contradictory instructions.

У каждого важного hook должен быть owner.

Практика

Спроектируйте hooks для demo repo или capstone feature.

Заполните шаблон:

text
Repository type:

Main languages/frameworks:

Critical workflows:
- edit:
- commit:
- push:
- deploy:

AfterEdit hooks:
1.
2.
3.

BeforeCommit hooks:
1.
2.
3.

BeforeDeploy hooks:
1.
2.
3.

scripts/verify:
- command:
- fast checks:
- full checks:
- security checks:

Failure behavior:
- formatter failure:
- lint failure:
- test failure:
- secret scan failure:
- deploy check failure:

Human approval points:
- dependency upgrade:
- migration:
- deploy:
- security override:

Evidence in agent report:
- command:
- result:
- not-run checks:
- known risks:

Минимальный хороший результат:

text
[ ] Есть AfterEdit hook для mechanical cleanup.
[ ] Есть BeforeCommit hook для локальной проверки.
[ ] Есть BeforeDeploy или release gate для risky action.
[ ] Есть `scripts/verify` как единый вход.
[ ] Failure behavior описан.
[ ] Агент знает, как report'ить hook evidence.
[ ] Slow checks не запускаются слишком рано.
[ ] High-risk failures не fail open без approval.

Мини-Задание: Перевести Prompt Rules В Hooks

Возьмите 5 prompt rules:

text
1. Always format code before final response.
2. Always run tests before commit.
3. Never commit secrets.
4. Validate prompt files after editing them.
5. Check docs links before release.

Переведите их:

Prompt rule Hook
Always format code before final response. AfterEdit formatter или BeforeCommit format check.
Always run tests before commit. BeforeCommit runs ./scripts/verify --changed.
Never commit secrets. BeforeCommit secret scan blocks commit.
Validate prompt files after editing them. AfterEdit/BeforeCommit prompt schema validation.
Check docs links before release. BeforeRelease link checker.

После этого спросите:

  • что должно fail closed;
  • что может быть warning;
  • где нужен human approval;
  • какой script будет единым entry point;
  • какую evidence агент должен показать reviewer'у.

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

Hook - это deterministic automation вокруг agent workflow. Он запускается по событию, выполняет command, возвращает result и помогает решить, можно ли переходить к следующему stage.

Главный принцип:

text
Do not ask the model to remember what the system can enforce.

Hooks особенно полезны для:

  • formatting;
  • lint;
  • typecheck;
  • tests;
  • secret scan;
  • generated files;
  • docs checks;
  • prompt/skill validation;
  • deploy readiness checks.

Но hooks не заменяют judgement. Они не должны принимать product decisions, менять scope, скрывать failures или deploy'ить без approval. Хороший hook делает workflow более предсказуемым: cheap checks run early, expensive checks run at gates, failed checks stop the transition, evidence попадает в handoff.

Для курса ключевой artifact:

text
./scripts/verify

Это executable contract между человеком, агентом и CI.

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

  1. Чем hook отличается от prompt instruction?
  2. Почему scripts/verify полезен именно для AI-assisted development?
  3. Какие проверки подходят для AfterEdit, а какие лучше оставить для BeforeCommit или CI?
  4. Что должен сделать агент, если BeforeCommit hook failed?
  5. Почему hook не должен автоматически принимать security или deploy decisions?

Что дальше

В следующем уроке мы разберем guardrails: branch protection, tool permissions, CI gates, approval gates и другие hard constraints. Hooks запускают автоматизацию в нужный момент. Guardrails задают границы, через которые workflow не должен проходить без выполнения правил или явного human approval.

Обновлено 03.10.2026