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
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Webware alignment Dev Container.
//
// This is a thin wrapper around compose.yml — it reuses the `tooling` service
// This is a thin wrapper around compose.yml - it reuses the `tooling` service
// rather than defining a parallel environment, so VS Code and plain
// `docker compose` users share the exact same container. Non-VS Code
// developers are not orphaned: they use `docker compose up -d` +
Expand Down
18 changes: 9 additions & 9 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Webware Message — Copilot Agent Instructions
# Webware Message: Copilot Agent Instructions

## Read this before acting — fleet working agreements
## Read this before acting: fleet working agreements

`vendor/webware/webware-tools/agent-working-agreements.md` is authoritative for how work is done
in this fleet, and it overrides anything else in this file or in any local note. Read it before
acting, and again before reporting. The non-negotiables:

- Do exactly the scope asked — only the files, branches and repositories named. No adjacent edits,
- Do exactly the scope asked - only the files, branches and repositories named. No adjacent edits,
no cleanup, no onboarding, no surveys.
- Anything else you notice gets one line at most, with no proposed fix.
- Never close a reply with a condensed restatement of it, and never present an inference as a
Expand All @@ -21,22 +21,22 @@ PHPUnit 13 enforces a strict separation between mocks and stubs. Violating these

- **Use `createStub()`** when the test double only needs to return values (`method()->willReturn()`, `method()->willReturnCallback()`). No expectations are configured.
- **Use `createMock()`** only when the test verifies behavior with `expects()` (e.g. `expects($this->once())`, `expects($this->never())`).
- **Never** call `createMock()` without also calling `expects()` on at least one method — PHPUnit 13 will issue a notice.
- **Never** call `createMock()` without also calling `expects()` on at least one method - PHPUnit 13 will issue a notice.
- **Remove** `/** @var ClassName&MockObject */` annotations and `MockObject` intersection types on variables created with `createStub()`.
- **Remove** the `use PHPUnit\Framework\MockObject\MockObject;` import from any file where no `createMock()` + `expects()` usage remains.

### Examples

```php
// CORRECT — stub returns value, no expectations
// CORRECT - stub returns value, no expectations
$container = $this->createStub(ContainerInterface::class);
$container->method('get')->willReturnCallback(static fn(string $id): mixed => ...);

// CORRECT — mock verifies behavior with expects()
// CORRECT - mock verifies behavior with expects()
$handler = $this->createMock(ErrorHandler::class);
$handler->expects($this->once())->method('attachListener');

// WRONG — createMock() with no expects() triggers PHPUnit notice
// WRONG - createMock() with no expects() triggers PHPUnit notice
$logger = $this->createMock(Logger::class);
$logger->method('withName')->willReturn($logger); // should be createStub()
```
Expand All @@ -45,6 +45,6 @@ $logger->method('withName')->willReturn($logger); // should be createStub()

`phpunit.xml.dist` has `requireCoverageMetadata="true"`. Every test class **must** have:

1. `#[CoversClass(ClassName::class)]` — one per source class under test.
2. `#[CoversMethod(ClassName::class, 'methodName')]` — one per public/protected method exercised.
1. `#[CoversClass(ClassName::class)]` - one per source class under test.
2. `#[CoversMethod(ClassName::class, 'methodName')]` - one per public/protected method exercised.
3. `use PHPUnit\Framework\Attributes\CoversClass;` and `use PHPUnit\Framework\Attributes\CoversMethod;` imports.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#
# Builds a self-contained, interactive PHP development environment carrying
# the Webware toolchain: PHP CLI, Composer, Mago, and Xdebug. Developers work
# inside this container — either through the VS Code Dev Container (backed by
# inside this container: either through the VS Code Dev Container (backed by
# compose.yml) or by `docker compose up -d` + `docker compose exec tooling`.
# The host machine (Windows, WSL, Linux, or macOS) never needs a native PHP
# toolchain.
Expand Down
10 changes: 5 additions & 5 deletions compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# This compose file is the single source of truth for the environment. Two
# ways to use it:
#
# 1. VS Code Dev Container — "Reopen in Container" uses
# 1. VS Code Dev Container: "Reopen in Container" uses
# .devcontainer/devcontainer.json, which is *backed by* this file (it
# references the `tooling` service rather than defining its own).
#
Expand All @@ -24,7 +24,7 @@
# Packages whose tests need MySQL uncomment the `mysql` service below (and the
# `phpmyadmin` web UI if wanted), plus the `depends_on` block on `tooling`. The
# `mysql` service mirrors the `db-image` package parameter used by CI, and is
# reachable from `tooling` as host `mysql` on port 3306 — matching the PhpDb
# reachable from `tooling` as host `mysql` on port 3306: matching the PhpDb
# `mysql.local.php` connection convention. Packages that need a different
# engine add an equivalent service here (postgres, mariadb, ...) mirroring
# their own `db-image` parameter.
Expand Down Expand Up @@ -57,7 +57,7 @@ services:
volumes:
# Bind-mount the source so edits are visible on both the host and the
# container. vendor/ is deliberately overridden below with a named
# volume — do not bind-mount it from the host.
# volume - do not bind-mount it from the host.
- .:/app
# Named volumes keep vendor/ and the Composer cache on the Linux
# filesystem. Bind-mounting vendor/ from a Windows host is extremely
Expand All @@ -73,7 +73,7 @@ services:
working_dir: /app

# -------------------------------------------------------------------------
# MySQL (optional) — uncomment this whole block for packages whose tests
# MySQL (optional) - uncomment this whole block for packages whose tests
# need a MySQL database (e.g. webware-acl via php-db/phpdb-mysql).
#
# Mirror the spec's `db-image` / `db-env-json` / `db-port` Package Parameters
Expand All @@ -99,7 +99,7 @@ services:
# # survives `docker compose down` (use `down -v` to wipe it).
# - mysql-data:/var/lib/mysql
#
# # phpMyAdmin — optional web UI for the `mysql` service above. Reachable at
# # phpMyAdmin - optional web UI for the `mysql` service above. Reachable at
# # http://localhost:8080 (log in with the MYSQL_* credentials). Uncomment
# # alongside `mysql`.
# phpmyadmin:
Expand Down
2 changes: 1 addition & 1 deletion docs/v1/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
]
```

`SystemMessenger` is not a singleton — it is constructed per request from the
`SystemMessenger` is not a singleton - it is constructed per request from the
session by `MessageMiddleware`.

## View Helpers
Expand Down
2 changes: 1 addition & 1 deletion docs/v1/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

- PHP 8.4.1 or later
- A Mezzio application (PSR-11 container, PSR-15 middleware)
- Session middleware in the pipeline — the message middleware reads the
- Session middleware in the pipeline - the message middleware reads the
session from `SessionMiddleware::SESSION_ATTRIBUTE`

## Composer
Expand Down
4 changes: 2 additions & 2 deletions docs/v1/messenger.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ $messenger->sendNow('Visible this request too', MessageLevel::Info);

### Hops

- `send()` defaults to one hop — visible on the next request, then expires.
- `sendNow()` defaults to zero hops — visible in the current request only.
- `send()` defaults to one hop - visible on the next request, then expires.
- `sendNow()` defaults to zero hops - visible in the current request only.
- Passing `$hops` persists the message across that many additional hops.

```php
Expand Down
Loading