Claude Code subagent imported from yaremenko-maksym/CheekyCheeseIT_CRM (
.claude/agents/pm-snippets.md). Copyright stays with the author.
PM Snippets — On-Demand Reference
Готовые сниппеты для диспетча агентов, проверки PR, прогона CI и User Testing.
PM не читает этот файл upfront — обращается через локальный skill pm-dispatching когда реально нужен сниппет.
Диспетч агентов
P0 — обязательная строка в КАЖДОМ dispatch-промпте write/test-агента (Coder / AutoTest / Manual QA / Designer / DevOps):
P0 запрет фоновых ожиданий: у субагента НЕТ уведомлений — завершение хода убивает фоновые процессы.
Долгие прогоны (тесты/билд) — ОДНОЙ foreground Bash-командой с timeout до 600000 мс;
при нехватке — чанковать по файлам/шардам. Перед прогоном — kill своих осиротевших dev-портов. Dev-стек/сервер в worktree поднимать ТОЛЬКО через scripts/devops/dev-ttl.sh -- <команда> (TTL-самоликвидация 4ч; голый nest/vite/pnpm dev заблокирован хуком pre:bash:devserver-ttl-gate); перед бутом проверь порт: lsof -ti tcp:<PORT> | xargs kill -9.
Причина: рецидив 4× за 2026-07-12/13 — агент запускал E2E/vitest в фоне и завершал ход «подожду уведомления»; фон умирал вместе с ходом, спеки оставались незакоммиченными, dev-порты сиротели (lessons autotest #subagent-lifecycle). Шаблоны ниже уже содержат эту строку — при написании ad-hoc промпта добавить вручную.
P0 — изоляция (ошибка ДИСПЕТЧЕРА, не агента). Правило:
.claude/rules/common/agent-isolation.md. Гейт: хук pre:agent:dispatch-isolation.
- Пишущий агент (
coder/autotest/devops/ui-ux-designer/manual-qa/legal/pm/architect) — всегдаisolation="worktree"(или явныйcwd=). Без этого он унаследует рабочий каталог оркестратора и будет коммитить/переключать ветки в общем чекауте (PR #497, раунды 2–3: кодер перевёл каталог сессии наfeature/resume-base).cdвнутри промпта не спасает: рабочий каталог сбрасывается на каталог сессии между вызовами Bash. - Read-only агент (
code-reviewer/security-reviewer/copy-reviewer/Explore/Plan/ фан-аутcodebase-audit) — изоляция не нужна и не навязывается: лишний worktree стоит дисковых операций, а diff читается черезgh/ GitHub MCP. - Рабочий каталог НИКОГДА не задаётся в промпте общим абсолютным путём
(
/tmp/rev<PR>и подобные): номер PR одинаков для всех ревьюеров этого PR, и на PR #493 два ревьюера так и оказались в одном каталоге — чужая правка попала в замеры как свойство кода. Каталог агент выводит из своего идентификатора сам. - Обязательная строка в КАЖДОМ dispatch-промпте пишущего агента (шаблоны ниже её уже содержат; в ad-hoc промпт — добавить вручную):
Изоляция: работай ТОЛЬКО внутри своего worktree. Первой командой выполни
git rev-parse --show-toplevel и сверь с выданным путём. Не совпало или worktree
исчез — ОСТАНОВИСЬ и сообщи, не продолжай в том каталоге, куда тебя выбросило.
Все Edit/Write — относительными путями внутри worktree; по абсолютным путям в
главный чекаут не писать. Чужие worktree не удалять, процессы гасить только свои
по PID (lsof -ti tcp:<порт> → kill <PID>), pkill -f / killall запрещены.
В финальном отчёте — строка: Worktree: <path> (verified).
Проверка после КАЖДОГО завершившегося пишущего агента (второй эшелон на случай,
если хук не отработал — см. agent-isolation.md «Как узнаем, что нарушено»):
git -C <main-repo> status --porcelain apps/ packages/ # пусто = OK
git -C <main-repo> branch --show-current # должен быть main
Отчёт агента без строки Worktree: … (verified) = сверка не сделана → вернуть на
доработку, как за отсутствующий вердикт.
Coder — новая фича
Agent(
isolation="worktree",
description="Coder: task-<slug>",
prompt="""Ты — Coder-агент для CRM Cheeky Cheese IT.
Прочитай .claude/agents/coder.md — системный промпт (golden rules + workflow + recovery).
Прочитай .claude/RULES.md — cross-agent rules (MCP, git, skills, zone-of-write).
Прочитай .claude/agents/project-state.md — фазы / миграции / RBAC / shared schemas / технические gotchas.
Прочитай .claude/agents/memory/coder/lessons.md — накопленные уроки.
Task-файл: .claude/tasks/task-<slug>.md
Repo: yaremenko-maksym/CheekyCheeseIT_CRM
P0 запрет фоновых ожиданий: у субагента НЕТ уведомлений — завершение хода убивает фоновые процессы. Долгие прогоны (тесты/билд) — ОДНОЙ foreground Bash-командой с timeout до 600000 мс; при нехватке — чанковать по файлам/шардам. Перед прогоном — kill своих осиротевших dev-портов. Dev-стек/сервер в worktree поднимать ТОЛЬКО через scripts/devops/dev-ttl.sh -- <команда> (TTL-самоликвидация 4ч; голый nest/vite/pnpm dev заблокирован хуком pre:bash:devserver-ttl-gate); перед бутом проверь порт: lsof -ti tcp:<PORT> | xargs kill -9."""
)
Phase 3d.2 (ECC): PM dispatches только Coder shell. Coder сам инвоукает ECC sub-agents в своём workflow:
- §1.5 —
tdd-guide(TDD план для новой фичи) - §2.5 —
typescript-reviewer(self-review TS/TSX ДО push)
PM не передаёт дополнительные prompts для sub-agents — Coder читает свою же coder.md.
Coder — фикс в существующую ветку
Agent(
isolation="worktree",
description="Coder: fix-<slug>",
prompt="""Ты — Coder-агент. Прочитай .claude/agents/coder.md (golden rules + recovery).
Прочитай .claude/RULES.md (cross-agent rules).
Прочитай .claude/agents/project-state.md (фазы / миграции / gotchas).
Прочитай .claude/agents/memory/coder/lessons.md.
Task: .claude/tasks/task-fix-<slug>.md
target_branch: <pr_branch>
Ветка уже существует — переключись: git checkout <pr_branch>
Изоляция: работай ТОЛЬКО внутри своего worktree. Первой командой — git rev-parse --show-toplevel,
сверь с выданным путём; не совпало или worktree исчез — ОСТАНОВИСЬ и сообщи. Чужие worktree не
удалять; процессы гасить только свои по PID (pkill -f / killall запрещены). В отчёте — строка
Worktree: <path> (verified).
Находки ревью (перенесены ПОЛНЫМ списком, включая те, что решено не делать):
CR-H-1 — <кратко>
CR-H-2 — <кратко>
CR-M-1 — <кратко>
SR-H-1 — <кратко>
Отчитайся по КАЖДОМУ идентификатору отдельной строкой, включая отказы:
CR-H-1 done — <что сделано> / CR-M-1 not done — <почему>
Пропуск строки = незакрытая находка (PR #504: потеряна находка безопасности при переносе).
Правило: .claude/rules/common/review-findings-transfer.md
P0 запрет фоновых ожиданий: у субагента НЕТ уведомлений — завершение хода убивает фоновые процессы. Долгие прогоны (тесты/билд) — ОДНОЙ foreground Bash-командой с timeout до 600000 мс; при нехватке — чанковать по файлам/шардам. Перед прогоном — kill своих осиротевших dev-портов. Dev-стек/сервер в worktree поднимать ТОЛЬКО через scripts/devops/dev-ttl.sh -- <команда> (TTL-самоликвидация 4ч; голый nest/vite/pnpm dev заблокирован хуком pre:bash:devserver-ttl-gate); перед бутом проверь порт: lsof -ti tcp:<PORT> | xargs kill -9."""
)
Phase 3d.2 (ECC) — для bugfix: tdd-guide НЕ диспатчится (это для новых фич). Coder использует superpowers:systematic-debugging skill (см. coder.md §1.5). typescript-reviewer self-review остаётся обязательным для milestones с TS/TSX изменениями.
Design-gate — UI-задача (артефакт ПЕРЕД кодером)
Источник: .claude/rules/common/design-gate.md. Применяется к любой задаче, чей diff трогает
визуальную поверхность apps/web/** / apps/landing/**.
PM-гейт перед диспетчем UI-кодера:
- Определи
## Design tier:задачи (1 новый экран / 2 правка / 3 косметика). Если поля нет на UI-задаче — дефолт Tier 1. - Tier 1/2: убедись, что существует артефакт
docs/design/<slug>.md(+docs/design/assets/<slug>/design.png). Нет артефакта → СНАЧАЛА запусти дизайн-флоу (skillclaude-design-workflow→ ui-ux-designer Mode E), и только потом диспатчи кодера. НЕ диспатчить UI-кодера без артефакта. - Tier 3: артефакт не нужен, но запиши conformance-отметку (ui-ux-designer проверил соответствие синхронизированной дизайн-системе) — в task-файле / pr-state.
Dispatch-промпт UI-кодера ОБЯЗАН содержать (Tier 1/2):
Design tier: <1|2>
Design артефакт: docs/design/<slug>.md (spec) + docs/design/assets/<slug>/design.png (референс)
Правило: строй НАШИМИ shadcn/ui компонентами + токенами globals.css по spec; соответствуй design.png;
НЕ вставляй сырой экспортированный HTML из design.html (это визуальный референс, не код).
После реализации задача уйдёт на ui-ux-designer Mode B fidelity-аудит (live vs design.png).
После пуша UI-кодера: диспатчи ui-ux-designer Mode B (fidelity-аудит vs design.png) параллельно
с code-reviewer. code-reviewer выдаст Verdict: BLOCK, если на apps/web/apps/landing PR нет
дизайн-артефакта + Mode B-аудита (tier ≠ 3). merge-approved ставит ТОЛЬКО PM/owner по «мерджим».
AutoTest — post-approval тесты
Agent(
description="AutoTest: PR #<N>",
prompt="""Ты — AutoTest-агент. Прочитай .claude/agents/autotest.md (golden rules + 3 режима).
Прочитай .claude/RULES.md (cross-agent rules).
Прочитай .claude/agents/project-state.md (RBAC / seed users).
Прочитай .claude/agents/memory/autotest/lessons.md.
PR для анализа: #<N>, repo: yaremenko-maksym/CheekyCheeseIT_CRM.
Режим 1: Post-approval — написать E2E тесты для новых AC.
P0 запрет фоновых ожиданий: у субагента НЕТ уведомлений — завершение хода убивает фоновые процессы. Долгие прогоны (E2E/vitest) — ОДНОЙ foreground Bash-командой с timeout до 600000 мс; при нехватке — чанковать по spec-файлам/шардам. Перед прогоном — kill своих осиротевших dev-портов. Dev-стек/сервер в worktree поднимать ТОЛЬКО через scripts/devops/dev-ttl.sh -- <команда> (TTL-самоликвидация 4ч; голый nest/vite/pnpm dev заблокирован хуком pre:bash:devserver-ttl-gate); перед бутом проверь порт: lsof -ti tcp:<PORT> | xargs kill -9."""
)
AutoTest — фикс упавшего E2E
Agent(
isolation="worktree",
description="AutoTest: fix-e2e-<slug>",
prompt="""Ты — AutoTest-агент. Прочитай .claude/agents/autotest.md.
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/autotest/lessons.md.
Task: .claude/tasks/task-fix-e2e-<slug>.md
target_branch: <pr_branch>
Ветка: git checkout <pr_branch>
P0 запрет фоновых ожиданий: у субагента НЕТ уведомлений — завершение хода убивает фоновые процессы. Долгие прогоны (E2E/vitest) — ОДНОЙ foreground Bash-командой с timeout до 600000 мс; при нехватке — чанковать по spec-файлам/шардам. Перед прогоном — kill своих осиротевших dev-портов. Dev-стек/сервер в worktree поднимать ТОЛЬКО через scripts/devops/dev-ttl.sh -- <команда> (TTL-самоликвидация 4ч; голый nest/vite/pnpm dev заблокирован хуком pre:bash:devserver-ttl-gate); перед бутом проверь порт: lsof -ti tcp:<PORT> | xargs kill -9."""
)
UI/UX Designer — Mode A (pre-feature design direction)
Trigger: BA brief описывает UI-heavy фичу (новый экран / поток / dashboard). Diпатчится в начале Mode 1 ДО Coder. Output → docs/design/<slug>.md spec.
Agent(
subagent_type="ui-ux-designer",
isolation="worktree",
description="Designer Mode A: <slug>",
prompt="""Ты — UI/UX Designer агент. Прочитай .claude/agents/ui-ux-designer.md (golden rules + 4 mode workflow + zone-of-write).
Прочитай .claude/RULES.md (cross-agent rules).
Прочитай .claude/agents/project-state.md (RBAC матрица / design system overview §8 / фазы).
Прочитай .claude/agents/memory/ui-ux-designer/lessons.md.
Прочитай docs/business/modules/<модуль>.md + docs/business/user-flows.md.
Mode: A — Design Direction (pre-feature)
Brief: .claude/briefs/pm-brief-<slug>.md (или task: .claude/tasks/task-design-<slug>.md)
Output: docs/design/<slug>.md
Invoke skills: frontend-design-direction → design-system (если нужны новые tokens) → accessibility (critical paths).
Spec должен содержать: Purpose / Audience / Tone / Memorable detail / Constraints / Component list / Token map / Motion spec / A11y critical paths / Edge cases.
P0 запрет фоновых ожиданий: у субагента НЕТ уведомлений — завершение хода убивает фоновые процессы. Долгие прогоны (тесты/билд) — ОДНОЙ foreground Bash-командой с timeout до 600000 мс; при нехватке — чанковать по файлам/шардам. Перед прогоном — kill своих осиротевших dev-портов. Dev-стек/сервер в worktree поднимать ТОЛЬКО через scripts/devops/dev-ttl.sh -- <команда> (TTL-самоликвидация 4ч; голый nest/vite/pnpm dev заблокирован хуком pre:bash:devserver-ttl-gate); перед бутом проверь порт: lsof -ti tcp:<PORT> | xargs kill -9."""
)
UI/UX Designer — Mode B (visual audit, post-impl, параллельно с code-reviewer)
Trigger: PR трогает apps/web/**. Дispatch'ится параллельно с code-reviewer + Manual QA + (опц.) security-reviewer.
Agent(
subagent_type="ui-ux-designer",
description="Designer Mode B: PR #<N>",
prompt="""Ты — UI/UX Designer агент. Прочитай .claude/agents/ui-ux-designer.md.
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/ui-ux-designer/lessons.md.
Mode: B — Visual Audit (post-impl)
PR: #<N>, repo: yaremenko-maksym/CheekyCheeseIT_CRM
target_branch: <pr_branch>
Invoke skills: design-system (Mode 2 10-dim audit + Mode 3 AI-slop) → make-interfaces-feel-better → accessibility (spot-check WCAG SC 2.4.11 / 2.5.8 / 1.4.3).
Pоsтить PR comment через mcp__github__add_issue_comment с первой строкой `Design Review: PASS|POLISH-REQUESTED|BLOCK`.
Mode D — если нашёл LOW/MED cosmetic в зоне apps/web/** — пофикси сам + re-verify скриншотом + push в ту же ветку.
P0 запрет фоновых ожиданий: у субагента НЕТ уведомлений — завершение хода убивает фоновые процессы. Долгие прогоны (тесты/билд) — ОДНОЙ foreground Bash-командой с timeout до 600000 мс; при нехватке — чанковать по файлам/шардам. Перед прогоном — kill своих осиротевших dev-портов. Dev-стек/сервер в worktree поднимать ТОЛЬКО через scripts/devops/dev-ttl.sh -- <команда> (TTL-самоликвидация 4ч; голый nest/vite/pnpm dev заблокирован хуком pre:bash:devserver-ttl-gate); перед бутом проверь порт: lsof -ti tcp:<PORT> | xargs kill -9.""",
run_in_background=True
)
Aggregate verdict logic (Mode 2): Designer Mode B даёт event designer_review_done с verdict PASS|POLISH-REQUESTED|BLOCK. PM объединяет с code-reviewer / security-reviewer / Manual QA verdict'ами (все 4 PASS → awaiting-pm-review; хотя бы один BLOCK → do-not-merge).
Fallback (до cache refresh): subagent_type: claude + inline-системный промпт из ui-ux-designer.md.
Manual QA — pre-merge visual / functional check
Phase 7 (2026-06-04): Manual QA добавлен как полноценный subagent type. Диспатчится параллельно с code-reviewer когда PR трогает UI surface (см. contracts.md §5.1). Скорее «дополнение» к AutoTest, а не замена: AutoTest пишет .spec.ts с mocks; Manual QA интерактивно гоняет РЕАЛЬНЫЙ UI на живом стеке.
Agent(
subagent_type="manual-qa",
isolation="worktree",
description="Manual QA: PR #<N>",
prompt="""Ты — Manual QA агент. Прочитай .claude/agents/manual-qa.md (golden rules + workflow + zone-of-write).
Прочитай .claude/RULES.md (cross-agent rules).
Прочитай .claude/agents/project-state.md (RBAC матрица / seed users / phases).
Прочитай .claude/agents/memory/manual-qa/lessons.md.
PR для visual QA: #<N>, repo: yaremenko-maksym/CheekyCheeseIT_CRM
target_branch: <pr_branch>
Список фич для проверки (golden path + edge cases + RBAC):
<bullet-list-of-features-from-task-or-PR-description>
Mode: <pr-final-visual | download-verify | rbac-verify | complement-e2e>
Зона фиксов: cosmetic UI в apps/web/** (apply + re-verify скриншотом).
Backend / функциональные баги — отчёт PM с severity (CRITICAL/HIGH/MED/LOW) + repro + скриншот.
P0 запрет фоновых ожиданий: у субагента НЕТ уведомлений — завершение хода убивает фоновые процессы. Долгие прогоны (тесты/билд/стек) — ОДНОЙ foreground Bash-командой с timeout до 600000 мс; при нехватке — чанковать по файлам/шардам. Перед прогоном — kill своих осиротевших dev-портов. Dev-стек/сервер в worktree поднимать ТОЛЬКО через scripts/devops/dev-ttl.sh -- <команда> (TTL-самоликвидация 4ч; голый nest/vite/pnpm dev заблокирован хуком pre:bash:devserver-ttl-gate); перед бутом проверь порт: lsof -ti tcp:<PORT> | xargs kill -9.""",
run_in_background=True
)
Aggregate verdict logic (Mode 2): Manual QA даёт event manual_qa_done в pm-state.json с verdict PASS | ISSUES_FOUND:
PASS→ нет багов, либо нашёл и сам пофиксил cosmetic'ы (push) → переходит кawaiting-pm-review(если Reviewer тоже APPROVE).ISSUES_FOUND(HIGH/CRITICAL) → PM создаётtask-fix-pr-<N>.mdдля Coder ДО merge. MED/LOW можно собрать в follow-up (после merge), но HIGH+ блокируют merge.
Fallback (до PR # merge): если harness ещё не подхватил subagent_type: manual-qa (frontmatter cache), использовать subagent_type: claude + inline-системный промпт из manual-qa.md в bullet'е prompt.
code-reviewer — default code review (любой PR)
Phase 3b split: sonnet, default на каждый PR с product-code changes. Зона: TypeScript strict / ESLint / arch patterns / zone-of-write / write-then-post / Verdict: BLOCK first-line. Использует mcp__eslint__lint-files ДО review и Pre-Report Gate (HIGH→body / MED→warnings / LOW→summary-only).
Agent(
description="code-reviewer: PR #<N>",
prompt="""Ты — code-reviewer агент. Прочитай .claude/agents/code-reviewer.md (golden rules + write-then-post + Pre-Report Gate).
Прочитай .claude/RULES.md (zero-tolerance patterns).
Прочитай .claude/agents/project-state.md (canonical architecture / version pins / RBAC).
Прочитай .claude/agents/memory/reviewer/lessons.md (legacy общий с security-reviewer до Phase 4 split).
PR для review: #<N>, repo: yaremenko-maksym/CheekyCheeseIT_CRM
Рабочий каталог: НЕ задан намеренно. Diff читай через gh / GitHub MCP — worktree тебе не нужен.
Если понадобится ЗАПУСТИТЬ / замерить / откатить код — сделай СВОЙ чекаут по пути из
СВОЕГО идентификатора (scratchpad сессии), НЕ из номера PR и НЕ в чужом дереве:
SHA=$(gh pr view <N> --json headRefOid --jq .headRefOid)
git worktree add --detach "$SCRATCH/checkout" "$SHA"
До замеров: git -C "$SCRATCH/checkout" status --porcelain (пусто) + rev-parse HEAD (== SHA).
Закончил — git worktree remove "$SCRATCH/checkout". Чужие worktree не трогать.
В теле review — строка Checkout: <path> @ <sha> (clean). См. skill code-review-discipline §6.
Находки нумеруй: CR-H-1 / CR-M-2 / …, в конце контрольная строка Findings: <ids> (N) — §7.
Sensitive paths flag: <none|list> # PM передаёт если задеты critical-path zones — это сигнал что security-reviewer диспатчится параллельно""",
run_in_background=True
)
При aggregate-verdict logic — code-reviewer всегда даёт code_review_done event с verdict APPROVE/BLOCK. См. pm.md Mode 2 "Aggregate verdict logic".
security-reviewer — для critical-path PR (auth/finance/USDT/wallets)
Phase 3b split: opus, диспатчится параллельно с code-reviewer когда PR трогает critical-path trigger zones (см. pm.md §"Critical-path trigger zones" — единый DRY-список). Зона: OWASP Top 10 / npm audit / secrets detection / USDT-ETH patterns / write-then-post / Verdict: BLOCK first-line.
Agent(
description="security-reviewer: PR #<N>",
prompt="""Ты — security-reviewer агент. Прочитай .claude/agents/security-reviewer.md (golden rules + OWASP чеклист + write-then-post + Pre-Report Gate).
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md (RBAC матрица / shared schemas / auth flow).
Прочитай .claude/agents/memory/reviewer/lessons.md (legacy общий с code-reviewer до Phase 4 split).
PR для security review: #<N>, repo: yaremenko-maksym/CheekyCheeseIT_CRM
Рабочий каталог: НЕ задан намеренно (worktree тебе не нужен — diff через gh / GitHub MCP).
Нужен запуск / замер / откат — СВОЙ чекаут из СВОЕГО идентификатора, не из номера PR:
SHA=$(gh pr view <N> --json headRefOid --jq .headRefOid)
git worktree add --detach "$SCRATCH/checkout" "$SHA"
До замеров: status --porcelain пусто + rev-parse HEAD == SHA. После — worktree remove.
Code-reviewer работает параллельно в СВОЁМ каталоге: его дерево не трогать, своё не отдавать
(PR #493 — общий каталог, чужая правка попала в замеры как свойство кода).
В теле review — строка Checkout: <path> @ <sha> (clean). См. skill code-review-discipline §6.
Находки нумеруй: SR-H-1 / SR-M-2 / …, в конце контрольная строка Findings: <ids> (N) — §7.
Sensitive paths которые тригернули dispatch: <list, e.g. apps/api/src/finance/**, packages/shared/src/schemas/finance.ts>
Code-reviewer параллельно — не дублируй его code/lint checks.""",
run_in_background=True
)
При aggregate-verdict logic — security-reviewer даёт security_review_done event с verdict APPROVE/BLOCK. PM объединяет с code-reviewer verdict (см. pm.md Mode 2).
DevOps — инфра-задача
Agent(
isolation="worktree",
description="DevOps: task-infra-<slug>",
prompt="""Ты — DevOps-агент. Прочитай .claude/agents/devops.md (golden rules + workflow).
Прочитай .claude/RULES.md (version pins / git / skills).
Прочитай .claude/agents/project-state.md (CI/CD pipeline актуальный — §11).
Прочитай .claude/agents/memory/devops/lessons.md.
Task: .claude/tasks/task-infra-<slug>.md"""
)
Параллельный запуск (Coder + DevOps)
В одном сообщении — оба Agent вызова с run_in_background=True:
Agent(isolation="worktree", run_in_background=True, description="Coder: task-<slug>", prompt="...")
Agent(isolation="worktree", run_in_background=True, description="DevOps: task-infra-<slug>", prompt="...")
Legal — Mode A (on-demand consult)
Agent(
description="Legal: consult-<slug>",
prompt="""Ты — Legal-агент. Прочитай .claude/agents/legal.md (golden rules + 4 modes).
Прочитай .claude/agents/CLAUDE-legal.md.
Прочитай .claude/RULES.md (cross-agent rules).
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/legal/lessons.md.
Прочитай .claude/knowledge/legal/cross-cutting/escalation-zones.md.
Прочитай .claude/knowledge/legal/cross-cutting/citation-rules.md.
mode: consult
Task: .claude/tasks/task-legal-<slug>.md
Append `## Ответ юриста` в task-файл по структуре из legal.md.
После завершения верни PM summary: Confidence + TL;DR."""
)
Legal — Mode B (auto PR review, critical zones)
Agent(
description="Legal: pr-review-<N>",
prompt="""Ты — Legal-агент. Прочитай .claude/agents/legal.md.
Прочитай .claude/agents/CLAUDE-legal.md.
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/legal/lessons.md.
Прочитай .claude/knowledge/legal/cross-cutting/escalation-zones.md.
Прочитай .claude/knowledge/legal/cross-cutting/citation-rules.md.
mode: pr-review
pr_number: <N>
repo: yaremenko-maksym/CheekyCheeseIT_CRM
Используй write-then-post pattern (CLAUDE-legal.md секция).
Постить с event: COMMENT (НЕ APPROVE / REQUEST_CHANGES).
Первая строка body: `Legal Review: <CONFIDENCE>`.
Добавь label `legal-noted` на PR через gh."""
)
Legal — Mode C (pre-feature brief check)
Agent(
description="Legal: brief-check",
prompt="""Ты — Legal-агент. Прочитай .claude/agents/legal.md.
Прочитай .claude/agents/CLAUDE-legal.md.
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/legal/lessons.md.
Прочитай .claude/knowledge/legal/cross-cutting/escalation-zones.md.
Прочитай .claude/knowledge/legal/cross-cutting/citation-rules.md.
mode: brief-check
brief_file: .claude/briefs/pm-brief-<slug>.md
Идентифицируй legal touchpoints в brief. Вывод — `.claude/briefs/pm-brief-legal-check.md` с акцентом на Recommendations для AC."""
)
Legal — Mode D (strategic advisor, direct user question)
Agent(
description="Legal: strategic-<slug>",
prompt="""Ты — Legal-агент. Прочитай .claude/agents/legal.md.
Прочитай .claude/agents/CLAUDE-legal.md.
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/legal/lessons.md.
Прочитай .claude/knowledge/legal/cross-cutting/escalation-zones.md.
Прочитай .claude/knowledge/legal/cross-cutting/citation-rules.md.
mode: strategic
consultation_file: .claude/knowledge/legal-consultations/<YYYY-MM-DD-slug>.md
Append `## Ответ юриста` в consultation-файл по структуре из legal.md.
После завершения верни PM summary для отправки USER в чат: Confidence + TL;DR + 1-2 ключевые recommendation."""
)
Параллельный запуск code-reviewer + security-reviewer + Legal (critical-path PR)
Триггер: PR трогает любой путь из pm.md §"Critical-path trigger zones" (auth/finance/transactions/payouts/wallets/documents/users + соответствующие shared schemas + package.json/lockfile + contracts/**).
Все три агента параллельно — один dispatch message, все run_in_background=True:
# code-reviewer (sonnet) — default reviewer
Agent(
description="code-reviewer: PR #<N>",
prompt="""Ты — code-reviewer. Прочитай .claude/agents/code-reviewer.md.
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/reviewer/lessons.md.
PR для review: #<N>, repo: yaremenko-maksym/CheekyCheeseIT_CRM
Sensitive paths flag: <list> # security-reviewer параллельно""",
run_in_background=True
)
# security-reviewer (opus) — обязателен для critical-path
Agent(
description="security-reviewer: PR #<N>",
prompt="""Ты — security-reviewer. Прочитай .claude/agents/security-reviewer.md.
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/reviewer/lessons.md.
PR: #<N>, repo: yaremenko-maksym/CheekyCheeseIT_CRM
Triggered paths: <list>
Code-reviewer параллельно — не дублируй его проверки.""",
run_in_background=True
)
# Legal Mode B (info-only) — диспатчится по тому же DRY-списку trigger paths
Agent(
description="Legal: pr-review-<N>",
prompt="""Ты — Legal-агент. Прочитай .claude/agents/legal.md.
Прочитай .claude/agents/CLAUDE-legal.md.
Прочитай .claude/RULES.md.
Прочитай .claude/agents/project-state.md.
Прочитай .claude/agents/memory/legal/lessons.md.
Прочитай .claude/knowledge/legal/cross-cutting/escalation-zones.md.
Прочитай .claude/knowledge/legal/cross-cutting/citation-rules.md.
mode: pr-review
pr_number: <N>
repo: yaremenko-maksym/CheekyCheeseIT_CRM
Triggered paths: <list>""",
run_in_background=True
)
Verdict aggregation для PM:
- code-reviewer event:
code_review_done(APPROVE | BLOCK) — gate (parsed Verdict: first line). - security-reviewer event:
security_review_done(APPROVE | BLOCK) — gate (parsed Verdict: first line). - Legal event:
legal_review_postedсconfidence— info-only, labellegal-noted, не блокирует merge.
PM ждёт оба review events (code + security) перед принятием решения. Aggregate = BLOCK если любой BLOCK; APPROVE если оба APPROVE. См. pm.md Mode 2 "Aggregate verdict logic".
Параллельный запуск code-reviewer только (без security/Legal — обычный PR)
Для PR который не трогает critical-path zones — диспатчить только code-reviewer:
Agent(description="code-reviewer: PR #<N>", prompt="...", run_in_background=True)
Только code_review_done event ожидается. PM не ждёт security_review_done потому что security-reviewer не диспатчен.
PR и CI команды
Найти PR по ветке
gh pr list --repo yaremenko-maksym/CheekyCheeseIT_CRM \
--head "feature/<slug>" --json number,title --jq '.[0]'
Статус CI на PR
gh pr view <N> --repo yaremenko-maksym/CheekyCheeseIT_CRM \
--json statusCheckRollup --jq '.statusCheckRollup[] | {name, conclusion}'
Или через MCP:
mcp__github__get_pull_request_status({owner: "yaremenko-maksym", repo: "CheekyCheeseIT_CRM", pull_number: <N>})
Лейблы на PR
gh pr view <N> --repo yaremenko-maksym/CheekyCheeseIT_CRM \
--json labels --jq '[.labels[].name]'
Управление лейблами
# Pre-review (code-reviewer выставляет когда code-reviewer APPROVE; security-reviewer ставит security-noted)
gh pr edit <N> --repo yaremenko-maksym/CheekyCheeseIT_CRM --add-label "awaiting-pm-review"
# После User Testing апрува (PM выставляет)
gh pr edit <N> --repo yaremenko-maksym/CheekyCheeseIT_CRM \
--add-label "merge-approved" \
--remove-label "awaiting-pm-review"
# Снять CI-failed после фикса
gh pr edit <N> --repo yaremenko-maksym/CheekyCheeseIT_CRM --remove-label "ci-failed"
Review-комментарии (через MCP, не gh api)
mcp__github__get_pull_request_reviews({owner: "yaremenko-maksym", repo: "CheekyCheeseIT_CRM", pull_number: <N>})
mcp__github__get_pull_request_comments({owner: "yaremenko-maksym", repo: "CheekyCheeseIT_CRM", pull_number: <N>})
User Testing подготовка окружения
Все шаги в одном скрипте — выполнить перед каждым User Testing:
bash scripts/pm/prep-user-testing.sh <pr_branch>
Скрипт делает: git fetch && checkout (auto-detect worktree) → миграции → unit-тесты (api/web/shared, без e2e) → production build (api + web с VITE_API_URL=/api + VITE_DEV_LOGIN=true) → kill prev по PORT → старт API + Vite preview → wait-for-services → Serveo SSH tunnel (ssh -R 80:localhost:3000 serveo.net) → блокирует foreground.
Через tunnel демка отдаётся как production bundle (не dev) — быстрее на мобильнике, без flaky HMR через туннель. URL формат https://<hash>.serveousercontent.com. OAuth через tunnel НЕ работает — использовать Dev Login (email на /login).
Env overrides: SKIP_TUNNEL=1, SKIP_UNIT_TESTS=1, POSTGRES_*.
Если упал — не показывать пользователю, читать /tmp/pm-api.log + /tmp/pm-web.log + Serveo лог → классифицировать (build/DB/tunnel/port-clash) → fix-задача для Coder/DevOps. Troubleshooting — docs/runbooks/user-testing-tunnel.md.
E2E запуск (GHA workflow_dispatch)
# Запустить E2E workflow
gh workflow run e2e.yml --repo yaremenko-maksym/CheekyCheeseIT_CRM
# Последние run'ы
gh run list --repo yaremenko-maksym/CheekyCheeseIT_CRM --workflow=e2e.yml --limit=3
# Статус конкретного run
gh run view <run_id> --repo yaremenko-maksym/CheekyCheeseIT_CRM --json status,conclusion
# Логи провалившегося run
gh run view <run_id> --repo yaremenko-maksym/CheekyCheeseIT_CRM --log-failed
PM ждёт E2E двумя способами — выбрать по длительности:
- Короткий wait (< 30 мин), активная сессия —
ScheduleWakeup(delay=270). Простой harness API, но не выживает session boundary. - Длинный wait или критичный fire —
mcp__scheduled-tasksчерезpm-schedule.sh(см. секцию ниже). Survives session boundary, но stand-up'ит fresh Claude-сессию.
Полная матрица — секция «⚠️ ScheduleWakeup limitations» ниже в этом файле.
⚠️ ScheduleWakeup limitations (D1 [P0])
ScheduleWakeup не выживает session boundary. Real incident: 2026-05-23 PM поставил wake-up на 2 часа, session завершилась → wake-up потерян → PR висел без действия.
PM имеет два слоя для wake-up'ов с разными гарантиями. Выбирать по длительности и критичности.
Layer 1 — ScheduleWakeup (in-session, < 30 минут)
Прямой harness API. Дёшево, быстро, но умирает с сессией.
Используй когда:
- Wait < 30 минут (короткий CI poll)
- Чёткая уверенность что сессия не закроется (active interactive turn)
- Wake-up — нежёсткое требование (если потеряется, USER увидит и перезапустит)
Workaround pattern (если всё-таки используешь Layer 1 для важного wait):
# Перед wake-up — сохрани действие в state, чтобы новая сессия могла catch-up
pm_state["active"][task_idx]["next_action"] = {
"type": "poll_e2e_run",
"run_id": run_id,
"scheduled_at": now_iso(),
"max_age_min": 30
}
ScheduleWakeup(delay=270) # 4.5 мин для GHA E2E
# При старте новой session (Mode 3) — catch-up:
for task in pm_state["active"]:
if next_action := task.get("next_action"):
age_min = (now() - parse_iso(next_action["scheduled_at"])).total_seconds() / 60
if age_min > next_action["max_age_min"]:
handle_next_action(next_action) # missed wake-up — immediate execute
Layer 2 — mcp__scheduled-tasks__* (cross-session, любая длительность)
External scheduler, выживает session boundary. Запускает fresh Claude-сессию на запланированное время с self-contained prompt. Полноценный workaround D1.
Используй когда:
- Wait ≥ 30 минут (длинный CI, GHA E2E, deploy verification)
- Жёсткое требование fire'а (потеря недопустима)
- Длительный wait через session timeout
Workflow (PM шаги):
- Сгенерировать параметры через
pm-schedule.sh:
bash scripts/pm/pm-schedule.sh \
--delay-min 15 \
--task-id-hint poll-e2e-pr42 \
--description "Poll E2E run 26298999300 for PR #42" \
--prompt-template poll-e2e-run \
--prompt-var REPO=yaremenko-maksym/CheekyCheeseIT_CRM \
--prompt-var RUN_ID=26298999300 \
--prompt-var PR=42 \
--state-file .claude/state/pm-state.json \
--state-task-id task-knowledge-api
Это:
- Вычисляет
fireAtв local TZ (BSD/GNU date compat) - Генерит unique
taskId(kebab-case + UTC timestamp suffix) - Материализует self-contained prompt из
scripts/pm/wakeup-prompts/<template>.md - Append event
wakeup_scheduled+next_actionв pm-state.json - Печатает JSON в stdout
- Прочитать materialized prompt:
cat $(jq -r .promptPath <stdout-json>)
- Вызвать MCP-tool прямо из PM-сессии:
mcp__scheduled-tasks__create_scheduled_task({
taskId: "<from JSON>",
description: "<from JSON>",
fireAt: "<from JSON>",
prompt: "<contents of promptPath>"
})
Матрица выбора
| Сценарий | Layer | Почему |
|---|---|---|
pnpm test finishing, ждать unit (~5 мин) |
1 (ScheduleWakeup) | Сессия active, короткий wait |
| GHA E2E workflow (~10-20 мин) | 2 (mcp__scheduled-tasks) | Может пережить session timeout |
| Daily morning check (12 часов) | 2 | Точно cross-session |
| Сразу после dispatch агента, проверить через 2 мин | 1 | Foreground agent уже notify'ит |
| User Testing wait → пользователь даст ответ через ~1ч | 2 | Сессия закроется во time of waiting |
Не комбинируй оба слоя на same wait — это дублирует wake-up'ы и spamит scheduled-tasks store.
Связанная задача: .claude/tasks/task-harness-schedule-wakeup-persistence.md — изначально NEEDS-USER. Layer 2 — полноценный workaround, harness-fix остаётся nice-to-have для unification API.
Cross-session wake-up (mcp__scheduled-tasks через pm-schedule.sh)
Используется для wait'ов которые могут не уложиться в текущую PM-сессию: длинный GHA E2E, deploy verification, daily checks.
Generate parameters + create scheduled task
# 1. Подготовить параметры (вычисляет fireAt, материализует prompt, апдейтит pm-state.json)
JSON=$(bash scripts/pm/pm-schedule.sh \
--delay-min 15 \
--task-id-hint poll-e2e-pr42 \
--description "Poll E2E run 26298999300 for PR #42" \
--prompt-template poll-e2e-run \
--prompt-var REPO=yaremenko-maksym/CheekyCheeseIT_CRM \
--prompt-var RUN_ID=26298999300 \
--prompt-var PR=42 \
--state-file .claude/state/pm-state.json \
--state-task-id task-knowledge-api)
# 2. Извлечь параметры из JSON
TASK_ID=$(echo "$JSON" | jq -r .taskId)
FIRE_AT=$(echo "$JSON" | jq -r .fireAt)
DESCRIPTION=$(echo "$JSON" | jq -r .description)
PROMPT=$(cat "$(echo "$JSON" | jq -r .promptPath)")
Call MCP tool (из PM сессии)
mcp__scheduled-tasks__create_scheduled_task({
taskId: <TASK_ID>,
description: <DESCRIPTION>,
fireAt: <FIRE_AT>,
prompt: <PROMPT>
})
PM получает обратно taskId — это совпадает с next_action.scheduled_task_id в pm-state.json.
Список и управление
mcp__scheduled-tasks__list_scheduled_tasks()
# → возвращает массив с taskId, description, fireAt, enabled, nextRunAt, lastRunAt, path
mcp__scheduled-tasks__update_scheduled_task({
taskId: "<existing>",
enabled: false // disable не удаляя
})
Доступные templates
| Template | Use case | Required vars |
|---|---|---|
poll-e2e-run |
GHA E2E workflow result | REPO, RUN_ID, PR |
poll-pr-checks |
Все CI checks на PR | REPO, PR |
poll-pr-merged |
Verify auto-merge сработал | REPO, PR |
Подробнее — scripts/pm/wakeup-prompts/README.md.
Dry-run (smoke test без реального scheduled task)
bash scripts/pm/pm-schedule.sh \
--delay-min 5 \
--task-id-hint smoke \
--description "test" \
--prompt-template poll-pr-checks \
--prompt-var REPO=yaremenko-maksym/CheekyCheeseIT_CRM \
--prompt-var PR=42 \
--dry-run
# → JSON печатается в stdout, материализованный prompt в /tmp/pm-schedule-<id>.prompt.md,
# pm-state.json НЕ изменяется
Workflow lookups (verification AutoTest не no-op)
# Сколько e2e-файлов изменил PR
gh api repos/yaremenko-maksym/CheekyCheeseIT_CRM/pulls/<N>/files \
--jq '[.[] | select(.filename | startswith("apps/e2e"))] | length'
Если 0 после AutoTest запуска — он не сделал работу (no-op). Создать новый task-файл и перезапустить.
Coder hung — recovery (C1 detection layer)
После dev-flow RCA hook .claude/hooks/post-edit-write-coder-progress.sh пишет activity лог в <main-repo>/.claude/coder-activity.log (gitignored, TSV). PM использует его для detection silent termination.
Лог содержит два типа rows (поле $2):
Edit/Write/MultiEdit/NotebookEdit— auto-hook PostToolUse, что Coder писал. Покрывает «живой ли».INTENT— explicit marker от Coder черезbash scripts/coder/coder-intent.sh "<text>". Покрывает «что планировал». См.coder.mdсекция 8.1.1.
Recovery flow: сначала смотри intents (контекст), потом file activity (progress).
Шаг 1: Latest Coder activity
LOG="$(git rev-parse --git-common-dir 2>/dev/null)/../.claude/coder-activity.log"
LOG=$(cd "$(dirname "$LOG")" && pwd)/$(basename "$LOG") # absolute path
# Семантический контекст — что Coder намеревался делать (intent markers, opt-in)
echo "── Last intents ──────────────────────────────"
awk -F'\t' '$2=="INTENT"' "$LOG" | tail -5
# Прогресс — какие файлы Coder реально писал (auto-hook)
echo "── Last edits ────────────────────────────────"
awk -F'\t' '$2!="INTENT"' "$LOG" | tail -10
Формат строки (5 tab-separated полей): <ISO>\t<type>\t<branch>\t<cwd>\t<file_or_intent>.
Как интерпретировать пару intent+edit:
| Последний INTENT | Последний Edit | Интерпретация |
|---|---|---|
intent: starting test run for auth |
apps/api/.../auth.service.ts |
Coder остановился в момент edit ПОСЛЕ старта tests |
intent: AC #3 implementing |
None после intent | Coder обрывался ДО любого edit — задача на AC #3 не начата |
intent: rebasing onto main |
apps/... без вновь intent |
Rebase завершён, Coder начал работу — обрыв midway |
| (нет INTENT в последнем часу) | apps/... |
Coder не записывал intent — recovery строится только на git state |
Шаг 2: Detect hung
LAST_TS=$(tail -1 "$LOG" | cut -f1)
AGE_SEC=$(( $(date -u +%s) - $(date -u -d "$LAST_TS" +%s 2>/dev/null || date -ujf '%Y-%m-%dT%H:%M:%SZ' "$LAST_TS" +%s) ))
if [ "$AGE_SEC" -gt 600 ]; then
echo "⚠️ Coder последний раз writeл $((AGE_SEC / 60)) мин назад — likely hung"
fi
Шаг 3: Pick worktree from last entry
# Последняя активность ЛЮБОГО типа (INTENT или Edit) — для cwd/branch
LAST_CWD=$(tail -1 "$LOG" | cut -f4)
LAST_BRANCH=$(tail -1 "$LOG" | cut -f3)
echo "Last activity: $LAST_BRANCH в $LAST_CWD"
git -C "$LAST_CWD" log --oneline -5
git -C "$LAST_CWD" status --porcelain
Шаг 4: Recover unpushed work
# Если есть uncommitted
git -C "$LAST_CWD" stash push -u -m "pm-recovery $(date -u +%Y%m%dT%H%M%SZ)"
# Если есть unpushed commits — push to remote (если pre-push hook требует ac_verified,
# либо проверить commit messages, либо использовать --no-verify в emergency).
git -C "$LAST_CWD" log --oneline HEAD..origin/$LAST_BRANCH # обратное направление = unpushed
git -C "$LAST_CWD" push origin "$LAST_BRANCH"
Шаг 5: Записать event
{ "at": "<ISO>", "type": "coder_recovered", "branch": "<branch>", "unpushed_commits": <N>, "stashed": true/false }
Для крупных задач — semantic milestone
Если Coder поддерживал .claude/tasks/<task>.progress.md (см. coder.md секция 8.2):
cat .claude/tasks/<task>.progress.md
# Видишь current_milestone — перезапускаешь Coder с явным "continue from milestone N+1"
Common pitfalls — checklists
После большого UI batch (User Testing → много правок)
После того как Coder завершил массовый UI fix-раунд, ДО объявления PR готовым к мерджу:
- Auto-dispatch AutoTest на specs update — UI tests могут протухнуть от изменений селекторов:
Agent(description="AutoTest: spec-update-PR-<N>", prompt="Ты — AutoTest. Прочитай .claude/agents/autotest.md. PR #<N> содержит UI batch — обнови селекторы в apps/e2e/tests/<module>.spec.ts target_branch: <pr_branch>") - Ожидать E2E rebuild — после AutoTest push CI re-run; ждать второго зелёного раунда:
gh pr view <N> --repo yaremenko-maksym/CheekyCheeseIT_CRM \ --json statusCheckRollup --jq '.statusCheckRollup' - НЕ диспетчить merge-approved до второго зелёного CI. Первый раунд мог быть до AutoTest update — нужен второй чтобы проверить что новые тесты тоже зелёные.
- Записать в pm-state.json event
autotest_post_ui_batchс PR номером — это маркер «UI rounds потребовали re-test».
После migration rebuild (Drizzle schema change)
После того как Coder сделал миграцию, до User Testing:
-
Создать DevOps task на
__drizzle_migrationssync если миграции были созданы вручную или переименованы:# task-infra-migrations-sync ## Агент: devops ## Контекст В PR #<N> добавлена/изменена миграция. Проверить что `__drizzle_migrations` table sync с `drizzle/migrations/meta/_journal.json` — иначе db:migrate упадёт на fresh DB. ## AC - [ ] `pnpm --filter @crm/api db:init-tracking` синхронизирует state - [ ] Smoke test: `docker-compose down -v && docker-compose up -d && pnpm db:migrate && pnpm db:seed` проходит без ошибок -
Smoke test fresh-DB flow до User Testing — если миграции не применяются на чистой БД, User Testing будет видеть данные но fresh deploy сломается.
-
Записать в pm-state.json event
migration_rebuild_requiredс PR номером.
Типичные длительности агентов
| Тип задачи | Ожидаемое время |
|---|---|
| Coder: 1-2 файла | 8-12 мин |
| Coder: модуль (3-6 файлов) | 15-25 мин |
| Coder: большой модуль (7+) | 25-40 мин |
| AutoTest: написание/обновление тестов | 8-15 мин |
| code-reviewer: code review (small/medium PR) | 5-10 мин |
| code-reviewer: large PR (>500 LOC) | 10-15 мин |
| security-reviewer: small PR (auth/finance touch) | 8-12 мин |
| security-reviewer: large PR + npm audit + WebSearch CVE | 15-25 мин |
| DevOps: workflow изменения | 5-10 мин |
| E2E через e2e.yml (GHA) | 10-20 мин — использовать ScheduleWakeup(delay=270) или Layer 2 |
| Legal: Mode A consult (static база покрывает) | 5-8 мин |
| Legal: Mode A consult (нужен WebSearch) | 10-15 мин |
| Legal: Mode B pr-review (small PR) | 8-12 мин |
| Legal: Mode B pr-review (large finance/auth + S3) | 15-25 мин |
| Legal: Mode C brief-check | 8-12 мин |
| Legal: Mode D strategic (deep question) | 10-20 мин |
Foreground агенты блокируют PM до завершения — результат приходит сразу.
Background агенты (run_in_background=True) — PM получает уведомление автоматически.
Именование веток
feature/<slug>— новая фича (Coder)test/<slug>— тесты (AutoTest standalone)infra/<slug>— инфраструктура (DevOps)fix/<slug>— фикс бага или E2E
Структура .claude/tasks/
.claude/tasks/
├── task-<slug>.md # активная задача
├── task-<slug>.blocked.md # блокер от агента
├── task-<slug>.progress.md # sentinel Coder для крупных задач (>4 файлов)
└── templates/
└── task.md.tpl
Правила именования task-файлов
- Новая фича:
task-<module>-<aspect>.md(task-knowledge-api.md) - Фикс от reviewer (code-reviewer / security-reviewer / оба):
task-fix-pr-<N>.md - Фикс E2E:
task-fix-e2e-<slug>.md - Фикс теста:
task-fix-test-<slug>.md - Фикс от user testing:
task-fix-<short-description>.md
pm-state.json schema v2
Файл локальный, gitignored. PM пишет и читает между сессиями. Формат поддерживает события и метрики.
{
"feature": "Knowledge Base",
"brief": ".claude/briefs/pm-brief-<slug>.md",
"started_at": "2026-05-18T10:00:00Z",
"phase": "development",
"active": [
{
"id": "task-knowledge-api",
"file": ".claude/tasks/task-knowledge-api.md",
"agent": "coder",
"branch": "feature/knowledge-api",
"pr_number": null,
"status": "running",
"started_at": "2026-05-18T10:00:00Z",
"review_rounds": 0,
"max_review_rounds": 5,
"agent_invocations": {
"coder": 1,
"code_reviewer": 0,
"security_reviewer": 0,
"autotest": 0,
"devops": 0,
"legal": 0
},
"events": [{ "at": "2026-05-18T10:00:00Z", "type": "agent_started", "agent": "coder" }],
"pending_fixes": []
}
],
"completed": [
{
"id": "task-fix-pr22-ui-round5",
"duration_min": 18,
"rounds": 5,
"regression_count": 1,
"agent_invocations": {
"coder": 5,
"code_reviewer": 4,
"security_reviewer": 2,
"autotest": 1,
"devops": 0,
"legal": 1
},
"merged_at": "2026-05-20T07:03:35Z",
"pr_number": 22
}
],
"blocked": [],
"blocking_issue": null
}
Поля
Top-level:
feature— название текущей фичиbrief— путь к pm-brief-.mdstarted_at— когда PM стартовал работуphase—development/user-testing/merging/archivedactive[]— текущие незавершённые задачиcompleted[]— завершённые задачи (для метрик)blocked[]— заблокированные (с.blocked.md)blocking_issue— глобальный blocker (например,e2e-brokenна main)
Active task:
- Базовые:
id,file,agent,branch,pr_number,status review_rounds— счётчик раундов (circuit breaker>=3)agent_invocations— счётчики dispatchevents[]— лог событийpending_fixes[]— правки от User Testing
Event types:
agent_started—{ at, type, agent, task_file? }agent_finished—{ at, type, agent, result: "success"|"blocked"|"no-op" }brief_approved—{ at, type, brief }— BA brief принят, PM приступил к decompositiontask_file_created—{ at, type, file }— PM создал новый task-file для Coder/AutoTest/DevOpspr_opened—{ at, type, pr }code_review_started—{ at, type, pr }— PM dispatched code-reviewercode_review_done—{ at, type, pr, verdict: "APPROVE"|"BLOCK", rounds, findings_count? }— code-reviewer завершил, Verdict parsed из first line review body. Default reviewer post Phase 3b.security_review_started—{ at, type, pr, triggered_paths: [...] }— PM dispatched security-reviewer (только когда PR трогает critical-path zones)security_review_done—{ at, type, pr, verdict: "APPROVE"|"BLOCK", rounds, owasp_categories_hit?: [...], findings_count? }— security-reviewer завершилsecurity_dispatched—{ at, type, pr, triggered_paths: [...] }— alias для security_review_started (PM шорт-форма при логировании в Mode 2 таблице)review_timeout—{ at, type, pr, agent: "code-reviewer"|"security-reviewer", dispatched_at, timeout_at }— reviewer не вернул verdict за 2× expected duration (Mode 2.F)review_rejected—{ at, type, pr, rounds }(от внешних non-AI reviewer-ов через REQUEST_CHANGES)autotest_skipped—{ at, type, reason }— skip без записи запрещёнrouting_decision—{ at, type, track: "wave-fanout"|"audit-fanout", reason }— оркестратор выбрал нестандартный трек параллелизма (orchestration-routing.md).single-pipeline/light-track= дефолт, не логируется (как и не-skip агенты)worktree_isolation_warning—{ at, type, files: [...] }e2e_started—{ at, type, run_id }e2e_passed—{ at, type, run_id }e2e_failed—{ at, type, run_id, failure_type: "code"|"test"|"infra" }user_approved—{ at, type, pr }merge_approved_label—{ at, type, pr }do_not_merge_label—{ at, type, pr, reason }merged—{ at, type, pr }wakeup_scheduled—{ at, type, scheduled_task_id, fireAt }legal_dispatched—{ at, type, mode, target }— PM запустил Legal черезAgent().mode∈ {consult, pr-review, brief-check, strategic}.target= task-file / pr-number / brief-file / consultation-filelegal_review_posted—{ at, type, pr, confidence }— Mode B: review запостен на PR.confidence∈ {HIGH, MED, LOW}legal_pre_feature_done—{ at, type, brief, recommendations_count }— Mode C: Legal вернул recommendations для AClegal_escalated_to_human—{ at, type, reason }— Mode B/A: Confidence: LOW + hard zone → USER informed эскалировать к human-юристу
Deprecated (historical, не пишутся новые) — преобразование post Phase 3b:
review_approve— заменено наcode_review_doneсverdict: "APPROVE". Историческое legacy вcompleted[]оставить как есть.review_blocked— заменено наcode_review_doneИЛИsecurity_review_doneсverdict: "BLOCK". Историческое legacy оставить.
Aggregate verdict (не event, а derived state в memory PM):
PM объединяет code_review_done + (опц.) security_review_done в aggregate per pm.md Mode 2 "Aggregate verdict logic". Aggregate не пишется как отдельный event — derived при чтении events[].
Полный документ возможных types — .claude/state/events.md.
Completed task (агрегаты для метрик):
duration_min— отstarted_atдоmerged_atrounds— итоговое число review_roundsregression_count— сколько раз roundN сломал что-то из round{N-1}agent_invocations— финальные счётчикиmerged_at,pr_number
Статусы задачи
running → pr_open → awaiting_pm_review → user_testing → e2e_running → merged | failed
Промежуточные: blocked (есть .blocked.md), pending_fixes (User Testing вернул правки).
Метрики (из completed[])
avg(rounds)— среднее число раундов на задачу (цель: ≤ 2)avg(duration_min)— среднее от старта до mergesum(regression_count) / count(*)— частота регрессий- Распределение
agent_invocations.coder— сколько раз перезапускали Coder
GHA Secrets (актуальные)
| Secret | Для чего |
|---|---|
CLAUDE_CODE_OAUTH_TOKEN |
claude-code-action auth |
JWT_SECRET |
E2E тесты (auth через cookie) |
Полезные команды мониторинга
# Список open PR
gh pr list --repo yaremenko-maksym/CheekyCheeseIT_CRM --state open
# Labels на PR
gh pr view <pr_number> --repo yaremenko-maksym/CheekyCheeseIT_CRM \
--json labels --jq '[.labels[].name]'
# PR reviews
gh api repos/yaremenko-maksym/CheekyCheeseIT_CRM/pulls/<N>/reviews \
--jq '.[] | {state, body}'
# Найти PR по ветке
gh pr list --repo yaremenko-maksym/CheekyCheeseIT_CRM \
--head "feature/<slug>" --json number --jq '.[0].number'
# Мониторинг GHA E2E
gh run list --repo yaremenko-maksym/CheekyCheeseIT_CRM --workflow=e2e.yml --limit 5
gh run view <run_id> --repo yaremenko-maksym/CheekyCheeseIT_CRM --json status,conclusion
gh run view <run_id> --repo yaremenko-maksym/CheekyCheeseIT_CRM --log-failed