---
title: Claude Code automation recommendations — внедрение 8 пунктов (MCP × 2 + skills × 2 + hooks × 2 + subagents × 2)
date: 2026-05-13
status: draft (awaiting customer approval before plan execution; user requested plan-only, no install)
author: Claude (через superpowers:writing-plans)
related-rules: |
  - [CLAUDE.md §3.3](../../../CLAUDE.md) — реестр 33 формализованных инструментов (после внедрения станет 35 при условии sync нормативки — НЕ в этом плане)
  - [Pravila §4.5](../../../docs/Pravila_raboty_Claude_v1_1.md) — варианты A/B/C перед нетривиальным выбором
  - [Pravila §4.6](../../../docs/Pravila_raboty_Claude_v1_1.md) — self-review триггеры
  - [Pravila §4.7 п.4](../../../docs/Pravila_raboty_Claude_v1_1.md) — relative paths `../../../<target>` для plans/specs (квирк 76 от 13.05)
  - [Pravila §12 hard rule](../../../docs/Pravila_raboty_Claude_v1_1.md) — skill инвокация ПЕРВОЙ
  - [Pravila §13](../../../docs/Pravila_raboty_Claude_v1_1.md) — UI/UX pool координация
  - [PSR_v1 R10.1](../../../docs/Plugin_stack_rules_v1.md) — формализация внешних инструментов (отдельный план)
  - [Tooling §3.3](../../../docs/Tooling_v8_3.md) — реестр; sync — отдельный план
  - Existing [`.claude/settings.json`](../../../.claude/settings.json) — пример PostToolUse markdownlint hook
  - Existing [`.mcp.json`](../../../.mcp.json) — пример 4 MCP server entries
  - Existing [`lefthook.yml`](../../../lefthook.yml) — 8 pre-commit + 2 pre-push jobs (не дублировать)
---

# Design: Claude Code automation recommendations — внедрение 8 пунктов

## 1. Контекст и триггер

**Триггер:** заказчик в session 13.05.2026 day +1 запустил `/claude-code-setup:claude-automation-recommender` — skill проанализировал codebase и выдал 8 рекомендаций (2 MCP + 2 custom skills + 2 hooks + 2 subagents) + 1 plugin (`commit-commands`). На вопрос о scope заказчик ответил «**Все 7 пунктов одним планом, plugins не устанавливай, экономия 0%**». Это spec для технической части (plugin `commit-commands` исключён; sync нормативки PSR_v1/Tooling/CLAUDE.md/Pravila — отдельным планом потом).

**Numerical reconciliation:** «7 пунктов» = округление заказчика. По факту 8 технических автоматизаций после исключения plugin commit-commands. Скоп подтверждаю в Section 2.

**Текущее состояние [`.claude/`](../../../.claude/):**

- `.claude/settings.json` — permissions (24 allow / 6 deny) + 1 PostToolUse hook (markdownlint auto-fix на `*.md` кроме CLAUDE.md).
- `.claude/settings.local.json` — user-specific overrides (есть, но содержимое не критично для плана).
- `.claude/worktrees/` — 2 isolated worktrees от прошлых subagent dispatches (не трогать).
- `.claude/agents/` — **отсутствует**.
- `.claude/skills/` — **отсутствует**.
- `.claude/commands/` — **отсутствует**.
- `.claude/hooks/` — **отсутствует**.

**Текущее [`.mcp.json`](../../../.mcp.json):** 4 MCP server entries — `playwright`, `github` (HTTP+PAT), `laravel-boost` (stdio локальный), `semgrep` (stdio через `npx -y semgrep-mcp`).

**Текущий [`lefthook.yml`](../../../lefthook.yml):** 8 pre-commit jobs (gitleaks, markdownlint, cspell, stylelint, pint, larastan, squawk, eslint-vue) + 2 pre-push (gitleaks-full-history, lychee). **Важно для дизайна hook'ов:** Claude Code hooks ≠ git hooks. Lefthook срабатывает на `git commit`/`git push`, Claude Code hooks — на `Edit`/`Write`/`Bash` tool calls. Не дублировать функционал.

## 2. Scope (8 пунктов)

| # | Тип | Имя | Файл результата | Атомарный коммит |
|---|---|---|---|---|
| 1 | MCP | Sentry MCP | [`.mcp.json`](../../../.mcp.json) +1 entry | `feat(mcp): add sentry-mcp` |
| 2 | MCP | Redis MCP | [`.mcp.json`](../../../.mcp.json) +1 entry | `feat(mcp): add redis-mcp` |
| 3 | Skill | `/q-item-add` | `.claude/skills/q-item-add/SKILL.md` | `feat(skill): add q-item-add` |
| 4 | Skill | `/rls-check` | `.claude/skills/rls-check/SKILL.md` | `feat(skill): add rls-check` |
| 5 | Hook | PreToolUse block CLAUDE.md | [`.claude/settings.json`](../../../.claude/settings.json) +1 hook | `feat(hook): block direct CLAUDE.md edits` |
| 6 | Hook | PostToolUse schema CHANGELOG reminder | [`.claude/settings.json`](../../../.claude/settings.json) +1 hook | `feat(hook): remind schema CHANGELOG on db/schema.sql edits` |
| 7 | Subagent | `rls-reviewer` | `.claude/agents/rls-reviewer.md` | `feat(agent): add rls-reviewer` |
| 8 | Subagent | `pest-parallel-debugger` | `.claude/agents/pest-parallel-debugger.md` | `feat(agent): add pest-parallel-debugger` |

## 3. Out of scope

- **Plugin `anthropics/claude-plugins-official:commit-commands`** — заказчик исключил («plugins не устанавливай»).
- **Sync нормативной документации** (PSR_v1 R10.1 формализация Sentry/Redis MCP, Tooling §3.3 numbering #34/#35, CLAUDE.md §3.3 строки, Pravila §13.2 счётчик infrastructure subsection) — заказчик подтвердил «sync — потом отдельно». **Прецедент v1.83 audit gap (5 инструментов активно без формализации) явно принят на этот цикл.**
- **`coverage:json` / vitest coverage улучшения** для skills/subagent'ов — out (не code).
- **CI integration** (запуск hooks/skills в GitHub Actions) — out.
- **Производственная активация Sentry/Redis credentials** — pre-flight Task 1 documents secrets-injection pattern, но реальные credentials заказчик инжектирует вне плана (через `$env:SENTRY_TOKEN`, etc.).

## 4. Архитектура — per-item

### 4.1. MCP Sentry

**Цель:** прямой доступ Claude к Sentry issues/events для self-hosted экземпляра в Yandex Cloud (см. [CLAUDE.md §2](../../../CLAUDE.md) — «Sentry: self-hosted в Yandex Cloud»).

**Package selection unknown:** ecosystem MCP servers для Sentry на 2026-05-13 — несколько вариантов:

- `@sentry/mcp-server` (official, если есть)
- `mcp-server-sentry` (community)
- Docker-based wrapper

→ **Pre-flight Task 1 проверит `npm search sentry mcp` + `npm view <pkg>` + GitHub search**, фиксирует канонический package + version. Plan Task 2 использует определённое имя; до pre-flight — placeholder `<sentry-mcp-pkg>`.

**Config pattern:**

```json
{
  "sentry": {
    "command": "npx",
    "args": ["-y", "<sentry-mcp-pkg>"],
    "env": {
      "SENTRY_URL": "${SENTRY_URL}",
      "SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}"
    },
    "comment": "Off-phase tool — Sentry MCP для self-hosted в Yandex Cloud. Pending sync в Tooling §3.3 #34 (отдельный план). Env vars: SENTRY_URL (https://sentry.<your-domain>.ru), SENTRY_AUTH_TOKEN (user scope sentry:read). Credentials в .env.local (gitignored), Claude Code считывает env из shell startup."
}
```

**Secrets handling:**

- `SENTRY_URL` + `SENTRY_AUTH_TOKEN` — env vars из shell. Заказчик настраивает через PowerShell profile `[Environment]::SetEnvironmentVariable` или `.env.local` подгружаемый им.
- **НЕ commit'ить credentials.** Существующий gitleaks (lefthook pre-commit + pre-push) поймает leak — это validated safety net.
- `.gitleaks.toml` allowlist для `${SENTRY_*}` patterns — проверить, что `${...}` syntax не триггерит false positive. Pre-flight Task 1.

### 4.2. MCP Redis

**Цель:** read-only debug-доступ к Memurai (Redis 7-совместимый, локальный Windows service) для отладки очередей, кэша, Pest --parallel cache race ([memory quirk 72](../../../../../Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_environment.md)) и retry-state в `RouteSupplierLeadJob`.

**Package:** `@modelcontextprotocol/server-redis` (документирован в Anthropic MCP ecosystem на 2026-05; pre-flight Task 1 verify через `npm view`).

**Config pattern:**

```json
{
  "redis": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-redis", "redis://localhost:6379"],
    "comment": "Off-phase tool — Redis MCP для Memurai (Redis 7-совместимый Windows service на localhost:6379). Pending sync в Tooling §3.3 #35 (отдельный план). READ-ONLY usage — для debug очередей, кэша, Pest --parallel race (memory quirk 72). НЕ для production Redis (нет prod на этом этапе). Tools: KEYS, GET, LRANGE, etc."
}
```

**Безопасность:**

- Локальный Memurai на 6379 без auth — это dev-only, не prod. Документировать в comment'е.
- Если в будущем будет prod Redis в Yandex Cloud с auth — отдельный entry `redis-prod` с `redis://user:pass@host:port` через env var.

### 4.3. Skill `/q-item-add` — добавить запись в реестр Открытых_вопросов

**Цель:** инкапсулировать workflow добавления нового Q-item (Биз-N/CTO-N/Ю-N/Диз-N/DO-N/OPEN-N) в [docs/Открытые_вопросы_v8_3.md](../../../docs/Открытые_вопросы_v8_3.md). Сейчас это 5-6 шагов вручную:

1. Найти секцию (Биз / CTO / Ю / Диз / DO / OPEN) в narrative.
2. Найти следующий свободный номер (последний +1).
3. Вписать строку формата `**<prefix>-N <STATUS-EMOJI>** ⏸ от 2026-05-13: <текст> — <дата-фиксации>`.
4. Bump «Сводка §0» counters (открытые / закрытые).
5. Bump header version + footer version + changelog entry.
6. Sync §0 row в [CLAUDE.md](../../../CLAUDE.md) (cross-reference на v1.X→v1.X+1 реестра).

**Risk:** легко забыть пп. 4-6 → реестр и CLAUDE.md уходят в дрейф. Прецедент: v1.83 audit gap (5 инструментов активно без формализации) показал, что multi-file sync без skill'а ненадёжен.

**Skill structure (`.claude/skills/q-item-add/SKILL.md`):**

```yaml
---
name: q-item-add
description: |
  Add a new open question (Q-item) to the registry docs/Открытые_вопросы_v8_3.md.
  Use when customer raises a new business/CTO/legal/design/devops/OPEN question
  that does not have an immediate answer. Walks through 6-step workflow:
  detect section, find next number, insert entry, update §0 counters,
  bump header/footer/changelog version, sync §0 row in CLAUDE.md.
disable-model-invocation: true
---

# Q-item-add — add a new open question to the registry

## Usage
Invoke explicitly via `/q-item-add <Биз|CTO|Ю|Диз|DO|OPEN> "<question text>"`.

## Workflow
1. Open `docs/Открытые_вопросы_v8_3.md` and find section for the prefix (e.g., section ## 13 for Биз-*).
2. Grep latest number in that section (e.g., `Биз-31` is current max → new = `Биз-32`).
3. Insert new row in table or below previous entry in narrative form.
4. Update «Сводка §0»: `Биз 24 ✅ / 7 ⏸` → `Биз 24 ✅ / 8 ⏸` (or shifts as appropriate).
5. Bump header version (e.g., `v1.83 от 13.05.2026 (day +1)` → `v1.84 от 13.05.2026 (day +1)`).
6. Bump footer version + add changelog entry under «История версий».
7. Sync `CLAUDE.md` §0 row «Открытые вопросы» — bump `v1.83+` → `v1.84+`.

## Validation
- After save: `lychee --config .lychee.toml docs/Открытые_вопросы_v8_3.md` (0 broken links).
- Counter arithmetic check: sum of ✅ + ⏸ per prefix unchanged unless adding new.

## When NOT to use
- Customer says «закрываем X» — that's closure, not addition. Use targeted Edit instead.
- Item already exists with same text — это duplicate; ask customer or update existing.
```

**`disable-model-invocation: true`** — skill только для пользовательской инвокации (`/q-item-add ...`), Claude не должен сам решать «давайте добавим Q-item», т.к. правило Pravila §2.2 требует явного запроса от заказчика.

### 4.4. Skill `/rls-check` — verify RLS policy на новой таблице

**Цель:** инкапсулировать чек-лист для security-critical работы — добавление таблицы в [db/schema.sql](../../../db/schema.sql) требует:

1. Колонка `tenant_id UUID NOT NULL` (или явное обоснование для SaaS-level таблицы как `supplier_csv_reconcile_log`).
2. `ENABLE ROW LEVEL SECURITY`.
3. 2 политики минимум: SELECT для `crm_app_*` ролей, ALL для `crm_app_admin`.
4. GRANT для 5 ролей (`crm_app_user`, `crm_app_admin`, `crm_supplier_worker`, `crm_readonly`, `crm_migrator`).
5. Запись в [db/CHANGELOG_schema.md](../../../db/CHANGELOG_schema.md).
6. squawk на staged SQL (lefthook pre-commit это уже делает, но skill напоминает).
7. Smoke test через `tests/Feature/RlsSmokeTest.php` или новый тест для конкретной таблицы.

**Skill structure (`.claude/skills/rls-check/SKILL.md`):**

```yaml
---
name: rls-check
description: |
  Verify Row-Level Security on a new or modified table in db/schema.sql.
  Use when adding a new table, adding/removing tenant_id column, or modifying
  RLS policies. Walks through 7-step checklist (tenant_id, ENABLE RLS, 2+
  policies, 5 role GRANTs, CHANGELOG, squawk, smoke test).
disable-model-invocation: true
---

# RLS-check — verify Row-Level Security on a new table

## Usage
Invoke explicitly via `/rls-check <table_name>`.

## Checklist
1. **tenant_id column.** Grep `db/schema.sql` for `CREATE TABLE <name>`. Verify `tenant_id UUID NOT NULL REFERENCES tenants(id)` exists. Exception: SaaS-level tables (e.g., `supplier_csv_reconcile_log`) — must have explicit comment justifying.
2. **ENABLE RLS.** Grep `ALTER TABLE <name> ENABLE ROW LEVEL SECURITY;` — must be present.
3. **Policies.** Minimum 2 policies: `SELECT` for `crm_app_user`/`crm_app_admin` (tenant scope via `current_setting('app.current_tenant_id')::uuid`), `ALL` for `crm_app_admin` (or other privileged role). For SaaS-level tables — BYPASSRLS via role (e.g., `crm_supplier_worker`).
4. **Role GRANTs.** Verify `GRANT SELECT|INSERT|UPDATE|DELETE` for each of 5 roles per current pattern in `db/02_grants.sql`. Missing GRANT = silent failure in production.
5. **CHANGELOG.** Add entry to `db/CHANGELOG_schema.md` with date + table name + summary (per [CLAUDE.md §5 п.8](../../../CLAUDE.md)).
6. **squawk lint.** Run `./bin/squawk.exe db/schema.sql` and verify 0 issues (lefthook pre-commit will catch this, but skill verifies pre-commit).
7. **Smoke test.** Add or extend `tests/Feature/RlsSmokeTest.php` — assert that user in tenant A cannot SELECT row from tenant B for new table. Run: `cd app && ./vendor/bin/pest --filter RlsSmokeTest`.

## Output
Print pass/fail per item + count of issues. If all 7 pass — output `RLS-check: 7/7 ✅`. If any fail — list specific failures with line numbers (`db/schema.sql:NNNN missing tenant_id`).

## When NOT to use
- Modifying existing well-RLS'd table without adding new columns — overhead.
- Tables explicitly outside RLS scope (e.g., `migrations`, `cache` — Laravel internal).
```

### 4.5. Hook PreToolUse — блокировка прямой правки `CLAUDE.md`

**Цель:** runtime enforcement [§5 п.10](../../../CLAUDE.md) — hard rule: `CLAUDE.md` правится только через `/claude-md-management:revise-claude-md` или `/claude-md-management:claude-md-improver`. Сейчас правило только текстом; direct `Edit CLAUDE.md` физически возможен.

**Design challenge:**

Claude Code PreToolUse hook видит `CLAUDE_TOOL_NAME` (e.g., `Edit`) и `CLAUDE_TOOL_INPUT` (JSON с `file_path`, etc.), но **не видит контекст вызова** — был ли Edit инициирован напрямую или через skill. Plugin `claude-md-management` сам использует `Edit`/`Write` под капотом — hook не отличит legitimate edit от violating.

**Три варианта дизайна (см. [Pravila §4.5](../../../docs/Pravila_raboty_Claude_v1_1.md) — варианты A/B/C для нетривиального выбора):**

**Option A — Warning-only (recommended).** Hook не блокирует, но в stderr выводит напоминание: «You are editing CLAUDE.md directly. Prefer `/claude-md-management:revise-claude-md`. If invoked via that skill, this warning is informational.» Trade-off: violation возможна, но видна сразу.

**Option B — Hard block with skill-marker env.** Hook блокирует, если `$CLAUDE_SKILL_ACTIVE !== 'claude-md-management'`. **Risk:** этой env var может не существовать на 2026-05 Claude Code API. Pre-flight Task 1 verify.

**Option C — Hookify rule.** Использовать `/hookify:hookify` для создания rule на основе conversation analysis (hookify уже работает для economy hook 6-component architecture, см. [memory `feedback_superpowers_hard_rule.md`](../../../../../Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_superpowers_hard_rule.md)). Trade-off: внешняя зависимость от plugin hookify; gain: контекстная аналитика (skill-marker detection уже работает).

**Решение (для spec, awaiting customer):** Pre-flight Task 1 определяет наличие `CLAUDE_SKILL_*` env vars. Если есть — Option B. Если нет — Option A (warning) + параллельно открыть AskUserQuestion для согласования миграции на hookify (Option C) как явная отдельная задача (не в этом плане).

**Hook code (Option A draft):**

```json
{
  "matcher": "Edit|Write",
  "hooks": [
    {
      "type": "command",
      "command": "node -e \"const f=process.env.CLAUDE_FILE_PATH||''; const skillCtx=process.env.CLAUDE_SKILL_ACTIVE||''; if (/^CLAUDE\\\\.md$/i.test(require('path').basename(f)) && !skillCtx.includes('claude-md-management')) { process.stderr.write('\\\\n[hook] WARNING: Direct edit of CLAUDE.md detected. Per §5 п.10, prefer /claude-md-management:revise-claude-md or /claude-md-management:claude-md-improver. If invoked via the skill, this warning is informational.\\\\n'); }\""
    }
  ]
}
```

NB: `path.basename(f)` чтобы matchнуть только корневой `CLAUDE.md`, не `app/CLAUDE.md` или `node_modules/.../CLAUDE.md`.

**Hook code (Option B draft, if `CLAUDE_SKILL_ACTIVE` exists):**

Same `command`, но `process.exit(2)` + stderr вместо warning, когда skill-marker отсутствует.

**Альтернативное проектирование (Option D, расширение):** matcher для `Bash` calls типа `sed -i.*CLAUDE.md` или `> CLAUDE.md`. Текущее предложение в spec не покрывает Bash-обход. Bash-обход редок (≥99% правок через Edit/Write), но для completeness — Task 6 включает sub-step «consider Bash matcher» с фиксацией решения в коммит-сообщении.

### 4.6. Hook PostToolUse — напомнить про `db/CHANGELOG_schema.md`

**Цель:** runtime reminder [§5 п.8](../../../CLAUDE.md) — каждая правка `db/schema.sql` требует записи в `db/CHANGELOG_schema.md`. Self-review (§8) ловит это поздно (после ≥3 групп правок), hook — сразу.

**Design:** PostToolUse matcher `Edit|Write`, check `process.env.CLAUDE_FILE_PATH` for `db/schema.sql` (basename match), output reminder в stdout (видим в transcript).

**Hook code:**

```json
{
  "matcher": "Edit|Write",
  "hooks": [
    {
      "type": "command",
      "command": "node -e \"const f=process.env.CLAUDE_FILE_PATH||''; const norm=f.replace(/\\\\\\\\/g,'/'); if (/(^|\\\\/)db\\\\/schema\\\\.sql$/i.test(norm)) { process.stdout.write('\\\\n[hook] REMINDER: You modified db/schema.sql. Per §5 п.8 (CLAUDE.md), add a corresponding entry to db/CHANGELOG_schema.md before committing.\\\\n'); }\""
    }
  ]
}
```

NB: `\\\\` для JSON escape → real `\\` в Node → real `\` в regex. Test in Task 7 verify Windows path separators normalize.

**Trade-off:** stdout vs stderr. stdout viewable в Claude transcript directly (как сейчас markdownlint output появляется); stderr может теряться. Решение — stdout.

**Edge case:** если правка через Bash (`echo "..." >> db/schema.sql` или `psql` direct DDL) — hook не сработает. Bash matcher альтернатива (как в 4.5 Option D). Скоп этой spec — только Edit/Write, Bash-обход документирован как known limitation.

### 4.7. Subagent `rls-reviewer`

**Цель:** parallel review subagent для migration PR'ов, специализированный на RLS-семантике Лидерры. Generic `security-review` plugin не знает про 5 ролей, `crm_supplier_worker` BYPASSRLS, `current_setting('app.current_tenant_id')` pattern.

**Subagent structure (`.claude/agents/rls-reviewer.md`):**

```yaml
---
name: rls-reviewer
description: |
  Review RLS (Row-Level Security) compliance on migration commits/PRs.
  Use when reviewing changes to db/schema.sql or db/migrations/ that add
  or modify tables. Specialized for Лидерра's 5-role architecture
  (crm_app_user, crm_app_admin, crm_supplier_worker BYPASSRLS,
  crm_readonly, crm_migrator). Reports orphan policies, missing
  tenant_id columns, inconsistent GRANTs, missing CHANGELOG entries.
tools: Read, Grep, Glob, Bash
---

# RLS reviewer agent (Лидерра)

You are reviewing a database migration or schema change for RLS (Row-Level Security) compliance in the Лидерра CRM project.

## Context

- The project uses PostgreSQL 16 with 5 roles defined in `db/00_create_roles.sql` and `db/02_grants.sql`:
  - `crm_app_user` — regular tenant user, RLS enforced via `current_setting('app.current_tenant_id')`.
  - `crm_app_admin` — tenant admin, RLS enforced, broader policies.
  - `crm_supplier_worker` — SaaS-level worker (BYPASSRLS), for supplier integration jobs.
  - `crm_readonly` — read-only role for reports, RLS enforced.
  - `crm_migrator` — DDL role, RLS BYPASSED via session, used by Laravel migrations.
- Each tenant-scoped table must have:
  - `tenant_id UUID NOT NULL REFERENCES tenants(id)` column.
  - `ENABLE ROW LEVEL SECURITY`.
  - At least 2 policies: SELECT (tenant scope) and ALL (admin scope), or per project convention.
  - GRANTs for the 5 roles in `db/02_grants.sql`.
- SaaS-level tables (e.g., `supplier_csv_reconcile_log`, `system_settings`) are exempt from tenant_id; must have explicit comment justifying.
- Every schema change requires a `db/CHANGELOG_schema.md` entry.

## Workflow

1. Read the target migration file or `db/schema.sql` diff.
2. For each table added/modified, run the 7-item checklist (same as `/rls-check` skill but in review mode — read-only, no fixes).
3. Cross-check `db/02_grants.sql` for matching GRANTs.
4. Cross-check `db/CHANGELOG_schema.md` for entry with correct date.
5. Run `./bin/squawk.exe <changed-sql>` and capture issues.
6. Output a structured report:

```text
RLS Review — <table_name>
  [✅/❌] tenant_id column present
  [✅/❌] ENABLE ROW LEVEL SECURITY
  [✅/❌] SELECT policy for crm_app_user
  [✅/❌] ALL policy for crm_app_admin
  [✅/❌] 5-role GRANTs in db/02_grants.sql
  [✅/❌] db/CHANGELOG_schema.md entry
  [✅/❌] squawk passes (0 issues)
Issues:
  - <line>:<column> <message>
Pass: <N>/7
```

## Constraints

- Read-only — do not edit files, only report.
- If a table is SaaS-level, accept exemption with explicit comment; flag if comment missing.
- For composite PK or partitioned tables (e.g., `lead_charges` partitioned by month), verify the policy applies to parent + children.

## Out of scope

- General SQL style (squawk handles).
- General code review (other agents handle).
- Performance review (separate concern).

```

**Tools:** `Read, Grep, Glob, Bash` — read-only, plus `Bash` для squawk binary.

### 4.8. Subagent `pest-parallel-debugger`

**Цель:** specialized debugger для Pest --parallel flaky failures. Знает 2 квирка из [memory `feedback_environment.md`](../../../../../Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_environment.md), специфичных для Pest --parallel в этом проекте:

- **Quirk 72** (memory line 389) — Pest --parallel Redis cache `supplier:session` race в subdir-only run. Full --parallel suite passes 742/739/0/3 ✅. `vendor/bin/pest --parallel tests/Feature/Supplier/` deterministic 41/43 (2 random failed каждый run, fixed `CleanupInactiveSupplierProjectsJobTest::handles_404_from_supplier`). Root cause: `SupplierPortalClient::loadSession()` (line 220-244) читает global Redis `supplier:session`; в subdir-only — race постоянная (4 supplier files × 8 workers); в full suite — race редкая. Mitigation: subdir = `--parallel=0` или sequential; full suite = известно green.
- **Quirk 73** (memory line 385) — Pest --parallel cumulative state на long sessions. Symptom: `LookupsTest line 31` «1067 matches 2», `LookupsTest line 48` «admin@example.ru vs Абрам К.», `ProjectExtensionsTest line 89` «7677 identical to 1» — «too many rows» signatures. Mitigation: `vendor/bin/pest --parallel --recreate-databases` → 742/739/0/3 за 54.9s. Worker-DBs кэшируются через token-suffix, migrations не пересоздаются между runs без флага.

Generic debug skill не знает эти specifics — каждый раз пробег по той же диагностике.

**NB:** quirks 70-71 в memory — про a11y / Vuetify aria-label, **не Pest** — не входят в этот subagent. Quirks 74-76 — про npm/Lucide/plans paths, тоже не Pest.

**Subagent structure (`.claude/agents/pest-parallel-debugger.md`):**

```yaml
---
name: pest-parallel-debugger
description: |
  Diagnose Pest 4 --parallel test failures in the Лидерра CRM project.
  Classifies failures as (a) real failure, (b) quirk 72 (Redis supplier:session
  race in subdir-only), (c) quirk 73 (cumulative state on long sessions),
  or (d) other — escalate. Falsifies hypotheses with actual command runs.
tools: Read, Grep, Bash
---

# Pest --parallel debugger agent (Лидерра)

You are diagnosing a Pest 4 --parallel test failure in the Лидерра CRM project.

## Known quirks (from memory feedback_environment.md, line refs as of 2026-05-13)

1. **Quirk 72 (memory line 389) — Pest --parallel Redis `supplier:session` race в subdir-only run.** Symptom: `vendor/bin/pest --parallel tests/Feature/Supplier/` deterministic 41/43 + 2 random failed (one fixed: `CleanupInactiveSupplierProjectsJobTest::handles_404_from_supplier`). Full suite passes 742/739/0/3 ✅. Root cause: `SupplierPortalClient::loadSession()` (line 220-244) читает global Redis key `supplier:session`; afterEach forget vs concurrent worker reads → race. Mitigation: `--parallel=0` или sequential для subdir; full suite = known green.
2. **Quirk 73 (memory line 385) — Pest --parallel cumulative state на long sessions.** Symptom: `LookupsTest line 31` «1067 matches 2», `LookupsTest line 48` «admin@example.ru vs Абрам К.», `ProjectExtensionsTest line 89` «7677 identical to 1». Cause: worker-DBs `liderra_testing_<token>` кэшируются; migrations не пересоздаются без `--recreate-databases`; DatabaseTransactions (не RefreshDatabase per `Pest.php` line 23 commented) покрывает row-state, но не committed DDL/Redis. Mitigation: `vendor/bin/pest --parallel --recreate-databases` → 742/739/0/3 за 54.9s.

## Diagnostic pipeline

Given a failure output (paste from user or capture from `./vendor/bin/pest --parallel`):

1. **Capture exact failure.** What test file:line failed? Assertion message?
2. **Hypothesis 1 — real failure.** Read failing test + production code. Catches real bug? If yes — fix the code.
3. **Hypothesis 2 — quirk 72 (Redis supplier:session race).** Failing test в `tests/Feature/Supplier/*`? Rerun `./vendor/bin/pest --parallel=0 <test-path>` (sequential). If passes — race confirmed. If full suite (`./vendor/bin/pest --parallel`) also passes — known subdir flake, document.
4. **Hypothesis 3 — quirk 73 (cumulative state).** Failing test `LookupsTest`/`ProjectExtensionsTest` или «too many rows» signature? Rerun `./vendor/bin/pest --parallel --recreate-databases`. If passes — cumulative DB pollution.
5. **Hypothesis 4 — other.** If none of above — escalate с raw output + tested hypotheses + outcome per hypothesis.

## Output format

```text
Pest --parallel debugger report

Failure: <file>:<line>
Assertion: <message>

Hypothesis 1 (real failure): <falsified|confirmed|untested>
  Evidence: <test code summary + production code review with file:line pins>
Hypothesis 2 (quirk 72 Redis supplier:session race): <falsified|confirmed|untested>
  Evidence: <command + output>
Hypothesis 3 (quirk 73 cumulative state): <falsified|confirmed|untested>
  Evidence: <command + output>

Conclusion: <real fix needed | quirk 72 — known race document | quirk 73 — recreate-databases fixed | other — escalate>
Recommendation: <next step for user>
```

## Constraints (pest-debugger)

- Falsify hypotheses with actual command runs, do not just speculate.
- Capture raw output, not summaries.
- Never claim "should pass" — only "passed with this command" or "failed with this command + output".
- If unsure — escalate, do not guess.

```

**Tools:** `Read, Grep, Bash` — read tests, grep memory quirks, run Pest variations.

## 5. Открытые вопросы перед implementation (resolve в Task 1 pre-flight)

| # | Вопрос | Resolution |
|---|---|---|
| Q1 | Canonical package name для Sentry MCP? | Pre-flight `npm search sentry mcp` + `npm view <pkg>` + GitHub search → фиксируем имя |
| Q2 | Canonical package name для Redis MCP? | Pre-flight `npm view @modelcontextprotocol/server-redis` → подтвердить версию + tools list |
| Q3 | Есть ли `CLAUDE_SKILL_ACTIVE` env var в Claude Code hooks API на 2026-05? | Pre-flight: `env` dump из тестового hook'а в throwaway file → фиксируем какие vars доступны |
| Q4 | gitleaks false positive на `${SENTRY_URL}` syntax в .mcp.json? | Pre-flight test: добавить тестовый entry → `./bin/gitleaks.exe protect --staged` → проверить |
| Q5 | Hookify rule vs custom hook для §5 п.10 CLAUDE.md block — какой подход? | Решение по Q3: если есть skill-marker env — Option B (hard block); если нет — Option A (warning) + plan для Option C (hookify) отдельно |
| Q6 | Custom .claude/skills/ и .claude/agents/ — auto-discover на старте session или требуют restart? | Pre-flight: создать throwaway test skill → проверить inv через `/<name>` без restart |
| Q7 | `app/CLAUDE.md` (Boost) — должен ли быть exempt от hook block? | Yes — hook matches `basename(f) === 'CLAUDE.md'` AND parent dir is project root. Регекс уточняем в Task 6 |

## 6. Dependencies

- **Sentry MCP** — требует self-hosted Sentry экземпляр + auth token. Зависимость от заказчика для credentials. План документирует pattern, install — pending credentials. До credentials MCP entry можно добавить со stub'ом `SENTRY_URL=disabled` (отключённый).
- **Redis MCP** — требует running Memurai на localhost:6379 (уже работает per [§2](../../../CLAUDE.md) стек).
- **`/q-item-add`** + **`/rls-check`** — нет внешних deps, чистый markdown.
- **PreToolUse hook §5 п.10** — зависит от Q3 resolution. Если Option B — требует `CLAUDE_SKILL_ACTIVE` env. Если Option A — work standalone.
- **PostToolUse hook db/schema.sql** — нет deps.
- **Subagent `rls-reviewer`** — требует `./bin/squawk.exe` (уже установлен per lefthook job 7).
- **Subagent `pest-parallel-debugger`** — требует Pest 4 setup в `app/` (уже установлен).

## 7. Success criteria

| Критерий | Метрика | Validation |
|---|---|---|
| `.mcp.json` валиден | JSON schema `https://raw.githubusercontent.com/anthropics/claude-code/main/schemas/mcp.json` | Open in editor → no validation errors; `claude mcp list` (если CLI доступен) shows 6 entries |
| Sentry MCP enumerable | Tools list returns ≥1 tool (`get_issue`, `list_events`, etc.) | Pre-flight verify; если credentials отсутствуют — stub mode тоже OK для test of registration |
| Redis MCP enumerable | Tools list returns ≥1 tool (`KEYS`, `GET`, etc.) + connection to localhost:6379 ОК | Manual MCP call `mcp__redis__KEYS *` returns array |
| `/q-item-add` invocable | `Skill` tool list shows `q-item-add` | После создания файла, в новой session check `/q-item-add` появляется (или в текущей — pre-flight Q6) |
| `/rls-check` invocable | Same | Same |
| Hook block CLAUDE.md active | Manual Edit `CLAUDE.md` (test path, not real) → warning/block visible | Test: try `Edit` on temp `CLAUDE.md` copy → observe hook output |
| Hook reminder schema.sql active | Manual Edit `db/schema.sql` (1-line whitespace) → reminder visible | Test: edit whitespace-only line in `db/schema.sql` → observe; rollback edit |
| Subagent `rls-reviewer` invocable | `Agent({ subagent_type: 'rls-reviewer' })` succeeds | Test invocation on small migration commit |
| Subagent `pest-parallel-debugger` invocable | Same | Test invocation on a known flaky output (synthetic) |
| 0 regressions | Pest 742/739/0/3, Vitest 88/683+3, lychee 252 OK, gitleaks 0 | Post-implementation full lefthook regression suite |
| Atomic commits | 8 task commits + 1 pre-flight setup + 1 final = 10 commits | git log review per [Pravila §4.3](../../../docs/Pravila_raboty_Claude_v1_1.md) |
| 0 sync drift | CLAUDE.md / Tooling / PSR_v1 / Pravila — НЕ изменены этим планом | git diff на 4 nominal files = 0 — sync отдельным планом |

## 8. Координация с правилами

- **Sentry MCP / Redis MCP** — формально новые позиции #34 / #35 в [Tooling §3.3](../../../docs/Tooling_v8_3.md). **НЕ формализуются в этом плане** (out of scope). Прецедент v1.83 audit gap accepted на данный цикл; future audit plan (отдельный) закроет.
- **`/q-item-add` + `/rls-check`** — project-local skills, не входят в Tooling registry (внутренние). Регулируются [PSR_v1 R0.6](../../../docs/Plugin_stack_rules_v1.md) hard-стопами (не trigger'ят).
- **Hooks 4.5 + 4.6** — runtime enforcement existing rules ([§5 п.8](../../../CLAUDE.md), [§5 п.10](../../../CLAUDE.md)). Не новые правила.
- **Subagents 4.7 + 4.8** — project-local agents, не trigger'ят PSR_v1 R10 (не plugins).
- **Pravila §12 hard rule** — этот spec / plan создан через `superpowers:writing-plans` (skill инвокирован первым).
- **Pravila §4.5** — варианты A/B/C — применены к Q5 (CLAUDE.md hook design).
- **Pravila §4.7 п.4** — relative paths `../../../` использованы во всех cross-references из этого spec.

## 9. Self-review (на момент написания spec, до plan)

- [x] Goal в Section 1 — одно предложение, конкретное.
- [x] Scope в Section 2 — 8 пунктов, табличная форма, mapping на файлы и коммиты.
- [x] Out of scope явно — plugin + sync.
- [x] Per-item Section 4 — каждый пункт имеет цель, design, code/config draft.
- [x] Открытые вопросы Section 5 — 7 Q resolve в pre-flight.
- [x] Dependencies Section 6 — внешние зависимости явны.
- [x] Success criteria Section 7 — каждый пункт измеримый.
- [x] Координация с правилами Section 8 — sync с Pravila/PSR_v1/Tooling/CLAUDE.md явна.
- [ ] **NB ограничение:** не верифицировал, что `CLAUDE_SKILL_ACTIVE` env var существует — pre-flight Task 1 закроет.
- [ ] **NB ограничение:** не верифицировал, что `@modelcontextprotocol/server-redis` доступен на npm — pre-flight закроет.
- [ ] **NB ограничение:** Sentry MCP package name unknown — pre-flight закроет.
- [ ] **NB ограничение:** не запускал тесты для проверки нерегрессии — этот spec design-only.
