📘 reference — overview/guide, not tied to a code symbol
Validation by Beadloom
doc_sync— same source assync-check.
Atomic IO (component) ​
Internal building block of the infrastructure domain.
Source: src/beadloom/infrastructure/atomic_io.py
Overview ​
A domain-agnostic, dependency-free primitive that writes a YAML file with crash-safe integrity, so a partial write can never replace the source-of-truth graph YAML (.beadloom/_graph/*.yml, and the onboarding services.yml / imported.yml / rules.yml / config.yml) with a truncated or half-written file.
write_yaml_atomic serializes the data, writes it to a temporary file in the same directory as the target, flushes + fsyncs it, then commits with os.replace — an atomic rename on POSIX. A reader therefore always observes either the complete old file or the complete new file, never a half-written one. On any failure the temp file is removed and the prior target is left untouched (the rename is the single commit point).
It lives in infrastructure (the lowest layer) so that every graph-YAML writer — the graph loader/patcher, the services link patcher, and the onboarding scaffolders — routes through one crash-safe commit point instead of a raw open(..., 'w') / yaml.dump -> write_text that can truncate a file on interruption.
What it guarantees (integrity, not durability) ​
write_yaml_atomic guarantees integrity, not full durability — the two are deliberately distinct, and the boundary is documented here so callers do not over-rely on it.
- Integrity (guaranteed). A crash, exception, or interruption at any point during the write never leaves a torn file in place. The target is always one complete YAML document: either the prior contents or the new contents. This holds because the bytes are fully written and
fsynced to a temp file before the singleos.replacecommit, and a failed/interrupted write removes the temp file and leaves the target untouched. - Durability boundary (not guaranteed). The parent directory entry is not
fsynced after the rename. The file's data is flushed, but the directory metadata recording the rename is left to the OS. So across an OS-level or power crash immediately after a commit, the filesystem may roll the rename back and the reader sees the prior complete file — the latest commit can be lost, but the file is never corrupted. This is an acceptable, deliberate trade-off: the invariant we need is integrity (the graph YAML is always parseable), and a lost last write is recovered by re-running the command. Full directory-fsyncdurability is a possible future hardening if a use case ever needs it.
Public surface ​
write_yaml_atomic(path, data, **dump_kwargs)— serializedatawithyaml.dump(data, **dump_kwargs)and write it topathatomically. Thedump_kwargs(e.g.sort_keys=False,default_flow_style=False,allow_unicode=True) are passed through verbatim so the emitted bytes are identical to the prior direct-dump call-site (behavior-preserving).
Collaborators ​
graph/loader.py— patches nodesummary/sourceback to disk.services/commands/index_ops.py— thelinkadd/remove patcher.onboarding/scanner/bootstrap.py— writesservices.yml+config.yml.onboarding/scanner/doc_classify.py— writesimported.yml.onboarding/scanner/rules_gen.py— writesrules.yml.onboarding/doc_generator.py— the_patch_docs_fieldwriter.
Component doc (BDL-060 S1 / G6). Public surface verified against
atomic_io.py. Behavior-preserving: identical output bytes vs the prior directyaml.dump->write_textpath. Integrity is guaranteed; the parent-directory is notfsynced, so the last commit may be lost (never corrupted) across an OS/power crash — a documented boundary, not a defect.