From 546a18a20ef92024986d07ca6699ca4e5f2c345f Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 4 Nov 2026 00:46:25 +0100 Subject: [PATCH] =?UTF-8?q?Design=2025:=20answer=20the=20third=20review=20?= =?UTF-8?q?(views=20families=20on=20the=20old=20streams=20sections=20under?= =?UTF-8?q?=20a=20record=20extending=20ADR=200595=20=C2=A710,=20the=20tool?= =?UTF-8?q?=20runner's=20first-view=20tools=20on=20the=20mesh=20MCP=20serv?= =?UTF-8?q?er,=20the=20running=20judge=20takes=20the=20process-subject=20f?= =?UTF-8?q?orm=20in)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The assigner must start on a fresh mesh before the bus module can answer, so its new stream stays on its old section; a new indexer can never judge its own manifest, so the running judge must accept the form first. The glossary stops counting the mesh MCP server's tools. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig --- 00-META/glossary.md | 2 +- 03-DESIGN/01-to-be/25-the-bus-on-nats.md | 62 ++++++++++++++++-------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/00-META/glossary.md b/00-META/glossary.md index 4d33e14a..73d59d19 100644 --- a/00-META/glossary.md +++ b/00-META/glossary.md @@ -858,7 +858,7 @@ asking, never the act. **Decided by** ADR 0152, 0175, 0234, 0259, 0272, 0383, 03 **Uses:** operator, person, node, module, seat, tool (Module), proof and identity (Identity and access), release (Delivery). - **mesh MCP server** — the endpoint on a node's loopback through which every agent and person on that - node reaches the mesh: the MCP server named `mesh`, with its five tools `mesh_overview`, + node reaches the mesh: the MCP server named `mesh`, with its tools, among them `mesh_overview`, `mesh_machine`, `mesh_search`, `mesh_describe` and `mesh_call`. It is the tool runner's loopback mode, not a module of its own. "Console" suggested a terminal or a shell, and the module `mesh-console` it once named no longer exists; "the tool bridge" and "the brain" named the predecessor's program. diff --git a/03-DESIGN/01-to-be/25-the-bus-on-nats.md b/03-DESIGN/01-to-be/25-the-bus-on-nats.md index 688824ee..c9a7a3a7 100644 --- a/03-DESIGN/01-to-be/25-the-bus-on-nats.md +++ b/03-DESIGN/01-to-be/25-the-bus-on-nats.md @@ -757,12 +757,12 @@ vault as an own secret: JetStream create and update under modules' names only (s no manifest form today (the assigner serves its seat verbs as tools); the form is new in mesh-sdk's manifest types and rides the milestone's one rebuild. Which part issues these subjects' grants first is not yet decided: the grants part composes every grant from the manifests, and is itself one of these readers, so its own first view - cannot wait on a grant it has not composed (an open point, tracked on issue 1966). Under the same point: which - judge takes in the indexer's and the assigner's own new manifests, which use that form. Every manifest of the - merge is judged by the indexer that runs, the old build, and mesh-sdk's strict decoding refuses a field it does - not know (research 082, its Findings for question 5), so the running judge would refuse the new form; whether the - form rides an earlier release the running judge already decodes, or the new indexer judges its own manifest, is - not decided by a record. The owner answers at once from what it holds, as soon as its process is + cannot wait on a grant it has not composed (an open point, tracked on issue 1966). **The judge that runs takes the + form in.** Every manifest of the merge is judged by the indexer that runs, the old build, before any new build + runs, so a new indexer can never judge its own manifest; and mesh-sdk's strict decoding refuses a field it does not + know (research 082, its Findings for question 5). So the running judge accepts the process-subject form before the + indexer and the assigner use it, decided in a record of this milestone extending ADR 0615 §3 (to be proposed), and + design 51's *When the group is pushed* holds the push until the judge that runs accepts it. The owner answers at once from what it holds, as soon as its process is connected and before it has its own first view of any other part, with the revision of its state it answered at, so the indexer and the assigner, each asking the other at start, never wait on each other (§4). The reader then follows the owner's declared events, each carrying the revision of the state it follows, and never asks the verb @@ -770,19 +770,32 @@ vault as an own secret: JetStream create and update under modules' names only (s families of their own, apart from the indexer's `manifest-refused` and `manifest-accepted` and the assigner's `put`: the indexer's `indexer.views` and the assigner's `assigner.views`, one event per changed key with its bucket, key and revision and the key's value whole, or a delete mark for a key removed, so a reader keeps its - picture from the events alone and asks the verb only on a gap (ADR 0615 §5). Each family is kept seven days and - capped at 256 MiB, dropping its oldest when full (the template events); a reader that misses a dropped event sees - the gap in revisions and asks once more. The indexer declares `indexer.views` in its old `streams` section, its - own kept data staying there (ADR 0595 §10 names the indexer among the foundation). The assigner is not named - there and is touched in this milestone, so it asks for `assigner.views` in the new form, as bus state of the - template events in its `requires` (ADR 0595 §1, §11). A waiter on an existing event, `manifest-accepted` or the + picture from the events alone and asks the verb only on a gap (ADR 0615 §5). **Both families are declared in + their owners' old `streams` sections**, each an entry with `max-age-days` 7 and `max-mib` 256: the old section keeps + a stream by limits, which drops its oldest when full (only a work queue refuses the new instead), so a reader that + misses a dropped event sees the gap in revisions and asks once more. The indexer's own kept data stays on the old + sections (ADR 0595 §10 names it among the foundation); the assigner's goes beside its existing `streams` entry + `placement`, under a record of this milestone extending ADR 0595 §10's foundation (to be proposed) to the parts + the bus module's own composition, placement, build or delivery needs before it can answer: the assigner, the tool + runner, the builder, the checker, mesh-config and the vault. **The size, an estimate**: read on the bus on + 2026-11-04, the buckets the readers read hold about 3 MiB of current values at the indexer (its manifests about + 5 KiB a value) and about 1.5 MiB at the assigner (its wants about 0.25 KiB a value). The milestone's one mesh-sdk + rebuild rewrites every module's keys, up to three times in its window (design 51 *How many builds*), so a week of + it is some 20 MiB on `indexer.views` and some 10 MiB on `assigner.views` with ordinary merges added, each well + under its 256 MiB. Each event carries one value whole, the largest today a manifest of tens of KiB, under the bus's + largest message, 1 MiB (the bus server's `max_payload`); an owner whose value with its event would pass it emits + the key's revision alone, as a gap, so the reader asks the first view once, and the owner writes its finding + naming the key. + A waiter on an existing event, `manifest-accepted` or the assigner's `put`, never wakes on them. **When an owner's revisions go back**: should an owner's state be rebuilt by the bus module's `recreate`, its revisions start again; a reader that hears a revision lower than the one it holds takes it as a gap and asks the first view again, and keeps what that answer says, whatever revision it held before. A `recreate` that could not keep the data answers empty at revision 0, so the grants part keeps its list in force (below): a login revoked meanwhile stays until the owner's first change, and the grants part's - first-view condition stays raised meanwhile, naming the owner and the empty answer, cleared by an answer above - revision 0. A reader that starts while its owner is down raises a + first-view condition stays raised meanwhile, naming the owner, the empty answer and the operator's step: let the + owner write its state again from its sources (the indexer by taking each module in again, `indexer_take_in`; the + assigner by its next composition of the wants), then ask the grants part's first view again, + `grants_first_view_again`. It is cleared by an answer above revision 0. A reader that starts while its owner is down raises a condition naming the owner and the verb past its bound and keeps asking until it answers, never reading the owner's state instead; once it had its first view, it keeps working on what it heard (§6). The bound is longer than an owner's start (two minutes), so a normal start, readers and owners coming up together, notifies nobody; @@ -791,9 +804,13 @@ vault as an own secret: JetStream create and update under modules' names only (s force until an answer at a revision above 0. Each reader's tools say the owner, verb and revision its first view holds, when it asked and when it was answered (a read tool), and ask the first view again by hand (a re-read tool, recorded as a hand act): the grants part's `grants_first_views` and `grants_first_view_again`, the tool runner's - `runtime_first_views` and `runtime_first_view_again`, the indexer's `indexer_first_views` and - `indexer_first_view_again`, and the assigner's `assigner_first_views` and `assigner_first_view_again`. The - order of owner before reader is kept by the module graph's served-verb edge for the 19 readers (ADR 0614 §2), and, + `mesh_first_views` and `mesh_first_view_again`, the indexer's `indexer_first_views` and + `indexer_first_view_again`, and the assigner's `assigner_first_views` and `assigner_first_view_again`. The tool + runner's two are tools of the mesh MCP server, beside `mesh_runtimes`, since the tool runner serves its own state + there: the mesh MCP server gains them, and the operator sees them among its tools. **On a fresh mesh** the + assigner starts before any new-form bus state exists and needs no binding of the bus module first: its own state + and `assigner.views` are on its old sections, which the grants part creates, so it answers the indexer, the grants + part and the tool runner their first views while the bus module still waits on it. The order of owner before reader is kept by the module graph's served-verb edge for the 19 readers (ADR 0614 §2), and, for the four, whose verb edges lie on cycles the graph leaves out (ADR 0614 §3), by the owner's answer at once and the reader's wait (ADR 0615 §2). - **Only the owner reaches it** (ADR 0596 §2). The membership grants the owner's account its own entries and no @@ -944,7 +961,10 @@ and the new form are never both used for one local name. During the move the gra sections' entries, so each entry has one creator. The indexer counts the modules on each old section, a tool reads the count, and the judge refuses a section once its count is 0. The foundation's own kept data (the bus module's, the grants part's and the indexer's) stays on the old sections for good and is not counted: those modules cannot -wait for a process that needs them first. +wait for a process that needs them first. A record of this milestone extending ADR 0595 §10's foundation (to be +proposed) adds the parts the bus module's own composition, placement, build or delivery needs before it can answer: +the assigner, the tool runner, the builder, the checker, mesh-config and the vault; their new state and streams of +this milestone go on their old sections too (§ 12.2; design 51 *The move*; design 32). **Readers move after their owners** (ADR 0596 §3). Today 195 `reads` entries in 37 modules read another module's bus state (counted 2026-11-03 02:00). **A correction of fact**: the indexer's and the assigner's state, counted again @@ -965,8 +985,10 @@ issue 1966. | The bus module creates, and the binding follows | live, by tool call: a module asking for a state, a log, objects and a ledger in `requires` receives each binding in its membership, written after `created`, never before; `show` gives each entry's template, settings and fill; a module calling `create` is refused | | The bus module runs whole | one integration test in the nats module's repository that starts the bus module whole against the real bus server: a verdict, then `created`, then the binding in the membership; a restart that catches up a verdict given while it was down; a bucket whose settings differ raises `drifted`, the seat's `apply` of a larger cap clears it with `drift-cleared`; a refused create raises its condition and hands no binding; `recreate` and `drop` without the operator's warrant are refused, and with it act after a stream snapshot; an orphan is listed, raises `orphaned`, and goes only by `drop`; each template at a small cap refuses, events drop the oldest, and `full` is raised at the raise mark and cleared only below the clear mark; `recreated` rewrites the binding and `dropped` removes it; at start the first view from `indexer_bus_state` creates what a verdict given while it was down asked; the older remove tools refuse a new-form entry, naming `drop`'s tool | | A module asking bus state waits for the bus module | the module graph's table test: a manifest with a ledger entry has a requirement edge to the module providing `bus-state`, one without has none (ADR 0614 §5) | -| A foundation part's first view | unit tests of each owner and reader (ADR 0615's How it is checked), as table cases, and these cases of the whole-module integration tests that exist today (mesh-delivery is over its integration budget, so no new test function): the indexer's (`cmd/mesh-delivery-indexer`, its one whole-module test, which the milestone's packages test merges into), the assigner's (`cmd/mesh-delivery-assigner`) and the grants part's (`cmd/mesh-grants`), and the tool runner's in mesh-tools: the owner answers its verb at once from what it holds, with its revision, before its own first view; the reader asks once at start, then only on a gap in revisions; a reader whose owner is down raises its condition only past the bound and never reads the owner's state, and the owner's answer clears it; an empty answer at revision 0 drops no login; an owner's event carries the changed value whole, and a reader applies a put and a delete from the events alone and never asks the verb; a revision lower than the one held makes the reader ask its first view again; an existing waiter on `manifest-accepted` or on the assigner's `put` does not wake on the new families; the read tool shows the revision each reader holds, and the re-read tool asks once and records the hand act. Live, after the delivery: the indexer's count of `reads` entries on the indexer's and the assigner's state reads 0 | -| A foundation part's first view comes within its bound | live, after the delivery: each reader's read tool (`grants_first_views`, `runtime_first_views`, `indexer_first_views`, `assigner_first_views`) shows, for the indexer's and the assigner's verbs, the time from its ask to the owner's answer under the two-minute bound, and no first-view condition raised by the delivery | +| A foundation part's first view | unit tests of each owner and reader (ADR 0615's How it is checked), as table cases, and these cases of the whole-module integration tests that exist today (mesh-delivery is over its integration budget, so no new test function): the indexer's (`cmd/mesh-delivery-indexer`, its one whole-module test, which the milestone's packages test merges into), the assigner's (`cmd/mesh-delivery-assigner`) and the grants part's (`cmd/mesh-grants`), and the tool runner's in mesh-tools: the owner answers its verb at once from what it holds, with its revision, before its own first view; the reader asks once at start, then only on a gap in revisions; a reader whose owner is down raises its condition only past the bound and never reads the owner's state, and the owner's answer clears it; an empty answer at revision 0 drops no login; an owner's event carries the changed value whole, and a reader applies a put and a delete from the events alone and never asks the verb; a revision lower than the one held makes the reader ask its first view again; an existing waiter on `manifest-accepted` or on the assigner's `put` does not wake on the new families; the read tool shows the revision each reader holds, and the re-read tool asks once and records the hand act; in the +assigner's whole-module test, the assigner starts before any new-form bus state exists, with no binding of the bus +module, and the indexer, the grants part and the tool runner each get their first view of it. Live, after the delivery: the indexer's count of `reads` entries on the indexer's and the assigner's state reads 0 | +| A foundation part's first view comes within its bound | live, after the delivery: each reader's read tool (`grants_first_views`, the mesh MCP server's `mesh_first_views`, `indexer_first_views`, `assigner_first_views`) shows, for the indexer's and the assigner's verbs, the time from its ask to the owner's answer under the two-minute bound, and no first-view condition raised by the delivery | | The bus module's first view | cases in the nats module's one integration test: a replayed verdict older than the first view is not applied; an `indexer_bus_state` that does not answer turns the health unhealthy naming it and is asked again on the backoff; a set-aside manifest missing from the first view keeps its `asked` key, an empty `manifest-accepted` removes it; a deleted module's entry, after its empty `manifest-accepted`, is listed by `orphans` and raises `orphaned`, and a set-aside module's entry is neither; `nats_first_view_again` asks at once and records the hand act | | `manifest-accepted` is never lost silently | unit tests of the indexer: a failed publish is published again, and one still failing writes the finding; `indexer_say_accepted` says it again for one module from the verdict held, and refuses a module with no accepted verdict | | Until the identity seat, the caller is the one the tool runner proved | a unit test of the bus module's process: a request on its tool subject naming another caller in its body acts for the proved caller; `drop` without the warrant is refused |