# ARCH-02 composition-root experiment

This fixture supports the planned article *A Composition Root Makes Choices
Visible*. It compares two Laravel quote use cases with the same request and
response:

- `QuoteProduct` declares `ProductPrices` in its constructor, and a registered
  service provider selects the HTTP adapter; and
- `LocatedQuoteProduct` has no constructor dependency and resolves a configured
  adapter from Laravel's container inside `execute()`.

The experiment asks when Laravel can detect an incomplete object graph and
where a reviewer can discover the adapter choice. It does not treat container
resolution time or file count as design evidence.

## Run it

Docker is the only host dependency.

```sh
./run.sh
```

The runner builds a digest-pinned image and retains commands, exits, durations,
responses, failures, source diffs, and generated composition reports under
`results/`.

## Behavior and resolution matrix

| Case | Expected result |
| --- | --- |
| explicit v1 with provider v1 | request passes |
| explicit v1 with provider v2 | mapping fails at the v1 field |
| explicit v2 with provider v2 | request passes |
| located v2 with provider v2 | request passes |
| explicit binding present | `QuoteProduct` resolves without invoking it |
| explicit binding missing | resolution raises the expected binding error before invocation |
| located entry invalid | `LocatedQuoteProduct` resolves, then invocation raises the expected entry error |

The missing-selection cases are PHPUnit integration contracts. Their commands
exit successfully only when the expected Laravel exception occurs at the
declared boundary. Retained output records whether the application method was
invoked.

## Source controls

`analyze.php` reads the committed PHP and configuration files. It verifies the
registered provider, `ProductPrices` binding, constructor dependency, both
adapter choices, framework-free explicit application, and deliberate located
lookup. Three owned controls must be rejected independently:

- application code calling the container;
- a provider absent from `bootstrap/providers.php`; and
- a registered provider without a `ProductPrices` binding.

## Boundary of the conclusion

Laravel feature requests are in-process integration evidence, not real inbound
network requests. The catalogue adapter does cross a real local HTTP process
boundary. The fixture proves the owned container graph, failure timing,
provider-body mapping, and source inventory. It does not prove DNS, TLS,
credentials, deployment behavior, debugging speed, or a universal provider
layout.
