From c2e1504f19271c8da551db20effd1cbdd5ebba98 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Sun, 30 Aug 2026 17:39:59 -0700 Subject: [PATCH] docs(mirror): record the measured real-machine state of the mirror lifecycle The step-7 lifecycle had never been watched on a real machine, which is what both remaining children of dig_ecosystem#3166 were gated on. It was measured against a `dign` built from 9eb8fbd and it works: `mirror bond-states` answers `state: "known"` with epoch 104 and a complete, truthful empty inventory, and the pass publishes. Recorded in DEVELOPMENT_LOG.md rather than left in a ticket comment because three of the facts are the kind a future lane re-derives at the cost of a full build: that a `chain_unreadable` reading is only evidence about the binary that produced it, that `entries: []` under `state: "known"` is a truth rather than a fabricated zero, and that `chain_unreadable` is today the catch-all for five structurally different states of which two are terminal. Also records, from the same session, the two independent blockers on a create/reclaim proof: this node caches zero capsules, so there is no (store, root) to bond, and it has no publishable advertise URL (#426). Refs #433, #412, #411 --- CHANGELOG.md | 8 -------- Cargo.toml | 2 +- DEVELOPMENT_LOG.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbb735ec..d2bb32fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,6 @@ All notable changes to this project are documented here. This project adheres to [Semantic Versioning](https://semver.org) and [Conventional Commits](https://www.conventionalcommits.org). -## [0.179.0] - 2026-08-31 - -### Features -- **mirror:** Construct the bond-state observation (#412 step 7) (#419)- **mirror:** Operator-scoped $DIG CAT coin selector for mirror creates (#421) (#423)- **mirror:** Advertised URLs this node can be fetched at (#426) (#430)- **dht:** Attach the untrusted mirror-coin pointer to the provider announce (#431)- **mirror:** Wire a production broadcaster for the mirror lifecycle (#424) (#434) - -### Bug Fixes -- **wallet:** Honest refusal reasons when no signer is configured (#410) (#432) - ## [0.172.0] - 2026-08-30 ### Features diff --git a/Cargo.toml b/Cargo.toml index 696fd3f7..92da2121 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ edition = "2021" # the ROOT manifest (`[workspace.package].version`), so it MUST be set here for a # release to fire (§3.6). The library crates (dig-node-core/dig-runtime/dig-wallet) # keep their own independent versions — only the released binary tracks the workspace version. -version = "0.179.0" +version = "0.179.1" # Release hardening, matching digstore: keep integer-overflow checks ON in release. # The node parses untrusted serialized input and does offset/length arithmetic over diff --git a/DEVELOPMENT_LOG.md b/DEVELOPMENT_LOG.md index 200b691f..1c2716f7 100644 --- a/DEVELOPMENT_LOG.md +++ b/DEVELOPMENT_LOG.md @@ -4,6 +4,52 @@ High-signal realizations from debugging/development: non-obvious cross-system co sharp edges, and gotchas. Concise durable facts with context — NOT a change diary. See `CLAUDE.md` §4.5 for the maintenance contract (a curator periodically re-verifies + prunes). +## The mirror lifecycle observes correctly on a real machine, and `entries: []` there is a truth (#433) + +Measured 2026-08-31 on Windows 11 against a `dign` built from `9eb8fbd` (0.179.0), run with +`RUST_LOG=mirror=debug`. The whole step-7 lifecycle is exercised at bring-up and answers: + +``` +$ dign mirror bond-states --json +{"ok":true,...,"state":"known","entries":[],"complete":true,"cursor":null, + "locked_dig_base_units":0,"epoch":104} + +INFO mirror: the mirror lifecycle is live: this node may create and reclaim collateral +DEBUG mirror: mirror pass complete epoch=104 bonds=0 locked_dig_base_units=0 reclaimed=0 created=0 +``` + +Three durable facts, each of which has already cost a wrong conclusion once: + +- **A `chain_unreadable` reading is only evidence about the binary that produced it.** #433 was + filed from installed `dign 0.172.0` = `6e8bfa7`, and step 7 (`5df3e34`) is not an ancestor of it. + That binary carried the stub, which answers `unknown { chain_unreadable }` by construction and + runs no pass at all. Before treating a mirror reading as a symptom, check + `git merge-base --is-ancestor $(git rev-list -n1 )`. + +- **`entries: []` and a fabricated zero look identical on the wire, and are told apart by `state`.** + `state: "known"` with `complete: true` and a named epoch is a published observation from a pass + that genuinely read the chain — here, truthfully, that this node has never created a mirror coin. + The `Err` arms in `spawn_mirror_passes` deliberately do NOT publish, precisely so an empty page + can never mean "the read failed". Resolving a mirror `unknown` by returning an empty page would + destroy that distinction; it is a claim about money. + +- **`chain_unreadable` is the catch-all for five structurally different states**, only one of which + is a chain read failing: `enable_chain_sync == false` (no task is ever spawned), no operator + wallet (the task `return`s *permanently*), no epoch in force, `chain_source()` `Err`, and + `pass.run()` `Err`. The first two are terminal, not transient, so a node in either answers + `chain_unreadable` forever while its chain reads work perfectly — which sends an operator to + inspect peers that are fine. None was in force in this reading. Naming them needs a wider + `MirrorBondStatesUnknownReason`, which lives in `dig-node-control-interface` and is therefore a + release-first change rather than a dig-node edit. + +**What a mirror CREATE still needs, measured the same session.** Two independent blockers, so the +#412 step-8 create/reclaim proof is not reachable by configuration alone: this node caches zero +capsules (`observe_disk` reads `cache_list_cached`, and both pinned stores hold `capsule_count: 0`), +so there is no `(store, root)` to bond; and it has no publishable advertise URL (#426), so `create` +refuses by name ahead of any chain read. The advertise slot is not a formality to fill in — its +value is written to chain as a claim about where this node can be fetched, so an invented URL is a +permanent false advertisement on a money artifact. + ## Two workflows assemble one release, so whichever finishes first used to publish it half-built (#335) A stable `vX.Y.Z` release of dig-node is built by **two** workflows that neither know about nor wait