Duplicated logic the previous audits could not see: 23 divergent copies of one test helper, and the storage-schema scaffolding written eight times
164 files, 1030 added against 2186 removed. The whole kernel suite, 183 classes, passes at every commit.
What the detector found that the earlier passes could not
#3618840 was the duplication audit and it did its job on production code. It excluded tests as "mostly setUp boilerplate" and grouped clone windows only across different files, so within-file repetition and the whole test suite were outside its reach. Both exclusions sounded reasonable; both were wrong. 57 of the 89 remaining groups were test-only.
The tests had not merely duplicated, they had diverged
getParkedNodes(), the question nearly every engine test asks, existed in 23 classes as six different implementations. Three filtered in SQL, two reset the entity storage cache and filtered in PHP, and one collapsed two tokens parked on the same node into a single entry without sorting. Two classes asking the same question could be reading different state. The same shape repeated for getTokensByState (4 copies, 2 behaviours), getParkedTokenId (10 in 3), getTokensByNode (6 in 3), getWorkItem (5 in 3) and getParkedTokensAtNode (4).
ParkedTokenTrait now holds one implementation of each, filtering in the query so the answer never depends on the static cache, and named for what each returns: the three helpers called "Tokens...AtNode" all had callers wanting the one token, so they are singular now, and the two that asserted "exactly one" keep that assertion in getSoleParkedTokenId() and getSoleWorkItem(), because that assertion is why a caller reaches for "the" token.
Where a difference was real, it was kept
Four classes carried their own drainQueue() beside DrainEngineQueueTrait, and the difference was not cosmetic: the trait lets a failing advance escape, which is what most tests want, while the copies capped their iterations and released a failing item so a test that drives the engine into a dead letter or an incident can still drain. Both behaviours survive, as drainQueue() and drainQueueToleratingFailures().
Production
Eight of the nine storage schemas wrote the same four lines around their index literal. IndexedStorageSchema holds them and asks for getIndexes(), the seam Kessai's PaymentStorageSchema already offers and orchestra_payment already extends. All 30 index declarations and their columns are unchanged, checked name by name.
TimeoutSweeper::fire() and fireTimer() differed only in which inner method they called, around the same transaction handling; they share atomically() now.
The 140 kernel tests that start a run each listed the same six entity schemas. In all 140 the six calls were six consecutive lines, so each became one installEngineSchemas().
Deliberately not done
The same transaction wrapper appears eight more times, five in IncidentManager. Each has an early rollBack() and return inside the try, for a claim it could not take. Moving that body into a closure turns the return into a return from the closure, falling through to commitOrRelease() and committing exactly where the code means to roll back, which is the failure #3618543 fixed. That wants its own issue and its own tests, not a mechanical extraction.
Also left alone, having read them: plugin buildConfigurationForm() and getLabels() share a shape but no content; symmetric pairs such as getIncomingFlows() and getOutgoingFlows() would need a direction argument to merge; declarative tables like tokenInfo() collide only because the detector collapses string literals.