Skip to content

Debugging Package Discovery

Use this when a package is installed with Composer but Capell cannot see its commands, settings, admin surfaces, frontend output, or Marketplace metadata.

flowchart LR
Composer["composer show package"] --> Autoload["PSR-4 autoload"]
Autoload --> Provider["Laravel provider discovery"]
Provider --> Manifest["capell.json loaded"]
Manifest --> Registry["Capell package registry"]
Registry --> Bucket["Provider bucket for context"]
Bucket --> Surface["Admin/frontend/settings/cache contribution"]

Debug left to right. Do not start by editing UI code until Composer, autoload, provider discovery, and manifest state are proven.

Terminal window
composer show capell-app/example
composer dump-autoload -o
php artisan optimize:clear
php artisan capell:package-cache:clear
php artisan list capell

If the package comes from a private repository or local path repository:

Terminal window
composer config repositories
composer show capell-app/example --available
SymptomLikely causeCheckFix
Composer cannot find packageRepository/auth/path config missingcomposer config repositoriesAdd repository/auth or local path repo, then composer clear-cache.
Composer installs package but classes failPSR-4 namespace mismatchcomposer dump-autoload -o outputFix composer.json autoload namespace/path.
Laravel never boots providerProvider discovery missing/disabledcomposer show -a package and package extra.laravel.providersAdd provider discovery or register provider in host app.
Capell package state missingcapell.json invalid or package cache staleInspect manifest and clear package cacheFix manifest v3 fields and run php artisan capell:package-cache:clear.
Admin surface missing only in browserAdmin provider not in admin bucket or config cache staleCheck capell.json providers and php artisan optimize:clearMove Filament code to admin provider/AdminBridge.
Frontend output missingFrontend provider not loaded or path not reservedphp artisan route:list and frontend registry testsRegister frontend provider, render hook, component, or reserved path.
Settings missingSettings class/schema not registeredInspect SettingsSchemaRegistry registrationsRegister settings class and schema; run settings migration.

Composer drift means capell_extensions and the current Composer/package registry no longer agree. The Extensions dashboard reports drift as a health alert, but it is read-only: loading /admin/extensions must never run composer require.

Capell classifies drift into four reasons:

ReasonWhat it meansRepair path
Missing registry manifestA capell_extensions row exists, but the current registry has no manifestReview the record manually. The package may have been removed, renamed, or stopped registering metadata.
Composer unavailableThe registry manifest exists, but Composer does not expose the packageRun php artisan capell:extensions:repair-composer-drift vendor/example.
Version mismatchComposer exposes a different version than the Capell extension recordRun the repair command, then verify the extension install/upgrade path if metadata still disagrees.
Disabled or failed in CapellComposer exposes the package, but capell_extensions.status blocks runtime useReview status, runtime gate, and recent install/upgrade failures before re-enabling the extension.

For bulk repair, the CAPELL_EXTENSIONS_COMPOSER_DRIFT_AUTO_FIX gate, --force, and the recorded repair metadata, see capell:extensions:repair-composer-drift.

The package manifest should answer:

  • What is the Composer package name?
  • What kind of package is it?
  • Which provider buckets should load in install/runtime/admin/frontend contexts?
  • Which settings group does it own?
  • Which product group/tier/bundle should Marketplace and docs show?
  • Which scopes does it require?

Older manifest fields such as capell-version are not supported. Use manifest version 3.

it('registers package metadata and providers', function (): void {
$package = CapellCore::getPackage('capell-app/example');
expect($package->name)->toBe('capell-app/example')
->and($package->getLabel())->toBe('Example')
->and($package->hasAdminScope())->toBeTrue();
});
it('boots the package provider without writing host state', function (): void {
expect(fn (): array => $this->app->getLoadedProviders())
->not->toThrow(Throwable::class);
});