# ARCH-01 hexagonal-boundary experiment

This fixture supports the planned article *A Hexagon Is Not a Directory
Layout*. It runs one Laravel quote request through three source structures:

- a controller coupled to Laravel HTTP and the provider schema;
- the same dependency moved under an `Application` namespace; and
- an application-owned `ProductPrices` port with HTTP adapters outside it.

The provider changes from top-level `price_cents` to nested
`price.amount_minor`. The fixture asks where that change lands. It does not use
file counts or timings as a maintainability claim.

## Run it

Docker is the only host dependency.

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

The runner builds a digest-pinned image, starts a local PHP provider for each
case, sends one in-process Laravel HTTP request through real routing and
container resolution, and retains every command, exit, duration, request,
provider response, application response, failure, source diff, and dependency
report under `results/`.

Laravel's feature request is integration evidence, not end-to-end evidence.
The inbound request is simulated inside the framework process. The outbound
catalogue request crosses a real local HTTP process boundary.

## Expected behavior matrix

| Flow | Provider | Result |
| --- | --- | --- |
| coupled v1 | v1 | pass |
| coupled v1 | v2 | fail with missing v1 value |
| coupled v2 | v2 | pass |
| renamed v1 | v1 | pass |
| renamed v1 | v2 | fail with missing v1 value |
| renamed v2 | v2 | pass |
| hexagonal v1 adapter | v1 | pass |
| hexagonal v1 adapter | v2 | fail with typed missing v1 value |
| hexagonal v2 adapter | v2 | pass |

Every passing row returns the same application JSON for two `desk-lamp`
products. Every cross-schema failure receives the v2 provider payload but uses
the v1 mapping.

## Dependency evidence

`analyze.php` reads the committed PHP files and verifies:

- coupled controllers import Laravel HTTP and provider fields;
- renamed application services still import Laravel HTTP, call framework
  configuration, and read provider fields;
- the hexagonal application imports no Laravel type, infrastructure class,
  provider field, URL, or configuration helper;
- both HTTP adapters implement the application-owned `ProductPrices` port; and
- the v1 and v2 renamed controllers are identical after normalizing only their
  version namespace.

The runner also executes an owned direction-defect fixture. Its application
class imports an HTTP adapter, and the analyzer must reject it. The retained
v1-to-v2 diffs identify the coupled controller, renamed application service,
and hexagonal HTTP adapter as the provider-aware change sites.

## Boundary of the conclusion

The fixture proves source direction and one controlled schema-change surface.
It does not prove lower defect rates, faster delivery, easier navigation, or a
universal need for ports and adapters. A direct flow remains reasonable when
the provider mechanism is stable, the application policy is trivial, and the
proposed port would copy HTTP vocabulary instead of naming an application
conversation.
