claude-code: an agent proposes a shared instruction section, and every node takes it only on the operator's warrant (hq ADR 0274)
mesh/merge-gate fail: builds claude-code → ace, g14, novox, shanks; no bus step; a manifest the change touches fails the module check: claude-code uses the…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate fail: builds claude-code → ace, g14, novox, shanks; no bus step; a manifest the change touches fails the module check: claude-code uses the…
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
Shared instructions were the terminal's alone since hq issue 340, because the tool runner cannot tell an agent from the operator. The operator channel now proves who answered, so an agent may propose a section; each node proves the router's warrant against the exact text itself and keeps what it approved in its own file, so nothing written to the bus becomes active.
This commit is contained in:
@@ -67,6 +67,7 @@ must see, a node that joins later included — kept, so it carries no secret eit
|
||||
| a person ran `/login` here | the credentials file gains a refresh token this module never writes; its next report shows it, and the licence manager asks `claude_code_grant` for it, giving its key — the one time a refresh token leaves the node, for the manager to adopt by refreshing it |
|
||||
| what this node should hold | the licence manager's `bindings` state, this node's key; on a newer generation this module asks `anthropic-licence-manager.current` for its token, sealed to the key it sends, and writes it access-token-only — so the agent here never refreshes. A node that was off reads its key when it is back |
|
||||
| an MCP server registered through this module before registering was refused (hq issue 340) | a key in the module's `servers` state — `all.<server>` for every node, `<node>.<server>` for one; every node watches it and renders what applies to it, a node's own entry over the one for every node. A node that joins later, or was off, reads the whole current set at start; unregistering is a delete. Nothing adds a key any more: a new tool server is the operator's, in the `mcp_servers` setting at the controller's terminal |
|
||||
| a proposed instruction section (hq ADR 0274) | a key in the module's `proposals` state per proposal, the ask published on `operator-channel` under this module's name, and the router's record of it read under that name alone; what a node approved is its own file, never the bus |
|
||||
| the agent's configuration (hq ADR 0216) | a key in the module's `config` state per registration — `mesh.<kind>.<name>` for every node, `node.<node>.<kind>.<name>` for one, `home.<node>.<kind>.<name>` for one account's own directory — the item and its files in one value, at most 256 KiB. Every node watches it and renders what applies to it, a node item over a mesh item of the same kind and name. A hook, settings, or an item that would run something by itself is never taken, whenever it was put there (hq issue 340) |
|
||||
|
||||
## The mesh's tools first (hq ADR 0245)
|
||||
@@ -142,6 +143,23 @@ files, each a list of lines. For example `mesh-cli settings set claude-code '{"i
|
||||
registered before; what the operator writes there is not judged, but an item that is not well formed is left out and
|
||||
said in the render's answer. What was registered before is still rendered and may be unregistered.
|
||||
|
||||
**An instruction section may be proposed for the operator's approval** (hq ADR 0274). An agent calls
|
||||
`claude_code_instructions_propose` with a scope (`mesh`, or `node` and the nodes), a name and the text — a rule, a
|
||||
hand-over, the context a later session needs — or with `remove` for a section approved before. Nothing becomes
|
||||
active: the proposal is kept in the module's `proposals` state and the operator is asked through the operator
|
||||
channel (`operator-channel`, hq ADR 0259) with Approve and Decline, both at the level approve, so only a channel that
|
||||
proves who answered (Telegram) carries either. The phone shows the whole text when it is short and every line may
|
||||
leave the mesh, else its first lines and a fingerprint; the whole text is read at the controller's terminal with
|
||||
`mesh-cli ask claude-code claude_code_proposals '{"id": "<id>"}'`. Decline, or no answer within a day, discards it.
|
||||
**Every node proves the approval itself**: it reads the router's own record of the ask under this module's name,
|
||||
composes the ask again from the proposal and holds the warrant to it (the same ask digest, the option's bound act,
|
||||
the text's digest, in time), and only then writes the section into its own `approved.json`, which the managed
|
||||
instruction file renders under "Instructions the operator approved". A proposal is decided once per node; a record
|
||||
deleted from the bus removes nothing. Refused: shell lines, front matter, an `@` file reference, anything shaped like
|
||||
a secret, more than 16 KiB, a name the terminal sets, and — at once, naming the terminal's line — whenever no channel
|
||||
that proves its sender is there. The controller's hand-act log records each warrant once (`warranted`), read from the
|
||||
router's record. The text is never logged.
|
||||
|
||||
The home scope is registered through the tools **only where the home belongs to an agent account of its own**
|
||||
(hq ADR 0266, issue 340), and only for the node whose module serves the call. Where the agent runs as the operator,
|
||||
the home is the operator's own `~/.claude`, whose rules and skills load in every session the operator starts, and
|
||||
|
||||
Reference in New Issue
Block a user