# Полный аудит портала Лидерра — Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans (recommended for этого аудита — последовательные фазы с verify-gates). Subagent dispatch — точечно для Phase 1 (4 независимых блока статанализа).

**Дата:** 2026-05-12
**Ветка:** `plan5-frontend-projects` (79 commits ahead of `main`, 0 commits behind upstream)
**Режим:** экономия 0% (full reads, full output, verify-before-completion обязателен на каждом шаге)
**Триггер:** заказчик уходит спать, попросил «полный аудит, выяви все ошибки, неработающие элементы, неточности; исправь что сможешь; вопросы фиксируй и продолжай»

## Согласованные решения (2026-05-12 ночь, перед стартом)

1. **Phase 5 UI smoke = Full × 24 + interactive.** Все 24 view + критические interactive flows (login, dashboard, create deal, kanban drag, billing pricing tiers, admin tenants создать-сменить статус). Бюджет 120+ мин. Phase 8 fix-loop соответственно сокращается, но за ночь укладывается.
2. **DemoSeeder.php — read + использовать после проверки безопасности.** Сначала Read содержимое; если seeder создаёт только tenant+admin+тест-данные (без вызовов prod API / external calls) — `php artisan db:seed --class=DemoSeeder` на dev. Если найду опасные паттерны — записать в blocked, skip seeder, fallback на tinker.
3. **38 untracked .png — переместить в `audit-screens/legacy/`.** Не удалять (могут быть полезные ссылки на skeleton'ы прошлых fix'ов), но убрать из git status шума.
4. **Phase 9 final commit — push на `plan5-frontend-projects`.** После прохода pre-push lefthook (gitleaks-full-history + lychee). НЕ push на main; НЕ create PR (пользователь утром решит сам).

**Goal:** Снять состояние портала по 7 осям (статанализ × 8 tools, runtime tests × 3, UI smoke через Playwright по 24+ экранам, schema-integrity, SAST/gitleaks, doc cross-ref integrity, реестр open-questions vs фактический state). Зафиксировать все находки. Исправить всё, что не пересекается с правилами-стопами из §«Decision tree» ниже. Зафиксировать blocked-вопросы заказчику в `docs/superpowers/audits/.../-blocked.md`.

**Архитектура подхода:** девять phase'ов, каждый завершается verify-gate (`Expected:` блок). Phase 1 — параллельный subagent dispatch на 4 независимых статанализа (backend/frontend/docs/sql). Phase 5 — UI smoke через Playwright MCP в режиме golden path × 24+ экрана с скриншотами и console-капчёй. Phase 7 — categorization gate перед массовыми правками. Phase 8 — fix-loop в порядке P0 → P1 → P2 → P3, по одному logical group → один commit, после каждого relevant verify (Pest/Vitest по контексту).

**Tech stack:** Pest 4 + Vitest 4 + Histoire 1.0-beta.1 + Vite 8 + vue-tsc 3.2 + ESLint 10 + Prettier 3 + Larastan 3.9 + Pint 1.29 + squawk 2.51 + pgFormatter 5.9 + Semgrep + gitleaks + cspell + markdownlint-cli2 + lychee + Playwright MCP + claude-md-management skill (для CLAUDE.md правок) + writing-plans + dispatching-parallel-agents + verification-before-completion skills.

**Артефакты:**

- `docs/superpowers/audits/2026-05-12-portal-full-audit-report.md` — итоговый сводный отчёт (executive summary + per-phase)
- `docs/superpowers/audits/2026-05-12-portal-full-audit-findings.md` — детальный список находок с `file:line` + severity + статус (fixed/blocked/deferred)
- `docs/superpowers/audits/2026-05-12-portal-full-audit-blocked.md` — вопросы заказчику (P0 product/design decisions, новые pending для реестра)
- `audit-screens/` — UI smoke скриншоты (npm `start` portal + Playwright)
- Один commit на одну logical fix-group; финальный `chore(audit): summary report + findings` commit поверх всех

---

## Decision tree во время аудита (read each phase under this lens)

**Hard-stop (не делать без явного `закрываем` от заказчика):**

1. **НЕ менять `db/schema.sql`** — Pravila §4.2 требует синхронной правки `db/CHANGELOG_schema.md` + согласования.
2. **НЕ закрывать `Биз-*`/`CTO-*`/`Ю-*`/`Диз-*`/`DO-*`/`OPEN-*`** — Pravila §2.2.
3. **НЕ устанавливать новые пакеты** (`composer require`/`npm install --save`) — Pravila §13.10 + PSR_v1 R0.6 hard-stop.
4. **НЕ трогать** `docs/CRM_bp-gr_Инструкция_v8_5.md`, `BRANDBOOK_v2.md`, `DEVELOPER_HANDOFF.md` — ТЗ и handoff = first sources.
5. **НЕ править корневой `CLAUDE.md` напрямую** — только через `claude-md-management:claude-md-improver` или `revise-claude-md` (§5 п.10).
6. **НЕ trigger force-push, reset --hard, branch -D, --no-verify** — Bash-tool safety.

**Можно делать (без эскалации):**

- Fix lint (Pint, ESLint, markdownlint) на staged-видимых сейчас файлах.
- Fix Larastan ошибок выше baseline (новые) — фиксим до baseline.
- Fix Vitest/Pest упавших тестов, если корень причины очевиден (1 файл, 1 hypothesis после ≥3-гипотезного falsification).
- Fix typos в docs (cspell positives после проверки), битые ссылки (lychee, если URL изменился очевидно).
- Fix unused imports/vars от knip.
- Fix новые ESLint `no-explicit-any` / `no-unused-vars` / type-ошибок vue-tsc.
- Удалить ghost-screenshots из workdir (38 `.png` в git status — pre-session dirt) после явного user-OK на удаление.
- Запустить migrate:fresh на dev — деструктивно, но dev только; запросить confirmation если найду drift schema vs CLAUDE.md метрик.
- Обновить CLAUDE.md/memory если найду расхождения через `claude-md-management`.

**Если сомнение → пиши в `-blocked.md` и продолжай.** Не блокировать ночной прогон на ожидание ответа.

---

## Phase 0 — Pre-flight (≈3 мин)

**Files:**

- Read-only: `git status`, `git log --oneline -50`, `git fetch && git status -sb`
- Create: `docs/superpowers/audits/2026-05-12-portal-full-audit-findings.md` (skeleton)
- Create: `docs/superpowers/audits/2026-05-12-portal-full-audit-blocked.md` (skeleton)
- Create: `audit-screens/` directory

- [ ] **Step 0.1: Fetch + branch sanity**

```
git fetch origin
git log --oneline -1 origin/plan5-frontend-projects
git log --oneline -1 HEAD
git log --oneline -1 origin/main
```

Expected: `HEAD == origin/plan5-frontend-projects == b5849bb`; `origin/main == 615db99`; нет divergence.

- [ ] **Step 0.2: Inventory ghost files**
38 untracked `.png` файлов + 2 untracked `docs/superpowers/specs|plans/*` от Quiet Luxury session. Не удалять — заказчик их не видел. Записать в `findings.md` под `[Phase 0] workspace dirt: 38 PNG + 2 docs uncommitted`. Скриншоты от прошлых сессий не мешают аудиту — оставить.

- [ ] **Step 0.3: Создать skeletons файлов**

`docs/superpowers/audits/2026-05-12-portal-full-audit-findings.md`:

```markdown
# Portal Full Audit — Findings (2026-05-12)

## Severity легенда
- P0 — блокирует production / data corruption / security incident
- P1 — нарушение функциональности / failing test / type error / a11y violation
- P2 — warning / style / dead code / stale doc
- P3 — cosmetic / nice-to-have

## Phase 0 — Pre-flight
…

## Phase 1 — Static analysis
…
(остальные phase'ы заполняются по ходу)
```

`docs/superpowers/audits/2026-05-12-portal-full-audit-blocked.md`:

```markdown
# Portal Full Audit — Blocked questions (2026-05-12)

## Что нужно от заказчика для закрытия
…
```

- [ ] **Step 0.4: Commit skeletons (если они появятся)**
Не коммитим скелеты пустыми — заполним содержимым из Phase 1+. Финальный commit аудита соберёт это всё.

---

## Phase 1 — Static checks (parallel, ≈8-12 мин)

**Подход:** dispatching-parallel-agents — 4 независимых subagent через одно сообщение с 4 `Agent` calls. Каждый возвращает **raw output** (как требует экономия 0%), не summary. Результаты в `findings.md` под `## Phase 1`.

**Subagent A — Backend static** (general-purpose):

```
cd app
composer pint --test         # zero-tolerance — должен быть 0 issues
composer stan                # должен пройти baseline. Новые ошибки = P1.
composer audit-offline       # composer audit --locked. CVE = P0.
```

Expected: pint 0 issues, stan 0 errors above baseline, audit 0 advisories. Любое отклонение → P0/P1 в findings.

**Subagent B — Frontend static** (general-purpose):

```
cd app
npx eslint "resources/js/**/*.{ts,vue}" "tests/Frontend/**/*.ts" --max-warnings=0
npx vue-tsc --noEmit
npx prettier --check "resources/js/**/*.{ts,vue,css}" "tests/Frontend/**/*.ts"
npx knip --production --reporter=compact   # report-only; найдёт unused exports/files/deps
```

Expected: eslint 0/0, vue-tsc 0 errors, prettier all formatted. knip — informational; mark в findings как `[Phase 1 / Subagent B / knip] N unused exports` для review в Phase 7. **Tail-context**: VSCode-extension running, относительные импорты вместо `@/` alias (memory: квирк 52).

**Subagent C — Docs/Markdown** (general-purpose):

```
cd "c:/моя/проекты/портал crm/Документация"
npm run lint:md
npm run spell
./bin/lychee.exe --config .lychee.toml "docs/**/*.md" "db/**/*.md" "*.md"
```

Expected: markdownlint 0 issues, cspell 0 unknown words, lychee 0 broken links. Tail-context: cspell словарь `cspell-words.txt`, lychee config `.lychee.toml`.

**Subagent D — SQL/Schema** (general-purpose):

```
cd "c:/моя/проекты/портал crm/Документация"
./bin/squawk.exe db/schema.sql
perl -I bin/pgFormatter/lib bin/pgFormatter/pg_format db/schema.sql > db/.schema-formatted.tmp.sql
diff -q db/schema.sql db/.schema-formatted.tmp.sql
rm db/.schema-formatted.tmp.sql 2>/dev/null
```

Expected: squawk 0 issues (есть `.squawk.toml` exclude list), pgFormatter — `diff` пуст ИЛИ только cosmetic whitespace (если diff не пуст — P3 в findings, не fix самим pgFormatter potentially-перепишет structure).

- [ ] **Step 1.0: Запустить 4 subagent параллельно** (одно сообщение, 4 Agent tool uses; `description` ≤5 слов; в `prompt` — точное название блока + точные команды + явное «верни raw output, не summary; verify exit codes; запиши findings под P0/P1/P2/P3 в формате `file:line — описание`»).

- [ ] **Step 1.1: Aggregate findings**
Собрать 4 raw outputs → дописать в `findings.md` под `## Phase 1`. Categorize: P0 (audit advisories, CVE), P1 (lint errors, type errors, broken links), P2 (warnings, knip unused), P3 (style/cosmetic).

**Expected total time:** 8-12 мин (parallel). Self-review trigger §8: ≥3 групп патчей в дальнейшем → схема-метрики сверка + 0 orphan-FK; пока только инвентаризация.

---

## Phase 2 — Test suites (sequential, ≈10-18 мин)

**Files:**

- Read-only: запуск тестов

- [ ] **Step 2.1: Pest без --parallel**

```
cd app
php artisan config:clear --ansi
php artisan test --without-tty 2>&1 | tail -200
```

Expected: 742+ passed (memory: 742/738/1 flaky/3 skipped) или близко. Любой failure ≠ известных flaky (если найду «flaky-known» — записать) → P1 в findings с `file:test_name — assertion message`.

Memory-quirk учесть: dev-БД `liderra` теперь ICU; test `liderra_testing` всё ещё `Russian_Russia.1251`. **Если** Pest падает на cyrillic ILIKE — это «known» (квирк 61) для test-DB, не P0; записать в findings как P2 с предложением «применить recreate с ICU на `liderra_testing`».

- [ ] **Step 2.2: Pest с --parallel (вторая прогон для flaky detection)**

```
cd app
php artisan test --parallel --without-tty 2>&1 | tail -200
```

Expected: те же ±1 flaky. Diff между --parallel и no-parallel → P2 для investigation.

- [ ] **Step 2.3: Vitest**

```
cd app
npx vitest run --reporter=verbose 2>&1 | tail -200
```

Expected: 579+/582 (memory: foundation tests + квирки 53-57 могут давать ±). Failed → P1. Записать `file:line — message`.

- [ ] **Step 2.4: Histoire build (smoke)**

```
cd app
npx histoire build 2>&1 | tail -80
```

Expected: 24+ stories / 31+ variants собрались. Build fail → P1.

- [ ] **Step 2.5: Vite production build (smoke)**

```
cd app
npx vite build 2>&1 | tail -120
```

Expected: build success, no warnings о circular deps / large chunks > 500 KB (если есть — P2 + bundle-analyzer запустить отдельно в Phase 7). Записать chunk sizes top-10 в findings для inventory.

- [ ] **Step 2.6: Aggregate test findings**
Дописать в `findings.md` под `## Phase 2`.

**Expected total time:** 10-18 мин.

---

## Phase 3 — Schema integrity (≈5 мин)

**Цель:** сверить факт схемы с заявленными метриками CLAUDE.md §0 / §2 / §8 (v8.19: **62 base tables + 12 partitions + 117 indexes + 39 RLS-policies + 5 functions + 13 triggers + 5 DB roles**).

**Files:**

- Read-only: query через Laravel Boost MCP (предпочтительно — мнеемкее) ИЛИ `psql -d liderra -c "..."`

- [ ] **Step 3.1: Сверить базовые таблицы**
Через Laravel Boost MCP `mcp__laravel-boost__database-query`:

```sql
SELECT count(*) FROM information_schema.tables
WHERE table_schema='public' AND table_type='BASE TABLE'
  AND table_name NOT LIKE '%_p20%' AND table_name NOT LIKE '%_default%';
```

Expected: `62`. Diff → P1 (drift), в findings с конкретным `actual_count`.

- [ ] **Step 3.2: Индексы**

```sql
SELECT count(*) FROM pg_indexes WHERE schemaname='public';
```

Expected: `117`.

- [ ] **Step 3.3: RLS-политики**

```sql
SELECT count(*) FROM pg_policies WHERE schemaname='public';
```

Expected: `39`.

- [ ] **Step 3.4: Функции + триггеры**

```sql
SELECT count(*) FROM pg_proc p JOIN pg_namespace n ON p.pronamespace=n.oid WHERE n.nspname='public';
SELECT count(*) FROM pg_trigger WHERE NOT tgisinternal;
```

Expected: `5` функций, `13` триггеров.

- [ ] **Step 3.5: DB-роли**

```sql
SELECT rolname FROM pg_roles WHERE rolname LIKE 'crm_%';
```

Expected: 5 ролей включая `crm_supplier_worker` (Plan 3+4).

- [ ] **Step 3.6: Orphan FK check (self-review trigger §8)**

```sql
SELECT conname, conrelid::regclass FROM pg_constraint
WHERE contype='f'
AND NOT EXISTS (SELECT 1 FROM pg_class WHERE oid=confrelid);
```

Expected: 0 rows.

- [ ] **Step 3.7: Aggregate**
Дописать в `findings.md` под `## Phase 3` таблицу `metric | expected | actual | diff`. Если все equal → `## Phase 3 — clean`.

**Expected total time:** 5 мин.

---

## Phase 4 — Security scan (≈15-30 мин)

**Files:**

- Read-only: scan

- [ ] **Step 4.1: gitleaks полная история**

```
cd "c:/моя/проекты/портал crm/Документация"
./bin/gitleaks.exe detect --source . --no-banner --config .gitleaks.toml --redact 2>&1 | tail -100
```

Expected: 0 leaks. **Any leak = P0**. Если найдено — НЕ удалять без consent (может потребоваться history rewrite или allowlist-добавление); записать в findings + blocked.

- [ ] **Step 4.2: Semgrep SAST**

```
cd "c:/моя/проекты/портал crm/Документация"
npx semgrep --config=p/php --config=p/javascript --config=p/typescript --config=p/secrets --config=.semgrep.yml --error --time --json --output=audit-semgrep.json 2>&1 | tail -80
```

Expected: 0 high/critical. Низкие severity → P2 list. Если Semgrep не установлен глобально — запустить через `pip install semgrep` skipped (нельзя ставить пакеты — Pravila §13.10) → mark `[Phase 4 Semgrep] tool unavailable, requires local install` blocked.

- [ ] **Step 4.3: Roave/SecurityAdvisories check (already in composer.json)**

```
cd app
composer audit --locked 2>&1 | tail -40
```

Expected: уже сделано в Phase 1 Subagent A — cross-link, не дублировать.

- [ ] **Step 4.4: Aggregate**
Дописать в `findings.md` под `## Phase 4`.

**Expected total time:** 15-30 мин (Semgrep — самая медленная часть).

---

## Phase 5 — UI smoke через Playwright (≈40-60 мин)

**Цель:** golden path × 24 view, capture screenshots + console + network 4xx/5xx + axe-like a11y через Pa11y, найти неработающие элементы.

**Files:**

- Background: `cd app && php artisan serve --port=8000` + `cd app && npm run dev`
- Tool: Playwright MCP (`mcp__playwright__browser_*`)
- Output: `audit-screens/<view-name>.png`, `audit-screens/<view-name>-console.txt`

**Roster экранов (24+):**

| Тип | View | Path | Auth required |
|---|---|---|---|
| auth | LoginView | /login | no |
| auth | RegisterView | /register | no |
| auth | TwoFactorView | /2fa | partial |
| auth | RecoveryCodesView | /recovery | partial |
| auth | UseRecoveryCodeView | /use-recovery | partial |
| auth | ForgotPasswordView | /forgot | no |
| auth | ResetPasswordView | /reset | no |
| main | DashboardView | /dashboard | yes |
| main | DealsView | /deals | yes |
| main | KanbanView | /kanban | yes |
| main | ProjectsView | /projects | yes |
| main | ReportsView | /reports | yes |
| main | BillingView | /billing | yes |
| main | SettingsView | /settings | yes |
| main | RemindersView | /reminders | yes |
| admin | AdminTenantsView | /admin/tenants | yes (admin) |
| admin | AdminTenantDetailView | /admin/tenants/:id | yes |
| admin | AdminBillingView | /admin/billing | yes |
| admin | AdminIncidentsView | /admin/incidents | yes |
| admin | AdminSystemView | /admin/system | yes |
| admin | AdminImpersonationView | /admin/impersonation | yes |
| admin | AdminPricingTiersView | /admin/pricing-tiers | yes |
| admin | AdminSupplierPricesView | /admin/supplier-prices | yes |
| errors | ErrorView 404 | /not-found-path | n/a |
| errors | ErrorView 403 | (trigger via tenant mismatch) | n/a |
| errors | ErrorView 500 | (n/a — нельзя гарантированно вызвать) | n/a |

- [ ] **Step 5.1: Start dev servers (background, run_in_background=true)**

```
cd app && php artisan serve --port=8000
cd app && npm run dev
```

**ВАЖНО**: оба в background; ждать ≈10 сек на boot (Vite HMR ≈3-7 сек, artisan serve ≈2 сек). Получить URL Vite (обычно http://127.0.0.1:5173 + Laravel-config через `laravel-vite-plugin`).

Запасной вариант если Vite порт занят / artisan конфликтует с lock'ом — `php artisan config:clear`, перезапуск.

- [ ] **Step 5.2: Подготовка seed-пользователя для логина**
Проверить, есть ли уже seeded admin/tenant у `php artisan db:seed --class=DemoSeeder` (есть `DemoSeeder.php` untracked — скорее всего создан в прошлой сессии, проверить содержимое и **НЕ** запускать без awareness; альтернатива — `tinker`-команда создать минимального user).

Если seed недоступен — записать `[Phase 5] no demo seed available — skipping auth-required views beyond login screen` в blocked, продолжать со screenshot'ами только auth-views.

- [ ] **Step 5.3: Loop по экранам**
Для каждого экрана:

1. `mcp__playwright__browser_navigate` → URL
2. `mcp__playwright__browser_wait_for` networkidle (≈2 сек)
3. `mcp__playwright__browser_take_screenshot` → `audit-screens/<view>.png` (full page)
4. `mcp__playwright__browser_console_messages` → собрать errors/warnings → `<view>-console.txt`
5. `mcp__playwright__browser_network_requests` → найти 4xx/5xx → `<view>-net.txt`
6. Опционально: `mcp__playwright__browser_evaluate` инжект axe-core минимальной проверки роли/контраста (если получится без npm-install — Pa11y запускать отдельно)
7. Записать в findings: `[Phase 5 <view>] OK` ИЛИ список observed issues (`console error: foo`, `network 404 /api/bar`, `visual: text overflows on .ld-card` — со скриншот-ref'ом)

- [ ] **Step 5.4: Pa11y по live URL'ам**
Pa11y configured в `pa11y.config.json` — проверить content (наверняка указывает на `web/v8/*.html` концепты; для live URL потребует временной правки конфига, что не P0). Запустить как есть для baseline; если нацелено на `web/v8/*.html` — это check концептов, не реального портала. Записать P2 если найду divergence.

- [ ] **Step 5.5: Aggregate UI findings**
Дописать в `findings.md` под `## Phase 5` per-view блоки + сводная таблица «view | status | issue count P0/P1/P2/P3».

- [ ] **Step 5.6: Stop dev servers**
KillBash оба фоновых процесса.

**Expected total time:** 40-60 мин (sequential по экранам, Playwright MCP slow per-call).

---

## Phase 6 — Cross-doc integrity (≈10 мин)

**Цель:** сверить декларации в CLAUDE.md / Pravila / Tooling / PSR_v1 / memory с фактическим состоянием.

**Files:**

- Read-only: cross-check
- Write (через `claude-md-management:claude-md-improver`): CLAUDE.md обновления если найду stale

- [ ] **Step 6.1: Cross-ref versions**
Прочитать шапки (frontmatter / topmost версионные строки):
- `CLAUDE.md` (v1.87 на 2026-05-12 ночь)
- `docs/Pravila_raboty_Claude_v1_1.md` (v1.11)
- `docs/Plugin_stack_rules_v1.md` (v2.0)
- `docs/Tooling_v8_3.md` (v1.16)
- `docs/Открытые_вопросы_v8_3.md` (v1.81)

Сверить cross-refs. Memory говорит: CLAUDE.md v1.88, Pravila v1.11, PSR_v1 v2.0, Tooling v1.16, реестр v1.81. **Если факт-версия меньше memory** — memory stale, перезаписать через `memory_state.md` update. **Если факт-версия больше memory** — нормально, обновить memory.

- [ ] **Step 6.2: Schema metrics в CLAUDE.md vs Phase 3**
CLAUDE.md §0 row «Схема БД» / §2 / §6 / §8 декларируют v8.19 = 62/12/117/39/5/13/5. Phase 3 actual цифры → diff. Если drift → `claude-md-improver` targeted update (правка только §0/§2/§6/§8 чисел).

- [ ] **Step 6.3: Open-questions registry sanity**
Прочитать `docs/Открытые_вопросы_v8_3.md` § «Сводка» (~line 2186) → таблица счётчиков (open/in-progress/closed). Найти все «P0» / «BLOCKED» / «открыт» строки. Сверить с CLAUDE.md §6 «Биз-25..31 / DO-*/ OPEN-* / etc». Любое расхождение → P2 в findings.

- [ ] **Step 6.4: Memory consistency**
Прочитать `memory/MEMORY.md` индекс. Найти rows ссылающиеся на конкретные file:line или версии. Cross-check с current state. Особое внимание:
- `project_state.md` → branch, commit count, test counts
- `feedback_environment.md` → 62 квирка
- `reference_archive.md` → cross-refs версий
- `project_supplier_integration.md` → Plan progression
- `project_portal_redesign.md` → 20 commits на ветке
- `project_dev_indices.md` → 10 commits + temporary feature flag

Stale → update memory file. Если расхождение существенное (например, branch уже merged в main — не нашёл такого в Phase 0, но проверить) → blocked для confirm.

- [ ] **Step 6.5: Aggregate**
Дописать в `findings.md` под `## Phase 6`. Если есть docs-fixes — применить через skill, commit отдельно.

**Expected total time:** 10 мин (сама сверка) + 5-15 мин (применение fixes через claude-md-improver, если нужны).

---

## Phase 7 — Categorize + plan fixes (≈5 мин, no tool calls)

**Цель:** просмотреть весь `findings.md`, расставить severity, решить что фиксим vs документируем.

- [ ] **Step 7.1: Severity pass**
Каждая находка → P0/P1/P2/P3 (легенда в шапке `findings.md`). Конфликты — приоритет более высокий.

- [ ] **Step 7.2: Fix-eligibility classify**
Для каждой находки — флаг `[FIX-NOW]`, `[FIX-DEFER]`, `[BLOCKED]`:
- `[FIX-NOW]`: попадает под «Можно делать» из decision-tree, я могу решить sam без user-input, фикс ≤30 min — фиксим в Phase 8.
- `[FIX-DEFER]`: можно фикснуть, но требует ≥1 час / большой refactor / захватывает несколько модулей — записать как новый pending в `-blocked.md` как «предлагаемая задача для следующей сессии».
- `[BLOCKED]`: попадает под hard-stop из decision-tree (schema, регистрационные вопросы, новые packages, ТЗ-правки) → `-blocked.md` с явным «нужно от заказчика: <решение>».

- [ ] **Step 7.3: Order fix-queue**
P0 → P1 → P2 → P3 внутри каждого — по «cheap first» (быстрые wins перед dolgo). Записать в `findings.md` секцию `## Phase 7 — Fix Queue` упорядоченный list с ID.

**Expected total time:** 5 мин.

---

## Phase 8 — Fix loop (≈variable, до конца сессии)

**Подход:** TDD где применимо (для PHP — Pest test first; для Vue — Vitest test first; для config-only — skip TDD). Один logical fix → один commit. После каждого commit — relevant verify (контекстный test prepository file). Self-review trigger §8 после ≥3 групп.

**Pattern per fix:**

- [ ] **Step 8.N.1: Pick top finding from queue**

- [ ] **Step 8.N.2: Write failing test** (если применимо — code fix, не config)

- [ ] **Step 8.N.3: Run test → verify FAIL**

- [ ] **Step 8.N.4: Implement fix**

- [ ] **Step 8.N.5: Run test → verify PASS**

- [ ] **Step 8.N.6: Run relevant suite (всё что зависит от файла)**
- PHP fix → `php artisan test --filter=<related>` or full Pest
- Vue fix → `vitest run <related-file>` or full Vitest
- Lint fix → relevant lint command (pint --test, eslint, markdownlint)
- Schema fix → **STOP** — это hard-stop из decision-tree

- [ ] **Step 8.N.7: Commit (atomic)**

```
git add <specific-files>
git commit -m "fix(<scope>): <conventional message>

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

Pre-commit hooks обязательно прошли (gitleaks, markdownlint, cspell, stylelint, pint, larastan, squawk, eslint-vue).

- [ ] **Step 8.N.8: Update findings.md status**
`[fix #N] status: fixed in <commit-sha>` рядом с finding.

**Expected total time:** до конца сессии. После каждых 3 commits — self-review §8 (schema metrics, narrative версии, реестр).

---

## Phase 9 — Final verification + report (≈15 мин)

- [ ] **Step 9.1: Re-run всех Phase 1 static checks**
Идентично Phase 1 — параллельный subagent dispatch на 4 блока. Expected: всё прошло (или те же flaky/known что и в Phase 1, явно отмеченные blocked).

- [ ] **Step 9.2: Re-run всех Phase 2 test suites**
Pest + Vitest + Histoire build + Vite build. Expected: 0 regression — counts ≥ Phase 2 numbers.

- [ ] **Step 9.3: Pre-commit emulate (lefthook)**

```
cd "c:/моя/проекты/портал crm/Документация"
npx lefthook run pre-commit
```

Expected: все 8 jobs прошли на текущем working tree.

- [ ] **Step 9.4: Write summary report**
`docs/superpowers/audits/2026-05-12-portal-full-audit-report.md`:

```markdown
# Portal Full Audit — Summary (2026-05-12)

## TL;DR
- Findings total: N (P0: a, P1: b, P2: c, P3: d)
- Fixed: M (across K commits)
- Deferred: L (см. blocked.md)
- Blocked on user: J (см. blocked.md)

## По phase'ам
… (1 параграф на phase + ссылка на детальный блок в findings.md)

## Commits (audit fixes only)
- sha — scope — message
…

## Blocked questions for user
- (короткие 1-strok формулировки + ссылка на blocked.md детали)

## Метрики до/после
- Pest: was 742/738 → now N/M
- Vitest: was 579/582 → now N/M
- Larastan: was 0 above baseline → now N
…
```

- [ ] **Step 9.5: Commit summary**

```
git add docs/superpowers/audits/2026-05-12-portal-full-audit-*.md audit-screens/
git commit -m "chore(audit): portal full audit 2026-05-12 — findings + fixes + blocked"
```

**НЕ** push (Pravila — push только по явному запросу заказчика; и не на main в любом случае).

**Expected total time:** 15 мин.

---

## Self-review checklist (после plan'а, перед execution)

**1. Spec coverage:** Заказчик хотел «полный аудит, выяви все ошибки, неработающие элементы, неточности; исправь что сможешь; вопросы фиксируй». План покрывает: статанализ ✓, runtime tests ✓, UI smoke ✓, schema ✓, security ✓, docs ✓, реестр ✓, fix loop ✓, blocked list ✓, final report ✓.

**2. Placeholder scan:** Все step'ы содержат конкретные команды + Expected output. Нет «TBD», «handle edge cases», «similar to step N» (Phase 8 — паттерн step 8.N.x намеренный, конкретизируется по факту находок).

**3. Type consistency:** `findings.md` / `blocked.md` / `report.md` — три файла, имена согласованы во всех phase'ах. Severity P0..P3 — единый код. Phase нумерация 0..9 без gaps.

**4. Decision-tree coverage:** schema-changes / open-question closures / package-installs / ТЗ-правки / CLAUDE.md direct edits — все имеют явные «hard-stop / эскалировать в blocked» handling в соответствующих phase'ах.

**5. Время:** Σ ≈ 110-180 мин для Phase 0-9 без Phase 8. Phase 8 — открытый horizon до конца сессии. Заказчик идёт спать → ночной прогон, до 6-8 часов до его пробуждения; это укладывается с запасом.

---

## Открытые в плане предположения (если что — fallback)

1. **Vite порт 5173 свободен.** Если нет — `cd app && npx kill-port 5173` или ENV `VITE_PORT=5174`.
2. **PostgreSQL service running на Windows.** Если упадёт `database/query` — записать как infra-blocked, продолжать без Phase 3 + skip auth-required views в Phase 5.
3. **`DemoSeeder.php`** untracked есть. Прочитать перед запуском (не run без read'а).
4. **Playwright MCP доступен** и работает в текущей сессии (deferred tool, надо ToolSearch select).
5. **Subagent budget.** Phase 1 — 4 параллельных. Если падает на budget → перейти в sequential.
6. **Semgrep CLI** может не быть установлен — fallback в Step 4.2.
