Module packaging evaluation
Outcome
K0smos retains one root Composer package. Per-module composer.json files are
not adopted in 0.26.0 because no independent publisher or consumer exists and
the current directories are not independently installable. ADR 0005 is the
decision record.
Reproducible inventory
Run:
php tools/architecture/module-boundary-inventory.php
composer validate --no-check-publish --no-interaction
composer dump-autoload --optimize --no-interaction
vendor/bin/phpunit tests/Unit/Architecture/ModuleComposerBoundaryTest.php
Evidence captured on 2026-08-21:
| Measure | Result |
|---|---|
Co-located Config/module.php descriptors |
41 |
| Explicit root module PSR-4 mappings | 41 |
| Missing root module PSR-4 mappings | 0 |
| Nested module Composer manifests | 0 |
| Nested module vendor directories | 0 |
| Direct runtime-module reference pairs | 18 |
| Core-to-runtime-module reference pairs | 20 |
Before this evaluation, Cart, Esapi, Psapi, and Wpapi were discovered through the broad root classmap but lacked explicit PSR-4 mappings. They now follow the same root ownership as every other module.
The inventory reports reference counts rather than declaring every reference a
defect. Some are transitional or intentional runtime integration points; all
are extraction work that a real package pilot would have to classify. It skips
modules/Ai/src/example/, which is non-authoritative by repository policy.
Goal gate
| Candidate goal | Current evidence | Decision |
|---|---|---|
| Independent publishing | K0smos and its modules are not published; no external consumer | Not present |
| Dependency declaration | Runtime dependencies already live in module.php; PHP packages are root-resolved |
Existing manifest is sufficient |
| Split-repository readiness | Core and module reference pairs plus non-PHP resources need contracts first | Inventory only; no fake readiness claim |
| Contributor tooling | One install already serves all modules; no measured install/test pain addressed by packages | No benefit demonstrated |
| Metadata only | Would duplicate module identity/version/dependency ownership | Reject duplication |
Representative pilots
Tax represents a dependency-light leaf. Documentation represents an optional
module that consumes core rendering, search, vector projection, and console
contracts. Both are found by ModuleCatalog, have no runtime-module dependency,
instantiate while enabled, remain absent while disabled, and load through the
root PSR-4 map.
Creating nested manifests was deliberately not part of the pilot because the goal gate failed. A disposable package manifest would not test split archives, resource installation, migrations, service discovery, tenant activation, or version coordination, and committing it would create duplicate ownership.
Root install invariants
- One root install, lock file, and
vendor/directory are authoritative. - Module directories never run
composer installat runtime or in CI. - Composer
repositoriesremain root-owned; dependency repository declarations are not loaded by Composer. - A future path-repository pilot must test both symlink and mirror behavior, especially on Windows.
- Module archives must include PHP, templates, migrations, translations, assets, license metadata, and discovery metadata or they are incomplete.
- Root/module PHP class ownership must not overlap across packages.
Validation caveat
Optimized autoload generation succeeds. After Codeception removal, the stricter
combined --strict-psr --strict-ambiguous diagnostic no longer reports its
support namespaces; it exits 2 for the pre-existing Stringable stub collision
between marc-mabe/php-enum and symfony/polyfill-php80. Discovery's explicit
JSON-schema test dependency still requires the enum package. The ambiguity is
not caused or solved by per-module packaging and remains separate vendor
autoload cleanup.