from __future__ import annotations import json import os import tempfile from datetime import UTC, datetime from pathlib import Path from typing import Any def utc_now_iso() -> str: """Return a stable UTC timestamp for manifests and capture artifacts.""" return datetime.now(UTC).isoformat(timespec="milliseconds").replace("+00:00", "Z") def write_json_atomic(path: Path, payload: Any) -> None: """Write JSON without exposing or acknowledging a partial commit. Flushing the temporary file protects its contents, but a crash can still lose the directory entry created by ``replace``. The parent directory is therefore flushed after the atomic rename as the second durability edge. """ path = path.expanduser() path.parent.mkdir(parents=True, exist_ok=True) serialized = json.dumps(payload, ensure_ascii=False, indent=2) + "\n" temp_name: str | None = None try: with tempfile.NamedTemporaryFile( mode="w", encoding="utf-8", dir=path.parent, prefix=f".{path.name}.", suffix=".tmp", delete=False, ) as stream: temp_name = stream.name stream.write(serialized) stream.flush() os.fsync(stream.fileno()) Path(temp_name).replace(path) directory_flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) directory_flags |= getattr(os, "O_DIRECTORY", 0) directory_descriptor = os.open(path.parent, directory_flags) try: os.fsync(directory_descriptor) finally: os.close(directory_descriptor) finally: if temp_name is not None: Path(temp_name).unlink(missing_ok=True)