Summary
In zero-config mode (no extra.mozart block), PackageFactory::resolveConfig() returns a new Mozart object that is not attached to the Package. This creates fragile coupling between Compose and PackageFactory that could break if the call order changes.
Location
src/PackageFactory.php, lines 46–55 (approximate).
Detail
When extra.mozart exists, resolveConfig() returns the Mozart object that lives inside the package's config — so applyDefaults() mutates it in-place and downstream code that accesses the package's config sees the updated values.
In zero-config mode, it returns new Mozart() which is completely independent of the package. This works today because:
Compose calls finder->setConfig() with the returned config before loadDependencies()
loadDependencies() skips its own setConfig() call when isValidMozartConfig() is false
But this coupling is implicit. Reordering those calls, or having a partial config that passes validation, would cause loadDependencies() to overwrite the finder's config with an un-defaulted version from the package.
Impact
Not a current bug — everything works correctly today. This is a maintenance concern: the implicit ordering dependency between setConfig() and loadDependencies() is non-obvious and could cause subtle issues during future refactoring.
Possible improvement
Have resolveConfig() attach the newly created Mozart to the package in zero-config mode, so the config object is always in sync regardless of call order. Alternatively, document the required call order explicitly.
Summary
In zero-config mode (no
extra.mozartblock),PackageFactory::resolveConfig()returns a newMozartobject that is not attached to thePackage. This creates fragile coupling betweenComposeandPackageFactorythat could break if the call order changes.Location
src/PackageFactory.php, lines 46–55 (approximate).Detail
When
extra.mozartexists,resolveConfig()returns theMozartobject that lives inside the package's config — soapplyDefaults()mutates it in-place and downstream code that accesses the package's config sees the updated values.In zero-config mode, it returns
new Mozart()which is completely independent of the package. This works today because:Composecallsfinder->setConfig()with the returned config beforeloadDependencies()loadDependencies()skips its ownsetConfig()call whenisValidMozartConfig()is falseBut this coupling is implicit. Reordering those calls, or having a partial config that passes validation, would cause
loadDependencies()to overwrite the finder's config with an un-defaulted version from the package.Impact
Not a current bug — everything works correctly today. This is a maintenance concern: the implicit ordering dependency between
setConfig()andloadDependencies()is non-obvious and could cause subtle issues during future refactoring.Possible improvement
Have
resolveConfig()attach the newly createdMozartto the package in zero-config mode, so the config object is always in sync regardless of call order. Alternatively, document the required call order explicitly.