From 9cef0db2d61262395e5b9b9a33126930c20cb4cb Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 28 Oct 2026 17:15:50 +0000 Subject: [PATCH] docs(chord): slice 8 registry failures --- packages/chord/docs/next/decisions.md | 5 +++++ packages/chord/docs/next/slice-8.md | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/chord/docs/next/decisions.md b/packages/chord/docs/next/decisions.md index 825343ec1..3d00c73e7 100644 --- a/packages/chord/docs/next/decisions.md +++ b/packages/chord/docs/next/decisions.md @@ -1742,6 +1742,11 @@ validation and copies the v2 kernel added around Delta. for versioned things: a shared definition (object types, registries) keeps its adapters with the provider; a definition of one owner (documents, tables, `json(...)` columns, jobs) keeps them in itself. Refines Q8's "one authoritative declaration" (the serve is it) and design ยง17's example. +- **Slice 8: registry failures (owner, 2026-10-27: "ok", "agree"):** contributions never fail a registry: a + watchable contribution that fails is left out of the table and reported (`contribution_failed`), back once healed; + a throwing `compose` (the owner's bug) is reported (`registry_failed`), its watches get a `failed` call, and `.value` + keeps the last good composition (before any, it throws). Derives keep `.value` throwing while failed: state must match + its sources, an extension point must stay available. - **The performance and memory bar, and converging reviews (owner, 2026-10-27: "yes"):** supersedes "as good as HEAD in everything" for Chord v2 slices and pi changes. CPU: each hot path (calls, changes, watches, links) within about 5% of HEAD, measured in bursts with alternating processes pinned to one CPU; worse is fixed or goes to the diff --git a/packages/chord/docs/next/slice-8.md b/packages/chord/docs/next/slice-8.md index a30aaa885..f18d456ac 100644 --- a/packages/chord/docs/next/slice-8.md +++ b/packages/chord/docs/next/slice-8.md @@ -62,9 +62,13 @@ await host.root(async (ctx) => (await ctx.get(Notes, { session })).add(note, ctx `contribution_refused { registry, plugin, version }`). - **`compose(table, { report })`:** pure, runs whenever the table changes (a contributor goes live or ends, a contribution that is a watchable changes), in the owner's flush, never inside another owner's commit step (W4); - `report(conflict)` goes to `onError` as `registry_conflict { registry, message, plugins }`. A throwing `compose` - makes the composed value fail: its watches get a `failed` call, `.value` throws the error, the next good compose heals - it ("Failures are watch calls"). + `report(conflict)` goes to `onError` as `registry_conflict { registry, message, plugins }`. +- **Failures (owner, 2026-10-27):** contributions never fail the registry. A contribution that is a watchable and fails + is left out of the table and reported (`contribution_failed { registry, plugin, error }`), the table recomposes without + it, and it is back once it heals. A `compose` that throws (the owner's bug) is reported (`registry_failed { registry, + error }`), the composed value's watches get a `failed` call, and `.value` keeps the last good composition (an extension + point stays available; derives keep their own rule, `.value` throwing while failed); the next good composition + replaces it. Before any good composition `.value` throws the error. - **Without a provider** (the defining plugin is not loaded): the composed value is failed with `unavailable/undeclared` (readers see the error as from a failed reference); contributions wait in the table; its serve heals it.