Commit Graph
115 Commits
Author SHA1 Message Date
jschoubben 9afb287b9d Merge branch 'feat/47-G-fix11-a1' into feat/47-G-fix11-hrun 2026-11-12 05:43:50 +01:00
jschoubben c2710f52dd MV1: move contracts and sdk under modules/, importers follow
The delivery repository's contracts and SDK live under modules/ as
mesh-delivery-contracts and mesh-delivery-sdk, their Go module paths
renamed to match the folders (the TypeScript names already did), and
every importer in mesh-delivery, mesh-catalog, mesh-host, mesh-tools
and mesh-sdk follows in the same group: a design as it should be, one
path per module, checked by the group's check building every importer.

Builds: design 47 G §427, §88

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:09:56 +01:00
jschoubben ac3422f914 H-17: the node-engine's own name is read from its applied record or first composing
Discovery, the finding writer and the vault login names read it; no fixed name.

Builds: design 47 G §527, §634 (A-149)
2026-11-12 04:58:28 +01:00
jschoubben c6df8fa20f G §683: a start composes the modules whose kept want and entry it holds before its other inputs are read
The node's own record comes from the node-engine's statement of itself, taken in memory with no bus.

Builds: design 47 G A-117, A-120, §683, A-95
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 01:12:06 +01:00
jschoubben 054ca5a6b3 G §614: the node-engine writes the finding entry-not-found for a fingerprint the catalog half holds none of
Builds: design 47 G A-117, §614, A-15, A-95
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 01:07:53 +01:00
jschoubben dc1aee51d9 W13.5: the node agent asks mesh-recovery for a restore point before a form change and restores it at a revert
Before a move across a kept data's form change the node agent asks snapshot-kept and waits for the ended of its own act; at a revert it stops the newer build (Env.Stop), asks kept-points, asks restore-kept with the snapshot of the point of the form and fingerprint it reverts from, waits for restored, applies the reverted build, and calls the point's catch-up as the module's tool through the tool runner. The wait is in the have (ask-at, act), bounded by a bounds key of the state bounds (recovery-wait-minutes, 90), and each ending is read as the table of 560 says. The manifest consumes mesh-recovery's ended and restored and invokes its three verbs.

Builds: design 47 G §296, §297, §554, §555, §560, §630, §631, §632, §633, A-77, A-92, A-98, A-108
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 00:16:31 +01:00
jschoubben cf378f9a25 G §421, §683: the node-engine reads the entry its want names by fingerprint and keeps its entries and wants
The node's own composer reads the catalog half through meshcatalogclient's Entries cache over its own calls of
mesh-catalog's verb entry, and no longer watches or reads the indexer's modules, manifests and verdicts or the
builder's builds: a module's manifest is its entry's, each artifact's reference is made from the digest its want's
part names (artifact-store://<module>/<artifact>/blobs/<digest>, A-50). A want whose entry is asked or not found is
held, its have the phase held with a detail opening entry-asked: or entry-missing: naming the fingerprint. The
entries and wants it composes from are kept in composed-<node> (entry.<digits> and want.<module>), written before
the composition that uses them, read at start before anything is asked, a kept want standing until the wants'
live read answers, and dropped when nothing names them. The shadow keeps its reads (G §628).

The node grant gains the verb entry and the running stream's consumer calls; OverNATS hears the running stream
as the link's session does.

Builds: design 47 G §421, §683, §614, §628, A-47, A-50
2026-11-11 23:55:50 +01:00
jschoubben 5173f2a31c W13.8: the node-engine fetches a kept build through the build node's kept-artifact, the node taken from the want's kept-on
A want that names a node in kept-on, for an artifact its parts name, is fetched through kept-artifact of that node's build seat and
read as an object on the bus, checked against the digest; with no kept-on it is fetched from the store, and the builder's builds
are read no more (the apply hook, the fetch and the object read from bc8fbc7, its node and fingerprint from the want).

Builds: design 47 G §271, §526, §421 (A-50)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-11 23:39:36 +01:00
jschoubben 602ed830e9 H-15: the apply guard and the yields read the node-engine's module from the entry claiming its seat
The module is the one whose catalog entry claims node-engine, else the one this node heard run the build its own
fingerprint names; no name is fixed in the guard or in the compose.

Builds: design 47 G §364, §527, §428

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 14:05:43 +01:00
jschoubben 45e2b946c7 H-5: the seats a node passes on are decided from what every node said it runs, by SeatsToPassOn's new input
The node follows the node-engine seat's running events (an ordered read of the last message of each subject, then a durable
consumer), keeps what each node runs by `at`, acts on none until the first read ended, and hands the composer each node's
heard build with the manifest read by the event's digest; compose resolves the passes through catalogue.SeatsToPassOn
(heard, entries) with the trunk's entry for a node that said nothing.

Builds: design 47 G §199, §249, §459, §536, §556

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 13:58:33 +01:00
jschoubben 26581d87ed H-3: the node-engine says composed, running and capabilities-changed on the seat's subjects
Builds: design 47 G §260, §227, §226, §177, §309, §404

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 12:05:18 +01:00
jschoubben 4af6c274b8 S4: an unread seat list holds a module before its build is read
On ace, a node-engine left on its bootstrapped seat list could not find the
artifact store's seat, refused avahi's archive reference and with it the whole
pass, so the seat-list hold never ran and every module said "reaches no
artifact store". While the list is unread, a placed module whose seats are not
all bootstrapped is now held as it runs before anything of its build is read
(frombus.Scope.Held), its reason names the bootstrapped seats the node holds,
and a pass refused whole says the unread list first (issue 1966).

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-10 00:40:53 +01:00
jschoubben 3dc4307aec The node's words for a want it composes nothing of are said once per reason, and proved on the live paths (issue 1966)
The said-once keys no longer hold where the indexer's picture stands; a module composed from the manifest for want of a done
build is named in Pass.Unmade; the agent's wait is told once per want and again after the composition was there; the two tests
are folded into existing ones.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-09 09:04:45 +01:00
jschoubben 5f37a43b91 The node says why it composes nothing of a want, and hands again what its agent waits for (issue 1966)
Every pass names each wanted module it made no composition of, with why (Pass.Unmade, the verb compose, one journal line per
change); a want not taken is said; the agent says once per want that it waits for the composer and why, and tells it, so a
composition the composer believed handed is handed again.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-09 08:58:33 +01:00
jschoubben 5b75e866d0 The composition verb says what holds each held module and the build it would be composed at (issue 1921, milestone 47/G H4)
mesh/delivery closed: a newer head of the same pull request
mesh/delivery-group group feat/registry-milestone checking: 6 of 7 member(s) ready
mesh/check failed (4): unit: git.novox.be/novox/mesh-catalog/checks/gitignored.TestNoProgramABuildLeavesIsC…; and 3 more | 5b75e866d079 on e73aae3686a6
The node's own composition named a held module's why only; it now also says whether its manifest's verdict or this
node-engine's decoder holds it, and at which build, as the input a check's composer reads says it. Said in the held
words, so the node-engine seat's answer keeps its shape.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-07 02:38:18 +01:00
jschoubben 015304f4a3 Fold three tests into existing ones, drive the marker test by channels, keep the last view through set(nil) and drop it once the node is held
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 23:09:00 +01:00
jschoubben 7add29cffe Merge fix/compose-pass-bounded: the composition pass never waits on marking haves
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 22:35:09 +01:00
jschoubben c1b8b9d115 The composition pass never waits on marking haves, and the compose verb answers while a pass runs
The marks of the haves (a refusal, the words a module keeps) read and write each module's have in turn, and each write
walks every have: on a slow bus the pass waited minutes on them (shanks, 2026-11-05 22:22). They now run off the pass,
newest word per kind, each bounded; an ask of compose during a pass is answered at once and queues one more pass.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 22:33:21 +01:00
jschoubben 8717ec76d4 The node-engine follows the module-assignment seat: assignments, not placement; the seat's packages move to mesh-contracts and mesh-delivery (issue 1966)
The state, events and types of the seat mesh-module-assigner say assignments; the legacy node key form is gone from the
reads; the dead seat-verb list of the retired name is deleted. The placement guard and the placed-file sense stay.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 22:08:40 +01:00
jschoubben 2bcc34a59b Node-engine test: a node whose own composition folds the holder of the seat mesh-catalog starts it before the list is read and composes the rest after (ADR 0636 §1; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 16:30:45 +01:00
jschoubben e282e08917 Node-engine: a held own composition that was handed stays handed, as a held module's does (ADR 0636 §1; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 16:28:02 +01:00
jschoubben ae26376a90 Node-engine: while the seat list is unread, the node's own composition lets through the holder of the seat mesh-catalog's resources and accounts over what runs (ADR 0636 §1; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 16:22:15 +01:00
jschoubben 13e2fe14aa Node-engine: logins, signers, enrolment tokens and redeems, and the grants part's sealed user list come from the vault and node-enroller clients and the grants state package; no file imports go/delivery (ADR 0634 §1, §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 15:47:59 +01:00
jschoubben 4bfa94dfef Node-engine: a builder's build, its keys and codec come from the builder's builds package (ADR 0634 §1, §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 15:44:31 +01:00
jschoubben 10852161c9 Node-engine: the catalogue's modules, manifests, verdicts and candidates are the mesh-catalog seat's types and its client's keys and codecs; the composer case is the delivery SDK's, its verdicts and placements raw; the provided module is the private network's (ADR 0634 §1, §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 15:42:34 +01:00
jschoubben c35cc1d9e4 Node-engine: the placement, the wants and the placement candidates are the seats' contract types and the assigner client's keys and codecs; the found tunnel is the placement seat's typed record (ADR 0634 §1, §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 15:34:02 +01:00
jschoubben 7eb7b9fa62 Node-engine: the have, the node's facts, the record, the health report and the data items are the seat's contract types, written through the node-engine client; the interim bridge is gone (Have group, ADR 0634 §1, §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 15:21:48 +01:00
jschoubben 5906e18028 Node-engine: a composition, its codec, digest and keys come from the node-engine client; the candidate answer and its limits from the seat's contract; the declared packages are the engine's own (H-2, H-3, ADR 0634 §1; issue 1966)
The engine's Composed keeps the catalogue's Plan and the declaration types and goes through nodeengineclient's codec; the fingerprint key part is meshcatalogclient's. The candidate answer is nodeengine.CandidateAnswer; the have still holds it through an interim JSON bridge (link.interimAnswers) until the Have group moves.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 15:10:45 +01:00
jschoubben df44d21c82 Node-engine: composition comparison, seals and differing paths are the engine's own package, internal/compositions, with the tests moved from mesh-sdk's delivery (H-1, ADR 0634 §1; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 14:53:06 +01:00
jschoubben dcbdc70919 Node composer: while the seat list is unread the node's own composition is held too, whole, under the scope node; only what runs and the bootstrapped modules go on (ADR 0636 §1; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 14:48:20 +01:00
jschoubben 84e50beb65 Node-engine: the private network's names and generator come from mesh-wireguard's overlay package; the host's internal/overlay is deleted, mesh-sdk's go/overlay has no importer left here; contracts imports follow the domain folders (ADR 0636 §6, ADR 0634; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 14:45:43 +01:00
jschoubben a222db8c69 Node-engine composer: a module new to the node is held until the seat list was read, unless its seats are bootstrapped; the read hands it (H-7, ADR 0636 §1; issue 1966) 2026-11-05 14:17:28 +01:00
jschoubben 2b14f166de The node-engine speaks operator-channel, mesh-vault and node-engine through their contracts and clients; it serves no pull-waits
ADR 0627 §1, §4: mesh-sdk keeps no asks, asker, vault answers or compose-candidate checks, so the node-engine takes them
from mesh-contracts: operator-channel's contract and client (asks, warrants, the asker's client), mesh-vault's sign verb
and answer, and node-engine's own contract and client for compose-candidate's ask, answer, verdicts and bound. The
lead's ruling on pull-waits (no record gives the seat that verb): the verb and its handler go; the row that read the
waits now holds the seat refusing the verb, and failed before the change. The go.mod requires of mesh-contracts' modules
come with the group's pin.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 14:02:44 +01:00
jschoubben c6ae0fc405 The node-engine answers compose-candidate in its seat's contract: the input as a JSON object, a module's fingerprint Fp
mesh-sdk's ComposeCandidateAnswer and ModuleComposed are now the generated nodeengine types (ADR 0613 §3, §5), so the
input sent for the checker's sandbox is decoded once into the object the contract carries, its numbers kept as written
(json.Number), and its size still counted from the bytes it was marshalled to.

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-04 12:40:34 +01:00
jschoubben f7129fdb41 node-engine.composition shows the node's own fields and what the last pass held (issue 774)
Reading ace's node composition gave four resources twice and no way to see that one revision named no provisioner
client's account. The verb now shows, for module node, the revision's provisioner account beside what runs names, its
adoption, how many identities, groups and libraries it names, and each module the composer's last pass held with why.

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-04 01:50:21 +01:00
jschoubben f7abd05981 A node composition that drops the provisioner client's account what runs names is said (issue 774)
Applied, a node's own composition naming no account refuses every filled write and hands no module, which on ace
went unsaid from 01:29 to 01:33 but for the refusals themselves. The pass now says it once, naming the account what
runs names. A placed client keeps its account by the previous commit; this says the case that is left, a client no
longer composed here.

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-04 01:48:12 +01:00
jschoubben 2239fb253d Rows for the composer's composition of today: the same inputs give the running digest, a changed input another, a build it cannot compose none (ADR 0601 §1; review round 1, finding 2) 2026-11-03 14:02:01 +01:00
jschoubben 7da4deb3f1 What a node keeps of a module as it runs, for a manifest that does not yet say it, is carried on the module's have by module, so the watchman raises its condition (ADR 0601 §4; review round 1, finding 3) 2026-11-03 14:02:01 +01:00
jschoubben 5b455cecfe A have waiting for a yes says whether the move changes the build alone: the composer composes the build the module runs with today's settings and secrets and the agent compares it with what runs, so a release's Approve answers it and a changed setting is still asked (ADR 0601 §1) 2026-11-03 13:35:12 +01:00
jschoubben faa2005538 A node agent that meets a manifest which does not yet say it is the tool runner, or that its own secrets are the core's credentials, keeps what runs of it, its tool runner process and its sealed secrets alike, known by what runs and said; never composed without it (ADR 0601 §4) 2026-11-03 13:31:44 +01:00
jschoubben 649ed21d55 The sandbox refuses no module the node holds composing without the change, a module blamed for a refusal among them (issue 774, review round 1) 2026-11-03 13:28:44 +01:00
jschoubben 7b8f5e7805 The sandbox composes a node as its node-engine does, from an input that says how, and names a node it cannot judge from an older engine's input (issue 774, ADR 0593 §9) 2026-11-03 13:28:44 +01:00
jschoubben df13a83a91 The sandbox composes a node from the input its engine took in, through one shape
mesh/delivery merged: source.main moved to novox/mesh-host@798d73eb11e9
mesh/check checking df13a83a9117 on 798d73eb11e9
The second sandbox fault of the same kind on mesh-host #200 (postgres's secret
reader handed, the module not): the engine stripped the whole catalogue from
the input it answers, so the sandbox composed the node's own modules from the
indexer's source manifests while the bus reader composes them taken in from
their builds (artifacts, templates archive texts, what is handed). Both sides
now go through composer.SentInput: the node's own taken-in manifests and kept
builds stay in the input, and the sandbox composes them over the cases'. An
input past what one bus answer carries is refused in words. A conformance row
composes one node through the bus reader and through the sandbox and requires
the same declaration.

Issue 1126.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-03 01:55:08 +01:00
jschoubben b8158affa7 compose-candidate is answered off its subscription, so its bound counts from the ask
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: novox: not composed on novox: these assignments cannot be applied: | b8158affa7af on 27a956448c0a
An endpoint's subscription hands its asks over one at a time: two checks asking
one node at once queued, and the second answered at about 100 s, past the
checker's bound and the bus's one-minute reply window. compose-candidate is now
answered in a goroutine of its own, at most four at once, one more refused in
words. The new cases are rows of the existing tests (test budget).

Issue 1126, review round 1.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-03 01:28:45 +01:00
jschoubben ebb4f4af18 compose-candidate reads each manifest once and answers within the bus's reply window
Off the control-node an ask of compose-candidate ran into its 60 s bound: each of
its two compositions read every manifest in the mesh one key at a time over the
bus, on scratch copies of the shadow that kept nothing, so each ask read them all
twice again (about 35 s per composition on ace, g14 and shanks; 2 s on novox).
The answer at 60 s then came after the bus's one-minute reply window
(allow_responses ttl), so the bus refused it and the checker heard nothing.

Now the manifests are read eight at a time into the shadow before either
composition, a scratch copy keeps what never changes (manifest, archive, done
build) in the shadow too, the candidate is laid over a copy taken after the
composition without it, and the engine answers within 50 s: unready, naming what
it waits on, when not done. Every answer is said in one journal line with its
reads and its longest wait.

Issue 1126.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-03 01:23:17 +01:00
jschoubben 0bbdae1d9d compose-candidate reads the indexer's candidate by its group key, not the check's key
mesh/delivery merged: source.main moved to novox/mesh-host@27a956448c0a
mesh/check checking 0bbdae1d9dfb on 27a956448c0a
The checker asks by the composition key, <group>.<heads hash> (ADR 0593 §7), but the
indexer keys a candidate by its group alone (delivery.CandidatesKey). The node-engine
read the ask's key as the bucket key, so every check's composition was refused on
every node with "the indexer holds no candidate" (mesh-catalog #599, 2026-11-02).

It now parses the ask, reads CandidatesKey(group), and answers unready when the
group's candidate has moved to other heads. Both tests' fixtures had captured the
wrong key; they now key by group, with a slash in the group name.

Quick fix: this lookup. Thorough fix (a shared SDK reader that takes a composition
key and returns the candidate at those heads) not taken: one reader, one repository.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-03 00:05:04 +01:00
jschoubben d68e241724 Take the catalogue's composition rules into the node-engine
ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk
carries no composition rule. The catalogue functions only the
node-engine's composition reaches (Resolve, Resolution's Compose,
Declaration, DataItems, LeftOut, Rules and the rest, the settings,
placeholder and template refusals, the rendering helpers) are copied
with their tests into internal/compose/resolution; a method of a
mesh-sdk shape becomes a function taking it first. The composition
calls its own copies, and the captured catalogue its tests read lives
here now, shared by mesh-compose's tests.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 19:15:55 +01:00
jschoubben be0226b624 Stop verifying composition signatures: the node applies only its own
ADR 0593 §6: a composition read from composed-<node> is a record never
applied, and the engine applies only what it composes itself, so no
composition carries a signature and nothing is verified. The agent's
trusted signers, its signed-composition test and the unused signing
helper of the integration bed go, so mesh-sdk can drop SignComposed,
VerifyComposed and Composed.Signature.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 19:01:12 +01:00
jschoubben f6bda12a32 The node whole publishes its compositions and answers a candidate (H6)
ADR 0593 §6, §7, §9: the integration test runs the node agent against
the real bus under the grant the grants part composes for a node: it
publishes web's composition in composed-<node> with the digest its have
names, and answers compose-candidate for the indexer's candidate,
changing nothing. A node that cannot compose now answers unready, so
the checker counts it as no answer by the verdict and never by words.
The golden grant reads the indexer's candidates and verdicts as it
reads the builder's builds.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:39:12 +01:00
jschoubben 3fa41dfe1a Serve node-engine.compose-candidate from the node's shadow (H4)
ADR 0593 §7: a check's composition is the checker's, made from each
placed node's answer, since only a node can compose with its own sealed
values. The node composes the indexer's candidate in shadow on a copy of
its shadow's inputs, the candidate's modules laid over the indexer's
with their manifest verdicts, and answers per module composed (changed
or not), refused or held, and its own composition's verdict, within the
answer bound; it applies, writes and hands nothing. With input it also
answers the composition input, for the sandbox path.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:33:58 +01:00