Purpose
Wave 2 tracker. Wave 1 (#36188, 53 children, 2026-09-01) attacked the root causes of a broken compiler: boxed typed ints, no hash in the hashtable, no optimisation passes, silent-null builtins, VM boot cost, red CI. Most of it landed within a day. This tracker is about a successful compiler: one that a PHP developer can install in one command, point at a real project, get a binary that behaves like Zend and runs faster, and trust — because every claim about it is produced by a gate.
Workers claim the children below; DECISION items are for the maintainer. Sibling of #36142 (RunForge north star) and #36188.
What "successful" means (the v2.0 exit criteria — each is a child's Done-when)
| criterion |
measured by |
today (2026-09-02) |
| A clean checkout builds; master CI green for 14 days |
#36377, #36401 |
0 green Compiler-gate runs on master in the last 60 |
| Real projects run: 12 OSS packages' own tests pass under AOT; php-src's Zend/tests + ext/standard/tests scoreboard published |
#36380, #36381, #36382 |
no external corpus exists |
| Faster than Zend where it matters: typed ≥ 3x, untyped ≤ 1.5x slower, strings/arrays/objects ≤ 1.5x, web req/s ≥ php-fpm |
#36385, #36386 |
typed 1.1x, untyped 2.5x slower, arrays/strings 10–500x slower or OOM (top level) |
| Compiles fast: hello ≤ 3 s, MiniWebApp ≤ 10 s, one-file edit < 25 % rebuild |
#36387 |
17 s / did not compile / no incremental |
| Installs in one command, on x86_64 and arm64 |
#36390, #36391 |
clone + composer + patches + LLVM build; x86_64 only |
| Something real is deployed on it and monitored |
#36392 |
nothing |
| Debuggable: file:line traces, DWARF, profiler |
#36394 |
signal names and IR dumps |
| Memory-safe by construction and by CI: spec + assertions + ASan + fuzzing |
#36397, #36398 |
no sanitizer job, no spec, no fuzzer |
| Every README number generated; releases on a cadence with signed artifacts |
#36395, #36389, #36399 |
July numbers, v1.1.0 unreleased since May |
| The fleet cannot close an issue it did not finish |
#36400, #36404 |
4 of the first 6 wave-1 closures were partial |
Priority order (claim first unmerged)
| P |
issue |
what |
| P0 |
#36377 |
clean checkout unbuildable: patch guard + pass-manager patch (re-#36250/#36213/#36229) |
| P0 |
#36380 |
real-world app corpus (12 packages, own test suites, scoreboard) |
| P0 |
#36382 |
Composer/PSR-4 autoload + computed include under AOT |
| P0 |
#36386 |
performance targets + codegen roadmap (ICs, escape analysis, speculation) |
| P0 |
#36400 |
Definition of Done: no partial closes |
| P0 |
#36401 |
master must be green: protection + streak |
| P0 |
#36405 |
false "Undefined variable" warnings on assigned top-level vars (re-#36190) — wave-1 regression |
| P0 |
#36406 |
strlen() after .= still wrong on master (re-#36244) — closed-but-not-done |
| P0 |
#36407 |
wave-1 runtime regressions: mandelbrot timeout (51 s sys), simple 2x slower — bench gate never ran (CI red) |
| P1 |
#36381 |
php-src phpt corpus under VM/AOT, scoreboard |
| P1 |
#36383 |
error/exception semantics parity (stderr + exit code) |
| P1 |
#36384 |
probed syntax matrix + PHP baseline DECISION |
| P1 |
#36385 |
benchmark suite v2 + history + chart |
| P1 |
#36387 |
compile-time targets + gate (finish #36224/#36199) |
| P1 |
#36388 |
memory program: request arena, soak, leak CI |
| P1 |
#36389 |
ship v1.1.0; release cadence; readiness < 15 min |
| P1 |
#36390 |
one-command install: image + tarball + cold gate |
| P1 |
#36392 |
web deployment story + living demo + req/s vs php-fpm |
| P1 |
#36394 |
debuggable binaries: DWARF, traces, --asan, phpc profile |
| P1 |
#36395 |
honest generated docs; purge stale claims |
| P1 |
#36397 |
memory-safety CI + runtime assertions + memory-model spec |
| P1 |
#36398 |
differential fuzzing nightly |
| P1 |
#36402 |
ADRs + four maintainer DECISIONs |
| P1 |
#36408 |
string-key arrays still ~n² after the DJB index (re-#36191) |
| P1 |
#36409 |
containers still leak payload, 219 MB for 200k small arrays (re-#36215) |
| P1 |
#36410 |
.= residual: 300x slower + wrong length; in-place append missing (re-#36216) |
| P1 |
#36411 |
VM still 218 s per 1M iterations, boot 0.99 s (re-#36207/#36206) |
| P2 |
#36391 |
platform matrix: linux/arm64, then macOS |
| P2 |
#36393 |
DECISION: self-host scope = static phpc binary |
| P2 |
#36396 |
unsupported-feature UX + phpc-lint package |
| P2 |
#36399 |
reproducible builds + signed releases |
| P2 |
#36403 |
size budgets + ownership map |
| P2 |
#36404 |
weekly automated status report |
Sequencing: #36377 and #36401 before anything else (nothing else is observable while master is red and unbuildable) · #36400 in the same week (otherwise wave 2 closes the way wave 1 did) · #36382 and #36380 unlock #36381-scale evidence and the web demo · #36385 before #36386 work is claimed (no speed claim without the suite) · #36397 spec before any further refcount/GC change (wave 1 shipped one revert already).
Wave-1 leftovers folded in
Partial closures re-verified on 2026-09-02 master 1edb103c34 (see the results comment on #36188): compile scaling "still ~n^2.6" (#36224 → #36387), helper-unit common.o "hook only" (#36246 → #36390/#36399), string capacity "partial" (#36216 → #36386 item 6), ext manifest partial (#36204 open), Compiler.php decomposition (#36230 open → #36403), patches fork (#36229 open — the root of #36377), LLVM 22 (#36220 open → #36391 decision).
Daily verify (all implementers)
make check # dev-verify-fast: smoke + tier-0 sweep (< 90 s)
script/differential-sweep.sh --aot --repeat 3
script/bench-gate.sh # and, once #36385 lands, --v2
Do not spend runs on
Purpose
Wave 2 tracker. Wave 1 (#36188, 53 children, 2026-09-01) attacked the root causes of a broken compiler: boxed typed ints, no hash in the hashtable, no optimisation passes, silent-null builtins, VM boot cost, red CI. Most of it landed within a day. This tracker is about a successful compiler: one that a PHP developer can install in one command, point at a real project, get a binary that behaves like Zend and runs faster, and trust — because every claim about it is produced by a gate.
Workers claim the children below; DECISION items are for the maintainer. Sibling of #36142 (RunForge north star) and #36188.
What "successful" means (the v2.0 exit criteria — each is a child's Done-when)
Priority order (claim first unmerged)
strlen()after.=still wrong on master (re-#36244) — closed-but-not-done.=residual: 300x slower + wrong length; in-place append missing (re-#36216)Sequencing: #36377 and #36401 before anything else (nothing else is observable while master is red and unbuildable) · #36400 in the same week (otherwise wave 2 closes the way wave 1 did) · #36382 and #36380 unlock #36381-scale evidence and the web demo · #36385 before #36386 work is claimed (no speed claim without the suite) · #36397 spec before any further refcount/GC change (wave 1 shipped one revert already).
Wave-1 leftovers folded in
Partial closures re-verified on 2026-09-02 master
1edb103c34(see the results comment on #36188): compile scaling "still ~n^2.6" (#36224 → #36387), helper-unit common.o "hook only" (#36246 → #36390/#36399), string capacity "partial" (#36216 → #36386 item 6), ext manifest partial (#36204 open), Compiler.php decomposition (#36230 open → #36403), patches fork (#36229 open — the root of #36377), LLVM 22 (#36220 open → #36391 decision).Daily verify (all implementers)
Do not spend runs on
AOT: X returns nullissues (the registry route AOT: builtin class methods are resolved from a hand-written proxy allowlist, so every unlisted method lowers to a silent null — root cause of the one-issue-per-method treadmill (lib/JIT/Context.php findInternalBuiltinInModule, lib/JIT/Call/ExternalMethod.php) #36202 is in; a null is now a bug in that route)bench-gaterow; docs numbers typed by hand