Progressive Quality Program
Scheduling status (2026-08-21): the first bounded P4 tranche remains valid, but further cleanup is deferred until a new bounded-context scope is designed and explicitly approved. This document is not authorization for opportunistic cross-context cleanup.
This document records bounded cleanup tranches. The recorded baseline and the
first tranche were measured on the 0.26.0 line; the program continues across
later lines and each new tranche re-records its own evidence. It is a delta
program, not authorization for repository-wide rewrites.
Each tranche starts with behavior tests and current evidence, owns an explicit
scope, and must pass its gates before another context is selected.
Bounded Context Map (Waves 1–2)
| Context / owner | Public surface | Allowed dependencies | Forbidden direction |
|---|---|---|---|
Core rendering (src/Rendering/TemplateData, ViewModel, ThemeEngine) |
immutable template payload/value interfaces, composer, legacy adapter, root schema | PSR-7, Symfony serializer/translation, Plates, core session/profile DTOs | optional module classes in template-data contracts; page/module ownership overriding core roots |
Core secret management (Application/Security/Secret, Infrastructure/Security/Secret) |
secret context/store/keyring contracts and bounded maintenance services | OpenSSL, DBAL adapters, tenant context | optional modules; JWT-derived keys for new envelopes; presentation/log disclosure |
Container bootstrap (ContainerFactory, Container/Definition) |
grouped definition providers and tenant runtime entries | PHP-DI, core ModuleRegistry extension contracts |
module rebinding a core key; compiled tenant/module objects |
Esapi / EasyStore (modules/Esapi, legacy Infrastructure/Esapi) |
captured vendor contract, client/factory/import boundaries | shared bounded PSR-18 transport, import ownership contracts | unverified vendor fields/windows; private-network endpoints; duplicated transport policy |
Admin settings presentation (AdminSettingsController, Application/System) |
declared settings overview payload and small status providers | typed application read interfaces; core settings services | repositories or module-specific domain objects in page payloads |
tests/Unit/Architecture/ArchitectureBoundaryTest.php currently enforces the
module-neutral rendering/secret boundaries, request-time DDL prohibition, and
process-local PHPUnit database rule. DI key ownership is enforced separately by
DefinitionGroupCollisionTest. Existing legacy core-to-module dependencies
outside these high-integrity boundaries remain measured debt; this document
does not describe them as clean.
Reproducible Baseline — 2026-08-20
Commands:
composer qa:phpstan
composer qa:metrics
- Full PHPStan:
493pre-existing file errors across the repository; zero general errors. This is a debt baseline, not an accepted quality target. The rendering contract and each modified tranche are analysed separately with a zero-error gate. - PHPMetrics before tranche 1: 958 classes, 159 interfaces, average class CCN
13.96, average efferent coupling3.88, 0 critical / 288 error / 297 warning / 52 informational violations. AdminSettingsControllerbefore tranche 1: CCN36, weighted method count66, maximum method CCN15, maintainability57.41, efferent coupling20, LOC301.
Generated evidence is under reports/phpstan.json, reports/metrics.json, and
reports/metrics/. Rector output remains advisory and was not applied in this
tranche.
The advisory Rector inventory was refreshed on 2026-08-31 against the current
0.26.5 tree by running php bin/qa/run-rector-report.php directly. It
completed in about 279 seconds with zero errors and identified 872 suggested
rule applications across 463 src files (65 distinct rules). The ignored raw
report remains at reports/rector.json; no transform was applied. These counts
are inventory evidence, not authorization for a broad cleanup tranche.
Tranche 1 — Admin Menu Status Extraction
Risk selected: AdminSettingsController combined high coupling and branching
with many unrelated settings collaborators. Its menu summary mixed traversal
and counting behavior into the HTTP adapter even though the dashboard consumes
one stable read payload.
Behavior was characterized first in AdminMenuStatusProviderTest: system
channel/item/visibility counts, custom menu/activity/placement counts, hook
count, and malformed optional nested lists. The coherent refactor introduced
two narrow read interfaces implemented by the existing menu services and moved
the summary to AdminMenuStatusProvider; the controller now depends on that one
application provider.
Gates And Result
| Gate | Before | After | Result |
|---|---|---|---|
| Targeted PHPStan findings | 0 | 0 | pass |
| Controller CCN | 36 | 22 | pass, -38.9% |
| Controller maximum method CCN | 15 | 9 | pass, -40% |
| Controller efferent coupling | 20 | 19 | pass |
| Controller LOC | 301 | 258 | pass |
| Extracted provider maximum method CCN | n/a | 9 | pass (gate <= 10) |
| Full average class CCN | 13.96 | 13.94 | pass |
| PHPMetrics critical/error/warning | 0 / 288 / 297 | 0 / 288 / 297 | pass |
| Characterization + DI + settings HTTP | n/a | 8 tests / 60 assertions | pass |
The extracted class adds the expected type/constructor overhead (provider CCN 15, WMC 18) but does not create a new method hotspot: its maximum method CCN is 9, and the formerly multi-purpose controller is materially smaller and less coupled. No request-performance gate was needed because the same two service reads occur once and the extraction adds no I/O.
Program Review
Review thresholds after three completed tranches:
- targeted PHPStan remains at zero and the full baseline does not gain errors;
- no new PHPMetrics critical/error/warning violations;
- selected hotspot maximum method CCN or coupling falls materially without merely moving a larger hotspot elsewhere;
- focused characterization and isolated broad integration checks pass;
- no broad Rector transform or unrelated formatting/rename churn is included.
Tranche 1 is complete. The three-tranche review is intentionally still open.