docs(chord): dependency model: hostAddress

This commit is contained in:
Mario Zechner 2026-10-29 07:37:56 +00:00
parent 5ec2418820
commit 373fbcc706
3 changed files with 48 additions and 46 deletions

View file

@ -166,22 +166,22 @@ and a reload that removes a type sends `gone`. Both go.
A request goes to one place, and the address decides which. For a `local` type, the place is this
host. For a `remote` type, the consumer computes the address from the params with its own contract's
placement function (design §3): `Notes { session: "S1" }` is placed on `Session { id: "S1" }`. If that is this host's
`hostAddress` function (design §3; `placement` until 2026-10-29): `Notes { session: "S1" }` is placed on `Session { id: "S1" }`. If that is this host's
address, the request goes here; otherwise over the route for that kind, or over the parent link.
Today the code checks something else first: whether the type is registered here. A type placed on this host but not
registered yet is sent over the parent link, which is wrong twice. Sol's example: the server has address `Server`,
the catalog type is placed on `Server`, and no facet serves it yet. Today's `Placement.reference` sends the server's
the catalog type is placed on `Server`, and no facet serves it yet. Today's `Placement.reference` (`host/placement.ts`) sends the server's
own request over a parent link the server never had. And when the catalog plugin is installed later, nothing wakes
that request, because it was never registered as waiting here.
:::flow wide | Placement by address. The destination follows from the address alone; only then is the provider found there checked.
:::flow wide | The destination by address. The destination follows from the address alone; only then is the provider found there checked.
row "Where" accent
box addr "the request's address" "from the consumer's own placement function" accent
box addr "the request's address" "from the consumer's own `hostAddress`" accent
box here "here" "a local type, or this host's address"
box away "a route or the parent" "every other address" blue
row "Then" muted
box check "check the provider here" "served? fitting version? authorize, own placement"
box check "check the provider here" "served? fitting version? authorize, own host address"
box hold "hold over the path" "the provider host checks it the same way" blue
arrow addr -> here
arrow addr -> away
@ -189,13 +189,14 @@ arrow here -> check
arrow away -> hold
:::
The rule, from the reviews (Sol B1, Astra F1): placement never looks at what is registered when the type names an
The rule, from the reviews (Sol B1, Astra F1): the destination never depends on what is registered when the type names an
address. A request placed here whose provider is missing is **unbound here**, waiting for the name. A version check
compares the consumer with the provider actually selected, never with a same-name registration on the consumer's own
host (today `#assertRoute` does that before placement, so worker W1 serving `Notes` v1 rejects a `Notes` v2 request
host (today `#assertRoute` does that before choosing the destination, so worker W1 serving `Notes` v1 rejects a `Notes` v2 request
placed on W2, which serves v2).
Every `remote` type declares its placement (owner, 2026-10-29). Until then `remote()` allowed leaving it out, a
Every `remote` type declares its `hostAddress` (owner, 2026-10-29, who also renamed `placement` to it). Until then
`remote()` allowed leaving it out, a
leftover of slice 3a, which built remote objects over one link before host kinds existed; such a type went "here if
served, otherwise the parent", which needed its own fallback and a re-placement when a tab that loads before it
connects gets its first parent link (Opus, Sol). Opus and Fable proposed making it required; the owner agreed.
@ -203,7 +204,7 @@ connects gets its first parent link (Opus, Sol). Opus and Fable proposed making
## What the check finds
Once placed, the provider found there is checked: served, a fitting version (the current one or an accepted older one,
with the fingerprint computed from the provider's own history), `authorize`, and the provider's own placement check.
with the fingerprint computed from the provider's own history), `authorize`, and the provider's own host-address check.
The request is then **bound** (to an object here, or to a hold over a path), or **unbound** with a reason:
| The check finds | The request | Shows |
@ -211,7 +212,7 @@ The request is then **bound** (to an object here, or to a hold over a path), or
| a fitting provider | bound | its object's state |
| this host has not published its facets yet | unbound `unpublished` | `loading` |
| nobody serves the name at its address | unbound `not_served` | `failed { waiting }` |
| no fitting version, a fingerprint that differs at the same version, a placement the provider computes elsewhere | unbound `version` | `failed { waiting }` |
| no fitting version, a fingerprint that differs at the same version, a host address the provider computes elsewhere | unbound `version` | `failed { waiting }` |
| the registry is served, but its first `compose`, or the reader's version mapping, threw | unbound `compose` | `failed { waiting }` |
| the provider host is installing, and the hold does not fit its current code | unbound `installing`, at the provider | `loading` |
| the path has no link (a drop, a route resolving) | waits on the path | `loading` |
@ -598,9 +599,9 @@ has natives (§21), as for any reload.
## A type that moved
A plugin can move a type from the worker to the server by changing its placement. A consumer's request carries the
A plugin can move a type from the worker to the server by changing its `hostAddress`. A consumer's request carries the
address its own code computed, so the provider appearing on the server cannot wake it: the request is not waiting
there. The old host answers `not_served`; the consumer's own reload, which brings the new placement, makes a new
there. The old host answers `not_served`; the consumer's own reload, which brings the new `hostAddress`, makes a new
request. The model adds no redirect: moving state between hosts is a deliberate migration, not something Chord guesses.
## Rollouts across hosts
@ -1216,7 +1217,7 @@ scenarios against five drafts; the catalog in the chapters before this one is a
| R18, the boundary | "live" means every dependency was live at the end of activation | the dependency check is the boundary: after it, a dependency leaving `live` is treated as after live |
| `self.get` of a missing `local` type | throws in the factory: `broken` | unbound `not_served`: `failed { waiting }`, woken by the publication that serves it |
| a remote hold the provider cannot serve | refused `broken`; the dependent polls by backoff | refused and kept at the provider, re-run at its publication; `failed { waiting }` |
| design §3, placement | "served here" decides "here"; `placement` optional on `remote()` | the address decides; every remote type declares its placement (owner, 2026-10-29) |
| design §3, the destination | "served here" decides "here"; `placement` optional on `remote()` | the address decides; every remote type declares its `hostAddress`, renamed from `placement` (owner, 2026-10-29) |
| the start barrier, `pendingLoad` | holds wait for all of `load` | holds wait only for the publication; the barrier is (a) or (b) |
| S2, a registry reader newer than its provider | `broken` | `failed { waiting, version }` |
| S3, a registry without a value | `transient`, woken at the first value only | `failed { waiting }`, woken at every transition to usable |
@ -1314,14 +1315,14 @@ A needs W's B, B needs S's C; W's hold for C waits for S's whole `load`, which w
code (`host.get`, `host.hold`, `host.registry`), a link's peer (`hold`). **It ends only when its holder ends it** (the
attempt ends, the call settles, `release()`, a getter gives up, the peer's link or origin closes, revocation, the
holding host closes), never because its provider is missing, went away or does not fit.
- **Placement by address** (round 1): a `local` type goes here; a `remote` type with a placement goes to the address
its placement (computed from the consumer's own contract) gives: here if that is this host's address, whether served
- **The destination by address** (round 1): a `local` type goes here; a `remote` type goes to the address its
`hostAddress` (computed from the consumer's own contract) gives: here if that is this host's address, whether served
here or not, else over the route for that kind or the parent (design §3). Every `remote` type declares
its placement (owner, 2026-10-29: the optional placement of slice 3a is removed, and with it the fallback "here if
its `hostAddress` (owner, 2026-10-29: the optional `placement` of slice 3a is removed and the field renamed, and with it the fallback "here if
served, otherwise the parent" and its re-placement at the first parent link). A hold arriving for an address that is not this host's is relayed or
refused (`invalid/placement`) as today; a relay never captures a hold because it serves the same name.
refused (`invalid/host_address`) as today; a relay never captures a hold because it serves the same name.
- **Then the selected provider is checked** (served, version or accepted version and fingerprint, `authorize`, the
provider's own placement check). Version checks never look at a same-name registration elsewhere.
provider's own host-address check). Version checks never look at a same-name registration elsewhere.
- **The publication gate:** a request made on this host, or arriving on its links, before the host's first
publication (§6) is not placed yet; it shows `loading` and is placed by the publication. The gate lasts only for the
synchronous setups, never for activation, so it cannot deadlock.
@ -1332,7 +1333,7 @@ A needs W's B, B needs S's C; W's hold for C waits for S's whole `load`, which w
| a fitting provider | bound (to the object here, or to the hold over a path) |
| not published yet | unbound `unpublished`: `loading` |
| nobody serves the name at its address | unbound `not_served`: `failed { waiting }` |
| no fitting version, a fingerprint that differs at the same version, a placement the provider computes elsewhere (code skew) | unbound `version`: `failed { waiting }` |
| no fitting version, a fingerprint that differs at the same version, a host address the provider computes elsewhere (code skew) | unbound `version`: `failed { waiting }` |
| the registry is served, but its first `compose` (or the reader's version mapping) threw | unbound `compose`: `failed { waiting }` |
| the provider host is installing a revision and the hold does not fit its current code | unbound `installing` at the provider: `loading` |
| the path has no link (a drop, a route resolving) | on the path: `loading` |
@ -1646,7 +1647,7 @@ ring that never existed, `/tmp/model/sol-probe4.log`).
R18 (dependency failures `waiting`, no backoff, the deadline paused while parked, the dependency check as boundary,
wakes on every change, an ended dependency breaks), S2 and S3 (`waiting`, woken at every usable value), slice 8's
last-good rule (dropped when a contribution leaves), §3's placement table (by address; the publication gate), §6 (the
last-good rule (dropped when a contribution leaves), §3's destination table (by address; the publication gate), §6 (the
simultaneous-cycle gap: (A) one narrowed deadline or (B) the probe), §7 (`host.hold`, getters, calls), §21 (no `gone` on
removal; a dropped version unbinds only its requests; installs never await activations; rollout without revision
fields; the reload handover), the start barrier (R17, W6), `FailureCause` (+ `waiting`), `loading`/`failed` with the

View file

@ -314,26 +314,27 @@ and a reload that removes a type sends <code>gone</code>. Both go.</p>
<h3 id="the-address-decides-where">The address decides where</h3>
<p>A request goes to one place, and the address decides which. For a <code>local</code> type, the place is this
host. For a <code>remote</code> type, the consumer computes the address from the params with its own contract&#39;s
placement function (design §3): <code>Notes { session: &quot;S1&quot; }</code> is placed on <code>Session { id: &quot;S1&quot; }</code>. If that is this host&#39;s
<code>hostAddress</code> function (design §3; <code>placement</code> until 2026-10-29): <code>Notes { session: &quot;S1&quot; }</code> is placed on <code>Session { id: &quot;S1&quot; }</code>. If that is this host&#39;s
address, the request goes here; otherwise over the route for that kind, or over the parent link.</p>
<p>Today the code checks something else first: whether the type is registered here. A type placed on this host but not
registered yet is sent over the parent link, which is wrong twice. Sol&#39;s example: the server has address <code>Server</code>,
the catalog type is placed on <code>Server</code>, and no facet serves it yet. Today&#39;s <code>Placement.reference</code> sends the server&#39;s
the catalog type is placed on <code>Server</code>, and no facet serves it yet. Today&#39;s <code>Placement.reference</code> (<code>host/placement.ts</code>) sends the server&#39;s
own request over a parent link the server never had. And when the catalog plugin is installed later, nothing wakes
that request, because it was never registered as waiting here.</p>
<figure class="fig wide"><svg viewBox="0 0 720 242" width="100%" role="img" aria-label="Placement by address. The destination follows from the address alone; only then is the provider found there checked." xmlns="http://www.w3.org/2000/svg" style="font-family:'Avenir Next','Helvetica Neue',Helvetica,Arial,sans-serif;max-width:760px"><defs><marker id="f2m" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#7b7468"/></marker><marker id="f2a" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#b4472f"/></marker><marker id="f2b" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#2e6a8a"/></marker></defs><text x="16" y="22" font-size="10" fill="#b4472f" text-anchor="start" font-weight="600" letter-spacing="2">WHERE</text><text x="16" y="155" font-size="10" fill="#7b7468" text-anchor="start" font-weight="600" letter-spacing="2">THEN</text><rect x="19" y="36" width="210" height="55" rx="4" fill="#fff" stroke="#b4472f" stroke-width="1.5"/><text x="124" y="54.5" font-size="11" fill="#2a2723" text-anchor="middle">the request's address</text><text x="124" y="68.5" font-size="9.5" fill="#7b7468" text-anchor="middle">from the consumer's own placement</text><text x="124" y="81" font-size="9.5" fill="#7b7468" text-anchor="middle">function</text><rect x="255" y="36" width="210" height="55" rx="4" fill="#fff" stroke="#c9bfae"/><text x="360" y="60.8" font-size="11" fill="#2a2723" text-anchor="middle">here</text><text x="360" y="74.8" font-size="9.5" fill="#7b7468" text-anchor="middle">a local type, or this host's address</text><rect x="491" y="36" width="210" height="55" rx="4" fill="#fff" stroke="#2e6a8a" stroke-width="1.5"/><text x="596" y="60.8" font-size="11" fill="#2a2723" text-anchor="middle">a route or the parent</text><text x="596" y="74.8" font-size="9.5" fill="#7b7468" text-anchor="middle">every other address</text><rect x="137" y="169" width="210" height="55" rx="4" fill="#fff" stroke="#c9bfae"/><text x="242" y="187.5" font-size="11" fill="#2a2723" text-anchor="middle">check the provider here</text><text x="242" y="201.5" font-size="9.5" fill="#7b7468" text-anchor="middle">served? fitting version? authorize,</text><text x="242" y="214" font-size="9.5" fill="#7b7468" text-anchor="middle">own placement</text><rect x="373" y="169" width="210" height="55" rx="4" fill="#fff" stroke="#2e6a8a" stroke-width="1.5"/><text x="478" y="187.5" font-size="11" fill="#2a2723" text-anchor="middle">hold over the path</text><text x="478" y="201.5" font-size="9.5" fill="#7b7468" text-anchor="middle">the provider host checks it the same</text><text x="478" y="214" font-size="9.5" fill="#7b7468" text-anchor="middle">way</text><path d="M229 63.5 L253 63.5" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M124 32 Q360 -12 596 32" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M360 91 L242 167" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M596 91 L478 167" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/></svg><figcaption><span class="fignum">Figure 2.</span> Placement by address. The destination follows from the address alone; only then is the provider found there checked.</figcaption></figure>
<p>The rule, from the reviews (Sol B1, Astra F1): placement never looks at what is registered when the type names an
<figure class="fig wide"><svg viewBox="0 0 720 231" width="100%" role="img" aria-label="The destination by address. The destination follows from the address alone; only then is the provider found there checked." xmlns="http://www.w3.org/2000/svg" style="font-family:'Avenir Next','Helvetica Neue',Helvetica,Arial,sans-serif;max-width:760px"><defs><marker id="f2m" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#7b7468"/></marker><marker id="f2a" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#b4472f"/></marker><marker id="f2b" viewBox="0 0 8 8" refX="7" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" fill="#2e6a8a"/></marker></defs><text x="16" y="22" font-size="10" fill="#b4472f" text-anchor="start" font-weight="600" letter-spacing="2">WHERE</text><text x="16" y="144" font-size="10" fill="#7b7468" text-anchor="start" font-weight="600" letter-spacing="2">THEN</text><rect x="19" y="36" width="210" height="44" rx="4" fill="#fff" stroke="#b4472f" stroke-width="1.5"/><text x="124" y="55.3" font-size="11" fill="#2a2723" text-anchor="middle">the request's address</text><text x="124" y="69.3" font-size="9.5" fill="#7b7468" text-anchor="middle">from the consumer's own `hostAddress`</text><rect x="255" y="36" width="210" height="44" rx="4" fill="#fff" stroke="#c9bfae"/><text x="360" y="55.3" font-size="11" fill="#2a2723" text-anchor="middle">here</text><text x="360" y="69.3" font-size="9.5" fill="#7b7468" text-anchor="middle">a local type, or this host's address</text><rect x="491" y="36" width="210" height="44" rx="4" fill="#fff" stroke="#2e6a8a" stroke-width="1.5"/><text x="596" y="55.3" font-size="11" fill="#2a2723" text-anchor="middle">a route or the parent</text><text x="596" y="69.3" font-size="9.5" fill="#7b7468" text-anchor="middle">every other address</text><rect x="137" y="158" width="210" height="55" rx="4" fill="#fff" stroke="#c9bfae"/><text x="242" y="176.5" font-size="11" fill="#2a2723" text-anchor="middle">check the provider here</text><text x="242" y="190.5" font-size="9.5" fill="#7b7468" text-anchor="middle">served? fitting version? authorize,</text><text x="242" y="203" font-size="9.5" fill="#7b7468" text-anchor="middle">own host address</text><rect x="373" y="158" width="210" height="55" rx="4" fill="#fff" stroke="#2e6a8a" stroke-width="1.5"/><text x="478" y="176.5" font-size="11" fill="#2a2723" text-anchor="middle">hold over the path</text><text x="478" y="190.5" font-size="9.5" fill="#7b7468" text-anchor="middle">the provider host checks it the same</text><text x="478" y="203" font-size="9.5" fill="#7b7468" text-anchor="middle">way</text><path d="M229 58 L253 58" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M124 32 Q360 -12 596 32" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M360 80 L242 156" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/><path d="M596 80 L478 156" fill="none" stroke="#7b7468" marker-end="url(#f2m)"/></svg><figcaption><span class="fignum">Figure 2.</span> The destination by address. The destination follows from the address alone; only then is the provider found there checked.</figcaption></figure>
<p>The rule, from the reviews (Sol B1, Astra F1): the destination never depends on what is registered when the type names an
address. A request placed here whose provider is missing is <strong>unbound here</strong>, waiting for the name. A version check
compares the consumer with the provider actually selected, never with a same-name registration on the consumer&#39;s own
host (today <code>#assertRoute</code> does that before placement, so worker W1 serving <code>Notes</code> v1 rejects a <code>Notes</code> v2 request
host (today <code>#assertRoute</code> does that before choosing the destination, so worker W1 serving <code>Notes</code> v1 rejects a <code>Notes</code> v2 request
placed on W2, which serves v2).</p>
<p>Every <code>remote</code> type declares its placement (owner, 2026-10-29). Until then <code>remote()</code> allowed leaving it out, a
<p>Every <code>remote</code> type declares its <code>hostAddress</code> (owner, 2026-10-29, who also renamed <code>placement</code> to it). Until then
<code>remote()</code> allowed leaving it out, a
leftover of slice 3a, which built remote objects over one link before host kinds existed; such a type went &quot;here if
served, otherwise the parent&quot;, which needed its own fallback and a re-placement when a tab that loads before it
connects gets its first parent link (Opus, Sol). Opus and Fable proposed making it required; the owner agreed.</p>
<h3 id="what-the-check-finds">What the check finds</h3>
<p>Once placed, the provider found there is checked: served, a fitting version (the current one or an accepted older one,
with the fingerprint computed from the provider&#39;s own history), <code>authorize</code>, and the provider&#39;s own placement check.
with the fingerprint computed from the provider&#39;s own history), <code>authorize</code>, and the provider&#39;s own host-address check.
The request is then <strong>bound</strong> (to an object here, or to a hold over a path), or <strong>unbound</strong> with a reason:</p>
<table>
<thead>
@ -359,7 +360,7 @@ The request is then <strong>bound</strong> (to an object here, or to a hold over
<td><code>failed { waiting }</code></td>
</tr>
<tr>
<td>no fitting version, a fingerprint that differs at the same version, a placement the provider computes elsewhere</td>
<td>no fitting version, a fingerprint that differs at the same version, a host address the provider computes elsewhere</td>
<td>unbound <code>version</code></td>
<td><code>failed { waiting }</code></td>
</tr>
@ -721,9 +722,9 @@ object then; Sol and Astra caught it: the object, its documents, its jobs and it
fine. Only the requests on version 1 become unbound <code>version</code>. The object&#39;s own plugin reload still restarts it if it
has natives (§21), as for any reload.</p>
<h3 id="a-type-that-moved">A type that moved</h3>
<p>A plugin can move a type from the worker to the server by changing its placement. A consumer&#39;s request carries the
<p>A plugin can move a type from the worker to the server by changing its <code>hostAddress</code>. A consumer&#39;s request carries the
address its own code computed, so the provider appearing on the server cannot wake it: the request is not waiting
there. The old host answers <code>not_served</code>; the consumer&#39;s own reload, which brings the new placement, makes a new
there. The old host answers <code>not_served</code>; the consumer&#39;s own reload, which brings the new <code>hostAddress</code>, makes a new
request. The model adds no redirect: moving state between hosts is a deliberate migration, not something Chord guesses.</p>
<h3 id="rollouts-across-hosts">Rollouts across hosts</h3>
<p>A rollout installs a revision on the server first, then on the workers, then on the tabs (design §21). Between those
@ -1929,9 +1930,9 @@ owner&#39;s decisions.</li>
<td>refused and kept at the provider, re-run at its publication; <code>failed { waiting }</code></td>
</tr>
<tr>
<td>design §3, placement</td>
<td>design §3, the destination</td>
<td>&quot;served here&quot; decides &quot;here&quot;; <code>placement</code> optional on <code>remote()</code></td>
<td>the address decides; every remote type declares its placement (owner, 2026-10-29)</td>
<td>the address decides; every remote type declares its <code>hostAddress</code>, renamed from <code>placement</code> (owner, 2026-10-29)</td>
</tr>
<tr>
<td>the start barrier, <code>pendingLoad</code></td>
@ -2099,15 +2100,15 @@ code (<code>host.get</code>, <code>host.hold</code>, <code>host.registry</code>)
attempt ends, the call settles, <code>release()</code>, a getter gives up, the peer&#39;s link or origin closes, revocation, the
holding host closes), never because its provider is missing, went away or does not fit.</p>
</li>
<li><p><strong>Placement by address</strong> (round 1): a <code>local</code> type goes here; a <code>remote</code> type with a placement goes to the address
its placement (computed from the consumer&#39;s own contract) gives: here if that is this host&#39;s address, whether served
<li><p><strong>The destination by address</strong> (round 1): a <code>local</code> type goes here; a <code>remote</code> type goes to the address its
<code>hostAddress</code> (computed from the consumer&#39;s own contract) gives: here if that is this host&#39;s address, whether served
here or not, else over the route for that kind or the parent (design §3). Every <code>remote</code> type declares
its placement (owner, 2026-10-29: the optional placement of slice 3a is removed, and with it the fallback &quot;here if
its <code>hostAddress</code> (owner, 2026-10-29: the optional <code>placement</code> of slice 3a is removed and the field renamed, and with it the fallback &quot;here if
served, otherwise the parent&quot; and its re-placement at the first parent link). A hold arriving for an address that is not this host&#39;s is relayed or
refused (<code>invalid/placement</code>) as today; a relay never captures a hold because it serves the same name.</p>
refused (<code>invalid/host_address</code>) as today; a relay never captures a hold because it serves the same name.</p>
</li>
<li><p><strong>Then the selected provider is checked</strong> (served, version or accepted version and fingerprint, <code>authorize</code>, the
provider&#39;s own placement check). Version checks never look at a same-name registration elsewhere.</p>
provider&#39;s own host-address check). Version checks never look at a same-name registration elsewhere.</p>
</li>
<li><p><strong>The publication gate:</strong> a request made on this host, or arriving on its links, before the host&#39;s first
publication (§6) is not placed yet; it shows <code>loading</code> and is placed by the publication. The gate lasts only for the
@ -2134,7 +2135,7 @@ synchronous setups, never for activation, so it cannot deadlock.</p>
<td>unbound <code>not_served</code>: <code>failed { waiting }</code></td>
</tr>
<tr>
<td>no fitting version, a fingerprint that differs at the same version, a placement the provider computes elsewhere (code skew)</td>
<td>no fitting version, a fingerprint that differs at the same version, a host address the provider computes elsewhere (code skew)</td>
<td>unbound <code>version</code>: <code>failed { waiting }</code></td>
</tr>
<tr>
@ -2565,7 +2566,7 @@ once it is live; the run count keeps the object as today.</li>
<h3 id="12-what-changes-in-the-design">12. What changes in the design</h3>
<p>R18 (dependency failures <code>waiting</code>, no backoff, the deadline paused while parked, the dependency check as boundary,
wakes on every change, an ended dependency breaks), S2 and S3 (<code>waiting</code>, woken at every usable value), slice 8&#39;s
last-good rule (dropped when a contribution leaves), §3&#39;s placement table (by address; the publication gate), §6 (the
last-good rule (dropped when a contribution leaves), §3&#39;s destination table (by address; the publication gate), §6 (the
simultaneous-cycle gap: (A) one narrowed deadline or (B) the probe), §7 (<code>host.hold</code>, getters, calls), §21 (no <code>gone</code> on
removal; a dropped version unbinds only its requests; installs never await activations; rollout without revision
fields; the reload handover), the start barrier (R17, W6), <code>FailureCause</code> (+ <code>waiting</code>), <code>loading</code>/<code>failed</code> with the

View file

@ -61,14 +61,14 @@ A needs W's B, B needs S's C; W's hold for C waits for S's whole `load`, which w
code (`host.get`, `host.hold`, `host.registry`), a link's peer (`hold`). **It ends only when its holder ends it** (the
attempt ends, the call settles, `release()`, a getter gives up, the peer's link or origin closes, revocation, the
holding host closes), never because its provider is missing, went away or does not fit.
- **Placement by address** (round 1): a `local` type goes here; a `remote` type with a placement goes to the address
its placement (computed from the consumer's own contract) gives: here if that is this host's address, whether served
- **The destination by address** (round 1): a `local` type goes here; a `remote` type goes to the address its
`hostAddress` (computed from the consumer's own contract) gives: here if that is this host's address, whether served
here or not, else over the route for that kind or the parent (design §3). Every `remote` type declares
its placement (owner, 2026-10-29: the optional placement of slice 3a is removed, and with it the fallback "here if
its `hostAddress` (owner, 2026-10-29: the optional `placement` of slice 3a is removed and the field renamed, and with it the fallback "here if
served, otherwise the parent" and its re-placement at the first parent link). A hold arriving for an address that is not this host's is relayed or
refused (`invalid/placement`) as today; a relay never captures a hold because it serves the same name.
refused (`invalid/host_address`) as today; a relay never captures a hold because it serves the same name.
- **Then the selected provider is checked** (served, version or accepted version and fingerprint, `authorize`, the
provider's own placement check). Version checks never look at a same-name registration elsewhere.
provider's own host-address check). Version checks never look at a same-name registration elsewhere.
- **The publication gate:** a request made on this host, or arriving on its links, before the host's first
publication (§6) is not placed yet; it shows `loading` and is placed by the publication. The gate lasts only for the
synchronous setups, never for activation, so it cannot deadlock.
@ -79,7 +79,7 @@ A needs W's B, B needs S's C; W's hold for C waits for S's whole `load`, which w
| a fitting provider | bound (to the object here, or to the hold over a path) |
| not published yet | unbound `unpublished`: `loading` |
| nobody serves the name at its address | unbound `not_served`: `failed { waiting }` |
| no fitting version, a fingerprint that differs at the same version, a placement the provider computes elsewhere (code skew) | unbound `version`: `failed { waiting }` |
| no fitting version, a fingerprint that differs at the same version, a host address the provider computes elsewhere (code skew) | unbound `version`: `failed { waiting }` |
| the registry is served, but its first `compose` (or the reader's version mapping) threw | unbound `compose`: `failed { waiting }` |
| the provider host is installing a revision and the hold does not fit its current code | unbound `installing` at the provider: `loading` |
| the path has no link (a drop, a route resolving) | on the path: `loading` |
@ -393,7 +393,7 @@ ring that never existed, `/tmp/model/sol-probe4.log`).
R18 (dependency failures `waiting`, no backoff, the deadline paused while parked, the dependency check as boundary,
wakes on every change, an ended dependency breaks), S2 and S3 (`waiting`, woken at every usable value), slice 8's
last-good rule (dropped when a contribution leaves), §3's placement table (by address; the publication gate), §6 (the
last-good rule (dropped when a contribution leaves), §3's destination table (by address; the publication gate), §6 (the
simultaneous-cycle gap: (A) one narrowed deadline or (B) the probe), §7 (`host.hold`, getters, calls), §21 (no `gone` on
removal; a dropped version unbinds only its requests; installs never await activations; rollout without revision
fields; the reload handover), the start barrier (R17, W6), `FailureCause` (+ `waiting`), `loading`/`failed` with the