Plan and designs after ADR 0193, 0195 and 0198: bundles are launched and the runtime is their bus; the manager's daemon is a long-running bundle; the console's five tools

The dated note on ADR 0183 now rests on ADR 0193 and 0198 rather than on a bundle having no way to
call: the manager starts every exchange by the operator's direction, through mesh/ask. To-be 40's
WP4 no longer waits on a record — ADR 0198 is it — and the live proofs count the console's five
tools (ADR 0195).
This commit is contained in:
jochen
2026-10-03 23:41:38 +02:00
parent 88fd7d9739
commit baf82b1cdb
4 changed files with 37 additions and 32 deletions
@@ -152,18 +152,19 @@ the node is bound to, and refuses with a notification otherwise.
| An unservable binding refuses rather than lends | a manager test: a worker bound to a dead licence is answered with a refusal, never another licence's token |
| A switch through the console changes the token on the node and nothing in the answer is a token | a live check on one workstation |
> **The mechanism changed — 2026-10-03, by [ADR 0192](0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md).**
> **The mechanism changed — 2026-10-03, by [ADR 0193](0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md)
> and [ADR 0198](0198-a-modules-long-running-code-is-launched-by-the-node-runtime-and-reaches-the-bus-through-it.md).**
> What stands: one manager holding the seat, one rotation source, a token sealed to the receiving
> module's key on request/reply and never an event, the agent module alone writing what the agent
> reads, the identity guard, the host knowing nothing. What moved: the agent module's code is now a
> tools bundle the node's runtime serves ([ADR 0175](0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md),
> [ADR 0188](0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md)),
> and a bundle has no bus credential of its own and answers calls rather than making them (ADR 0192's
> consequences). So **the manager starts every exchange**: it asks each bound node's agent module for
> its public key, hands it a token, asks it for a login waiting to be adopted, and reconciles every node
> on a schedule — which is what "the agent module asks the seat for its current token" and "offers the
> grant to the manager" in the decision above now mean in practice. The manager's own process needs a
> bus credential to make those calls, which is the question design 38's WP4c leaves to a record.
> reads, the identity guard, the host knowing nothing. What moved: both modules' code is bundles the
> node's runtime launches over stdio and is the bus for — `mesh/ask` for a call made on the module's
> behalf, `mesh/publish` and `mesh/subscribe` beside it — so neither holds a bus credential of its own.
> The manager's refresh and visits are a long-running bundle the control node's runtime launches. And,
> by the operator's direction, **the manager starts every exchange**: it asks each bound node's agent
> module for its public key, hands it a token, asks it for a login waiting to be adopted, and reconciles
> every node on a schedule — which is what "the agent module asks the seat for its current token" and
> "offers the grant to the manager" in the decision above now mean in practice. The agent module could
> ask through its runtime; it does not need to.
## References
@@ -124,8 +124,8 @@ the playbooks in the record.
**Other tool servers** a person wants on every machine, or on one, are a declared setting of this module
— mesh layer or node layer — rendered into the same managed file. The person sets them with the
controller's `settings` verb on this module, so the list stays declared state; a tool of this module
cannot set it, because a bundle calls nothing (ADR 0192). The agent's own HTTP-only constraint for managed servers applies; a person's local
controller's `settings` verb on this module, so the list stays declared state; the list is the operator's
choice, set where every setting is set. The agent's own HTTP-only constraint for managed servers applies; a person's local
command-based servers stay their own, in their own file.
**The entry's name is `mesh`.** The hand-made entry both workstations carry today is named after this
@@ -157,9 +157,9 @@ decides it; to-be 39 is the manager's half. This module:
the file matches what was handed over — by fingerprint, never by value.
Switching is the seat's `switch` verb, asked through the console; this module only applies what it is
handed. *2026-10-03:* every exchange is started by the manager, because a tools bundle answers calls and
has no bus credential to make them ([ADR 0192](../../02-DECISIONS/0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md),
ADR 0183's dated note). The tool names follow the catalogue's `<module>_<verb>` form.
handed. *2026-10-03:* every exchange is started by the manager, by the operator's direction (ADR 0183's dated
note); this module is a bundle the node's runtime launches over stdio and answers what it is asked
([ADR 0193](../../02-DECISIONS/0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md)). The tool names follow the catalogue's `<module>_<verb>` form.
## 6. Scope, settings and the order of assignment
@@ -169,7 +169,7 @@ extra tool servers. **Prerequisite:** the manager holds its seat and has adopted
**Order:** the manager assigned and a refresh observed; the console's provision in the catalogue; this
module on one workstation; the six predecessor files and the hand-made console entry removed there; a
new session read to confirm it sees the mesh's instruction file, the console's tools under `mesh`, and
new session read to confirm it sees the mesh's instruction file, the console's five tools under `mesh`, and
its licence; then the rest.
## 7. The package
@@ -193,7 +193,7 @@ installer is rejected: it puts a self-updating binary under the person's home, i
| a switch asked of the seat through the console changes the licence and the token on the node; no tool answer and no log line holds a token | ADR 0183 |
| the API-key binding writes nothing under the home and the agent authenticates through the helper | ADR 0183 |
| the console's provision resolves by co-location; a machine without the console refuses the module by name | ADR 0027, ADR 0152 |
| a new session on the assigned workstation lists the console's tools under `mesh` and answers "which node am I" from the instruction file | the exit of the build |
| a new session on the assigned workstation lists the console's five tools under `mesh` ([ADR 0195](../../02-DECISIONS/0195-the-meshs-tools-are-found-by-address-not-announced-whole.md)) and answers "which node am I" from the instruction file | the exit of the build |
## What this does not settle
@@ -74,8 +74,8 @@ Carried from the predecessor, where each rule was earned by an incident:
## 4. Handing a token to a node
**The manager starts every exchange** (ADR 0183's dated note of 2026-10-03): the agent module is a
tools bundle, which answers and calls nothing. The manager asks each bound node's module for its public
**The manager starts every exchange** (ADR 0183's dated note of 2026-10-03), by `mesh/ask` through the
runtime that launched it ([ADR 0198](../../02-DECISIONS/0198-a-modules-long-running-code-is-launched-by-the-node-runtime-and-reaches-the-bus-through-it.md)). The manager asks each bound node's module for its public
key the first time and keeps it. From then on:
- **On rotation**, the manager calls `claude-code.apply@<node>` on every node bound to the rotated
@@ -23,11 +23,15 @@ packages, their order, their sizes and their proofs, and is wrong the moment it
It is the shape [design 38](38-building-the-operators-machine.md) gives the operator's machine.
*Revised 2026-10-03, after design 38's WP1–WP4b ran:* the node's tool runtime is live on all four
machines, tools are bundles it serves and each is given only the words its artifact declares, and a
bundle has no bus credential of its own. Three things in the first version of this plan changed with
that: the wait on design 38's WP3 is over; the agent module calls nothing, so the manager starts every
exchange (ADR 0183's dated note); and the manager's own process now waits on a different question,
named under WP4.
machines, tools are bundles it serves and each is given only the words its artifact declares, every
bundle is a child the runtime launches over stdio and is the bus for
([ADR 0193](../../02-DECISIONS/0193-every-bundle-the-runtime-serves-is-launched-and-the-runtime-knows-no-language.md),
[ADR 0198](../../02-DECISIONS/0198-a-modules-long-running-code-is-launched-by-the-node-runtime-and-reaches-the-bus-through-it.md)),
and the console offers five tools over addresses
([ADR 0195](../../02-DECISIONS/0195-the-meshs-tools-are-found-by-address-not-announced-whole.md)). What changed
in this plan: the wait on design 38's WP3 is over; the manager starts every exchange, by the operator's
direction (ADR 0183's dated note); and the manager's daemon is a long-running bundle the runtime launches,
which ADR 0198 decided the same day — nothing in this plan waits on another record.
## How this is built, and where it is run
@@ -52,8 +56,8 @@ Measured 2026-10-03 on the four machines and in the repositories.
| escalation | passwordless `sudo` for the operator account on all four — a fact about the machines, checked by nobody | how the agent module writes its managed directory under `/etc` |
| the agent itself | installed on all four, at four different versions, all above the one the managed tool-server key needs | declared as the module's package |
| a bundle's words | paths and constants written with `${dir:…}` and `${port:…}` only; a fact the mesh knows reaches a bundle as a file whose path is a word | the agent module's facts file and settings file |
| a bundle calling a tool | **not possible**: a bundle answers calls; it holds no bus credential | the manager starts every exchange |
| a module's own long-running process with a bus credential | **undecided** — design 38's WP4c names it as the question its next record answers | the manager's daemon (WP4) |
| a bundle calling a tool | `mesh/ask` through the runtime that launched it (ADR 0198); no bundle holds a bus credential | how the manager visits every node |
| a module's own long-running code | a bundle the runtime launches and restarts (ADR 0198); the runtime's subscription and grants built, the modules moving in design 38 WP4c's waves | the manager's daemon (WP3, WP4) |
| the vendor's refresh, the sealed box, the grant file | `anthropic-manager` in the catalogue, built on the controller placement ADR 0183 moved away from; assigned to nothing | its client ported into the manager; the module retired (WP6) |
| the credentials write, the strip, the identity read | `anthropic-consumer` in the catalogue; tested; assigned to nothing | ported into the agent module with its tests; the module retired (WP6) |
| the predecessor's manager and consumer | the lease per licence, the expiry floor, the lineage comparison, the identity guard, three touchpoints, cooldowns | ported as logic with its tests |
@@ -68,7 +72,7 @@ WP3 the manager's code, built and tested (mesh-catalog)
│
WP2 live: one workstation, configuration only — no licence yet ── the first live proof
│
WP4 the manager live on the control node ── waits on design 38 WP4c's record (a process's bus credential)
WP4 the manager live on the control node ── its daemon a long-running bundle (ADR 0198)
WP5 the licence end to end on one workstation
WP6 the rest of the nodes, and the predecessor's remains
```
@@ -127,7 +131,7 @@ contains a token. The catalogue's checks pass.
**Proof, live, on one workstation, configuration only.** Assign the module; set the node's role; push.
The agent's managed directory holds the two files; everything under the person's agent directory is
byte-identical to before; a new session lists the mesh's tools under `mesh` and answers *which node am
byte-identical to before; a new session lists the console's five tools under `mesh` and answers *which node am
I* from the managed instruction file. `claude_code_status` answers through the console. No licence is
touched: the module writes the credentials file only when it is handed a token.
@@ -136,7 +140,7 @@ touched: the module writes the credentials file only when it is handed a token.
*mesh-catalog. Two to three days.*
**What is written**, as design 39 says: the manifest (the seat and its verbs, a database, a `secret`
for the key the grants are encrypted with, a tools bundle, a process bundle for the daemon, settings
for the key the grants are encrypted with, a tools bundle and a long-running bundle for the daemon, both launched by the runtime, settings
with defaults); the store's migrations; the refresh with its plan, lease, floor and cadence as pure
functions; the vendor client from `anthropic-manager`; adoption from a file and from a node's waiting
login with the identity guard; usage and its threshold; the visit — key, hand-over, waiting login — per
@@ -149,9 +153,9 @@ node's key.
## WP4 — The manager live on the control node
*The live mesh. Half a day.* **Waits on design 38 WP4c's record** — how a module's own long-running
process is given a bus credential and its subscriptions — because the daemon must call the agent module
on every node. Until that record exists, nothing in this plan works around it: no tool container, no
*The live mesh. Half a day.* The daemon is a long-running bundle the control node's runtime launches
(ADR 0198); it calls each node's agent module by `mesh/ask`. If the runtime's half of ADR 0198 is not
yet live on the control node when this package starts, this package waits for it: no tool container, no
credential copied by hand.
**Order.** Assign the manager on the control node; push. Adopt the API key from a file there. Adopt the