Publish one complete generation =============================== A reader should never see half an updated site. This is a publication property. It is separate from parsing and rendering. The invariant ------------- Let :math:`P` be the published output tree. During preparation, :math:`P` remains unchanged. The next tree :math:`Q` is complete before the commit is decided. The commit journal names the output and the records that belong with it. **Preparation can fail.** The host abandons the unfinished generation. **A decided commit can be interrupted.** The next build finishes or restores it from the journal. It does not guess from a staging directory's name. .. graphviz:: :caption: The durable journal separates preparation from a decided commit. :alt: Prepare and flush, save journal, switch output, replace records, then remove journal. digraph commit { graph [rankdir=TB, bgcolor="transparent", pad="0.3"]; node [shape=box, style="rounded,filled", fillcolor="#edf5f2", color="#216553", fontname="Helvetica", fontcolor="#16382f"]; edge [color="#216553"]; prepare [label="Prepare Q\nrender + complete + flush"]; journal [label="Save durable journal\ncommit is decided"]; switch [label="Switch output generation"]; records [label="Replace manifest and environment"]; settle [label="Flush names\nremove journal and previous records"]; prepare -> journal -> switch -> records -> settle; } Why the cache is outside the output ----------------------------------- A directory exchange moves everything inside the publication directory. A journal placed inside it would move during the very operation it describes. Its location would cease to be stable when recovery needed it most. Guidedog keeps records in a stable directory outside the publication tree. A custom output uses a sibling cache for this reason. Durability and visibility ------------------------- Flushing file contents is not the same as flushing directory names. The algorithm accounts for both before removing the journal. Platforms differ in how directories are exchanged. The recovery protocol is designed around those differences. See ``lib/project/commit.odin`` and ``lib/project/publish.odin`` for the implementation. This protects the project publication. It is not a distributed transaction with an external hosting provider. Copying a successful build to a server is another operation, owned by the deployment tool.