Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### Component foundation

- Added Phase 5.7 Testing SDK and independent component acceptance coverage inside `evolvephp/testing`, including public pre-beta experimental `ComponentDefinitionFixture` and `ComponentEntryPointFixture` closure-backed fixtures for the accepted component contracts, no direct PHPUnit dependency in Testing source, no Module/Plugin replacement semantics, no hidden registries or lifecycle orchestration, and independent integration coverage for explicit `ModuleDefinition`, `ComposerPluginDiscovery`, app-controlled enablement, Core `ComponentBootstrapper`, real graph ordering, restricted registration, service-registry freeze, `ApplicationKernel` boot, component boot, ready and reverse shutdown. Create-project tooling, generators, Doctor, route inspection, environment inspection and broader developer tooling remain Phase 6 work.
- Added Phase 5.6B Composer plugin discovery inside `evolvephp/plugin`, including public pre-beta experimental `ComposerPluginDiscovery` for Composer 2 `vendor/composer/installed.json`, schema 1 `extra.evolvephp.plugin` metadata, Composer package name as the authoritative identifier, deterministic discovered-definition ordering, graph metadata projection into existing Contracts declarations, application-controlled enablement through `evolve.components.enabled`, disabled-definition inertness, no entry-point construction or instantiation during discovery, no recursive package scanning, no Composer 1 support, no new Composer dependency and no Composer runtime API dependency.
- Added Phase 5.6A explicit component definitions and app-controlled enablement, including public pre-beta experimental `ComponentDefinition` in `evolvephp/contracts`, explicit `ModuleDefinition` and `PluginDefinition` wrappers, Core-owned `ComponentBootstrapper`, `ApplicationKernel` bootstrapper integration, strict `evolve.components.enabled` allowlist validation, disabled-definition inertness, validate-all-before-create behavior, existing graph-resolution reuse and exact binding into the Phase 5.5 lifecycle coordinator. Composer discovery, package scanning, Composer `extra` metadata, automatic enablement, descriptor serialization, component versions, dependency version ranges and SemVer graph decisions remain deferred.
- Added Phase 5.5 component lifecycle entry points and Core-owned orchestration, including public pre-beta experimental `ComponentEntryPoint` and `ComponentBootContext` in `evolvephp/contracts`, `Evolve\Module\Module` and `Evolve\Plugin\Plugin` SDK entry points, deterministic registration -> freeze -> boot -> ready ordering through `ApplicationKernel`, reverse successful-boot shutdown, boot-failure deferred cleanup, ready-failure cleanup, attributed aggregate shutdown failures, original startup failure preservation and at-most-once lifecycle state enforcement. Discovery and enablement remain Phase 5.6.
Expand Down
8 changes: 5 additions & 3 deletions packages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

`packages/` contains the initial EvolvePHP 2 modular-monorepo package set.

The packages define Composer package identities, namespace ownership, dependency direction, the first Phase 3 lifecycle, configuration, service-container, execution-scope, runtime-neutral execution orchestration, generic Core instrumentation and minimal Core console foundations, plus the Phase 4.1 PSR HTTP middleware foundation, Phase 4.2 routing foundation, Phase 4.3 routed handler dispatch foundation, Phase 4.4 HTTP execution-kernel integration, Phase 4.5 HTTP response/error and health foundation, Phase 4.6 `ResponseEmitter` runtime-neutral response-emission boundary and integration acceptance, Phase 5.1 Component Identity Foundation, the Phase 5.2 Module/Plugin immutable descriptor foundation, the Phase 5.3A dependency/capability graph declaration vocabulary, the Phase 5.3B Core-owned graph validation/resolution foundation, the Phase 5.4 restricted component service-definition registration foundation, the Phase 5.5 component lifecycle entry-point/orchestration foundation, the Phase 5.6A explicit component definition/bootstrap foundation and the Phase 5.6B Composer plugin discovery foundation for EvolvePHP 2. Complete runtime implementation is not yet present for the framework, and the packages are not yet published.
The packages define Composer package identities, namespace ownership, dependency direction, the first Phase 3 lifecycle, configuration, service-container, execution-scope, runtime-neutral execution orchestration, generic Core instrumentation and minimal Core console foundations, plus the Phase 4.1 PSR HTTP middleware foundation, Phase 4.2 routing foundation, Phase 4.3 routed handler dispatch foundation, Phase 4.4 HTTP execution-kernel integration, Phase 4.5 HTTP response/error and health foundation, Phase 4.6 `ResponseEmitter` runtime-neutral response-emission boundary and integration acceptance, Phase 5.1 Component Identity Foundation, the Phase 5.2 Module/Plugin immutable descriptor foundation, the Phase 5.3A dependency/capability graph declaration vocabulary, the Phase 5.3B Core-owned graph validation/resolution foundation, the Phase 5.4 restricted component service-definition registration foundation, the Phase 5.5 component lifecycle entry-point/orchestration foundation, the Phase 5.6A explicit component definition/bootstrap foundation, the Phase 5.6B Composer plugin discovery foundation and the Phase 5.7 Testing component fixture and independent acceptance foundation for EvolvePHP 2. Complete runtime implementation is not yet present for the framework, and the packages are not yet published.

All package manifests require PHP `^8.4`.

Expand All @@ -15,7 +15,7 @@ All package manifests require PHP `^8.4`.
| `evolvephp/http` | `Evolve\Http\` | HTTP boundary with the Phase 4.1 PSR HTTP interoperability and `MiddlewarePipeline` foundation, Phase 4.2 route definitions and matching, Phase 4.3 routed handler dispatch with typed routing failures, Phase 4.4 `HttpKernel` integration with Core execution orchestration, Phase 4.5 response/error plus health foundation and Phase 4.6 explicit response-emitter boundary; runtime adapters remain deferred. |
| `evolvephp/module` | `Evolve\Module\` | Module SDK boundary with the public experimental `ModuleDescriptor`, EvolvePHP-major compatibility validation foundation, Phase 5.3A `graphDeclaration()` projection, Phase 5.5 `Module` entry point extending `ComponentEntryPoint` and Phase 5.6A explicit `ModuleDefinition`; discovery remains deferred. |
| `evolvephp/plugin` | `Evolve\Plugin\` | Plugin SDK boundary with the public experimental `PluginDescriptor`, EvolvePHP-major compatibility validation foundation, Phase 5.3A `graphDeclaration()` projection, Phase 5.5 `Plugin` entry point extending `ComponentEntryPoint`, Phase 5.6A explicit `PluginDefinition` and Phase 5.6B `ComposerPluginDiscovery` for packaged plugin metadata. |
| `evolvephp/testing` | `Evolve\Testing\` | Testing-support boundary for later developer testing utilities. |
| `evolvephp/testing` | `Evolve\Testing\` | Development-only testing-support boundary, including Phase 5.7 public experimental component fixtures and independent Phase 5 acceptance coverage. |

## Dependency Direction

Expand Down Expand Up @@ -78,6 +78,8 @@ Phase 5.6A adds explicit component definitions and app-controlled enablement. Co

Phase 5.6B adds packaged plugin metadata discovery inside `evolvephp/plugin`. The public experimental `ComposerPluginDiscovery` reads Composer 2 `vendor/composer/installed.json` only, recognizes `extra.evolvephp.plugin`, treats the Composer package name as the authoritative identifier, returns sorted `PluginDefinition` objects and keeps application-controlled enablement through `evolve.components.enabled`. Disabled discovered definitions remain inert; discovery does not instantiate entry points, check classes, inspect root composer.json modules, use Composer 1 metadata, access the network, add caching, or require the Composer runtime API. It uses installed.json only with no recursive package scanning and no new Composer dependency.

The Phase 4 HTTP package foundation is complete after this slice, but the complete production runtime is still deferred. EvolvePHP 2 does not yet provide complete HTTP runtime adapters, concrete runtime adapters, concrete PSR-7 implementation, SAPI response transmission, SAPI request creation, HTML or JSON error rendering, content negotiation, debug pages, automatic health routes, environment or dotenv loading, configuration files, queue or scheduled-job adapters, retry policy, process recycling or termination, module/plugin runtime, runtime CLI adapters, shell executables, argv or shell parsing, stdout/stderr stream implementations, Symfony Console integration, Doctor, generators, developer tooling commands, Insight, Observe, OpenTelemetry propagation, tracing, metrics, logs, telemetry storage/export, persistent-worker concurrency guarantees or production-ready framework runtime behavior. Phase 5.6B does not implement descriptor serialization, component versions, dependency version ranges or Composer semantic-version constraint evaluation. Module runtime remains deferred to later Phase 5 slices, and Phase 6 owns developer tooling.
Phase 5.7 adds the first concrete `evolvephp/testing` SDK surface for component tests. `ComponentDefinitionFixture` and `ComponentEntryPointFixture` are public experimental test fixtures that reuse the real component contracts while remaining simple closure-backed wrappers. The Testing package also carries an independent integration acceptance test covering explicit `ModuleDefinition`, `ComposerPluginDiscovery`, application-controlled enablement, Core `ComponentBootstrapper`, real dependency ordering, restricted registration, `ServiceRegistry` freeze, `ApplicationKernel` boot, component boot, ready and reverse shutdown. These fixtures do not replace Module or Plugin definitions, lifecycle orchestration, discovery, graph resolution, developer tooling, mocks or PHPUnit assertion APIs.

The Phase 4 HTTP package foundation is complete after this slice, but the complete production runtime is still deferred. EvolvePHP 2 does not yet provide complete HTTP runtime adapters, concrete runtime adapters, concrete PSR-7 implementation, SAPI response transmission, SAPI request creation, HTML or JSON error rendering, content negotiation, debug pages, automatic health routes, environment or dotenv loading, configuration files, queue or scheduled-job adapters, retry policy, process recycling or termination, module/plugin runtime, runtime CLI adapters, shell executables, argv or shell parsing, stdout/stderr stream implementations, Symfony Console integration, Doctor, generators, developer tooling commands, Insight, Observe, OpenTelemetry propagation, tracing, metrics, logs, telemetry storage/export, persistent-worker concurrency guarantees or production-ready framework runtime behavior. These capabilities remain deferred. Phase 5.6B does not implement descriptor serialization, component versions, dependency version ranges or Composer semantic-version constraint evaluation. Phase 5.7 does not add create-project tooling, generators, Doctor, environment inspection, route inspection or a general testing framework. Phase 6 owns developer tooling.

The EvolvePHP 2 repository root resolves and validates these local packages. See [../DEVELOPMENT.md](../DEVELOPMENT.md) for setup, testing, quality commands, lockfile, static-analysis, coding-standard and architecture-boundary policy.
32 changes: 32 additions & 0 deletions packages/testing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

Testing utilities for EvolvePHP 2 packages and applications.

This package remains development-only.

## Package

`evolvephp/testing`
Expand All @@ -14,6 +16,36 @@ PHP `^8.4`

`evolvephp/contracts`, `evolvephp/core`, `evolvephp/http`, `evolvephp/module`, `evolvephp/plugin`

## Component Fixtures

Phase 5.7 adds the first small Testing SDK surface for component-oriented tests.

The package provides two public experimental fixtures:

- `Evolve\Testing\Component\ComponentDefinitionFixture`
- `Evolve\Testing\Component\ComponentEntryPointFixture`

Both fixtures reuse the real Evolve component contracts from `evolvephp/contracts`.
They are intended for framework and application tests that need a generic component
definition or lifecycle participant without creating bespoke test-only classes each
time.

`ComponentDefinitionFixture` preserves a caller-supplied component identifier,
component type, graph relations, optional validator and entry-point factory. It
creates one graph declaration during construction, returns that same declaration
on every `graphDeclaration()` call, invokes the validator only when supplied and
delegates entry-point creation to the caller-supplied factory.

`ComponentEntryPointFixture` accepts optional callbacks for `register`, `boot`,
`ready` and `shutdown`. Missing callbacks are no-ops, supplied callbacks receive
the exact lifecycle objects passed by the framework and callback failures are not
wrapped by the fixture.

These APIs are experimental and may change before stable release. They do not
replace `ModuleDefinition`, `PluginDefinition`, module or plugin entry-point
interfaces, graph resolution, lifecycle orchestration, service registration
policy, discovery, developer tooling, mocks or PHPUnit assertions.

## Publication Status

EvolvePHP 2 is pre-release. This package is not yet independently published, and the current canonical source is the EvolvePHP monorepo:
Expand Down
Empty file removed packages/testing/src/.gitkeep
Empty file.
62 changes: 62 additions & 0 deletions packages/testing/src/Component/ComponentDefinitionFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace Evolve\Testing\Component;

use Closure;
use Evolve\Contracts\Component\ComponentDefinition;
use Evolve\Contracts\Component\ComponentEntryPoint;
use Evolve\Contracts\Component\ComponentGraphDeclaration;
use Evolve\Contracts\Component\ComponentGraphRelations;
use Evolve\Contracts\Component\ComponentIdentifier;
use Evolve\Contracts\Component\ComponentType;

/**
* Generic component definition fixture for framework and application tests.
*
* @experimental
*/
final readonly class ComponentDefinitionFixture implements ComponentDefinition
{
private ComponentGraphDeclaration $graphDeclaration;

/**
* @param Closure(): ComponentEntryPoint $entryPointFactory
* @param Closure(): void|null $validator
*/
public function __construct(
private ComponentIdentifier $identifier,
private ComponentType $type,
private Closure $entryPointFactory,
ComponentGraphRelations $relations = new ComponentGraphRelations(),
private ?Closure $validator = null,
) {
$this->graphDeclaration = new ComponentGraphDeclaration($identifier, $relations);
}

public function identifier(): ComponentIdentifier
{
return $this->identifier;
}

public function type(): ComponentType
{
return $this->type;
}

public function graphDeclaration(): ComponentGraphDeclaration
{
return $this->graphDeclaration;
}

public function validate(): void
{
($this->validator ?? static function (): void {})();
}

public function createEntryPoint(): ComponentEntryPoint
{
return ($this->entryPointFactory)();
}
}
51 changes: 51 additions & 0 deletions packages/testing/src/Component/ComponentEntryPointFixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Evolve\Testing\Component;

use Closure;
use Evolve\Contracts\Component\ComponentBootContext;
use Evolve\Contracts\Component\ComponentEntryPoint;
use Evolve\Contracts\Component\Registration\ServiceDefinitionRegistrar;

/**
* Callback-driven component lifecycle fixture for framework and application tests.
*
* @experimental
*/
final readonly class ComponentEntryPointFixture implements ComponentEntryPoint
{
/**
* @param Closure(ServiceDefinitionRegistrar): void|null $register
* @param Closure(ComponentBootContext): void|null $boot
* @param Closure(): void|null $ready
* @param Closure(): void|null $shutdown
*/
public function __construct(
private ?Closure $register = null,
private ?Closure $boot = null,
private ?Closure $ready = null,
private ?Closure $shutdown = null,
) {}

public function register(ServiceDefinitionRegistrar $registrar): void
{
($this->register ?? static function (ServiceDefinitionRegistrar $registrar): void {})($registrar);
}

public function boot(ComponentBootContext $context): void
{
($this->boot ?? static function (ComponentBootContext $context): void {})($context);
}

public function ready(): void
{
($this->ready ?? static function (): void {})();
}

public function shutdown(): void
{
($this->shutdown ?? static function (): void {})();
}
}
Loading