Verified against Semitexa Ultimate 2026.09.30.1034

Unused Classes and Dependency Loops

bin/semitexa ai:review-graph:findings
bin/semitexa ai:review-graph:findings --kind=unused --min-confidence=high
bin/semitexa ai:review-graph:findings --kind=cycles --module=Orm --format=markdown

Answered from the project graph in well under a second. Every finding has a stable id (its kind and a hash of its classes), so two runs can be compared line by line, and every format carries the coverage summary.

Unused classes

A class counts as used when a declared class (or a configuration file) outside tests/ depends on it — a code reference (extends, implements, new, a type, a static call, a constant, instanceof, catch, an attribute) or wiring (injection, handles, listens_to, ...). What is left is graded:

Confidence Meaning
high Nothing refers to it, the framework does not discover it, and no runtime class name in its module could reach it.
medium Nothing refers to it, but the framework discovers it — its role (command, handler, listener, service, ...), wiring it declares, or a Semitexa attribute on the class (#[AsAiSkill], #[AsMapper], #[Capability]) — or only tests use it.
low It is named only as Foo::class, or its module builds class names at runtime (new $class), so it may be reached in a way the graph cannot see.

Test code is never a candidate; #[GraphIgnore] classes are skipped. The evidence line says which rule applied.

A class named in a configuration file — *.neon, *.yaml, composer.json, phpunit.xml — counts as used too: a PHPStan rule registered in phpstan.neon is not a finding. Only exact fully-qualified names are read.

Read before deleting. A high finding is a class this workspace does not use. A package may still offer it to its consumers — a test double documented in the README, say — and that is a decision for a person, not for the report.

Dependency loops

Classes that depend on each other in a loop, one row per loop: its members and one shortest cycle through them — the concrete path to read and break. Only real dependencies count (code references and injection); a use line alone, an attribute, and inferred edges do not.

15 classes: ContainerFactory -> OrmManager -> StaticLoggerBridge -> ContainerFactory
2 classes: CacheManager -> ScopedCacheManager -> CacheManager

Options

Option Description
--kind=unused|cycles|all What to report (default all)
--min-confidence=high|medium|low Unused classes at or above this grade (default medium)
--module=NAME Unused classes of one module, and loops that touch it
--format=text|json|ndjson|markdown ndjson starts with a summary line
--no-refresh Answer from the graph as it is, without the incremental refresh
Have a product idea?One free MVP every month