Commit Graph
82 Commits
Author SHA1 Message Date
jschoubben e63d707eac R-11: mesh/publish with ack answers its sequence or {error}, mesh/subscribe with deliver new makes an ordered consumer; finding-calls is stated
The subscription's key resolves through mesh-sdk's buscompose.EventSubjects (lead answer A-153; the sdk commit EE-S1 is
cherry-picked into this change's sdk placement), a wildcard is refused.

Builds: design 47 G §559, §488, §576, §622

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:04:18 +01:00
jschoubben 5e373af70d R-1 rest, R-12, R-13: the capability words are mesh-sdk's, the ledger's fill and removal are answered, the artifact states the words
sent-get is under sent-objects-calls; mesh/ledger.fill answers the history's fill against its cap and mesh/ledger.remove
removes an instance's operations, snapshot, state and index entries, both under ledger-upkeep-calls; the runtime artifact's
`states` is exactly the words the runner states.

Builds: design 47 G §462, §488, §545, §587, §622, §155

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:02:04 +01:00
jschoubben 99c36d8ddf G sessions: the runner serves a bundle's put and get sessions and states put-sessions
A value over buscalls.ChunkBytes is put by mesh/objects.put-chunk (written into the module's store as each chunk is
taken, sealed on the last, dropped at its bound or a disorder) and got by mesh/objects.get-chunk after a chunked answer,
for a state's object and a sent object alike; the 8 MiB BundleObjectMost cap is gone with the stateobjects constant.

Builds: design 47 G §518, §345, §457, §490, §620, §622, A-21, A-25
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-11 22:39:04 +01:00
jschoubben 4bfae38a73 G findings: the runner's first views write their unanswered finding through one held writer over its own connection
bus.Conn gains its one JetStream accessor; firstview keeps the runner's own consumer and its four followers and writes and clears each follower's first-view-unanswered finding with the contract's Finding.

Builds: design 47 G A-27, A-28, A-16, A-29
2026-11-11 22:23:44 +01:00
jschoubben 1176df0cd2 T-8: the 8 MiB cap holds on a bundle's runtime call only; the console reads a larger sent object whole (af0ba22, taken)
Builds: design 47 G §69, §62, §407

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 14:47:35 +01:00
jschoubben 78e5de538b T-6: the tool runner reads a sent object by its reference, under the bus state capability
mesh/objects.sent-get reads a sender's sent store only; refused: a state's objects, a reference that is none, an object over a bundle's channel.

Builds: design 47 G §347, §59, §462

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 12:06:40 +01:00
jschoubben 62dce9fec7 T1: the seat settle applies a delayed nak with the bus's own delay (ADR 0664 §1, issue 1748)
mesh/delivery merged: source.main moved to novox/mesh-tools@447a8d035935
mesh/delivery-group group fix/1748-transport-retry merged: every member is merged
mesh/check checking 62dce9fec7a4 on 447a8d035935 | novox/mesh-tools#68 in group fix/1748-transport-retry
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-09 22:53:21 +01:00
jschoubben 312e29478e Tool runner: the cap's reason fails the call; the test proves the ending; the refused-answer limit keys on the caller's prefix and forgets old entries (issue 1966, review round 1)
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
2026-11-09 13:59:13 +01:00
jschoubben f3a9cc276e Tool runner: a bundle's over-long line ends the bundle and is said; an unanswered call and a refused answer are logged (issue 1966)
The reader of a bundle's stdout stopped at a line over 16 MiB without a word and the bundle's next write
blocked for good: every call of the module then timed out, unheard of. Now the line is said, the bundle ended
and started again by the exit path. A call the bundle does not answer in time is logged with tool and caller,
and a refused publish of an answer (to a caller's inbox) is said once per subject per minute.

Quick fix: only the bundle that met it (mesh-hand-acts' answer is cut by its own module). Thorough fix, chosen:
the runner guards every bundle, so the kind (a silent freeze of a module runtime) cannot recur for any module.

Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
2026-11-09 13:59:13 +01:00
jschoubben 8052fd14f4 Issue a key-value entry asked in requires as a state, by its local name
mesh/delivery merged: source.main moved to novox/mesh-tools@2ea4f019e594
mesh/delivery-group group fix/1966-requires-state merged: every member is merged
mesh/check checking 8052fd14f4fd on 2ea4f019e594 | novox/mesh-tools#66 in group fix/1966-requires-state
A bundle's state call on a key-value entry its module asks for in requires
(ADR 0595 §1) was refused "keeps and reads no state called", because the
tool runner read the old state list alone (issue 1966). It now reads mesh-sdk's
one rule, membership.StateIssued.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-09 12:39:04 +01:00
jschoubben 2135fed6cf A node's bucket opens under its own deadline, so a per-node page is ended by its budget too (issue 1966)
mesh/delivery merged: source.main moved to novox/mesh-tools@164547645aed
mesh/delivery-group group fix/1966-views-page-time merged: every member is merged
mesh/check checking 2135fed6cf1f on 9f61975c50a0 | novox/mesh-tools#64 in group fix/1966-views-page-time
Review round 3: the open on the first key of a node ran on the listing's context,
whose deadline is spent before the page's budget.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-09 09:04:39 +01:00
jschoubben aba2c11a27 A page's gets each have their own deadline, so its budget always ends it; a node's bucket is bound once (issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-09 09:02:34 +01:00
jschoubben 568140f667 A page reads the bucket bound once and stops at its time budget, one value at least; an unknown verb is told by its code (issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-09 09:00:20 +01:00
jschoubben 1a9190774d The runtime answers a bulk read of kept state: the values after a key in one request (issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-09 08:51:19 +01:00
jschoubben fb31cc4e99 The console reads the assigner's state assignments and imports the contracts' new paths (issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 22:02:06 +01:00
jschoubben 5bbe669cfb Merge b6/registry into the registry milestone's join: the console reads through the assigner's client, with the seat name mesh-module-assigner (issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 15:39:17 +01:00
jschoubben 6965119bce Tool runner: the grants part's membership bucket and key are membership's, which the SDK keeps (ADR 0635 §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 15:36:18 +01:00
jschoubben d5e4e4e8ab Console: the address text and the tests name the seat mesh-module-assigner (ADR 0634 §9; T-2; issue 1966) 2026-11-05 14:17:14 +01:00
jschoubben db3b5fe63d F-tools: the runner's views consumer is proven on the real bus; the heartbeat is asked of the bus only when a bundle wants it, with no race; a seat record says when the bus wrote it; the beat test counts ticks, not sleeps
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 16:26:50 +01:00
jschoubben 76e025dbbc J2: a state read carries the time the bus wrote the value, as at (stdio.StateEntry.At)
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 14:31:36 +01:00
jschoubben f87c9720ed J2: the tool runner tells a subscribed bundle how its module's consumer stands, as mesh/heartbeat (stdio.OnHeartbeat), at each idle beat and once Missed (ADR 0615, ADR 0621, issue 1966)
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 14:10:25 +01:00
jschoubben b3903446f9 Remove the TypeScript runtime code that called the old catalog module's tools; a test finds no file naming one (ADR 0604 section 4, issue 774) 2026-11-03 17:15:17 +01:00
jschoubben 961ec0ef96 Append and snapshot a ledger on mesh-sdk's ledger subjects, the ones its account is granted, refusing a binding naming others (issue 1966 T6) 2026-11-03 15:17:12 +01:00
jschoubben fadc73f73b Key and answer a ledger index by mesh-sdk's IndexKey and IndexEntry, the one shape the owner's watcher also writes (issue 1966 T3) 2026-11-03 15:15:00 +01:00
jschoubben 2bb0a6461d Publish a module's ledger history and snapshots only on its own ledger connection, read from the runner's own secret ledgers and followed without a restart (issue 1966 T6) 2026-11-03 13:51:47 +01:00
jschoubben 63c1e3faa2 Read a ledger: an instance's state, its history oldest first with sequence and author, a watch of its states, a declared index (issue 1966 T3) 2026-11-03 13:42:33 +01:00
jschoubben ad22c5e9fe Apply a ledger operation: check it against its type, append it with the last sequence expected, derive the state at the revision read, write the snapshot (issue 1966 T2) 2026-11-03 13:40:45 +01:00
jschoubben d6c516ab44 Serve a bundle its own bound objects, streams and work queues on its pipe (issue 1966 T1) 2026-11-03 13:34:32 +01:00
jschoubben 3f538027e9 Read a per-node state through mesh-sdk's pernode package, so the runtime and a process share one copy of its rules
Replaces the runtime's own bucket listing, advisory hearing and per-bucket bookkeeping; the bound on progress and the runtime's shapes stay here. ADR 0593 §6.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:31:18 +01:00
jschoubben 8114b45884 Serve a per-node state to a bundle as one state: get by the key's node, keys and watch over every node's bucket, a later bucket too
The provisioner, the assigner and the view read every node's composition (ADR 0593 §6); the runtime followed mesh-sdk's membership.StateIssued PerNode and process.NodeFamily on its own connection.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 18:27:34 +01:00
jschoubben 4f636b7080 Name no controller verb in hints and drop its handover and paging reads, since the controller ended (issue 1126 B19)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 11:23:14 +01:00
jschoubben 331fa06b54 The tool runner reads the memberships state again until it can, instead of giving a module up at its one follow
A JetStream 503 or a timeout at the follow (a bus right after its boot) left the module with no membership for good, since
Follow runs once per module and the stream fallback is gone. The read is now tried again with a growing wait (1 s doubling
to 30 s) until it watches the key or the connection closes; the failure is said once, and its reading once it succeeds.
Tests: none added; a step added to an existing unit test (TestAModuleHearsEveryStreamItsMembershipNames), which fails
without the retry.

(issue 774, 774/S32, review g1 round 1)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:51:19 +01:00
jschoubben 4fbfdfad13 The tool runner reads its membership from the grants part's state alone: no stream read, no subject heard (ADR 0571 §10)
Follow no longer asks the ASSIGNMENTS stream for a copy nor subscribes mesh.assignment; a module with no membership key is
said so and served in its derived shape. The test mesh issues memberships where the grants part keeps them.
Tests: none added; the stream-fallback assertions of two existing tests are replaced by their state-only counterparts, and
the test mesh no longer makes the stream. The two integration tests of the bus were run locally against the embedded bus.

(issue 774, 774/S32)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 00:25:19 +01:00
jschoubben 316a5a2fc3 A watch given up or stopped hands over nothing more; arrival of current values restarts its bound (issue 774)
mesh/delivery merged: source.main moved to novox/mesh-tools@747bfa71aa32
mesh/delivery-group group fix/sweep-2026-10-30 merged: every member is merged
mesh/check checking 316a5a2fc317 on 0edcd2501dae | novox/mesh-tools#50 in group fix/sweep-2026-10-30
Quick: check the watch context before each deliver in StateWatch. Thorough (chosen, same
file kind): also LogWatch drops a message fetched as it stopped, and the bound restarts
on arrival, not only after the bundle took a value.
2026-10-30 18:22:01 +01:00
jschoubben ac645e2cae Refuse a held-back membership's old wrapper in the tool runner, pinning mesh-sdk's review-round-1 codec
mesh/delivery merged: source.main moved to novox/mesh-tools@0edcd2501dae
mesh/delivery-group group fix/memberships-shape merged: every member is merged
mesh/check checking ac645e2caedd on 3c9068f99a43 | novox/mesh-tools#49 in group fix/memberships-shape
The old grants part wrote its wrapper for a held-back membership too; the new part leaves such a key alone, and taking
it would serve what the hold kept back with the stream's copy ignored. The integration test now proves that copy is
served instead. Review round 1 of issue 774's fix.
2026-10-30 15:38:40 +01:00
jschoubben a479a90fb2 Read the grants part's memberships through mesh-sdk's codec, so the tool runner serves its node's modules
The tool runner unmarshalled the state's value straight into its membership; the grants part had written its wrapper
there, so every module decoded empty, was marked as given by the grants part, and the correct copy on the assignments
stream was passed over: novox served no tool. followGrants now reads with membership.BareGrantsMembership, which takes
the bare membership, still takes the old wrapper (what the live mesh holds until the part writes again), and refuses
a value naming no node or module, leaving the stream's copy in force.

The fixture IssueInGrants built its value by hand from this package's type and so agreed with the mistake; it now
writes through mesh-sdk's encoder, and IssueInGrantsWrapped writes the old wrapper for one integration test that
proves tools and state are served from it (it fails without this fix with the empty membership seen live).

Issue 774 (the bus login list, L3). Quick fix: unwrap here alone. Thorough, chosen: one codec in mesh-sdk the writer
and this reader share, so the two cannot drift again. Pins mesh-sdk at the head of its fix/memberships-shape.
2026-10-30 15:31:26 +01:00
jschoubben 8c0618cfc5 Prove a later assignments-stream membership changes nothing once the grants part's state has given one (issue 1955, ADR 0571 clause 7) 2026-10-29 23:44:19 +01:00
jschoubben 54680238a0 Read memberships from the grants part's state, what the mesh holds from the indexer and placement, and give bundles newest, since and watch on logs, so the tool runner asks the controller for nothing it keeps (issue 1955, ADR 0571 clauses 1, 4, 5, 7)
Pins mesh-sdk bb993dd. The assignments stream stays the membership's
fallback until the lease write; a log another module keeps is read as
<module>.<log>.
2026-10-29 23:42:43 +01:00
jschoubben e9009b7f04 Answer mesh/state.info with a bucket's fill and caps, so a bundle's tools can say how full its state is (issue 1952) 2026-10-29 22:43:58 +01:00
jschoubben 1583fa85d9 Let a bundle write a state key with its own time to live and hear its end, so wakes need no in-process timer (issue 1952)
mesh/state.create and mesh/state.put take ttl_seconds (mesh-sdk 32f5ce3's
CreateTTL/RenewTTL contract); a bucket not declared key-ttl is refused,
naming it; a watch hands an expired key as op "expire". Pins mesh-sdk 32f5ce3.
2026-10-29 22:11:39 +01:00
jschoubben 2966c1e32c Runtime state guard: hold a provider reference's node and module to the mesh's name pattern, so no credential rides in one (issue 1126)
mesh/delivery merged: source.main moved to novox/mesh-tools@95a12105cf7b
mesh/check being carried to 2966c1e32c3d on 95a12105cf7b | from 27266f99a3c3
2026-10-28 21:49:52 +01:00
jschoubben 1a0424117a Runtime state guard: a credential-shaped name passes only holding an exact provider reference, node and module, so a placement's binding is kept and nothing else gets through (issue 1126) 2026-10-28 21:48:27 +01:00
jschoubben 23f5babe33 Runtime state guard: a name holding an object is data, not a credential, so a placement's binding of the provision secret is kept (issue 1126) 2026-10-28 21:47:06 +01:00
jschoubben 3baeaece61 A module's runtime waits for its broker credential and its account at a start, bounded, instead of exiting (issue 1496)
The node-engine starts a module's runtime before the provisioner's client fills
its broker file, and the bus carries a new account only after it reloads its
users. The runtime exited on both and was restarted until they were there (ace,
2026-10-26 21:19: mesh-build-node's and mesh-build-image's runtimes exited twice).
It now waits up to five minutes from its start, said once: the file is read again
each time its directory changes (the bundles' inotify watch, a 30 s backstop),
and an authorization refusal is asked again with the backoff. Past the bound it
gives up loudly; a file with no url, a pin mismatch and a bad URL stay final.
2026-10-26 22:06:39 +01:00
mesh-tools bb6a0e3192 Merge pull request 'node-tools: a consumer deleted or made again while no pull waits is noticed at the next rebind, so a module is not deaf for a heartbeat (issue 1945)' (#43) from fix/bus-consumer-remade-flake into main 2026-10-25 15:22:24 +00:00
jschoubben 3331719407 Ask the bus whether a bound consumer still exists, so a deleted and remade one is rebound within a rebind tick, not after nats.go's heartbeat (issue 1945)
mesh/delivery merged: source.main moved to novox/mesh-tools@bb6a0e3192db
mesh/check pass 33317194073a on bb6a0e3192db | unit 115 run, 11 kept, 11 skipped | integration 117 run, 11 kept, 10 skipped | over bound: unit (slowes…
nats.go ends a pull loop on a deleted consumer only when a pull is pending at that moment; otherwise the loop waits out its heartbeat. The rebind tick now looks each bound consumer up by name and compares its creation time.
2026-10-25 16:02:27 +01:00
jschoubben 2cd5550dc7 A stopped tool drops its membership handler and a stopped bundle starts no copy on a call, so a replaced bundle's old tools stay gone (issue 1945, review round 2)
mesh/delivery merged: source.main moved to novox/mesh-tools@5d6cee9d844e
mesh/check pass 2cd5550dc70f on 77b05089c8df | unit 0 run 126 kept | int 0 run 128 kept | clone 9.5s | composition passed on 4 machines
Its events are refused before the old bundle stops, the bundle watch follows a directory made between
its stat and its watch, and a bundle's reason is read without node's colour codes.
2026-10-25 15:44:10 +01:00
jschoubben d8ac69904d Refuse an event heard during a reload instead of panicking, and judge a bundle by its entrypoint alone (issue 1945, review)
An event a module's consumer heard after the module was dropped for a
reload read a deleted entry and panicked node-tools, taking every tool on
the machine down. The handler now refuses an event of a consumer that is no
longer the module's, and a stopped hearing hands nothing on and offers the
event again at once.

A bundle that writes beside itself (a cache, a socket) loaded itself again
after every quiet spell, because the signature took in every file in its
directory. A delivery puts every file in place anew, so the entrypoint alone
tells a new build. The watch also looks once as it begins, so a bundle that
came between its load and the watch is not missed.

Tests: 1945/AC23 and AC24 in internal/runtime/reload_test.go, and a stopped
hearing in internal/bus/hearing_stopped_test.go.
2026-10-25 15:26:02 +01:00
jschoubben 0211844e6a Bound a state watch's hand-over by its progress, not its whole set, so a large state's newest keys are handed over (issue 1726)
mesh/delivery delivering: 0 machine step(s) passed
mesh/check pass 0211844e6ad3 on 0e985f9bf186 | unit 0 run 117 kept | int 0 run 119 kept | clone 5.4s | composition passed on 4 machines
The gitea module's watch of mesh-delivery-checker.owed failed at every attempt
since 03:05 on novox: about 200 owed keys, each a round trip to the bundle,
outlast a 10 s bound for the whole set. The bundle dropped its handler, the
oldest keys were written again every 40 s and the newest, handed over last,
never were: group fix/1937-done-key-blobs's pass never reached mesh/check.
StateWatch now fails only when no current value is handed over within
StateTimeout.
2026-10-24 07:42:08 +02:00
jschoubben 9153a280f8 Let a bundle pull one message from its listed worker and settle it, so a build module takes an ask only when it has a free slot, in its workers' order (issue 1887 A11, ADR 0525 §4) 2026-10-23 15:28:06 +02:00