# Pilot 2 — 26 October 2026
The same protocol as [pilot 1](PILOT-1.md), one run per stack in parallel, after fixing the framework where pilot 1
showed MMOFramework's agent losing its turns. Laravel's and Symfony's starting points did not change; MMOFramework's
was made again by the updated installer (`mmo.start`, its first one kept as `mmo.start.pilot1`). Not recorded in
`src/content/benchmark.json`: a pilot checks the protocol, it is not a result.
## What changed in the framework
| pilot 1 found | fixed in |
|---|---|
| the agent read the source, never `search_documentation` | the project's `AGENTS.md`: "Before you write code" -- ask the MCP server first; its `dev.json` serves it |
| a page receiving its form's POST: undocumented | mmo.client `docs/Pages.md` "A form posting to its page", with a 422 and a redirect |
| no way to test a page as a browser asks for it | mmo.core `TestCase::http()`, and a controller no longer claims a route it did not match (a second request in the same process answered 404) |
| `php -S` answered the shell's menu | mmo.core: `cli-server` is not the command line; the project's `www/index.php` serves its files under `php -S` |
| a PDF: a hand-made writer over FPDF | mmo.pdf 3.1.0 `SimplePdf` (title, fields, a table, totals, UTF-8, the response), FPDF and its fonts bundled |
| the design system's class names, searched for | the mmo-client skill: "A page's html: the design system's classes" |
| looking for phpstan | the project's `AGENTS.md`: done is `phpunit`, a test asking each changed page |
## What it cost
| | turns | tokens | of which output | minutes | checks failed | cost | pilot 1 |
|---|---|---|---|---|---|---|---|
| MMOFramework | 72 | 10.2 M | 54 k | 8.2 | 4 of 8 | $4.40 | 122 turns, $8.84 |
| Laravel + Vue | 40 | 2.8 M | 35 k | 5.8 | 2 of 6 | $1.82 | 44 turns, $2.05 |
| Symfony + Twig | 53 | 4.0 M | 41 k | 6.3 | 0 of 6 | $2.26 | 36 turns, $1.80 |
MMOFramework's run took 41 % fewer turns and half the cost. It is still the most expensive: 1.4 times Symfony's
turns, 2 times its cost. One run per stack: Symfony's moved by 17 turns between pilots with nothing changed, so
these are directions, not measures.
## Was it done
All three, checked by hand under `php -S`: the list, an invoice's page, its PDF (a real `%PDF`, laid out as a
table), the form, their own test suites passing (35, 28 and 34 tests). MMOFramework's form refuses an empty customer
and a negative quantity with a 422, saying so beside each field. Its PDF is `SimplePdf`'s.
## Where MMOFramework's turns went
| | pilot 1 | pilot 2 |
|---|---|---|
| reading the framework's source | 27 | 1 (`TestCase.php`) |
| searching the framework's code | 22 | 1 (a glob of the core demo) |
| asking the MCP server | 7, never `search_documentation` | 18: 5 searches, 4 documentation pages, 6 class descriptions, 3 package lists |
| making a page receive its form | ~30 | 0: written once, then 8 small edits |
| writing a PDF | ~10 | 1 (`describe_class SimplePdf`) |
| the design system's classes | ~10 | 1 search |
| phpstan | 8 | 0 |
What is left:
1. **mmo.pdo, learnt by trying** (~15 steps): scratch scripts probing `PDORepository`, `PDOEntity` and `Table` --
how an entity maps to a table, a unique key, what an error looks like. `docs/Repository.md` and `Tables.md`
were read, and were not enough to write the repository straight: a worked example (an entity with child lines,
in SQLite, created on first use) would be.
2. **Apache cannot write `db/`** (4 steps, and a note to the user): pilot 1's fix 5 is half done -- `php -S` runs, but
a project made under a user's account still has a `db/` Apache's user cannot write. The installer could say so,
or make `db/` group-writable for the web server's group.
3. **Starting**: 5 steps listing and printing the project's files before the first question to the MCP server.
## Fixed since
- **mmo.pdo 2.1.0**: the worked example its docs lacked (an invoice and its lines, `docs/Repository.md`, run by a
test). Writing it found what the agent's probing had: `setEntityClass()` on a table already added changed nothing
(now `PDORepository::setEntities()`, before or after the tables), and a reference was written as an id but read
back as `null` (now the entity, a reference leading back to itself included).
- **`db/` and `www/bin/`**: the hub's `mmo.php project` makes them writable by apache and by you (default ACLs), and
a SQLite file mmo.pdo creates is group-writable -- apache, `php -S` and phpunit each write what another made.
## Seen on the way
The mmoframework and mmo-client skills, which every project carries, end with "ask Marc whether he wants a ticket
added on the board" -- the agent asked it at the end of a bench run. That is Marc's own workflow, not the
framework's: it belongs in his own `~/.claude/CLAUDE.md` (where it already is), not in what a project ships. The
mmo-client skill also names `/home/mmouret/...` paths.