3"""Runtime mutation proofs for the descriptor-bound image supervisor."""
5from __future__
import annotations
14from collections.abc
import Callable, Iterator
15from contextlib
import contextmanager, suppress
16from pathlib
import Path
18import hil_convergence_safety_runtime_launcher
as runtime_launcher
19import hil_convergence_safety_runtime_root_swap
as runtime_root_swap
20import hil_convergence_safety_runtime_sources
as runtime_sources
22Mutation = tuple[str, str, str, str]
23Census = Callable[[int], set[int] |
None]
24PipeFactory = Callable[[int], tuple[int, int]]
25SourceWriter = Callable[[Path, str, str, str], tuple[Path, Path, Path]]
26SourceBundle = tuple[str, str, str]
27RUNTIME_TIMEOUT_SECONDS, RESIDUE_TIMEOUT_SECONDS = 25.0, 5.0
30ROOT_PREFIX =
"ra8-devcontainer-image-selftest."
31ROOT_SUFFIX_LENGTH, PROCESS_GROUP_FIELD = 32, 2
32PROCESS_UID_FIELD_COUNT = 4
33INTEGRITY_REFUSAL_STATUS = 126
34PUBLIC_REFUSAL_STATUS = 125
37ONE_SHOT_MUTATION_STATUS = 5
38CANONICAL_TMP = Path(os.path.sep,
"tmp").resolve(strict=
True)
39RuntimeMutationError = runtime_sources.RuntimeSourceError
40_write_sources = runtime_sources.publish
41SupervisorStart = runtime_launcher.SupervisorStart
42_close_owned_descriptors = runtime_launcher.close_owned_descriptors
43_open_supervisor_sources = runtime_launcher.open_supervisor_sources
46GatePreparer = Callable[
47 [SourceBundle, str, Path],
48 tuple[Path, Path, Path, dict[str, str], tuple[int, int, int, int], set[int]],
50RootSwapHooks = tuple[GatePreparer, Callable[[], Path]]
53def _identity(path: Path) -> tuple[int, int]:
54 """Return one filesystem identity without following a final link."""
55 metadata = path.lstat()
56 return metadata.st_dev, metadata.st_ino
59def _identity_text(path: Path) -> str:
60 """Return the supervisor's stable device/inode spelling."""
61 return ":".join(str(value)
for value
in _identity(path))
64def _register_owned_root(root: Path, identity: tuple[int, int]) ->
None:
65 """Bind one created root to the currently active selftest run."""
66 registry = getattr(_create_root,
"_owned_root_registry",
None)
67 if registry
is not None:
68 registry.append((root, identity))
71def _forget_owned_root(root: Path, identity: tuple[int, int]) ->
None:
72 """Forget one root only after its exact bound inode was removed."""
73 registry = getattr(_create_root,
"_owned_root_registry",
None)
76 for index
in range(len(registry) - 1, -1, -1):
77 if registry[index] == (root, identity):
82def _created_root_cleanup(root: Path, identity: tuple[int, int]) -> RuntimeMutationError |
None:
83 """Remove a just-created root using independent containment and identity checks."""
85 metadata = root.lstat()
86 resolved = root.resolve(strict=
True)
88 return RuntimeMutationError(
"created supervisor runtime root became unobservable")
90 suffix = name.removeprefix(ROOT_PREFIX)
93 and root.parent == CANONICAL_TMP
95 and name.startswith(ROOT_PREFIX)
96 and len(suffix) == ROOT_SUFFIX_LENGTH
97 and all(character
in "0123456789abcdef" for character
in suffix)
98 and stat.S_ISDIR(metadata.st_mode)
99 and metadata.st_uid == os.getuid()
100 and metadata.st_gid == os.getgid()
101 and stat.S_IMODE(metadata.st_mode) == PRIVATE_MODE
102 and (metadata.st_dev, metadata.st_ino) == identity
105 return RuntimeMutationError(
"refusing unbound supervisor runtime root cleanup")
106 if not _no_residue((root,)):
107 return RuntimeMutationError(
"refusing live supervisor runtime cleanup")
111 return RuntimeMutationError(
"created supervisor runtime root cleanup failed")
112 if root.exists()
or root.is_symlink():
113 return RuntimeMutationError(
"supervisor runtime root survived cleanup")
117def _drain_owned_roots(registry: list[tuple[Path, tuple[int, int]]]) -> RuntimeMutationError |
None:
118 """Clean only roots recorded by this run, preserving the first refusal."""
119 first_error: RuntimeMutationError |
None =
None
120 for root, identity
in reversed(tuple(registry)):
121 if not root.exists()
and not root.is_symlink():
122 _forget_owned_root(root, identity)
125 _remove_root(root, identity)
126 except RuntimeMutationError
as error:
127 if first_error
is None:
133def _owned_root_scope() -> Iterator[None]:
134 """Own every root allocated in one run until its outer cleanup completes."""
135 state = vars(_create_root)
136 previous = state.get(
"_owned_root_registry")
137 registry: list[tuple[Path, tuple[int, int]]] = []
138 state[
"_owned_root_registry"] = registry
141 except BaseException
as primary:
142 cleanup_error = _drain_owned_roots(registry)
143 if cleanup_error
is not None:
144 raise primary
from cleanup_error
147 cleanup_error = _drain_owned_roots(registry)
148 if cleanup_error
is not None:
152 del state[
"_owned_root_registry"]
154 state[
"_owned_root_registry"] = previous
157def _root_path_is_safe(path: Path, identity: tuple[int, int]) -> bool:
158 """Prove one exact private direct child of the physical temporary root."""
160 metadata = path.lstat()
161 resolved = path.resolve(strict=
True)
165 suffix = name.removeprefix(ROOT_PREFIX)
168 and path.parent == CANONICAL_TMP
170 and name.startswith(ROOT_PREFIX)
171 and len(suffix) == ROOT_SUFFIX_LENGTH
172 and all(character
in "0123456789abcdef" for character
in suffix)
173 and stat.S_ISDIR(metadata.st_mode)
174 and metadata.st_uid == os.getuid()
175 and metadata.st_gid == os.getgid()
176 and stat.S_IMODE(metadata.st_mode) == PRIVATE_MODE
177 and (metadata.st_dev, metadata.st_ino) == identity
181def _new_root_path() -> Path:
182 """Choose one absent canonical root path with 128 random bits."""
183 for _attempt
in range(20):
184 candidate = CANONICAL_TMP / f
"{ROOT_PREFIX}{secrets.token_hex(16)}"
185 if not candidate.exists()
and not candidate.is_symlink():
187 message =
"could not select a fresh supervisor runtime root"
188 raise RuntimeMutationError(message)
191def _create_root() -> tuple[Path, tuple[int, int]]:
192 """Create and bind one private canonical suite root."""
193 root = _new_root_path()
194 root.mkdir(mode=PRIVATE_MODE)
195 return root, _bind_created_root(root)
198def _bind_created_root(root: Path) -> tuple[int, int]:
199 """Validate and register one already-created private canonical root."""
200 identity: tuple[int, int] |
None =
None
202 identity = _identity(root)
203 if not _root_path_is_safe(root, identity):
204 message =
"created supervisor runtime root is unsafe"
205 raise RuntimeMutationError(message)
206 except BaseException
as primary:
207 cleanup_identity = identity
208 if cleanup_identity
is not None:
209 cleanup_error = _created_root_cleanup(root, cleanup_identity)
210 if cleanup_error
is not None:
211 raise primary
from cleanup_error
213 _register_owned_root(root, identity)
217def _create_replacement_root(root: Path) -> tuple[int, int]:
218 """Create one root-swap replacement with the same transactional binding."""
219 root.mkdir(mode=PRIVATE_MODE)
220 return _bind_created_root(root)
223def _remove_root(root: Path, identity: tuple[int, int]) ->
None:
224 """Remove only one still-bound private runtime root."""
225 if not _root_path_is_safe(root, identity):
226 message = f
"refusing unbound supervisor runtime cleanup: {root}"
227 raise RuntimeMutationError(message)
228 if not _no_residue((root,)):
229 message = f
"refusing live supervisor runtime cleanup: {root}"
230 raise RuntimeMutationError(message)
232 if root.exists()
or root.is_symlink():
233 message = f
"supervisor runtime root survived cleanup: {root}"
234 raise RuntimeMutationError(message)
235 _forget_owned_root(root, identity)
238def _move_owned_root(source: Path, destination: Path) ->
None:
239 """Move one registry binding across an identity-preserving rename."""
240 registry = getattr(_create_root,
"_owned_root_registry",
None)
243 for index, (path, identity)
in enumerate(registry):
245 registry[index] = destination, identity
249def _remove_link(link: Path, identity: tuple[int, int]) ->
None:
250 """Remove one exact test-created canonical symlink."""
251 metadata = link.lstat()
253 suffix = name.removeprefix(ROOT_PREFIX)
256 and link.parent == CANONICAL_TMP
257 and name.startswith(ROOT_PREFIX)
258 and stat.S_ISLNK(metadata.st_mode)
259 and metadata.st_uid == os.getuid()
260 and metadata.st_gid == os.getgid()
261 and len(suffix) == ROOT_SUFFIX_LENGTH
262 and all(character
in "0123456789abcdef" for character
in suffix)
263 and (metadata.st_dev, metadata.st_ino) == identity
266 message =
"refusing unbound supervisor runtime symlink cleanup"
267 raise RuntimeMutationError(message)
271def _write_stall_entry(root: Path) -> Path:
272 """Write one payload whose live process retains an observable root marker."""
273 entry = root /
"stall-entry.sh"
276 '[[ "$1" == "--selftest" ]] || exit 64\n'
277 "trap '' HUP INT TERM\n"
278 'exec -a "$0" /bin/sleep 30\n',
281 entry.chmod(PRIVATE_MODE)
285def _process_group_members(group: int) -> set[int] |
None:
286 """Return live Linux process IDs in one exact process group."""
287 members: set[int] = set()
289 processes = tuple(Path(
"/proc").iterdir())
292 for process
in processes:
293 if not process.name.isdigit():
296 raw = (process /
"stat").read_bytes()
297 except FileNotFoundError:
301 closing = raw.rfind(b
")")
302 fields = raw[closing + 2 :].split()
if closing >= 0
else []
303 if len(fields) <= PROCESS_GROUP_FIELD
or not fields[PROCESS_GROUP_FIELD].isdigit():
305 if fields[0] == b
"Z":
307 if int(fields[PROCESS_GROUP_FIELD]) == group:
308 members.add(int(process.name))
312def _wait_group_members(
313 group: int, allowed: set[int], census: Census = _process_group_members
315 """Wait until a group contains only the explicitly allowed process IDs."""
316 deadline = time.monotonic() + RESIDUE_TIMEOUT_SECONDS
317 while time.monotonic() < deadline:
318 members = census(group)
319 if members
is not None and members <= allowed:
321 time.sleep(POLL_SECONDS)
325def _reap_terminal_runner(
326 process: subprocess.Popen[bytes], census: Census = _process_group_members
327) -> tuple[int, bool]:
328 """Remove descendants before reaping one already-terminal group leader."""
329 members = census(process.pid)
330 group_bound = members
is not None and members <= {process.pid}
332 with suppress(ProcessLookupError):
333 os.killpg(process.pid, signal.SIGKILL)
334 group_bound = _wait_group_members(process.pid, {process.pid}, census)
336 message =
"supervisor runtime runner group survived before leader reap"
337 raise RuntimeMutationError(message)
338 status = process.wait(timeout=RESIDUE_TIMEOUT_SECONDS)
339 return status, _wait_group_members(process.pid, set(), census)
342def _kill_and_reap_runner(
343 process: subprocess.Popen[bytes], census: Census = _process_group_members
344) -> tuple[int |
None, bool]:
345 """Immediately close one owned runner without signaling after leader reap."""
347 terminal = os.waitid(os.P_PID, process.pid, os.WEXITED | os.WNOHANG | os.WNOWAIT)
348 except ChildProcessError:
349 if process.returncode
is None:
350 message =
"supervisor runtime runner was reaped outside its owner"
351 raise RuntimeMutationError(message)
from None
352 return process.returncode, _wait_group_members(process.pid, set(), census)
354 with suppress(ProcessLookupError):
355 os.killpg(process.pid, signal.SIGKILL)
356 deadline = time.monotonic() + RESIDUE_TIMEOUT_SECONDS
357 while time.monotonic() < deadline:
358 terminal = os.waitid(os.P_PID, process.pid, os.WEXITED | os.WNOHANG | os.WNOWAIT)
359 if terminal
is not None:
361 time.sleep(POLL_SECONDS)
363 message =
"supervisor runtime runner survived its bounded SIGKILL deadline"
364 raise RuntimeMutationError(message)
365 return _reap_terminal_runner(process, census)
369 process: subprocess.Popen[bytes], census: Census = _process_group_members
370) -> tuple[int |
None, bool]:
371 """Retain the direct leader with WNOWAIT until its group is empty."""
372 deadline = time.monotonic() + RUNTIME_TIMEOUT_SECONDS
374 while time.monotonic() < deadline:
375 result = os.waitid(os.P_PID, process.pid, os.WEXITED | os.WNOHANG | os.WNOWAIT)
376 if result
is not None:
379 time.sleep(POLL_SECONDS)
381 return _kill_and_reap_runner(process, census)
382 return _reap_terminal_runner(process, census)
385def _close_runner_streams(process: subprocess.Popen[bytes]) ->
None:
386 """Close every parent-side pipe owned by one runner."""
387 first_error: OSError |
None =
None
388 for stream
in (process.stdin, process.stdout, process.stderr):
389 if stream
is not None:
392 except OSError
as error:
393 if first_error
is None:
395 if first_error
is not None:
399def _dispose_runner(process: subprocess.Popen[bytes]) -> tuple[int |
None, bool]:
400 """Terminate, group-clean, reap, and close one runner on a failure path."""
401 result: tuple[int |
None, bool] |
None =
None
402 primary: OSError | RuntimeMutationError | subprocess.TimeoutExpired |
None =
None
404 result = _kill_and_reap_runner(process)
405 except (OSError, RuntimeMutationError, subprocess.TimeoutExpired)
as error:
408 _close_runner_streams(process)
409 except OSError
as cleanup_error:
410 if primary
is not None:
411 raise primary
from cleanup_error
413 if primary
is not None:
416 message =
"supervisor runtime runner disposal produced no terminal result"
417 raise RuntimeMutationError(message)
421def _release_owned_descriptor(
422 descriptors: set[int], descriptor: int, closer: runtime_launcher.DescriptorCloser = os.close
424 """Release numeric authority before the one ambiguous close attempt."""
425 descriptors.remove(descriptor)
429def _start_supervisor(
433 arguments: tuple[str, ...],
434 launch: SupervisorStart |
None =
None,
435) -> subprocess.Popen[bytes]:
436 """Start one descriptor-bound supervisor in a retained runner group."""
437 result = runtime_launcher.launch(
438 (main_path, process_path, cases_path), arguments, launch
or SupervisorStart()
440 if result.close_error
is not None:
441 cleanup_error: OSError | RuntimeMutationError | subprocess.TimeoutExpired |
None =
None
442 if result.process
is not None:
444 _dispose_runner(result.process)
445 except (OSError, RuntimeMutationError, subprocess.TimeoutExpired)
as error:
446 cleanup_error = error
447 if result.start_error
is not None:
448 raise result.start_error
from result.close_error
449 if cleanup_error
is not None:
450 raise result.close_error
from cleanup_error
451 raise result.close_error
452 if result.start_error
is not None:
453 raise result.start_error
454 if result.process
is None:
455 message =
"supervisor launcher returned no process or error"
456 raise RuntimeMutationError(message)
457 return result.process
460def _collect_runner(process: subprocess.Popen[bytes]) -> tuple[int |
None, bool, bytes]:
461 """Collect one started runner through a finally-owned cleanup funnel."""
463 status, clean = _wait_runner(process)
464 _stdout, stderr = process.communicate(timeout=RESIDUE_TIMEOUT_SECONDS)
465 except (OSError, RuntimeMutationError, subprocess.TimeoutExpired, ValueError)
as primary:
467 OSError | RuntimeMutationError | subprocess.TimeoutExpired | ValueError |
None
470 _status, cleanup_clean = _dispose_runner(process)
471 except (OSError, RuntimeMutationError, subprocess.TimeoutExpired, ValueError)
as error:
472 cleanup_error = error
475 if not cleanup_clean:
476 message =
"supervisor runtime runner cleanup did not converge"
477 cleanup_error = RuntimeMutationError(message)
478 if cleanup_error
is not None:
479 raise primary
from cleanup_error
482 _close_runner_streams(process)
483 return status, clean, stderr
490 arguments: tuple[str, ...],
491) -> tuple[int |
None, bool, bytes]:
492 """Run and reap one supervisor while preserving its diagnostic bytes."""
493 return _collect_runner(_start_supervisor(main_path, process_path, cases_path, arguments))
496def _receipt_groups(paths: tuple[Path, ...]) -> set[int] |
None:
497 """Return numeric group receipts, or unknown on any unsafe observation."""
498 groups: set[int] = set()
501 receipts = tuple(root.iterdir())
502 except FileNotFoundError:
506 for receipt
in receipts:
507 if receipt.suffix
not in (
".bound",
".outer"):
510 value = receipt.read_bytes().strip()
511 except FileNotFoundError:
515 if not value.isdigit()
or int(value) <= 0:
517 groups.add(int(value))
521def _descriptor_path_reference(
522 descriptors: tuple[Path, ...], needles: tuple[bytes, ...]
524 """Return one descriptor table's reference state, or unknown."""
525 for descriptor
in descriptors:
526 if not descriptor.name.isdigit():
529 target = os.fsencode(descriptor.readlink())
530 except FileNotFoundError:
536 if any(needle
in target
for needle
in needles):
541def _process_path_reference(process: Path, needles: tuple[bytes, ...]) -> bool |
None:
542 """Return one process's reference state, or unknown on malformed observation."""
544 command = (process /
"cmdline").read_bytes()
545 descriptors = tuple((process /
"fd").iterdir())
546 except FileNotFoundError:
550 if command
and not command.endswith(b
"\0"):
552 if any(needle
in command
for needle
in needles):
554 return _descriptor_path_reference(descriptors, needles)
557def _process_has_suite_owner(process: Path) -> bool |
None:
558 """Return whether one process has any UID matching this selftest owner."""
560 lines = (process /
"status").read_text(encoding=
"ascii").splitlines()
561 except FileNotFoundError:
563 except (OSError, UnicodeError):
565 uid_lines = [line
for line
in lines
if line.startswith(
"Uid:")]
566 if len(uid_lines) != 1:
568 fields = uid_lines[0].split()[1:]
569 if len(fields) != PROCESS_UID_FIELD_COUNT
or not all(field.isdigit()
for field
in fields):
571 return str(os.getuid())
in fields
574def _paths_have_no_live_references(paths: tuple[Path, ...]) -> bool:
575 """Prove no process command or descriptor retains an owned runtime path."""
576 needles = tuple(os.fsencode(path)
for path
in paths)
577 deadline = time.monotonic() + RESIDUE_TIMEOUT_SECONDS
578 while time.monotonic() < deadline:
581 processes = tuple(Path(
"/proc").iterdir())
584 for process
in processes:
585 if not process.name.isdigit():
587 owned = _process_has_suite_owner(process)
592 state = _process_path_reference(process, needles)
600 time.sleep(POLL_SECONDS)
604def _receipt_group_is_absent(group: int) -> bool:
605 """Prove an owned group contains no live process."""
606 members = _process_group_members(group)
607 return members == set()
610def _no_residue(paths: tuple[Path, ...]) -> bool:
611 """Prove every process group named by an owned receipt is absent."""
612 groups = _receipt_groups(paths)
615 deadline = time.monotonic() + RESIDUE_TIMEOUT_SECONDS
616 while time.monotonic() < deadline:
617 if all(_receipt_group_is_absent(group)
for group
in groups):
619 time.sleep(POLL_SECONDS)
623def _watchdog_case(supervisor: str, process_source: str, cases: str) -> tuple[str, bool]:
624 """Require the one-second base to pass and the production-deadline mutant to fail."""
625 assignment =
'SELFTEST_WATCHDOG_TIMEOUT_SECONDS = MAIN_API["SELFTEST_WATCHDOG_TIMEOUT_SECONDS"]'
626 replacement =
'SELFTEST_WATCHDOG_TIMEOUT_SECONDS = MAIN_API["WATCHDOG_TIMEOUT_SECONDS"]'
627 if cases.count(assignment) != 1:
628 message =
"watchdog runtime mutation authority is not unique"
629 raise RuntimeMutationError(message)
630 outcomes: list[tuple[str, int |
None, bool, bool]] = []
631 roots: list[tuple[Path, tuple[int, int]]] = []
633 for label, source
in ((
"base", cases), (
"mutant", cases.replace(assignment, replacement))):
634 root, identity = _create_root()
635 roots.append((root, identity))
636 main_path, process_path, cases_path = _write_sources(
637 root, supervisor, process_source, source
639 entry = _write_stall_entry(root)
640 status, clean, _stderr = _run_supervisor(
644 (
"--selftest-watchdog-expiry", str(entry), str(root), _identity_text(root)),
646 outcomes.append((label, status, clean, _no_residue((root,))))
647 passed = outcomes == [(
"base", 0,
True,
True), (
"mutant", 1,
True,
True)]
648 return "watchdog runtime deadline mutation fires", passed
650 for root, identity
in reversed(roots):
651 _remove_root(root, identity)
654def _observation_case(supervisor: str, process_source: str, cases: str) -> tuple[str, bool]:
655 """Require the injected observation error to remain load-bearing."""
656 call =
" _inject_observation_failure()"
657 replacement =
" None # runtime mutation: required observation omitted"
658 if cases.count(call) != 1:
659 message =
"observation runtime mutation authority is not unique"
660 raise RuntimeMutationError(message)
661 outcomes: list[tuple[str, int |
None, bool, bool]] = []
662 roots: list[tuple[Path, tuple[int, int]]] = []
664 for label, source
in ((
"base", cases), (
"mutant", cases.replace(call, replacement))):
665 root, identity = _create_root()
666 roots.append((root, identity))
667 main_path, process_path, cases_path = _write_sources(
668 root, supervisor, process_source, source
670 entry = _write_stall_entry(root)
671 status, clean, _stderr = _run_supervisor(
675 (
"--selftest-observation-failure", str(entry), str(root), _identity_text(root)),
677 outcomes.append((label, status, clean, _no_residue((root,))))
678 passed = outcomes == [(
"base", 0,
True,
True), (
"mutant", 1,
True,
True)]
679 return "observation failure runtime mutation fires", passed
681 for root, identity
in reversed(roots):
682 _remove_root(root, identity)
685def _closed_death_group_race_case(
686 supervisor: str, process_source: str, cases: str
687) -> tuple[str, bool]:
688 """Prove a pre-cleanup census cannot leave live group residue."""
690 " if result is not None:\n"
691 " return result.si_code == os.CLD_KILLED and "
692 "result.si_status == signal.SIGKILL\n"
695 " if result is not None:\n"
696 " members = _group_members(child.pid)\n"
698 " result.si_code == os.CLD_KILLED\n"
699 " and result.si_status == signal.SIGKILL\n"
700 " and members is not None\n"
701 " and members <= {child.pid}\n"
704 if cases.count(observation) != 1:
705 message =
"closed-death group-census mutation authority is not unique"
706 raise RuntimeMutationError(message)
707 outcomes: list[tuple[str, int |
None, int |
None, bool, bool]] = []
708 roots: list[tuple[Path, tuple[int, int]]] = []
710 for label, source
in ((
"base", cases), (
"mutant", cases.replace(observation, premature))):
711 root, identity = _create_root()
712 roots.append((root, identity))
713 main_path, process_path, cases_path = _write_sources(
714 root, supervisor, process_source, source
716 entry = _write_stall_entry(root)
717 watchdog, watchdog_clean, _stderr = _run_supervisor(
721 (
"--selftest-watchdog-expiry", str(entry), str(root), _identity_text(root)),
723 closed, closed_clean, _stderr = _run_supervisor(
727 (
"--selftest-closed-death-fd", str(entry), str(root), _identity_text(root)),
730 (label, watchdog, closed, watchdog_clean
and closed_clean, _no_residue((root,)))
732 base = (
"base", 0, 0,
True,
True)
736 and mutant[0:2] == (
"mutant", 0)
737 and mutant[2]
in {0, 1}
738 and mutant[3:] == (
True,
True)
740 return "closed-death group census remains terminal-safe", safe
742 for root, identity
in reversed(roots):
743 _remove_root(root, identity)
746def _prepare_root_gate(*args: object, **kwargs: object) -> object:
747 """Delegate root-gate preparation to the focused swap module."""
748 return runtime_root_swap.__dict__[
"_prepare_root_gate"](*args, **kwargs)
751def _finalize_root_swap(*args: object, **kwargs: object) -> object:
752 """Delegate root-swap finalization to the focused swap module."""
753 return runtime_root_swap.__dict__[
"_finalize_root_swap"](*args, **kwargs)
756def _replace_root_after_gate(
757 sources: SourceBundle,
760 inject_after_rename: bool =
False,
761 hooks: RootSwapHooks |
None =
None,
762) -> tuple[int |
None, bool, bool, bool]:
763 """Replace a suite root at one deterministic retained-authority boundary."""
764 return runtime_root_swap.__dict__[
"_replace_root_after_gate"](
765 sources, phase=phase, inject_after_rename=inject_after_rename, hooks=hooks
769def runtime_cases(inputs: dict[str, str]) -> list[tuple[str, bool]]:
770 """Run every Linux-only descriptor, root, and cleanup mutation proof."""
771 if not Path(
"/proc/self/stat").is_file():
772 return [(
"image supervisor runtime mutations are Linux-only",
True)]
773 supervisor = inputs[
"devcontainer_image_selftest_supervisor"]
774 process_source = inputs[
"devcontainer_image_selftest_process"]
775 cases = inputs[
"devcontainer_image_selftest_supervisor_cases"]
776 with _owned_root_scope():
778 _watchdog_case(supervisor, process_source, cases),
779 _observation_case(supervisor, process_source, cases),
780 _closed_death_group_race_case(supervisor, process_source, cases),