diff --git a/docs/compaction-refresh/probes/p3_d4_focused_run.py b/docs/compaction-refresh/probes/p3_d4_focused_run.py index 6f8643d..4e465c3 100644 --- a/docs/compaction-refresh/probes/p3_d4_focused_run.py +++ b/docs/compaction-refresh/probes/p3_d4_focused_run.py @@ -24,6 +24,12 @@ from pathlib import Path from typing import Any, Callable HERE = Path(__file__).resolve().parent +# WI-2 is deliberately kept in its reviewed worktree until the release package +# contains the gated launcher. This harness pins the source it will execute; +# falling back to the released `mosaic` binary is forbidden. +GATED_WI_ROOT = HERE.parents[3].parent / "stack-827-probe3" +GATED_WI_HEAD = "abd2791f59b3f06f46dd08e55298ced72f6aa7c2" +GATED_LAUNCHER = GATED_WI_ROOT / "packages/mosaic/framework/tools/lease-broker/launch-runtime.py" class PiRpc: @@ -220,6 +226,30 @@ export default function register(pi: ExtensionAPI): void { ) +def gated_launcher_precondition(root: Path, socket_path: Path, environment: dict[str, str]) -> None: + """Refuse to launch unless the exact WI launcher binds this run's fixture.""" + + if environment.get("MOSAIC_LEASE_BROKER_SOCKET") != str(socket_path): + raise RuntimeError("D4 precondition: lease broker socket is not this fixture") + if socket_path.parent != root or root.parent != Path(tempfile.gettempdir()): + raise RuntimeError("D4 precondition: fixture socket is outside this run's temporary root") + try: + head = subprocess.check_output( + ["git", "-C", str(GATED_WI_ROOT), "rev-parse", "HEAD"], text=True + ).strip() + launcher_source = GATED_LAUNCHER.read_text(encoding="utf-8") + except (OSError, subprocess.CalledProcessError) as error: + raise RuntimeError("D4 precondition: gated WI launcher is unavailable") from error + if head != GATED_WI_HEAD: + raise RuntimeError(f"D4 precondition: gated WI head mismatch: {head}") + + register = launcher_source.find('"action": "register_anchor"') + execute = launcher_source.find("execute(command[0], command, environment)") + fixture_socket = launcher_source.find('source_environment["MOSAIC_LEASE_BROKER_SOCKET"]') + if register < 0 or execute < 0 or register >= execute or fixture_socket < 0: + raise RuntimeError("D4 precondition: launcher is not register-before-exec fixture-bound") + + def assert_d4(records: list[dict[str, Any]]) -> dict[str, object]: lifecycle = [record for record in records if record.get("event") == "runtime_generation_bump"] promotion = next(record for record in records if record.get("event") == "probe_lease_promoted") @@ -293,20 +323,6 @@ def run_once(index: int) -> Path: extension = root / "d4_extension.ts" write_extension(extension) - broker = subprocess.Popen( - [ - sys.executable, - str(HERE / "p3_generation_broker.py"), - "--socket", - str(socket_path), - "--log", - str(generation_log), - ], - text=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - wait_path(socket_path) environment = os.environ.copy() # Do not let the gated launcher inherit or fall back to its live/default # broker. Both its registration handshake and D4 lifecycle use this one @@ -321,10 +337,30 @@ def run_once(index: int) -> Path: "PI_SKIP_VERSION_CHECK": "1", } ) + # Must run before the fixture broker or Pi process is launched. It proves + # the launcher registers before exec and can only read this fixture socket. + gated_launcher_precondition(root, socket_path, environment) + broker = subprocess.Popen( + [ + sys.executable, + str(HERE / "p3_generation_broker.py"), + "--socket", + str(socket_path), + "--log", + str(generation_log), + ], + text=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + wait_path(socket_path) pi = PiRpc( [ - "mosaic", - "yolo", + sys.executable, + str(GATED_LAUNCHER), + "--runtime", + "pi", + "--", "pi", "--mode", "rpc",