# A1 backend-tooling 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. Project wrapper: `.claude/skills/subagent-driven-development/` (git-safety per Pravila §15.1).

**Goal:** Наполнить раздел A1 «Программирование — backend» четырьмя инструментами (Rector #64, PHP Insights #65, laravel-backend-patterns скил #66, NightOwl #67) с полным footprint роутера и наблюдателя.

**Architecture:** Off-phase tooling integration в изолированном worktree (паттерн A11/C10/finance). Rector/PHP Insights — Composer dev-deps + конфиги; backend-patterns — self-authored project-скил; NightOwl — self-hosted телеметрия в PG. Нормативка bump-ится атомарным набором (cross-ref-checker C2 STRICT). Spike-задачи определяют 2 gate-решения до сборки.

**Tech Stack:** PHP 8.3 / Laravel 13 / Composer / lefthook / PostgreSQL 16 / Markdown-нормативка / vis.js карта.

**Spec:** `docs/superpowers/specs/2026-05-20-a1-backend-tooling-design.md`

---

## Pre-flight (исполнитель — перед Task 1)

- Worktree от свежего `origin/main` через `superpowers:using-git-worktrees`. После создания скопировать gitignored-файлы (учёт Sprint 4): `app/.env`, `app/storage/`, `app/vendor/`, `app/node_modules/`, `bin/*.exe`, `лендинг/` — иначе composer/тесты/lefthook не запустятся.
- `git fetch && git log HEAD..origin/main --oneline` — pre-flight sync 8 нормативных файлов (Pravila §15.2).
- Закоммитить уже написанные spec (`docs/superpowers/specs/2026-05-20-a1-backend-tooling-design.md`) + этот план первым коммитом.

---

## File Structure

| Файл | Ответственность | Задача |
|---|---|---|
| `app/composer.json` | dev-deps (rector, rector-laravel, phpinsights, nightwatch) + scripts | 1,2,8 |
| `app/rector.php` | Rector ruleset (LaravelSetProvider + dead-code/code-quality) | 4 |
| `app/phpinsights.php` | PHP Insights config (complexity+architecture оси) | 5 |
| `lefthook.yml` | (условно) job 16 Rector dry-run | 4 |
| `.claude/skills/laravel-backend-patterns/SKILL.md` + `references/` | свод backend-конвенций Лидерры | 6 |
| `.claude/skills/laravel-backend-patterns/evals/evals.json` | trigger-евалы скила | 7 |
| `.mcp.json` | (условно) NightOwl MCP READ-ONLY | 8 |
| `tools/.l1-watcher-aliases.txt` | (условно) alias NightOwl MCP-имени | 8 |
| `docs/adr/ADR-013-backend-tooling.md` | границы узлов + BT1–BT9 | 9 |
| `docs/routing-off-phase.md` | +4 строки routing + связка L14 | 10 |
| `docs/router-procedure.md` | bump cross-ref | 10 |
| `docs/Tooling_v8_3.md` | §4.39–4.42 (9-атрибутные блоки) + §0 счётчик + header | 11 |
| `docs/Plugin_stack_rules_v1.md` | R10.1 +4 строки + header | 11 |
| `docs/Pravila_raboty_Claude_v1_1.md` | §13.2 +абзац + header | 11 |
| `CLAUDE.md` | §3.3 +#64–67, §6 +абзац, §9 +запись, header | 11 |
| `docs/automation-graph-data.js` | +4 узла NODE_SECTION + рёбра + версии-метки | 12 |

---

## Phase 0 — Spikes (определяют gate-решения)

### Task 1: Rector — установка + dry-run count spike

**Files:**

- Modify: `app/composer.json` (require-dev + scripts)
- Create: (нет в этой задаче — конфиг в Task 4)

- [ ] **Step 1: Установить Rector + rector-laravel**

Run (root `app/`):

```bash
composer require rector/rector driftingly/rector-laravel --dev
```

Expected: добавлены `rector/rector ^2.4`, `driftingly/rector-laravel` в `require-dev`; composer.lock обновлён.

- [ ] **Step 2: Временный минимальный конфиг для замера**

Create `app/rector.php` (временный, финальный — Task 4):

```php
<?php
use Rector\Config\RectorConfig;
use RectorLaravel\Set\LaravelSetProvider;
return RectorConfig::configure()
    ->withPaths([__DIR__ . '/app'])
    ->withSetProviders(LaravelSetProvider::class)
    ->withPreparedSets(deadCode: true, codeQuality: true);
```

- [ ] **Step 3: Прогнать dry-run и посчитать**

Run (root `app/`):

```bash
php vendor/bin/rector process --dry-run
```

Expected: вывод со списком предлагаемых изменений + итоговая строка `N files would have been changed`. **Записать N.**

- [ ] **Step 4: Зафиксировать решение по gate-постуре**

Записать в коммит-сообщение и в Task 4 решение:

- N ≤ ~5 → блокирующий lefthook job 16 (паттерн deptrac).
- N > ~5 → composer script + CI; lefthook-гейт отложить, в ADR-013 пометить.

- [ ] **Step 5: Commit**

```bash
git add app/composer.json app/composer.lock app/rector.php
git commit -m "feat(backend): install Rector + rector-laravel; dry-run baseline N=<N>"
```

---

### Task 2: PHP Insights — установка + baseline run

**Files:**

- Modify: `app/composer.json` (require-dev)

- [ ] **Step 1: Установить PHP Insights**

Run (root `app/`):

```bash
composer require nunomaduro/phpinsights --dev
```

Expected: `nunomaduro/phpinsights` в `require-dev`.

- [ ] **Step 2: Сгенерировать дефолтный конфиг**

Run (root `app/`):

```bash
php artisan vendor:publish --provider="NunoMaduro\PhpInsights\Application\Adapters\Laravel\InsightsServiceProvider"
```

Expected: создан `config/insights.php` (переедет в `app/phpinsights.php` в Task 5 — пока для baseline).

- [ ] **Step 3: Прогнать baseline-анализ**

Run (root `app/`):

```bash
php artisan insights --no-interaction --summary
```

Expected: 4 балла (Code / Complexity / Architecture / Style). **Записать значения.**

- [ ] **Step 4: Зафиксировать пороги**

По baseline выбрать `--min-quality` / `--min-complexity` / `--min-architecture` чуть ниже текущих (anti-regression), записать для Task 5.

- [ ] **Step 5: Commit**

```bash
git add app/composer.json app/composer.lock app/config/insights.php
git commit -m "feat(backend): install PHP Insights; baseline scores recorded"
```

---

### Task 3: NightOwl — feasibility spike

**Files:** (нет правок — разведка)

- [ ] **Step 1: Проверить доступность пакетов и MCP**

Run:

```bash
npm view @lemed99/nightowl-agent 2>$null; composer show laravel/nightwatch --available 2>$null
```

Прочитать README `github.com/lemed99/nightowl-agent` (WebFetch): (a) поддерживается ли self-hosted ingest в PostgreSQL без managed-аккаунта; (b) есть ли MCP-сервер в open-source варианте или только в managed (usenightowl.com).

- [ ] **Step 2: Зафиксировать access-path**

Записать решение для Task 8:

- MCP в open-source есть → регистрируем MCP-сервер в `.mcp.json` (READ-ONLY) + alias в l1-watcher.
- MCP только managed → fallback: телеметрия пишется в PG, Claude читает через Boost `database-query`; `.mcp.json` не трогаем.
- Self-hosted ingest на native-Windows невозможен/тяжёл → эскалировать заказчику (узел остаётся, но access-path = только Boost-чтение PG-таблиц nightwatch).

- [ ] **Step 3: Commit (документ разведки)**

```bash
git add docs/backend/nightowl-spike.md
git commit -m "docs(backend): NightOwl feasibility spike — access-path decided"
```

(Создать `docs/backend/nightowl-spike.md` с выводами Step 1–2.)

---

## Phase 1 — Rector финализация (#64)

### Task 4: Rector финальный конфиг + scripts + (условно) lefthook

**Files:**

- Modify: `app/rector.php`
- Modify: `app/composer.json` (scripts)
- Modify: `lefthook.yml` (условно — только если Task 1 N ≤ ~5)

- [ ] **Step 1: Финализировать `app/rector.php`**

Заменить временный конфиг (оставить conservative ruleset — без `typeDeclarations: true` на первом заходе):

```php
<?php
use Rector\Config\RectorConfig;
use RectorLaravel\Set\LaravelSetProvider;
return RectorConfig::configure()
    ->withPaths([__DIR__ . '/app', __DIR__ . '/database', __DIR__ . '/routes'])
    ->withSetProviders(LaravelSetProvider::class)
    ->withPreparedSets(deadCode: true, codeQuality: true)
    ->withSkip([
        __DIR__ . '/app/Console/Kernel.php',  // bootstrap — не трогать
    ]);
```

- [ ] **Step 2: Добавить composer scripts**

В `app/composer.json` `scripts`:

```json
"rector": "@php vendor/bin/rector process --dry-run",
"rector:fix": "@php vendor/bin/rector process"
```

- [ ] **Step 3: Проверить, что dry-run чист после финального конфига**

Run (root `app/`):

```bash
composer rector
```

Expected: `0 files would have been changed` ИЛИ зафиксированный baseline-список (если N>0 и решено не блокировать).

- [ ] **Step 4 (условно, N ≤ ~5): Добавить lefthook job 16 + доказать red-green**

В `lefthook.yml` `pre-commit.jobs` после job 15:

```yaml
    # 16. Rector — авто-рефакторинг / version-aware апгрейды (Прил. Н #64,
    # backend-tooling). dry-run на staged app/**/*.php — падает, если есть
    # неприменённые Rector-правки. Чистый PHP, без LLM (BT1-BT3).
    - name: rector
      glob: "app/**/*.php"
      root: "app/"
      run: php vendor/bin/rector process --dry-run --no-progress-bar
      fail_text: |
        Rector предлагает правки в staged-коде. Запусти `cd app && composer rector:fix`,
        проверь diff, прогони тесты и закоммить. Если правило неприменимо — добавь в withSkip() в app/rector.php.
```

Red-green доказательство: внести намеренный устаревший паттерн (напр. `array()` вместо `[]` в тест-файле) → `git add` → `lefthook run pre-commit` падает на job rector; откатить → проходит.

- [ ] **Step 5: Commit**

```bash
git add app/rector.php app/composer.json lefthook.yml
git commit -m "feat(backend): Rector config + composer scripts + lefthook gate (#64)"
```

---

## Phase 2 — PHP Insights финализация (#65)

### Task 5: PHP Insights конфиг (оси) + script

**Files:**

- Create: `app/phpinsights.php` (или оставить `config/insights.php` по факту publish)
- Modify: `app/composer.json` (scripts)

- [ ] **Step 1: Настроить конфиг — выключить Style-ось, акцент Complexity+Architecture**

В опубликованном конфиге (`config/insights.php`):

- в `remove` добавить sniff-классы стиля, которыми владеет Pint (`PSR12`, line-length, пробелы), чтобы не дублировать;
- задать `requirements` дефолты под baseline из Task 2 (min-quality/complexity/architecture).

- [ ] **Step 2: Добавить composer script**

В `app/composer.json` `scripts`:

```json
"insights": "@php artisan insights --no-interaction --min-quality=<Q> --min-complexity=<C> --min-architecture=<A>"
```

(подставить пороги из Task 2 Step 4).

- [ ] **Step 3: Прогнать и убедиться, что проходит пороги**

Run (root `app/`):

```bash
composer insights
```

Expected: exit 0 (баллы ≥ порогов). Если падает — поднять `remove`/скорректировать порог (baseline-аккуратно, не маскируя реальный долг).

- [ ] **Step 4: НЕ добавлять в lefthook** (BT9 — избегаем четверного гейта). Зафиксировать в коммит-сообщении.

- [ ] **Step 5: Commit**

```bash
git add app/config/insights.php app/composer.json
git commit -m "feat(backend): PHP Insights config (complexity+architecture axes, on-demand) (#65)"
```

---

## Phase 3 — laravel-backend-patterns скил (#66)

### Task 6: SKILL.md + references

**Files:**

- Create: `.claude/skills/laravel-backend-patterns/SKILL.md`
- Create: `.claude/skills/laravel-backend-patterns/references/conventions.md`

- [ ] **Step 1: Написать SKILL.md (frontmatter + тело)**

```markdown
---
name: laravel-backend-patterns
description: Backend-конвенции Лидерры (Laravel 13) — как писать controller→service→job, RLS-aware Eloquent, деньги через bcmath/LedgerService, идемпотентные джобы, partition-aware запросы. Используй при «как писать backend в Лидерре», «паттерн контроллера/сервиса/джоба», scaffolding новой backend-фичи. НЕ для generic-паттернов (architecture-patterns #38), аудита денег (billing-audit #62), РСБУ/налогов (ru-tax-accounting), security-аудита (D3).
---

# Laravel backend patterns — Лидерра

[Тело: 5 разделов-конвенций со ссылками на reference и реальные файлы-образцы кода проекта.]
```

- [ ] **Step 2: Написать references/conventions.md — 5 конвенций с code-образцами из проекта**

Каждая конвенция = правило + образец из существующего кода (file:line) + anti-pattern:

1. Слоистость `controller → FormRequest → service → job` (deptrac 13 слоёв `app/deptrac.yaml`); образец — существующий контроллер/сервис.
2. RLS-aware Eloquent: `SetTenantContext` middleware + `SET LOCAL app.current_tenant_id`; в queued-джобах под `crm_supplier_worker` (BYPASSRLS) — **явный** `where('tenant_id', ...)`; образец — `CsvReconcileJob`/`ImportLeadsJob`.
3. Деньги: bcmath / `LedgerService` (cross-ref billing-audit #62 — без копирования инвариантов, ссылка); образец — `LedgerService`.
4. Идемпотентные джобы: advisory-locks; образец — `HistoricalImportService`.
5. Partition-aware запросы к `deals` / `supplier_lead_costs`.

- [ ] **Step 3: Проверить, что скил обнаруживается**

Run: проверить, что `.claude/skills/laravel-backend-patterns/SKILL.md` валиден (frontmatter `name`+`description`). Запустить markdownlint/cspell локально (он линтуется — не в ignorePaths).

```bash
npx markdownlint-cli2 ".claude/skills/laravel-backend-patterns/**/*.md"
```

Expected: 0 ошибок (или авто-fix).

- [ ] **Step 4: Commit**

```bash
git add .claude/skills/laravel-backend-patterns/SKILL.md .claude/skills/laravel-backend-patterns/references/
git commit -m "feat(backend): laravel-backend-patterns skill — SKILL.md + conventions (#66)"
```

---

### Task 7: Скил evals (trigger-проверка)

**Files:**

- Create: `.claude/skills/laravel-backend-patterns/evals/evals.json`

- [ ] **Step 1: Написать failing evals (trigger + near-miss)**

```json
{
  "skill": "laravel-backend-patterns",
  "cases": [
    {"prompt": "как написать контроллер для новой backend-фичи в Лидерре", "should_trigger": true},
    {"prompt": "как правильно списать деньги в джобе под crm_supplier_worker", "should_trigger": true},
    {"prompt": "проверь, не теряются ли копейки в списании", "should_trigger": false, "expected": "billing-audit"},
    {"prompt": "опиши Clean Architecture в общем", "should_trigger": false, "expected": "architecture-patterns"},
    {"prompt": "учёт выручки по РСБУ", "should_trigger": false, "expected": "ru-tax-accounting"}
  ]
}
```

- [ ] **Step 2: Прогнать классификацию (skill-creator eval или ручная проверка description)**

Прогнать евал-кейсы против `description` (через skill-creator:skill-creator eval-режим или ручную проверку триггеров). Expected: trigger-кейсы → laravel-backend-patterns; near-miss → корректный сосед (billing-audit / architecture-patterns / ru-tax). Если near-miss перетягивает — уточнить `description` (граница по слою/операции).

- [ ] **Step 3: Commit**

```bash
git add .claude/skills/laravel-backend-patterns/evals/evals.json
git commit -m "test(backend): laravel-backend-patterns trigger evals (#66)"
```

---

## Phase 4 — NightOwl (#67)

### Task 8: NightOwl установка/конфиг per spike

**Files:**

- Modify: `app/composer.json` (require-dev)
- Modify (условно): `.mcp.json`, `tools/.l1-watcher-aliases.txt`
- Create: `docs/backend/nightowl-setup.md`

- [ ] **Step 1: Установить пакет сбора телеметрии**

Run (root `app/`):

```bash
composer require laravel/nightwatch --dev
```

Expected: `laravel/nightwatch` в require-dev.

- [ ] **Step 2: Настроить self-hosted ingest в PG (по выводам Task 3)**

По access-path из Task 3: настроить агент NightOwl на запись телеметрии в PostgreSQL Лидерры (отдельная схема/таблицы). Зафиксировать команды/конфиг в `docs/backend/nightowl-setup.md`. READ-ONLY для Claude.

- [ ] **Step 3 (условно — MCP доступен): зарегистрировать MCP + alias**

В `.mcp.json` добавить блок `nightowl` (READ-ONLY). В `tools/.l1-watcher-aliases.txt` добавить alias имени MCP-сервера → имя в Tooling Прил. Н (иначе C1 l1-watcher STRICT заблокирует коммит).
Smoke: `npx <nightowl-mcp> --help` (или эквивалент) verified.

- [ ] **Step 4 (условно — MCP только managed): зафиксировать Boost-fallback**

Если MCP недоступен — `.mcp.json` не трогаем; в `docs/backend/nightowl-setup.md` описать доступ к телеметрии через Boost `database-query` по таблицам nightwatch.

- [ ] **Step 5: Commit**

```bash
git add app/composer.json app/composer.lock docs/backend/nightowl-setup.md .mcp.json tools/.l1-watcher-aliases.txt
git commit -m "feat(backend): NightOwl self-hosted telemetry + access-path (#67)"
```

---

## Phase 5 — ADR + роутер/наблюдатель

### Task 9: ADR-013

**Files:**

- Create: `docs/adr/ADR-013-backend-tooling.md`

- [ ] **Step 1: Прочитать шаблон ADR**

Прочитать `docs/adr/ADR-012-*.md` (последний) как шаблон структуры (Status / Context / Decision / Consequences / Enforcement).

- [ ] **Step 2: Написать ADR-013**

Содержание: Decision — 4 узла backend-tooling + границы; Consequences — BT1–BT9 (§8 спеки); Enforcement-блок (если применимо к adr-judge — декларативные forbid/require; иначе пустой/информационный). Включить gate-решения из Task 1/3 (Rector posture, NightOwl access-path).

- [ ] **Step 3: Проверить adr-judge не падает**

Run (root):

```bash
git diff --cached --unified=0 | python -X utf8 tools/adr-judge.py --diff - --adr-dir docs/adr/
```

Expected: нет нарушений на собственном диффе.

- [ ] **Step 4: Commit**

```bash
git add docs/adr/ADR-013-backend-tooling.md
git commit -m "docs(adr): ADR-013 backend-tooling boundaries (BT1-BT9)"
```

---

### Task 10: routing-off-phase.md + router-procedure.md

**Files:**

- Modify: `docs/routing-off-phase.md`
- Modify: `docs/router-procedure.md`

- [ ] **Step 1: Прочитать текущие файлы**

Прочитать `docs/routing-off-phase.md` (формат routing-таблицы + связки L1–L13) и `docs/router-procedure.md` (header version v1.1).

- [ ] **Step 2: Добавить 4 строки routing-таблицы**

Для #64–67 — строки «триггер задачи → узел» (значения routing-trigger из спеки §3 / Task 11 атрибутов). Bump version routing-off-phase v1.2 → v1.3.

- [ ] **Step 3: Добавить каноническую связку L14**

L14 «backend-quality chain»: Rector (#64) → PHP Insights (#65) → Larastan (#12) → deptrac (#43). + anti-pattern: Rector-автоправка и PHP Insights-метрика — разные фазы, не один блокирующий шаг.

- [ ] **Step 4: Bump router-procedure.md**

router-procedure v1.1 → v1.2: процедура не меняется, обновить cross-ref-строку/счётчик узлов под новый набор.

- [ ] **Step 5: Verify lychee + commit**

```bash
./bin/lychee.exe --config .lychee.toml "docs/routing-off-phase.md" "docs/router-procedure.md"
git add docs/routing-off-phase.md docs/router-procedure.md
git commit -m "docs(router): +4 backend nodes routing + L14 chain (routing-off-phase v1.3, router-procedure v1.2)"
```

---

## Phase 6 — Нормативка (АТОМАРНЫЙ набор — C2 STRICT)

### Task 11: Tooling + PSR_v1 + Pravila + CLAUDE.md — один атомарный коммит

> **Критично:** cross-ref-checker (C2, lefthook job 12) STRICT — все §0/header cross-refs между этими 4 файлами должны совпасть. Поэтому **все 4 файла редактируются и коммитятся ОДНИМ коммитом.** l1-watcher (C1) тоже проверит NightOwl MCP формализацию (см. Task 8 alias).

**Files:**

- Modify: `docs/Tooling_v8_3.md`
- Modify: `docs/Plugin_stack_rules_v1.md`
- Modify: `docs/Pravila_raboty_Claude_v1_1.md`
- Modify: `CLAUDE.md`

- [ ] **Step 1: Tooling Прил. Н — §4.39–4.42 (9-атрибутные блоки)**

Прочитать §4.36 (finance plugin) как канонический шаблон 9-attribute блока, реплицировать структуру для 4 узлов со значениями:

- **§4.39 #64 Rector** — name@source: Rector+rector-laravel @ rectorphp/rector + driftingly/rector-laravel (Composer dev-dep); category: backend-tooling (off-phase, 16-я); install: `composer require rector/rector driftingly/rector-laravel --dev` + `app/rector.php`; activation: gate-постура Task 1 (lefthook job 16 если N≈0, иначе composer+CI); conflicts: BT1/BT2/BT3 (ADR-013); dormant: false; routing-trigger: «обнови/почини/рефактори backend-код», апгрейд Laravel-версии, dead-code; cost: 0 LLM.
- **§4.40 #65 PHP Insights** — @ nunomaduro/phpinsights (Composer dev-dep); backend-tooling; install: `composer require nunomaduro/phpinsights --dev` + `app/phpinsights.php`; activation: on-demand/CI (`composer insights`), НЕ lefthook (BT9); conflicts: BT4 (ADR-013); dormant: false; routing-trigger: «оцени качество/сложность кода», «где код запутан», аудит; cost: 0 LLM.
- **§4.41 #66 laravel-backend-patterns** — @ self-authored (`.claude/skills/`); backend-tooling; install: project skill auto-discovered; activation: trigger-based; conflicts: BT5/BT6 (ADR-013); dormant: false; routing-trigger: «как писать контроллер/сервис/джоб в Лидерре», scaffolding backend-фичи; cost: skill inference.
- **§4.42 #67 NightOwl** — name@source: NightOwl(self-hosted) @ lemed99/nightowl-agent + laravel/nightwatch; backend-tooling; install: `composer require laravel/nightwatch --dev` + nightowl-agent → PG; activation: active READ-ONLY, access-path per Task 3; conflicts: BT7/BT8 (ADR-013); dormant: false; routing-trigger: «почему медленно/падает в runtime», коррелированный трейс request↔job↔query; cost: 0 LLM.

§0 счётчик: 63 → **67**; добавить 16-ю off-phase подкатегорию «backend-tooling». Header Прил. Н: v2.18 → **v2.19** + наследие-строка.

- [ ] **Step 2: PSR_v1 — R10.1 +4 строки + header**

R10.1 Блок 1/3: +4 строки (#64–67, категория backend-tooling, не UI → вне R6/R14). Header v3.18 → **v3.19** + наследие.

- [ ] **Step 3: Pravila — §13.2 +абзац + header**

§13.2: +абзац «Off-phase backend-tooling» (#64 Rector / #65 PHP Insights / #66 laravel-backend-patterns / #67 NightOwl — 16-я подкатегория; счётчики — пин на Tooling Прил. Н §0). Header v1.34 → **v1.35** + §10 changelog.

- [ ] **Step 4: CLAUDE.md — §3.3 + §6 + §9 + header**

- §3.3: +4 строки #64–67 (однострочный индекс, пин на Tooling §4.39–4.42).
- §6: +абзац «2026-05-20 A1 backend-tooling integration» сверху.
- §9: +запись v2.22.
- §0 cross-refs: Pravila v1.35 / PSR_v1 v3.19 / Tooling Прил.Н v2.19.
- Header: v2.21 → **v2.22**.
(Прямой Edit — worktree-эксцепшн §5 п.10.)

- [ ] **Step 5: Verify cross-refs локально перед коммитом**

Run (root):

```bash
node tools/cross-ref-checker.mjs
node tools/l1-watcher.mjs
```

Expected: оба чисто (нет version drift; NightOwl MCP формализован/aliased).

- [ ] **Step 6: Атомарный commit (все 4 файла вместе)**

```bash
git add docs/Tooling_v8_3.md docs/Plugin_stack_rules_v1.md docs/Pravila_raboty_Claude_v1_1.md CLAUDE.md
git commit -m "docs(normative): A1 backend-tooling #64-67 — Tooling v2.19/PSR v3.19/Pravila v1.35/CLAUDE v2.22"
```

---

## Phase 7 — Карта

### Task 12: automation-graph-data.js +4 узла + рёбра + версии

**Files:**

- Modify: `docs/automation-graph-data.js`

- [ ] **Step 1: Добавить 4 узла в NODES + NODE_SECTION (все A1)**

Прочитать блок finance (`finance_plugin`/`billing_audit`/`ru_tax`) как образец. Добавить узлы `rector`, `php_insights`, `backend_patterns`, `nightowl` в `NODES` (group по типу: lefthook/agents/mcp/skills_proj) + в `NODE_SECTION` все 4 → `'A1'`. Reuse-кросс-рефы в `NODE_SECTION_SECONDARY` если есть (напр. backend_patterns → секция C6? нет — оставить только A1).

- [ ] **Step 2: Добавить рёбра**

Рёбра L14-цепочки (rector→php_insights→larastan/deptrac) + reuse-связи (backend_patterns↔billing_audit, nightowl↔mcp_sentry/mcp_boost). Обновить версии-метки шапки карты (v1.35/v2.22/v3.19/v2.19) + счётчики узлов/рёбер.

- [ ] **Step 3: Browser-smoke карты**

Открыть `docs/automation-graph.html` через Playwright MCP, проверить: 4 новых узла рендерятся в секторе A1, рёбра присутствуют, нет JS-ошибок в консоли. Скриншот.

- [ ] **Step 4: Commit**

```bash
git add docs/automation-graph-data.js
git commit -m "feat(map): +4 A1 backend-tooling nodes + L14 chain (137→141 nodes)"
```

---

## Phase 8 — Финал

### Task 13: Полная регрессия + finishing

**Files:** (нет правок)

- [ ] **Step 1: Полная регрессия**

Run (root `app/`):

```bash
composer pint -- --test
composer stan
php vendor/bin/pest --parallel --recreate-databases
```

Запустить Vitest если затронут frontend (не затронут — пропустить). Expected: Pint 0, Larastan 0 above baseline, Pest GREEN (выписать точные числа passed/failed с file:line при падении).

- [ ] **Step 2: Pre-push проверки**

Run (root):

```bash
./bin/gitleaks.exe detect --source . --no-banner --config .gitleaks.toml --redact
./bin/lychee.exe --config .lychee.toml "docs/**/*.md" "*.md"
```

Expected: gitleaks 0; lychee 0 broken (untracked spike-доки — если ломают, добавить в exclude или закоммитить).

- [ ] **Step 3: finishing-a-development-branch**

Использовать `superpowers:finishing-a-development-branch` — представить заказчику опции (push в main / PR / cleanup). Push паттерн `git push origin <ветка>:main` (memory reference_github).

---

## Self-Review (исполнено при написании плана)

**Spec coverage:**

- Спека §2 (4 узла + out-of-scope) → Tasks 1/2/6/8 (узлы), out-of-scope зафиксирован в ADR Task 9. ✅
- Спека §3 (детали узлов + границы) → Tasks 4/5/6/8 + ADR Task 9. ✅
- Спека §4 (роутер) → Task 10. ✅
- Спека §5 (наблюдатель: 9-атрибуты + C1/C2) → Task 11 (9-атрибуты §4.39-42, C1/C2 verify Step 5). ✅
- Спека §6 (нормативка атомарно) → Task 11. ✅
- Спека §7 (карта) → Task 12. ✅
- Спека §8 (BT1–BT9) → Task 9 ADR. ✅
- Спека §9 (spikes) → Tasks 1/2/3 + verify. ✅
- Спека §10 (worktree subagent-driven) → Pre-flight + execution handoff. ✅

**Placeholder scan:** `<N>`/`<Q>`/`<C>`/`<A>` — намеренные spike-выходы (заполняются в Task 1/2), не placeholder-долги. Условные шаги (Task 4 Step 4, Task 8 Step 3/4) явно помечены ветвлением по spike-результату. ✅

**Type consistency:** имена узлов карты (`rector`/`php_insights`/`backend_patterns`/`nightowl`), номера (#64–67), §4.39–4.42, версии (v1.35/v3.19/v2.19/v2.22), коды BT1–BT9, связка L14 — единообразны across задач. ✅
