# Claude Code Automation Recommendations — Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Внедрить 8 технических автоматизаций Claude Code (2 MCP servers + 2 project-local skills + 2 hooks + 2 subagents) per spec, **без plugin'ов** и **без sync нормативки** (исключено заказчиком).

**Architecture:** Atomic commits per pункт скопа — 10 коммитов суммарно (1 pre-flight + 8 automations + 1 final). Изменения локальны в `.mcp.json`, `.claude/settings.json`, `.claude/skills/<name>/SKILL.md`, `.claude/agents/<name>.md`. Существующий PostToolUse markdownlint hook не трогаем. Существующие 4 MCP entries не трогаем.

**Tech Stack:** JSON (mcp + settings configs), Markdown + YAML frontmatter (skills + agents), Node.js inline (`node -e "..."`) для hook commands. Verification: `cd app && ./vendor/bin/pest --parallel --recreate-databases` (~55s), `cd app && npm run test:vue` (~60s), `./bin/gitleaks.exe protect --staged`, `./bin/lychee.exe --config .lychee.toml ...`.

**Spec:** [docs/superpowers/specs/2026-05-13-claude-automation-recommendations-design.md](../specs/2026-05-13-claude-automation-recommendations-design.md) — содержит per-item architecture, 7 open questions resolved в Task 1, design Options A/B/C для hook §5 п.10.

---

## File Structure

| Файл | Действие | Что делается |
|---|---|---|
| `.mcp.json` | Modify | +2 entries: `sentry`, `redis` (Tasks 2-3) |
| `.claude/settings.json` | Modify | +2 hooks в `hooks` секции: PreToolUse Edit\|Write block CLAUDE.md, PostToolUse Edit\|Write reminder для `db/schema.sql` (Tasks 6-7) |
| `.claude/skills/q-item-add/SKILL.md` | Create | YAML frontmatter + markdown skill content (Task 4) |
| `.claude/skills/rls-check/SKILL.md` | Create | YAML frontmatter + markdown skill content (Task 5) |
| `.claude/agents/rls-reviewer.md` | Create | YAML frontmatter + system prompt для subagent (Task 8) |
| `.claude/agents/pest-parallel-debugger.md` | Create | YAML frontmatter + system prompt для subagent (Task 9) |
| `docs/superpowers/specs/2026-05-13-claude-automation-recommendations-design.md` | — | Уже создан (этот plan ссылается) |
| `docs/superpowers/plans/2026-05-13-claude-automation-recommendations-plan.md` | — | Этот файл |

**Файлы НЕ меняем:**

- [`CLAUDE.md`](../../../CLAUDE.md) — sync нормативки исключён заказчиком.
- [`docs/Pravila_raboty_Claude_v1_1.md`](../../../docs/Pravila_raboty_Claude_v1_1.md) — same.
- [`docs/Plugin_stack_rules_v1.md`](../../../docs/Plugin_stack_rules_v1.md) — same.
- [`docs/Tooling_v8_3.md`](../../../docs/Tooling_v8_3.md) — same.
- [`lefthook.yml`](../../../lefthook.yml) — Claude Code hooks ≠ git hooks; не дублируем.
- Existing `.claude/settings.json` markdownlint hook — не трогаем, только добавляем рядом.
- 4 existing `.mcp.json` entries — не трогаем, только добавляем.

---

## Pre-execution baseline (capture before Task 1)

Перед началом снять baseline для сравнения post-implementation:

```bash
cd "/c/моя/проекты/портал crm/Документация/app"
./vendor/bin/pest --parallel --recreate-databases 2>&1 | tail -3
```

Expected (per [CLAUDE.md §6 / memory project_state.md](../../../CLAUDE.md)): `{"tool":"pest","result":"passed","tests":742,"passed":739,"assertions":2243,"duration_ms":~55000,"skipped":3}`.

```bash
cd "/c/моя/проекты/портал crm/Документация/app"
npm run test:vue 2>&1 | tail -5
```

Expected: `Test Files  88 passed (88) | Tests  683 passed | 3 skipped (686)`.

```bash
./bin/lychee.exe --config .lychee.toml "docs/**/*.md" "db/**/*.md" "*.md" 2>&1 | tail -3
```

Expected: `Errors per input ...  ✓ 0 broken links / 252 OK` (per memory project_state.md 13.05.2026 day +1).

Зафиксировать в transcript для проверки regressions в Task 10.

---

## Task 1: Pre-flight — resolve 7 open questions из spec

**Files:**

- Read only: `.mcp.json`, `.claude/settings.json`, `app/CLAUDE.md`, `node_modules/` exploration.
- No commits (research only).

- [ ] **Step 1.1: Sentry MCP package name (Q1)**

```bash
npm search sentry mcp 2>&1 | head -30
```

Capture output. Look for packages matching `sentry-mcp`, `@sentry/mcp-server`, `mcp-server-sentry`, etc.

```bash
npm view @sentry/mcp-server 2>&1 | head -20
```

If 404 — try alternative:

```bash
npm view sentry-mcp 2>&1 | head -20
npm view mcp-server-sentry 2>&1 | head -20
```

Записать в notes: canonical `<sentry-pkg>` + version (e.g., `sentry-mcp@1.2.3`) + tools list (если доступен в README).

If no npm package — check GitHub MCP servers:

```bash
# manual: open https://github.com/modelcontextprotocol/servers/tree/main/src and search "sentry"
```

If нет официального — план fallback: **Task 2 skipped** (Sentry MCP откладывается, документируем в final report).

- [ ] **Step 1.2: Redis MCP package name + tools (Q2)**

```bash
npm view @modelcontextprotocol/server-redis 2>&1 | head -30
```

Expected: package exists; capture version + maintainers + bin entry.

If 404 — fallback:

```bash
npm view modelcontextprotocol-server-redis 2>&1 | head -20
npm search redis mcp 2>&1 | head -20
```

Записать canonical `<redis-pkg>` + version.

- [ ] **Step 1.3: Claude Code hooks env vars (Q3)**

Создать throwaway hook для env dump. Editing `.claude/settings.local.json` (НЕ `settings.json`, не commit'ить):

```bash
cat .claude/settings.local.json 2>&1 | head -20
```

If contains `hooks` section — append; if нет — add fresh.

Добавить временный PostToolUse hook (потом удалим):

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Read",
        "hooks": [
          {
            "type": "command",
            "command": "node -e \"console.error('[hook-env-dump]', JSON.stringify(Object.keys(process.env).filter(k => k.startsWith('CLAUDE_')).reduce((o,k)=>{o[k]=process.env[k];return o;},{})))\""
          }
        ]
      }
    ]
  }
}
```

Затем в текущей session дернуть Read на любой файл — hook выведет в stderr список `CLAUDE_*` env vars.

Записать:

- Какие env vars доступны? (`CLAUDE_FILE_PATH`, `CLAUDE_TOOL_NAME`, `CLAUDE_TOOL_INPUT`, `CLAUDE_PROJECT_DIR`, `CLAUDE_SESSION_ID`, etc.)
- Есть ли `CLAUDE_SKILL_ACTIVE` или эквивалент? (Yes/No)

После записи — **удалить throwaway hook из `.claude/settings.local.json`** (revert).

- [ ] **Step 1.4: gitleaks false positive test для `${SENTRY_*}` (Q4)**

Создать throwaway test file:

```bash
echo '{ "sentry": { "env": { "SENTRY_URL": "${SENTRY_URL}", "SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}" } } }' > /tmp/test-gitleaks.json
git add /tmp/test-gitleaks.json 2>&1
./bin/gitleaks.exe protect --staged --config .gitleaks.toml --no-banner 2>&1
git reset HEAD /tmp/test-gitleaks.json 2>&1
rm /tmp/test-gitleaks.json 2>&1
```

Expected: `0 leaks` (gitleaks should recognize `${VAR}` as env-var reference, not literal secret).

If leaks reported — записать regex + plan adding `${SENTRY_*}` to `.gitleaks.toml` allowlist в Task 2 как pre-step.

- [ ] **Step 1.5: Hookify vs custom — decision на Q5**

На основе Step 1.3 outcome:

- Если `CLAUDE_SKILL_ACTIVE` (или эквивалент) **существует** → Task 6 implements Option B (hard block через skill-marker check).
- Если **не существует** → Task 6 implements Option A (warning-only). Hookify migration (Option C) — отдельная задача, не в этом плане.

Зафиксировать решение в notes: «Q5 resolved: Option <A|B>».

- [ ] **Step 1.6: Custom skills/agents auto-discover (Q6)**

Создать throwaway skill для проверки auto-discovery:

```bash
mkdir -p ".claude/skills/test-discover"
cat > ".claude/skills/test-discover/SKILL.md" << 'EOF'
---
name: test-discover
description: Throwaway skill to verify auto-discover. Delete after test.
---

# Test skill

Used to verify Claude Code auto-discovers project-local skills without restart.
EOF
```

Проверка — попытаться инвокировать `/test-discover` в текущей session (через Skill tool). Если skill виден в `available skills` system reminder — auto-discover есть. Если только после restart — задокументировать.

Cleanup:

```bash
rm -rf ".claude/skills/test-discover"
```

- [ ] **Step 1.7: app/CLAUDE.md verification (Q7)**

```bash
ls -la "app/CLAUDE.md" 2>&1
ls -la "CLAUDE.md" 2>&1
```

Expected: оба файла существуют. `app/CLAUDE.md` — пустой/минимальный (Boost-managed); root `CLAUDE.md` — narrative.

Записать pattern для hook regex: matchнуть только root `CLAUDE.md` (file path === `<project>/CLAUDE.md`, **не** `app/CLAUDE.md`, **не** `node_modules/.../CLAUDE.md`). Использовать `CLAUDE_PROJECT_DIR` env var + path comparison (более надёжно, чем basename).

- [ ] **Step 1.8: Document pre-flight outcomes**

Записать inline в transcript текущей session AND в commit-сообщение Task 1.9 (research commit) AND опционально через Edit апдейтить этот plan-файл (добавив раздел `## Task 1 outcomes` в конце, либо inline в Task 1) — фиксируем:

- Q1 outcome: `<sentry-pkg>@<ver>` или «not available, Task 2 skip»
- Q2 outcome: `@modelcontextprotocol/server-redis@<ver>` (или alternative)
- Q3 outcome: список доступных `CLAUDE_*` env vars
- Q4 outcome: gitleaks `${VAR}` allowlist — нужен / не нужен
- Q5 decision: Option A или Option B
- Q6 outcome: auto-discover работает без restart / требует restart
- Q7 outcome: hook regex pattern для root CLAUDE.md

Если результаты блокируют Tasks 2-9 — отчёт user'у, stop plan.

- [ ] **Step 1.9: No commit для Task 1 (research only)**

```bash
git status 2>&1
```

Expected: working tree clean (throwaway files revert'ены).

---

## Task 2: Add Sentry MCP entry

**Files:**

- Modify: [`.mcp.json`](../../../.mcp.json) — +1 entry в `mcpServers` объект.

**Prerequisite:** Task 1.1 + Task 1.4 — known `<sentry-pkg>` + gitleaks behavior.

- [ ] **Step 2.1: If Task 1 → Q4 reports false positive — add gitleaks allowlist**

If gitleaks flagged `${SENTRY_*}` в Step 1.4 — добавить в `.gitleaks.toml`:

```toml
[[allowlist.regexes]]
regex = '''\$\{SENTRY_[A-Z_]+\}'''
description = "Env var placeholders in .mcp.json, not literal secrets"
```

Otherwise — skip Step 2.1.

- [ ] **Step 2.2: Read current `.mcp.json`**

```bash
cat .mcp.json
```

Confirm 4 entries (`playwright`, `github`, `laravel-boost`, `semgrep`). Capture exact JSON structure (indentation, trailing comma rules).

- [ ] **Step 2.3: Add `sentry` entry**

Edit `.mcp.json` — добавить новый key в `mcpServers` (после `semgrep`):

```json
    "semgrep": {
      "command": "npx",
      "args": ["-y", "semgrep-mcp"],
      "comment": "..."
    },
    "sentry": {
      "command": "npx",
      "args": ["-y", "<sentry-pkg>"],
      "env": {
        "SENTRY_URL": "${SENTRY_URL}",
        "SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}"
      },
      "comment": "Off-phase tool — Sentry MCP для self-hosted в Yandex Cloud (CLAUDE.md §2). Pending формализация в Tooling §3.3 #34 — sync отдельным планом. Env vars: SENTRY_URL (https://sentry.<domain>.ru), SENTRY_AUTH_TOKEN (scope: sentry:read). Если env пустые — MCP server fail gracefully на startup (см. <sentry-pkg> README)."
    }
```

Подставить реальный `<sentry-pkg>` из Task 1.1.

- [ ] **Step 2.4: Validate JSON syntax**

```bash
node -e "JSON.parse(require('fs').readFileSync('.mcp.json','utf8'))" 2>&1
```

Expected: no output, exit 0. If error — fix trailing comma / quotes.

- [ ] **Step 2.5: Validate schema match**

```bash
node -e "const s=require('./.mcp.json'); console.log(JSON.stringify(Object.keys(s.mcpServers),null,2))"
```

Expected: 5 entries — `playwright`, `github`, `laravel-boost`, `semgrep`, `sentry`.

- [ ] **Step 2.6: Smoke gitleaks**

```bash
git add .mcp.json
./bin/gitleaks.exe protect --staged --config .gitleaks.toml --no-banner 2>&1
```

Expected: `no leaks found`. If leaks — Step 2.1 allowlist insufficient; iterate.

- [ ] **Step 2.7: Commit**

```bash
git commit -m "$(cat <<'EOF'
feat(mcp): add sentry-mcp server entry

Self-hosted Sentry в Yandex Cloud (CLAUDE.md §2). Pending формализация
в Tooling §3.3 #34 — sync отдельным планом.

Env vars: SENTRY_URL, SENTRY_AUTH_TOKEN — injected via shell, не commit'ятся.
Package: <sentry-pkg>@<ver>.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

```bash
git status 2>&1
```

Expected: `nothing to commit, working tree clean`.

---

## Task 3: Add Redis MCP entry

**Files:**

- Modify: [`.mcp.json`](../../../.mcp.json) — +1 entry в `mcpServers` объект.

**Prerequisite:** Task 1.2 — known `<redis-pkg>` (default `@modelcontextprotocol/server-redis`).

- [ ] **Step 3.1: Read current `.mcp.json`**

```bash
cat .mcp.json
```

Confirm 5 entries after Task 2 (`playwright`, `github`, `laravel-boost`, `semgrep`, `sentry`).

- [ ] **Step 3.2: Add `redis` entry**

Edit `.mcp.json` — append `redis` after `sentry`:

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

- [ ] **Step 3.3: Validate JSON**

```bash
node -e "JSON.parse(require('fs').readFileSync('.mcp.json','utf8'))" 2>&1
```

Expected: exit 0.

- [ ] **Step 3.4: Smoke gitleaks**

```bash
git add .mcp.json
./bin/gitleaks.exe protect --staged --config .gitleaks.toml --no-banner 2>&1
```

Expected: `no leaks found`.

- [ ] **Step 3.5: Smoke MCP startup (optional, требует Memurai running)**

```bash
npx -y @modelcontextprotocol/server-redis redis://localhost:6379 --help 2>&1 | head -10
```

If `--help` not supported — пытаемся `--version`. Цель: проверить, что npm package скачивается без ошибки и запускается. Connect к Memurai не тестируем здесь (это smoke install, не runtime).

- [ ] **Step 3.6: Commit**

```bash
git commit -m "$(cat <<'EOF'
feat(mcp): add redis-mcp server entry

Memurai (Redis 7-совместимый Windows service, localhost:6379).
Pending формализация в Tooling §3.3 #35 — sync отдельным планом.

READ-ONLY use — отладка очередей, кэша, Pest --parallel race (memory quirk 72).
Package: @modelcontextprotocol/server-redis.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

---

## Task 4: Create `/q-item-add` skill

**Files:**

- Create: `.claude/skills/q-item-add/SKILL.md`

- [ ] **Step 4.1: Create directory**

```bash
mkdir -p ".claude/skills/q-item-add"
ls -la ".claude/skills/" 2>&1
```

Expected: dir created, `q-item-add/` listed.

- [ ] **Step 4.2: Write SKILL.md**

Содержимое (полностью, без placeholder'ов):

````markdown
---
name: q-item-add
description: |
  Add a new open question (Q-item) to the registry docs/Открытые_вопросы_v8_3.md.
  Use ONLY when customer explicitly requests adding a new business/CTO/legal/design/devops/OPEN
  question to the registry. 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 — добавить новый Q-item в реестр Открытых_вопросов

## Когда использовать

ТОЛЬКО при явном запросе заказчика добавить новый вопрос. Pravila §2.2 — закрытие/добавление вопроса требует явного указания заказчика.

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

## Workflow

1. **Detect section.** Открыть `docs/Открытые_вопросы_v8_3.md`, найти секцию по prefix:
   - `Биз-*` → section `## 13` (Бизнес).
   - `CTO-*` → section `## 3` (CTO/инженерные).
   - `Ю-*` → section `## 4` (Юридические).
   - `Диз-*` → section `## 5` (Дизайн).
   - `DO-*` → section `## 6` (DevOps/инфраструктура).
   - `OPEN-*` → section `## 7` (Прочие открытые).

2. **Find next number.** Grep последний номер в секции (e.g., max `Биз-31` → new = `Биз-32`).

   ```bash
   grep -oP '<prefix>-\d+' docs/Открытые_вопросы_v8_3.md | sort -t- -k2 -n | tail -1
   ```

3. **Insert entry.** Добавить строку формата:

   ```markdown
   **<prefix>-N ⏸** от 2026-MM-DD: <question text>
   ```

4. **Update §0 «Сводка».** Increment счётчик ⏸ для соответствующего prefix. Шапка `## 0` содержит таблицу типа `Биз 24 ✅ / 7 ⏸` — bump до `8 ⏸`. **Также** «Итого X / Y ✅ / Z ⏸» — bump соответствующие.

5. **Bump versions.** Header (`v1.83 от 13.05.2026 (day +1)` → `v1.84 от 13.05.2026 (day +1)`), footer (last line same), добавить запись в `## 9. История версий`.

6. **Sync CLAUDE.md.** В `CLAUDE.md` §0 row «Открытые вопросы» bump `v1.83+` → `v1.84+`. Помним: CLAUDE.md правится ТОЛЬКО через `/claude-md-management:revise-claude-md` (§5 п.10) — финальный шаг делегируем заказчику или этому skill'у через sub-invocation.

## Validation

После save:

```bash
./bin/lychee.exe --config .lychee.toml docs/Открытые_вопросы_v8_3.md 2>&1 | tail -3
```

Expected: 0 broken links.

Counter arithmetic check: sum of ✅ + ⏸ + 🟦 per prefix = total per prefix.

## Не использовать когда

- Заказчик говорит «закрываем X» — это closure (replace ⏸ → ✅ + дата), не addition. Skip skill, do targeted Edit.
- Item уже существует с тем же текстом — duplicate; уточнить у заказчика или обновить existing.
- Заказчик не давал явного «добавь X в реестр» — Pravila §2.2 запрещает proactive добавление.
````

Использовать Write tool с этим контентом.

- [ ] **Step 4.3: Validate YAML frontmatter**

```bash
node -e "
const fs = require('fs');
const c = fs.readFileSync('.claude/skills/q-item-add/SKILL.md', 'utf8');
const m = c.match(/^---\n([\s\S]+?)\n---/);
if (!m) { console.error('FAIL: no frontmatter'); process.exit(1); }
const lines = m[1].split('\n');
const hasName = lines.some(l => /^name:\s*q-item-add\s*$/.test(l));
const hasDesc = lines.some(l => /^description:/.test(l));
const hasDisable = lines.some(l => /^disable-model-invocation:\s*true\s*$/.test(l));
console.log(JSON.stringify({hasName, hasDesc, hasDisable}));
" 2>&1
```

Expected: `{"hasName":true,"hasDesc":true,"hasDisable":true}`.

- [ ] **Step 4.4: Lint markdown**

```bash
npx markdownlint-cli2 ".claude/skills/q-item-add/SKILL.md" 2>&1
```

Expected: exit 0 (no errors). If errors — npx markdownlint-cli2 --fix, then re-check.

- [ ] **Step 4.5: Smoke skill discovery**

Если Q6 в Task 1 показал auto-discover без restart — проверить, что `/q-item-add` появляется в available skills list в текущей session (system reminder).

Если требует restart — задокументировать в коммит-сообщении.

- [ ] **Step 4.6: Commit**

```bash
git add ".claude/skills/q-item-add/SKILL.md"
git commit -m "$(cat <<'EOF'
feat(skill): add /q-item-add — добавление Q-item в реестр Открытых_вопросов

Project-local skill в .claude/skills/q-item-add/SKILL.md.
Инкапсулирует 6-шаговый workflow: detect section → find next number →
insert entry → update §0 counters → bump versions → sync CLAUDE.md §0.

disable-model-invocation: true — только пользовательская инвокация
(Pravila §2.2: добавление Q-item требует явного запроса заказчика).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

---

## Task 5: Create `/rls-check` skill

**Files:**

- Create: `.claude/skills/rls-check/SKILL.md`

- [ ] **Step 5.1: Create directory**

```bash
mkdir -p ".claude/skills/rls-check"
ls -la ".claude/skills/" 2>&1
```

Expected: `q-item-add/` and `rls-check/` directories listed.

- [ ] **Step 5.2: Write SKILL.md**

Содержимое (полностью):

````markdown
---
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, db/CHANGELOG_schema.md entry, squawk, smoke test).
disable-model-invocation: true
---

# RLS-check — verify RLS на таблице

## Когда использовать

При добавлении или модификации таблицы в `db/schema.sql`, особенно перед коммитом. Инкапсулирует 7-item checklist; lefthook pre-commit job 7 (squawk) ловит только часть.

Invoke via `/rls-check <table_name>`.

## Checklist

1. **tenant_id column.** Grep `db/schema.sql` для `CREATE TABLE <name>`. Verify:
   - `tenant_id UUID NOT NULL REFERENCES tenants(id)` присутствует, **OR**
   - SaaS-level exemption — explicit comment типа `-- SaaS-level: no tenant_id (justification)`.

   ```bash
   grep -A30 "CREATE TABLE.*\b<name>\b" db/schema.sql | grep -E "tenant_id|SaaS-level"
   ```

2. **ENABLE RLS.** Должна быть строка `ALTER TABLE <name> ENABLE ROW LEVEL SECURITY;`.

   ```bash
   grep -E "ALTER TABLE\s+<name>\s+ENABLE ROW LEVEL SECURITY" db/schema.sql
   ```

3. **Policies — минимум 2.**
   - SELECT для `crm_app_user`/`crm_app_admin` с tenant scope: `USING (tenant_id = current_setting('app.current_tenant_id')::uuid)`.
   - ALL для `crm_app_admin` (или per-table convention).
   - SaaS-level: BYPASSRLS role pattern (e.g., `crm_supplier_worker`).

   ```bash
   grep -B1 -A5 "ON <name>" db/schema.sql | grep "POLICY"
   ```

4. **Role GRANTs.** В `db/02_grants.sql` должны быть GRANT'ы для 5 ролей. Проверить по pattern existing tables.

   ```bash
   grep -E "GRANT.*ON\s+<name>" db/02_grants.sql
   ```

   Expected: ≥5 GRANT statements (по одному на роль) или group GRANT.

5. **CHANGELOG entry.** В `db/CHANGELOG_schema.md` должна быть запись с датой + table name + summary (CLAUDE.md §5 п.8).

   ```bash
   grep "<name>" db/CHANGELOG_schema.md
   ```

6. **squawk lint.**

   ```bash
   ./bin/squawk.exe db/schema.sql 2>&1 | tail -10
   ```

   Expected: exit 0, no issues.

7. **Smoke test.** `tests/Feature/RlsSmokeTest.php` (или новый тест для конкретной таблицы) должен assert'ить, что user в tenant A не видит row из tenant B для новой таблицы.

   ```bash
   cd app && ./vendor/bin/pest --filter RlsSmokeTest 2>&1 | tail -10
   ```

   Expected: all assertions pass.

## Output

Print результат per item + total:

```text
RLS-check: <table_name>
  [✅] tenant_id column
  [✅] ENABLE RLS
  [✅] SELECT policy
  [✅] ALL policy
  [✅] 5-role GRANTs
  [✅] CHANGELOG entry
  [✅] squawk passes
  [✅] smoke test passes
Pass: 8/8
```

Or failure listing: `[❌] tenant_id column missing — db/schema.sql:NNNN`.

## Не использовать когда

- Modifying existing well-RLS'd table без новых columns — overhead.
- Tables explicitly outside RLS (e.g., Laravel `migrations`, `cache` — internal).
````

Использовать Write tool.

- [ ] **Step 5.3: Validate YAML frontmatter**

```bash
node -e "
const fs = require('fs');
const c = fs.readFileSync('.claude/skills/rls-check/SKILL.md', 'utf8');
const m = c.match(/^---\n([\s\S]+?)\n---/);
if (!m) { console.error('FAIL'); process.exit(1); }
console.log('OK');
" 2>&1
```

Expected: `OK`.

- [ ] **Step 5.4: Lint markdown**

```bash
npx markdownlint-cli2 ".claude/skills/rls-check/SKILL.md" 2>&1
```

Expected: exit 0.

- [ ] **Step 5.5: Commit**

```bash
git add ".claude/skills/rls-check/SKILL.md"
git commit -m "$(cat <<'EOF'
feat(skill): add /rls-check — 7-item RLS checklist для new tables

Project-local skill в .claude/skills/rls-check/SKILL.md.
Инкапсулирует security-critical chek: tenant_id, ENABLE RLS, 2+ policies,
5-role GRANTs (db/02_grants.sql), CHANGELOG, squawk, smoke test.

disable-model-invocation: true — для phyactical вызова при modify db/schema.sql.
Полезно для security-critical правок (39 RLS политик × 5 ролей).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

---

## Task 6: Add PreToolUse hook — CLAUDE.md edit warning/block

**Files:**

- Modify: [`.claude/settings.json`](../../../.claude/settings.json) — +1 entry в `hooks.PreToolUse` массив.

**Prerequisite:** Task 1.3 + Task 1.5 — Q3 (env vars) + Q5 (Option A vs B).

- [ ] **Step 6.1: Read current `.claude/settings.json`**

```bash
cat .claude/settings.json
```

Confirm structure: `$schema`, `permissions`, `hooks.PostToolUse` (markdownlint). No existing `PreToolUse` section — будет добавлен.

- [ ] **Step 6.2: Compose hook command**

**If Q5 = Option A (warning-only):**

```js
const f=process.env.CLAUDE_FILE_PATH||'';
const projectDir=process.env.CLAUDE_PROJECT_DIR||'';
const path=require('path');
const norm=path.resolve(f).replace(/\\/g,'/');
const root=path.resolve(projectDir).replace(/\\/g,'/');
if (norm === root+'/CLAUDE.md') {
  process.stderr.write('\n[hook] WARNING: Direct edit of root CLAUDE.md detected. Per §5 п.10, prefer /claude-md-management:revise-claude-md or /claude-md-management:claude-md-improver. If invoked via that skill, this warning is informational.\n');
}
```

**If Q5 = Option B (skill-marker hard block):**

Same + дополнительно `process.exit(2)` если `process.env.CLAUDE_SKILL_ACTIVE` не содержит `claude-md-management`.

- [ ] **Step 6.3: Edit `.claude/settings.json`**

Добавить в `hooks` object новый key `PreToolUse` (если уже есть — append в array):

```json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": { ... },
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "<inline node -e command from Step 6.2, escaped>"
          }
        ]
      }
    ],
    "PostToolUse": [
      { ... existing markdownlint hook ... }
    ]
  }
}
```

**Escaping note:** JSON requires `\"`, Node-inline requires backslash-escaping для backslashes (`\\\\`). Тестировать на throwaway file перед production save.

Example escaped command (Option A):

```text
node -e "const f=process.env.CLAUDE_FILE_PATH||''; const pd=process.env.CLAUDE_PROJECT_DIR||''; const p=require('path'); const n=p.resolve(f).replace(/\\\\/g,'/'); const r=p.resolve(pd).replace(/\\\\/g,'/'); if (n === r+'/CLAUDE.md') { process.stderr.write('\\n[hook] WARNING: Direct edit of root CLAUDE.md detected. Per §5 п.10, prefer /claude-md-management:revise-claude-md or /claude-md-management:claude-md-improver. If invoked via that skill, this warning is informational.\\n'); }"
```

- [ ] **Step 6.4: Validate JSON syntax**

```bash
node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8'))" 2>&1
```

Expected: exit 0.

- [ ] **Step 6.5: Test hook fires correctly — positive case (root CLAUDE.md)**

Create test scenario без actual modification — create a temporary copy first:

```bash
cp CLAUDE.md /tmp/CLAUDE-test-copy.md
```

В current Claude session — Edit на `CLAUDE.md` (тривиальная whitespace правка, потом revert). Наблюдать в transcript hook output.

Expected: stderr `[hook] WARNING: Direct edit of root CLAUDE.md detected. ...`

Revert правку через `git checkout -- CLAUDE.md` (или Edit reverse).

- [ ] **Step 6.6: Test hook does NOT fire — negative case (app/CLAUDE.md)**

Edit на `app/CLAUDE.md` (Boost-managed, тривиальная whitespace правка). Наблюдать transcript.

Expected: НЕТ hook output.

Revert.

- [ ] **Step 6.7: Test hook does NOT fire — node_modules CLAUDE.md (if exists)**

```bash
ls node_modules/*/CLAUDE.md 2>&1 | head -3
```

If existing — edit one тривиально. Expected: no fire. Revert.

If нет таких файлов — skip Step 6.7, document в commit.

- [ ] **Step 6.8: Commit**

```bash
git add ".claude/settings.json"
git commit -m "$(cat <<'EOF'
feat(hook): block direct edits of root CLAUDE.md

PreToolUse hook на Edit|Write — warns (Option A) or blocks (Option B)
если file path === <project>/CLAUDE.md AND вызов вне /claude-md-management:*.

Runtime enforcement существующего правила CLAUDE.md §5 п.10:
"Не править этот CLAUDE.md напрямую — только через плагин claude-md-management."

Не trigger'ит для app/CLAUDE.md (Boost-managed) и node_modules/*/CLAUDE.md.
Q5 решение: Option <A|B> per Task 1 pre-flight outcome.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

---

## Task 7: Add PostToolUse hook — db/schema.sql CHANGELOG reminder

**Files:**

- Modify: [`.claude/settings.json`](../../../.claude/settings.json) — +1 entry в `hooks.PostToolUse` массив (рядом с markdownlint).

- [ ] **Step 7.1: Read current `.claude/settings.json`**

```bash
cat .claude/settings.json
```

Confirm: после Task 6 есть `PreToolUse` + `PostToolUse` (markdownlint).

- [ ] **Step 7.2: Compose reminder command**

```js
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 CLAUDE.md §5 п.8, add a corresponding entry to db/CHANGELOG_schema.md before committing.\n');
}
```

- [ ] **Step 7.3: Edit `.claude/settings.json` — append PostToolUse hook**

Существующий PostToolUse array уже содержит markdownlint hook (matcher `Edit|Write`). Добавить ВТОРОЙ entry в этот же array:

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

**NB:** второй entry с тем же matcher OK — Claude Code обрабатывает оба последовательно (или параллельно, в зависимости от version; в обоих случаях оба сработают).

- [ ] **Step 7.4: Validate JSON syntax**

```bash
node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8'))" 2>&1
```

Expected: exit 0.

- [ ] **Step 7.5: Test hook fires — positive case**

В current session — Edit `db/schema.sql` (тривиальная whitespace правка, e.g., trailing space на пустой строке). Наблюдать transcript.

Expected: stdout output `[hook] REMINDER: You modified db/schema.sql. ...`

Revert правку: `git checkout -- db/schema.sql`.

- [ ] **Step 7.6: Test hook does NOT fire — negative case**

Edit любой другой файл (e.g., `README.md`). Наблюдать.

Expected: НЕТ hook output (только markdownlint output, если файл — `*.md`).

Revert.

- [ ] **Step 7.7: Commit**

```bash
git add ".claude/settings.json"
git commit -m "$(cat <<'EOF'
feat(hook): remind db/CHANGELOG_schema.md on db/schema.sql edits

PostToolUse hook на Edit|Write — outputs reminder в stdout если правка
file path matches db/schema.sql.

Runtime enforcement существующего правила CLAUDE.md §5 п.8:
"Не править db/schema.sql без записи в db/CHANGELOG_schema.md."

Self-review (§8) ловит это поздно (после ≥3 групп правок); hook — сразу.
Edge case: Bash-обход (echo ... >> db/schema.sql) не покрывается — known limitation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

---

## Task 8: Create `rls-reviewer` subagent

**Files:**

- Create: `.claude/agents/rls-reviewer.md`

- [ ] **Step 8.1: Create directory**

```bash
mkdir -p ".claude/agents"
ls -la ".claude/agents/" 2>&1
```

Expected: dir created.

- [ ] **Step 8.2: Write `rls-reviewer.md`**

Содержимое (полностью, без placeholder'ов; полный system prompt):

````markdown
---
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. Read-only review — DO NOT edit files.

## Контекст проекта

PostgreSQL 16 с 5 ролями (db/00_create_roles.sql + db/02_grants.sql):

1. `crm_app_user` — regular tenant user; RLS enforced via `current_setting('app.current_tenant_id')`.
2. `crm_app_admin` — tenant admin; RLS enforced, broader policies.
3. `crm_supplier_worker` — SaaS-level worker (BYPASSRLS) для supplier integration jobs.
4. `crm_readonly` — read-only для reports; RLS enforced.
5. `crm_migrator` — DDL role для Laravel migrations; RLS bypassed via session.

Каждая tenant-scoped таблица должна иметь:

- `tenant_id UUID NOT NULL REFERENCES tenants(id)` колонка.
- `ALTER TABLE <name> ENABLE ROW LEVEL SECURITY;`.
- Минимум 2 политики: SELECT (tenant scope `tenant_id = current_setting('app.current_tenant_id')::uuid`), ALL (admin scope).
- GRANT'ы для 5 ролей в `db/02_grants.sql`.

SaaS-level таблицы (e.g., `supplier_csv_reconcile_log`, `system_settings`) exempt от tenant_id; должны иметь explicit `-- SaaS-level` comment.

Каждое schema change требует записи в `db/CHANGELOG_schema.md` (CLAUDE.md §5 п.8).

## Workflow

1. Read target migration файл OR `db/schema.sql` diff (use `git diff HEAD~1 -- db/schema.sql` или указанные изменения).
2. Для каждой added/modified таблицы — run 7-item checklist:
   - tenant_id column (или SaaS-level comment).
   - ENABLE RLS.
   - SELECT policy для crm_app_user.
   - ALL policy для crm_app_admin (или per-convention).
   - 5-role GRANTs в db/02_grants.sql.
   - db/CHANGELOG_schema.md entry.
   - squawk passes (`./bin/squawk.exe <file>`).
3. Cross-check `db/02_grants.sql` для matching GRANTs.
4. Cross-check `db/CHANGELOG_schema.md` для entry.
5. Run `./bin/squawk.exe db/schema.sql 2>&1 | tail -10` и capture issues.
6. Output 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:
  - <file>:<line>:<col> <message>
Pass: <N>/7
```

## Constraints

- READ-ONLY — не edit files, только report.
- Falsify с actual command runs, не speculate.
- SaaS-level exemption — accept если explicit comment present; flag если comment отсутствует.
- Partitioned tables (e.g., `lead_charges` partitioned by month) — verify policy применяется к parent + children.

## Out of scope

- General SQL style (squawk handles).
- Business logic review (other agents).
- Performance review (separate concern).

## Verification protocol

Каждое утверждение про код — с `file:line` как pin'ом. "Looks correct" / "should pass" — запрещено. Только "passed with command X — output Y" or "failed with command X — output Y".
````

Use Write tool.

- [ ] **Step 8.3: Validate frontmatter**

```bash
node -e "
const fs = require('fs');
const c = fs.readFileSync('.claude/agents/rls-reviewer.md', 'utf8');
const m = c.match(/^---\n([\s\S]+?)\n---/);
if (!m) { console.error('FAIL'); process.exit(1); }
const hasTools = /^tools:\s*Read,\s*Grep,\s*Glob,\s*Bash\s*$/m.test(m[1]);
console.log(JSON.stringify({hasFm: !!m, hasTools}));
" 2>&1
```

Expected: `{"hasFm":true,"hasTools":true}`.

- [ ] **Step 8.4: Lint markdown**

```bash
npx markdownlint-cli2 ".claude/agents/rls-reviewer.md" 2>&1
```

Expected: exit 0.

- [ ] **Step 8.5: Smoke subagent invocation (optional, требует Agent tool)**

В current session — invoke:

```text
Agent({
  description: "RLS reviewer smoke test",
  subagent_type: "rls-reviewer",
  prompt: "Review db/schema.sql line range 100-200 for RLS compliance on whatever table is defined there. This is a smoke test — just verify the agent loads and can read files."
})
```

Expected: agent returns structured report (без crash на frontmatter parse).

If agent doesn't appear в `subagent_type` enum в текущей session — auto-discover требует restart; document это в коммит-сообщении.

- [ ] **Step 8.6: Commit**

```bash
git add ".claude/agents/rls-reviewer.md"
git commit -m "$(cat <<'EOF'
feat(agent): add rls-reviewer subagent для migration review

Project-local subagent в .claude/agents/rls-reviewer.md.
Specialized для 5-role архитектуры Лидерры (crm_app_user/admin/
supplier_worker BYPASSRLS/readonly/migrator).

Walks 7-item checklist: tenant_id, ENABLE RLS, 2 policies, 5-role GRANTs,
CHANGELOG, squawk. READ-ONLY (tools: Read, Grep, Glob, Bash).

Замена generic security-review для security-critical RLS работ (39 политик).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

---

## Task 9: Create `pest-parallel-debugger` subagent

**Files:**

- Create: `.claude/agents/pest-parallel-debugger.md`

- [ ] **Step 9.1: Create directory (если ещё нет)**

```bash
mkdir -p ".claude/agents"
ls -la ".claude/agents/" 2>&1
```

Expected: dir exists с `rls-reviewer.md`.

- [ ] **Step 9.2: Write `pest-parallel-debugger.md`**

Содержимое (полностью, с **верифицированными** quirks 72-73 из memory `feedback_environment.md` lines 385-391; quirks 70-71 в memory — про a11y/Vuetify, **не Pest** — не входят):

````markdown
---
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 в 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. Read-only diagnosis; recommend fixes, do not apply them.

## Known quirks (memory feedback_environment.md, verified 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 каждый run (one fixed: `CleanupInactiveSupplierProjectsJobTest::handles_404_from_supplier`). Single-file isolated 8/8 passes.
   - Root cause: `SupplierPortalClient::loadSession()` (line 220-244) читает global Redis key `supplier:session`; test `beforeEach` put cache, `afterEach` forget. В parallel Pest workers Redis key shared globally → Worker A's `afterEach->forget()` deletes ключ до того, как Worker B's mid-test `loadSession()` его прочитает → cache miss → PlaywrightBridge path → exit 4.
   - Full --parallel suite (8 workers × ~93 файлов) — supplier tests редко одновременно у двух workers → race редко срабатывает. Full passes 742/739/0/3 ✅.
   - Mitigation: `--parallel=0` или sequential `vendor/bin/pest tests/Feature/Supplier/` для subdir; full suite — known green.

2. **Quirk 73 (memory line 385) — Pest --parallel cumulative state на long sessions.**
   - Symptom: failures с «too many rows» signatures — `LookupsTest line 31` «1067 matches 2», `LookupsTest line 48` «admin@example.ru vs Абрам К.», `ProjectExtensionsTest line 89` «7677 identical to 1».
   - Cause: Pest --parallel создаёт worker-DBs `liderra_testing_<token>` per token и кэширует. Migrations не пересоздаются между runs без `--recreate-databases`. Tests используют `DatabaseTransactions` (не `RefreshDatabase` — `Pest.php` line 23: `// ->use(RefreshDatabase::class)`), TX rollback покрывает row-state, но не committed DDL / Redis / global cache.
   - Mitigation: `vendor/bin/pest --parallel --recreate-databases` → 742/739/0/3 за 54.9s. `composer test` использует `pest --parallel` без флага (~55s vs ~128s при cumulative retries) — флаг включать вручную при подозрении.

**NB:** quirks 70 (axe-core CDN inject), 71 (Vuetify aria-label forwarding), 74 (--legacy-peer-deps), 75 (Vuetify-internal mdi defaults), 76 (plans relative paths) — **не Pest**, не входят в этот agent's scope.

## Diagnostic pipeline

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

1. **Capture exact failure.** Какой 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 sequential `./vendor/bin/pest --parallel=0 <subdir>` или `./vendor/bin/pest <subdir>`. If passes — race. Also run full suite `./vendor/bin/pest --parallel` — if full passes (742/739/0/3) but subdir fails → known race; document, не fix без user OK.
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; baseline restored.
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

- Falsify hypotheses с actual command runs, не speculate.
- Capture raw output, не summaries.
- Никогда "should pass" — только "passed with <cmd>" or "failed with <cmd> + <output>".
- Каждое утверждение про код — с `file:line` pin'ом.
- If unsure — escalate, do not guess.

## Out of scope

- Не fix code — only diagnose + recommend.
- Не run full --parallel for >5 min без user OK (полный прогон ~55-128s OK).
- Vitest (frontend) failures — separate concern.
- a11y / Vuetify quirks — see separate quirks 70-71 in memory; not this agent.
````

Use Write tool.

- [ ] **Step 9.3: Validate frontmatter**

```bash
node -e "
const fs = require('fs');
const c = fs.readFileSync('.claude/agents/pest-parallel-debugger.md', 'utf8');
const m = c.match(/^---\n([\s\S]+?)\n---/);
if (!m) { console.error('FAIL'); process.exit(1); }
console.log('OK');
" 2>&1
```

Expected: `OK`.

- [ ] **Step 9.4: Lint markdown**

```bash
npx markdownlint-cli2 ".claude/agents/pest-parallel-debugger.md" 2>&1
```

Expected: exit 0.

- [ ] **Step 9.5: Commit**

```bash
git add ".claude/agents/pest-parallel-debugger.md"
git commit -m "$(cat <<'EOF'
feat(agent): add pest-parallel-debugger subagent

Project-local subagent в .claude/agents/pest-parallel-debugger.md.
Specialized для верифицированных Pest --parallel квирков 72 + 73
в проекте Лидерра (memory feedback_environment.md lines 385, 389):
- quirk 72 — Redis supplier:session race в subdir-only run
- quirk 73 — cumulative state на long sessions

4-hypothesis diagnostic pipeline (real / quirk 72 / quirk 73 / other).
READ-ONLY (tools: Read, Grep, Bash).

NB: quirks 70-71 в memory — про a11y/Vuetify, не Pest — не входят в agent's scope.
Quirks 74-76 — про npm/Lucide/plans paths, тоже не Pest.

Замена generic systematic-debugging для повторяющихся flake патернов.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

---

## Task 10: Final integration smoke + regression baseline

**Files:**

- Read only — verification step.

- [ ] **Step 10.1: Verify file inventory**

```bash
ls -la .claude/skills/ .claude/agents/ 2>&1
ls -la .claude/settings.json .mcp.json 2>&1
```

Expected:

- `.claude/skills/q-item-add/SKILL.md` exists.
- `.claude/skills/rls-check/SKILL.md` exists.
- `.claude/agents/rls-reviewer.md` exists.
- `.claude/agents/pest-parallel-debugger.md` exists.
- `.claude/settings.json` valid JSON with `PreToolUse` + 2 `PostToolUse` entries (markdownlint + db/schema reminder).
- `.mcp.json` valid JSON with 6 entries (4 original + sentry + redis).

- [ ] **Step 10.2: Validate all JSON configs**

```bash
node -e "JSON.parse(require('fs').readFileSync('.mcp.json','utf8')); console.log('.mcp.json: OK');" 2>&1
node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8')); console.log('.claude/settings.json: OK');" 2>&1
```

Expected: both report `OK`.

- [ ] **Step 10.3: Validate all YAML frontmatter**

```bash
for f in .claude/skills/q-item-add/SKILL.md .claude/skills/rls-check/SKILL.md .claude/agents/rls-reviewer.md .claude/agents/pest-parallel-debugger.md; do
  node -e "
    const fs=require('fs');
    const c=fs.readFileSync('$f','utf8');
    const m=c.match(/^---\n([\\s\\S]+?)\n---/);
    if (!m) { console.error('FAIL: $f'); process.exit(1); }
    console.log('$f: OK');
  " 2>&1
done
```

Expected: 4 × `OK`.

- [ ] **Step 10.4: Regression — Pest --parallel**

```bash
cd "/c/моя/проекты/портал crm/Документация/app"
./vendor/bin/pest --parallel --recreate-databases 2>&1 | tail -3
```

Expected: `{"tool":"pest","result":"passed","tests":742,"passed":739,"assertions":2243,"skipped":3}` (same as baseline; ничего не должно сломаться от config-only changes).

- [ ] **Step 10.5: Regression — Vitest**

```bash
cd "/c/моя/проекты/портал crm/Документация/app"
npm run test:vue 2>&1 | tail -5
```

Expected: `Test Files  88 passed (88) | Tests  683 passed | 3 skipped (686)`.

- [ ] **Step 10.6: Regression — gitleaks (full history)**

```bash
./bin/gitleaks.exe detect --source . --no-banner --config .gitleaks.toml --redact 2>&1 | tail -3
```

Expected: `no leaks found` (этот плагин не должен утечь credentials — `${SENTRY_*}` syntax).

- [ ] **Step 10.7: Regression — lychee**

```bash
./bin/lychee.exe --config .lychee.toml "docs/**/*.md" "db/**/*.md" "*.md" 2>&1 | tail -3
```

Expected: `0 broken links`.

**Note:** новые spec + plan содержат relative paths `../../../<target>` per Pravila §4.7 п.4. Lychee пройдёт по их ссылкам.

- [ ] **Step 10.8: Commit (final integration marker)**

```bash
git add docs/superpowers/specs/2026-05-13-claude-automation-recommendations-design.md docs/superpowers/plans/2026-05-13-claude-automation-recommendations-plan.md
```

```bash
git commit -m "$(cat <<'EOF'
docs(plan): claude-code automation recommendations — spec + plan + closure

Spec: docs/superpowers/specs/2026-05-13-claude-automation-recommendations-design.md
Plan: docs/superpowers/plans/2026-05-13-claude-automation-recommendations-plan.md

8 automations implemented в commits с 2 (sentry MCP) по 9 (pest debugger):
- MCP: sentry, redis
- Skills: /q-item-add, /rls-check
- Hooks: PreToolUse CLAUDE.md, PostToolUse db/schema.sql
- Subagents: rls-reviewer, pest-parallel-debugger

Sync нормативки (PSR_v1 R10.1 для MCP, Tooling §3.3 #34/#35, CLAUDE.md §3.3,
Pravila §13.2) — отдельным планом per customer decision.
Plugin commit-commands — excluded per "не устанавливай".

Regression: Pest 742/739/0/3, Vitest 88/683+3, lychee 0 broken, gitleaks 0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
EOF
)"
```

- [ ] **Step 10.9: Verify clean tree**

```bash
git status 2>&1
git log --oneline -12 2>&1
```

Expected:

- working tree clean
- последние ~10 коммитов: feat(mcp): sentry, feat(mcp): redis, feat(skill): q-item-add, feat(skill): rls-check, feat(hook): CLAUDE.md, feat(hook): schema.sql, feat(agent): rls-reviewer, feat(agent): pest-parallel-debugger, docs(plan): closure

- [ ] **Step 10.10: Report to user — final summary**

В transcript пользователю — summary:

```text
✅ 8 automations внедрены (10 commits)
- 2 MCP: sentry (<pkg>@<ver>), redis (@modelcontextprotocol/server-redis@<ver>)
- 2 skills: /q-item-add, /rls-check
- 2 hooks: PreToolUse CLAUDE.md block (Option <A|B>), PostToolUse db/schema.sql reminder
- 2 subagents: rls-reviewer, pest-parallel-debugger

Regression: Pest 742/739/0/3, Vitest 88/683+3, lychee 252 OK / 0 broken, gitleaks 0.

Pending (отдельным планом):
- Sync нормативки: PSR_v1 R10.1 формализация sentry+redis, Tooling §3.3 #34/#35,
  CLAUDE.md §3.3, Pravila §13.2 counters.
- Plugin commit-commands (excluded по запросу).
- Hookify migration для CLAUDE.md hook (если Option A был принят и customer
  хочет более тонкий context-aware enforcement).
```

---

## Self-review (после написания plan)

### 1. Spec coverage

| Spec Section | Plan coverage |
|---|---|
| Section 1 (Контекст) | Pre-execution baseline + Task 1 pre-flight |
| Section 2 (Scope 8 пунктов) | Tasks 2-9 (по одной задаче на пункт) |
| Section 3 (Out of scope) | Documented в `File Structure → Файлы НЕ меняем` + Task 10 final commit |
| Section 4.1 (Sentry MCP) | Task 2 |
| Section 4.2 (Redis MCP) | Task 3 |
| Section 4.3 (q-item-add) | Task 4 |
| Section 4.4 (rls-check) | Task 5 |
| Section 4.5 (PreToolUse CLAUDE.md) | Task 6 |
| Section 4.6 (PostToolUse schema.sql) | Task 7 |
| Section 4.7 (rls-reviewer) | Task 8 |
| Section 4.8 (pest-parallel-debugger) | Task 9 |
| Section 5 (7 Q's) | Task 1 Steps 1.1-1.7 |
| Section 6 (Dependencies) | Task 1 pre-flight covers credentials check |
| Section 7 (Success criteria) | Task 10 Steps 10.1-10.7 |
| Section 8 (Координация с правилами) | Implicit в Task descriptions; sync — out of scope |

✅ Все секции spec'а покрыты тасками.

### 2. Placeholder scan

Поиск red flags в этом plan'е:

- `TBD` / `TODO` — есть только `<sentry-pkg>` (canonical name определяется в Task 1.1) и `<redis-pkg>` (default `@modelcontextprotocol/server-redis`). Это намеренные placeholder'ы, resolve в pre-flight.
- `implement later` / `fill in details` — нет.
- `Add appropriate error handling` — нет.
- «Similar to Task N» — нет; каждая task standalone.

✅ Placeholder'ы только resolve-в-pre-flight, явно помечены в Task 1.

### 3. Type consistency

- `<sentry-pkg>` — referenced в Task 1.1 (define), Task 2.3 (use). Consistent.
- `<redis-pkg>` — default `@modelcontextprotocol/server-redis`. Use в Task 3.2. Consistent.
- `Option A|B` для CLAUDE.md hook — defined в Task 1.5, referenced в Task 6.2 / 6.3 / 6.8 commit message. Consistent.
- `CLAUDE_FILE_PATH`, `CLAUDE_PROJECT_DIR`, `CLAUDE_SKILL_ACTIVE` — names consistent across Tasks 1.3, 6.2, 7.2.
- Quirk numbers 70-73 — consistent с memory `feedback_environment.md` (см. spec Section 4.8 для cross-ref).
- Tool name slugs (`q-item-add`, `rls-check`, `rls-reviewer`, `pest-parallel-debugger`) — consistent across spec + plan + commit messages.

✅ Type consistency holds.

### 4. NB ограничения (явно)

- Я **не верифицировал** существование `CLAUDE_SKILL_ACTIVE` env var — Task 1.3 закроет.
- Я **не верифицировал** доступность `@modelcontextprotocol/server-redis` на npm — Task 1.2 закроет.
- Я **не верифицировал** canonical Sentry MCP package name — Task 1.1 закроет.
- Я **не запускал** тесты — этот plan design-only. Tasks 10.4-10.7 запустят regression baseline.
- Я **не тестировал** hook patterns на live system — Tasks 6.5-6.7 + 7.5-7.6 закроют smoke.
- Я **не верифицировал**, что project-local skills/agents auto-discover без restart — Task 1.6 закроет.
- Lychee passes для этого plan/spec **не запущен** — заявление о 252 OK основано на memory `project_state.md` 13.05.2026 day +1 baseline; Task 10.7 verify post-add.

---

## Execution handoff

Plan complete и сохранён в `docs/superpowers/plans/2026-05-13-claude-automation-recommendations-plan.md`. Две execution options (см. writing-plans skill):

1. **Subagent-Driven (recommended)** — fresh subagent per task, two-stage review между tasks, fast iteration. Использует `superpowers:subagent-driven-development`.

2. **Inline Execution** — execute tasks в текущей session через `superpowers:executing-plans`, batch execution с checkpoint'ами для review.

**Какой подход?** (или — если только план без execution — закрываем здесь, plan остаётся в реестре для будущей реализации.)
