Merge pull request #3 from CoralMinister/feat/claude-automation
Feat/claude automation
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
---
|
||||
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),
|
||||
(d) quirk 77 (unique-key collision в bulk-action tests with Faker-generated names),
|
||||
or (e) 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 (from 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) — флаг включать вручную при подозрении.
|
||||
|
||||
3. **Quirk 77 (memory feedback_environment.md, added 13.05.2026 day +1) — Pest --parallel deterministic unique-key collision на `projects(tenant_id, name)` в bulk-action tests.**
|
||||
- Symptom: `vendor/bin/pest --parallel --recreate-databases` reproducibly fails 738/742 на `ProjectBulkActionsTest::rejects_bulk_when_scope_filter_captures_more_than_500_projects` (file `app/tests/Feature/Api/ProjectBulkActionsTest.php:194-206`). Signature `SQLSTATE[23505] projects_tenant_id_name_key — (tenant_id, name)=(<id>, "<faker-3words>")`. Tenant_id varies per run (~50 apart — per-worker auto-increment).
|
||||
- Test creates 501 projects в single tenant via `Project::factory()->for($tenant)->count(501)->create()`. ProjectFactory.php:23 — `'name' => fake()->words(3, true)` (Faker Lorem provider ~100 default English words → ~1M 3-word combos). Birthday paradox math для 501 samples из ~1M combos → ~12.5% per-test failure probability — НЕ deterministic в isolation. Reproducible-in-parallel-but-not-sequential pattern suggests worker state sharing (shared Faker seed via PHP global state? Eloquent factory caching?). Full RCA pending.
|
||||
- Sequential `vendor/bin/pest tests/Feature/Api/ProjectBulkActionsTest.php` passes 14/14 ✅. Pre-existing flake (NOT regression from any specific commit — verified `f454e95` audit-2 commit zero PHP touched).
|
||||
- Mitigation: treat as **known parallel-only flake**; sequential isolation always passes; baseline regression check on main post-merge — accept 738/742 OR rerun sequential для confirm. Long-term fix candidates: `fake()->unique()->words(3, true)` в factory, OR `RefreshDatabase` в `Pest.php` line 18, OR explicit Faker seed per-test.
|
||||
|
||||
**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 — quirk 77 (unique-key collision в bulk-action tests).** Failing test creates ≥500 records of one model в single tenant с Faker-generated unique field? Pattern: `SQLSTATE[23505]` + `_tenant_id_<col>_key` constraint name + Faker-style value в DETAIL. Rerun sequential `./vendor/bin/pest <test-file>` — if passes 14/14 → quirk 77 confirmed; document as known parallel-only flake, не fix без user OK (root cause не fully RCA'd).
|
||||
6. **Hypothesis 5 — 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>
|
||||
Hypothesis 4 (quirk 77 unique-key collision): <falsified|confirmed|untested>
|
||||
Evidence: <command + output>
|
||||
|
||||
Conclusion: <real fix needed | quirk 72 — known race document | quirk 73 — recreate-databases fixed | quirk 77 — known parallel-only flake document | 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.
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
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".
|
||||
@@ -37,6 +37,17 @@
|
||||
]
|
||||
},
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node -e \"const f=process.env.CLAUDE_FILE_PATH||''; const pd=process.env.CLAUDE_PROJECT_DIR||''; const path=require('path'); if (f && pd && path.resolve(f) === path.resolve(pd, 'CLAUDE.md')) { process.stderr.write('\\n[hook] WARNING: Direct edit of root CLAUDE.md detected. Per CLAUDE.md §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'); }\""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
@@ -46,6 +57,15 @@
|
||||
"command": "node -e \"const f=process.env.CLAUDE_FILE_PATH||''; if(/\\\\.md$/i.test(f) && !/CLAUDE\\\\.md$/i.test(f)) { require('child_process').spawnSync('npx',['-y','markdownlint-cli2','--fix',f],{stdio:'inherit',shell:true}); }\""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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'); }\""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
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 добавление.
|
||||
@@ -0,0 +1,96 @@
|
||||
---
|
||||
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).
|
||||
@@ -23,6 +23,20 @@
|
||||
"command": "npx",
|
||||
"args": ["-y", "semgrep-mcp"],
|
||||
"comment": "Фаза 3 #25 — Semgrep MCP (SAST). Семантический поиск/анализ кода через Semgrep rules в Claude Code. Пакет: npmjs.com/package/semgrep-mcp — если 404, запустить 'npm search semgrep mcp' для актуального имени."
|
||||
},
|
||||
"sentry": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sentry/mcp-server"],
|
||||
"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 нормативки отдельным планом. Package: @sentry/mcp-server@0.33.0+ (official sentry-bot, repo getsentry/sentry-mcp, bin sentry-mcp). Env vars: SENTRY_URL (https://sentry.<your-domain>.ru), SENTRY_AUTH_TOKEN (PAT scope: sentry:read). Credentials в .env.local (gitignored), Claude Code считывает env из shell startup. Если env пустые — MCP server fail gracefully."
|
||||
},
|
||||
"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 нормативки отдельным планом. Package: @modelcontextprotocol/server-redis@2025.4.25 — DEPRECATED по статусу npm («Package no longer supported»), но Anthropic source, простой протокол, рабочий. Post-MVP migration на community alternative (e.g., @easy-mcps/redis-mcp-server@1.0.8 или @wenit/redis-mcp-server@1.0.3) когда подтвердим trust. READ-ONLY use — отладка очередей, кэша, Pest --parallel race (memory quirk 72). НЕ для prod (нет prod). Если в будущем prod Redis с auth — отдельный entry redis-prod с url через env var."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ pyc
|
||||
квирки
|
||||
неверифицированы
|
||||
мокают
|
||||
pункт
|
||||
|
||||
# Возврат к Бренд + термины
|
||||
бэкап
|
||||
@@ -1036,11 +1037,19 @@ favourite
|
||||
задек
|
||||
диффа
|
||||
закоммичены
|
||||
закоммиченных
|
||||
доразбор
|
||||
нормативки
|
||||
нерегрессии
|
||||
перехвачиваться
|
||||
недозвоном
|
||||
Неогранич
|
||||
|
||||
# Test fixtures + abbreviations
|
||||
AKIA
|
||||
gpg
|
||||
ver
|
||||
hookify
|
||||
MRT
|
||||
VLW
|
||||
YHC
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,364 @@
|
||||
# Task 9 Sync нормативки — Pre-prepared Edit Drafts
|
||||
|
||||
> **Status:** drafts only. NOT applied. Awaiting Task 1 (PR) merged before commit on feat/claude-automation-norm-sync branch.
|
||||
> **For executor:** at apply-time, **re-verify version numbers in shapkas** before applying — concurrent session activity may have bumped versions independently.
|
||||
|
||||
**Created:** 2026-05-13 day +1 (post Task 8 completion, before Task 9 execution).
|
||||
|
||||
**Source plan:** [docs/superpowers/plans/2026-05-13-claude-automation-completion-plan.md](2026-05-13-claude-automation-completion-plan.md) §Task 9.
|
||||
|
||||
**Scope:** 5 file updates documenting newly-installed Sentry MCP + Redis MCP as **off-phase tools #34 + #35** (paralleling existing claude-md-management #33 pattern).
|
||||
|
||||
**Architectural decision (re-verified during drafting):**
|
||||
|
||||
- Tooling §3.3 = «БД-инструменты», **не** off-phase tools. Off-phase live в **§4.5 (UPM) / §4.6 (21st) / §4.7 (claude-md-management)**.
|
||||
- Therefore new sentry+redis MCP → **§4.8 + §4.9** (new subsections), NOT §3.3.
|
||||
- Original plan Task 9.3 wording «§3.3 +#34/#35 rows» — error in original plan; corrected here.
|
||||
|
||||
---
|
||||
|
||||
## File 1: `docs/Tooling_v8_3.md`
|
||||
|
||||
### Edit 1.1 — §0 Сводка table: row «off-phase tools» bump count 3 → 5
|
||||
|
||||
**Anchor (read at apply-time to confirm):** line ~84.
|
||||
|
||||
**OLD:**
|
||||
|
||||
```markdown
|
||||
| **off-phase tools** | по факту включения в `~/.claude/settings.json` / `~/.claude.json` | **+3** | #31 UPM (UI-резерв), #32 21st Magic MCP (UI-генератор), #33 claude-md-management (инфраструктура CLAUDE.md edits) |
|
||||
```
|
||||
|
||||
**NEW:**
|
||||
|
||||
```markdown
|
||||
| **off-phase tools** | по факту включения в `~/.claude/settings.json` / `~/.claude.json` / `.mcp.json` | **+5** | #31 UPM (UI-резерв), #32 21st Magic MCP (UI-генератор), #33 claude-md-management (инфраструктура CLAUDE.md edits), #34 Sentry MCP (debug self-hosted Sentry в Yandex Cloud), #35 Redis MCP (debug Memurai/Redis runtime) |
|
||||
```
|
||||
|
||||
### Edit 1.2 — §0 footer: «Итого формализованных позиций» 33 → 35
|
||||
|
||||
**Anchor:** line ~86.
|
||||
|
||||
**OLD:**
|
||||
|
||||
```markdown
|
||||
**Итого формализованных позиций:** 33 (29 активных по фазам + 3 off-phase + 1 заменённый PG MCP исторически). Полный перечень — §2–§5 (по фазам) + §4.5/§4.6/§4.7 (off-phase). Карта «когда что использовать» — §7. Что НЕ ставим и почему — §9.
|
||||
```
|
||||
|
||||
**NEW:**
|
||||
|
||||
```markdown
|
||||
**Итого формализованных позиций:** 35 (29 активных по фазам + 5 off-phase + 1 заменённый PG MCP исторически). Полный перечень — §2–§5 (по фазам) + §4.5/§4.6/§4.7/§4.8/§4.9 (off-phase). Карта «когда что использовать» — §7. Что НЕ ставим и почему — §9.
|
||||
```
|
||||
|
||||
### Edit 1.3 — Add §4.8 Sentry MCP (after §4.7 claude-md-management, before §5)
|
||||
|
||||
**Anchor:** end of §4.7 (line ~324, before `---` and `## 5. Фаза 3 — pre-production`).
|
||||
|
||||
**OLD (anchor block — last lines of §4.7):**
|
||||
|
||||
```markdown
|
||||
**Аналогичные категории (built-in skills Claude Code, не плагины через marketplace):** `review`, `security-review`, `init`, `simplify`, `update-config`, `keybindings-help`, `fewer-permission-prompts`, `loop`, `schedule`, `claude-api`. Активируются по явному `/имя` от пользователя; не входят в `enabledPlugins`. См. PSR_v1 R10.1 блок 2 для полного реестра.
|
||||
|
||||
---
|
||||
|
||||
## 5. Фаза 3 — pre-production (+5 новых, итого 29 активных)
|
||||
```
|
||||
|
||||
**NEW:**
|
||||
|
||||
````markdown
|
||||
**Аналогичные категории (built-in skills Claude Code, не плагины через marketplace):** `review`, `security-review`, `init`, `simplify`, `update-config`, `keybindings-help`, `fewer-permission-prompts`, `loop`, `schedule`, `claude-api`. Активируются по явному `/имя` от пользователя; не входят в `enabledPlugins`. См. PSR_v1 R10.1 блок 2 для полного реестра.
|
||||
|
||||
### 4.8. Debug-инструмент Sentry — Sentry MCP (off-phase tool)
|
||||
|
||||
> **Введено 13.05.2026 day +1 (v1.17+ Прил. Н):** формализован как «инструмент-резерв вне фаз, debug-категория». Установлен на feat/claude-automation `6f7e7d7` в `.mcp.json`; формализован retrospectively в v1.17+. Категория **debug-runtime**, отличная от UI-пула (UPM/21st) и инфраструктурного (claude-md-management) — поэтому отдельная нумерация. Pending Sentry instance deployment в Yandex Cloud (зависит от Б-1 ООО registration P0).
|
||||
|
||||
| # | Инструмент | Установка | Состав | Когда использовать |
|
||||
|---|---|---|---|---|
|
||||
| 34 | **Sentry MCP** (`@sentry/mcp-server@0.33.0+`, official, repo `getsentry/sentry-mcp`, bin `sentry-mcp`) | `.mcp.json`: `mcpServers.sentry.command="npx" args=["-y", "@sentry/mcp-server"] env={SENTRY_URL, SENTRY_AUTH_TOKEN}`. Env vars — через PowerShell User scope (`[Environment]::SetEnvironmentVariable("SENTRY_URL", ..., "User")`). Credentials НЕ commit'ятся (gitleaks gate). | MCP tools: `mcp__sentry__get_issue`, `_list_events`, `_search_errors` (+ другие per @sentry/mcp-server@0.33.0 spec) | (1) production runtime error в self-hosted Sentry → прямой запрос issue details из Claude session; (2) post-incident debug (CLAUDE.md §2: Sentry self-hosted в Yandex Cloud); (3) READ-ONLY usage — scope auth token `org:read`, `project:read`, `event:read` only |
|
||||
|
||||
**Обязательные правила использования:**
|
||||
|
||||
| Правило | Где | Что значит |
|
||||
|---|---|---|
|
||||
| **R10.1** debug-runtime, не UI и не инфраструктура | R10.1 PSR_v1 (v2.1+) | Sentry MCP в **отдельной категории** от UPM/21st и от claude-md-management; не попадает в R14 pipeline UI-генераторов и не модифицирует CLAUDE.md |
|
||||
| **CLAUDE.md §5 п.4** не commit'ить ПДн/токены | CLAUDE.md | `SENTRY_AUTH_TOKEN` — секрет, НИКОГДА не в репозиторий. Только через PowerShell User scope env или `.env.local` (gitignored) |
|
||||
| **R7** не закрывает задачу | R7 PSR_v1 | Sentry MCP — источник информации, не gate (не deployable artifact) |
|
||||
| **Pre-MVP блокер** | — | Sentry instance в Yandex Cloud зависит от Б-1 ООО registration. До deployment — MCP startup fail gracefully (env пустые), tools не enumerable; это OK |
|
||||
|
||||
**Live-отмена (R0.4.B PSR_v1):** «не используй sentry-mcp сейчас» — отключает на текущее действие. По умолчанию активен после reload session с непустыми env vars.
|
||||
|
||||
**Безопасность:** Token `SENTRY_AUTH_TOKEN` — bearer secret. PowerShell User scope = encrypted per-user (Windows DPAPI). Не shared между пользователями. При утечке — немедленно revoke через Sentry web UI (`Settings → Account → API → Auth Tokens`).
|
||||
|
||||
### 4.9. Debug-инструмент Redis — Redis MCP (off-phase tool)
|
||||
|
||||
> **Введено 13.05.2026 day +1 (v1.17+ Прил. Н):** формализован как «инструмент-резерв вне фаз, debug-категория». Установлен на feat/claude-automation `bd4ec48` в `.mcp.json`; формализован retrospectively в v1.17+. Package `@modelcontextprotocol/server-redis@2025.4.25` **deprecated** по статусу npm («Package no longer supported»), но Anthropic source, рабочий. Post-MVP migration на community alternative (e.g., `@easy-mcps/redis-mcp-server@1.0.8` или `@wenit/redis-mcp-server@1.0.3`) когда подтвердим trust.
|
||||
|
||||
| # | Инструмент | Установка | Состав | Когда использовать |
|
||||
|---|---|---|---|---|
|
||||
| 35 | **Redis MCP** (`@modelcontextprotocol/server-redis@2025.4.25`, deprecated Anthropic source) | `.mcp.json`: `mcpServers.redis.command="npx" args=["-y", "@modelcontextprotocol/server-redis", "redis://localhost:6379"]`. Memurai (Windows Redis 7-совместимый service) running на `localhost:6379` — verified Task 4 (`memurai-cli ping → PONG`). | MCP tools: Redis operations (KEYS, GET, LRANGE, etc.) | (1) debug очередей (`route:supplier:*`); (2) debug кэша (`supplier:session` per quirk 72); (3) debug Pest --parallel race conditions; (4) READ-ONLY usage — НЕ для prod (нет prod пока). Если в будущем prod Redis с auth — отдельный entry `redis-prod` с url через env var |
|
||||
|
||||
**Обязательные правила использования:**
|
||||
|
||||
| Правило | Где | Что значит |
|
||||
|---|---|---|
|
||||
| **R10.1** debug-runtime, не UI и не инфраструктура | R10.1 PSR_v1 (v2.1+) | Redis MCP в той же категории что #34 sentry-mcp |
|
||||
| **READ-ONLY usage** | соглашение проекта | Никаких `DEL`, `FLUSHDB`, `SET`, `LPUSH` от Claude в runtime debug. Только read-операции. Manual Redis mutations — через `memurai-cli` напрямую заказчиком |
|
||||
| **Package deprecation** | npm | На startup `npx` emits deprecation warning в stderr. Это **cosmetic**, не functional. При выходе supported alternative (community OR official replacement) — migrate в Tooling v1.18+ |
|
||||
| **R7** не закрывает задачу | R7 PSR_v1 | Redis MCP — источник информации, не gate |
|
||||
|
||||
**Live-отмена (R0.4.B PSR_v1):** «не используй redis-mcp сейчас» — отключает на текущее действие.
|
||||
|
||||
**Безопасность:** Локальный Memurai на 6379 **без auth** — это dev-only setup. Если в будущем будут prod Redis с auth — entry `redis-prod` с url через env var `${REDIS_PROD_URL}`, credentials через PowerShell User scope (как Sentry). Сейчас prod нет (зависит от Б-1).
|
||||
|
||||
---
|
||||
|
||||
## 5. Фаза 3 — pre-production (+5 новых, итого 29 активных)
|
||||
````
|
||||
|
||||
### Edit 1.4 — §13 changelog: add v1.17 entry
|
||||
|
||||
**Anchor:** line ~607 (after v1.15 entry) or wherever latest changelog entry is at apply-time. **WARNING: file may already have v1.16 entry (R15 motion-runtime cleanup 12.05.2026) — verify line range carefully.**
|
||||
|
||||
**Expected current latest (per memory): v1.16** (R15 motion-runtime cleanup). If true:
|
||||
|
||||
**OLD (last entry before footer):**
|
||||
|
||||
```markdown
|
||||
| **v1.16** | 12.05.2026 | <existing R15 motion-runtime cleanup entry — leave intact> |
|
||||
```
|
||||
|
||||
**NEW (add v1.17 row after v1.16):**
|
||||
|
||||
```markdown
|
||||
| **v1.17** | 13.05.2026 (day +1) | **Формализация retrospective двух off-phase MCP debug-инструментов** установленных на feat/claude-automation (commits `6f7e7d7` sentry, `bd4ec48` redis): **§0 счётчик off-phase tools 3 → 5; Итого формализованных позиций 33 → 35**. **§4.8 (новый)** — #34 Sentry MCP (`@sentry/mcp-server@0.33.0+`, official, pending Sentry instance deployment Б-1). **§4.9 (новый)** — #35 Redis MCP (`@modelcontextprotocol/server-redis@2025.4.25`, deprecated Anthropic source, рабочий с Memurai localhost:6379; migration plan на community alternative post-MVP). Категория debug-runtime, отдельная от UI-пула (UPM/21st) и инфраструктурного (claude-md-management) — не попадает в R14 pipeline и не trigger'ит R6.0/R6.1 фильтры. Связано: PSR_v1 v2.0 → v2.1 (R10.1 +sentry+redis); CLAUDE.md v1.91 → v1.92 (§3.3 #34/#35; §0 cross-refs); Pravila v1.12 → v1.13 (§13.2 infrastructure subsection counter). Через `/claude-md-management:claude-md-improver` для CLAUDE.md; manual Edit для Tooling/PSR_v1/Pravila. |
|
||||
```
|
||||
|
||||
### Edit 1.5 — Footer standalone version notes: prepend v1.17
|
||||
|
||||
**Anchor:** line ~611 (`*Прил. Н v1.15 от 10.05.2026...*`) — verify v1.16 note also present.
|
||||
|
||||
**Insert before v1.15/v1.16 notes:**
|
||||
|
||||
```markdown
|
||||
*Прил. Н v1.17 от 13.05.2026 (day +1) — формализация retrospective off-phase MCP #34 Sentry + #35 Redis (debug-runtime category). 35 позиций (29 активных по фазам + 5 off-phase + 1 заменённый PG MCP исторически).*
|
||||
```
|
||||
|
||||
### Edit 1.6 — Shapka of file: bump version reference
|
||||
|
||||
**Anchor:** top of file, look for `**Прил. Н vX.YZ`. Bump to v1.17 от 13.05.2026 (day +1).
|
||||
|
||||
---
|
||||
|
||||
## File 2: `docs/Plugin_stack_rules_v1.md`
|
||||
|
||||
### Edit 2.1 — R10.1 table: add sentry + redis rows (in блок 1 «активно используемые плагины»)
|
||||
|
||||
**Anchor:** search for `R10.1` table start. Add after existing claude-md-management row (or after last MCP entry in block 1).
|
||||
|
||||
**WARNING:** PSR_v1 structure — R10.1 имеет несколько блоков (per reference_archive: «R10.1 разбит на 3 блока» в v1.5). Need to identify correct block at apply-time:
|
||||
|
||||
- Блок 1: активно используемые плагины (UI + инфраструктура)
|
||||
- Блок 2: built-in skills Claude Code (review/security-review/etc.)
|
||||
- Блок 3: возможные будущие
|
||||
|
||||
Sentry/Redis MCP добавляются как **новая категория «debug-runtime»** или вписываются в блок 1 как дополнительные плагины с пометкой role «debug-runtime, не UI и не инфраструктура».
|
||||
|
||||
**Proposed addition to R10.1 (location TBD at apply-time):**
|
||||
|
||||
```markdown
|
||||
| `@sentry/mcp-server` (MCP, `sentry` в `.mcp.json`) | Off-phase debug-runtime | Tooling #34. Установлен 13.05.2026 day +1 commit `6f7e7d7`. Pending Sentry instance deployment (Б-1 ООО registration). READ-ONLY scope (`org:read`, `project:read`, `event:read`). | — (не UI, не инфраструктура CLAUDE.md, не входит в R14 pipeline) |
|
||||
| `@modelcontextprotocol/server-redis` (MCP, `redis` в `.mcp.json`) | Off-phase debug-runtime | Tooling #35. Установлен 13.05.2026 day +1 commit `bd4ec48`. Deprecated package (Anthropic source). Memurai localhost:6379 verified Task 4 (`memurai-cli ping → PONG`). | — |
|
||||
```
|
||||
|
||||
### Edit 2.2 — Shapka: bump v2.0 → v2.1
|
||||
|
||||
**Anchor:** top of file, look for `**v2.0**` or current version marker. Bump to v2.1 от 13.05.2026 day +1.
|
||||
|
||||
### Edit 2.3 — История версий: add v2.1 entry
|
||||
|
||||
**Proposed entry:**
|
||||
|
||||
```markdown
|
||||
- **v2.1** (13.05.2026 day +1): R10.1 расширен 2 off-phase debug-runtime записями — `@sentry/mcp-server` (#34) + `@modelcontextprotocol/server-redis` (#35). Категория **debug-runtime** introduced — отличная от UI-пула (UPM/21st) и infrastructure (claude-md-management); не trigger'ит R6.0/R6.1 фильтры и не входит в R14 pipeline. Связано: Tooling v1.16 → v1.17 (§4.8 + §4.9); CLAUDE.md v1.91 → v1.92 (§3.3 #34/#35); Pravila v1.12 → v1.13 (§13.2 counter).
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File 3: `CLAUDE.md` (через `/claude-md-management:claude-md-improver`)
|
||||
|
||||
> **CRITICAL:** CLAUDE.md правится **только** через `/claude-md-management:claude-md-improver` per §5 п.10. **НЕ через Edit/Write tool напрямую.** PreToolUse hook (Task 6 commit `c5b0cdf`) emits warning при direct edit attempt.
|
||||
|
||||
### Skill invocation prompt (apply via `/claude-md-management:claude-md-improver`)
|
||||
|
||||
```text
|
||||
/claude-md-management:claude-md-improver
|
||||
|
||||
Apply following targeted updates to root CLAUDE.md:
|
||||
|
||||
1. §3.3 (table "Карта 33 инструментов") — add #34 + #35 rows after #33 claude-md-management:
|
||||
| 34 | Off-phase MCP — отладка production runtime errors через self-hosted Sentry в Yandex Cloud | **Sentry MCP** (`@sentry/mcp-server`, server `sentry` в `.mcp.json`, tools `mcp__sentry__*`) | автоматически через `.mcp.json`. Env vars `SENTRY_URL` + `SENTRY_AUTH_TOKEN` через shell (PowerShell User scope). Установлен 13.05.2026 day +1 (commit `6f7e7d7`); формализован retrospectively v1.92. Pending: Sentry instance deployment (зависит от Б-1 ООО registration). |
|
||||
| 35 | Off-phase MCP — отладка Redis/Memurai очередей, кэша, Pest --parallel races | **Redis MCP** (`@modelcontextprotocol/server-redis@2025.4.25` — DEPRECATED Anthropic source; migration plan на `@easy-mcps/redis-mcp-server@1.0.8` post-MVP; server `redis` в `.mcp.json`, tools `mcp__redis__*`) | автоматически через `.mcp.json`. URL `redis://localhost:6379` (Memurai Windows service, verified Task 4 ping PONG). READ-ONLY для debug. Установлен 13.05.2026 day +1 (commit `bd4ec48`). |
|
||||
|
||||
2. §3.4 footer — bump count "(Total формализованных позиций: 33)" → "(Total формализованных позиций: 35)".
|
||||
Also: "29 phase-active + 3 off-phase + 1 historic" → "29 phase-active + 5 off-phase + 1 historic".
|
||||
|
||||
3. §0 cross-refs — bump version refs:
|
||||
- row "Tooling": v1.16 → v1.17 (entry "Прил. Н v1.17 от 13.05.2026 day +1 — формализация retrospective off-phase MCP #34 Sentry + #35 Redis")
|
||||
- row "PSR_v1": v2.0 → v2.1 (entry "R10.1 расширен 2 off-phase debug-runtime записями")
|
||||
- row "Pravila": v1.12 → v1.13 (entry "§13.2 infrastructure subsection counter +2 off-phase MCP debug-runtime")
|
||||
|
||||
4. Шапка version bump: v1.91 → v1.92 от 13.05.2026 (day +1).
|
||||
|
||||
5. History entry в шапке (compact):
|
||||
v1.92 от 13.05.2026 (day +1) — sync нормативки после feat/claude-automation merge: §3.3 +#34 Sentry MCP + #35 Redis MCP (off-phase debug-runtime category); §3.4 footer 33 → 35; §0 cross-refs Tooling v1.16→v1.17, PSR_v1 v2.0→v2.1, Pravila v1.12→v1.13. Через /claude-md-management:claude-md-improver. Реализация feat/claude-automation #PR_NUM закрытие (PR merged).
|
||||
|
||||
Verification после apply:
|
||||
- npx markdownlint-cli2 CLAUDE.md (expected: 0 errors)
|
||||
- bin/lychee.exe --config .lychee.toml CLAUDE.md (expected: 0 broken links)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File 4: `docs/Pravila_raboty_Claude_v1_1.md`
|
||||
|
||||
### Edit 4.1 — §13.2 infrastructure subsection: extend для off-phase MCP
|
||||
|
||||
**Anchor:** §13.2 «Парность со Superpowers + расширенный пул UI-инструментов» — specifically subsection «Инфраструктурные плагины (вне расширенного UI-пула)» (added v1.9).
|
||||
|
||||
**Read at apply-time** для exact current text. Proposed extension:
|
||||
|
||||
**OLD (current sentence, paraphrased):**
|
||||
|
||||
```markdown
|
||||
**Инфраструктурные плагины (вне расширенного UI-пула):** `claude-md-management` (Tooling #33) — инфраструктурный канал правок CLAUDE.md; built-in skills Claude Code (`review`/`security-review`/`init`/`simplify`/`update-config`/`keybindings-help`/`fewer-permission-prompts`/`loop`/`schedule`/`claude-api`) — активируются по явному `/имя`. Регулируются PSR_v1 R10.1 блок 2.
|
||||
```
|
||||
|
||||
**NEW (add new paragraph after existing infrastructure paragraph):**
|
||||
|
||||
```markdown
|
||||
**Инфраструктурные плагины (вне расширенного UI-пула):** `claude-md-management` (Tooling #33) — инфраструктурный канал правок CLAUDE.md; built-in skills Claude Code (`review`/`security-review`/`init`/`simplify`/`update-config`/`keybindings-help`/`fewer-permission-prompts`/`loop`/`schedule`/`claude-api`) — активируются по явному `/имя`. Регулируются PSR_v1 R10.1 блок 2.
|
||||
|
||||
**Off-phase MCP debug-runtime (отдельная категория, введена v1.13 Pravila):** `@sentry/mcp-server` (Tooling #34, server `sentry`) — отладка production errors в self-hosted Sentry; `@modelcontextprotocol/server-redis` (Tooling #35, server `redis`) — отладка Redis/Memurai runtime. **Не UI** (не trigger'ят R6.0/R6.1 фильтры стека) и **не инфраструктура CLAUDE.md** (не модифицируют CLAUDE.md). READ-ONLY usage обязателен. Регулируются PSR_v1 R10.1 (v2.1+) — отдельной debug-runtime категорией.
|
||||
```
|
||||
|
||||
### Edit 4.2 — Шапка version bump: v1.12 → v1.13
|
||||
|
||||
**Anchor:** top of file. Bump version.
|
||||
|
||||
### Edit 4.3 — История версий: add v1.13 entry
|
||||
|
||||
**Proposed:**
|
||||
|
||||
```markdown
|
||||
- **v1.13** (13.05.2026 day +1): **§13.2 расширен** — добавлен абзац про «Off-phase MCP debug-runtime (отдельная категория)» для двух retrospectively формализованных off-phase MCP: `@sentry/mcp-server` (Tooling #34) + `@modelcontextprotocol/server-redis` (Tooling #35). Категория **отдельная** от UI-пула (Pravila §13.1-§13.8) и от infrastructure (claude-md-management) — не trigger'ит R6.0/R6.1 stack-фильтры. Связано: Tooling v1.16 → v1.17 (§4.8 + §4.9); PSR_v1 v2.0 → v2.1 (R10.1); CLAUDE.md v1.91 → v1.92 (§3.3 #34/#35). Без других содержательных изменений в §§1-12 + §§13.1, 13.3-13.10.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File 5: Memory `MEMORY.md` + `reference_archive.md`
|
||||
|
||||
> **NB:** Memory лежит вне repo (locally persistent). НЕ commit. Apply through Edit on actual memory files.
|
||||
|
||||
### Edit 5.1 — `MEMORY.md` line 4 (feedback_plugin_paired_stack reference)
|
||||
|
||||
**Anchor:** line 4, version refs «PSR_v1 **v2.0**, Pravila **v1.12**, Tooling **v1.16**, CLAUDE.md **v1.91**».
|
||||
|
||||
**OLD:**
|
||||
|
||||
```markdown
|
||||
Active: PSR_v1 **v2.0** (15 правил R0–R14), Pravila **v1.12**, Tooling **v1.16**, CLAUDE.md **v1.91**.
|
||||
```
|
||||
|
||||
**NEW:**
|
||||
|
||||
```markdown
|
||||
Active: PSR_v1 **v2.1** (15 правил R0–R14 + R10.1 +sentry+redis), Pravila **v1.13**, Tooling **v1.17** (35 позиций: 29 phase + 5 off-phase + 1 historic), CLAUDE.md **v1.92**.
|
||||
```
|
||||
|
||||
### Edit 5.2 — `MEMORY.md` line 7 (reference_archive)
|
||||
|
||||
**OLD:**
|
||||
|
||||
```markdown
|
||||
ТЗ v8.5, schema v8.20, **реестр v1.83** (...), **Tooling v1.16**, **CLAUDE.md v1.91** (session-end hygiene), **Pravila v1.12** (...), **Plugin_stack_rules_v1 v2.0**
|
||||
```
|
||||
|
||||
**NEW:**
|
||||
|
||||
```markdown
|
||||
ТЗ v8.5, schema v8.20, **реестр v1.83** (...), **Tooling v1.17** (35 позиций; +#34 Sentry MCP + #35 Redis MCP off-phase debug-runtime), **CLAUDE.md v1.92** (§3.3 #34/#35; sync нормативки), **Pravila v1.13** (§13.2 off-phase MCP debug-runtime subsection), **Plugin_stack_rules_v1 v2.1** (R10.1 +sentry+redis)
|
||||
```
|
||||
|
||||
### Edit 5.3 — `reference_archive.md` description (line 3)
|
||||
|
||||
**Anchor:** front-matter `description:` field.
|
||||
|
||||
Bump all version refs analogously: Tooling v1.16 → v1.17 (35 позиций); CLAUDE.md v1.91 → v1.92; Pravila v1.12 → v1.13; PSR_v1 v2.0 → v2.1.
|
||||
|
||||
### Edit 5.4 — `reference_archive.md` priority chain (lines 9-16)
|
||||
|
||||
**Anchor:** «Приоритет правил при конфликте» list.
|
||||
|
||||
Bump version refs analogously.
|
||||
|
||||
**NB:** `reference_archive.md` body (lines 22-46) has stale data (schema v8.18, CLAUDE.md v1.86, etc.) — это **исторический snapshot**, не trogal. Только header refs.
|
||||
|
||||
---
|
||||
|
||||
## Application order (recommended)
|
||||
|
||||
1. File 1 (Tooling) — most extensive, anchors most stable.
|
||||
2. File 2 (PSR_v1) — R10.1 expansion.
|
||||
3. File 4 (Pravila) — §13.2 addition.
|
||||
4. File 3 (CLAUDE.md) — via plugin invocation per §5 п.10.
|
||||
5. File 5 (Memory) — last (reflects all bumped versions).
|
||||
|
||||
**Atomic commits** per file (4 git commits + 1 memory edit без commit).
|
||||
|
||||
**Verification после каждого commit:**
|
||||
|
||||
```bash
|
||||
"C:/моя/проекты/портал crm/Документация/bin/lychee.exe" --config "C:/моя/проекты/портал crm/Документация/.lychee.toml" <file>
|
||||
npx markdownlint-cli2 <file>
|
||||
git diff --stat HEAD~1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Bonus finding: new Pest --parallel quirk #77 (candidate)
|
||||
|
||||
**Discovered Task 8 (subagent diagnostic):** `ProjectBulkActionsTest::rejects_bulk_when_scope_filter_captures_more_than_500_projects` ([app/tests/Feature/Api/ProjectBulkActionsTest.php](../../../app/tests/Feature/Api/ProjectBulkActionsTest.php)) fails under `--parallel --recreate-databases` с `SQLSTATE[23505] projects_tenant_id_name_key` unique violation. Passes 14/14 sequentially. Reproduces 2× в parallel runs с different tenant_id.
|
||||
|
||||
**Pattern:** parallel worker shared-DB collision на `(tenant_id, name)` unique key when bulk-creating 501 projects.
|
||||
|
||||
**Not covered by:**
|
||||
|
||||
- Quirk 72 (Redis `supplier:session` race — only `tests/Feature/Supplier/*`)
|
||||
- Quirk 73 (cumulative state — LookupsTest/ProjectExtensionsTest «too many rows», not unique key)
|
||||
|
||||
**NOT introduced by feat/claude-automation** — verified `git show f454e95 --stat` (audit-2 docs commit) and Pest baseline files unchanged.
|
||||
|
||||
**Recommendation (separate task, NOT in this sync plan):** add quirk #77 entry to memory `feedback_environment.md` AND extend [.claude/agents/pest-parallel-debugger.md](../../../.claude/agents/pest-parallel-debugger.md) с 5-th hypothesis (parallel worker shared-DB unique-key collision). This is a follow-up plan item, не Task 9 scope.
|
||||
|
||||
---
|
||||
|
||||
## Open questions remaining at apply-time
|
||||
|
||||
| Q | Detail | Resolution |
|
||||
|---|---|---|
|
||||
| Q1 | Tooling shapka actual version: v1.15 or v1.16? | Read top of file at apply-time |
|
||||
| Q2 | PSR_v1 R10.1 block where sentry/redis fit best? | Read R10.1 sections at apply-time; debug-runtime может потребовать new sub-block |
|
||||
| Q3 | Pravila §13.2 «Инфраструктурные плагины» subsection — exact current text? | Read at apply-time для exact OLD anchor |
|
||||
| Q4 | CLAUDE.md plugin invocation result — does `/claude-md-management:claude-md-improver` accept multi-edit instruction? | Test with single edit first; if plugin не handles batched — split в multiple invocations |
|
||||
| Q5 | Will lefthook pre-commit pass on main checkout (vs worktree where lefthook absent)? | После merge на main — lefthook active; verify pre-push hooks (gitleaks-full-history + lychee) pass |
|
||||
|
||||
---
|
||||
|
||||
## NB ограничения этого drafts file
|
||||
|
||||
- **Не верифицировал** точные line numbers в Tooling/PSR_v1/Pravila shapkas — apply-time read required.
|
||||
- **Не верифицировал** exact text Pravila §13.2 infrastructure paragraph — paraphrased from memory + grep evidence (line 37 of changelog).
|
||||
- **Не запускал** lychee/markdownlint на этом drafts file — будет done в commit step.
|
||||
- **Не применял** ни один Edit — это pre-prep document only.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+279
@@ -0,0 +1,279 @@
|
||||
# Quirk #77 — Pest --parallel Unique Key Collision Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Document Pest --parallel `ProjectBulkActionsTest::rejects_bulk_when_scope_filter_captures_more_than_500_projects` collision как новый quirk #77 в memory `feedback_environment.md` + extend `pest-parallel-debugger` subagent с 5-th hypothesis.
|
||||
|
||||
**Architecture:** 2 deliverables — (a) Memory quirk entry following established pattern (quirks 70-76 structure: symptom / root cause / why / how to apply); (b) Subagent system prompt extension (new hypothesis section + updated diagnostic pipeline + updated output template).
|
||||
|
||||
**Tech Stack:** Markdown edits, no code changes. Memory file lives outside repo (`C:/Users/Administrator/.claude/projects/...`). Subagent file in repo at `.claude/agents/pest-parallel-debugger.md`.
|
||||
|
||||
**Discovery context:** Task 8 of completion plan ([docs/superpowers/plans/2026-05-13-claude-automation-completion-plan.md](2026-05-13-claude-automation-completion-plan.md) §Task 8) — Pest baseline regression check discovered new flake in `ProjectBulkActionsTest`. Subagent applied `superpowers:systematic-debugging` (3 hypotheses, 2 falsified, 1 confirmed). NOT a regression from feat/claude-automation work (`f454e95` audit-2 commit zero PHP code touched). Pre-existing flake surfaced during baseline run.
|
||||
|
||||
**Evidence captured (this session):**
|
||||
|
||||
- [`db/schema.sql:836`](../../../db/schema.sql#L836) — `UNIQUE (tenant_id, name)` constraint on `projects` table
|
||||
- [`app/database/factories/ProjectFactory.php:23`](../../../app/database/factories/ProjectFactory.php#L23) — `'name' => fake()->words(3, true)` (Faker Lorem provider, default English locale ~100 words → ~1M combos)
|
||||
- [`app/tests/Pest.php:18`](../../../app/tests/Pest.php#L18) — `// ->use(RefreshDatabase::class)` (RefreshDatabase commented; DatabaseTransactions implicit)
|
||||
- [`app/tests/Feature/Api/ProjectBulkActionsTest.php:194-206`](../../../app/tests/Feature/Api/ProjectBulkActionsTest.php#L194-L206) — test creates 501 projects in single tenant via `Project::factory()->for($tenant)->count(501)->create()`
|
||||
|
||||
**Subagent raw output (Task 8) reproducible signature:**
|
||||
|
||||
```text
|
||||
{"tool":"pest","result":"failed","tests":742,"passed":738,"assertions":2240,"duration_ms":~32000,"errors":1,
|
||||
"error_details":[{
|
||||
"test":"P\\Tests\\Feature\\Api\\ProjectBulkActionsTest::__pest_evaluable_it_rejects_bulk_when_scope_filter_captures_more_than_500_projects",
|
||||
"file":"\\app\\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Connection.php",
|
||||
"line":426,
|
||||
"message":"SQLSTATE[23505]: Unique violation: 7 ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности \"projects_tenant_id_name_key\"\nDETAIL: Ключ \"(tenant_id, name)=(<id>, <faker-name>)=(11795, eius animi qui)\" уже существует."
|
||||
}],"skipped":3}
|
||||
```
|
||||
|
||||
Tenant_id varied between runs (11795 → 11850, ~50 apart suggesting per-worker auto-increment offset). Sequential isolation: 14/14 ✅.
|
||||
|
||||
**Spec/source:** Discovered empirically. No formal spec — quirk documentation is the spec.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
| Файл | Действие |
|
||||
|---|---|
|
||||
| `C:/Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_environment.md` | Append quirk #77 entry (following existing #70-76 pattern); **NOT in repo, не commit'ить** |
|
||||
| `C:/Users/Administrator/.claude/projects/c---------------------crm-------------/memory/MEMORY.md` line 5 (feedback_environment reference) | Bump «76 квирков» → «77 квирков», добавить #77 в summary list |
|
||||
| `.claude/agents/pest-parallel-debugger.md` (в repo на feat/claude-automation OR в работе после merge на main) | Extend subagent system prompt: +Quirk 77 in known-quirks section, +Hypothesis 5 в diagnostic pipeline, +Hypothesis 5 в output template |
|
||||
|
||||
---
|
||||
|
||||
## Task 1: Draft quirk #77 entry для memory `feedback_environment.md`
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `C:/Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_environment.md` (append before final blank line)
|
||||
|
||||
- [ ] **Step 1.1: Find anchor position**
|
||||
|
||||
```bash
|
||||
grep -n "^\*\*76\.\|^\*\*77\.\|^---$" "C:/Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_environment.md" | tail -5
|
||||
```
|
||||
|
||||
Identify line после last existing quirk #76 (or wherever pattern continues — file may have grown).
|
||||
|
||||
- [ ] **Step 1.2: Compose quirk #77 entry**
|
||||
|
||||
Follow established pattern (quirks 70-76 structure: bold-numbered title, then date + context, then Why, then How to apply):
|
||||
|
||||
```markdown
|
||||
**77. Pest --parallel deterministic unique-key collision на `projects(tenant_id, name)` (13.05.2026 day +1, Task 8 baseline check finding).** `vendor/bin/pest --parallel --recreate-databases` reproducibly fails 738/742 на `ProjectBulkActionsTest::rejects_bulk_when_scope_filter_captures_more_than_500_projects` (file `app/tests/Feature/Api/ProjectBulkActionsTest.php:194-206`). Signature: `SQLSTATE[23505] projects_tenant_id_name_key — (tenant_id, name)=(<id>, "<faker-name>")`. Tenant_id varies between runs (11795, 11850 — ~50 apart suggesting per-worker auto-increment); name from Faker Lorem provider `fake()->words(3, true)` (~100 default English words → ~1M 3-word combos). Test creates 501 projects in single tenant via `Project::factory()->for($tenant)->count(501)->create()`. Sequential isolation `vendor/bin/pest tests/Feature/Api/ProjectBulkActionsTest.php` passes 14/14. **Deterministic** in --parallel, **passing** sequential.
|
||||
**Why:** Root cause partial: collision on `(tenant_id, name)` UNIQUE (`db/schema.sql:836`). Birthday paradox math для 501 samples из ~1M combos дает ~12.5% per-test failure probability — НЕ deterministic. Reproducible-in-parallel-but-not-sequential pattern suggests interaction между worker processes (shared Faker seed via PHP global state? shared autoload init? Eloquent factory caching?). Full RCA pending — required deeper investigation beyond 41-second subagent diagnostic run (Task 8). NOT a regression from any specific commit — verified `git show f454e95 --stat` (audit-2 docs commit zero PHP touched), and `ProjectBulkActionsTest.php` last modification was commit `64d8dae` (feat: scope.filter resolver + 500-limit guard) without subsequent code changes triggering the flake.
|
||||
**How to apply:** (1) Treat as **known parallel-only flake** — sequential `vendor/bin/pest tests/Feature/Api/ProjectBulkActionsTest.php` always 14/14 ✅. (2) При baseline regression check после feature-merge — accept 738/742 как baseline (vs «pure» 742/739/0/3 memory baseline from earlier sessions when flake didn't surface); rerun sequential для isolation confirm. (3) Long-term fix candidates (когда позволяет окружение): seed Faker explicitly с unique-per-test seeds (`fake()->seed($testId)`), OR add `->unique()` to factory name generation (`fake()->unique()->words(3, true)`), OR migrate Pest.php к `RefreshDatabase::class` (currently commented line 18) которое force-recreates DB per-test instead of TX rollback. (4) При появлении similar collision flakes на других `(tenant_id, name)` или похожих UNIQUE constraints — этот же класс quirk, same hypothesis.
|
||||
```
|
||||
|
||||
- [ ] **Step 1.3: Append to memory file**
|
||||
|
||||
Use Edit tool с anchor (last existing quirk text), append new entry **before** any trailing whitespace/blank lines.
|
||||
|
||||
- [ ] **Step 1.4: Verify (no commit — memory files outside repo)**
|
||||
|
||||
```bash
|
||||
grep -c "^\*\*77\." "C:/Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_environment.md"
|
||||
```
|
||||
|
||||
Expected: `1`.
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Update `MEMORY.md` summary line для feedback_environment
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `C:/Users/Administrator/.claude/projects/c---------------------crm-------------/memory/MEMORY.md` line 5
|
||||
|
||||
- [ ] **Step 2.1: Bump count + add summary**
|
||||
|
||||
**OLD line 5:**
|
||||
|
||||
```markdown
|
||||
- [Особенности окружения](feedback_environment.md) — Windows Server 2022 + 76 квирков (последний bump: **13.05.2026 day +1 +квирки 74-76**): #76 docs/superpowers/plans/ relative paths требуют `../../../` для app/ references (lychee strict semantics; CTO-19 fixup `f6e1e64`); #75 Vuetify-internal default mdi-* names НЕ покрыты простым grep user code — нужно прочёсывать `node_modules/vuetify/lib/iconsets/mdi*` тоже (CTO-19 Task 2.b extension +25 entries → 103 total); #74 `npm install` требует `--legacy-peer-deps` из-за Histoire 1.0.0-beta.1 peerDep conflict; #73 Pest --parallel cumulative state расширился на long sessions без `--recreate-databases`. **Полный список 1-76 в файле**
|
||||
```
|
||||
|
||||
**NEW line 5:**
|
||||
|
||||
```markdown
|
||||
- [Особенности окружения](feedback_environment.md) — Windows Server 2022 + 77 квирков (последний bump: **13.05.2026 day +1 +квирк 77**): #77 Pest --parallel deterministic unique-key collision на `projects(tenant_id, name)` в `ProjectBulkActionsTest::rejects_bulk_when_scope_filter_captures_more_than_500_projects` (501-project bulk, Faker Lorem ~1M combos, ~12.5% sporadic→deterministic в parallel; sequential 14/14 ✅; root cause partial — possible worker state sharing); #76 docs/superpowers/plans/ relative paths требуют `../../../` для app/ references; #75 Vuetify-internal default mdi-* names НЕ покрыты простым grep user code; #74 `npm install` требует `--legacy-peer-deps` из-за Histoire 1.0.0-beta.1 peerDep conflict. **Полный список 1-77 в файле**
|
||||
```
|
||||
|
||||
- [ ] **Step 2.2: Verify**
|
||||
|
||||
```bash
|
||||
grep -E "77 квирков|#77 Pest" "C:/Users/Administrator/.claude/projects/c---------------------crm-------------/memory/MEMORY.md"
|
||||
```
|
||||
|
||||
Expected: 2 matches (line 5 mentions).
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Extend `.claude/agents/pest-parallel-debugger.md` subagent
|
||||
|
||||
**Files:**
|
||||
|
||||
- Modify: `.claude/agents/pest-parallel-debugger.md` (на feat/claude-automation OR на feat/claude-automation-quirk77-update — new sub-branch off main after PR merge)
|
||||
|
||||
**Decision (apply-time):** if Task 9 sync нормативки (completion plan) уже merged → create new sub-branch `feat/quirk-77-update` off main; else commit on `feat/claude-automation` directly (этот PR remains scoped к 8 automations + sync нормативки already drafted; adding quirk #77 в same PR mixes scope).
|
||||
|
||||
Recommendation: **separate branch** post Task 9 merge для atomic-commit hygiene.
|
||||
|
||||
### Edit 3.1: Add Quirk 77 в known-quirks section (after Quirk 73)
|
||||
|
||||
**Anchor:** end of Quirk 73 block, before `**NB:** quirks 70 (axe-core...)` line.
|
||||
|
||||
**Insert:**
|
||||
|
||||
```markdown
|
||||
3. **Quirk 77 (memory feedback_environment.md, added 13.05.2026 day +1) — Pest --parallel deterministic unique-key collision на `projects(tenant_id, name)` в bulk-action tests.**
|
||||
- Symptom: `vendor/bin/pest --parallel --recreate-databases` reproducibly fails 738/742 на `ProjectBulkActionsTest::rejects_bulk_when_scope_filter_captures_more_than_500_projects`. Signature `SQLSTATE[23505] projects_tenant_id_name_key — (tenant_id, name)=(<id>, "<faker-3words>")`. Tenant_id varies per run (~50 apart — per-worker auto-increment).
|
||||
- Test creates 501 projects в single tenant; Faker Lorem provider ~100 default English words → ~1M 3-word combos; birthday paradox ~12.5% per-test → НЕ deterministic baseline. Reproducible-in-parallel-but-not-sequential pattern suggests worker state sharing (shared Faker seed via PHP global state? Eloquent factory caching?). Full RCA pending.
|
||||
- Sequential `vendor/bin/pest tests/Feature/Api/ProjectBulkActionsTest.php` passes 14/14 ✅.
|
||||
- Mitigation: treat as known parallel-only flake; sequential isolation always passes; baseline regression check on main post-merge — accept 738/742 OR rerun sequential.
|
||||
```
|
||||
|
||||
(Adjust numbering — make this #3 in known-quirks list, push existing «**NB:**» line после.)
|
||||
|
||||
### Edit 3.2: Add Hypothesis 4 в diagnostic pipeline (between current H3 «cumulative state» и H4 «other»)
|
||||
|
||||
**Current diagnostic pipeline ends with «Hypothesis 4 — other». Insert new H4 (quirk 77) before, renumber «other» to H5.**
|
||||
|
||||
**Replace:**
|
||||
|
||||
```markdown
|
||||
4. **Hypothesis 4 — other.** If none of above → escalate с raw output + tested hypotheses + outcome per hypothesis.
|
||||
```
|
||||
|
||||
**With:**
|
||||
|
||||
```markdown
|
||||
4. **Hypothesis 4 — quirk 77 (unique-key collision в bulk-action tests).** Failing test creates ≥500 records of one model в single tenant с Faker-generated unique field? Pattern: `SQLSTATE[23505]` + `_tenant_id_<col>_key` constraint name + Faker-style value в DETAIL. Rerun sequential `./vendor/bin/pest <test-file>` — if passes 14/14 → quirk 77 confirmed; document as known parallel-only flake, не fix без user OK (root cause не fully RCA'd).
|
||||
5. **Hypothesis 5 — other.** If none of above → escalate с raw output + tested hypotheses + outcome per hypothesis.
|
||||
```
|
||||
|
||||
### Edit 3.3: Update output template — add Hypothesis 4 row
|
||||
|
||||
**Replace в Output format block:**
|
||||
|
||||
```text
|
||||
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>
|
||||
```
|
||||
|
||||
**With:**
|
||||
|
||||
```text
|
||||
Hypothesis 3 (quirk 73 cumulative state): <falsified|confirmed|untested>
|
||||
Evidence: <command + output>
|
||||
Hypothesis 4 (quirk 77 unique-key collision): <falsified|confirmed|untested>
|
||||
Evidence: <command + output>
|
||||
|
||||
Conclusion: <real fix needed | quirk 72 — known race document | quirk 73 — recreate-databases fixed | quirk 77 — known parallel-only flake document | other — escalate>
|
||||
```
|
||||
|
||||
### Edit 3.4: Update agent description (frontmatter)
|
||||
|
||||
**OLD description:**
|
||||
|
||||
```yaml
|
||||
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.
|
||||
```
|
||||
|
||||
**NEW description:**
|
||||
|
||||
```yaml
|
||||
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),
|
||||
(d) quirk 77 (unique-key collision в bulk-action tests with Faker-generated names),
|
||||
or (e) other — escalate. Falsifies hypotheses with actual command runs.
|
||||
```
|
||||
|
||||
### Step 3.5: Verify markdownlint + commit
|
||||
|
||||
```bash
|
||||
npx markdownlint-cli2 ".claude/agents/pest-parallel-debugger.md" 2>&1 | tail -5
|
||||
```
|
||||
|
||||
Expected: 0 errors.
|
||||
|
||||
```bash
|
||||
git add .claude/agents/pest-parallel-debugger.md
|
||||
"C:/моя/проекты/портал crm/Документация/bin/gitleaks.exe" protect --staged --config "C:/моя/проекты/портал crm/Документация/.gitleaks.toml" --no-banner
|
||||
git commit -m "$(cat <<'EOF'
|
||||
feat(agent): extend pest-parallel-debugger с quirk 77 (unique-key collision)
|
||||
|
||||
Added Quirk 77 documentation per memory feedback_environment.md addition:
|
||||
Pest --parallel deterministic unique-key collision на projects(tenant_id, name)
|
||||
в ProjectBulkActionsTest::rejects_bulk_when_scope_filter_captures_more_than_500_projects.
|
||||
|
||||
- New Hypothesis 4 в diagnostic pipeline (between quirk 73 и «other»)
|
||||
- Updated output template (Hypothesis 4 row + extended Conclusion options)
|
||||
- Updated description frontmatter (added quirk 77 classification)
|
||||
|
||||
Evidence (Task 8 baseline check):
|
||||
- Reproducible 738/742 в --parallel --recreate-databases
|
||||
- Sequential isolation 14/14 passes
|
||||
- Pre-existing flake, NOT regression from any specific commit
|
||||
- Root cause partial (Faker seed sharing hypothesis); full RCA pending
|
||||
|
||||
NB: project-local subagent auto-discovery может требовать session restart.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Self-review (after writing plan)
|
||||
|
||||
### 1. Spec coverage
|
||||
|
||||
- ✅ Memory quirk entry (Task 1) — follows established pattern (numbered, dated, symptom/why/apply).
|
||||
- ✅ MEMORY.md summary update (Task 2) — bumps count + adds #77 to inline summary.
|
||||
- ✅ Subagent extension (Task 3) — 4 distinct edits to integrate quirk 77 throughout subagent prompt.
|
||||
|
||||
### 2. Placeholder scan
|
||||
|
||||
- `<id>`, `<faker-name>`, `<faker-3words>`, `<col>`, `<test-file>` — these are documentation placeholders for varying actual values, not implementation gaps. Acceptable.
|
||||
- No "TBD" / "implement later" / "fill in details".
|
||||
|
||||
### 3. Type consistency
|
||||
|
||||
- Quirk number `77` consistent across Task 1 entry, Task 2 summary, Task 3 hypothesis label.
|
||||
- File paths `app/tests/Feature/Api/ProjectBulkActionsTest.php`, `app/database/factories/ProjectFactory.php`, `db/schema.sql:836` consistent.
|
||||
- Existing quirk numbers `70-76` referenced consistently with their actual content (verified via Grep this session).
|
||||
|
||||
### 4. NB ограничения (явно зафиксированы)
|
||||
|
||||
- **Не верифицировал** root cause of «deterministic-in-parallel-but-not-sequential» pattern beyond «possible worker state sharing» hypothesis. Full RCA requires deeper investigation (PHP shared globals via fork, Faker internal state, Pest worker config). Quirk entry honestly documents this как «root cause partial; pending».
|
||||
- **Не запускал** Pest на feat/claude-automation worktree to re-confirm collision — relied on Task 8 subagent's two consecutive --parallel runs.
|
||||
- **Не верифицировал** что Faker Lorem default has ~100 words exact count — citation of general Faker docs knowledge, may differ in actual installed Faker version.
|
||||
- **Не применил** ни одного Edit от Tasks 1-3 — это plan only.
|
||||
|
||||
---
|
||||
|
||||
## Execution handoff
|
||||
|
||||
Plan complete и saved to `docs/superpowers/plans/2026-05-13-quirk-77-pest-parallel-unique-key-collision-plan.md`. Two execution options:
|
||||
|
||||
1. **Inline Execution** — execute Tasks 1-3 в new session through `superpowers:executing-plans`. NB: Task 1+2 modify files OUTSIDE repo (memory), no commit needed. Task 3 commits to feat/claude-automation OR new sub-branch.
|
||||
|
||||
2. **Plan-only** — saved для будущей реализации; defer until Task 9 sync нормативки (completion plan) merged, then apply quirk 77 update on fresh sub-branch.
|
||||
|
||||
**Recommendation:** Plan-only — wait until completion plan Task 9 merged, then apply quirk 77 на separate branch `feat/quirk-77-update` для atomic-commit hygiene.
|
||||
|
||||
**Which approach?** (или — plan saved здесь, оставить как future-work item для memory cleanliness)
|
||||
@@ -0,0 +1,498 @@
|
||||
---
|
||||
title: Claude Code automation recommendations — внедрение 8 пунктов (MCP × 2 + skills × 2 + hooks × 2 + subagents × 2)
|
||||
date: 2026-05-13
|
||||
status: draft (awaiting customer approval before plan execution; user requested plan-only, no install)
|
||||
author: Claude (через superpowers:writing-plans)
|
||||
related-rules: |
|
||||
- [CLAUDE.md §3.3](../../../CLAUDE.md) — реестр 33 формализованных инструментов (после внедрения станет 35 при условии sync нормативки — НЕ в этом плане)
|
||||
- [Pravila §4.5](../../../docs/Pravila_raboty_Claude_v1_1.md) — варианты A/B/C перед нетривиальным выбором
|
||||
- [Pravila §4.6](../../../docs/Pravila_raboty_Claude_v1_1.md) — self-review триггеры
|
||||
- [Pravila §4.7 п.4](../../../docs/Pravila_raboty_Claude_v1_1.md) — relative paths `../../../<target>` для plans/specs (квирк 76 от 13.05)
|
||||
- [Pravila §12 hard rule](../../../docs/Pravila_raboty_Claude_v1_1.md) — skill инвокация ПЕРВОЙ
|
||||
- [Pravila §13](../../../docs/Pravila_raboty_Claude_v1_1.md) — UI/UX pool координация
|
||||
- [PSR_v1 R10.1](../../../docs/Plugin_stack_rules_v1.md) — формализация внешних инструментов (отдельный план)
|
||||
- [Tooling §3.3](../../../docs/Tooling_v8_3.md) — реестр; sync — отдельный план
|
||||
- Existing [`.claude/settings.json`](../../../.claude/settings.json) — пример PostToolUse markdownlint hook
|
||||
- Existing [`.mcp.json`](../../../.mcp.json) — пример 4 MCP server entries
|
||||
- Existing [`lefthook.yml`](../../../lefthook.yml) — 8 pre-commit + 2 pre-push jobs (не дублировать)
|
||||
---
|
||||
|
||||
# Design: Claude Code automation recommendations — внедрение 8 пунктов
|
||||
|
||||
## 1. Контекст и триггер
|
||||
|
||||
**Триггер:** заказчик в session 13.05.2026 day +1 запустил `/claude-code-setup:claude-automation-recommender` — skill проанализировал codebase и выдал 8 рекомендаций (2 MCP + 2 custom skills + 2 hooks + 2 subagents) + 1 plugin (`commit-commands`). На вопрос о scope заказчик ответил «**Все 7 пунктов одним планом, plugins не устанавливай, экономия 0%**». Это spec для технической части (plugin `commit-commands` исключён; sync нормативки PSR_v1/Tooling/CLAUDE.md/Pravila — отдельным планом потом).
|
||||
|
||||
**Numerical reconciliation:** «7 пунктов» = округление заказчика. По факту 8 технических автоматизаций после исключения plugin commit-commands. Скоп подтверждаю в Section 2.
|
||||
|
||||
**Текущее состояние [`.claude/`](../../../.claude/):**
|
||||
|
||||
- `.claude/settings.json` — permissions (24 allow / 6 deny) + 1 PostToolUse hook (markdownlint auto-fix на `*.md` кроме CLAUDE.md).
|
||||
- `.claude/settings.local.json` — user-specific overrides (есть, но содержимое не критично для плана).
|
||||
- `.claude/worktrees/` — 2 isolated worktrees от прошлых subagent dispatches (не трогать).
|
||||
- `.claude/agents/` — **отсутствует**.
|
||||
- `.claude/skills/` — **отсутствует**.
|
||||
- `.claude/commands/` — **отсутствует**.
|
||||
- `.claude/hooks/` — **отсутствует**.
|
||||
|
||||
**Текущее [`.mcp.json`](../../../.mcp.json):** 4 MCP server entries — `playwright`, `github` (HTTP+PAT), `laravel-boost` (stdio локальный), `semgrep` (stdio через `npx -y semgrep-mcp`).
|
||||
|
||||
**Текущий [`lefthook.yml`](../../../lefthook.yml):** 8 pre-commit jobs (gitleaks, markdownlint, cspell, stylelint, pint, larastan, squawk, eslint-vue) + 2 pre-push (gitleaks-full-history, lychee). **Важно для дизайна hook'ов:** Claude Code hooks ≠ git hooks. Lefthook срабатывает на `git commit`/`git push`, Claude Code hooks — на `Edit`/`Write`/`Bash` tool calls. Не дублировать функционал.
|
||||
|
||||
## 2. Scope (8 пунктов)
|
||||
|
||||
| # | Тип | Имя | Файл результата | Атомарный коммит |
|
||||
|---|---|---|---|---|
|
||||
| 1 | MCP | Sentry MCP | [`.mcp.json`](../../../.mcp.json) +1 entry | `feat(mcp): add sentry-mcp` |
|
||||
| 2 | MCP | Redis MCP | [`.mcp.json`](../../../.mcp.json) +1 entry | `feat(mcp): add redis-mcp` |
|
||||
| 3 | Skill | `/q-item-add` | `.claude/skills/q-item-add/SKILL.md` | `feat(skill): add q-item-add` |
|
||||
| 4 | Skill | `/rls-check` | `.claude/skills/rls-check/SKILL.md` | `feat(skill): add rls-check` |
|
||||
| 5 | Hook | PreToolUse block CLAUDE.md | [`.claude/settings.json`](../../../.claude/settings.json) +1 hook | `feat(hook): block direct CLAUDE.md edits` |
|
||||
| 6 | Hook | PostToolUse schema CHANGELOG reminder | [`.claude/settings.json`](../../../.claude/settings.json) +1 hook | `feat(hook): remind schema CHANGELOG on db/schema.sql edits` |
|
||||
| 7 | Subagent | `rls-reviewer` | `.claude/agents/rls-reviewer.md` | `feat(agent): add rls-reviewer` |
|
||||
| 8 | Subagent | `pest-parallel-debugger` | `.claude/agents/pest-parallel-debugger.md` | `feat(agent): add pest-parallel-debugger` |
|
||||
|
||||
## 3. Out of scope
|
||||
|
||||
- **Plugin `anthropics/claude-plugins-official:commit-commands`** — заказчик исключил («plugins не устанавливай»).
|
||||
- **Sync нормативной документации** (PSR_v1 R10.1 формализация Sentry/Redis MCP, Tooling §3.3 numbering #34/#35, CLAUDE.md §3.3 строки, Pravila §13.2 счётчик infrastructure subsection) — заказчик подтвердил «sync — потом отдельно». **Прецедент v1.83 audit gap (5 инструментов активно без формализации) явно принят на этот цикл.**
|
||||
- **`coverage:json` / vitest coverage улучшения** для skills/subagent'ов — out (не code).
|
||||
- **CI integration** (запуск hooks/skills в GitHub Actions) — out.
|
||||
- **Производственная активация Sentry/Redis credentials** — pre-flight Task 1 documents secrets-injection pattern, но реальные credentials заказчик инжектирует вне плана (через `$env:SENTRY_TOKEN`, etc.).
|
||||
|
||||
## 4. Архитектура — per-item
|
||||
|
||||
### 4.1. MCP Sentry
|
||||
|
||||
**Цель:** прямой доступ Claude к Sentry issues/events для self-hosted экземпляра в Yandex Cloud (см. [CLAUDE.md §2](../../../CLAUDE.md) — «Sentry: self-hosted в Yandex Cloud»).
|
||||
|
||||
**Package selection unknown:** ecosystem MCP servers для Sentry на 2026-05-13 — несколько вариантов:
|
||||
|
||||
- `@sentry/mcp-server` (official, если есть)
|
||||
- `mcp-server-sentry` (community)
|
||||
- Docker-based wrapper
|
||||
|
||||
→ **Pre-flight Task 1 проверит `npm search sentry mcp` + `npm view <pkg>` + GitHub search**, фиксирует канонический package + version. Plan Task 2 использует определённое имя; до pre-flight — placeholder `<sentry-mcp-pkg>`.
|
||||
|
||||
**Config pattern:**
|
||||
|
||||
```json
|
||||
{
|
||||
"sentry": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "<sentry-mcp-pkg>"],
|
||||
"env": {
|
||||
"SENTRY_URL": "${SENTRY_URL}",
|
||||
"SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}"
|
||||
},
|
||||
"comment": "Off-phase tool — Sentry MCP для self-hosted в Yandex Cloud. Pending sync в Tooling §3.3 #34 (отдельный план). Env vars: SENTRY_URL (https://sentry.<your-domain>.ru), SENTRY_AUTH_TOKEN (user scope sentry:read). Credentials в .env.local (gitignored), Claude Code считывает env из shell startup."
|
||||
}
|
||||
```
|
||||
|
||||
**Secrets handling:**
|
||||
|
||||
- `SENTRY_URL` + `SENTRY_AUTH_TOKEN` — env vars из shell. Заказчик настраивает через PowerShell profile `[Environment]::SetEnvironmentVariable` или `.env.local` подгружаемый им.
|
||||
- **НЕ commit'ить credentials.** Существующий gitleaks (lefthook pre-commit + pre-push) поймает leak — это validated safety net.
|
||||
- `.gitleaks.toml` allowlist для `${SENTRY_*}` patterns — проверить, что `${...}` syntax не триггерит false positive. Pre-flight Task 1.
|
||||
|
||||
### 4.2. MCP Redis
|
||||
|
||||
**Цель:** read-only debug-доступ к Memurai (Redis 7-совместимый, локальный Windows service) для отладки очередей, кэша, Pest --parallel cache race ([memory quirk 72](../../../../../Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_environment.md)) и retry-state в `RouteSupplierLeadJob`.
|
||||
|
||||
**Package:** `@modelcontextprotocol/server-redis` (документирован в Anthropic MCP ecosystem на 2026-05; pre-flight Task 1 verify через `npm view`).
|
||||
|
||||
**Config pattern:**
|
||||
|
||||
```json
|
||||
{
|
||||
"redis": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-redis", "redis://localhost:6379"],
|
||||
"comment": "Off-phase tool — Redis MCP для Memurai (Redis 7-совместимый Windows service на localhost:6379). Pending sync в Tooling §3.3 #35 (отдельный план). READ-ONLY usage — для debug очередей, кэша, Pest --parallel race (memory quirk 72). НЕ для production Redis (нет prod на этом этапе). Tools: KEYS, GET, LRANGE, etc."
|
||||
}
|
||||
```
|
||||
|
||||
**Безопасность:**
|
||||
|
||||
- Локальный Memurai на 6379 без auth — это dev-only, не prod. Документировать в comment'е.
|
||||
- Если в будущем будет prod Redis в Yandex Cloud с auth — отдельный entry `redis-prod` с `redis://user:pass@host:port` через env var.
|
||||
|
||||
### 4.3. Skill `/q-item-add` — добавить запись в реестр Открытых_вопросов
|
||||
|
||||
**Цель:** инкапсулировать workflow добавления нового Q-item (Биз-N/CTO-N/Ю-N/Диз-N/DO-N/OPEN-N) в [docs/Открытые_вопросы_v8_3.md](../../../docs/Открытые_вопросы_v8_3.md). Сейчас это 5-6 шагов вручную:
|
||||
|
||||
1. Найти секцию (Биз / CTO / Ю / Диз / DO / OPEN) в narrative.
|
||||
2. Найти следующий свободный номер (последний +1).
|
||||
3. Вписать строку формата `**<prefix>-N <STATUS-EMOJI>** ⏸ от 2026-05-13: <текст> — <дата-фиксации>`.
|
||||
4. Bump «Сводка §0» counters (открытые / закрытые).
|
||||
5. Bump header version + footer version + changelog entry.
|
||||
6. Sync §0 row в [CLAUDE.md](../../../CLAUDE.md) (cross-reference на v1.X→v1.X+1 реестра).
|
||||
|
||||
**Risk:** легко забыть пп. 4-6 → реестр и CLAUDE.md уходят в дрейф. Прецедент: v1.83 audit gap (5 инструментов активно без формализации) показал, что multi-file sync без skill'а ненадёжен.
|
||||
|
||||
**Skill structure (`.claude/skills/q-item-add/SKILL.md`):**
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: q-item-add
|
||||
description: |
|
||||
Add a new open question (Q-item) to the registry docs/Открытые_вопросы_v8_3.md.
|
||||
Use when customer raises a new business/CTO/legal/design/devops/OPEN question
|
||||
that does not have an immediate answer. Walks through 6-step workflow:
|
||||
detect section, find next number, insert entry, update §0 counters,
|
||||
bump header/footer/changelog version, sync §0 row in CLAUDE.md.
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# Q-item-add — add a new open question to the registry
|
||||
|
||||
## Usage
|
||||
Invoke explicitly via `/q-item-add <Биз|CTO|Ю|Диз|DO|OPEN> "<question text>"`.
|
||||
|
||||
## Workflow
|
||||
1. Open `docs/Открытые_вопросы_v8_3.md` and find section for the prefix (e.g., section ## 13 for Биз-*).
|
||||
2. Grep latest number in that section (e.g., `Биз-31` is current max → new = `Биз-32`).
|
||||
3. Insert new row in table or below previous entry in narrative form.
|
||||
4. Update «Сводка §0»: `Биз 24 ✅ / 7 ⏸` → `Биз 24 ✅ / 8 ⏸` (or shifts as appropriate).
|
||||
5. Bump header version (e.g., `v1.83 от 13.05.2026 (day +1)` → `v1.84 от 13.05.2026 (day +1)`).
|
||||
6. Bump footer version + add changelog entry under «История версий».
|
||||
7. Sync `CLAUDE.md` §0 row «Открытые вопросы» — bump `v1.83+` → `v1.84+`.
|
||||
|
||||
## Validation
|
||||
- After save: `lychee --config .lychee.toml docs/Открытые_вопросы_v8_3.md` (0 broken links).
|
||||
- Counter arithmetic check: sum of ✅ + ⏸ per prefix unchanged unless adding new.
|
||||
|
||||
## When NOT to use
|
||||
- Customer says «закрываем X» — that's closure, not addition. Use targeted Edit instead.
|
||||
- Item already exists with same text — это duplicate; ask customer or update existing.
|
||||
```
|
||||
|
||||
**`disable-model-invocation: true`** — skill только для пользовательской инвокации (`/q-item-add ...`), Claude не должен сам решать «давайте добавим Q-item», т.к. правило Pravila §2.2 требует явного запроса от заказчика.
|
||||
|
||||
### 4.4. Skill `/rls-check` — verify RLS policy на новой таблице
|
||||
|
||||
**Цель:** инкапсулировать чек-лист для security-critical работы — добавление таблицы в [db/schema.sql](../../../db/schema.sql) требует:
|
||||
|
||||
1. Колонка `tenant_id UUID NOT NULL` (или явное обоснование для SaaS-level таблицы как `supplier_csv_reconcile_log`).
|
||||
2. `ENABLE ROW LEVEL SECURITY`.
|
||||
3. 2 политики минимум: SELECT для `crm_app_*` ролей, ALL для `crm_app_admin`.
|
||||
4. GRANT для 5 ролей (`crm_app_user`, `crm_app_admin`, `crm_supplier_worker`, `crm_readonly`, `crm_migrator`).
|
||||
5. Запись в [db/CHANGELOG_schema.md](../../../db/CHANGELOG_schema.md).
|
||||
6. squawk на staged SQL (lefthook pre-commit это уже делает, но skill напоминает).
|
||||
7. Smoke test через `tests/Feature/RlsSmokeTest.php` или новый тест для конкретной таблицы.
|
||||
|
||||
**Skill structure (`.claude/skills/rls-check/SKILL.md`):**
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: rls-check
|
||||
description: |
|
||||
Verify Row-Level Security on a new or modified table in db/schema.sql.
|
||||
Use when adding a new table, adding/removing tenant_id column, or modifying
|
||||
RLS policies. Walks through 7-step checklist (tenant_id, ENABLE RLS, 2+
|
||||
policies, 5 role GRANTs, CHANGELOG, squawk, smoke test).
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
# RLS-check — verify Row-Level Security on a new table
|
||||
|
||||
## Usage
|
||||
Invoke explicitly via `/rls-check <table_name>`.
|
||||
|
||||
## Checklist
|
||||
1. **tenant_id column.** Grep `db/schema.sql` for `CREATE TABLE <name>`. Verify `tenant_id UUID NOT NULL REFERENCES tenants(id)` exists. Exception: SaaS-level tables (e.g., `supplier_csv_reconcile_log`) — must have explicit comment justifying.
|
||||
2. **ENABLE RLS.** Grep `ALTER TABLE <name> ENABLE ROW LEVEL SECURITY;` — must be present.
|
||||
3. **Policies.** Minimum 2 policies: `SELECT` for `crm_app_user`/`crm_app_admin` (tenant scope via `current_setting('app.current_tenant_id')::uuid`), `ALL` for `crm_app_admin` (or other privileged role). For SaaS-level tables — BYPASSRLS via role (e.g., `crm_supplier_worker`).
|
||||
4. **Role GRANTs.** Verify `GRANT SELECT|INSERT|UPDATE|DELETE` for each of 5 roles per current pattern in `db/02_grants.sql`. Missing GRANT = silent failure in production.
|
||||
5. **CHANGELOG.** Add entry to `db/CHANGELOG_schema.md` with date + table name + summary (per [CLAUDE.md §5 п.8](../../../CLAUDE.md)).
|
||||
6. **squawk lint.** Run `./bin/squawk.exe db/schema.sql` and verify 0 issues (lefthook pre-commit will catch this, but skill verifies pre-commit).
|
||||
7. **Smoke test.** Add or extend `tests/Feature/RlsSmokeTest.php` — assert that user in tenant A cannot SELECT row from tenant B for new table. Run: `cd app && ./vendor/bin/pest --filter RlsSmokeTest`.
|
||||
|
||||
## Output
|
||||
Print pass/fail per item + count of issues. If all 7 pass — output `RLS-check: 7/7 ✅`. If any fail — list specific failures with line numbers (`db/schema.sql:NNNN missing tenant_id`).
|
||||
|
||||
## When NOT to use
|
||||
- Modifying existing well-RLS'd table without adding new columns — overhead.
|
||||
- Tables explicitly outside RLS scope (e.g., `migrations`, `cache` — Laravel internal).
|
||||
```
|
||||
|
||||
### 4.5. Hook PreToolUse — блокировка прямой правки `CLAUDE.md`
|
||||
|
||||
**Цель:** runtime enforcement [§5 п.10](../../../CLAUDE.md) — hard rule: `CLAUDE.md` правится только через `/claude-md-management:revise-claude-md` или `/claude-md-management:claude-md-improver`. Сейчас правило только текстом; direct `Edit CLAUDE.md` физически возможен.
|
||||
|
||||
**Design challenge:**
|
||||
|
||||
Claude Code PreToolUse hook видит `CLAUDE_TOOL_NAME` (e.g., `Edit`) и `CLAUDE_TOOL_INPUT` (JSON с `file_path`, etc.), но **не видит контекст вызова** — был ли Edit инициирован напрямую или через skill. Plugin `claude-md-management` сам использует `Edit`/`Write` под капотом — hook не отличит legitimate edit от violating.
|
||||
|
||||
**Три варианта дизайна (см. [Pravila §4.5](../../../docs/Pravila_raboty_Claude_v1_1.md) — варианты A/B/C для нетривиального выбора):**
|
||||
|
||||
**Option A — Warning-only (recommended).** Hook не блокирует, но в stderr выводит напоминание: «You are editing CLAUDE.md directly. Prefer `/claude-md-management:revise-claude-md`. If invoked via that skill, this warning is informational.» Trade-off: violation возможна, но видна сразу.
|
||||
|
||||
**Option B — Hard block with skill-marker env.** Hook блокирует, если `$CLAUDE_SKILL_ACTIVE !== 'claude-md-management'`. **Risk:** этой env var может не существовать на 2026-05 Claude Code API. Pre-flight Task 1 verify.
|
||||
|
||||
**Option C — Hookify rule.** Использовать `/hookify:hookify` для создания rule на основе conversation analysis (hookify уже работает для economy hook 6-component architecture, см. [memory `feedback_superpowers_hard_rule.md`](../../../../../Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_superpowers_hard_rule.md)). Trade-off: внешняя зависимость от plugin hookify; gain: контекстная аналитика (skill-marker detection уже работает).
|
||||
|
||||
**Решение (для spec, awaiting customer):** Pre-flight Task 1 определяет наличие `CLAUDE_SKILL_*` env vars. Если есть — Option B. Если нет — Option A (warning) + параллельно открыть AskUserQuestion для согласования миграции на hookify (Option C) как явная отдельная задача (не в этом плане).
|
||||
|
||||
**Hook code (Option A draft):**
|
||||
|
||||
```json
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node -e \"const f=process.env.CLAUDE_FILE_PATH||''; const skillCtx=process.env.CLAUDE_SKILL_ACTIVE||''; if (/^CLAUDE\\\\.md$/i.test(require('path').basename(f)) && !skillCtx.includes('claude-md-management')) { process.stderr.write('\\\\n[hook] WARNING: Direct edit of CLAUDE.md detected. Per §5 п.10, prefer /claude-md-management:revise-claude-md or /claude-md-management:claude-md-improver. If invoked via the skill, this warning is informational.\\\\n'); }\""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
NB: `path.basename(f)` чтобы matchнуть только корневой `CLAUDE.md`, не `app/CLAUDE.md` или `node_modules/.../CLAUDE.md`.
|
||||
|
||||
**Hook code (Option B draft, if `CLAUDE_SKILL_ACTIVE` exists):**
|
||||
|
||||
Same `command`, но `process.exit(2)` + stderr вместо warning, когда skill-marker отсутствует.
|
||||
|
||||
**Альтернативное проектирование (Option D, расширение):** matcher для `Bash` calls типа `sed -i.*CLAUDE.md` или `> CLAUDE.md`. Текущее предложение в spec не покрывает Bash-обход. Bash-обход редок (≥99% правок через Edit/Write), но для completeness — Task 6 включает sub-step «consider Bash matcher» с фиксацией решения в коммит-сообщении.
|
||||
|
||||
### 4.6. Hook PostToolUse — напомнить про `db/CHANGELOG_schema.md`
|
||||
|
||||
**Цель:** runtime reminder [§5 п.8](../../../CLAUDE.md) — каждая правка `db/schema.sql` требует записи в `db/CHANGELOG_schema.md`. Self-review (§8) ловит это поздно (после ≥3 групп правок), hook — сразу.
|
||||
|
||||
**Design:** PostToolUse matcher `Edit|Write`, check `process.env.CLAUDE_FILE_PATH` for `db/schema.sql` (basename match), output reminder в stdout (видим в transcript).
|
||||
|
||||
**Hook code:**
|
||||
|
||||
```json
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "node -e \"const f=process.env.CLAUDE_FILE_PATH||''; const norm=f.replace(/\\\\\\\\/g,'/'); if (/(^|\\\\/)db\\\\/schema\\\\.sql$/i.test(norm)) { process.stdout.write('\\\\n[hook] REMINDER: You modified db/schema.sql. Per §5 п.8 (CLAUDE.md), add a corresponding entry to db/CHANGELOG_schema.md before committing.\\\\n'); }\""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
NB: `\\\\` для JSON escape → real `\\` в Node → real `\` в regex. Test in Task 7 verify Windows path separators normalize.
|
||||
|
||||
**Trade-off:** stdout vs stderr. stdout viewable в Claude transcript directly (как сейчас markdownlint output появляется); stderr может теряться. Решение — stdout.
|
||||
|
||||
**Edge case:** если правка через Bash (`echo "..." >> db/schema.sql` или `psql` direct DDL) — hook не сработает. Bash matcher альтернатива (как в 4.5 Option D). Скоп этой spec — только Edit/Write, Bash-обход документирован как known limitation.
|
||||
|
||||
### 4.7. Subagent `rls-reviewer`
|
||||
|
||||
**Цель:** parallel review subagent для migration PR'ов, специализированный на RLS-семантике Лидерры. Generic `security-review` plugin не знает про 5 ролей, `crm_supplier_worker` BYPASSRLS, `current_setting('app.current_tenant_id')` pattern.
|
||||
|
||||
**Subagent structure (`.claude/agents/rls-reviewer.md`):**
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: rls-reviewer
|
||||
description: |
|
||||
Review RLS (Row-Level Security) compliance on migration commits/PRs.
|
||||
Use when reviewing changes to db/schema.sql or db/migrations/ that add
|
||||
or modify tables. Specialized for Лидерра's 5-role architecture
|
||||
(crm_app_user, crm_app_admin, crm_supplier_worker BYPASSRLS,
|
||||
crm_readonly, crm_migrator). Reports orphan policies, missing
|
||||
tenant_id columns, inconsistent GRANTs, missing CHANGELOG entries.
|
||||
tools: Read, Grep, Glob, Bash
|
||||
---
|
||||
|
||||
# RLS reviewer agent (Лидерра)
|
||||
|
||||
You are reviewing a database migration or schema change for RLS (Row-Level Security) compliance in the Лидерра CRM project.
|
||||
|
||||
## Context
|
||||
|
||||
- The project uses PostgreSQL 16 with 5 roles defined in `db/00_create_roles.sql` and `db/02_grants.sql`:
|
||||
- `crm_app_user` — regular tenant user, RLS enforced via `current_setting('app.current_tenant_id')`.
|
||||
- `crm_app_admin` — tenant admin, RLS enforced, broader policies.
|
||||
- `crm_supplier_worker` — SaaS-level worker (BYPASSRLS), for supplier integration jobs.
|
||||
- `crm_readonly` — read-only role for reports, RLS enforced.
|
||||
- `crm_migrator` — DDL role, RLS BYPASSED via session, used by Laravel migrations.
|
||||
- Each tenant-scoped table must have:
|
||||
- `tenant_id UUID NOT NULL REFERENCES tenants(id)` column.
|
||||
- `ENABLE ROW LEVEL SECURITY`.
|
||||
- At least 2 policies: SELECT (tenant scope) and ALL (admin scope), or per project convention.
|
||||
- GRANTs for the 5 roles in `db/02_grants.sql`.
|
||||
- SaaS-level tables (e.g., `supplier_csv_reconcile_log`, `system_settings`) are exempt from tenant_id; must have explicit comment justifying.
|
||||
- Every schema change requires a `db/CHANGELOG_schema.md` entry.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Read the target migration file or `db/schema.sql` diff.
|
||||
2. For each table added/modified, run the 7-item checklist (same as `/rls-check` skill but in review mode — read-only, no fixes).
|
||||
3. Cross-check `db/02_grants.sql` for matching GRANTs.
|
||||
4. Cross-check `db/CHANGELOG_schema.md` for entry with correct date.
|
||||
5. Run `./bin/squawk.exe <changed-sql>` and capture issues.
|
||||
6. Output a structured report:
|
||||
|
||||
```text
|
||||
RLS Review — <table_name>
|
||||
[✅/❌] tenant_id column present
|
||||
[✅/❌] ENABLE ROW LEVEL SECURITY
|
||||
[✅/❌] SELECT policy for crm_app_user
|
||||
[✅/❌] ALL policy for crm_app_admin
|
||||
[✅/❌] 5-role GRANTs in db/02_grants.sql
|
||||
[✅/❌] db/CHANGELOG_schema.md entry
|
||||
[✅/❌] squawk passes (0 issues)
|
||||
Issues:
|
||||
- <line>:<column> <message>
|
||||
Pass: <N>/7
|
||||
```
|
||||
|
||||
## Constraints
|
||||
|
||||
- Read-only — do not edit files, only report.
|
||||
- If a table is SaaS-level, accept exemption with explicit comment; flag if comment missing.
|
||||
- For composite PK or partitioned tables (e.g., `lead_charges` partitioned by month), verify the policy applies to parent + children.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- General SQL style (squawk handles).
|
||||
- General code review (other agents handle).
|
||||
- Performance review (separate concern).
|
||||
|
||||
```
|
||||
|
||||
**Tools:** `Read, Grep, Glob, Bash` — read-only, plus `Bash` для squawk binary.
|
||||
|
||||
### 4.8. Subagent `pest-parallel-debugger`
|
||||
|
||||
**Цель:** specialized debugger для Pest --parallel flaky failures. Знает 2 квирка из [memory `feedback_environment.md`](../../../../../Users/Administrator/.claude/projects/c---------------------crm-------------/memory/feedback_environment.md), специфичных для Pest --parallel в этом проекте:
|
||||
|
||||
- **Quirk 72** (memory line 389) — Pest --parallel Redis cache `supplier:session` race в subdir-only run. Full --parallel suite passes 742/739/0/3 ✅. `vendor/bin/pest --parallel tests/Feature/Supplier/` deterministic 41/43 (2 random failed каждый run, fixed `CleanupInactiveSupplierProjectsJobTest::handles_404_from_supplier`). Root cause: `SupplierPortalClient::loadSession()` (line 220-244) читает global Redis `supplier:session`; в subdir-only — race постоянная (4 supplier files × 8 workers); в full suite — race редкая. Mitigation: subdir = `--parallel=0` или sequential; full suite = известно green.
|
||||
- **Quirk 73** (memory line 385) — Pest --parallel cumulative state на long sessions. Symptom: `LookupsTest line 31` «1067 matches 2», `LookupsTest line 48` «admin@example.ru vs Абрам К.», `ProjectExtensionsTest line 89` «7677 identical to 1» — «too many rows» signatures. Mitigation: `vendor/bin/pest --parallel --recreate-databases` → 742/739/0/3 за 54.9s. Worker-DBs кэшируются через token-suffix, migrations не пересоздаются между runs без флага.
|
||||
|
||||
Generic debug skill не знает эти specifics — каждый раз пробег по той же диагностике.
|
||||
|
||||
**NB:** quirks 70-71 в memory — про a11y / Vuetify aria-label, **не Pest** — не входят в этот subagent. Quirks 74-76 — про npm/Lucide/plans paths, тоже не Pest.
|
||||
|
||||
**Subagent structure (`.claude/agents/pest-parallel-debugger.md`):**
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: pest-parallel-debugger
|
||||
description: |
|
||||
Diagnose Pest 4 --parallel test failures in the Лидерра CRM project.
|
||||
Classifies failures as (a) real failure, (b) quirk 72 (Redis supplier:session
|
||||
race in subdir-only), (c) quirk 73 (cumulative state on long sessions),
|
||||
or (d) other — escalate. Falsifies hypotheses with actual command runs.
|
||||
tools: Read, Grep, Bash
|
||||
---
|
||||
|
||||
# Pest --parallel debugger agent (Лидерра)
|
||||
|
||||
You are diagnosing a Pest 4 --parallel test failure in the Лидерра CRM project.
|
||||
|
||||
## Known quirks (from memory feedback_environment.md, line refs as of 2026-05-13)
|
||||
|
||||
1. **Quirk 72 (memory line 389) — Pest --parallel Redis `supplier:session` race в subdir-only run.** Symptom: `vendor/bin/pest --parallel tests/Feature/Supplier/` deterministic 41/43 + 2 random failed (one fixed: `CleanupInactiveSupplierProjectsJobTest::handles_404_from_supplier`). Full suite passes 742/739/0/3 ✅. Root cause: `SupplierPortalClient::loadSession()` (line 220-244) читает global Redis key `supplier:session`; afterEach forget vs concurrent worker reads → race. Mitigation: `--parallel=0` или sequential для subdir; full suite = known green.
|
||||
2. **Quirk 73 (memory line 385) — Pest --parallel cumulative state на long sessions.** Symptom: `LookupsTest line 31` «1067 matches 2», `LookupsTest line 48` «admin@example.ru vs Абрам К.», `ProjectExtensionsTest line 89` «7677 identical to 1». Cause: worker-DBs `liderra_testing_<token>` кэшируются; migrations не пересоздаются без `--recreate-databases`; DatabaseTransactions (не RefreshDatabase per `Pest.php` line 23 commented) покрывает row-state, но не committed DDL/Redis. Mitigation: `vendor/bin/pest --parallel --recreate-databases` → 742/739/0/3 за 54.9s.
|
||||
|
||||
## Diagnostic pipeline
|
||||
|
||||
Given a failure output (paste from user or capture from `./vendor/bin/pest --parallel`):
|
||||
|
||||
1. **Capture exact failure.** What test file:line failed? Assertion message?
|
||||
2. **Hypothesis 1 — real failure.** Read failing test + production code. Catches real bug? If yes — fix the code.
|
||||
3. **Hypothesis 2 — quirk 72 (Redis supplier:session race).** Failing test в `tests/Feature/Supplier/*`? Rerun `./vendor/bin/pest --parallel=0 <test-path>` (sequential). If passes — race confirmed. If full suite (`./vendor/bin/pest --parallel`) also passes — known subdir flake, document.
|
||||
4. **Hypothesis 3 — quirk 73 (cumulative state).** Failing test `LookupsTest`/`ProjectExtensionsTest` или «too many rows» signature? Rerun `./vendor/bin/pest --parallel --recreate-databases`. If passes — cumulative DB pollution.
|
||||
5. **Hypothesis 4 — other.** If none of above — escalate с raw output + tested hypotheses + outcome per hypothesis.
|
||||
|
||||
## Output format
|
||||
|
||||
```text
|
||||
Pest --parallel debugger report
|
||||
|
||||
Failure: <file>:<line>
|
||||
Assertion: <message>
|
||||
|
||||
Hypothesis 1 (real failure): <falsified|confirmed|untested>
|
||||
Evidence: <test code summary + production code review with file:line pins>
|
||||
Hypothesis 2 (quirk 72 Redis supplier:session race): <falsified|confirmed|untested>
|
||||
Evidence: <command + output>
|
||||
Hypothesis 3 (quirk 73 cumulative state): <falsified|confirmed|untested>
|
||||
Evidence: <command + output>
|
||||
|
||||
Conclusion: <real fix needed | quirk 72 — known race document | quirk 73 — recreate-databases fixed | other — escalate>
|
||||
Recommendation: <next step for user>
|
||||
```
|
||||
|
||||
## Constraints (pest-debugger)
|
||||
|
||||
- Falsify hypotheses with actual command runs, do not just speculate.
|
||||
- Capture raw output, not summaries.
|
||||
- Never claim "should pass" — only "passed with this command" or "failed with this command + output".
|
||||
- If unsure — escalate, do not guess.
|
||||
|
||||
```
|
||||
|
||||
**Tools:** `Read, Grep, Bash` — read tests, grep memory quirks, run Pest variations.
|
||||
|
||||
## 5. Открытые вопросы перед implementation (resolve в Task 1 pre-flight)
|
||||
|
||||
| # | Вопрос | Resolution |
|
||||
|---|---|---|
|
||||
| Q1 | Canonical package name для Sentry MCP? | Pre-flight `npm search sentry mcp` + `npm view <pkg>` + GitHub search → фиксируем имя |
|
||||
| Q2 | Canonical package name для Redis MCP? | Pre-flight `npm view @modelcontextprotocol/server-redis` → подтвердить версию + tools list |
|
||||
| Q3 | Есть ли `CLAUDE_SKILL_ACTIVE` env var в Claude Code hooks API на 2026-05? | Pre-flight: `env` dump из тестового hook'а в throwaway file → фиксируем какие vars доступны |
|
||||
| Q4 | gitleaks false positive на `${SENTRY_URL}` syntax в .mcp.json? | Pre-flight test: добавить тестовый entry → `./bin/gitleaks.exe protect --staged` → проверить |
|
||||
| Q5 | Hookify rule vs custom hook для §5 п.10 CLAUDE.md block — какой подход? | Решение по Q3: если есть skill-marker env — Option B (hard block); если нет — Option A (warning) + plan для Option C (hookify) отдельно |
|
||||
| Q6 | Custom .claude/skills/ и .claude/agents/ — auto-discover на старте session или требуют restart? | Pre-flight: создать throwaway test skill → проверить inv через `/<name>` без restart |
|
||||
| Q7 | `app/CLAUDE.md` (Boost) — должен ли быть exempt от hook block? | Yes — hook matches `basename(f) === 'CLAUDE.md'` AND parent dir is project root. Регекс уточняем в Task 6 |
|
||||
|
||||
## 6. Dependencies
|
||||
|
||||
- **Sentry MCP** — требует self-hosted Sentry экземпляр + auth token. Зависимость от заказчика для credentials. План документирует pattern, install — pending credentials. До credentials MCP entry можно добавить со stub'ом `SENTRY_URL=disabled` (отключённый).
|
||||
- **Redis MCP** — требует running Memurai на localhost:6379 (уже работает per [§2](../../../CLAUDE.md) стек).
|
||||
- **`/q-item-add`** + **`/rls-check`** — нет внешних deps, чистый markdown.
|
||||
- **PreToolUse hook §5 п.10** — зависит от Q3 resolution. Если Option B — требует `CLAUDE_SKILL_ACTIVE` env. Если Option A — work standalone.
|
||||
- **PostToolUse hook db/schema.sql** — нет deps.
|
||||
- **Subagent `rls-reviewer`** — требует `./bin/squawk.exe` (уже установлен per lefthook job 7).
|
||||
- **Subagent `pest-parallel-debugger`** — требует Pest 4 setup в `app/` (уже установлен).
|
||||
|
||||
## 7. Success criteria
|
||||
|
||||
| Критерий | Метрика | Validation |
|
||||
|---|---|---|
|
||||
| `.mcp.json` валиден | JSON schema `https://raw.githubusercontent.com/anthropics/claude-code/main/schemas/mcp.json` | Open in editor → no validation errors; `claude mcp list` (если CLI доступен) shows 6 entries |
|
||||
| Sentry MCP enumerable | Tools list returns ≥1 tool (`get_issue`, `list_events`, etc.) | Pre-flight verify; если credentials отсутствуют — stub mode тоже OK для test of registration |
|
||||
| Redis MCP enumerable | Tools list returns ≥1 tool (`KEYS`, `GET`, etc.) + connection to localhost:6379 ОК | Manual MCP call `mcp__redis__KEYS *` returns array |
|
||||
| `/q-item-add` invocable | `Skill` tool list shows `q-item-add` | После создания файла, в новой session check `/q-item-add` появляется (или в текущей — pre-flight Q6) |
|
||||
| `/rls-check` invocable | Same | Same |
|
||||
| Hook block CLAUDE.md active | Manual Edit `CLAUDE.md` (test path, not real) → warning/block visible | Test: try `Edit` on temp `CLAUDE.md` copy → observe hook output |
|
||||
| Hook reminder schema.sql active | Manual Edit `db/schema.sql` (1-line whitespace) → reminder visible | Test: edit whitespace-only line in `db/schema.sql` → observe; rollback edit |
|
||||
| Subagent `rls-reviewer` invocable | `Agent({ subagent_type: 'rls-reviewer' })` succeeds | Test invocation on small migration commit |
|
||||
| Subagent `pest-parallel-debugger` invocable | Same | Test invocation on a known flaky output (synthetic) |
|
||||
| 0 regressions | Pest 742/739/0/3, Vitest 88/683+3, lychee 252 OK, gitleaks 0 | Post-implementation full lefthook regression suite |
|
||||
| Atomic commits | 8 task commits + 1 pre-flight setup + 1 final = 10 commits | git log review per [Pravila §4.3](../../../docs/Pravila_raboty_Claude_v1_1.md) |
|
||||
| 0 sync drift | CLAUDE.md / Tooling / PSR_v1 / Pravila — НЕ изменены этим планом | git diff на 4 nominal files = 0 — sync отдельным планом |
|
||||
|
||||
## 8. Координация с правилами
|
||||
|
||||
- **Sentry MCP / Redis MCP** — формально новые позиции #34 / #35 в [Tooling §3.3](../../../docs/Tooling_v8_3.md). **НЕ формализуются в этом плане** (out of scope). Прецедент v1.83 audit gap accepted на данный цикл; future audit plan (отдельный) закроет.
|
||||
- **`/q-item-add` + `/rls-check`** — project-local skills, не входят в Tooling registry (внутренние). Регулируются [PSR_v1 R0.6](../../../docs/Plugin_stack_rules_v1.md) hard-стопами (не trigger'ят).
|
||||
- **Hooks 4.5 + 4.6** — runtime enforcement existing rules ([§5 п.8](../../../CLAUDE.md), [§5 п.10](../../../CLAUDE.md)). Не новые правила.
|
||||
- **Subagents 4.7 + 4.8** — project-local agents, не trigger'ят PSR_v1 R10 (не plugins).
|
||||
- **Pravila §12 hard rule** — этот spec / plan создан через `superpowers:writing-plans` (skill инвокирован первым).
|
||||
- **Pravila §4.5** — варианты A/B/C — применены к Q5 (CLAUDE.md hook design).
|
||||
- **Pravila §4.7 п.4** — relative paths `../../../` использованы во всех cross-references из этого spec.
|
||||
|
||||
## 9. Self-review (на момент написания spec, до plan)
|
||||
|
||||
- [x] Goal в Section 1 — одно предложение, конкретное.
|
||||
- [x] Scope в Section 2 — 8 пунктов, табличная форма, mapping на файлы и коммиты.
|
||||
- [x] Out of scope явно — plugin + sync.
|
||||
- [x] Per-item Section 4 — каждый пункт имеет цель, design, code/config draft.
|
||||
- [x] Открытые вопросы Section 5 — 7 Q resolve в pre-flight.
|
||||
- [x] Dependencies Section 6 — внешние зависимости явны.
|
||||
- [x] Success criteria Section 7 — каждый пункт измеримый.
|
||||
- [x] Координация с правилами Section 8 — sync с Pravila/PSR_v1/Tooling/CLAUDE.md явна.
|
||||
- [ ] **NB ограничение:** не верифицировал, что `CLAUDE_SKILL_ACTIVE` env var существует — pre-flight Task 1 закроет.
|
||||
- [ ] **NB ограничение:** не верифицировал, что `@modelcontextprotocol/server-redis` доступен на npm — pre-flight закроет.
|
||||
- [ ] **NB ограничение:** Sentry MCP package name unknown — pre-flight закроет.
|
||||
- [ ] **NB ограничение:** не запускал тесты для проверки нерегрессии — этот spec design-only.
|
||||
@@ -0,0 +1,322 @@
|
||||
# Portal Full Audit #2 — Design (2026-05-13)
|
||||
|
||||
> **Версия:** 1.0 от 2026-05-13
|
||||
> **Триггер:** заказчик «продолжим аудит экономия 0%» (continuation после CTO-19 closure + plan5→main merge `21262ef`)
|
||||
> **Режим:** экономия 0% — максимальное всеобъемлющее качество, без любых скипов
|
||||
> **HEAD на старте:** `main` `21262ef` (Merge plan5-frontend-projects → main, 120 commits ahead `615db99`)
|
||||
> **Предыдущий аудит:** [../audits/2026-05-12-portal-full-audit-report.md](../audits/2026-05-12-portal-full-audit-report.md) (10/10 Q-items closed)
|
||||
|
||||
---
|
||||
|
||||
## 1. Цель
|
||||
|
||||
Полный 14-phase портальный аудит на main `21262ef` post-merge plan5→main. Сравнение с baseline 12.05.2026, обнаружение drift'а от 120 закоммиченных изменений (Plan 5 frontend Tasks 7-11, Quiet Luxury portal redesign, CTO-19 Lucide migration, Q.DEFER.003/004 closures, audit-fix tail). Закрытие residuals + новая Phase 14 pre-production readiness.
|
||||
|
||||
## 2. Scope-decisions (согласованы с заказчиком)
|
||||
|
||||
| Dimension | Выбрано | Альтернативы рассмотрены |
|
||||
|---|---|---|
|
||||
| Тип audit'а | Новый audit pass от main `21262ef` | (B) доразбор deferred / (C) Pa11y residual / (D) квирк 62 hygiene — отложены |
|
||||
| Глубина | Full 13-phase + Phase 14 pre-prod readiness | (A) full 13 / (B) core 6 / (C) delta-mode — отвергнуты |
|
||||
| Fix-стратегия | Hybrid: P0+P1 → atomic commits на main; P2/P3 → только findings.md | (A) fix-during-audit all / (B) audit-only / (C) per-phase gate — отвергнуты |
|
||||
| Branch policy | main directly, atomic commits, push в конце через `Bash(git push origin main:*)` | feature branch + PR — отвергнут (continuation pattern) |
|
||||
|
||||
## 3. Artifacts (выходные)
|
||||
|
||||
Все в `docs/superpowers/audits/`:
|
||||
|
||||
- **`2026-05-13-portal-full-audit.md`** — план (адаптация 12.05 плана к 2026-05-13 HEAD)
|
||||
- **`2026-05-13-portal-full-audit-findings.md`** — детальные findings per phase, P0/P1/P2/P3 + FIX-NOW/FIX-DEFER/BLOCKED tags, ≥3 гипотезы per non-trivial finding (per economy 0% + Pravila §4.5 systematic-debugging)
|
||||
- **`2026-05-13-portal-full-audit-blocked.md`** — Q-items (Q.HARD/Q.PRODUCT/Q.DEFER/Q.INFO) с «что нужно от заказчика» + «план Б»
|
||||
- **`2026-05-13-portal-full-audit-report.md`** — summary verdict 🟢/🟡/🔴 + метрики до/после + commits list + lessons captured
|
||||
|
||||
**Доп. артефакты:**
|
||||
|
||||
- Screenshots в `audit-screens/2026-05-13/` (24 views Phase 5).
|
||||
- Memory updates: новые квирки в `feedback_environment.md`, baseline updates в `project_state.md` после Phase 9.
|
||||
|
||||
## 4. Phases (14 шт.)
|
||||
|
||||
### Phase 0 — Pre-flight (~5 мин)
|
||||
|
||||
- `git status --short` + `git log --oneline -10` → подтвердить HEAD = `21262ef`, working tree clean.
|
||||
- `git diff HEAD~5 --stat` — что менялось в последних 5 коммитах.
|
||||
- Skeleton 4 audit-файлов в `docs/superpowers/audits/2026-05-13-portal-full-audit-{plan,findings,blocked,report}.md`.
|
||||
- Inventory untracked workdir после CTO-19 (Lucide migration screenshots, mapping changes).
|
||||
- Verify deps installed: `composer install --quiet` + `npm ci --legacy-peer-deps` (per квирк 74).
|
||||
|
||||
### Phase 1 — Static analysis (parallel ×4 subagents, ~20 мин)
|
||||
|
||||
Single message с 4 параллельными `Agent` tool calls (per `superpowers:dispatching-parallel-agents`):
|
||||
|
||||
- **Subagent A (Backend) — `subagent_type: general-purpose`:** `composer pint:test` + `composer stan` + `composer audit --locked`. Return raw exit codes + полный stderr/stdout, не summary.
|
||||
- **Subagent B (Frontend) — `subagent_type: general-purpose`:** `npm run lint:vue` + `npx vue-tsc --noEmit` + `npx prettier --check .` + `npx knip --production`. Raw output.
|
||||
- **Subagent C (Docs) — `subagent_type: general-purpose`:** `npm run lint:md` + `npm run spell` + `npm run links`. Raw output.
|
||||
- **Subagent D (SQL) — `subagent_type: general-purpose`:** `npx squawk lint app/database/migrations/` + `pg_format db/schema.sql > /tmp/schema-fmt.sql && diff db/schema.sql /tmp/schema-fmt.sql | wc -l`. Raw output.
|
||||
|
||||
**Я принимаю все решения по findings**, subagent'ы только собирают данные.
|
||||
|
||||
### Phase 2 — Test suites (sequential, ~10 мин)
|
||||
|
||||
В main session:
|
||||
|
||||
1. `composer test` без `--parallel` (квирк 62 — ожидаемые sequential failures из cumulative state). Полный output.
|
||||
2. `composer test -- --parallel --recreate-databases` (per квирк 73 — для long sessions).
|
||||
3. `cd app && npx vitest run --reporter=verbose` (без coverage — Phase 13 отдельно).
|
||||
4. `cd app && npm run story:build` (Histoire full, не watch).
|
||||
5. `cd app && npm run build` (Vite production).
|
||||
|
||||
### Phase 3 — Schema integrity (Boost MCP, ~5 мин)
|
||||
|
||||
Через `mcp__laravel-boost__database-query` к dev `liderra`:
|
||||
|
||||
```sql
|
||||
SELECT count(*) FROM pg_tables WHERE schemaname='public';
|
||||
SELECT count(*) FROM pg_indexes WHERE schemaname='public';
|
||||
SELECT count(*) FROM pg_policies WHERE schemaname='public';
|
||||
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 tgisinternal=false;
|
||||
SELECT count(*) FROM pg_inherits; -- partition relationships
|
||||
```
|
||||
|
||||
Diff с CLAUDE.md §0/§2 dev-actual baseline (75/102/289/39/5/19/0). Orphan FK check через `mcp__laravel-boost__database-schema`.
|
||||
|
||||
### Phase 4 — Security (~10 мин)
|
||||
|
||||
**Methodology gap closure (Pravila v1.12 §4.6):**
|
||||
|
||||
1. **ПЕРВЫМ** `ls .github/workflows/` (enumerate CI infra ДО semgrep verdict) — закрывает audit gap от 12.05.
|
||||
2. `./bin/gitleaks.exe detect --no-banner --redact` (full history).
|
||||
3. `composer audit --locked`.
|
||||
4. Production secrets grep:
|
||||
- `grep -rE "AKIA[0-9A-Z]{16}|SK[a-z0-9]{32}" app/ --include="*.php"`
|
||||
- проверка `.env.example` ↔ `app/config/*.php` references на полноту (нет ли missing env keys).
|
||||
|
||||
### Phase 5 — UI smoke (Playwright MCP, ~30 мин)
|
||||
|
||||
Main session (не subagent — MCP context inheritance не работает).
|
||||
|
||||
- DemoSeeder seed: `cd app && php artisan db:seed --class=DemoSeeder`.
|
||||
- Laravel server: `cd app && php artisan serve` (background).
|
||||
- Vite dev server: `cd app && npm run dev` (background).
|
||||
- 24 views per 12.05 table (auth ×7, main ×8, admin ×8, error ×1).
|
||||
- **CTO-19 verification:** Lucide icons rendering correctly на всех 24 views (custom Vuetify `IconSet` в `app/resources/js/plugins/vuetify.ts`, 103-entry mapping).
|
||||
- Login flow: admin@demo.local / password → POST /api/auth/login → /dashboard.
|
||||
- Logout flow: avatar dropdown → POST /api/auth/logout → /login.
|
||||
- Screenshots → `audit-screens/2026-05-13/01-login.png` … `24-error-404.png`.
|
||||
|
||||
### Phase 6 — Cross-doc integrity (~10 мин)
|
||||
|
||||
Версии 7 нормативных файлов (factual vs memory claims):
|
||||
|
||||
| Документ | Path | Expected (memory) |
|
||||
|---|---|---|
|
||||
| CLAUDE.md | `CLAUDE.md` | v1.91 |
|
||||
| Pravila | `docs/Pravila_raboty_Claude_v1_1.md` | v1.12 |
|
||||
| PSR_v1 | `docs/Plugin_stack_rules_v1.md` | v2.0 |
|
||||
| Tooling | `docs/Tooling_v8_3.md` | v1.16 |
|
||||
| Реестр | `docs/Открытые_вопросы_v8_3.md` | v1.83 |
|
||||
| Схема | `db/schema.sql` | v8.20 (per memory project_state) |
|
||||
| README | `docs/README_АРХИВ_v8_5.md` | v8.5 |
|
||||
|
||||
Плюс:
|
||||
|
||||
- `routes/web.php` explicit `Route::view` list completeness check (12.05 finding — `/reset`, `/projects`, `/admin/*` были missing; fixed `b9038bc`).
|
||||
- Vue Router routes inventory (`resources/js/router/index.ts`) vs views inventory (`resources/js/views/**`).
|
||||
- Memory description ↔ файлы факт (forward-stale check как Q.DEFER.001).
|
||||
|
||||
### Phase 7 — Categorize (~5 мин)
|
||||
|
||||
Taxonomy:
|
||||
|
||||
- **Severity:** P0 (блокирует prod / data corruption / security) → P1 (failing test / type error / a11y) → P2 (warning / style / stale doc) → P3 (cosmetic).
|
||||
- **Fix-eligibility:** FIX-NOW (≤30 мин) → FIX-DEFER (>1 час) → BLOCKED (hard-stop из decision-tree).
|
||||
|
||||
Severity rollup таблица per phase + total. Fix-queue ordered list для Phase 8.
|
||||
|
||||
### Phase 8 — Fix loop (hybrid policy)
|
||||
|
||||
- **Только P0+P1** атомарными коммитами на main.
|
||||
- **P2+P3** → только запись в findings.md (без commits).
|
||||
- Self-review §8 после каждых 3 коммитов: `git diff HEAD~3..HEAD --stat`.
|
||||
- После каждого Edit/Write на code → relevant тесты (Pest/Vitest).
|
||||
- Перед каждым commit → `lefthook run pre-commit --all-files`.
|
||||
- Никаких `--no-verify`, `--amend`, `--no-gpg-sign`.
|
||||
|
||||
### Phase 9 — Final regression verification
|
||||
|
||||
Re-run baseline (per economy 0% — full output, не summary):
|
||||
|
||||
- `composer test -- --parallel --recreate-databases` — ожидаемо ≥742 / ≥739 passed / 0 failed / ≤3 skipped.
|
||||
- `cd app && npx vitest run --reporter=verbose` — ожидаемо ≥88 files / ≥683 passed / 0 failed.
|
||||
- `cd app && npm run build` — exit 0, без warnings.
|
||||
- `cd app && npm run story:build` — ожидаемо ≥35 stories / ≥63 variants.
|
||||
- Если регрессия → systematic-debugging (≥3 гипотезы) → fix или rollback.
|
||||
|
||||
### Phase 10 — Live Pa11y / axe-core (~20 мин)
|
||||
|
||||
**Guest URLs (4) через Pa11y CLI:**
|
||||
|
||||
- `npx pa11y --standard WCAG2AA --timeout 30000 --wait 1500 http://127.0.0.1:8000/login`
|
||||
- `…/register`
|
||||
- `…/forgot`
|
||||
- `…/no-such-path-anywhere` (ErrorView 404)
|
||||
|
||||
**Auth-required views (16) через Playwright MCP + axe-core 4.10 CDN inject:**
|
||||
|
||||
Per Q.DEFER.004 false-alarm lesson + Pravila v1.12 §4.6 UI-refactor visual smoke:
|
||||
|
||||
1. `mcp__playwright__browser_navigate` → URL.
|
||||
2. **`await new Promise((r) => setTimeout(r, 500))`** через `browser_evaluate` (HMR race quirk).
|
||||
3. Hard reload (`browser_navigate` again).
|
||||
4. `browser_evaluate` inject axe-core 4.10 CDN script.
|
||||
5. `browser_evaluate` `axe.run()` + parse violations.
|
||||
|
||||
URLs: /dashboard, /deals, /kanban, /projects, /reports, /billing, /settings, /reminders + 8 admin (/admin/tenants, /admin/tenants/1, /admin/billing, /admin/incidents, /admin/system, /admin/pricing-tiers, /admin/supplier-prices, /admin/impersonation).
|
||||
|
||||
**Закрытие Q.DEFER.002 residual** — auth-required coverage gap.
|
||||
|
||||
### Phase 11 — TODO/FIXME sweep (~5 мин)
|
||||
|
||||
```bash
|
||||
# В Grep tool (НЕ Bash):
|
||||
pattern: '\b(TODO|FIXME|XXX|HACK)\b'
|
||||
path: app/
|
||||
output_mode: content
|
||||
-n: true
|
||||
head_limit: 0 # unlimited per economy 0%
|
||||
```
|
||||
|
||||
Категоризация: MVP-defer ⏸ Б-1 / Feature-defer (Plan 6+) / Production-readiness / Test infra / False-positive.
|
||||
|
||||
### Phase 12 — Bundle analyzer (~10 мин)
|
||||
|
||||
1 subagent: `cd app && BUILD_ANALYZE=1 npm run build:analyze` → парсит `storage/bundle-analyze.html` (rollup-plugin-visualizer). Raw top-15 chunks list. Сравнение с 12.05 baseline (VBtn 184 kB / KanbanView 182 kB / app 131 kB).
|
||||
|
||||
### Phase 13 — Vitest coverage (~5 мин)
|
||||
|
||||
1 subagent: `cd app && npx vitest run --coverage --coverage.reporter=text-summary --coverage.reporter=text` через `@vitest/coverage-v8`. Raw coverage tables. Сравнение с 12.05 baseline (Stmts 75% / Branch 75% / Funcs 67% / Lines 77%) + Q.DEFER.003 post-closure (Stmts 78.67% / Branch 76.21% / Funcs 70.56% / Lines 80.89%).
|
||||
|
||||
### Phase 14 — Pre-production readiness (новое, ~20 мин)
|
||||
|
||||
Main session:
|
||||
|
||||
- **14.1 Sentry integration:** `Grep -E "TODO\(production\)|Sentry::captureException" app/`. Status `ProcessWebhookJob.php:375` (12.05 finding) + any new TODOs.
|
||||
- **14.2 DB roles deployment:** Read `db/00_create_roles.sql` + `db/02_grants.sql`, проверка structure (5 ролей `crm_*` + grants matrix), prod parity expectations.
|
||||
- **14.3 Mock-data prod-gate (Q.PRODUCT.002 revisit):** проверка что решение (B) prod-fallback всё ещё актуально; считаем gzip overhead `mockDeals.ts` + `mockAdmin.ts` в production bundle (Phase 12 cross-link).
|
||||
- **14.4 CI workflows audit:** `ls .github/workflows/` + Read каждого workflow. Coverage: SAST (Semgrep `sast.yml` per Q.INFO.001), tests, build, deploy.
|
||||
- **14.5 Environment validation:** diff `app/.env.example` keys vs `Grep "env\(.*['\"](\w+)['\"]" app/config/`. Missing keys → P1.
|
||||
- **14.6 Queue/cron:** `php artisan schedule:list` + `php artisan queue:work --once --tries=1` smoke + verify `partitions:create-months` schedule entry.
|
||||
- **14.7 Backup/log rotation:** Grep `BACKUP|log-rotation|logrotate` в `docs/`, `app/config/logging.php` channels review.
|
||||
- **14.8 Deployment runbook:** `Glob deploy*.md DEPLOY*.md RUNBOOK*.md` — присутствие/отсутствие documented.
|
||||
|
||||
Финал: push на `origin/main`.
|
||||
|
||||
## 5. Subagent dispatch policy (raw output mandate per economy 0%)
|
||||
|
||||
| Phase | Subagent? | Single-message parallel? |
|
||||
|---|---|---|
|
||||
| 1 (Backend/Frontend/Docs/SQL) | ×4 parallel | YES — single message с 4 `Agent` calls |
|
||||
| 5 (UI smoke) | NO — MCP context inheritance broken | n/a |
|
||||
| 10 (Pa11y) | NO — MCP context | n/a |
|
||||
| 11 (TODO sweep) | NO — direct Grep | n/a |
|
||||
| 12 (Bundle analyzer) | YES — 1 | n/a |
|
||||
| 13 (Vitest coverage) | YES — 1 | n/a |
|
||||
| 14 (Pre-prod) | NO — main session | n/a |
|
||||
|
||||
Prompts всем subagent'ам: «верни **raw** exit codes + полный output stderr+stdout, **не summary**. Решения принимаю я».
|
||||
|
||||
## 6. Verification gates
|
||||
|
||||
**После Edit/Write:**
|
||||
|
||||
| Файл-тип | Тест |
|
||||
|---|---|
|
||||
| PHP code | `composer test -- --filter=<closest>` или full Pest `--parallel` |
|
||||
| Vue/TS frontend | `npx vitest run <closest-spec>` или full Vitest |
|
||||
| schema/migration | Pest RLS + model smoke + `mcp__laravel-boost__database-schema` re-check |
|
||||
| routes/web.php | `php artisan route:list` + Pest feature tests |
|
||||
| CLAUDE.md/Pravila/PSR_v1/Tooling | `claude-md-management:claude-md-improver` skill (не direct Edit) + markdownlint + lychee |
|
||||
|
||||
**Перед commit:** `lefthook run pre-commit --all-files`.
|
||||
|
||||
**Pre-push (один раз в конце):** `lefthook run pre-push` (gitleaks-full-history + lychee strict).
|
||||
|
||||
## 7. Error handling и lessons-applied
|
||||
|
||||
Guardrails из 12.05 audit + post-audit (Pravila v1.12 + memory квирки 74-76):
|
||||
|
||||
- **Pravila v1.12 §4.6 audit methodology gap:** Phase 4 SAST → `ls .github/workflows/` FIRST.
|
||||
- **Pravila v1.12 §4.6 UI-refactor visual smoke:** если фикс задеёт UI → Playwright visual smoke + axe-core re-check (CTO-19 lesson — unit tests jsdom insufficient для Vuetify-internal defaults).
|
||||
- **Q.DEFER.004 axe-core HMR race:** `setTimeout 500ms` + hard reload перед `axe.run()`.
|
||||
- **Квирк 62/73 Pest cumulative state:** для full-suite после long session — `--recreate-databases` flag обязателен.
|
||||
- **Pravila v1.12 §4.7 п.4 plans relative paths:** в audit-plan/spec ссылки на `app/` через `../../../app/...` (lychee semantics; прецедент CTO-19 fixup `f6e1e64`).
|
||||
- **Квирк 74:** `npm install` требует `--legacy-peer-deps` (Histoire 1.0.0-beta.1 peerDep).
|
||||
- **Квирк 75:** Vuetify-internal default mdi-* names — grep также по `node_modules/vuetify/lib/iconsets/mdi*`.
|
||||
|
||||
## 8. Decision-tree hard-stops (per Pravila §13 + PSR_v1 R0.6)
|
||||
|
||||
Эти findings автоматически → BLOCKED, не FIX:
|
||||
|
||||
- Schema.sql semantic changes (не cosmetic).
|
||||
- New packages (composer require / npm install кроме devDependencies update — даже это требует согласования).
|
||||
- ТЗ-правки (`docs/CRM_bp-gr_Инструкция_v8_5.md`).
|
||||
- Реестр-вопросы closing (`Б-/CTO-/DO-/Ю-/Диз-/OPEN-`) без явного «закрываем».
|
||||
- Force-push на main / `--no-verify` / hook bypass / `--no-gpg-sign`.
|
||||
- Production DB connection.
|
||||
- ПДн / токены / API-ключи в commits (gitleaks gate).
|
||||
|
||||
## 9. Testing/verification план
|
||||
|
||||
**Baseline (фиксируем в Phase 2 как точку отсчёта):**
|
||||
|
||||
| Метрика | Expected (post-merge `21262ef`) |
|
||||
|---|---|
|
||||
| Pest `--parallel --recreate-databases` | 742 / 739 passed / 0 failed / 3 skipped |
|
||||
| Pest sequential | 742 / 736 passed / 3 failed (квирк 62) / 3 skipped |
|
||||
| Vitest | 88 files / 683 passed / 3 skipped |
|
||||
| Vite build | ~3.5s, 0 warnings |
|
||||
| Histoire build | 35 stories / 63 variants |
|
||||
| ESLint | 0 errors |
|
||||
| vue-tsc | 0 errors |
|
||||
| Prettier --check | 0 issues |
|
||||
| markdownlint | 1 (untracked design.md из прошлой сессии) |
|
||||
| cspell | ≤18 (mixed-script artifacts) |
|
||||
| lychee | 0 broken |
|
||||
| gitleaks (full history) | 0 leaks |
|
||||
| RLS policies | 39 |
|
||||
|
||||
**Regression gate (Phase 9):** все метрики ≥ baseline. Регрессия → rollback или fix перед push.
|
||||
|
||||
## 10. Out of scope
|
||||
|
||||
Явно НЕ делаем в этой сессии:
|
||||
|
||||
- pgFormatter swap schema.sql (Q.HARD.002 — закрыт «не трогать»).
|
||||
- Q.DEFER.003 sub-A api/* — уже closed `95f5f94`.
|
||||
- Pest квирк 62 corrective hygiene (test-DB DROP+CREATE+ICU+migrate) — отдельная задача.
|
||||
- CSS code-splitting KanbanView vuedraggable / NewDealDialog / DealDetailDrawer — Phase 12 P2 defer.
|
||||
- Sentry actual integration (только аудит TODO statuses, не fix).
|
||||
- Б-1 saas-admin SSO middleware (BLOCKED).
|
||||
|
||||
## 11. Success criteria
|
||||
|
||||
- 14 phases completed.
|
||||
- All P0 + P1 findings либо fixed (atomic commit) либо BLOCKED (явно в blocked.md с reason).
|
||||
- Phase 9 regression gate passed: 0 регрессий vs baseline.
|
||||
- Pre-push lefthook clean (gitleaks-full-history + lychee).
|
||||
- 4 audit-docs committed.
|
||||
- Memory updates если найдены новые квирки.
|
||||
- Push на `origin/main` через `Bash(git push origin main:*)`.
|
||||
- Verdict 🟢 / 🟡 / 🔴 в report.md с обоснованием.
|
||||
|
||||
## 12. Известные ограничения этой сессии
|
||||
|
||||
- **Не верифицировал** до старта: production environment parity (Phase 14.4-14.7) — будет в Phase 14.
|
||||
- **Не верифицировал** до старта: actual coverage delta после Q.DEFER.003 closure beyond memory claim — будет в Phase 13.
|
||||
- **Зависит от MCP availability:** Playwright + Boost MCP должны быть запущены (default).
|
||||
- **Зависит от dev servers:** Laravel + Vite background processes для Phase 5/10.
|
||||
|
||||
---
|
||||
|
||||
*Конец design'а. После approval — invoke writing-plans skill для конкретного implementation plan.*
|
||||
Reference in New Issue
Block a user