Problem
#1498 closed the M4 scaffold : bootstrap-loop-probe.sh runs gen-1 link + Zend gen-2 emit and exits 2 until M3 strict is green. BOOTSTRAP_M4_GEN2_STRICT=1 in script/bootstrap-loop-gen1-link.sh still refuses Zend fallback, but there is no focused tracker for making gen-2 emit native end-to-end.
Docs still say M4 is “partial — gen-2 Zend emit” (docs/bootstrap-selfhost.md, docs/self-host-target.md).
Goal
BOOTSTRAP_M4_GEN2_STRICT=1 ./script/bootstrap-loop-gen1-link.sh
# emit_path=native; build/bootstrap-loop-gen2 runs without php bin/compile.php
./build/bootstrap-loop-gen2
# stdout contains compiler smoke marker
Full probe (non-dry-run) advances from exit 2 → 0 when M3 strict (#1937 ) is green.
Scope
Piece
Path
Notes
Gen-1 native compile
script/bootstrap-loop-gen1-link.sh
BOOTSTRAP_M4_LINK_COMPILE_DRIVER=1
Gen-2 emit
build/bootstrap-loop-gen2
Native bin/compile.php or src/cli.php (#1467 )
Runtime compile
BOOTSTRAP_M4_RUNTIME_COMPILE=1
Pairs #1402 / #1937
Hashtable
#66 / #1761
Native emit may still fault without rehash
Probe
script/bootstrap-loop-probe.sh
Update exit-code docs when green
Presenter
#2379
make north-star4-verify bundles M4 commands when script lands
CI
#2112
Opt-in BOOTSTRAP_M4_GEN2_STRICT_GATE in ci-local after probe stable
Out of scope: vendor prelink (#1416 ), full-tree rebuild (#1521 ).
Implementation hints (ordered)
M3 strict emit — BOOTSTRAP_M3_COMPILE_SMOKE_STRICT_GATE=1 green (Self-host M3: Native emit for compiler compile-smoke fixture (post-#1493) #1937 , CI: Default BOOTSTRAP_M3_COMPILE_SMOKE_STRICT_GATE=1 in ci-local after #1968 green #2165 flip)
Spine tail — Self-host M2 slice: native-link lib/AOT/Linker.php in spine smoke (1/2 deferred paths) #2267 lib/AOT/Linker.php + Self-host M2: BootstrapVmDriver native execute smoke (post-#2134 bin/vm.php link) #2201 bin/vm.php native link/execute
Gen-1 — bootstrap-loop-gen1-link.sh with BOOTSTRAP_M4_LINK_COMPILE_DRIVER=1
Gen-2 binary — run ./build/bootstrap-loop-gen2 -r 'echo smoke;' without Zend on PATH for compile step
Probe — ./script/bootstrap-loop-probe.sh (non --dry-run) exit 0
Debug when gen-2 still uses Zend
BOOTSTRAP_M4_GEN2_STRICT=1 PHP_COMPILER_DEBUG=1 ./script/bootstrap-loop-gen1-link.sh 2>&1 | tee /tmp/m4-gen2.log
grep -E ' emit_path|zend|native' /tmp/m4-gen2.log
Acceptance criteria
script/apply-patches.sh
BOOTSTRAP_M4_GEN2_STRICT=1 ./script/bootstrap-loop-gen1-link.sh
./script/bootstrap-loop-probe.sh # exit 0 when M3 strict + gen-2 native green
Harness:
./script/docker-exec.sh -- bash -lc ' script/apply-patches.sh && BOOTSTRAP_M4_GEN2_STRICT=1 ./script/bootstrap-loop-gen1-link.sh'
Dependencies
Links
Problem
#1498 closed the M4 scaffold:
bootstrap-loop-probe.shruns gen-1 link + Zend gen-2 emit and exits 2 until M3 strict is green.BOOTSTRAP_M4_GEN2_STRICT=1inscript/bootstrap-loop-gen1-link.shstill refuses Zend fallback, but there is no focused tracker for making gen-2 emit native end-to-end.Docs still say M4 is “partial — gen-2 Zend emit” (
docs/bootstrap-selfhost.md,docs/self-host-target.md).Goal
Full probe (non-dry-run) advances from exit 2 → 0 when M3 strict (#1937) is green.
Scope
script/bootstrap-loop-gen1-link.shBOOTSTRAP_M4_LINK_COMPILE_DRIVER=1build/bootstrap-loop-gen2bin/compile.phporsrc/cli.php(#1467)BOOTSTRAP_M4_RUNTIME_COMPILE=1script/bootstrap-loop-probe.shmake north-star4-verifybundles M4 commands when script landsBOOTSTRAP_M4_GEN2_STRICT_GATEinci-localafter probe stableOut of scope: vendor prelink (#1416), full-tree rebuild (#1521).
Implementation hints (ordered)
BOOTSTRAP_M3_COMPILE_SMOKE_STRICT_GATE=1green (Self-host M3: Native emit for compiler compile-smoke fixture (post-#1493) #1937, CI: Default BOOTSTRAP_M3_COMPILE_SMOKE_STRICT_GATE=1 in ci-local after #1968 green #2165 flip)lib/AOT/Linker.php+ Self-host M2: BootstrapVmDriver native execute smoke (post-#2134 bin/vm.php link) #2201bin/vm.phpnative link/executebootstrap-loop-gen1-link.shwithBOOTSTRAP_M4_LINK_COMPILE_DRIVER=1./build/bootstrap-loop-gen2 -r 'echo smoke;'without Zend on PATH for compile step./script/bootstrap-loop-probe.sh(non--dry-run) exit0Debug when gen-2 still uses Zend
Acceptance criteria
script/apply-patches.sh BOOTSTRAP_M4_GEN2_STRICT=1 ./script/bootstrap-loop-gen1-link.sh ./script/bootstrap-loop-probe.sh # exit 0 when M3 strict + gen-2 native greenHarness:
./script/docker-exec.sh -- bash -lc 'script/apply-patches.sh && BOOTSTRAP_M4_GEN2_STRICT=1 ./script/bootstrap-loop-gen1-link.sh'emit_path=nativefor gen-2 onphp-compiler:22.04-devdocs/bootstrap-selfhost.md+docs/self-host-target.mdM4 rows updatedDependencies
src/cli.phpspine entryLinks