From 3756ea801b076f3ddf4f0886f7269cf831c1256d Mon Sep 17 00:00:00 2001 From: Dmitry Prikotov Date: Thu, 10 Sep 2026 10:50:59 +0700 Subject: [PATCH 1/3] refactor(deptrac): support version 4 contracts --- composer.json | 2 +- src/Deptrac/CrossModuleDomainRule.php | 8 +- src/Deptrac/MetricsJsonOutputFormatter.php | 20 ++--- src/Deptrac/ReservedLayerSegmentRule.php | 8 +- src/Deptrac/ServiceContractDependencyRule.php | 8 +- tests/Deptrac/CrossModuleDomainRuleTest.php | 42 +++++---- .../MetricsJsonOutputFormatterTest.php | 24 ++--- .../Deptrac/ReservedLayerSegmentRuleTest.php | 12 +-- .../ServiceContractDependencyRuleTest.php | 42 +++++---- todo/TASK-support-deptrac-4.todo.md | 88 +++++++++++++++++++ 10 files changed, 181 insertions(+), 73 deletions(-) create mode 100644 todo/TASK-support-deptrac-4.todo.md diff --git a/composer.json b/composer.json index a106ca83..0f1bc298 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ ], "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.2", - "deptrac/deptrac": "^2.0", + "deptrac/deptrac": "^4.7", "php-code-archeology/php-code-archeology": "^2.11", "phpstan/phpstan": "^2.1", "phpunit/phpunit": "^10.5", diff --git a/src/Deptrac/CrossModuleDomainRule.php b/src/Deptrac/CrossModuleDomainRule.php index fe54c8b2..baa8300a 100644 --- a/src/Deptrac/CrossModuleDomainRule.php +++ b/src/Deptrac/CrossModuleDomainRule.php @@ -4,10 +4,10 @@ namespace PrikotovCodingStandard\Deptrac; -use Qossmic\Deptrac\Contract\Analyser\EventHelper; -use Qossmic\Deptrac\Contract\Analyser\ProcessEvent; -use Qossmic\Deptrac\Contract\Analyser\ViolationCreatingInterface; -use Qossmic\Deptrac\Contract\Ast\DependencyType; +use Deptrac\Deptrac\Contract\Analyser\EventHelper; +use Deptrac\Deptrac\Contract\Analyser\ProcessEvent; +use Deptrac\Deptrac\Contract\Analyser\ViolationCreatingInterface; +use Deptrac\Deptrac\Contract\Ast\AstMap\DependencyType; /** * Custom Deptrac rule that forbids cross-module access entirely, diff --git a/src/Deptrac/MetricsJsonOutputFormatter.php b/src/Deptrac/MetricsJsonOutputFormatter.php index 20ab2a5d..903e9cae 100644 --- a/src/Deptrac/MetricsJsonOutputFormatter.php +++ b/src/Deptrac/MetricsJsonOutputFormatter.php @@ -4,16 +4,16 @@ namespace PrikotovCodingStandard\Deptrac; -use Qossmic\Deptrac\Contract\OutputFormatter\OutputFormatterInput; -use Qossmic\Deptrac\Contract\OutputFormatter\OutputFormatterInterface; -use Qossmic\Deptrac\Contract\OutputFormatter\OutputInterface; -use Qossmic\Deptrac\Contract\Result\Allowed; -use Qossmic\Deptrac\Contract\Result\CoveredRuleInterface; -use Qossmic\Deptrac\Contract\Result\OutputResult; -use Qossmic\Deptrac\Contract\Result\RuleInterface; -use Qossmic\Deptrac\Contract\Result\SkippedViolation; -use Qossmic\Deptrac\Contract\Result\Uncovered; -use Qossmic\Deptrac\Contract\Result\Violation; +use Deptrac\Deptrac\Contract\OutputFormatter\OutputFormatterInput; +use Deptrac\Deptrac\Contract\OutputFormatter\OutputFormatterInterface; +use Deptrac\Deptrac\Contract\OutputFormatter\OutputInterface; +use Deptrac\Deptrac\Contract\Result\Allowed; +use Deptrac\Deptrac\Contract\Result\CoveredRuleInterface; +use Deptrac\Deptrac\Contract\Result\OutputResult; +use Deptrac\Deptrac\Contract\Result\RuleInterface; +use Deptrac\Deptrac\Contract\Result\SkippedViolation; +use Deptrac\Deptrac\Contract\Result\Uncovered; +use Deptrac\Deptrac\Contract\Result\Violation; use RuntimeException; /** diff --git a/src/Deptrac/ReservedLayerSegmentRule.php b/src/Deptrac/ReservedLayerSegmentRule.php index 97be9871..64709254 100644 --- a/src/Deptrac/ReservedLayerSegmentRule.php +++ b/src/Deptrac/ReservedLayerSegmentRule.php @@ -4,10 +4,10 @@ namespace PrikotovCodingStandard\Deptrac; -use Qossmic\Deptrac\Contract\Analyser\PostProcessEvent; -use Qossmic\Deptrac\Contract\Analyser\ViolationCreatingInterface; -use Qossmic\Deptrac\Contract\Result\Error; -use Qossmic\Deptrac\Core\Ast\AstMapExtractor; +use Deptrac\Deptrac\Contract\Analyser\PostProcessEvent; +use Deptrac\Deptrac\Contract\Analyser\ViolationCreatingInterface; +use Deptrac\Deptrac\Contract\Result\Error; +use Deptrac\Deptrac\Core\Ast\AstMapExtractor; /** * Custom Deptrac rule that forbids reserved layer names as nested namespace segments. diff --git a/src/Deptrac/ServiceContractDependencyRule.php b/src/Deptrac/ServiceContractDependencyRule.php index 2932b659..4adca6da 100644 --- a/src/Deptrac/ServiceContractDependencyRule.php +++ b/src/Deptrac/ServiceContractDependencyRule.php @@ -4,10 +4,10 @@ namespace PrikotovCodingStandard\Deptrac; -use Qossmic\Deptrac\Contract\Analyser\EventHelper; -use Qossmic\Deptrac\Contract\Analyser\ProcessEvent; -use Qossmic\Deptrac\Contract\Analyser\ViolationCreatingInterface; -use Qossmic\Deptrac\Contract\Ast\DependencyType; +use Deptrac\Deptrac\Contract\Analyser\EventHelper; +use Deptrac\Deptrac\Contract\Analyser\ProcessEvent; +use Deptrac\Deptrac\Contract\Analyser\ViolationCreatingInterface; +use Deptrac\Deptrac\Contract\Ast\AstMap\DependencyType; /** * Custom Deptrac rule that enforces service contract boundaries. diff --git a/tests/Deptrac/CrossModuleDomainRuleTest.php b/tests/Deptrac/CrossModuleDomainRuleTest.php index 9d654b3e..0d635382 100644 --- a/tests/Deptrac/CrossModuleDomainRuleTest.php +++ b/tests/Deptrac/CrossModuleDomainRuleTest.php @@ -6,19 +6,20 @@ use PHPUnit\Framework\TestCase; use PrikotovCodingStandard\Deptrac\CrossModuleDomainRule; -use Qossmic\Deptrac\Contract\Analyser\AnalysisResult; -use Qossmic\Deptrac\Contract\Analyser\EventHelper; -use Qossmic\Deptrac\Contract\Analyser\ProcessEvent; -use Qossmic\Deptrac\Contract\Ast\DependencyContext; -use Qossmic\Deptrac\Contract\Ast\DependencyType; -use Qossmic\Deptrac\Contract\Ast\FileOccurrence; -use Qossmic\Deptrac\Contract\Layer\LayerProvider; -use Qossmic\Deptrac\Contract\Result\RuleInterface; -use Qossmic\Deptrac\Contract\Result\SkippedViolation; -use Qossmic\Deptrac\Contract\Result\Violation; -use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeReference; -use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeToken; -use Qossmic\Deptrac\Core\Dependency\Dependency; +use Deptrac\Deptrac\Contract\Analyser\AnalysisResult; +use Deptrac\Deptrac\Contract\Analyser\EventHelper; +use Deptrac\Deptrac\Contract\Analyser\ProcessEvent; +use Deptrac\Deptrac\Contract\Ast\AstMap\DependencyContext; +use Deptrac\Deptrac\Contract\Ast\AstMap\DependencyType; +use Deptrac\Deptrac\Contract\Ast\AstMap\FileOccurrence; +use Deptrac\Deptrac\Core\Layer\LayerProvider; +use Deptrac\Deptrac\Contract\OutputFormatter\BaselineMapperInterface; +use Deptrac\Deptrac\Contract\Result\RuleInterface; +use Deptrac\Deptrac\Contract\Result\SkippedViolation; +use Deptrac\Deptrac\Contract\Result\Violation; +use Deptrac\Deptrac\Contract\Ast\AstMap\ClassLikeReference; +use Deptrac\Deptrac\Contract\Ast\AstMap\ClassLikeToken; +use Deptrac\Deptrac\DefaultBehavior\Dependency\Helpers\Dependency; /** * @see CrossModuleDomainRule @@ -536,11 +537,11 @@ public function testCrossModuleDependencyHonorsSkipViolations(): void 'App\Common\Module\User\Domain\Service\Account\FindAccountServiceInterface', DependencyType::PARAMETER, ); - $rule = new CrossModuleDomainRule(new EventHelper([ + $rule = new CrossModuleDomainRule($this->createEventHelper([ 'App\Common\Module\Billing\Domain\Service\Invoice\CreateInvoiceService' => [ 'App\Common\Module\User\Domain\Service\Account\FindAccountServiceInterface', ], - ], new LayerProvider([]))); + ])); $rule->onProcessEvent($event); @@ -551,7 +552,16 @@ public function testCrossModuleDependencyHonorsSkipViolations(): void /** @param array> $skippedViolations */ private function createRule(array $skippedViolations = []): CrossModuleDomainRule { - return new CrossModuleDomainRule(new EventHelper($skippedViolations, new LayerProvider([]))); + return new CrossModuleDomainRule($this->createEventHelper($skippedViolations)); + } + + /** @param array> $skippedViolations */ + private function createEventHelper(array $skippedViolations): EventHelper + { + $baselineMapper = $this->createStub(BaselineMapperInterface::class); + $baselineMapper->method('loadViolations')->willReturn($skippedViolations); + + return new EventHelper(new LayerProvider([]), $baselineMapper); } private function createProcessEvent( diff --git a/tests/Deptrac/MetricsJsonOutputFormatterTest.php b/tests/Deptrac/MetricsJsonOutputFormatterTest.php index bfa993e7..16ddfff7 100644 --- a/tests/Deptrac/MetricsJsonOutputFormatterTest.php +++ b/tests/Deptrac/MetricsJsonOutputFormatterTest.php @@ -6,18 +6,18 @@ use PHPUnit\Framework\TestCase; use PrikotovCodingStandard\Deptrac\MetricsJsonOutputFormatter; -use Qossmic\Deptrac\Contract\Analyser\AnalysisResult; -use Qossmic\Deptrac\Contract\Ast\DependencyContext; -use Qossmic\Deptrac\Contract\Ast\DependencyType; -use Qossmic\Deptrac\Contract\Ast\FileOccurrence; -use Qossmic\Deptrac\Contract\OutputFormatter\OutputFormatterInput; -use Qossmic\Deptrac\Contract\OutputFormatter\OutputFormatterInterface; -use Qossmic\Deptrac\Contract\OutputFormatter\OutputInterface; -use Qossmic\Deptrac\Contract\OutputFormatter\OutputStyleInterface; -use Qossmic\Deptrac\Contract\Result\Allowed; -use Qossmic\Deptrac\Contract\Result\OutputResult; -use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeToken; -use Qossmic\Deptrac\Core\Dependency\Dependency; +use Deptrac\Deptrac\Contract\Analyser\AnalysisResult; +use Deptrac\Deptrac\Contract\Ast\AstMap\DependencyContext; +use Deptrac\Deptrac\Contract\Ast\AstMap\DependencyType; +use Deptrac\Deptrac\Contract\Ast\AstMap\FileOccurrence; +use Deptrac\Deptrac\Contract\OutputFormatter\OutputFormatterInput; +use Deptrac\Deptrac\Contract\OutputFormatter\OutputFormatterInterface; +use Deptrac\Deptrac\Contract\OutputFormatter\OutputInterface; +use Deptrac\Deptrac\Contract\OutputFormatter\OutputStyleInterface; +use Deptrac\Deptrac\Contract\Result\Allowed; +use Deptrac\Deptrac\Contract\Result\OutputResult; +use Deptrac\Deptrac\Contract\Ast\AstMap\ClassLikeToken; +use Deptrac\Deptrac\DefaultBehavior\Dependency\Helpers\Dependency; use RuntimeException; final class MetricsJsonOutputFormatterTest extends TestCase diff --git a/tests/Deptrac/ReservedLayerSegmentRuleTest.php b/tests/Deptrac/ReservedLayerSegmentRuleTest.php index aa099811..6d606517 100644 --- a/tests/Deptrac/ReservedLayerSegmentRuleTest.php +++ b/tests/Deptrac/ReservedLayerSegmentRuleTest.php @@ -6,12 +6,12 @@ use PHPUnit\Framework\TestCase; use PrikotovCodingStandard\Deptrac\ReservedLayerSegmentRule; -use Qossmic\Deptrac\Contract\Analyser\AnalysisResult; -use Qossmic\Deptrac\Contract\Analyser\PostProcessEvent; -use Qossmic\Deptrac\Core\Ast\AstMap\AstMap; -use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeReference; -use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeToken; -use Qossmic\Deptrac\Core\Ast\AstMapExtractor; +use Deptrac\Deptrac\Contract\Analyser\AnalysisResult; +use Deptrac\Deptrac\Contract\Analyser\PostProcessEvent; +use Deptrac\Deptrac\Core\Ast\AstMap; +use Deptrac\Deptrac\Contract\Ast\AstMap\ClassLikeReference; +use Deptrac\Deptrac\Contract\Ast\AstMap\ClassLikeToken; +use Deptrac\Deptrac\Core\Ast\AstMapExtractor; /** * @see ReservedLayerSegmentRule diff --git a/tests/Deptrac/ServiceContractDependencyRuleTest.php b/tests/Deptrac/ServiceContractDependencyRuleTest.php index e0e81dbf..99b06861 100644 --- a/tests/Deptrac/ServiceContractDependencyRuleTest.php +++ b/tests/Deptrac/ServiceContractDependencyRuleTest.php @@ -6,19 +6,20 @@ use PHPUnit\Framework\TestCase; use PrikotovCodingStandard\Deptrac\ServiceContractDependencyRule; -use Qossmic\Deptrac\Contract\Analyser\AnalysisResult; -use Qossmic\Deptrac\Contract\Analyser\EventHelper; -use Qossmic\Deptrac\Contract\Analyser\ProcessEvent; -use Qossmic\Deptrac\Contract\Ast\DependencyContext; -use Qossmic\Deptrac\Contract\Ast\DependencyType; -use Qossmic\Deptrac\Contract\Ast\FileOccurrence; -use Qossmic\Deptrac\Contract\Layer\LayerProvider; -use Qossmic\Deptrac\Contract\Result\RuleInterface; -use Qossmic\Deptrac\Contract\Result\SkippedViolation; -use Qossmic\Deptrac\Contract\Result\Violation; -use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeReference; -use Qossmic\Deptrac\Core\Ast\AstMap\ClassLike\ClassLikeToken; -use Qossmic\Deptrac\Core\Dependency\Dependency; +use Deptrac\Deptrac\Contract\Analyser\AnalysisResult; +use Deptrac\Deptrac\Contract\Analyser\EventHelper; +use Deptrac\Deptrac\Contract\Analyser\ProcessEvent; +use Deptrac\Deptrac\Contract\Ast\AstMap\DependencyContext; +use Deptrac\Deptrac\Contract\Ast\AstMap\DependencyType; +use Deptrac\Deptrac\Contract\Ast\AstMap\FileOccurrence; +use Deptrac\Deptrac\Core\Layer\LayerProvider; +use Deptrac\Deptrac\Contract\OutputFormatter\BaselineMapperInterface; +use Deptrac\Deptrac\Contract\Result\RuleInterface; +use Deptrac\Deptrac\Contract\Result\SkippedViolation; +use Deptrac\Deptrac\Contract\Result\Violation; +use Deptrac\Deptrac\Contract\Ast\AstMap\ClassLikeReference; +use Deptrac\Deptrac\Contract\Ast\AstMap\ClassLikeToken; +use Deptrac\Deptrac\DefaultBehavior\Dependency\Helpers\Dependency; /** * @see ServiceContractDependencyRule @@ -618,11 +619,11 @@ public function testServiceContractDependencyHonorsSkipViolations(): void 'App\Common\Module\User\Domain\Service\Account\FindAccountServiceInterface', DependencyType::PARAMETER, ); - $rule = new ServiceContractDependencyRule(new EventHelper([ + $rule = new ServiceContractDependencyRule($this->createEventHelper([ 'App\Common\Module\Billing\Integration\Service\User\FindUserService' => [ 'App\Common\Module\User\Domain\Service\Account\FindAccountServiceInterface', ], - ], new LayerProvider([]))); + ])); $rule->onProcessEvent($event); @@ -633,7 +634,16 @@ public function testServiceContractDependencyHonorsSkipViolations(): void /** @param array> $skippedViolations */ private function createRule(array $skippedViolations = []): ServiceContractDependencyRule { - return new ServiceContractDependencyRule(new EventHelper($skippedViolations, new LayerProvider([]))); + return new ServiceContractDependencyRule($this->createEventHelper($skippedViolations)); + } + + /** @param array> $skippedViolations */ + private function createEventHelper(array $skippedViolations): EventHelper + { + $baselineMapper = $this->createStub(BaselineMapperInterface::class); + $baselineMapper->method('loadViolations')->willReturn($skippedViolations); + + return new EventHelper(new LayerProvider([]), $baselineMapper); } private function createProcessEvent( diff --git a/todo/TASK-support-deptrac-4.todo.md b/todo/TASK-support-deptrac-4.todo.md new file mode 100644 index 00000000..32bed29c --- /dev/null +++ b/todo/TASK-support-deptrac-4.todo.md @@ -0,0 +1,88 @@ +--- +type: refactor +created: 2026-09-10 03:49:39 (1789012179) +due: +started: 2026-09-10 03:49:39 (1789012179) +completed: +cancelled: +value: V2 +complexity: C2 +priority: P2 +cost_plan: +cost_fact: +depends_on: +epic: +author: Бэкендер Левша (pi) +assignee: Бэкендер Левша (pi) +branch: task/support-deptrac-4 +pr: +status: in_progress +--- + +# TASK-support-deptrac-4: Поддержать Deptrac 4 + +## 0. Простое описание (Human Brief) + +### Проблема простыми словами (Problem) +- Кастомные правила и форматтер метрик используют пространства имён и контракты Deptrac 2, поэтому не загружаются с Deptrac 4. +- Это блокирует обновление Deptrac в проектах-потребителях, включая `task-orchestrator`. + +### Варианты или путь решения (Solution Sketch) +- Перейти на пространства имён и контракты Deptrac 4. +- Адаптировать тестовые зависимости `EventHelper` к новому конструктору через `BaselineMapperInterface`. + +### Ожидаемый результат (Expected Result) +- Все расширения пакета загружаются и сохраняют прежнее поведение с Deptrac 4.7. + +## 1. Концепция и Цель (Concept and Goal) + +### История (User Story) +> Как сопровождающий проекта-потребителя, я хочу использовать актуальный Deptrac 4 вместе с `prikotov/coding-standard`, чтобы получать исправления анализатора без потери проектных архитектурных правил. + +### Цель по SMART (Goal) +- Обеспечить совместимость всех четырёх интеграций Deptrac с версией 4.7 и подтвердить её полным `composer check`. + +## 2. Контекст и Границы (Context and Scope) +- **Где делаем:** `src/Deptrac/`, соответствующие тесты и ограничение `deptrac/deptrac` в `composer.json`. +- **Вне границ:** изменение семантики архитектурных правил, миграция PHPUnit, поддержка Deptrac 2 и 3. + +## 3. Требования, MoSCoW (Requirements) +### 🔴 Обязательно (Must Have) +- [x] Пакет разработки требует `deptrac/deptrac ^4.7`. +- [x] Правила и форматтер используют контракты Deptrac 4. +- [x] Тесты учитывают новый контракт `EventHelper`. +- [x] Полный `composer check` проходит успешно. +### ⚫ Won't Have (Не будем делать) +- Одновременная поддержка несовместимых внутренних контрактов нескольких основных версий Deptrac. + +## 4. План реализации (Implementation Plan) +1. [x] Обновить ограничение Deptrac до `^4.7`. +2. [x] Перенести импорты на пространства имён Deptrac 4. +3. [x] Адаптировать тестовые объекты и проверку `skip_violations`. +4. [x] Выполнить `composer check`. + +## 5. Критерии приёмки (Definition of Done) +- [x] `composer check` завершается без ошибок. +- [x] Все 287 тестов расширений и правил проходят. +- [x] Пакет можно установить совместно с Deptrac 4.7. + +## 6. Самопроверка (Verification) +```bash +composer validate --strict +composer check +``` + +## 7. Риски и зависимости (Risks and Dependencies) +- Изменение несовместимо с Deptrac 2, поэтому требует повышения minor-версии пакета в линии `0.x`. +- `EventHelper` остаётся внутренним контрактом Deptrac и может потребовать новой адаптации при следующем основном обновлении. + +## 8. Источники (Sources) +- Исходный код контрактов установленного `deptrac/deptrac 4.7.1`. + +## 9. Комментарии (Comments) +- Изменение подготовлено как предварительное условие полного обновления зависимостей `task-orchestrator`. + +## История изменений (Change History) +| Дата | Автор (роль) | Изменение | +| :--- | :--- | :--- | +| 2026-09-10 03:49:39 (1789012179) | Бэкендер Левша (pi) | Создание задачи | From c093fcc11be2fc21a2ad305eff8c90bc586d8cfa Mon Sep 17 00:00:00 2001 From: Dmitry Prikotov Date: Thu, 10 Sep 2026 10:52:45 +0700 Subject: [PATCH 2/3] chore(todo): move Deptrac 4 support to review --- todo/TASK-support-deptrac-4.todo.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/todo/TASK-support-deptrac-4.todo.md b/todo/TASK-support-deptrac-4.todo.md index 32bed29c..d3ecd950 100644 --- a/todo/TASK-support-deptrac-4.todo.md +++ b/todo/TASK-support-deptrac-4.todo.md @@ -15,8 +15,8 @@ epic: author: Бэкендер Левша (pi) assignee: Бэкендер Левша (pi) branch: task/support-deptrac-4 -pr: -status: in_progress +pr: https://github.com/prikotov/coding-standard/pull/125 +status: review --- # TASK-support-deptrac-4: Поддержать Deptrac 4 From 5b1cd1ab2966d00c1539138cdaf841428bd09331 Mon Sep 17 00:00:00 2001 From: Dmitry Prikotov Date: Thu, 10 Sep 2026 10:54:01 +0700 Subject: [PATCH 3/3] chore(todo): complete Deptrac 4 support task --- todo/{ => done}/TASK-support-deptrac-4.todo.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename todo/{ => done}/TASK-support-deptrac-4.todo.md (98%) diff --git a/todo/TASK-support-deptrac-4.todo.md b/todo/done/TASK-support-deptrac-4.todo.md similarity index 98% rename from todo/TASK-support-deptrac-4.todo.md rename to todo/done/TASK-support-deptrac-4.todo.md index d3ecd950..107671a7 100644 --- a/todo/TASK-support-deptrac-4.todo.md +++ b/todo/done/TASK-support-deptrac-4.todo.md @@ -3,7 +3,7 @@ type: refactor created: 2026-09-10 03:49:39 (1789012179) due: started: 2026-09-10 03:49:39 (1789012179) -completed: +completed: 2026-09-10 03:54:01 (1789012441) cancelled: value: V2 complexity: C2 @@ -16,7 +16,7 @@ author: Бэкендер Левша (pi) assignee: Бэкендер Левша (pi) branch: task/support-deptrac-4 pr: https://github.com/prikotov/coding-standard/pull/125 -status: review +status: done --- # TASK-support-deptrac-4: Поддержать Deptrac 4