Skip to content

deploy replaces the record: readback.Fold is bounded to the current lifetime, one writ deploy invocation across scopes #922

Closed

Description

@David-Noble-at-work

Epic: #451 · Feature: #762 The writ lifecycle surface · Schedule: #916, lane 1, PR A

The ruling

Deploy replaces the record (#913, 2026-09-22). Each
deploy is one lifetime; its receipts stack and fold naturally through the upgrades and reconciliations that follow,
until a later deploy replaces it or a decommission removes it. Ruled 2026-09-23 for this lane: a lifetime is the
whole writ deploy invocation, across scopes
-- not one per scope graph.

What the code does today

readback.Fold (cmd/writ/writ/readback/readback.go:143) reads the run index, collects every writ run the machine
has ever made, sorts them by time, and folds them all onto one map of targets, the newest receipt per target
winning. That map is what deploy's pre-flight (occupantIsOurs) and reconcile read as the record. A file the
previous deploy placed and the current one does not is therefore still in the record, and reconcile reports it as
orphan (target present, source gone) or missing (target absent) -- the 52 rows found on danoble-ud24-1.local
on 2026-09-22 after a layer reorganization.

The change

  1. The record is the current lifetime: the receipts of the most recent writ deploy invocation, across every scope
    it ran, plus the upgrade and reconcile receipts written after it. Earlier lifetimes are not folded.
  2. A writ deploy invocation is therefore identifiable as one lifetime in the store -- the run index carries what
    groups a deploy's per-scope receipts with the upgrades and reconciliations that follow, and distinguishes them
    from the previous deploy's. The representation is this lane's to design and state in
    5.1-reconciliation.md.
  3. Pre-flight and reconcile read the bounded fold; nothing else changes in what they do with it (lane 2 changes
    what reconcile says).
  4. Earlier lifetimes stay in the store, unread. Pruning them is lane 13's design, not this lane's.

Acceptance

  • a receipt from a previous lifetime is not in the record: TestFold_DeployReplacesTheRecord; the layer-journey scenario step 3.5 (2026-09-23)
  • an upgrade after a deploy is in the same lifetime: TestFold_UpgradeStacksOnTheDeploy
  • a deploy's scopes are one lifetime: deploy mints once per invocation and appends per scope (TestLifetime_RoundTrip appends two graphs to one lifetime; the deploy fixture is single-scope)
  • 5.1-reconciliation.md "The lifetime in the store" and "What the fold does" (2026-09-23)
  • both VMs: on the Linux VM the personal reorganization of 2026-09-22 had left 52 missing rows; after one --conflict=replace deploy and a plain deploy, reconcile reports 166 linked, 1 copied, no missing, no orphan; Windows 71 linked (2026-09-23)

Plan and design documents

Kind Document
Plan arrives with the branch
Design docs/architecture/5.1-reconciliation.md, 10-command-line-interface.md §3.1

Activity

  1. David-Noble-at-work commented on Sep 24, 2026

    @David-Noble-at-work
    ContributorAuthor

    Landed in PR #940 (merged 2026-09-24T06:13:59Z). The pull request body carried no closing keyword, so this is closed by hand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Epic:WritDeploymentwrit deployment: layers, adoption, and drifttaskImplementation work item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions