A node holds the one module it cannot compose and applies the rest, as its shadow already answers (group fix/1126-apply-culprit, issue 1126) #118

Merged
mesh-tools merged 1 commits from fix/1126-apply-culprit into main 2026-10-28 16:34:46 +00:00
Member

Delivery group fix/1126-apply-culprit (mesh-sdk, mesh-host). Issue 1126 notes 102, 105, 106. Found by the review of design 47 L2's seed: merging it switches every node to compose its own modules, and the APPLYING path (frombus.Compose, refuse=nil) refused the whole node on one module's error. On novox (the control-node) de-spiegel's unset config (accepted until L5) would have marked all ~81 modules failed and moved nothing. Second meeting of the kind ‘one module's refusal freezes a node’ (the shadow in seed-8): fixed for the kind.

  • One rule, frombus.composeEach, for both Compose (apply) and Answer (shadow).
  • A held module (compose.Node.Held) keeps what it last applied: none of its own composition is applied; it is carried as it runs (compose.RunsAnyOf, Carried from Scope.Running), including while it leaves the fold.
  • What others read of a held module is what runs; dependsOnHeld composes again with stubs, and a module whose composition differs is held too; if the node's own composition differs, the node is refused.
  • dependents: for every held module, the providers it contributes to are held, and the filter's holder when it listens (cascading).
  • Only a refusal belonging to no single module refuses the node.
    On novox today: de-spiegel, route-proxy and nftables are held (they keep running as now) until de-spiegel's config is declared (L5).
    Cost to measure after delivery: about 7 compositions per pass on novox while held (6-30 s, the reviewer's estimate).

Tests: rows (E)-(H) in answer_rows_test.go and frombus_test.go, each failing first; no new function.
Review: three rounds (a held module leaving the fold lost its resources; providers composed from a stub; a held module's new manifest).

Reviewed-by: rev-apply-culprit@shanks at 0de3006415

Delivery group fix/1126-apply-culprit (mesh-sdk, mesh-host). Issue 1126 notes 102, 105, 106. Found by the review of design 47 L2's seed: merging it switches every node to compose its own modules, and the APPLYING path (frombus.Compose, refuse=nil) refused the whole node on one module's error. On novox (the control-node) de-spiegel's unset config (accepted until L5) would have marked all ~81 modules failed and moved nothing. Second meeting of the kind ‘one module's refusal freezes a node’ (the shadow in seed-8): fixed for the kind. - One rule, frombus.composeEach, for both Compose (apply) and Answer (shadow). - A held module (compose.Node.Held) keeps what it last applied: none of its own composition is applied; it is carried as it runs (compose.RunsAnyOf, Carried from Scope.Running), including while it leaves the fold. - What others read of a held module is what runs; dependsOnHeld composes again with stubs, and a module whose composition differs is held too; if the node's own composition differs, the node is refused. - dependents: for every held module, the providers it contributes to are held, and the filter's holder when it listens (cascading). - Only a refusal belonging to no single module refuses the node. On novox today: de-spiegel, route-proxy and nftables are held (they keep running as now) until de-spiegel's config is declared (L5). Cost to measure after delivery: about 7 compositions per pass on novox while held (6-30 s, the reviewer's estimate). Tests: rows (E)-(H) in answer_rows_test.go and frombus_test.go, each failing first; no new function. Review: three rounds (a held module leaving the fold lost its resources; providers composed from a stub; a held module's new manifest). Reviewed-by: rev-apply-culprit@shanks at 0de30064156a60f14da6081c975b099764bd3ee3
mesh-tools added 1 commit 2026-10-28 16:25:45 +00:00
A module refused alone is held, composed as what runs of it, on the node that applies as in its answer: one rule for both paths (issue 1126)
mesh/delivery merged: source.main moved to novox/mesh-sdk@98f2f2406921
mesh/delivery-group group fix/1126-apply-culprit merged: every member is merged
mesh/check pass 0de30064156a on 7aedd28f01dc | unit 2667 run, 590 kept, 36 skipped | integration 2676 run, 633 kept, 29 skipped | over bound: unit (sl…
0de3006415
The applying path (frombus.Compose) composed with no culprit, so one module's
refusal came back as the whole node's: novox's apply would have refused all its
modules for de-spiegel's unset route names. composeEach is now the one rule
Compose and Answer both follow:
- a module whose stub changes the refusal is held (compose.Node.Held); in the
  applying path a stand-in for a module placed here holds that module; only a
  refusal of no single module refuses the node;
- a held module is composed from what runs of it (compose.Carried of its own
  composition in Running) and carried in the node's own wherever that runs it,
  folded or leaving the fold, so the node's own apply never removes it (issue
  1945 by a new path) and what the others read of it is what runs;
- none of a held module's own composition is in what is applied;
- a module whose composition differs when the held ones are composed as stubs
  is held too; the node's own differing refuses the node;
- since a held module is composed from its new manifest, what reads that
  manifest is held with it: the providers of what it contributes to (the
  proxy its routes) and, when it listens, the filter's holder.

Quick fix weighed: a culprit loop in Compose alone. Thorough, chosen: one
shared function, since the kind met twice (seed-8 shadow, now the apply), and
review rounds 1 and 2 found its leaks.
Author
Member

Delivery novox/mesh-sdk@0de30064156a — merged since 2026-10-28T16:34:47Z

Source — source.main moved to novox/mesh-sdk@98f2f24069. Whether it reached the machines is mesh-delivery-view's, derived from source.main, the wants and the haves.

Group fix/1126-apply-culprit: novox/mesh-host@24c23a1d06, novox/mesh-sdk@0de3006415

  • composed together: pass — the checker's verdict at the members' heads (23be06c61d1b)

Transitions

  • 2026-10-28 16:25 (new) → proposed (announced): novox/mesh-sdk#118's head announced
  • 2026-10-28 16:25 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail; or the check gates no merge (check-gates-merge false)
  • 2026-10-28 16:34 ready → merged (merged): on the trunk its modules follow: merged there

The commit's note under refs/notes/mesh-plan keeps every transition of this change up to its merge: git log --notes=mesh-plan.

<!-- mesh-delivery:view --> **Delivery** `novox/mesh-sdk@0de30064156a` — **merged** since 2026-10-28T16:34:47Z **Source** — source.main moved to novox/mesh-sdk@98f2f2406921. Whether it reached the machines is `mesh-delivery-view`'s, derived from `source.main`, the wants and the haves. **Group** `fix/1126-apply-culprit`: novox/mesh-host@24c23a1d066f, novox/mesh-sdk@0de30064156a - composed together: pass — the checker's verdict at the members' heads (23be06c61d1b) **Transitions** - 2026-10-28 16:25 (new) → proposed (announced): novox/mesh-sdk#118's head announced - 2026-10-28 16:25 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail; or the check gates no merge (check-gates-merge false) - 2026-10-28 16:34 ready → merged (merged): on the trunk its modules follow: merged there The commit's note under `refs/notes/mesh-plan` keeps every transition of this change up to its merge: `git log --notes=mesh-plan`.
mesh-tools merged commit 98f2f24069 into main 2026-10-28 16:34:46 +00:00
mesh-tools deleted branch fix/1126-apply-culprit 2026-10-28 16:34:47 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-sdk#118