mesh/check checking 53351dd30df2 on b1125c02cfe6 | novox/mesh-catalog#675 in group feat/47-G-join11
mesh-conditions keeps G's form: the keeper reads no observer's state (no reads, no Observers list), so main's zfs entry there goes. The zfs follower says its findings through G's findings writer over its keeper: the keeper gains the publish of the writer's three events on the finding stream finding-events and the hear of mesh-conditions.findings-asked on its own durable, nothing else; each pool or device not ONLINE is scope module, id zfs.<pool>.<device> (the device's own name), kind not-online, on the node. The manifest asks its state findings by template in requires (G §529, §577), and gains the finding-events stream and the consumes, and the keeper's bus the three events and the consumes.
Builds: design 47 G §383, §384, §387, §529, §577, A-339, A-340, A-341, A-342; design 42 zfs-owns-zfs §27, A-32, A-37, A-39, A-41
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
mesh/check being carried to 0041b69d1736 on 32f1566cc879 | from 117f933dacf0, mesh-delivery 7221a1e5cd7f, mesh-host 0193949efe9f, mesh-sdk e42b9491c93…
The validator refused zfs and mesh-conditions: mesh-conditions reads zfs.findings, which zfs had moved to bus state in requires, where the new form has no readers (ADR 0596 section 2). The keeper process's bus.state keeps naming findings. The manifest test holds it.
Builds: design 42 zfs-owns-zfs A-46 (A-32, 26, 27)
In the test's temporary directory, or /tmp when the socket path would pass 100 characters, so a long TMPDIR cannot fail the bind.
Builds: design 42 zfs-owns-zfs §18, A-37
Issue 1979, blocking: a date-bound test. The warrant dated 2026-10-29 fell out of the listing's 14 days on 2026-11-13, failing every mesh-catalog check.
Builds: design 42 zfs-owns-zfs (the group's check)
The group's check failed TestRulesBus/NoCatalogueManifestNamesAnInstallation: 11 values name an installation (the vendor sites in the package's zed-functions.sh, resources[13]).
Builds: design 42 zfs-owns-zfs §14, A-2
The group's check failed TestOnlyRootOpensTheKeepersSocketAndANeedlessKeeperIsTheBusDown and TestAKeeperThatDoesNotAnswerIsWarnedOnce: stat /var/tmp: no such file or directory.
Builds: design 42 zfs-owns-zfs §18, A-37
The group's check failed TestEveryControllerKindHasItsHome: the reader zfs's findings are not read by the keeper.
Builds: design 42 zfs-owns-zfs §27, A-32
mesh/delivery-group group feature/1979-zfs-owns-zfs rejected: composed together: the checker's verdict at the members' heads (03f2ebff6ed0): unit: mesh-conditi…
mesh/check failed (9): unit: mesh-conditions/cmd/mesh-conditions.TestEveryControllerKindHasItsHome: the rea…; and 8 more | d15502f3650d on 117f933dacf0
Builds: design 42 zfs-owns-zfs §13, §24, lead answers A-45, A-43
The tools say every event of §25 (snapshot.taken.person, scrub.requested and the others) with mesh/stream.publish on the
stream events, never stdio.Emit; the hand acts' 30 s wait reads the mark (stream.fill) before the act starts, then
stream.read from the next sequence, for at most HandWait.
Builds: design 42 zfs-owns-zfs §25, §24, lead answers A-42, A-12
A failed keeper call in a root process (hand acts, forget, Paused, every call) now adds one warning that the bus is
taken as down, instead of being dropped silently. RunKeeper closes the connection acct.Dial opens when the keeper
stops; the message id's comment says it is nanotime-pid.
Builds: design 42 zfs-owns-zfs A-37
The three root processes declare no bus and reach the keeper's socket; the module invokes the service manager's start. The judge refuses the keeper's bus emits and state until the validator accepts what the module asks for in requires (A-38).
Builds: design 42 zfs-owns-zfs §25, §26, §27, §28, A-6, A-19, A-36, A-37, A-38
Renamed TestTheBundleRunsOnlyTheFormsOfADR0679: each root form is held to its whole argument list, no verb the decision never allows, zgenhostid only with the parsed hostid, a device only as cache or log.
Builds: design 42 zfs-owns-zfs §19
The manifest declares zfs-utils and zfs-dkms, renames scrub-pool to pool, and declares every new value not managed until set; its config file is ${config-json}, the options file, ZED's folder, rc, functions, handlers and drop-in each under their condition, the three ZFS units, the apply (run-once, restarted by its config file) and the run before the distribution's scrub and trim timers. One commit: the three subtasks change the one file module.json.
Builds: design 42 zfs-owns-zfs §6, §7, §8, §9, §11, §12, §13, §14, §15, §18, §20, A-1, A-2, A-3, A-7, A-14, A-15, A-16, A-23
zfs_config also says what the module says before it leaves a node (Z17): the next load of the kernel module uses ZFS's defaults, the three units and /etc/hostid stay.
Builds: design 42 zfs-owns-zfs §28, §30, §10, A-31, A-35
A trim schedule of weekly or monthly with no trim-day or trim-time is one refused value naming it; a keep count of 0 is that kind's none: the existing scheduled ZFS snapshots are kept and a warning names them.
Builds: design 42 zfs-owns-zfs §20, §21, §22, A-33, A-35
A value of another form is refused before anything is written or run; absent and empty are not managed.
Builds: design 42 zfs-owns-zfs §9, §11, A-15, A-23
The node-engine writes a cron step (*/15) as a calendar systemd refuses, so
zfs-mesh-scrub.timer never started and the pool had no scrub schedule. A list
of minutes is written as *-*-* *:0,15,30,45:00, which systemd takes.
Builds: design 42 zfs-owns-zfs §18. Tests: 1979/AC1.
The validator refused the manifest: a bundle's env may not set what the runtime gives every tool bundle. The processes
night and awake keep theirs.
Builds: ADR 0192
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
intel-ucode failed an apply on a stale package database and stopped the delivery; an Intel machine
fails the unit by the image check and gets intel-ucode in the change that adds it. Tests: 1977/AC1
and the pinned order string adjusted.
Builds: L10 (issue 1977 note 6)
Before mkinitcpio -P, a preset naming ALL_config="/etc/mkinitcpio.conf" is copied to the state's
taken-over/ and loses that line (another ALL_config is left and named); after it, an image without
kernel/x86/microcode/ in its first 64 KiB fails the unit and records nothing. The unit may write
/etc/mkinitcpio.d. The README names no node. Tests: 1977/AC7, 1977/AC8; AC3/AC4 fixtures write images.
Builds: L7, L8, L9 (issue 1977 note 4)
Replaces the state record read (root's 0700) with images_with_microcode per /boot/initramfs-*.img:
true when the first 64 KiB hold a path under kernel/x86/microcode/; an unreadable image goes to
image_errors with its error. Test: 1977/AC5.
Builds: L6 (issue 1977 note 3)
Declares amd-ucode and intel-ucode, the drop-in /etc/mkinitcpio.conf.d/mesh-microcode.conf, the
initramfs script and mesh-kernel-initramfs.service; kernel_boot answers the running revision and
whether the images were built with the drop-in. Tests: 1977/AC1-AC5.
Builds: L1, L2, L3, L4, L5 (issue 1977 note 2)
mesh/check checking d22a7f3a412f on a60728e6f09d | novox/mesh-catalog#671 in group fix/1748-resolver-wait
The resolver file of systemd-resolved (resolvers and kept facts) carries options timeout:3 attempts:2 edns0 in place of timeout:1; manifest test asserts both facts, guard test's literal follows.
Builds: design 50 resolver-wait §1, §4 (and §2 of the main file, line 73)
Since A-290 a run whose program exited other than 0 ends its key failed, the
reason saying the exit, its answer kept (steprun.finish); the test still
wanted passed. It now wants failed with "the program exited 7" and reads the
kept answer as before.
Builds: design 47 G A-290
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Every TypeScript module of a fetch gets the registry's latest SDK (ADR 0573 §2,
A-284), so the harness's machine named the real registry and 11 tests (9 unit,
11 integration runs) reached the network; with the resolver down they failed.
The harness now serves a registry of the test's own holding one SDK release,
and the userconfig test reads its address from it.
Builds: design 47 G A-284, A-285
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Store.ListReadable lists every record and, beside them, each file it cannot read
by name with its error; RecordsHeld lists those as rows with an error and goes
on. recordsError stays for a store that cannot be listed at all. Store.List and
ListPrefix keep their behaviour for their other callers.
Builds: design 39 bus-and-switch §20; design 39 parts §12. Lead answers (issue 1409): V9 (keep recordsCount and recordsError), V10.
S1 vault-licence-secrets-listed. secret_holders answers `records` and
`recordsCount` beside holders, count and enrolments: each store record's name,
generation, since, changed, changedBy/changedVia, origin, length and the vault's
own fingerprint of the whole value, plus key and part for licence.<key>.<part>.
A record the vault cannot open stays listed with an error. Never a value.
Builds: design 39 bus-and-switch §20, §15; design 39 parts §12 (D1); design 24 Every secret lives in the vault, Beyond generate and hold; as-is 06 The vault, as it runs.
Lead answers (issue 1409 note 11): V1, V-thorough, V2-V8. V3 drops the map's
tokenFingerprint and AC5; V-thorough widens the licence.-prefix list to every record.
Both holders' uplink-tools copies read address, master, link and
link_index/link_netnsid from the existing ip -j address show call. Fields
are left out where a link has none (L3); a parent in another namespace is
{index, namespace} (L2); the form lives in uplink.go only (L4); only the
tool description changes, not seat.json (L5); bridge fdb MACs are not
answered (L6); names mac, master, parent (L1).
Builds: design 48 10, design 08 code:, issue 1965 note 11 L1-L6
Brings #664 (licences_switches carried entries), #665 (mesh-files lists a
place a secret is kept), #666 (provisioner: bounded retiring ask id, a
refused ask said, provisioner_health), #667 (mesh-build-go's step end
rewritten without the taken versions when over the steps state's bound),
#668 (mesh-files find writes the NUL itself). #667's buildstep/step.go and
digestshape_test.go conflict with G's deletion (the step runner moved to
mesh-delivery-sdk/steprun, SD5): G's side is kept; its intent, an answer over
the bound not lost, is G's A-290 (the answer kept as an output object).
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The keeper's hand-made receive (subscribe to the call's chunks, ask, receive in order, acknowledge each) moves into
mesh-sdk's process.Conn.CallChunks; the keeper's answer checks (an answered error, the space it fits, no chunk granted)
run as its accept hook before a chunk is taken.
Builds: design 47 G A-291
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Live on novox 2026-11-12: node-files.list of a root-only directory answered
'fork/exec /usr/bin/sudo: invalid argument'. The kernel refuses a program
argument that holds a NUL byte, and listAsRoot's -printf format and
searchBelowAsRoot's ended in a literal \x00 since 5d98bcc0 (2026-10-16), so
no list or search through root ever ran on a node. find writes \0 itself.
The stand-in root in the tests refuses an argument holding a NUL, as exec
does, so every root call is held to it; it found the search's instance.
Builds: design 39 parts §15 and the lead's answer D3 (list through root of a place a secret is kept).
A catalog check's answer of 264712 bytes was refused by the steps state
(256 KiB per value) and its end written failed without it, so the checker
lost the biggest member's answer and could not preview it. When a passed
or failed end is refused as too large, finish writes it once more without
the fetch's taken versions (fetch.packages, which no reader judges), the
step's reason saying how many were left out, why, and that the module's
journal names each; still too large, it ends failed as before.
Quick fix for issue 1921 (note 91); the thorough fix is design 47 G A-290
(an answer over the bound kept as the object output.<ask>).
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
mesh/check checking 3bb8ace833d1 on c0d666fdcf55 | novox/mesh-catalog#666 in group fix/1966-unpublished-placed-module
The retiring ask's id is made from the key's digest and the time (at most 64 characters),
so a long key is asked. An ask the router's rules refuse is said in the key's why and in
provisioner_health. The Composition comment says what the code does: an unpublished
module keeps only its own plan and keys.
Builds: design 47 fix-unpublished-placed-module U6, U7, ADR 0593 §8
Issue 1409. readTools no longer appends the refusal sentence to list. A row in
TestSecretPlacesAreRefusedByNameBeforeAnyRead holds a link's target in a secret place to the content rule.
S2's match on sudo's English message is left as it is: the root path sets no locale, and sudo's environment
handling decides whether LC_ALL reaches stat.
Builds: design 39 parts D3 (§15), bullets 2 and 4
Main brought #663 (fff3b819) in mesh-build-go/buildstep/askrun.go; G moved that step
runner into mesh-delivery-sdk/steprun, where 5fbc366f holds the same answer on error,
so G's deletion of buildstep's askrun.go and its test is kept. The tree is G's.
Builds: design 47 G A-286
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
KEPT gains failed-steps, idle and transfers, so each declared state can be read by
its tools; the force-push refusal's test holds that the refusal names the one tool
that may do it and that it runs on the operator's Approve of that call.
Builds: design 47 G A-287, A-288
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Issue 1409. A stat through root of a path that is not there answered that the file modes refuse it; it says
it does not exist, so design 39 parts §15's "gone" can be read.
Builds: design 39 parts D3 (§15), bullet 3
Issue 1409. A list of a place the mesh keeps a secret, or of a machine's credential places, at any depth,
answers each entry's name, type, owner, group, mode, size and a link's target held to the content rule,
never content, and says secret-place; a process's environ, mem, fd, map_files, root and cwd stay refused.
Lines touched cite ADR 0394 §7.
Builds: design 39 parts D3 (§15), bullets 2 and 5
The seat mesh-pipeline-runner's step event carries `fingerprint`; gitea read
`fp`, which no event carries, and which the type-check refuses once the Node
fetch places the runner's contracts (design 47 G A-285).
Builds: design 47 G A-285
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
gitea imports @novox/mesh-delivery-contracts-mesh-pipeline-runner, so its
package.json names it and the Node fetch places the group's (design 47 G A-285);
the catalog view's revision answer is typed with its revision and entries, which
revisionAnswer already refuses loudly when the holder leaves them out.
Builds: design 47 G A-285
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The fetch takes `group-packages` (a member's repository, commit, ref and the
package's directory there) in place of the single `package` and its tagged form;
it packs each package a module of the tree takes, publishing nothing, and places
it in every module whose package.json names it, the SDK in every module, in place
of the registry's whatever the lock names.
Builds: design 47 G A-284, A-285
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
mesh/check checking fff3b819d383 on f1c04801e477 | novox/mesh-catalog#663 in group fix/checker-preview-after-failed-step
A level that does not compile or generate ended the check step failed with no
result, so the checker could not tell a merged fetch from one that never
answered, and previewed and judged no manifest or composition of the member.
The step now ends failed with its answer all the same: its fetch and the
levels so far beside the error, which the step's end already keeps.
Builds: design 47 G A-286 (G-22-lead-answers-2.md at hq 41dd30fe; issue 1921; principle 3)
Quick: this checker on main; thorough: the same rule in G's checker (join 11, J15).
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Try 2 of milestone G failed in go test, verifying nats-server against the checksum database: restic's
integration tests load it through testbus, neither its go.mod nor its go.sum named it, and the fetch's
shut-off load ran untagged, so it never met it. The second failure of this kind (after the join's
dropped zero-version requires), so the guard is held once, where every repository's check passes: each
directory of the checked tree is loaded untagged and with the integration level's tags, and its own
go.mod and go.sum must name every module the loads reach (a mesh module required, no sums; every other
required at the version selected, with both go.sum lines). The fetch fails naming the module and the
line. A sibling laid beside is loaded as before, unjudged.
This guard lands with G, so G's own check still runs today's proof; no harm, the gaps it finds in the
seven repositories are fixed in this join.
Builds: design 47 G (join 11, the check's shut-off build of the group's modules)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The check builds with GOPROXY=off, so a module its packages load that go.sum does not hash is looked up in the
checksum database and fails (try 2: verifying nats-server v2.11.17). mesh-sdk testbus, which restic's tests import,
brings nats-server and its four requirements; go.mod and go.sum now name them, as go list -mod=readonly -deps -test
against the group's heads asks (both build tags).
Builds: design 47 G (join 11, the check's shut-off build of the group's modules)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Area 2 added seat:operator-channel.notify to the manifest's invokes for the call in main.go,
and the test of the manifest's invokes still listed the old ones, so the unit level failed.
Builds: design 47 G GR8
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The checker's fetch pins only the zero-version requirements a directory's go.mod names
(mesh-build-go workspace.go goModOf), so a module reached only through another, such as
meshhandacts through meshhandactsclient or mesh-delivery-sdk through meshcatalogclient,
was never downloaded and the shut-off load failed (fetch.go:267). The join's merges had
dropped these indirect requirements that the trunk's go.mod files list.
Builds: design 47 G (join 11, the check's fetch of the group's modules)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The conflict in the old cmd/claude-licence-manager/tools_test.go resolves to both sides: main
moved it to cmd/manager, and the join's count of binding.changed.<consumer> under its family
goes into the moved TestResyncSaysEachOnce. The whole-module test's runtime refused
binding.changed.<consumer> because the manifest names the family binding.changed: it now
accepts a key that extends a named family by further parts, as A-134 says the event.
Builds: design 47 G A-134
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
mesh/check being carried to cff1005422c1 on 6d000647de2d | from f9dcbc295723
The one bundle that did everything becomes the manager bundle, which runs long and answers the seat's ten verbs and
the three acting tools, and a tools bundle of its own that answers the four reading tools and writes nothing, so they
answer while the manager fails to load or stops. Both import the module's one package for the layouts of the kept
data and the log entries, the key form, the entries' names and the settings with their validity; the settings file
and the account with its directory stay as they are.
Builds: design 39 parts §1, §2, §3, §4, §5, §6, §7, §8
The gate consumes pull-updated and invokes open-pulls and pull; it writes deliveries and groups
under their key forms, deletes them as a take-in or a closed pull request leaves them, copies a
delivery's base onto the record's member, answers groups from records and the group key together,
puts a missed event right at its start, and writes switch.done once the switch has run.
Builds: design 47 G §716, A-279, A-236, A-281
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The carry-over from the store database ran live once and carried every row, so its code, the gate that answered
"the carry-over has not ended", the condition carry-over-failed, the tool licences_carried, the opening of grants
with grant.key and the postgres driver leave the module, with its requirement of the database and of the secret
grant-key. The state carried stays as the carry-over's record; at its start the manager waits for nothing and
clears a carry-over-failed it finds kept.
Builds: design 39 parts §6 (the template files/database.url), §9, §10, §11
nats and distribution declare the old stream form and require no finding-events, so their writers stay on it.
Builds: design 47 G A-274 (answers G-22)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
buildstep no longer takes mesh-sdk's buscalls objects (that package now reaches
the bus): the module judges each object of its kept-builds store with
KeptBuildOf and orders them with SortKept.
Builds: design 47 G (join 11 area 4: buildstep kept free of the bus)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
AnswerSeat checks a call's caller against the seat's definition its caller
reads from the seat list it follows (A-186). The bus module's keeper hands
it the mesh-broker definition its seat list holds once heard; mesh-recovery,
which followed none, follows one over its connection and an event hub, read
again once its events are live, and its manifest and its process invoke
seat-definitions and consume the list's two events. Its whole test answers
the seat list.
Builds: design 47 G lead answers A-179, A-186 (join 11 area 6)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The vendor retired the session limit and answers the session window empty, so Room required a percentage that never
comes: live, no licence had room and no switch could choose a target. Room is now 100 less the weekly percentage; the
session window takes no part in the switch threshold, a target's bound, the near-limit warning or no-room's words.
A reading with no weekly percentage still has unknown room. The settings' descriptions and the README say so.
The whole tests' vendor answers the session window empty, as it does live; on the old rule they failed with the live
symptom ("has no session or weekly window in its reading").
Builds: design 39 bus-and-switch C4
The merge of main's holder test (caller list from the config watch) over C3d's
(no caller list, REG2) left cases the merged holder does not answer; the
holder's code is C3d's, so its test is too, with the moved delivery paths.
Builds: design 47 G REG2 (C3d)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The join's importers name the delivery repository's moved contracts and sdk
(MV1), node-tools' tests use mesh-sdk's gate, the duplicate node-engine claim
rule of the reader release gives way to G's, and the assigner names its first
watched branch, never a constant. The seat holders' AnswerSeat callers are
area 6's.
Builds: design 47 G join 11 (merge of fix round 11)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Live after #659 the manager, in its own runtime, was still issued none of its logs: the runtime on main issues
template states but logs only from the `logs` section. usage (35 days, 256 MiB) and audit (64 MiB) move there; the
states stay templates. The whole tests' runtime now issues logs only from `logs`, as main does, and failed on the
old manifest.
Builds: design 39 bus-and-switch C3
Each module's puller keeps an answer over what step-ended carries inline in the object store `outputs` its manifest requires
(template objects, 256 MiB) and its tools serve `<seat>.output` from it; the manifest claims the verb.
Builds: design 47 G A-254, A-257
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Moved to its own account, the manager finds manager-key.json still owned by the tool runner's account, which the
node-engine does not hand over; it skipped making a pair because the file existed, and every verb answered the read
error. Now a pair it cannot read is replaced by a new one, renamed over it, and said in its journal; every use passes
the public key per ask, so nothing depends on the old pair.
Builds: design 39 bus-and-switch C2
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Run inside the machine's tool runner, the manager was issued none of its own logs and states, so the carry-over
failed live ("keeps no log called usage ... it was issued: none"). It now declares runs-as claude-licence-manager,
makes that account, owns what it places on its machine and its secrets, reaches the bus with its own broker secret,
and invokes a node's claude_code_grant, which the tool runner's account could ask and its own could not.
The whole tests play the manager's own runtime: they issue only the states, logs, asks and events its manifest
names, and fail on a manifest without runs-as; a unit test holds every ask in the code to the manifest's invokes.
Builds: design 39 bus-and-switch C1
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
OpenForgeMade is the fill; no path of the gate opens a forge-made record (design 47 G §151 ends the mark from G's delivery),
so the teller says none until one does.
Builds: design 47 G §170, §522, A-161, A-172
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
A catalog revision is pinned by its watched branch and its number (revisions are numbered per branch): PinnedRevision gains
branch, Pin and Free take it, the key names it so two branches' revision 9 are two pins, and pinsOf says {branch, revision}.
Also the C2 merge's sourcetools imports follow the contracts' new path.
Builds: design 47 G §579, A-171
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The keeper follows meshcatalogclient's branch follower and the seat list on its views reader, and plans again at each
move of a branch's view, the registrations or the seat list. Each local name is planned from the first of the module's
watched branches in its registration's order; another branch asking it with other settings is said drifted, naming
the branch. A module of the new form whose resolved seat definition has a verb or an event gets its sent store; one
including only parts, and a foundation part, none. A module in no watched branch's newest revision loses its plans
key, its entries orphans. The sum of the caps counts the old sections the entries declare. The manifest consumes the
catalog half's and the seat list's events and invokes their verbs; manifest-accepted and indexer_bus_state go.
Builds: design 47 G §344, §433, §532, §533, §537, §538, §547, §591
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The runtime source is *steprun.SeatAsks (named worker not bound is said through the module's journal); the callers follow
the seat list (steprun.SeatListCallers).
Builds: design 47 G §543, §544, A-163, A-170
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The config `callers`, the tool registry_callers and its invokes, the caller-list code and the holder's per-verb
Allowed checks go. The windows' driver counts as build modules the modules claiming a `node-build-*` seat in the
catalog half, followed by the seat mesh-catalog's branch follower on the program's views reader (one shared events
hub); it wakes again when a build module's entry moves. The retention check of remove finds the artifact sweep's
holder through the seat mesh-module-assigner's holders (seatlist.HolderOf), not a name.
Builds: design 47 G §610, §7, §428, A-156, A-82
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
An integration test starts the night as the node does: its credential is read from where the manifest places it (the process
night's MESH_BROKER_FILE, the module's own-secrets broker), it says each item started and ended on the seat node-backup, gives
way to a restore that runs (items put off as keys of the state put-off, started again on the restored) and, past put-off-bound,
the bus's expiry writes backup-waits into the findings. It found that WaitRestored held a fetch of a minute after its context
ended, so an expiry ended the wait up to a minute late: it now consumes the restored events and ends on the context.
Builds: design 47 G §563, §561, §554, A-150, A-155
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The record backed-up reads is the key `<module>.<item>` of the module's own state put-off (key-ttl), bounded by the setting
put-off-bound (minutes, default 60); the bus removing it is heard as the expiry, which writes the finding backup-waits through
the held writer over the module's findings and ends the wait, so the night never holds its lock without a bound. The file
put-off.json and its writes are gone. The manifest requires put-off, findings and finding-events and hears findings-asked.
Builds: design 47 G §561, §563, §557, §302, A-155, A-77
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
All of mesh-build-go's buildstep Go module leaves mesh-catalog for
modules/mesh-delivery-sdk: the step run, fetch and release and the
regenerate-and-compare step as the package steprun, the CPU share as
steprun/buildcpu, the conformance kit as steprun/conformance, the seat
generator as seatgen with cmd/seatgen, and cmd/mesh-pack. The three
build modules and the builder's and checker's tests import the SDK and
keep no copy; the SDK requires nothing of mesh-catalog. Code the build
modules share is the delivery domain's SDK, not one module's package.
It carries the build-module round's two new files of that package
(dropdetected.go 247c422f, storedbuilds.go 904b8aed).
Builds: design 47 G §464, §680, §327, §420, §495
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The tool is marked in the manifest's needs-approval, so each call runs on the operator's Approve; the manifest
uses operator-channel; set_full keeps refusing a force-push onto a trunk and names the new tool; both clients
gain deleteBranchProtection.
Builds: design 46 approval mark §21 (milestone G)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
A Go program is linked with -X main.meshVersion beside main.builtFor, a Node program's package.json version is set, an
image is labelled org.opencontainers.image.version; a build with no version stamps none.
Builds: design 47 G §458, §573
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The guard's toolchains value carries the sha256 of the go or node program found on the path (read again when the version
changes); toolchain-reported is said on the build seat's subject of the node at start and on each change of version,
recipe or digest; a build's ToolchainUsed names the digest. The legacy toolchain.reported emit and its stream go: nobody
consumes them.
Builds: design 47 G §492, §472, §466 (lead answer A-152)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
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
Each member's build is read at /v2/<module>/<artifact>/blobs/<digest> through the required provision artifact-store
(bound to a file), checked against its digest and laid as the package it names: a Go module zip replaced in the temporary
modfile, an npm tarball in node_modules. A mismatch or a store that does not answer fails the step naming the member.
Builds: design 47 G §465, §373, §466 (lead answer A-151)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
A drop of a kept detected-steps key records the act with the caller the bus proved, then deletes the key; a log that
refuses deletes nothing and is answered error; a drop without why is refused; fetch is asked unless drop.
Builds: design 47 G §463, §480
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
mesh/check being carried to 15db34169e24 on 89ad37048520 | from d9f2b7bcfa07, mesh-contracts 29ec1c3df312
mesh-delivery's parts.Receiver.Take took a chunk 0 again on purpose (276412d7, design 51 Publishing, 1966/AC203-1,
AC203-2); the holder's test still expected it refused and failed on every run, on trunk too. The test now expects a
chunk out of sequence refused and a chunk 0 again taken.
Builds: design 51 Publishing, the bullet "The file travels in parts through the seat"; issue 1975's group check
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The whole test runs the process on its own account against a bus of its
own, every bound a setting of seconds, with a stand-in bus module for
snapshot-get, snapshot-restore and snapshot-restored: a hand take's log,
a restore waiting on the dump past its bound key, busy and the ask again,
the expiry on its bound key, a keeper's snapshot in three chunks, a
protected restore cancelled at its bound and its aside put back, one the
keeper answers neither, and a stop putting the aside back.
It found that an act said its ending event while it was still the running
one, so a caller told busy that asked again on hearing it was told busy
with the same act and heard nothing more: the act is now released and
written ended before its ending event, and the removal at a snapshot-kept
runs before its ended.
Builds: design 47 G §557, §554, §681, §562, §551, A-138, A-140, A-141, A-143
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
mesh/delivery-group group fix/1975-kernel-log rejected: composed together: the checker's verdict at the members' heads (c265ee221ccf): unit: distribution/inter…
mesh/check failed (2): unit: distribution/internal/holder.TestTheHolderOfTheTwoImageSeats/a_transfer_in_par…; and 1 more | ebcc7761f178 on d9f2b7bcfa07
Each wait's bound is a key of the module's state bounds with its own time to
live, dump-wait.<act> and restore-wait.<act>, its expiry heard on the key's
watch, so no timer stays in the process.
Builds: design 47 G A-143, A-77, A-138, §681, §561
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
point-keep-days, dump-wait-minutes and snapshot-restore-wait-minutes may
be fractions, and expire-every-hours (24 unless set) times the removal of
old points by a key of the state bounds whose own time to live the bus
ends, heard as its change: no timer in the process.
Builds: design 47 G §551, §557, A-77, A-130, A-138
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
journalctl --dmesg --boot=N under the same escalation, window, priority, fixed-string match, 2000-line cap
and redaction as the journal verb (shapeLines is the one filter both use); a boot is 0 or a negative whole
number, refused otherwise before anything runs. No scope: the kernel belongs to no manager.
Builds: issue 1975, the operator's request of 2026-11-12 (the lead's handover; no design line names the verb)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
A move or a restart stops the process: from its stop signal every call
is answered an error naming the stop, the running act ends through its
own failure path (an aside put back whole, whatever its context), and
every accepted act not ended ends failed with stopped and its event, so
its caller asks again.
Builds: design 47 G §562, A-141
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
An unprotected snapshot is received through snapshot-get into
incoming/<request>, refused before the first chunk past the cap, checked
against its digest before any aside, and restored by the module; a
protected one is verified, the running data set aside and restored in
place by the keeper, waited on by snapshot-restored within
snapshot-restore-wait-minutes, cancelled at the bound. The bus module
sends its chunks with mesh-sdk's form.
Builds: design 47 G §681, §682, A-137, A-138, A-139, A-140
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The validator refused it as placed nowhere (ADR 0348 §5): the keeper reads it from its settings
beside ask-bound-seconds and view-waits-seconds, which are marked so.
Builds: design 47 G §557
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The manager says binding.changed.<consumer>: the module's views reader hears it by the adoption
and asks the first view (FirstBinding) once its subscription is taken, instead of a subscription
of the exact subject of its own.
Builds: design 47 G A-134
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The follower main added (issue 1409) used the removed views.FindingWriter: it is adopted by a
views.Reader holding the vault's one finding writer, which the assignments view shares, and hears
claude-licence-manager.binding.changed.<consumer> through the adoption.
Builds: design 47 G A-16, A-28, A-134
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The consumer is the event's further part, the one form of G's seat events, so mesh-vault and
claude-code adopt it through their views reader.
Builds: design 47 G A-134
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Its tool check stands on its own runtime beside the process's unit check, its
template states are its own by requires alone (not listed again in the
process's bus, which keeps its account), and digests takes the state
template's fixed cap (A-135).
Builds: design 47 G §657, §567, §554, A-133, A-135
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
claude-code's and mesh-vault's manifests take both sides' additions (G's seat reads and
findings-asked, main's licence seat verbs and events); claude-code's manifest test lists both.
mesh-vault's licence-bindings follower still uses the removed views.FindingWriter: fixed after.
Builds: design 47 G §610
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The catalogue keeps no file text inline for a new module: each setting's file is a template
under files/, packed by the module's archive artifact. A local build of the tools bundle
leaves a binary the module's ignore file now names.
Builds: design 47 G §633, A-112, A-130
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The module measures its points directory against the fill mark of its cap at its start and
after each act, writes recovery-waits for an act that waits on the dump past its bound and
clears it once the act starts its work or ends, and writes aside-unrestored for each aside
only it holds the data of, cleared once the aside is restored or discarded. The bounds are
the settings points-filling-mark and dump-wait-minutes, read at the start.
Builds: design 47 G §561, §557, §564, §633, A-112, A-130
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The process reads its broker account, answers the seat mesh-recovery's verbs itself with the
caller the bus proved, takes and restores streams through mesh-sdk's bussnap, keeps the digests
in its state, names a kept data's bus objects from its catalog entry as mesh-sdk names them,
learns the fingerprint a module runs at from the node-engine seat's running and the bus
module's dumps from the backup holders' item events, each read whole at its start, and asks
the backup holder on its node to bring the points directory back. A restore whose
restore-started the bus did not acknowledge reads and sets aside nothing.
Builds: design 47 G §554, §516, §551, §556, §563, §567, §655, A-107, A-112, A-121, A-123, A-126, A-132
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The module's declared health check names recovery_kept_points: it answers what kept-points
answers with the health answer beside it, unhealthy while an aside only it holds the data of
is listed.
Builds: design 47 G A-129, §554, §657
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The take and restore of one stream is shared code in mesh-sdk; the bus module's keeper, its
nightly dump and its tools import it from there and keep no copy.
Builds: design 47 G §655, A-125
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Builds: design 47 G §554, §656, §657, §682
recovery_kept_points reads kept-points; every hand tool (take, restore, retry, aside, discard_aside, restore_aside, cancel, expire_points) is one verb of the seat called with the asker the tool runner proved; the bundle holds no grant of its own.
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Builds: design 47 G §516, §554, §656, §682, §691, A-107, A-115
Each acting verb answers one of accepted, busy or error; arguments are read afresh per call and refused when unknown (local-name, from, aside-only, discard-aside) or without why; restore takes exactly one of snapshot and request (request is refused until built); the hand-act log names the proved account and the asker.
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Builds: design 47 G §516, §554, §566, A-123, A-124
aside takes the bus names from the catalog entry of the fingerprint the node-engine's placement runs, takes the aside whole and checked, removes the live objects, says set-aside; restore-aside puts it back.
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Builds: design 47 G §516, §554, §560, §562, §563, §564, §566, §567, §682, §691, A-117
restore says restore-started, waits for the dump, finds the point (or has the backup holder bring it back), checks its digests against the bus, sets the live data aside whole and checked, removes it, restores the point and its consumers, and puts the aside back when a step after the removal fails; cancel ends a waiting act failed/cancelled with the hand act's words; at a start it clears temporary points, puts an aside back and ends a cut-off act failed/stopped.
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Builds: design 47 G §516, §551, §554, §560, §564, §567, §517
Accept writes the hand-act log first, answers accepted/busy/error at once and writes the act before it answers; take writes each stream under a temporary name, its digests on the bus before ended; the cap is refused before anything is written; expiry never removes the newest point.
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Builds: design 47 G §554, §656, §657, §633, §564, §557, A-107, A-115
The seat claimed once for the mesh with every verb of its definition; a process answering them (serves beside bus), a tools bundle, the data item points, the state digests (§567), the findings of §561, the four settings.
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The lead's answer B44: a lease the bundle before held in today's database
and still live at the run is written to `leases` under the bus's key form
with what is left of its lifetime, so no refresh races it whatever the
delivery's order; an expired one is counted read and not written.
Builds: design 39 bus-and-switch §4, §12, B44
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Review round 1, finding 5: the reading reads the grant under the licence's
lease (another run holding it reads nothing that round), and a grant the
vault refuses writes readError, keeps the percentages and goes on to the
next licence, so the conditions are still said after the round.
Review round 1, finding 6: these answers were built by earlier commits that
did not name them: B26, B27, B28 and B29 by M-6 (9cc62818), B30 by M-9
(39912119), B35 by M-11 (6cf98386); B23 and B24 by V-1 (e85cf002) and M-7
(5ca3876b), named again in b8e8be61; B31 and B32 in 36d9d739.
Builds: design 39 bus-and-switch §4, §16, §24, §31, B23, B24, B26, B27, B28, B29, B30, B34, B35
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Review round 1, finding 4: the vault hands a licence's access token only to
a machine a binding names, so licences_resync builds it from the grant (the
key itself for an API key) instead of reading it back.
Builds: design 39 bus-and-switch §15, §17, §42, B23, B24
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Review round 1, finding 3: adoptedFrom is the node a login came from, or
where an API key came from; a newer login of the same account keeps the
latest reading and generation the key holds.
Builds: design 39 bus-and-switch §2, §34, §46
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Review round 1, finding 2: a reader's first view taken while the carry-over
runs is brought up to date by the event said after each key is written.
Builds: design 39 bus-and-switch §12, §21
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Review round 1, finding 1, and the lead's answer B43. Until the vault's first
view of the licence bindings is answered since its start, licence-put's
access token is refused, saying why. A first view removes a consumer's key it
does not name only when that key was written before the view was asked. The
newer generation's binding staying over a first view (B32) was built in V-2's
keep and is named here.
Builds: design 39 bus-and-switch §17, B31, B32, B43
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
vault_first_views lists the licence bindings' first view beside the
assignments'; vault_first_view_again asks the one its new argument `of`
names, and both when it is absent.
Builds: design 39 bus-and-switch §52, §15 to §17, B21, B42
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The built binary played as its runtime plays it, its kept data in a real
nats-server's buckets and streams, today's rows in a real postgres: a start
stopped at a table says carry-over-failed and acts on nothing, the next
carries every row and a further one writes nothing; an unreachable database
calls no vendor; a reading at the threshold moves four consumers in one act
and no-room is raised and cleared on the operator channel's subject, read
through its client; a new login is adopted, listed and a target.
Builds: design 39 bus-and-switch §9, §11, §12, §13, §23, §26, §28, §29, §46, B41
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The licences verb answers each licence's organisation, latest usage with its
reset times, its room or why it is not known, whether it is where a full
licence's consumers move next, when and from where it was adopted and its open
conditions. The usage verb takes since, a limit of at most 2000 and raw. The
module's tools: licences_switches from the audit, licences_read_usage and
licences_switch_now with dry, licences_settings with the level mesh-config
answers (the manifest invokes its config verb), licences_kept over every
bus-state entry with its fill, licences_resync, licences_conditions and
licences_carried with its run, refused once carried. An acting tool waits for
the carry-over.
Builds: design 39 bus-and-switch §34, §35, §37, §38, §39, §40, §41, §42, §43, §44, §47, §20, §11, B9, B18, B40
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Each condition the manager holds is written in its state conditions with its
body and since, then said on the operator channel's condition accept under
claude-licence-manager, scope module; it is said again only when its words
change, and said cleared, its key deleted, once it no longer holds. At its
start, after the carry-over's run, it judges every kind anew: raised again
each it holds, cleared each kept key it no longer holds. The kinds:
carry-over-failed, settings.<setting>.invalid for a pair above
switch_at_pct and for a setting outside its bound, and per licence no-room
when the rule finds no target, near-limit at warn_at_pct with consumers, and
usage-unread once its latest success, or its adoption when none, is older
than usage_stale_minutes. Headlines name counts and short names, cut at 60.
Builds: design 39 bus-and-switch §9, §11, §29, §30, §31, §33, B17, B34, B36, B37, B38, B39
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
After each reading of a licence with consumers whose session or weekly
window is at or above switch_at_pct, the manager moves every consumer bound
to it, when switch_auto is on and the settings are valid, to the other
licence with known room whose windows are both below room_below_pct and the
most room, the first by name on a tie. Each consumer moves as the switch verb
does, by usage, and says binding.changed; the act says one licence.switched
and one audit entry switched with the window, its percentage and reset and
the target's room, and is told to the operator; the switch verb is not told.
By hand the rule runs with switch_auto off, and dry answers the moves alone.
Builds: design 39 bus-and-switch §26, §27, §28, §32, §33, B22
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The settings gain switch_auto, switch_at_pct, room_below_pct, warn_at_pct,
usage_minutes and usage_stale_minutes with the manifest's defaults and
bounds, a value outside its bound keeping the default. The settings file is
read again at every reading, each changed value written in the audit under
settings, and the usage timer follows usage_minutes. A room or warning above
switch_at_pct is found as an invalid pair naming both values.
Builds: design 39 bus-and-switch §33, §24
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
grantedBy is dropped: any caller of snapshot-get gets the chunks, a protected snapshot never.
The chunks are a transfer on the core bus, published with a core publish and kept on no stream.
Builds: design 47 G A-109 (G-20-lead-answers), §681
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
snapshot-get, snapshot-restore, snapshot-restore-cancel and snapshot-remove are answered by
the keeper's process with the proved caller; it publishes snapshot-get's chunks and hears
their acks on its own subscription, and acts at once with no hand-over through requests
(the record of a running restore is written before it runs). The tools bundle keeps its
tools, nats_snapshots among them. The protected refusal and the whole test's case (send,
restore in place, removal) stay.
Builds: design 47 G A-107 (G-20-lead-answers), §681
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The usage reading flattens the session, weekly and sonnet windows each with
its reset time, keeps it beside the licence with when it was read, and says
it as usage.read; a failed answer keeps the last percentages and writes the
vendor's status and reason. A licence's room is 100 less the higher of its
session and weekly windows, known only for a subscription read within
usage_stale_minutes whose refresh is healthy; an API key's is never known.
Builds: design 39 bus-and-switch §24, §25, §48, §2
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The manager consumes the agent module's holdings-changed, keeping each report
as its node's latest and considering them at once, in place of reading the
agent module's state; once it hears them, at every start after its
carry-over, it says holdings.asked with its time and who asks, so every node
says what it holds again.
Builds: design 39 bus-and-switch §23, §46, B12, B22
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The agent module asks the seat's current which licence it holds and its key,
then the vault's get for that licence's access secret sealed to its own key:
at its start, on a binding.changed with a newer generation than it applied,
and on the vault's secret-changed for the licence it holds. The applied
binding keeps the licence's key, so the vault's event is matched by the
carried key, never one formed here.
Builds: design 39 bus-and-switch §19, §18, B7, B9, B11
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The agent module consumes the manager's binding.changed, acting only on the
one naming its node's consumer, and each time it hears those events anew asks
the seat's bindings for its own consumer as its first view; its read of the
manager's bindings state goes.
Builds: design 39 bus-and-switch §22, B9, B10, B22
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The vault's get judges a licence's secret by a rule of its own, before the
asker rule: a grant goes to any proven caller, and an access token to a
machine on which a consumer's binding in licence-bindings names that
licence's key; a refusal names the rule and is recorded.
Builds: design 39 bus-and-switch §16, §17, A1, B3, B8, B25
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The vault consumes the licence manager's binding.changed and, at its start,
asks the seat's bindings until it answers; it keeps each consumer's licence,
the licence's key and the generation in its own state licence-bindings,
never an older generation, deleting a released consumer's key. The state is
in the vault's old state section, and holds no secret.
Builds: design 39 bus-and-switch §17, B2, B9, B10, B22, B25
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Each binding the verb bindings answers carries its licence's key beside the
§3 fields, as binding.changed does, so the vault's first view matches a
token's secret name to the binding without the key form of its own.
Builds: design 39 bus-and-switch §17, B10, B25 (hq 128236e7 and after, PR #561)
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Bind, switch, release, a login's move and a rotation's advance each say one
binding.changed per consumer moved, with the licence's key, after the key of
bindings is written or deleted; a switch through the verbs says one
licence.switched with the from, to, consumers, by and why the audit's
switched entry also holds. licence.bound, released and rotated are said no
more. An adoption advances the consumers already bound before it moves the
login's nodes, so each is said once.
Builds: design 39 bus-and-switch §21, §27 (the verb's switch), §36, B7, B16
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
At its first start the manager reads the six tables of its database, read
only, and writes them into its kept data and its grants into the vault at
generation 1, then carried.postgres; until then only its read verbs answer.
A second start never opens the database, and a stopped run is done again
whole without doubling a log entry. The store's write code and its postgres
test go: nothing writes the database again.
Builds: design 39 bus-and-switch §1, §8, §11, §12, §13, A3, B14
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Recovered from cfee5f2d (feat/47-G-buildmods).
Builds: design 47 G §571 (the build writes a mesh package's lock entry from the latest published version), A-56
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Recovered from 90d70b83 (feat/47-G-asks).
Builds: design 47 G §40; design 46 §6 Limits, batching, history (no ask hidden or refused for its asker's count)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Every reading is appended under its licence's key with the vendor's answer whole (ADR
0054), and every act under its kind, never rewritten; an act whose audit entry the log
does not take fails and says so. The memory store goes: the tests run the bus store over
a bus kept in memory.
Builds: design 39 bus-and-switch §6, §7, B20
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
A lease is a key created with a two-minute lifetime, which fails while another holds it:
the bus's own compare-and-set keeps one rotation source (ADR 0183 §6). An offered grant's
outcome is kept under its fingerprint in the key form for 90 days, every outcome kept.
Builds: design 39 bus-and-switch §4, §5, B13
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The state licences holds one key per licence by its key form, never a secret, with its
latest reading beside it; the state bindings, the same local name the consumers read,
holds each consumer's licence, kind, generation, since, why and by, written by the store
itself. Each consumer counts its own generations, past what its node reported.
Builds: design 39 bus-and-switch §2, §3, B11, B22
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The manager hands what the vendor answers to licence-put, the grant first and then the
access, at the licence's next generation, and reads a grant with get for one act; it keeps
no token at rest (ADR 0550 §3). The sealing at rest goes; opening stays for the carry-over.
Builds: design 39 bus-and-switch §15, §16, §20, §45, B15
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The vault hands every token (ADR 0550 §3); current names the licence, its key, kind,
generation, health and access expiry, and keeps the account's identity for the agent's
account file. bindings takes an optional consumer, answered unpaged.
Builds: design 39 bus-and-switch §18, B7, B10, B19
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The licence manager follows the nodes' holdings by an event and asks for them with
holdings.asked, instead of reading the agent module's state (ADR 0596 §2). The state
holdings stays the module's own.
Builds: design 39 bus-and-switch §23
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
A licence's grant and access token move into the vault (ADR 0550 §3), handed in two steps
with a key made for the call, as move-in does; the caller's generation is the record's,
an older one is refused, and secret-changed names the secret and its generation.
Builds: design 39 bus-and-switch §15, B3, B4, B5, B6
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
Pull request facts come from seat git's pull, ancestry from contains, the review time from the runner's review step,
and get shows one pipeline row per module (no run where the runner's list answers none).
Builds: design 47 G §654, A-75
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Eight bus-state entries in the typed long form; the old state and the reads of
claude-code.holdings go, and so does the run-once prepare, since nothing writes the
tables again. The database and grant-key stay as the carry-over's read-only source.
The manifest declares its new events, its consumption of holdings-changed, the
operator channel it uses, the verbs it invokes, six settings and its eight tools.
Builds: design 39 bus-and-switch §1, §9, §21, §23, §27, §33, §37-§44, A3, B9, B16
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
sudo and localization expect version 0.1; distribution and gitea read the old objects and state sections; mesh-build-go, mesh-knowledge, mesh-provisioner and mesh-self-check expect the findings asked in requires and the keeper's ask consumed. Each assertion failed against the changed manifest before it was changed.
Builds: design 47 G §368, §529, §584, A-30
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
A key of the bus takes fewer characters than a licence's name; the key is the store's
alone, and two names that write the same key would overwrite each other.
Builds: design 39 bus-and-switch §10, B6
Claude-Session: https://claude.ai/code/session_01NcbgfHb9d4T9nq5Q6WqdiJ
The healers' manifest already asks findings (template state) and finding-events (template events, the three finding events,
7 days, 16 MiB) and declares no old stream or findings state, and their writer reaches the state by its local name (built in
76be864b and the join); this adds the test that holds it.
Builds: design 47 G §529, §577, A-30
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The seat mesh-healers' attempt-changed carries the attempt whole with until (a week from its write), on the subject keyed by
the condition and the attempt, each escaped as a key's name is. The event is the seat definition's; the manifest's emits stays
empty as for healer-acted.
Builds: design 47 G §541, §665
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The node-engine's composed, running, wait-held and wait-ended make the have the hold compares with the wants; the healers'
attempt-changed makes an attempt, dropped at its until on the keeper's own clock (a bound with its own time to live) or when
removed. The manifest's reads are gone and its consumes gain the five events.
Builds: design 47 G §541, §665, §556, §499, §434
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
A findings-stated carrying kinds sets the keeper's view of that observer, node and set of kinds, and clears only the
conditions of those kinds it does not name; no kinds covers every kind. The finding events are taken from either form of the
part's finding stream, the observer and node read from the subject.
Builds: design 47 G §580, §529 (A-30), §383, §384
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
The keeper copies owner and waiting-on from the finding at raising (and into a condition kept from before G at its next
change), hands a pipeline-failed to operator-channel after the setting owner-handover-seconds (default two hours, timed
from the finding's since as a bound with its own time to live), says each change as the change owner, and the tool
conditions_owner sets an owner now, written in the hand-act log.
Builds: design 47 G §540, §685, §678, §557, A-58 (seed-waits: the indexer sets the finding's waiting-on; no kind rule here)
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
A module naming only the mesh's packages beyond typescript and the types needs no lock (gitea names the contracts' git and mesh-catalog packages); a row in the first test fails without the change, as does the catalogue's own run.
Builds: design 47 G A-56, ADR 0469 §5
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
incoming goes to the old objects section; transfers, idle (key-ttl), holds, windows, mirrors and findings to the old state section; the stream events becomes the old stream distribution-events (A-54, EVENTS being the mesh's own stream).
Builds: design 47 G §584, A-54, ADR 0619 §2
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
FindingScope is delivery, the scope the mesh already uses for the delivery's findings; the test names the literal (it failed with gate).
Builds: design 47 G §592, A-42
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
ask-bound-seconds and view-waits-seconds are read by the keeper's own code at its start (settings.go ReadSettings, stdio.Config), so the manifest marks them runtime: true; go.mod requires meshcatalogclient at the zero version, which cmd/mesh-conditions/branches.go imports (the requiredmodules check).
Builds: design 47 G §557
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
transfers, idle (key-ttl), failed-steps (history 1) go from requires entries to the old state section and incoming to the old objects section, as §584 has the forge module keep every state in its old sections.
Builds: design 47 G §584, ADR 0619 §1
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
claude-code, mesh-build-go, mesh-provisioner and mesh-self-check drop their old state findings and stream <module>-findings for the requires entries findings (state) and finding-events (events: the three finding events, 7 days, 16 MiB); mesh-knowledge gains finding-events and the consume. The manifest forms follow mesh-watcher's. The judge refused each for the old form (§529, §577) or for the missing stream or consume (§387).
Builds: design 47 G §387, §529, §577, A-30
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
mesh-delivery-builder.builder_versions answered no numbered version for any name asked (mesh-sdk go and ts, mesh-host, node-tools, mesh-delivery-builder, mesh-conditions), so every module takes 0.1, the floor §368 gives a module with none published: all 144 manifests (141 from "1", distribution, mesh-provisioner and mesh-provisioner-client from "2", which carries nothing over, §583).
Builds: design 47 G §368, §411, §583, A-46
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
Adopt subscribes a seat's event with further parts (<seat>.<event>.>), which never matches the plain views event of an owner; the reader's Follow hears it and asks again on a gap. Also the distribution whole test counts its own two events by subject, as the writer's are said beside them.
Builds: design 47 G A-28, A-26, A-30
The held writer reads the keys of its state when it is made, so it is made after Serve answers state calls; the keeper says a finding is not said before it exists.
Builds: design 47 G A-32, A-29, A-37
The test bus made buckets from the old state section alone, so a template state (deliveries, groups, owed, conditions) was 'not declared'; it now
makes a bucket for each requires entry of the template state under its local name (A-20).
Builds: design 47 G §613, A-20, A-33, A-34 (G-17, G-20)
Removes holder, table, approval, ready, onestatus, pullkey, checks, group_merge, the effects, the forge reads, the teller's
and the view's reads, kvOperator, kvPulls, delivery_merge_again and their tests. deliveries, show, groups and stalled answer
the records as kept (stalled: a record open past a day, and an act owed unanswered past 15 minutes, read from the record's
acts); the switch reads the old section deliveries and says approval-carried for each unperformed merges key. The manifest
drops pulls, asks, reads, the forge, teller and view consumes and invokes, and the events group and merged.
Builds: design 47 G §172, §431, §592, §593, §613, A-24, A-35 (G-3, G-9, G-16, G-17, G-20)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The writer listens to mesh-conditions.findings-asked, so each also consumes it, as the modules that moved before.
Builds: design 47 G A-30, §383, §686
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
WriterConfig.Asked is the generated mesh-conditions contract's SubjectFindingsAsked (A-17), a reader's Findings is the
module's writer itself (A-22, A-26), and mesh-build-go's single manifest ask writes and clears its first-view-unanswered
finding through the writer with the contract's Finding (A-28). mesh-config and mesh-vault's own followers (A-28) are not
yet moved onto a views.Reader: they do not compile at mesh-sdk 24f876a.
Builds: design 47 G §687, §689, A-17, A-22, A-26, A-28
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
artifact-store-tools (image-missing, sweep-refused), distribution (program and tools bundle, one writer each over its own
kinds), gitea's package-registry (and the token-refused key the TypeScript bundle watches) and mesh-config keep their
findings open and write and clear them through the generic writer; mesh-vault states its assignments view's. A part of an
id told apart by a ref is in the id (<id>.<ref>), each escaped; the writer starts once Serve has the runtime's channel; the
removed findings helpers and resolved words go.
Builds: design 47 G §686, §687, §689, A-3, A-14, A-16, A-22
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
merges and source stay in the old state section; pulls and asks wait for the removal of the merge states.
Builds: design 47 G §613, A-8, A-20 (G-17, G-20)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
nfs-server, minio object-store, claude-code, mesh-watcher, mesh-provisioner and mesh-build-go hand their views reader
views.WriterFindings over views.NewStdioWriter and start it; the removed meshconditionsclient.FindingWriter goes.
Builds: design 47 G §686, §687, §689, A-3, A-16, A-17
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
GATE17: record.go Remove asks buscalls.LedgerRemove, recordfill.go reads buscalls.Fill, the manifest names ledger-upkeep-calls.
GATE11: the verb settle, its ask, EvSettled and the Settle field leave with the merge states.
Builds: design 47 G §587, §431
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The gate's source value is the contract's SourceByBranchValue and its key SourceKey(branch); the verb takes an optional
branch and answers branches alone when given none. The whole-module package does not compile on the join for GATE11
(settle) and GATE17 (ledger fill and remove), so the unit suite was run with those five sites stubbed in a scratch edit,
never committed: green apart from the stubbed removal case.
Builds: design 47 G §690, §614, §15
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Reverts bbd9f638, c2e017a4 and b6884796; cmd/mesh-nats-snapshot/restore.go is as before them. The manifest test
asserts the claim serves only the reading verbs and the keeper's state is asked, requests, spent.
Builds: design 47 G §554, §555
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The gate reads its records' ledger fill before it opens a record; its manifest asked no
capability, so it could run beside a runner answering neither. It now asks ledger-calls and
ledger-fill, the fill a capability of its own.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from c20044a2.)
Builds: design 47 G §181, §462, §488 (GATE12)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
ADR 0659 §4 kept three description reads that shape words only until they move to the bus: the
issue numbers the ask names, the author a stalled line names and the notice that after: lines are
not read. The ask now names the issues linked to each member's pull request, read once per head
through the seat issue-tracker's list (a tracker that does not answer is said, never waited on);
the author is the forge's pull request record's, from the seat git's events; the after: notice is
gone. The gate's forms of a pull request and a delivery hold no description field.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from ddd93a78.)
Builds: design 47 G §50, §143 (GATE15)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Design 47: a store filling is said before it is full. The gate reads its ledger's fill through the
tool runner's mesh/ledger.fill, says filling of the seat mesh-delivery when a record takes the ledger
past 80 % of its cap, refuses the next record when none fits and says full naming it, and keeps the
merge waiting for room on its delivery (held_full), so a restarted gate judges alike. Once the
ledger is below 80 % again, after the retention's removals, it says room and hands the merge.
gate_records says the fill against its cap, or why it is unread.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 061be00d.)
Builds: design 47 G §181 (GATE12)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
ADR 0661: the check gates the ask, in one place (askWaits); once the Approve covers
the heads (approvedWaits) no verdict, carry, composed check or required status is
judged, an Approve given before a trunk move merges onto the new trunk, and a
failure after the Approve is said once on the pull request and as a stalled line
naming the merge it follows. A check failing before the answer withdraws the ask.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 43696644.)
Builds: design 47 G §278, test 52 (GATE10)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The module's own manifest is embedded (package at the module's root); an event the gate hears from another module is
the consumes entry with that event's name after its owner. No new seat, no second publisher on the seat git (the
lead's ruling). Rows in the manifest test, which also reads the gate's sources for those names.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 2de87fd8.)
Builds: design 47 G §7, §146 (GATE16); the bridge's name stays in code for the old merge follower (eb131beb left out, G §167, §542)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Every key of owed, and the member merging in every key of merges, is said as owed under
meshdeliveryclient.SwitchedActID(state, key, revision), at every switch, the same act each time. The switch reads
the old states through one reader (OldState). Rows in the switch's test.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from dd0c4294.)
Builds: design 47 G §169 (GATE5, GATE6); only the owed carry: the member merging in the old state merges is not carried as a merge act (G §167, §542)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
At the gate's start every unanswered act is said again under the same id; an outcome is written into the record that
holds the pull request, then answered; an outcome other than performed is said; the checker's are not the gate's.
Needs the forge bridge's forgemsg owed.ended (feat/47-G-forge).
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from cf3715ea.)
Builds: design 47 G §162, §163, §164, §165, §166 (GATE5)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The base's protection and required contexts, the forge's conflict word and the merging
account's write access come from the pull answer's merging (issues 1275, 1945; ADR 0441 §1);
a required context not a success at the commit blocks.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 13e12d2c.)
Builds: design 47 G §252, §310, §312 (GATE14)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The gate named the forge module's tools and events and guessed their answers' shape (operator (d), F14).
Its reads now are the seat git's verbs pull, statuses, open-pulls and contains, typed in the seat's
contract, a failed read an error and never none; its forge events are the seat's pull.updated,
pull.merged, pull.closed, forge.pull, forge.status and repo.writable, read into the gate's own forms
in one place (gitseat.go). What the forge would merge now (the base's protection, its conflict word,
whether the merging account writes) has no verb of the seat yet: it stays the one read of the
forge's statuses tool, named as such (mergeStateTool), until the seat carries it.
The bus tests' runtime now serves the gate's ledger, so the two whole-bundle tests that failed
since W11.1 pass again.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 14338514.)
Builds: design 47 G §252, §310, §312, test 51 (GATE14)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Design 47 (The switch carries today's state in, once): at the gate's start, before any event is
taken, each group in flight becomes a record keyed by its milestone and its heads (the heads its
merge was approved at when merges holds one), with that merge as its group state; a second switch
finds each record there and opens none, so a restart or a delivery of milestone G again after a
revert asks nothing again. From then on every merge the gate hands is written into its record too,
so the record's outcomes are found by its members' merge commits.
Left for W11.17 and W11.14: the merge handed as an owed merge-pull instead of the merges key, the
owed keys carried, and merges and turns no longer declared.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from e9415814.)
Builds: design 47 G §156, §220 (GATE4)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Design 47 (The delivery record): the outcomes arrive as events through the module's durable
consumer, each applied once and only from its owner's account. A family per step event names the
pattern the manifest consumes, its owner and whether its subject names a node; an event is applied
only when its key names its owner and, for a node's event, its x-node is the node its subject
names. It is taken once its outcome is in every open record holding it (by a member's merge
commit, or by the entry of the record's graph difference), so one the ledger did not take is
offered again; an unreadable one is said and taken. The indexer's take-in.taken is the first
family; each other step's event joins the table with its owner's contract.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 4c4d1239.)
Builds: design 47 G §34, §141 to §146 (GATE2)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
ADR 0656 §7 and design 47 (The delivery record): the gate asks the bus module for a ledger
`records` (template ledger, capped at 768 MiB) with two types: a record, keyed by its milestone and
its heads, whose operations open it, write its group state, trace, outcomes, nodes away, pinned
revisions and end, and remove it; and a month's list of the records opened, since a bundle cannot
list a ledger's instances. An open of heads already recorded leaves the record as it is, an outcome
applied twice writes nothing, and each open removes the records past the setting record-retention
(90 days by default), naming each revision they pinned. The layout is the gate's own (design 20).
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 84eda463.)
Builds: design 47 G §141, §142, §143, §144, §145, §146, §155, §34 (GATE1)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Design 47 lines 1888-1906 at b229f5c4 (test 60): the verb sits in every build seat's definition.
Its judgement (what may be kept, the kept builds a node holds, the three refusals) is shared code of
one domain's modules, so it is the domain SDK's (sdk/buildstep KeptArtifact, ADR 0634 §2):
mesh-build-go keeps its store, sweep and tools and drops its own copy of the judgement and its table;
mesh-build-node and mesh-build-image keep no build and answer over none, so a module claiming no
oci-artifact-registry is refused and the holder is answered not kept. Their manifests serve the verb
and invoke seat:mesh-catalog.module, which the judgement asks.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 42d364fe.)
Builds: design 47 G §271, §464 (BLD9)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Builds design 47 *The artifact store's holder takes its own new build even
when its seat is the one broken* (lines ~1811-1830, test 60): a trunk build of
a module claiming oci-artifact-registry that the seat refuses or does not
answer is kept as an object by digest and answered kept (BuildAnswer.Kept);
kept-artifact answers its store and object, refusing a module that claims no
oci-artifact-registry, one not kept here and one under another digest. The
store is the template objects (ADR 0666 §4: a part outside the foundation keeps
its data in ADR 0595's templates; design 47's "old objects form" contradicts
it for a non-foundation part, reported). Whether a module claims the seat is
asked of the seat mesh-catalog's verb module (ADR 0596). Callers are left to
the seat definition and the grants part (ADR 0666 §20). build_go_kept reads the
kept builds, build_go_kept_drop drops one (ADR 0666 §25).
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 5e1cdade.)
Builds: design 47 G §271, test 60 (BLD9)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
A test step runs only the packages with no kept result for their digest, and the runner makes
that carry in the checker's place (ADR 0666 section 8; design 47 *Carried, not run* line 593 at
hq b229f5c4): the kept results reach the step in its ask (StepRun.kept, mesh-delivery
dc0df1b5), so the module's reads lose mesh-delivery-checker.kept and the lookup of the
checker's kept bucket goes. The carried and kept packages are in the step's end, on its step
key.
Milestone 47/G, research 086 area C (K1).
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 1c991294.)
Builds: design 47 G §25, §27, §66, §416 (BLD5)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Lint is a pipeline step of its own, served by the build seat (ADR 0666 section 7; design 47
*The steps and who serves them* line 571 at hq b229f5c4), so the unit level runs tests alone
and the lint step runs gofmt and go vet, with every tag the files name, over each go.mod
directory of the artifact's module directory; a module directory holding no go.mod has
nothing to lint (prepare finding F12).
Milestone 47/G, research 086 area A.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from a46e01a2.)
Builds: design 47 G §328, §417 (BLD6)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The runner asks a lint or test step of an artifact as the build seat's accepted kind step, and
hears its end as the seat's step-ended on the node that ran it (ADR 0666 sections 7, 8, 21;
design 47 *The steps and who serves them* line 571 and *Asked on a work queue, ended by an event*
lines 583-590 at hq b229f5c4). The build modules' shared package runs a test step as a check of
its one level, carries the packages whose digest the ask names kept, keeps what it passed and
says the counts; a level with no tests ends nothing to run, a source fault could not run, and a
transport fault or an end that could not be said is handed back unsaid, so the work queue gives
the step again and it ends once under its ask's id. The neutral forms are the domain SDK's
(sdk/buildstep pipelinestep.go, mesh-delivery dc0df1b5); the Go module says the end through the
runtime's seat publish.
Milestone 47/G, research 086 area A.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
(Joined from 72fee3c6.)
Builds: design 47 G §22, §24, §86, §116, §140 (BLD3, BLD4)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The container image and OCI artifact seats' holder asks the seat mesh-builds' verb reserved in place of builder_versions; the manifest
invokes it and takes no builder package.
Builds: design 47 G §381, §478, §504
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The holder asks the seat mesh-builds' verb reserved with the publish's name and version in place of builder_versions, and stores
only a version reserved for an artifact of the publish's digest; the manifest invokes the verb and takes no builder package.
Builds: design 47 G §381, §478, §504
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
merge-pull refuses a head at whose fingerprint a run failed a required step (policy-failed, naming run, module, step), from the
module's own state failed-steps kept from step-ended, with the seen keys of every step end and the deletion once no watched
branch's head nor open pull request's head names a commit. The two tools read it with its fill and drop a key after the hand act.
Builds: design 47 G §39, §83, §84, §85, §135, §475, §487, §548
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The fixed Observers list and the engineModule constant are removed; sources are the modules whose catalog entry declares the
finding events, a module in no branch's revision is cleared (module left the catalog), a stopped module no longer placed is
cleared (module left the node), Keeper.Holder is derived from the entry's claims. The per-branch catalog followers in main.go
wait on a design question (how a part adopts one catalog view per registered branch); the whole integration test is red until then.
Builds: design 47 G §365, §196, §200, §364, §384
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Sends reads a claim of a seat whose definition has a verb or an event, or an event of its own; AsksOf reads
an entry's bus-state asks and claims. The follower's branch and the wiring wait on the design's answer.
Builds: design 47 G §344, §433
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Each of the six declares the stream <module>-findings (finding-written.*, finding-cleared.*,
findings-stated.*, 7 days, 16 MiB) and consumes mesh-conditions.findings-asked; the manifest
tests that hold consumes say it. The other observers' manifests are written by their own families.
Builds: design 47 G §387, §383
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
An observer on a machine away is not named in findings-unstated; a machine back has its
observers asked again (mesh-watchdogs machine-away and machine-back in consumes).
Builds: design 47 G §389
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
resync writes the hand-act log, says findings-asked for every observer or the one named and
settles what it holds; an observer silent five minutes after an ask (bounds state, key time
to live), its machine not away, is the keeper's finding findings-unstated of scope module,
cleared by its next findings-stated; conditions_findings_views answers each observer and node.
The nodes asked are those heard (the kept list of COND2 is stopped on a question).
Builds: design 47 G §390
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Verbs snapshot-kept and restore-kept (with aside-only and discard-aside) on the seat mesh-broker, handed to the
keeper; taken over from the join's 0480e16f and c4e88eaa, without the verbs aside and discard-aside and the tool
nats_kept, which no design line gives.
Builds: design 47 G §296, §297, §302, §337, §405
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
findings-stated raises what is new, keeps each pending key unchanged, clears every other
condition of the observer on that node with its reason, clears a pending key past its bound
(bounds state, key time to live), and for an observer held once takes the holder's set and
later events only. The holder lookup is a hook (Keeper.Holder) that COND6 wires from the
catalog; the view is kept in memory until COND2 keeps findings-views.
Builds: design 47 G §384
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The store is made by Keeper.Sends, kept when a verdict asks nothing of it, and a full one says `full`.
Which module sends is NATS3's input (the catalog half); this makes the store.
Builds: design 47 G §59, §137, §344, §477
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The keeper takes finding-written and finding-cleared from each observer's stream
(`*.finding-written`, `*.finding-cleared`, `*.findings-stated` in consumes); its reads of
every `findings`, the views.findings consumes and the read_findings invokes go.
node-engine's name is a local constant since mesh-sdk's buscompose lost it.
Builds: design 47 G §383, §386
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The base "main" fallbacks of the open-pulls read and the announcer are gone (the indexer's module name and tool went with GIT10).
The manifest's version is MAN1's, written with the fill's source it needs.
Builds: design 47 G §7, §428
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The config value callers, the package seats' list of callers with its watch, and the seat git's caller judgement are gone:
the grants part grants by each definition's callers and the bus refuses the rest.
Builds: design 47 G §68, §127, §313, §321
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
A tag at that commit is answered performed; at another commit, refused (a tag is never moved). The builder alone calls it:
the bus refuses any other account from the definition's callers.
Builds: design 47 G §370
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
merge-pull answers its refused-kind (head-moved, unprotected, git-refused, no-registrations); an already merged pull request at
that head is answered performed. The failed-steps refusal (policy-failed) is GIT7, stopped on a design question.
GIT9: registrations.ts learns the first registrations from the seat mesh-catalog's verb registrations at the start and its event
registration-changed; the code artifact needs mesh-delivery-assigner:program.
Builds: design 47 G §38, §129, §314, §95, §96, §130, §353, §432
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The four share files (index.ts, module.json, guard.test.ts), so they land as one commit.
GIT1: seat.ts serves pull, open-pulls, tags, trees, file, contains, statuses, status, comment, view, note, merge-pull
as tools on the seat, each answering the contract's shape and an error of kind refused, not-found or failed; a comment,
view or note whose act id is held is answered held (note matched by id). merge-pull merges the head the caller names
(its from-G judgements are GIT6, GIT7, GIT9).
GIT2: seatevents.ts says pull-updated, pull-merged, pull-closed, forge-pull, forge-status, forge-delete and repo-writable on
mesh.seat.git.event.<event>; the module's emits drop them.
GIT3: merge.ts, check.ts, the acting tools, the owed watch, the gate's source read and check-gates-merge are gone.
GIT10: catalog.ts follows the seat mesh-catalog (revision, catalog-revision); no write is granted before the first view.
Builds: design 47 G §310, §311, §312, §313, §314, §163, §317, §278, §321, §196
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Node answers the type-check as lint always, unit where a package has a test
script and integration where it has test:integration, kept in detected-steps by
fingerprint as the Go module keeps it; the image answers none. The manifests
serve it. The step ask's end (step-ended) of BLD7 and BLD8 waits for BLD3 and
the build-step package of mesh-delivery-sdk.
Builds: design 47 G §22, §307, §326, §328
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Part of BLD15: the manifest's stream mesh-build-go-findings (the three
finding events, 7 days, 16 MiB) and the consume of mesh-conditions.findings-asked.
The module's writing of findings through mesh-sdk's finding writer waits for
the writer (the writer's API is an open design question, D-16).
Builds: design 47 G §383, §384, §387
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The Go build module asks the input verb in the ask (the checker's, the
indexer's mesh-catalog input or the assigner's mesh-wants input) and its
manifest invokes the two seats' verbs. The bus refuses the other accounts
(grants of the contract's callers). The step key keeps the contract's form
<node>.<id>: no asker part is named there (question to the lead).
Builds: design 47 G §125, §206, §338, §354
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The Go compile, the Node tsc/esbuild/npm and the image's buildah bud get the
build argument MESH_VERSION from the version the build ask carries. The late
publish on version.numbered goes (code, tests, the consumes of the Go and
image manifests). The image's label and tag and a program's stamp are open
(question to the lead): the design names no key or symbol.
Builds: design 47 G §349, §370, §413
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Part of BLD2 (Go module): the state detected-steps asked by the template
state, one key per artifact, answered for the same fingerprint, replaced by a
newer one and by again. The drop of a key and the Node and image modules wait
(drop: question to the lead; the others follow in BLD7 and BLD8).
Builds: design 47 G §326, §414
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The verb fetches the artifact's tree and answers lint always, unit and
integration steps by the packages holding test files (integration by the tag),
a level with no test left out; the manifest serves it.
Builds: design 47 G §22, §307, §28
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
An event whose subject carries parts is published by a function taking each part and heard by a filter with a * per
part; an event naming keep gets the stream SEAT_<seat>_<event>, in Go and in the TypeScript contract. The reader of the
sdk's reader release reads acts (every, a language, kind:image), keep as an object and callers as a list.
Builds: design 47 G §89, §203, §238, §260, §324, §331, §396, §397
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
A seat's npm package holds index.js, index.d.ts and parts/<part>.js with .d.ts, with no TypeScript source and no
tsconfig.json, so a TypeScript module imports it with no build step and no tsc of the contract.
Builds: design 47 G §341
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
The generator checks each verb's and accepted kind's callers in a definition and a part before reading it, naming the
file, the verb and the entry; text is refused as one entry; the contracts it writes carry no caller check.
Builds: design 47 G §336, §339, §392
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
mesh/check checking ae056a44dd72 on 9dfb2eae0eb3 | novox/mesh-catalog#656 in group fix/1966-bindings-first-view
Held.binding is the entry's plan binding, the value its created and recreated
carry, present when the bus holds the entry's objects and absent on one it does
not (waiting, refused). Table rows in the reading verbs' test: the binding of a
held entry equals the one its created carries; a waiting entry has none.
Builds: design 25 bindings-first-view §2, §7 (hq d0760629, PR 543)
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
go mod download loads only the module graph a go.mod names; a vet, a test or a build then loads
packages shut off from the network and failed far from the fetch, in fewer words (the builder's
"pull_drop.go:11:2: module lookup disabled by GOPROXY=off"). After each directory's download the
fetch loads its packages with their tests shut off and fails naming each package whose load
would reach the network. The graph of a sibling laid beside is loaded once with the network
first, so a go.mod the composer's build reads and the graph's download skipped is fetched, then
proven the same way.
1966/AC178-2: a row of TestAVerifyThatFailsEndsTheStepNamingTheDirectoryAndTheLine; the beside
case in TestTheFetchDownloadsTheGraphOfASiblingModuleLaidWithTheTreesItRequires.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
ADR 0573 §2 builds every module against the latest published version of each mesh package it
uses, whatever its go.mod names. The fetch took versions only for packages the directory's own
go.mod names, so a package only a module it replaces by a directory requires (mesh-build-image
replacing buildstep, which imports the node-build-go seat package) was never taken: go mod
download passed and every shut-off step looked it up on the network. Now the requirements of
each module the directory replaces by a directory count too, taken the same way (the ask, its
repository's asked head, else the latest) and said as named by that directory.
1966/AC178-1: rows of TestARequirementAtTheZeroVersionIsTakenFromTheAskOrTheTrunk.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
Since buildstep's drop verb imports the node-build-go seat package, both modules' shut-off vet,
test and build looked it up on the network: their go.mod did not name it, so the fetch took no
version for it. go mod tidy adds it as an indirect requirement.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
mesh/check checking c39503e3227c on c4463ba47fcf | novox/mesh-catalog#650 in group fix/1966-seat-list-unread
claude_code_seat_list_again answered person.<name> and the healers, but every
call through the mesh MCP server is proved as its machine's tool runner
(issue 627); node-tools now stands for that session (issue 1966).
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
ace's node-engine wrote seat-list-unread in its state findings, and no
condition rose: the keeper's observers did not name the node-engine. It now
reads mesh-host.findings, so ADR 0636 §1's condition is raised and clears at
the first full read (issue 1966).
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
GOPROXY joined the Go seat, the public proxy and direct with commas, so go went on only after a 404 or 410: a contracts
package the seat does not hold, and a public proxy a node cannot reach, ended the fetch before direct. It joins them
with | now, so any failure goes on to the next. go words a proxy it cannot reach as "invalid version", which the pin
path read as an unknown revision and labelled "on no pull request head"; a network failure is never that now
(network is unreachable and no route to host are network failures).
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
A lost event between a shared stream and a module's consumer could not be located: no tool read a consumer's delivered and acknowledged sequence or a stream's messages for one subject. nats_consumer reads from the monitoring document; nats_stream_messages asks STREAM.MSG.GET on the module's own credential, newest first and bounded.
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
hand-acts read the whole log (84k entries, 47 MB) on every call and could never answer inside the call bound or
the bus payload. It now reads from the newest entry backwards, page by page, and stops at the window's start, at
900 KiB of acts or at 20 s, saying complete: false, cut and why. warrants is bounded the same way. mesh-healers'
start-up seed takes a partial answer and logs it, instead of retrying forever.
Quick fix: this (mesh-catalog only, about 1.5 h). Thorough fix: also the tool runner never freezing on an oversized
bundle line and logging unanswered calls (mesh-tools, a separate fix by another developer, lead's ruling Q3), and an
SDK-side bound. Chosen here: quick for this module, the thorough part running beside it; the byte cap is the
module's own (lead's ruling Q1, a `limit` argument is a later note).
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
mesh/check checking 4e2a1a5a1f58 on 503411e6289b | novox/mesh-catalog#640 in group fix/1966-checker-compositions-objects
The checker sends a large node's request packed, as it passes the bus's message limit; compose reads either form through
ComposeJob.RequestBytes. Only mesh-build-go serves compose. Delivered as a group with the mesh-delivery change of the same
branch name: an older mesh-build-go refuses a packed ask naming that it holds no request object.
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
mesh/check checking 80186d079808 on 6a24e4d0c77e | novox/mesh-catalog#639 in group fix/1966-forge-made-merge
Merges made on the forge directly since 2026-11-09 07:04 UTC have no gate merge record,
and the indexer holds them; an empty merge through the gate covers this repository's head.
Second of its kind: the group's mesh-delivery member removes the need (the forge bridge
reads a forge-made merge's pull request from the forge).
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
Not read is not unneeded on the newest scope too (issue 940's rule): a module whose newest composition is
unpublished or refused is held at its newest build, said in provisioner_plans newest-held and bounded on the health.
A retiring key needed again cancels its ask on operator-channel (accept.cancel), retried until the router takes it.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
The composer finds a listen's machine port in a container mapping that names
it on either side (MachineSide). The program's listen 5000 matched the
registry container's inner 5000 in 127.0.0.1:5001:5000, so the store's address
became the container's loopback side and the program's own port was never
opened: the move to 83cd1a3d on 2026-11-08 23:25 UTC cut the artifact store off
(issue 1966 note 109). The program now binds 5100, where every machine fetches
(the artifact-store alias and the seats' reach agree), and the container serves
5001 inside and out. A row holds that no container names 5100.
Undo: revert this commit.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
nats_keeper_health found the keeper's consumer novox_nats_keeper in /jsz, but the read it shares with the
broker verbs asked /jsz?accounts=1&streams=1&config=1, without consumers=1, so keeperPending always read -1
and the keeper was "unhealthy: what waits on its consumer cannot be read from the bus's monitoring" for
ever (2026-11-08, issue 1966).
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
mesh-knowledge's stream reviews says max-age-days "none", which the indexer's judge accepts
(judge/busstate.go noAge), but the keeper refused it ("not a whole number"), so the stream was
never made and the keeper stayed unhealthy (2026-11-08, issue 1966). Quick fix; the thorough one,
one shared reader of the template options in mesh-sdk catalogue for the judge and the keeper, is
noted on issue 1966.
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
The two server lines were literals in the template, so changing an upstream needed a build. They are now the config keys upstream-resolver-first (1.1.1.1) and upstream-resolver-second (8.8.8.8), placed with ${config:...}; the service already restarts on its config file. no-resolv and every other line stay.
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
The caps were literals in server.env and the container named no restart-on, so a changed env-file never reached the running forge. They are now three gitea config values placed with ${config:...}, and the server container restarts on server-env.
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
mesh/check failed (3): ace: the check of novox/mesh-catalog#632 failed: downloading the asked version 68581…; and 2 more | b4192c525e7e on 61737962fcb6
Kind: short package names (builds, sshkeys, forgemsg, backupgood,
diskreadings, grantsstate, busgrants) in `packages`, which the indexer's
judge refuses by design 32's rule (a Go package is named by its go.mod's
module path). This held mesh-delivery-gate, the build modules, mounts and
restic. Each key is now the import path the module's code uses, with its
series kept; the manifest tests read the new keys, and the host/machine-name
word tests in mounts, nfs-server, mesh-build-node and mesh-delivery-gate
look past the path's `git.novox.be/novox/` prefix.
Quick fix: only the gate's manifest. Thorough fix (chosen): all 15, since
the same refusal holds each. Follow-up for the checker: the candidate
verdict lets such a name through (J7(3)), so the merge check did not stop it.
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
The operator, 2026-11-07: remove any gate that reads a description. An unreviewed pull request whose
other waits are met is asked, and the ask names no review line.
Claude-Session: https://claude.ai/code/session_01NcbgfFfQ4Z9UE5jK32PmE5
With check-gates-merge false (the configuration seat's value) the gate still held the Approve until the check had
a verdict (verdictWaits), so a one-line recovery waited half an hour for a whole-suite check it does not gate. The
operator, 2026-11-07: 'we aren't running any checks anymore, we're delivering'; 'disable the check'. The Approve is
now asked once the delivery is reviewed and ready; a later verdict is still shown and asks the pending Approve again
in its words. Tests follow: asked at once with no verdict or a running check, a group too, a re-pushed member too.
Merged by the session as a recovery fix (instruction recovery-fixes-merge-and-tell), the operator told on Telegram.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh/check checking 83732dcd53d8 on 9a3356bd38b1 | novox/mesh-catalog#627 in group fix/1966-bootstrap-no-packages
The running builder predates Go package artifacts ("refused kind: package of language go ... no build module
builds it"), so it can build neither the new builder, the grants module, the Go build module nor the checker:
each new part is needed before the others can be built or delivered. For the bootstrap of the registry
delivery, at the operator's word (19:4x, "do the temporary change"), the package artifacts leave the manifests of
the parts that run; the contracts and SDK modules, which run on no node, keep theirs. They come back in one change
once the new builder runs. Quick vs thorough: quick; the thorough fix is 47/G's tier order (issue 1921 note 80).
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh-catalog #625 offered artifact-store again with serves port 5000, copied from the manifest before the
registry milestone. The running node-engines turn that port through the ports the node assigned the module; with
the milestone's manifest the assignment no longer turns 5000 into 5100, where the store's container has published
since 2026-10-04 (docker_ports on novox: 0.0.0.0:5100->5000). Since #625 was taken in, novox fetches from :5000
and is refused (node-engine journal 18:54: connection refused), while the store's log shows fetches on :5100
until 18:47:52. The alias now names 5100. Removed with the alias once every node-engine runs the milestone's build.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
The registry milestone renamed what distribution offers (container-image-registry, oci-artifact-registry,
mesh-artifact-store), as ADR 0632 section 3 decides. The node-engines running on every node are the ones
from before it: they find the store through the provision artifact-store, so they fetch no new build,
including their own successor, and keep running what they ran. ADR 0632 section 2's guarantee (no node loses
the store while its engine reads it the old way) lives in the new indexer's hold, which the running indexer
predates. So this goes against ADR 0632 section 3 for a limited time, at the operator's word (bootstrap of
2026-11-07, no new record): offered again beside the new roles until every node-engine runs the registry
milestone's build, then removed in the next change to distribution.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh/check failed: shanks: the check of novox/mesh-catalog#624 failed: downloading the asked version 54aff0a3d9201e3df2… | 77b30bd2966c on f2b332de73d6
The group check of 8a80e8e86858 laid every Go module beside the check, and one of them (mesh-delivery's
mesh-grants, which now requires disk-load's diskreadings) required a catalogue module the catalogue under check
never lays beside itself: Go looked its zero version up and the composer did not build.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh/delivery-group group feat/registry-milestone rejected: composed together: the checker's verdict at the members' heads (8a80e8e86858): unit: git.novox.be/n…
mesh/check failed (4): unit: git.novox.be/novox/m…; and 3 more | 62fe1cc36d30 on f2b332de73d6 | judged by the candidate's mesh-build-go at e8757a23634d
Quick fix: add the one require to mesh-build-go's go.mod (a minute). Thorough fix, chosen because the kind was met twice (a
local go.work resolving what go.mod never names) and hides itself from every local build: checks/requiredmodules reads every
go.mod and Go source (tests and tagged files included), finds the owning module by the longest module line among the
repositories beside, and fails in go test and the repository check before any push. The scan over the seven group heads
found this one instance.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh/check failed (3): ace: the check of novox/mesh-catalog#612 failed: the unit level: the candidate's mes…; and 2 more | 7bf15a3dc4db on f2b332de73d6
mesh/check being carried to c8bcb2cdf567 on f2b332de73d6 | from 980ade933853, hq 885099eebbbd, mesh-delivery 2d201f781ced, mesh-sdk c1b50e99a639
The operator's answer: reading mesh-delivery-checker.inputs broke ADR 0596 §2. The manifest drops that read and invokes
seat:mesh-delivery-checker.input; the run step asks the verb through the runtime (stdio.Ask) and takes only the bytes
the ask names (delivery.RunInput.Read).
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
Go 1.27 looks the zero version of a workspace member up once a build loads the module graph; a versioned replace is the
form it takes with no lookup. workspaceOf writes the use list and those replaces, and a unit case loads such a graph with
GOPROXY=off. The only go.work the build path writes is this fixture's: the build module itself places requirements by
replaces in its modfile (pins.go), which are unversioned and not in a workspace, so they are untouched.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
The release read the versions from the untyped fetch's packages argument; the group's ComposeJob carries them in
buildstep.Fetch.Packages, so the group's form stands, and the release's check that the key differs for named versions
joins the existing test.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh-build-go keeps trunk's zero-version resolution on the group's mesh-delivery sdk types; mesh-build-node keeps per-path packages with the builder's version and seat.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
The legacy key form placement.<node> is gone from the client, so the readers and their fixtures lose it. The check noplacement
now also refuses the assigner's retired names in a manifest.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
It could not be changed at all: propose refused a name set there and never replaced one. The ask now says plainly that
it replaces or removes the registered section and binds its text's digest; on Approve every node renders the new text
in the place of the old (a removal leaves it out); a replacement keeps the section's own heading form (issue 340 note 14).
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
A key form such as <node>.<module>.<key> made the parser declare the parameter key and the part key together (TS2300 Duplicate identifier), which the per-package unit level now surfaces. The parameter and the locals are now _key, _rest and _at<n>; a test row with such a form fails on the old output. Issue 1966.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh/check failed: integration: mesh-vault/cmd/mesh-vault.Tes… | 1feda1f533b8 on 559939aa8ce1 | judged by the candidate's mesh-build-go at 87d30b709d68
A go.mod requirement of a forge module at v0.0.0-00010101000000-000000000000 names no commit; the fetch looked for the commit 000000000000 among the pull request heads and failed. It is now taken from the commit the ask names for the package, else from the head of its repository among the asked versions, else from the latest published version.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
A folder module (the contracts folders) declares several package artifacts under ts/seats/<seat>/, each with its own package.json and lock and none at the module directory; the fetch asked for a lock at the module directory and failed the group's check. The fetch installs, the build packs and the test level runs at the artifact's path; an artifact naming no usable path keeps the module directory. The module's .gitignore anchors the binary's name so the command directory is not ignored.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
A member's go.mod names the oldest version a module accepts; the check builds the group's own heads whatever it names. go.sum lines of mesh packages are left out.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
catalogue's SeatReference, InRegistrySeat, Routed, Recorded, InArtifactStore and ArtifactSweepSeat leave mesh-sdk;
each package gives the two registry seats' names from their contracts (or the build step's copies of them).
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
The part build-step lacks the check job's toolchain and types the check answer's fetch as the fetch arguments; both are kept in askrun_gaps.go until the part has them.
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
mesh/check being carried to 5ceb6e9e38a4 on 211186edd769 | from fd4931a75261, mesh-delivery ae31b66a9e33 | novox/mesh-catalog#615 in group feat/take-in
mesh/check failed (2): mesh-build-go: the indexer's judge at the group's mesh-delivery head 7b7096f37ea76e1…; and 1 more | d023a25849f3 on fd4931a75261
The gate passes by a group's end only when the event is the forge bridge's forge.group.merged whole, so the merged message
of a repository named forge/group is read as one; row in the holder test. The keeper's take-in-waits row (T26) is dropped:
it showed nothing the keeper does not already hold. The gate pins forgemsg at mesh-delivery 7b7096f3.
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
Forge, its kinds and the group's end moved out of mesh-sdk into the forge bridge's own package (mesh-delivery
modules/mesh-delivery-forge-bridge/forgemsg, the operator, 2026-11-04: logic one module owns lives with it). The gate
imports it at the mesh-delivery head 4e4601a1 that holds the move, and the suffix it passes by before decoding is the
package's own ForgeGroupEndEvent, not a constant of its own. mesh-sdk is pinned at 5a38a12, origin/main.
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
The docker exec listing and the HTTP door go; held and the sweep's index
skip ask the seat's list too. The store's address file is the image seat's
reach, used for the catalogue's definitions only.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The store is found by the seats' holder and its listen registry; list says,
per repository, each manifest's digest, whether it is an index and what it
names, its tags, its size and whether it is held, so the sweep reads the
store through the seat. E15 now asks that nothing is provided or served.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A have of the bus module heard while the placement did not yet name its node as holding the bus
adopted nothing, and nothing adopted it again until the have changed, so a vault could stay without
the bus node's adoption and the loaded list's revision for good. The vault now keeps each node's
latest have and, on the placement's next change, adopts from the bus node's kept have if it was not
adopted: the placement's event, no timer. The rotation test now writes the have before the
placement (its wait for the vault's picture is gone), so it takes this path every run.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
messenger's refusal took its declaration of operator-channel out of the judged catalogue, so claude-code's use of it
was refused too. distribution's two remaining refusals (its program builds beside the artifact store it provides,
and its only health check is its own tool) are a design question left to the lead.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The rotation test failed twice under parallel runs ("never: the rotation begins"), from two races in
its player. The player refused mesh/subscribe, so the placement events it said never reached the
vault: when the vault's first view was answered before the test wrote the placement, the vault never
knew the bus node. And the test wrote the bus node's have right after the placement, so the vault
could hear the have before it applied the placement, adopt nothing, and never learn the loaded list's
revision. The player now answers mesh/subscribe and holds a family's events until it is subscribed,
as the module's consumer does; the test writes the placement only after the vault's first view and
the have only once the vault's picture holds every placement key (vault_first_views), so both orders
are fixed rather than waited out.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Twice in the registry milestone a module's program, built in its folder, was committed with git add -A
and stayed in the branch's history. The ignore list was kept by hand and covered 56 of 229 programs.
checks/gitignored now lists every main package's program (in its directory and at its Go module's
root) and fails on one no ignore file names; the root .gitignore names each, anchored to its path.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
mesh-sdk's views.UnsaidFinding (id <owner>.<state>) is written by the indexer and the assigner in their own findings;
the closed set finds a catalogue writer of it too. nats.status-unwritten is said to the keeper directly, not a finding:
no row.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Saying removed for a version the store still holds told the builder something false. remove now answers
kept with the reason shared-digest and the other tags naming its digest, removed false, and says the
seat's event kept with them (mesh-contracts' shared registry part); the builder raises no retry.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A person who later makes a team named packages or readers would have lost it at the next start. A team
counts as the provisioner's only in its organisation and when every member is one of its accounts (it
put its own accounts there alone, and they go with the first run), so a team made later stays.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
registry_incoming, npm_incoming and go_incoming dropped a transfer by hand with only a log line. Each
drop now records its hand act through the seat mesh-hand-acts before anything goes, as nats_requests
does; an act not recorded leaves the transfer open. distribution's manifest invokes the seat.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Review round 2 of the registry milestone:
- security F2: the spend record leaves requests, which the tools write as the tool runner's account, for state spent,
named in the keeper's bus.state and declared read-only (the lead's 18:1x ruling: the tools read it, never write);
nats_requests lists the warrants spent from it;
- running F1: the fill pass also runs while the manifest-accepted consumer is bound again;
- health note 3: an event said on the seat's subject and refused by its history is kept with its one id and said again
on the history alone, never again with a new id;
- seams note 3, health note 4: words unsaid with a status that cannot be written raise the keeper's own condition
status-unwritten, cleared when it is written; the health names what a restart would lose.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A transfer whose idle key ended while the bundle was down was never dropped. Both hand mesh-sdk's
FollowIdle their open transfers, which it gives Expired once the watch is taken.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Every module that imports mesh-sdk requires its group head; each requires the mesh-contracts seats and clients it
imports, and mesh-contracts/go through the SDK's seat list. The placeholder versions are gone.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The store's pinned image is registry 2.8.3, whose DeleteManifest cannot delete a tag alone: by a tag it
deletes the empty digest and answers 400 DIGEST_INVALID. The fakes accepted a DELETE by tag, a fixture
agreeing with the mistake, so every merge of a reproducible build would have been a refused remove and a
retry finding live. RemoveTag now answers ErrNoTagAlone for that answer; remove then keeps the tag, whose
bytes stay under the other tag anyway, and says removed with that reason, so the builder lets it go. Any
other store failure is still refused; a digest shared with nothing is still deleted by digest. The fakes
answer as 2.8.3 does.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Both holders carried the same idle bound and the same read of incoming's cap; the second instance of the
kind moved into mesh-sdk's Receiver (Arm, Expired, Bound, with BusArm, BusCap and FollowIdle). Each
holder now hands its idle state and its objects to those, and keeps its rows.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Review round 1 of the registry milestone (design 25 § 12.2, § 12.3, § 12.7):
- the fill pass runs from the start, while the first view is asked;
- recreate and drop wake on the operator channel's decided on the keeper's durable consumer, never a minute's tick;
- a warrant is spent by compare-and-set (acted.<ask id> in requests) before anything is deleted; a second request on it
is refused; a request whose ask ended unanswered is ended, said; the ask is raised before the request is handed;
- created is marked only once said; an event or a condition the bus did not take is kept, named by the health and
said again at the next fill pass with its one id, on the subjects left (the double publish);
- the health judges the first view past its bound and never skips an unread consumer backlog;
- an unrecordable hand act is said on the request; nats_requests reads what waits, what ended and each warrant spent,
and drops a waiting request by hand; a tool waits for its request's end on one watch of requests;
- the whole-module test reads the warrant from the router's record under a process connection.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
buildstep's generated.go and generated_test.go and claude-code's config_test.go reached the join
unformatted: the second of a kind, which no check caught since each module's tests hold only themselves.
All three are formatted, and checks/gofmt refuses a Go file of the catalogue gofmt would change.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A bare pattern meant for a binary (mesh-build-node) matched the command directory of the same name, so git
ignored every new file there and publish.go was never committed (catalogue review F1). The kind: every
bare pattern of a module's .gitignore is anchored to the binary (nfs-server's hid all of cmd/nfs-server),
and checks/gitignored refuses an ignore pattern, the module's or the catalogue's, that hides a directory
under a module's cmd/ or internal/, a Go file added there, or a source file there, in a git checkout and a
plain folder alike.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
ADR 0605 §5 revokes the npm write token, and the 14:04 deferral is withdrawn (security review F5): the
accounts the removed pair provisioner made (mesh_<node>_<consumer>) still logged in with write on the
organisation's packages. cmd/agent-teams, run at each start of the module and change of its teams value,
removes both teams and each account of that form whose only teams they are, never purging: one the forge
refuses to delete because it owns something keeps it and has its login prohibited.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The package seats kept incoming, transfers and findings with no read or drop tool (tools review F4).
npm_incoming and go_incoming list a seat's open transfers, incoming's fill and the cap its binding carries,
and drop one by hand. The same fault as distribution's (running review F2, its second instance): the
transfers state's own lifetime dropped a transfer's key and left its chunks, and the drop otherwise waited
for the next publish. transfers keeps for good; each open transfer has a key in the new state idle with its
own time to live, whose end drops it. The holder counts against its binding's cap.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The state mirrors had no read tool and no ask-again (seams review note 1): a copy a follower holds and
does not end could only wait for a restart. registry_mirrors lists each kept copy and its claim, asks one
again with its claim let go, and drops one, saying refused under the ask's id so its waiter ends.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Their views findings were written and raised by nobody (ADR 0615 §6). The test finds every catalogue module
writing a views finding in the tree, so a new writer cannot go unobserved; homes for publish-refused,
publish-unanswered, seat-outcome-unread and family-not-heard.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The holder counted against 20 GiB while the bus caps incoming at 8 GiB, so the bus refused writes before
the holder said refused naming the cap, and the 80 % finding came too late (running review F2). The cap is
read from incoming's binding (the object store's fill); IncomingCap, 8 GiB, is said only where none is read,
and the manifest's row holds it equal to max-mib. An abandoned transfer was dropped only on the next publish,
and the transfers state's own lifetime dropped its key while its parts stayed: transfers keeps for good, and
each open transfer has a key in the new state idle with its own time to live, whose end drops it (re-armed
for the rest when it took a part since). registry_incoming reports the bound cap.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A read naming no node (an empty node_haves) closed both windows for good (security review F3, second of
a kind): the window embeds delivery.WindowHeld and steps by the shared rule, named being every node the
read named, and keeps its own guard that a window once closed stays closed. A node-engine whose
manifest-reads did not answer (a timeout included) counts as stating nothing as before, and the window's
record now says so per node (Why), so registry_old_name tells a timeout from an old node-engine. A read
that fails otherwise is an error the wake judges nothing on, no longer taken as not served.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The lead's ENG-5 ruling: on a fresh mesh the bootstrap pushes the holders' own images to the store on its
loopback with no credential, so the front's bootstrap token, its file, the bootstrap-push window and the
program's removal of the file go. Fewer secrets; nothing to refuse once a window closes.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Deleting the manifest by its digest removed every tag on it, and reproducible builds share a digest
between a branch's tagged version and the trunk's numbered one, so a branch's end deleted the trunk's
image (security review F1). The fake catalog now deletes by digest as the store does; a store that
cannot delete a tag alone removes nothing and the removal is refused.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A decoder keeps the last of two equal keys without a word, so a merge
of two branches that each add a field to a manifest loses one side
silently; the indexer's judge reads the same bytes. Rows: a top-level
field and a field inside an artifact, each named by its path.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A3's merge auto-merged a second invokes into mesh-build-go's manifest
(the registry seats' publish verbs beside the indexer's read tool); a
decoder kept the last and dropped the read tool, which
TestTheModuleReadsTheIndexersManifests caught. One list holds both.
gitea's package-registry row named only the builder's versions; the
manifest also asks the indexer's modules and records a re-read.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The overview page read MESH_KNOWLEDGE_PAGE, which nothing in the mesh
sets; only its bus test did, to serve no page. checks/environment,
which came with A3's merge, refuses such a read. The page listens on
the port its manifest declares; the test's bundle sets the package's
address empty instead.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Conflict in mesh-knowledge's reviewOne: the join judges a record in
parts, #611 asks a closing only of the records its judged links name,
with the status it moves from. Both kept: a closing is one part,
ClosingPart, asked #611's ClosingQuestion over the named records.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Conflicts, both sides kept: artifact-store-tools' invokes (the assigner's
and indexer's read tools, followed through views, beside the registry
seats' hold, release and remove), its main (the views reader and the
seat asker), its manifest row; gitea's invokes (the indexer's read tool,
the hand act and the builder's versions) and its consumes of the
indexer's views. gitea's account test takes the packages account's
names; repoCheckFacts, removed on main, is not imported. No catalogue
module reads the indexer's state.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
distribution answers released false for what it does not hold, as the
registry seats now define, and takes the removal reason from the
generated constant; the sweep reads the answer instead of matching
the error's text.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
An image built unnumbered is published by its digest; the builder's
version.numbered now publishes it under its version, sending nothing.
The late publish moved into buildstep, so mesh-build-go and
mesh-build-image share one.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
mesh-sdk's publish package left mesh-sdk (ADR 0627): buildstep binds each
registry seat to its client in mesh-contracts, over mesh-sdk's
seat-neutral sender of parts. The late publish uses the same path.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The patterns mesh-build-node and mesh-build-image matched the command
directory, so publish.go and its test were never committed and the
branch did not compile. Anchored to the binaries now.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The sweep asks remove now instead of deleting over the store's door, so
what its door did for an index is the holder's: a removal for retention
removes the platform manifests no tagged or held index of the repository
names, and refuses a manifest such an index names.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The sweep holds and removes through the registry seats, so the store's
LetGo, holds and holder manifests, and the unused GetBlob and
HoldsManifest, have no caller. One table test reads the door's two
remaining answers in both reference forms.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The store's write side is its holder's now, so the sweep asks the seats'
hold, release and remove instead of writing to the store's door. Both
reference forms meet as one artifact; a refusal stops the sweep and writes
the finding sweep-refused, which a clean sweep clears.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
asked, waiting on the seat every five minutes, stored or refused, as the ask's
phase on its step key, so a publish or a copy that stands still is readable on
the bus. PublishOne and PublishFiles narrate for every build module; the image
copy and the late publish use the same narration.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The image seat's published and refused reach one instance of the module, not
necessarily the one whose copy waits, so an outcome held only in memory was
dropped. The instance that hears it now writes it into the copy's key, and the
copy reads it there, woken by its watch of the state; build_image_mirror_waits
reads the state.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
No build module writes into a store any more: mesh-build-go's store test
plays the holder with its own two-request upload, as mesh-build-node's does.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
askOf keeps its key step and holds the carried ask to its id and an option with
occ.Carried, the one reader the assigner, teller and view use; its own decode, id and
option checks are gone. Rows in TestTheGateRefusesAnAskWithAnotherIdOrNoOption name the
client's refusals and a value carrying no ask; they failed with the gate's own checks.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A trunk image is written as an OCI layout and published by the seat's
publish and publish-part, only the parts the holder lacks; an upstream copy is
the seat's mirror, ended on the holder's published or refused. The module
holds no registry address: artifact-store, files/registry and the copier go,
and the step answers the seat's reference.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Conflicts in mesh-knowledge: main.go Verbs and manifest_test.go, A6's draft verbs and
#610's close, both kept in the manifest's order; review.go reviewOne, A6 judges a version
in parts and #610 judges a closing on its closing alone: a closing version is one part
(ClosingPart) asked ClosingQuestion. Joined: close.go's asks import by the rewrite map,
and its rules probe names its overview section "Overview", since A6's section-form rule
refuses a file-named section (close's test failed on it).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
At the joined SDK the bundle is served in the test, so ServePage's first view asks the
tracker's list and milestones and mesh-delivery's groups once beside progress (checked:
with the page's start skipped the counts are the old 3, 1, 3).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The seat definition names mesh-config's renamed, retiring and retired on its own stream
(mesh.stream, A1c), and the runtime publishes an event the module's stream carries
there; the test assumed EVENTS (mesh.mod) for every event and failed at the joined heads.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
npm-package-registry is form none, so the registry pair the lab's clones of
mesh-tools-go used is no longer minted. The lab requires forge-account as the
build modules do; its clones go over ssh through a git and ssh configuration the
mesh writes from that binding. The secret, contributes and MESH_LAB_FORGE_SECRET go.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A8's CAT-RD4 and CAT-RD8 committed the mesh-conditions and minio binaries
(checks/nobinaries): removed and ignored. The long-running resources without health fell
to 57 in the joined tree (checks/health ratchet).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A8 gave gitea a findings state and the keeper its read; gitea's announcement did not name
it, so the read was refused on the mesh (checks/readable) and its own kept test failed.
Rows in test/kept.test.ts; they failed before the change.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The ledger pipe asks the runtime through stdio.BusState (it answered ErrNoPipe before), an
operation names the call the runtime proved (stdio.CallIDOf), and the page takes the
runtime's word on its consumer (stdio.OnHeartbeat): a beat is every subscription heard, a
missed heartbeat marks each subscribed source at once with the runtime's why. Rows in
TestASourceThatDoesNotAnswerIsSaidAndAskedAgainOnABackoff and
TestTheLedgerStoreRefusesWhatTheLedgerWouldHaveToTakeBack; each failed before the change.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
mesh-sdk holds neither asks nor asker, nor the vault's answer types, and mesh-delivery's
sdk/views is mesh-sdk's go/views (a1-progress.md, the rewrite map for the join): thirteen
modules switch to the operatorchannel contract and client, mesh-sdk's channel package and
meshvault, with go.mod requiring each at the group pin (nats: meshbroker too). The gate
holds the checks mesh-sdk dropped (an ask's id is its key's asking, at least one option),
with a row that fails without them; claude-code refuses a router record whose times do
not parse, as its JSON decode did, with a row.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Bundles go through oci-artifact-registry and answer the seat's reference;
a trunk package is packed under the builder's version and published through
npm-package-registry, so the holder can check it with the builder. Reads are
anonymous, so the write pair, the sealed secret and the store's address go.
The one-part sender moves into buildstep for both build modules, so the move
to the registry clients is made in one place.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The builder's four kinds, the indexer's four, the package seats' token refused and the
owners' view too large get their homes; the keeper reads the findings of every reader
of the indexer's and the assigner's state (teller, enrolment, builder, checker, view),
and asks the indexer's findings of its read tool and follows its views events, as the
assigner's (ADR 0615 §1). Rows in TestEveryControllerKindHasItsHome and the manifest
test; each failed before the change.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
mesh-build-go consumes the builder's version.numbered and publishes the held
digest under its version, naming its one part by digest only, since the packed
bytes left the node; distribution tags it at the size its store holds, so the
version's manifest names the blob truly.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Its version is the build module's own, so a new generator is a new build of
mesh-build-go and mesh-build-node and a new fingerprint of what they compare;
no repository of its own. Moved from seatgen c1fdd7c unchanged but for the
import path.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Conflict in mesh-knowledge main.go, the propose tool's description: #609 (79c2fc7f)
names ideas and the research-active-at-most limit, A6 names a research effort's
partial new version; both sentences kept, A6's rule count (31).
Conflict in mesh-conditions keeper.go Observers and module.json reads: origin/main
added mesh-vault's findings, A8 added the first-view readers' findings; both kept.
The unit level fails on one, a module with no tests of its own too; a build ask answers
them in its out-of-step through buildstep's compare (lead's ruling on A2k finding 1).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The unit level fails on a file that differs, is missing or was not generated; a build
ask answers the same files in its out-of-step, a failed build's too, so a trunk build's
end raises generated-types-out-of-step (lead's ruling on A2k finding 1). The compare is
buildstep's, each build module its own root, with the seat generator as a requirement.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A word its manifest does not set and the mesh gives no process is a contract nobody
keeps (MESH_REGISTRY_REACH, MESH_CONFIG_CALLERS). The 63 reads outside this milestone's
modules are listed in unset, which only shrinks (lead's ruling on A3n).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The reach came from MESH_REGISTRY_REACH, which nothing sets, so every published event
answered /<name>@<digest>. The store answers the path; the holder puts the seat's name
before it, as catalogue.InRegistrySeat reads it back (ADR 0605 §9; lead's ruling on A3n).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The Go bundle raises packages-token-refused in the module's findings state when the forge
answers 401 to a write; the watcher mints afresh on that key's event and clears it (lead's
ruling on A3n, map-onto-how-the-mesh-is-built: nothing waits on a timer).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Design 51 Publishing, ADR 0605 §3: a Go package is published from a trunk build through go-package-registry
under the version the builder gave it. The build packs the directory the artifact names as Go's module zip,
answers its digest and h1: sum, and on a version publishes it under the Go module path (the forge's Go seat
takes the name as the module path); a candidate publishes nothing. The ask's seat and version reach the build.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
mesh/check being carried to 55a88cdba4e5 on 79c2fc7fe1d5 | from 7fe569ef4067
Round 2 of issue 1970's review: a research effort has no clauses, so holds never serves one; Served on an
idea is tested in TestAnIdeaIsListedAndNeverServedAsTruth.
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
ADR 0605 §9: a done key names the seat's reference, oci-artifact-registry/<module>/<artifact>@<digest>,
not the store's older artifact-store:// form; the builder keeps the older form beside it while a counted
node-engine reads only that (ADR 0624). The whole test reads it back as a node-engine routes it.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Design 51: only a registry seat's holder writes into its store. The module pushed each bundle
and archive straight into the artifact store; it now publishes through the seat's publish and
publish-part with mesh-sdk's sender, invokes both verbs, and no longer requires artifact-store
or places its address. push.go is gone.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The bundle built and played as the tool runtime plays it, its incoming, transfers and findings on
a nats-server of the test, the builder's builder_versions and the config value callers answered:
a numbered Go package goes up in two chunks as the packages account and says published with its
module path; an unnumbered one is refused before the forge and writes the finding. A publish
naming no transfer is now refused: the transfer's name is the caller's own.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Design 51 keeps each holder's write side as an own secret beside a read-only tool token. The Go
bundle wrote as the forge's administrator; it now reads with the tools' token (read:package added)
and writes with the mesh-packages account's token (write:package alone), which the watcher makes,
mints, keeps and renews.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Reads of the organisation's packages are anonymous and every write goes through the seats'
verbs (design 51 *Publishing*, prepare Q4), so npm-package-registry is form none like
go-package-registry: receives, grants, the consumers' data entry, the grants directory and
the TypeScript pair provisioner with its teams go. Pairs with BN3 (mesh-build-node) and the
lab, which still require the pair.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
go_packages and go_retention read the forge's Go registry as npm_* read npm's: a version a
go.mod on a default branch requires (or replaces to) is kept, with the newest keep; a go.mod
that cannot be read stops a real run before anything is deleted; each deletion says removed
on the Go seat, under the module path and without Go's leading v (design 51 *Retention*).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The node-engine fills ${config:} only in files, unit names, owners and groups, never in a
process's environment, so MESH_CONFIG_CALLERS was never set and design 51's defaults always held.
The tools bundle now reads `callers` through stdio.Config on each call (holder.ConfiguredCallers,
Verbs.WithCallers per call); the program, which has no runtime resolving config, asks its own
tools bundle's new registry_callers on each wake of the windows (manifest invokes). The
environment variable is gone.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A second tools process following mirrors would copy again and say published twice. The ask is claimed by
compare-and-set before it is copied, and its outcome carries the ask's id as the event id, so a redelivery is one
message. The cap's publish-refused finding stands on incoming, not on one file, and clears with the next publish
taken.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
ADR 0607 §3, §5: the fetch's package argument also takes {name, version}; the version is placed from the registry in
each TypeScript member whatever its lock names, checked against the lock's integrity when the lock names it, else the
registry's; nothing is packed then, and a version the registry lacks fails naming it. The packed {repository, commit}
form stays for a checker that hands it. Rows in the placement and argument tests.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
ADR 0607 §3, §5: an asked semantic version (v0.1.15-feat-x.2) is downloaded through the Go seat and built whatever
go.mod names, said when go.mod names a newer one; one the seat does not hold fails naming it as a download that may be
retaken, never looked for among the pull request heads. Rows in the asked-version table test.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A large base could outlast a call's bound. The ask is kept in the state mirrors and the copy runs on that state's
watch, so a copy a restart cut is taken on again; published (or refused, with why) on container-image-registry's
events is the end the caller waits on, the place the seat's contract already gives mirror.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The holder's own transfer logic goes: parts.Receiver takes the chunks into incoming, checks the hashes, drops an idle
transfer and tells the fill; distribution gives it the builder_versions check, its store and its seats' events, so
the forge's two package seats bind the same receiver instead of a copy.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
list, show and orphans answer meshbroker.ListAnswer, Held and OrphansAnswer; check answers CheckAnswer with each
differing entry's settings asked and held by stream and whether the difference only grows; show takes the contract's
local-name. Built against mesh-contracts' seats/meshbroker module in the workspace; the group pin adds its require.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The verbs answered the holder's own shapes (missing and ended, a part named digest, versions as bare strings, held as
the publish's event) while the seat definitions, now generated into mesh-contracts, name lacks and held, part,
versions of artifacts, tags with digests and a hold's own body. A build module using mesh-sdk's parts helper would
have read no lacking part and sent nothing. The bundle now takes and answers the contract's types and says each
event in its body; an image's manifest is the part whose digest is the publish's, as the contract names no media
type, and a hold on the image seat is of a copied base.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The program had no test that runs it whole. This one starts run() on a nats-server of its own, with the registry
container faked on the loopback and node_haves and manifest-reads answered on their call subjects: an away node holds
both windows open, its return closes them, each closing said once on distribution.events, a direct write is then
refused, reads stay open, the health check answers through the program's port, and a waiter on published wakes on
none of the windows' events.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The lead's ruling of 13:0x (registry milestone): mesh-broker's events are mesh.seat.mesh-broker.event.<event> on the
shared events stream like every seat's, and the bus module's own 30-day stream keeps each for its history tool.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
An http probe of /v2/ said only that a port answered; design 51 asks the health check to call versions per seat and
probe the read side each minute, naming the program when it is down, from outside its process. registry_health asks
versions of each seat through the program's port, writes the read-side finding while it fails and clears it after.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The windows' logic was built but nothing woke it, so both windows stayed open for ever. The program now reads every
node through node_haves and the node-engine seat's manifest-reads at its start, on each delivered and on each
manifest-reads-changed, steps both windows, says their closing once on distribution.events and raises the seven-day
finding. A build module's have counts as publishing through the seats when it runs a build heard publishing (the
tools bundle records the fingerprint of each publish's proved caller), so a paused build agent running the same
build holds nothing open.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The keeper already reads the router's record of the ask on its own account and verifies the
warrant itself (bound to this act on this entry, at the destroy level), so only the rows are new.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Until now mirror only answered a copy the store already held, so mesh-build-image had nothing to call for an upstream
base (design 51: an upstream image is copied by mirror with its pinned digest). The copy takes an anonymous pull
token, checks every manifest's and blob's bytes against its digest, copies an index's every platform first, and
fetches only the blobs the store lacks. tags was already served.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The test of the five ends holds every key of a body to the seat definition's holder events, so the router and the contract cannot drift.
Issue 1968.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
module, local-name, storage-type, template, options, configuration, bus-name,
asked, held, fill, snapshot and why as the seat's definition in mesh-contracts
names them, so taking its generated type changes no byte; binding (a ledger's
several names) and revision (the indexer's, of the verdict acted on) beside,
asked of the definition.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Design 25 § 12.7's rows, as subtests of one test on one server (CAT-N10): a
verdict, then created on its own stream BROKER_EVENTS, the objects on the bus;
a restart catching up a verdict given while it was down; a replay older than
the first view not applied and a module missing from the first view keeping
its key; a drift said, a growth applied and the drift cleared; a refused
create with no created; a log at a small cap refusing, full raised and cleared;
an orphan dropped only on the operator's warrant, after a snapshot written
whole, recorded as a hand act; nats_first_view_again's hand act.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The bus module's tool hands the ask to the keeper through its own state
requests (design 25 § 12.2), as the caller the tool runner proved; the keeper
asks indexer_bus_state at once beside its backoff, applies what it answers,
records the hand act and writes back what it answered and at which revision.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
It reads the keeper's status from its own state asked, what the keeper holds,
and how many accepted verdicts wait on its consumer <node>_nats_keeper on
EVENTS from the monitoring endpoint, and answers HealthOf's judgement:
unhealthy, naming why, past the three-minute bound; the entries refused,
waiting and past the raise mark named beside.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The mesh deletes a module's kept data only through drop and recreate (ADR
0595 §4 as its insight has it; design 25 § 12.3): nats_stream_remove,
nats_bucket_remove and nats_consumer_remove read the keeper's own state asked
and refuse a stream or bucket the keeper made, before the bus is reached,
naming nats_drop and nats_recreate; one that cannot be told apart is not
removed. The old sections' entries are removed as before. Rows of the
existing refusal test.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The bus module's tools hold no grant of the seat's acting verbs (design 25
§ 12.3): nats_create, nats_apply, nats_recreate and nats_drop write a request
into the keeper's own state requests, stamped with stdio.CallerOf (a name in
the arguments is never the caller), and read its end back. recreate and drop
raise the operator's ask first, its option binding exactly that act; the
keeper acts only on the router's warrant for it (Warrant.For, Option.Performs),
after a snapshot of the entry's streams (bussnap, moved from the snapshot
command with a streams filter), says recreated or dropped, and records every
act as a hand act through mesh-hand-acts. A drop removes an orphan alone.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Served by the bus module's bundle from the keeper's own state asked and the
bus's monitoring endpoint (design 25 § 12.3): each entry's template, bus
names, settings asked and held and fill against its cap; check names each
object missing or differing; orphans what no accepted manifest asks for.
nats_history reads one entry's events, in order, from the bus module's own
stream BROKER_EVENTS on the tools' credential. The manifest test now holds
every tool and reading verb the manifest names to what the bundle serves.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
nats-tools keep is the process keeper, on its own account (own secret
broker-keeper): it asks the indexer's indexer_bus_state once, on a backoff
from 10 s doubling to 5 min while it does not answer (unhealthy meanwhile,
nothing created or orphaned), then binds its durable consumer on EVENTS
(<node>_nats_keeper, the indexer's manifest-accepted) and applies each verdict
only if newer by the indexer's revision; a manifest-accepted carrying no
revision yet is read as 0. A fill pass every minute, waiting entries made
again on the same backoff. It says its events on its own stream and its
conditions through the condition keeper, and serves nothing (ADR 0436 §3).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The keeper's one periodic read (ADR 0595 §6): every entry that refuses when
full, by its fullest object; full raised at the raise mark (75 by default),
cleared only below the clear mark (70), so an entry at the mark does not flap;
an entry dropping its oldest is never read. HealthOf is the keeper's health
for its tool: unhealthy when its pass is more than three minutes old, its
first view has not answered (naming the indexer's verb), or verdicts wait on
its consumer unanswered past the bound; it names the entries refused, waiting
and full beside.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
An entry made for a module whose newest accepted manifest no longer asks for
it is said orphaned and raised, never removed; asked again it is kept, its
binding said again with created and the condition cleared. A module missing
from a first view keeps its key (a set-aside manifest is not in it); an entry
never made leaves nothing, so the empty verdict ends that module's key.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Rows of the keeper's table test: a larger cap is applied with no event; a
smaller one is drifted with what differs, raised once, and drift-cleared once
the manifest asks what the bus holds again; an entry the bus already holds is
taken as made and its binding said, nothing made twice.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Each bus-state entry is planned into its objects (design 25 § 12.1): state a
bucket <module>_<local>; events, work queue, log and a bare stream a stream
<module>_<local> on mesh.bus.<module>.<local>.>; objects an object store;
a ledger its history stream, its state and index buckets and its snapshot
stream, one message per subject. The keeper makes what the bus lacks on its
own account; a refusal of its grant waits for the next check, a refusal of the
entry is said (refused) and raised, cleared by a later create. The comparison
of what is held and the orphans are in the same pass (CAT-N4, N5).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The keeper is a process of the tools bundle on its own account (own secret
broker-keeper, ADR 0436 §1): it hears the indexer's manifest-accepted, keeps
what it heard in its old state asked and the persons' requests in requests
(ADR 0595 §10), and says its nine events on its own stream broker-events,
30 days at 256 MiB (design 25 § 12.3, ADR 0620 §2). mesh-broker serves its
four reading verbs; its acting verbs are the keeper's own work. The server
gains a tcp check, which the keeper's tool check stands beside.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
offered once when an ask is offered, closed once for each of the five ends (answered, expired, cancelled by its asker, replaced, ended by the router), with the key, asker and headline and never an option, ticket or proof; on a stream of the events kept seven days, 64 MiB, granted by the trusted value readers, which names the knowledge base alone. Issue 725's runtime change is delivered (resolved 2026-10-26).
Issue 1968.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
knowledge_overview answers the page's model as data (reads); knowledge_overview_reread asks one source's verb again by hand, no other, and
records the hand act (acts). A source marked from its verb is asked again alone from 10 seconds, doubling to 5 minutes, its first answer clearing
the mark; one marked from its subscription asks nothing while silent and the verb once on its next event. The module's health carries the page's
last rebuild and says it is degraded while a source is unanswered, staying healthy.
Issue 1968.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The module's bundle (the one process with the bus) serves the page on the port its manifest declares under listens, from: machine,
and requires a route that reaches it. No form, no script, no verb behind it; any method but GET is 405. A source that does not
answer is said on the page, never shown as an empty list.
Issue 1968.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The model is built once at start from the issue tracker's milestones and list, the delivery groups and the operator channel's asks, and
kept in memory from their events (group, transition, merged; offered, closed; opened, moved, milestone-set, milestone-moved), asking no verb
again; the records come from the ledger and the seven days are counted when the answer is given. The manifest invokes groups and asks,
consumes those events, has no reads and no decided family.
Issue 1968.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
One integration test: the module's states are JetStream buckets, its events are published under their message ids to a stream
that drops a repeat; it moves its records, proposes, is reviewed and accepts a record, loses an event between an operation and its
send, restarts, sends the lost event exactly once, builds its index and checks the database within 40 seconds, and is healthy. The
test found that a restart probed the ledger number by number and stopped at a gap of 50, finding 3 of 14 records: the store now
keeps a key held.<kind>.<number> in the state findings for each record it creates and reads them at start (the old probing, with a
gap of 1000, only for a ledger written before the keys).
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Unhealthy, naming the cause, for a ledger or the verdicts' stream that does not answer, a head behind its history, an index behind
the ledger and a stream at its cap; the idle drafts, the parts waiting on the judge and the records the form-only check refused
are counted and leave it healthy. A part waiting more than 30 minutes is asked of the operator once, cleared when it is judged.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A record imported with file-named sections gets plain titles, and its links to files become references of the one form, in one
version written after the move by the tool knowledge_form_only: marked form, listing the names changed, accepted without a
judgement because a check proves each section's text with its links replaced by their labels is the same and each new link names
the record the old one named. The old names stay as aliases get takes; the parts' reviews carry over; a record waiting for its
review is skipped.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
knowledge_head, _operations, _section, _draft, _parts, _asked, _fill, _rebuild_index, _review_again, _integrity,
_move and _move_check, beside the health, highest and marks tools; the manifest lists them and a test compares them with the code.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A movableStore serves the database until the switch key says the ledger. The move copies every version of every record as an
import operation (the old author kept apart, marked imported; the ledger's author the module's account), refuses writes for its
length, checks record by record, and sets the switch only on a clean check. From then on the ledger is served and the database is
written beside it, behind or not (database.sequence, database.behind); the check runs at every start before the drop, and the
search index is built then.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The tools bundle runs in the tool runner's account and cannot remove a file in
distribution's 0700 state directory, so its first answered publish closes the
window bootstrap-push in the state windows and the program removes the file
(design 51 On a fresh mesh).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
ask and holds on the ledger answer from a full-text index of the heads and the current versions' text and clauses; it is
built at start (index not built is the answer meanwhile), a new version replaces its record's documents, a reserved,
withdrawn or retracted record has none. A new pure Go dependency, bleve.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
mesh-vault gains the state findings (old section); past two minutes without the assigner's first view it writes
first-view-unanswered naming the owner and the tool, the answer deletes it. mesh-conditions reads mesh-vault.findings
and holds a row for the kind.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
An event of a change carries the record, the version it follows and the event as its message id; the last version sent per
record is a key of the state sent; at start the events of the operations after it are sent again under the same ids, so a
stop between an operation and its event loses none and a second start sends none.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Six states (modules, manifests, predefined, config-candidates, placement, wants) are asked of the owners' read
tools at start and kept from their views.<state> events, a gap asks again; a reader started while an owner is
down keeps asking and writes a finding past two minutes. The builder's builds has no owner tool and stays a
read. The returning node-engine's event is read by its node token (ADR 0618 as built). Tools
config_first_views and config_first_view_again.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
One judgement per part with no tools, at most two at once; a section is read with its frame (the clauses and records it
names and the digest of its Context), so a usual revision judges only what changed. The latest approval of each part is
kept in the head and carried to the next version; a part that could not be judged keeps the others' verdicts and is the
only one asked again; reviewed is said once per version and each verdict as part-reviewed on the stream reviews. A part
in flight is a key of the state asked. A version is accepted when every part approves; findings name their part.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
With go-package-registry bound, the fetch's GOPROXY is the Go seat, then proxy.golang.org, then direct (kept for
this milestone, E11: removed by the first change after mesh-sdk's and mesh-contracts' first numbered versions
are in the Go seat); no GOPRIVATE, and the checksum database off for the forge's paths (design 51 *Go packages*,
ADR 0605 §6). The module requires and binds go-package-registry, so its new build waits for the forge's build
that offers it (E2). Unbound, the fetch is as before.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
retire takes the definition's warrant (the hand act's id, naming node, module, name and ask) and answers
retired; own-retired, renamed, retiring and retired carry exactly the definition's bodies on its subjects.
The whole-module tests decode what the module published strictly into the generated types. The modules
require mesh-contracts, to be pinned with the group (a local replace in an uncommitted go.work until then).
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
go-package-registry, mesh scope, read with no credential, is offered only by the forge module's new build, so
mesh-build-go's fetch from the Go seat waits for it (design 51, E2); its read side is the forge's Go proxy. The
npm registry's public-root stays served (ADR 0346 §6, the operator 2026-11-04). Both rows of the forge's
manifest test.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The program serves the store's port 5000 in front of the registry container, now on the node's loopback
(127.0.0.1:5001), listed before the program so the port is free when it starts (E14). The tools bundle serves
each seat's verbs as <seat>.<verb> and registry_incoming, registry_holds, registry_old_name and
registry_direct_writes, on distribution's own account, with the caller the tool runner proved. The manifest
claims container-image-registry and oci-artifact-registry with their verbs, keeps mesh-artifact-store and
provides artifact-store until the old name closes (E15), asks its bus state in requires (incoming, transfers,
holds, windows, findings, events) and declares its health outside the program. The bootstrap's one-off
credential is discarded at the first publish answered.
Not yet: the runtime's object store helper for incoming (mesh-sdk), the windows' driver on delivered and
manifest-reads-changed, the read-side health probe calling versions per seat.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A new rule, section-form (31 now), refuses from the day the records move a section whose title is a file name, a number
prefix, a slash or over 200 bytes, a title twice in a record, and a text that holds a local path, a file and line, or a
link to a file. Only a section that is new or changed is judged, so a record imported with file-named sections keeps
them until its form-only version; write refuses at once.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The caller must be on the vault's trusted list retire-callers (the holder of mesh-config alone) and carry
a hand act it recorded for exactly this node, module and name. A waiter on rotated or own-replaced does
not wake on own-retired. Reviewer note of issue 1966: HandedOf returns a placement read error instead of
dropping the modules placed there.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A draft is a key of the state drafts (author, fields, sections as title, digest and the sequence of their write-section);
write puts the text into the record's history at once, submit makes the draft a version through the rules propose is
judged by and writes no section again. Only the author writes; take-over hands a draft, a proposal or a reserved number
to the caller with the reason in the next version's message. A new version of an effort starts from the served sections
and keeps its title, date and deciders (the rows of the commit folded in, now run over the ledger too). A tool call is
named to the ledger so the runtime stamps the caller it proved.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The holder answers publish and publish-part into incoming (parts of at most 1 MiB, resumed from what is held,
hashed, only the missing layers sent, 20 GiB with its 80 % finding and a refusal at the cap, a transfer idle 24
hours dropped), asks builder_versions before it stores, and says published or refused (design 51 *Publishing*,
ADR 0605 §4, ADR 0611). versions, remove (a tagged version; untagged only for the sweep's retention, which a
hold keeps), hold and release (ADR 0617 §2: the sweep alone; the operator's session by hand; never
distribution's own account), tags and mirror. The caller list is a trusted config value checked against the
caller the tool runner proved. The store's port is the program's: reads open, writes refused but while the
direct-write window is open (never over a tag published through the seat) or with the bootstrap's one-off
credential. The old-name and direct-write windows read every node, away ones included, close once, and name a
node holding them seven days.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The built binary, played as the node's tool runtime over a real bus: a renamed value moves and both
names answer, the module restarted inside the window keeps it and says renamed once, a refused move
writes its finding, g14's window closes on delivered, a value no manifest reads is asked about once
when no node reads it and removed only on the Approve.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
Closing a long research effort (its status and became links) meant retyping
its whole text through propose. A research effort's new version that gives no
sections now keeps the served version's, and its title, date and deciders when
none are given; the version so composed is judged and reviewed as any other.
A decision, or an effort with no served version, still needs its text.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
ledgerStore implements Store on the tool runner's ledger calls: a record is the instance decision/0290 or research/081,
a Save is the operation named by what changed, a section's text is written once in its write-section and named by
digest and sequence in the head, a version is read back from the history, the whole-set findings and the told marks
are keys of the state findings. Every test that runs over each store now also runs over the ledger, played with the
manifest's own types.
The bundle's pipe to the tool runner needs the SDK's raw request (request to A1); until then it answers loudly.
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
A declaration's renamed-from moves the value with its trust and opens a window per node,
closed on delivered and, for a returning node-engine, on manifest-reads-changed (ADR 0618).
A value no manifest reads is marked retiring only once no node runs a build that reads it,
asked once, removed only on the Approve (a secret through the seat mesh-vault's retire).
New state in the old sections (ADR 0619), the stream config-events, the tools config_renames,
config_rename_again, config_rename_close, config_retiring and the seat verb renames.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
The manifest keeps postgres-database until the drop and asks, in the typed form, the ledger records (a type for each
kind, the operations of the move), the states drafts, asked, findings and sent, and the stream reviews (kept for good,
refusing when full, granted by the trusted value readers). It consumes claude-code's judged and says the eleven new
events. The mesh-delivery indexer's judge accepts it (checked against main).
Issue 1966.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
js.Consumer refuses a push consumer ("consumer is not a pull consumer"), so the
controller's leftovers on EVENTS and CONTROL could not be read and were not
removed. The tool now reads a consumer of either kind (CONSUMER.INFO only, which
is all its grant gives), before the delete and for the confirmation after it.
Quick fix: this change, in the tool, one function, about an hour with its test
rows (a pull and a push consumer). Thorough fix: the same tool also needs its
grant to cover the KV_* streams' consumers (mesh-controller-take-in,
mesh-controller-config-follow), and that grant is composed by mesh-sdk's
BusRemovalGrants from a closed set (ControllerLeftoverConsumersOn), not by the
manifest, so it is not in this commit: it needs a change in mesh-sdk and a
group delivery. Chosen here: the quick fix for the read, since it is one place
and blocks the operator's removal now; the grant is reported to the lead.
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
mesh/check being carried to 237a534ca4d3 on 7a7db0166ad2 | from dd458cb155f5, mesh-host 4d47ff5ce743
The vault leaves a handed module's own secrets out of `own`, judged by the plan in its assignment, and nothing read
that judgement: on 2026-11-04 the circle on ace (no plan, so not handed, so refused, so no plan) could be told only by
reading the provisioner's plans beside the node-engine's refusals. own_handed answers, per module the vault keeps an
own secret of on the machine or that is placed there, handed or not and why.
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
mesh/check checking 6c09be4a703e on dd458cb155f5 | novox/mesh-catalog#605 in group feat/l3-final
The test of a node coming back stops the client before the report of zsh is kept; the cancelled Put left s.applied without zsh, so leftModules never removed it (2 of 20 runs failed under -race, also at origin/main). Thorough: report() keeps under context.WithoutCancel with a 5 s bound; the same test now passes 40 of 40.
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
The running indexer holds refusals from 21:14 for the exact bytes of these manifests, which carry core-credentials again. A new digest is read afresh; the thorough fix of stale verdicts is in the indexer in this group (issue 774).
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
mesh/delivery-group group feat/l3-final rejected: composed together: the checker's verdict at the members' heads (278aa5f0ccbe): unit: mesh-provisioner-client/…
mesh/check failed (2): unit: mesh-provisioner-client/cmd/mesh-provisioner-client.TestNatsANodeComingBackFil…; and 1 more | 093967af9b2f on be24f5ac387f
mesh/check being carried to f2eb54820469 on be24f5ac387f | from e6de42630355, mesh-delivery 4154c3040cee, mesh-tools 01ee2ef39488
The running indexer's judge refuses the word, a refused manifest holds the bus's user list, and so the indexer build
that knows the word is never granted. The node-engine on main still finds these modules by its name list, and the
vault keeps no list, so no credential is lost; the word comes back once the new judge runs (issue 774).
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
A provider whose build does not offer the provision it was asked for must
not be counted as having delivered it; the provisioner reads the build's
manifest (the builds read serves only this offer check and makes no plan,
ADR 0593 section 8) before it takes the provider's have as the outcome.
mesh/check failed (60): integration: mesh-knowledge/cmd/mesh-knowledge.TestARecordThatNeedsTheOperatorIsAc…; and 59 more | 7c78fd2e0c4f on f469eb387a30
A pass runs on every change of its node, and a newly placed module stays
unpublished for the minutes its build takes, so counting passes made every
new placement unhealthy while nothing was wrong. The health now says a hold
only once a module has stayed unpublished at one build for longer than 45
minutes (the build step's bound is 30), with since when; a published module
or another build starts the clock again.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
A node-wide hold while any module's composition was unpublished meant one
placed module whose newest build never completes blocked every retirement on
its node for good, said only as a line of the pass. The incomplete first read
is already covered by the load gate, and an unpublished module's own plan and
keys are already kept as held. So the node-wide hold goes; a removed consumer
retires beside an unpublished module, and a module held unpublished for more
than two passes in a row is said on provisioner_health with its build.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
At 2026-11-02 22:55:58 the provisioner's first pass after a new membership read
part of the picture, took the modules missing from it as handing nothing, set
21 route keys of running web apps retiring and asked the operator to remove
them; 3 s later the next pass put every plan back. Only 3 asks reached the
router; the other 18 were refused yet counted asked. Third of its kind (937,
1332), so the kind is fixed, not the instance.
Quick fix: wait for the watched reads' first load before any pass.
Thorough fix, chosen because the kind recurred three times and its obvious
answer would cut running apps off their routes:
- no pass judges before placement, wants, haves, the indexer's modules and the
published compositions have loaded once; a read error fails the pass
instead of reading as empty;
- while a module's composition is not published at its build, no key on that
node turns retiring and no plan is removed; a placed module with no known
build is held, not counted as handing nothing;
- a key whose consumer still has a want or a have on the node and no plan read
in this pass is left as it is;
- a pass that would retire most of a node's consumers at once (more than 3, or
more than half and at least 2) retires and asks nothing and says it as a
fault through provisioner_health (runtime-health, so a condition names the
likely cause); provisioner_compose retire-many is the operator's word that
such a removal is meant;
- at most 3 asks stand open (the router's bound per asker); the rest wait and
are raised as one ends, and an ask the router holds no record of a minute on
is raised again.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/delivery-group group feat/sdk1 rejected: composed together: the checker's verdict at the members' heads (6b0f5a2e9397): integration: meshbuildgo/cmd/mesh-…
mesh/check failed: integration: meshbuildgo/cmd/mesh-build-go… | 68e7a2ddbfb9 on ee75d4327ce5 | judged by the candidate's mesh-build-go at 773f299aed81
mesh/delivery-group group feat/sdk1 rejected: composed together: the checker's verdict at the members' heads (5c08034be629): integration: meshbuildgo/cmd/mesh-…
mesh/check failed: integration: meshbuildgo/cmd/mesh-build-go… | 640455999e66 on ee75d4327ce5 | judged by the candidate's mesh-build-go at 785ebb388d5a
ensureModfile copied go.mod word for word into pins/<dir>/, where `go mod verify` runs, so a replace to ./x or ../x pointed
nowhere (route-proxy's failure of 2026-11-02 13:53, met a second time with the release's sibling packages). Every relative
replace target is now made absolute under the tree the go.mod came from. mesh-build-node installs a module's own npm
packages in a scratch copy of package.json, so a file:, link: or portal: dependency on a relative path would fail the same
way; it is refused naming the package and its path, as a module without a lock is.
Quick fix: rewrite the one replace route-proxy had, in ensureModfile (minutes). Thorough fix: the kind, a go.mod or
package.json copied away from its tree, for every replace form (single, block, with a version, ./ and ../) in the one place
all copies go through (ensureModfile, which versions.go and the pins share), and the same kind in the other build module
that copies a manifest. Chosen: thorough, since it was met twice and hides a failure until the delivery (quick-or-thorough,
fix-a-bug-met-twice). Test: TestARelativeReplaceStillResolvesInTheTemporaryModfile runs real go mod verify in the pins directory.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check being carried to 45084af849fc on ee75d4327ce5 | from c52afdf88b84
ensureModfile copied go.mod word for word into pins/<dir>/, where `go mod verify` runs, so a replace to ./x or ../x pointed
nowhere (route-proxy's failure of 2026-11-02 13:53, met a second time with the release's sibling packages). Every relative
replace target is now made absolute under the tree the go.mod came from. mesh-build-node installs a module's own npm
packages in a scratch copy of package.json, so a file:, link: or portal: dependency on a relative path would fail the same
way; it is refused naming the package and its path, as a module without a lock is.
Quick fix: rewrite the one replace route-proxy had, in ensureModfile (minutes). Thorough fix: the kind, a go.mod or
package.json copied away from its tree, for every replace form (single, block, with a version, ./ and ../) in the one place
all copies go through (ensureModfile, which versions.go and the pins share), and the same kind in the other build module
that copies a manifest. Chosen: thorough, since it was met twice and hides a failure until the delivery (quick-or-thorough,
fix-a-bug-met-twice). Test: TestARelativeReplaceStillResolvesInTheTemporaryModfile runs real go mod verify in the pins directory.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh-build-image's two tests that composed with catalogue.Resolve (gone with the composition) now hold the module's own
facts: its registry file is the placement and no file binds the store; it requires rootless-image-build, which buildah
provides and docker does not. What only proved composition is listed in .work/sdk1/proofs-for-node-engine.md. sdkjudge's
composition list drops the six refusals that left mesh-sdk.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The test copies the node-engine's repository from beside the check (MESH_CHECK_BESIDE, mesh-host, with mesh-sdk's Go module
beside it as one workspace when a group places it), has the module build github.com/novox/mesh-host/cmd/mesh-compose there,
and runs it; it fails loudly when the repository is not beside.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The module already builds whatever repository, directory and package the ask names; the tests now say so for the node-engine's
repository (a Go module at its root, the command mesh-compose) instead of mesh-sdk's composer, which leaves mesh-sdk, and the
real-bus test builds a stand-in command in its fetched tree. The README tells the runner's new home and what a build says at
its end.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
deps skips a forge requirement the go.mod already replaces to a directory (a package of the module's own repository), which
it used to look for in a clone beside the check and fail. The new check removedpackages refuses an import of a package
mesh-sdk gave up and a use of the build runner through mesh-sdk's buildstep; it is red on mesh-provisioner until the
provisioner stops composing (the release's provisioner subtask). controllerdeps also refuses a go.mod requiring the
controller's repository.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The new argument files, a list of directories (the root as the empty name), adds files, {directory: {path relative to it:
blob id}}, every blob under each directory from the call's one recursive listing. A directory the commit lacks fails naming
it, a cut listing still fails whole, and a badly spelled directory is refused before the forge is asked.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The digest counted a module outside the tree by its version and checksum, so every mesh-sdk merge invalidated each kept
verdict of each repository. A package of the mesh's forge is now hashed by the files the tests reach, as a replacement to a
directory already was; any other outside module still counts by version and checksum. Every kept verdict is invalidated
once, by the form change.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
ModuleTrees answers each module directory's git tree, its manifest and lock digests, and the git objects of the paths its
artifacts name; it no longer computes delivery.NamedTree or reads the mesh packages out of go.sum.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
A build ask whose job built an artifact asks the new step build_go_imports once: `go list -deps` of each Go bundle's program,
no tests, the forge's packages outside the module's own directory (a sibling package of the same repository counts), sorted
and each once. The answer carries them as BuildAnswer.Imports. The step is also a tool, to read them by hand.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The runner, the toolchain guard, the fetch, the parsers, buildcpu, the conformance kit and mesh-pack move from mesh-sdk's
buildstep into modules/mesh-build-go/buildstep (own go.mod). mesh-build-go, mesh-build-node and mesh-build-image require it
by a same-repository replace; what the delivery parts read (the failure contract, the fetch request, the stale sweep, the
module tree shape, NewID, CapacitySetting) stays imported from mesh-sdk as sdkstep.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The node-engine alone composes (ADR 0593 §6, §8), so the provisioner stops
composing with frombus and fromruntime and reads each module's plan from
composed-<node> (read as mesh-host.composed): at its want, or the build its
have runs, and at the indexer's newest build, so a key ahead of its want
still carries its plan entry. A refused or not yet published composition
holds the module with its last plan kept. The golden test proves the plans
and provisions are today's, captured from the composing holder before the
change. It no longer reads the builds or the resolved values.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check pass 019614aedc14 on fe7c5ccb64bf | unit 6028 run, 142 kept, 16 skipped | integration 6091 run, 174 kept, 25 skipped | over bound: unit, in…
With the controller gone nothing made the pair row of a new consumer: the vault minted only for a provider
handed to the provisioner (ADR 0349 clause 17's premise, that a holder filled the old way gets the controller's
value). A node composing its own now asks the vault for its credentials (own, ADR 0547 §2, ADR 0550 §5), so the
vault makes the first value of a shared or per-login provision for every holder, create-only (issue 1126; ADR
0570 §6). A remake or a rotation still waits while a holder is filled the old way. A credential asked of the
vault in mesh-provisioner's provisions starts a pass at once, one pass at a time, and vault_status answers each
provider and provision's last outcome as `credentials`.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check checking fa6dc3a48b0c on 32c4c52261c4 | novox/mesh-catalog#594 in group feat/1126-removal
When the forge's listing of pull request heads fails, the fetch now says it
as a download failure that may be retaken, so a forge outage is asked again
and not held as a refusal (issue 1748, issue 1126 review 3).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The group's check has no name lookup, so go failed on the network before it
could say it knew no such revision, and the fetch, reading go's words, took
the asked head for a download failure. Whether a commit is a pull request's
head is now the forge's fact, asked whenever go cannot fetch it; go's words
only label a commit on no head (issue 1748, issue 1126 review 2).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/delivery-group group feat/1126-removal rejected: composed together: the checker's verdict at the members' heads (a523066f1791): integration: meshbuildgo/c…
mesh/check failed: integration: meshbuildgo/cmd/mesh-build-go… | 7f8701637f9d on 32c4c52261c4 | judged by the candidate's mesh-build-go at b82f7f676986
nox cleanup delete without --confirm deletes nothing; the vault refuses it
for its missing confirm alone and judges only a confirmed delete, and nox
records the warranting act only for that one (issue 1126 review 2).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
nox records a hand act before each sensitive vault verb, with the verb's
address as its verb and cause operator; two in a fortnight raised a false
healer-wanted. mesh-healers reads those four verbs as decisions by design
(issue 1126 review 2).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
A reader on an older mesh-sdk refuses a provision field it does not know,
so a key a plan names carries no entry: such readers skip only a key ahead
of its consumer's want, which they could never bind (issue 1126 review 1).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh-provisioner keys provisions from a consumer's wanted and newest builds
but writes the wanted build's plan alone, so a requirement the newest build
adds was never bound. Each key now carries its plan entry, and a key ahead of
its want says in its why that no plan names it yet and its provider binds it
from the entry (issue 1126 review 1).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller is not placed (ADR 0590), yet the vault still answered a
caller named controller alone (accept), took its relay of who asked
(secret-ask, rotate's by) and sealed it the core's credentials. Those
branches and accept go with their tests; a node's account alone is never
minted or rotated here. The sensitive-verb judge now needs the act's verb to
be the vault's own, mesh-vault.<verb>, not any verb ending so (issue 1126
review 1).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Nobody raises a lost or a far-behind consumer since the self-check's bus-consumer probe ended (issue 1126): the grants
part makes a missing account consumer itself and says one far behind as mesh-grants.consumer-behind, and H4's repair
was the controller's. The mesh defines no consumer of its own, so H-bus's consumer half judged nothing.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh-hand-acts records one what per act, so an approve of two consumers
could never be warranted. The judge reads each word of the act's what as a
name, and nox records one act listing the consumers (issue 1126 review 1).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Each sensitive vault verb judges its own caller, and nox reaches the vault
as its machine's runtime, never as a person, so it could use none of them.
Before rotate, retire approve, cleanup delete and secret export nox records
the act through mesh-hand-acts (the vault verb as its verb, what it acts on
as its what) and names it as act; a refused recording calls the vault not at
all (ADR 0590 §8, issue 1126 review 1).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
With the controller ended mesh-sdk defines no mesh consumer, so the probe judged none and always passed (issue 1126).
The account consumers are the grants part's, which now says their differences and delays as conditions of its own;
the probe's three kinds are carried as ended in mesh-conditions' table.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The removal test took a grant written by hand; it now composes it with
BusRemovalGrants for controller-leftovers and the node-engine's acts, so
it proves the mesh's own grant is enough and no wider (issue 1126 B5).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
move-asks copied the controller's record of asks into the vault's once;
the controller is not placed (ADR 0590) and nothing else calls it. move-in
stays: the node-engine calls it. The drift test names the node's own
composition now that the controller composes for none (issue 1126).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh-sdk drops compare, take-over and hand-back from the keeper's and
config's seats (ADR 0590): there is no controller to compare with or hand
back to. mesh-conditions loses those verbs, its take-over key and asks;
mesh-config reads its own sources always and pull-declares is gone; and
mesh-hand-acts no longer names the controller's log (issue 1126).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller judged the operator's account for approving or deleting a
retirement, rotating a secret and exporting sealed copies; it is not
placed, and these verbs are reached through the mesh MCP server on each
machine. Each now answers the operator's account (person.<name>), or a
caller naming its own recorded hand act for that verb and subject, and
nothing else (ADR 0590 §8, issue 1126).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller is not placed (ADR 0590), so its tools, modules, nodes and
node verbs answer nothing. claude-code now reads the seats' verbs from the
seats' contract, the placed modules' replaces from the indexer's manifests,
and the machines and where modules run from mesh-placement's placement; the
rendered instructions name the seats that own each job (issue 1126 B13).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller is not placed and its assignments mirror is frozen (ADR
0590). artifact-store-tools already answers through the seat's holder, so
its controller client goes. mesh-provisioner-client reads the seat
mesh-placement's placement, which its account is granted whole: a module
placed here stays while the seat holds no plan of it, filled from its last
plan, and leaves only when neither names it (issue 1126 B12).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Both stand-in judges answered the fixed due date 2026-11-01; since 2026-11-02 00:00 UTC that date is past,
signalEntries drops the mail, no tell is sent, and both tests time out on every check that rebuilds the module
(met in the enrolment group's check of issue 774, 2026-11-02 02:50).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller is not placed (ADR 0590): messenger no longer treats it as
a condition owner or a walk's subject, mesh-watcher reads only where the bus
runs, restic tells the operator to compose the machine or set config through
the seats that do it now, and mesh-issues' examples name a placed repository.
mesh-issues keeps mesh-controller among its owners: issues located there,
issue 1126 among them, and route-proxy until it moves, still name it
(issue 1126 B11).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller ended by its unassignment, so its consumers, streams and
buckets may be removed as recorded hand acts (ADR 0590 §6). The nats tools'
account declares controller-leftovers in place of the lease write's two
words, and the removal test proves a consumer of EVENTS and a bucket's
stream go while EVENTS and its other consumers stay (issue 1126 B5).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
controllerdeps refuses any manifest naming the controller's seat, states or
buckets, the lease and the entries once kept to its write among them, and
any module file naming one of its buckets (ADR 0590 §5). The words check
refuses a controller address in any text a module shows. The handacts check
and noplacement's list of assignments readers are folded into it (issue 1126 B10).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The vault deletes a retired holder only when confirm repeats its name, so
sending confirm "true" could never delete anything. The stand-in console now
also says which machine answered as a block of its own, as node-tools does.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The console appends which machine answered after the JSON, so the nodes
table decoded nothing and printed the raw answer; read the first value
and keep the trailer.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller ended by its unassignment, so its lease is never handed and
both stayed in their controller-era branch (issue 1126, A5). mesh-config no
longer trusts the controller's relay: a trusted value needs the operator's
Approve. The condition keeper carries nothing from the controller, clears
once at start what it carried, and refuses take-over as the one source.
Both drop their manifest read of mesh-controller.lease.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
nox now reaches the mesh through this machine's console, so the module
requires mcp-endpoint and writes the bound address to /etc/mesh-cli/console
rather than trusting a fixed port. No invokes: mesh-cli has no bus account,
and one nothing dials would only be minted.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller nox forwarded every line to is unassigned (issue 1126), so nox
answered nothing but enrol open. Each line now calls the seat verb or module
tool that owns its job through this machine's console (mesh_call); a line no
seat owns says so and names what to use, never failing silently.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller ended by its unassignment, so its lease key is absent for good
and the healers stayed in shadow while nobody swept the artifact store (issue
1126, A4). Drop both gates and each manifest's read of mesh-controller.lease;
the would bucket stays readable until its keys expire.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller ended by its unassignment and its lease key expired, so the
gate on a handed lease kept retirement, rotation and node-login rotation off
for good (issue 1126, A3). Drop the gate, the lease watch and the manifest's
read of mesh-controller.lease; vault_status no longer reports a lease.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh-sdk now carries the hand acts that warranted a node's rotations as NodeLogin.Acts (ADR 0583 §2), so the vault's
own `acts` field beside the codec is gone: a used act is refused from the key's Acts, and a key written without them
keeps the ones recorded. The seat's tunnel takes all five fields; the wire table refuses an issue missing the machine's
tunnel key or the range as well. Built against mesh-sdk 4224665; mesh-vault stays at 134 unit tests.
(issue 774, 774/S43, 774/S46, review round 1b)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Review round 1 found that redeem could never succeed: the vault's answers were not the shapes mesh-enrolment decodes.
- enrolment-token reads `sealed` (not `show`), so asking for the sealed token no longer mints a new one; it answers
delivery.EnrolmentTokenAnswer: at issue the bus address, its certificate fingerprint and the vault's signing key.
- Issue takes the machine's first tunnel (`tunnel`), keeps it beside the token and refuses a token whose Missing() is
not empty, so the sealed token is one a machine can use (ADR 0587 §3, insight 2026-11-02).
- node-account answers delivery.NodeAccountAnswer: the login, and the password sealed anonymously to the presented
raw X25519 key in base64, as the node-engine's SealingKey.Open reads it.
- A joining node's certificate is signed for the serving key presented at the redeem, only when the four presented keys
have the digest node-account recorded; the name comes from placement (ADR 0587 §6).
- rotate-node refuses a hand act that is not rotate-node of this node, keeps the act id in the node's node-logins key
(`acts`, beside mesh-sdk's fields) and refuses an id used before (ADR 0583 §2).
The enrolment test now calls the real tool handlers and decodes every answer into mesh-sdk's types, failing on an
empty field; it replaces the earlier enrolment test, so mesh-vault stays at 134 unit tests.
(issue 774, 774/S43, 774/S44, 774/S45, 774/S46, review round 1)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The vault wrote its own copies of the NodeLogin key and the token; the node-engine and the grants part read them through
mesh-sdk's codec (delivery.EncodeNodeLogin refuses a key without its version, a login that is not the node's, a stage
without a rotation). It now writes and reads through that codec and builds the token with delivery.Token, so the shapes
are one (ADR 0583 §1 insight, ADR 0587 §3). Built against the group's mesh-sdk with a go.work outside the worktree; go.mod
still pins the earlier mesh-sdk, for the lead to re-pin.
(issue 774, 774/S43, 774/S46, 774/S49)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The seat mesh-enrolment's tokens answers the token sealed to the operator key; the operator opens it at their own
terminal. The subcommand reads the sealed token on standard input and the private key from a file, prints the token text
a joining machine takes, asks nothing of the node-engine's socket, and says the token is not sealed to a wrong key
(ADR 0587 §6, §8). New: one table-style test function; mesh-cli had 6, so none was merged or deleted.
(issue 774, 774/S51)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The vault serves the verbs enrolment-token, node-account, rotate-node, node-account-confirm and abandon, keeps the state
node-logins, and says rotation-begun, node-account-ready and rotation-done (ADR 0587 §3, §5, §8; ADR 0583 §1-§7 and
insights; ADR 0561 §4, §5). Only mesh-enrolment asks the first two and sign for an enrolment; a rotation needs a hand act
read back from mesh-hand-acts by its id, runs one at a time with the bus node last, and is ready only when the loaded list
holds the new login and done when it lacks the old one. A node's login is handed to that node's engine alone, sealed to
the key it stated. The key of a node that leaves the placement is deleted. Accounts kept for an enrolment or a node are
marked and never retired as unwanted.
Subtasks 774/S43 to S50 in one commit: they share enrolment.go, noderotation.go, tools.go and the manifest, and could not
be cut apart without a commit that does not build. New tests: 3 unit functions (table-style flows) and the one
integration test of S50; mesh-vault stays at 134 unit and 2 integration tests, within the module budget of 500 and 50, so
none was merged or deleted. The integration test's player gained a mesh/ask answer.
(issue 774, 774/S43, 774/S44, 774/S45, 774/S46, 774/S47, 774/S48, 774/S49, 774/S50)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check failed: mesh-build-go: the check of novox/mesh-catalog#590: the ask mvyhumdm860c7f's step on shanks did not end within 30m0s of its start |…
After the group the messenger and the watcher hear the condition keeper alone; a hand-back written to the take-over key
answered follow: controller and changed nothing. It is now answered as gone, naming its record, as placement's adopt and
hand-back are; the verb stays on the seat so a caller is told rather than not found.
Tests: none added; the hand-back lines of TestCompareCountsOnlyWhatBothSidesRaise become a row per lease state, each
answered as gone with the take-over key unwritten.
(issue 774, review g1 round 1)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
checks/controllerdeps decodes every module.json and judges the set with mesh-sdk's ManifestRefusals at the phase of the
lease write's own delivery, so no module reads, invokes or consumes the controller beyond the lease and the entries
kept to the write. At origin/main it refuses 11 declarations (the ones S7-S12 drop); at this head it passes. Two
tests (the real tree, and four rows on a tree of its own), in a new check of its own; go.mod pins the previous
mesh-sdk until the group's head is pinned, and go.sum needs the group's entries then.
(issue 774, 774/S13)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The three mesh-controller condition-event consumes, the invoke of mesh-controller.conditions, the follow switch
(takeover.go) and its read of mesh-conditions.takeover are gone: the messenger consumes mesh-conditions' events and
reads its open conditions from seat mesh-conditions.conditions at its start. An ask of the keeper is shown on a
condition's message like the controller's was. The manifest test now refuses any controller entry; the event test
refuses the controller's events; the words fixture's action verb names the keeper's. No test added.
(issue 774, 774/S12)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The watcher hears the self-check's `checked` alone: the consume of mesh-controller.doctor-heartbeat, the subscription
to the controller's seat, the follow switch (takeover.go) and its read of mesh-conditions.takeover are gone. The
manifest test now lists the one consume and the heartbeat-key test refuses the controller's event. No test added.
(issue 774, 774/S11)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh-hand-acts lists acts from its own log alone and no longer copies: its copy tools answer that the copy is over,
with the marker of the copy that was made (the live top-up runs before this delivery). mesh-healers drops the watch of
mesh-controller_hand-acts and counts the seat's acts: it asks the seat's `hand-acts` once at its start for the
fortnight (new invoke) and hears act-recorded after, an act listed and heard counting once, so a restart does not
forget the fortnight. Tests: the two-log listing and the copy table became one listing and one copy-is-over test; the
healers' count test lost its controller-bucket helper and gained the seat listing; the integration test now proves the
old bucket is not copied.
(issue 774, 774/S10)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Declarations come from the modules' own manifests and the list of predefined keys from the indexer's, whatever the
switch says; compare keeps only the pull request rows; hand-back is answered as gone; a switch that still names the
controller is read as the indexer and said gone. The read-only mirrors, mirrorDeclarations/mirrorList and the value
and list comparisons are deleted with their test cases (two table tests lose their mirror rows, one block of the
newest-list test goes; two table rows added).
(issue 774, 774/S9)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The keeper watches the controller's lease alone; the watch of mesh-controller.conditions, its constant and its manifest
read are gone, so no condition is carried from the controller's bucket any more. The manifest test now refuses that read.
The carry code in the keeper (Controller, the compare tool) stays, unfed, until the controller is removed. No test
added.
(issue 774, 774/S8)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The controller's declared-packages mirror ended with its lease: the view no longer falls back to it, the manifest no
longer reads it, and a node whose engine wrote no key is named in the answer (declared_none) instead. The fallback
rows of the view test became the no-key and unreadable-engine cases; no test added.
(issue 774, 774/S7)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
nats_bucket_expiry reads a bucket's stream, sets MaxAge (a duration, or none), reads it back, records a hand act
through mesh-hand-acts and says bucket-expiry-set, so the lease write can take the 15 seconds off the lease bucket and
the hand-back can restore them. Refuses a missing why and a name that is no bucket. Two new unit tests (stand-in
embedded server) in a module at 26 of 500; no test removed, none needed to stay in budget.
(issue 774, 774/S6)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
A test that slept a fixed time and then asserted what a goroutine, process or
watcher did failed under the checker's load. Each now waits for its positive
evidence (a started baseline, a call counted, a state reached) within 30 s, and
the concurrency-limit tests meet at a barrier instead of overlapping by sleep.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/delivery-group group feat/node-packages rejected: composed together: the checker's verdict at the members' heads (98ce55efa892): unit: i3/cmd/i3-tools.Tes…
The opener ranked the list and took its turn in the same step, so its upgrade started
before the keeper's change hook wrote /etc/pacman.d/mirrorlist, and a failed write on
any node was only logged. A round's run now writes the list first and checks the file
holds the revision the round opened with; otherwise the run is refused with why and
tried again an hour later, as every refused run is. A refresh asks again for a running
round right before its write, since ranking takes minutes.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The delivery group feat/node-packages pins one mesh-sdk head in every member: pacman reads EnginePackagesRead from it, and mesh-provisioner composes a node once with it.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
provisioner_compose took 2.6-13.6 s per node with nothing changed, CPU
bound. The node is now composed at its wanted and its newest builds over
one read (frombus.PlansHeldTwice, whose composer resolves each machine
once), its own plans, provisions and refusals and the providers' entries
are read from the watched copy, its own writes taken in at once, and a
provider's manifest once by digest: no read by key per composition is
left. The result says where the time went, phase by phase, and a slow
composition that changed nothing says it in the log.
BenchmarkComposeNode times it over a mesh captured with the read tools
(MESH_COMPOSE_CAPTURE): novox 11.7 s to 0.49 s, ace 0.49 s, g14 and
shanks 0.39 s; plans and provisions identical to before over nine
compositions of the four nodes.
Needs mesh-sdk feat/compose-once (5d26c65); go.mod still pins the old
mesh-sdk until the group pins its head.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Each node's reflector ranked its own list on its own timer, and on 2026-10-31 one node's
lagging first mirror left it a Node.js version behind the rest. The list is now the
module's state mirrors, key list: the node that opens a week's round ranks it with the
module's reflector options, keeps only mirrors whose last sync is no older than the
newest found, and the round's key names the list's revision. Every keeper writes
/etc/pacman.d/mirrorlist whole from the key through the root helper's new verb
mirrorlist, when the key changes and when the file differs, and never writes an empty
or unreadable list. reflector.timer is declared stopped and disabled, and reflector.conf
saves nothing. pacman_mirrors answers the shared list, its ranker and age and whether
this node's file matches; with refresh it asks this node's keeper to rank again,
refused while a round runs, naming it. The round's integration test proves the opening
write and both nodes' files.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
The read node-engine.packages named a bucket node-engine_packages that nothing writes:
the engine's manifest is mesh-host's, so its state is mesh-host_packages, read as
disk-load reads mesh-host.data. The view still names which source answered, the
engine's key or the controller's mirror.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/delivery-group group feat/l5-l7-main rejected: composed together: the checker's verdict at the members' heads (c598e176f3b2): unit: modules/gitea.the chec…
mesh/check failed: unit: modules/gitea.the checker's owed is what this module reads, and it consumes no check.status: "Cannot read properties of undef…
ADR 0580 clause 2 as revised: the holder hears haves by watch as it hears resolved values, so a have's change recomposes
its node from the copy it already holds.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
Composing one node read every placement, have, module and resolved key one at a time and took past 30 s with the bus
local (ADR 0580 clause 2): the holder now reads them from mesh-sdk's watched copy, its watch handlers queue the nodes a
change touches after the copy took it, and a resolved value's change recomposes its node. mesh-sdk pinned at ba8b8f2.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check checking 432326264f6c on 4b16c193f0fb | novox/mesh-catalog#585 in group feat/judge-once
The test copies aMesh's log, dated from 2026-10-01 for a fixed clock, but runs the holder on time.Now; since
2026-10-31 every entry fell outside the log's 30 days, so the sweep rightly kept every copy as unrecorded and the
mirror act was missing. The sweep is right; the fixture is shifted to now (issue 1955, L7a).
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/delivery-group group feat/judge-once rejected: composed together: the checker's verdict at the members' heads (5c42ba1fb5f3): integration: artifactstoreto…
mesh/check failed: integration: artifactstoretools/cmd/artifa… | 3e08301b27ea on 4b16c193f0fb | judged by the candidate's mesh-build-go at 8dd51540f73a
ADR 0573 §2 and §4 have a build take the latest published version of
each mesh package, or a group's own head, whatever go.mod names (issue
1585, S15). The fetch writes each asked version into the directory's
temporary modfile before downloading: a trunk commit is required at its
Go version with its checksums for go mod verify, a pull request's head
is placed as a pin on a head is, a newer go.mod version is kept and
said, and the answer and the log name each.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check pass 0c46f47ae57e on 444c2903af7b | unit 4510 run, 4259 kept, 49 skipped | integration 4589 run, 4361 kept, 51 skipped | over bound: unit, …
A key deleted while disk-load was not watching (a restart, a reboot, a machine asleep) never
arrives as a delete. Once the watch has handed over every current key, the readings of modules
with no key are retired once; an empty set is skipped and said, since the engine has not written.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
A round no longer retires readings missing from the watched set, which may be empty or partial;
a module's readings are retired when its key of mesh-host_data is deleted or names fewer items.
A round refused before the watch caught up runs once it has, not an hour later. disk_round reads
this machine's key alone, as its grant allows.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
It watches its node's keys of mesh-host_data instead of composing every module's items from
about 370 resolved keys per round, so a round no longer takes 30 to 45 minutes across the tunnel
and a manifest its mesh-sdk cannot judge no longer silences it. A changed key measures its module
at once; each round writes how far it got to the per-node state rounds, said by disk_round.
Pins mesh-sdk feat/data-items.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check being carried to 7e5980ff17e0 on 444c2903af7b | from 19714898986c
The check on 654d90a2 failed on TestTheSeatSweepsAtABuildsEndOnARealBusOnceTheLeaseIsAway, which fails the same
way at main's pin (2 hand acts recorded where 3 are expected; reproduced locally in 0.1 s). Not this change's.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check failed: integration: artifactstoretools/cmd/artifact-store-tools.TestTheSeatSweepsAtABuildsEndOnARealBusOnceTheLeaseIsAway: the hand acts r…
Since 2026-10-30 disk-load on every machine refused each round ("nats's tools bundle tools's bus removes
"ASSIGNMENTS", which is not one of ..."): its mesh-sdk copy (2da0de75) predates the allowance for removing
the ASSIGNMENTS stream (process_bus.go RemovesAssignmentsStream). No machine was measured, novox kept no
readings, and the controller's stale data-quiet on novox's jetstream kept mesh-conditions.compare apart,
refusing the L4 take-over. artifact-store-tools composes from the bus on the same copy and gets the same
pin. Same kind as mesh-catalog #580 for mesh-build-go; the thorough fix (every module on the latest
published mesh-sdk) is issue 1585.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check pass bbd02004b863 on 3d7830cfdc4f | unit 2729 run, 4570 kept, 16 skipped | integration 2975 run, 4493 kept, 25 skipped | over bound: unit, …
The self-check's D13 read every reading, good night, indexer module and
manifest one key at a time through the runtime and never finished
within its 30 s; it now keeps those states by watching them and judges
from memory, and reads the setting `probes` once a run. Findings name
their key's last part `ref`, since the runtime refuses a field named
`token`; the self-check, the healers and the keeper are pinned to the
mesh-sdk that reads it and lets a carried holder say its seat's events.
The controller's own bus.nats.upgrade-failed ends with its lease, as
the operator approved on 2026-10-31, so compare lists it apart.
Quick vs thorough: quick, these fixes for L4's take-over now; the
thorough fix (research 032 / ADR 0240's health view extension) is
decided later.
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
mesh/check failed: integration: mesh-vault/cmd/mesh-vault.TestTheVaultWholeMintsOnTheBusWhoeverHoldsTheLease: never: the account minted under the cont…
The build module checks every manifest with the mesh-sdk compiled into it. At a37181261c24 that copy did not know
the removal ASSIGNMENTS, so nats's manifest was refused at 11:45 and 11:48 and the catalogue's members of the group
(the vault, the provisioner and the rest) never built. A hand pin, allowed for this group one last time; issue 1585
makes every dependent follow a published mesh-sdk.
mesh/check failed: shanks: the check of novox/mesh-controller#487 failed: go mod download in modules/route-proxy: go: git.novox.be/novox/mesh-controll…
mesh/check being carried to 5d50b952d4cb on 65fad0ae1c31 | from a68b39f7b512
A record proposed before a retraction and accepted after it marked the
retracted clause changed or the retracted record superseded, serving it again;
and returning a drafted record numbered its clauses anew, bringing retracted
ones back in force or making a waiting Approve mark another clause. accept now
leaves what is retracted alone, Return refuses a record with a retraction, and
retract waits until a record's drafting is done.
The operator prefers removing a wrong decision to stacking a correcting
record on it, and withdraw took only reserved or proposed records. retract
asks the operator through the router like a record that needs the operator,
and changes nothing until the Approve; a retracted record or clause no longer
holds in ask, holds, get, links and progress, history keeps every version, and
the whole-set rules still read a retracted record's links so a retraction alone
raises no finding. withdraw with retraction true takes a waiting one back.
mesh/check checking fdb8deea4c9e on a68b39f7b512 | novox/mesh-catalog#577 in group fix/merge-ask-ends-on-merge
endStaleAsks skipped every merged delivery, so a pull request merged without the
Approve kept its merge ask in the gate's asks until it lapsed: on 2026-10-31 two
such asks held two of the router's three places for the teller and a placement
ask was refused for want of room. Every look now takes away a standing ask none of
whose deliveries is still open, read from what the gate keeps, so a failed take
away is retried. A settle asked again for another set takes the earlier settle ask
away for the same reason.
mesh/check being carried to b60138990b34 on dcf3950f7b07 | from 0e78909a75b9
Quick fix: the plan reader keeps the machine's one placement key for the answer, as it keeps each module's assignment (issue 1126, 2026-10-28); the second time one answer's reads per credential held own past the node-engine's 15 s.
Thorough fix (not here): the node-engine asks own only when a secret or a credential it composes from changed, and the assigner writes no want that is unchanged.
mesh/check being carried to 843c1c337cdd on cb91a4b9c292 | from mesh-sdk b74e23f973ab | novox/mesh-catalog#572 in group fix/one-rule-for-provisions
A module not handed now has a plan for what a provider's helper answers of it, so grafana's route is keyed and
route-proxy's helper hears it; handed modules' plans are unchanged. Deliver after #570, whose client reads a plan with
no templates.
On 2026-10-30 mesh-catalog #571 joined fix/held-module-and-assigner-contract at 21:59; the group stayed
checking, so mesh/delivery-group kept saying "3 of 3 member(s) ready" for a group of four, and #571 had
no mesh/delivery-group status until the state changed.
Quick fix: compare the why too. Thorough fix: compare the why and the member ids (each names its head),
so a push that keeps the count is said as well. Chose thorough: same size, covers the push case.
mesh/check checking b5475cfa5c3d on 395a37dddab9 | novox/mesh-catalog#571 in group fix/held-module-and-assigner-contract
mesh-healers slept 2 s before its first subscribe to the keeper's conditions; its whole test delivered
condition-raised once the lease was read, often before that, and the event was dropped: "never: the would-act
written" in about two runs of three on main, failing the group check. Eight modules had the same shape.
Quick fix: sleep after a failed subscribe in mesh-healers alone.
Thorough fix (chosen, the kind is in eight modules): every loop that asks the runtime for events or a watch
waits for stdio.Served() and subscribes at once, sleeping only after a refusal (mesh-healers, mesh-config,
mesh-mail, mesh-issues, mesh-provisioner, mesh-watcher, mesh-delivery-gate); mesh-knowledge, whose pinned
mesh-sdk has no Served, subscribes first and sleeps after a refusal. The healers' whole test delivers the
event only once the bundle has subscribed it, as the runtime's consumer holds it until then.
mesh/check being carried to 7522961ae3b0 on cb91a4b9c292 | from 5d9cead336ab
A plan with no templates archive made the client fetch an empty source and fail the module's report. The next
mesh-provisioner composes such plans (a module not handed gets one for what a provider's helper answers, its route), so
this reaches the nodes first.
Quick fix: none (a failed report per routed module). Thorough fix (chosen): a plan with no archive is read as provisions
alone by the one client every node runs.
mesh/delivery-group group fix/held-module-and-assigner-contract rejected: composed together: the checker's verdict at the members' heads (c82f18b5e6bb): integr…
mesh/check failed: integration: mesh-healers/cmd/mesh-healers.TestTheHealersWholeActOnTheBusAndBrake: never: the would-act written | b8ce4f0c0ac5 on 3…
The sweep of 2026-10-30 20:10: <node>.claude-code.gitea-read and <node>.mesh-build-node.npm-package-registry failed on
all four nodes with "gitea does not serve": gitea's provider helper answers only forge-account and refuses every other
bind into gitea.bound, and the provisioner took any entry of a module declaring `bound` as the outcome. And
novox.gitea.route, novox.keycloak.route and <node>.claude-code.mcp-endpoint stood asked: route-proxy and node-tools keep
entries the manifest did not read.
Quick fix: add route-proxy.bound and node-tools.bound to the reads. Thorough fix: judge each offer by who answers it
(answered-by: helper reads the entries, any other offer of a module that names a helper is judged by its have), and say
on gitea's forge-account that the helper answers it. Chose both: the reads alone leave gitea's two provisions failed.
mesh/check checking b4b22aac2060 on 0695ae25dbd2 | novox/mesh-catalog#567 in group fix/one-bad-item-holds-one-module
PlansHeld reads the same frombus input that refused every node on 2026-10-30 at 19:13; at 754edfae it holds the
module whose manifest the mesh refuses, with why, and composes every other module's plan. Quick and thorough fix are
the SDK's (one rule in frombus input); this is the pin.
ca8d6f33 gave power's bar item attributes its bar places by none of; ParseManifest refuses that, and at 19:13 on
2026-10-30 every node-engine refused to compose. No check of #565 parsed the manifest: that judgement was
mesh-controller's `module check`, run over every manifest by the old merge gate, and since the checker moved to
mesh-delivery it runs this repository's Go tests and the composition, where no test parsed a manifest whole.
Quick fix: a row refusing node-bar block attributes other than bar, place and order. Thorough fix: checks/manifests
parses every modules/*/module.json with mesh-sdk's ParseManifestWith against predefined.json and its templates beside
it, then CatalogueProblems, IdentityProblems and DataProblems over the shelf, the functions the nodes and registration
use. Chose thorough: it refuses every kind of manifest the nodes refuse, not this attribute alone. It fails at
7e905a66 naming power's item 2 and passes at 0695ae25.
mesh-provisioner, mesh-config, mesh-issues and mesh-healers need KeptState.Follow; mesh-build-go, -image and -node the
retry of a state write the bus delivered to no one; claude-code asks.Condition; mesh-vault the credential forms list.
Each passes go vet, go vet -tags integration and go test on this pin, built with no go.work.
683fd547 and b7f87822 took every `broker-<id>` own secret for a bus account. mesh-controller's broker-address is the
bus's address (MESH_BROKER_ADDRESS_FILE, read by broker.FromEnvironment to issue enrolment tokens and credentials):
c1 would have refused to keep it, and it was counted among the "owed bus-account hashes" every minute.
A name is now a bus account when it is declared: `broker` or `provisioner-broker`, or the own secret of an account the
grants part wants, which it composes from the manifests' bus processes (what catalogue.ToolsBusSecret names). A
`broker-<id>` holding an account the controller issued before its want was heard is still hashed. Anything else is
kept as given, never refused, never minted over, never hashed and never owed. The mint path replaced only wanted
names already, so the address was never at risk of replacement there; the test now proves it.
Quick fix: except broker-address by name. Thorough fix: the declaration decides, for every name. Chose thorough.
Table rows: broker-address kept as given, not replaced, owed nothing; broker-nats-tools replaced by a minted account
once wanted and refused a plain value after. They fail on the previous code.
mesh-provisioner, mesh-config, mesh-issues and mesh-healers each wrote a watch-again loop (`watched`). mesh-sdk
61b67d61 adds KeptState.Follow, which asks again with backoff and says each give-up, and its watches now answer a
change at once and run the handler beside the runtime (the provisioner's "names no watch of this bundle"). The four
modules use it; their loops are gone. Built and tested against the mesh-sdk group head through a go.work that is not
committed: their mesh-sdk pins move to that head with the group.
The client dated each report with the time it was said, and says a failure again whenever its words change, so the
controller's apply-failing alarm, which reads that time, saw a new failure: on novox the vault's refusal replaced a
bus refusal at 16:56 and the alarm cleared for five minutes while every module still failed.
Quick fix: the controller keeps a raised alarm while any failure stands (done there). Thorough fix: the report says
failing-since, kept from the module's last report (this run's, else the applied bucket's) while it stays failed,
whatever its reason says; any other status ends it. Chose both: the controller can now judge the failure's age
rather than its newest words, which is its change to make.
move-in's refusal "the vault already holds another value for ..." was an error's text, which the node-engine and the
controller could only quote. It is now an answer: `refused` with the reason holds-another-value and the held value's
record (generation, changed by, changed at, origin; never the value), `why` in words, and no read-back, so an
engine that does not read `refused` still fails as before ("answered with no read-back"). keepLocked's refusal is a
typed error (HeldAnother) whose text is unchanged for every other path.
Quick fix: a stable prefix in the text. Thorough fix: the fields. Chose thorough, as asked; mesh-host's
moveIntoTheVault has to read `refused` to use them.
The three random values kept before the vault judged them (own/novox/nats/broker-nats-tools,
own/novox/mesh-controller/broker-address and broker-management) are held, so minting refused them ("held already")
and their users stay off the bus. A value that is no account has no hash and logs in nowhere, so replacing it
breaks no login the grants part composed. When the grants part wants the user (every want is heard at the vault's
start), the vault now mints an account in its place, judged again under the store's lock, keeping the value it
replaces beside it. A held account is still never minted anew (ADR 0561 §4).
Quick fix: let an operator rotate the three by hand. Thorough fix: the mint path replaces any such value, so no
other one stays behind. Chose thorough.
own/novox/nats/broker-nats-tools (moved in today) and mesh-controller's broker-address and broker-management (moved in
from the controller's store) are random values, not the account JSON a bus user is hashed from, so the hash step says
"not JSON" and the grants part leaves those users off the bus. The controller made them (fixed there, c421629f); the
vault kept them, since nothing it keeps judged a covered name's value.
Quick fix: refuse a plain value in move-in. Thorough fix: keepLocked, which every way into the store passes, refuses
for any covered name (broker, provisioner-broker, broker-<binary>, which catalogue.ToolsBusSecret names) a value that
is no account, saying "not issued". Chose thorough: one rule where every value is kept.
gitea asked an owed status again every 30 s forever, even on 403 and 404 (jschoubben/hal and jschoubben/novadock, 119
times each in the sweep), and a key the checker deleted did not end a loop already running.
Quick fix: return from askAgain on 403/404. Thorough fix: the same, said once with its cause; a delete of the key
marks its revision seen, so any running ask again ends before its next write; a newer revision still asks anew.
The checker no longer owes statuses outside the mesh (mesh-delivery), which removes the trigger. Not done: raising
the module's health, since gitea's TypeScript SDK has no seat publish for a condition (mesh-sdk).
pair.go kept its own copy of the forms a plan may name; the copy in the provisioner client went in #564, after it
refused plans naming `none` while the vault's copy took them. Quick fix and thorough fix are the same here: the vault's
constants are mesh-sdk's (catalogue.CredentialForm*), and a form is judged by catalogue.IsCredentialForm, so a new
form is added in one place. No new test: behaviour is unchanged, and the existing form tests pass on the shared list.
mesh-vault's mesh-sdk pin moves to 9379e9a9, the provisioner client's, the first with the list.
i3status-rust on g14 and shanks cannot watch power.draw ("was issued: none", 148 times): its read was granted from
the bar contribution's data (shows: state, options.state; catalogue.ReadsGranted), and design 57 L3 moved the block
to an item, whose attributes said nothing of it, while ReadsGranted reads contributions alone.
Quick fix: `reads: power.draw` on i3status-rust, which grants every machine's draw instead of its own key (ADR 0260).
Thorough fix: the item says its read (shows: state, state: power.draw), and mesh-sdk's ReadsGranted grants a held
item's read as it grants a contribution's, keyed to the machine. Chose thorough; its mesh-sdk half is another
repository's, and until it lands the fault stays.
Grafana on ace answers 401 to the vault's admin password, every 30 s since at least 2026-10-05. I think the cause is
the adoption: Grafana keeps the admin password it was first given in its database and applies
GF_SECURITY_ADMIN_PASSWORD__FILE only when it creates it; ace's Grafana came with its database before the mesh minted
own/ace/grafana/admin (2026-09-30, generation 1, unchanged since), so the minted value never took (keycloak's
admin, hq issue 179, is the same kind).
Quick fix: none in code; the password in Grafana's database must become the vault's (grafana cli admin
reset-admin-password in the container), an act on ace no tool offers yet. Thorough fix: a step that converges the
admin password at every start, which needs a container entrypoint the node-engine's declaration does not carry.
This commit does what the catalogue can now: the refusal is said once with its cause and what ends it, asked again
hourly, and its end is said.
The sweep took the node seat node-engine's root-free for one nothing answers; the engines had been refused their
subscriptions by the bus since 12:10 (fixed in mesh-host), so the address was right. This puts it back and keeps
what the previous commit added: every failed ask said with its error, a fresh word not thrown away, and the failure
as the held ask's reason.
The file gitea-read.secret was declared with no owner, so it was root's at 0600; claude-code's tools run in the
node's runtime as the operator's account and could not read it ("permission denied", ~870 times a machine), said
only in the journal. A file a bundle reads is the runtime account's only when a word of the bundle names it
(catalogue givenTo); this one was found through MESH_CLAUDE_CODE_STATE alone.
Quick fix: name the file with the bundle word MESH_CLAUDE_CODE_FORGE, which the reader now uses. Thorough fix: the
same, plus a failure to place the credential raises a warning condition of the module on the operator-channel seat,
once per reason, cleared when it places again. Chose thorough: the fault ran unseen for days. A change of the
credential now restarts the node's runtime, as for every file a bundle word names.
claude-code's mesh-sdk pin moves to 2da0de75 (main's), the first with asks.Condition.
The controller grants a read only from the owner's announcement (ADR 0495 clause 3). gitea announced `bound`
unreadable, so mesh-provisioner bound no forge account; disk-load announced `readings` unreadable, refused to restic,
nfs-server and mounts; restic announced `good` unreadable, which the self-check reads. Nothing in the catalogue
compared readers with announcements since the gate's manifest check went (clause 5).
Quick fix: mark those three states readable. Thorough fix: also checks/readable, which reads every owner's Go and
TypeScript announcement and refuses any `reads` of a state it does not announce readable, so the next owner to
announce cannot repeat it. Chose thorough: the same kind hit three owners at once.
Reads of other repositories' owners (mesh-controller.lease, mesh-grants.accounts) are not judged here.
The messenger asked seat:node-engine.root-free@<machine>, which nothing on the mesh answers (the engine's acts are
left out of its declared state, mesh-host #178; ADR 0571 §11's self-check probe is not held either), and deleted
its kept word on each failure without a log line: every ask from an agent or a merge was held, silently.
Quick fix: point RootFreeVerb back at mesh-controller.root-free. Thorough fix: the same, plus every failed ask is
logged with its error, the failure is kept beside the word and becomes the held ask's reason, a fresh word is no
longer thrown away by one failed ask (an answer is still judged only on a word asked then), and a held ask whose
reason changes is logged. Chose thorough: the silence is what hid the fault for a day.
novox since 15:36 (nats's built manifest) and ace since 15:37 (baserow's config.json) had no plans at all, so the
vault refused every secret their clients asked. The holder now composes with frombus.PlansHeld: a module whose build
or plan refuses is held, its why kept in the new state refused and read by provisioner_plans, its last plan and its
provisions left as they were, and every other module on the node composed and written. Pins mesh-sdk 59311407.
mesh/check checking 67dcf252ecfa on 82ac613b4ed0 | novox/mesh-catalog#564 in group fix/credential-forms-one-list
Since 13:55 the client refused every plan with credential-form none
(gitea's forge-account, the artifact store), and g14 and shanks placed no
files for mesh-build-go, mesh-build-node, mesh-build-image or ssh-client.
Second meeting of the credential-form list kind: the controller's copy was
fixed alone before. Thorough: one list in mesh-sdk; this client drops its
copy and pins mesh-sdk 9379e9a. A none entry is never a holder's issued
value: its bound values come from the provider's entry, and a secret named
for it fails loudly instead of waiting on a vault that mints nothing.
mesh/check being carried to d6a069ae4959 on 1aa22efb0d78 | from 12c2574c9d54
On 2026-10-29 the group feat/774-vault-mints-l2 was approved and never handed: hq#495 kept a Decline of an earlier ask beside the Approve of the next, readyAsks skipped it and handTurn returned nil for every member, with no log line. The Approve and a new ask now clear an earlier Decline, a run's answer names its ask (answered_ask), an approved merge that waits for nothing and is not handed logs why once and is a stalled line, and delivery_turns lists no unwritten turn while the check gates no merge.
mesh/delivery-group group feat/774-l3-reland rejected: composed together: the checker's verdict at the members' heads (b48c90fea31f): integration: mesh-self-ch…
mesh/check failed: integration: mesh-self-check/cmd/mesh-self-check.TestTheSelfCheckWholeRunsOnTheBus: the run answered {Run:doctor-1793351737-1 At:20…
One commit with exactly the tree of the reviewed head 35b4509c0a, on main 12c2574c9d, so two compiled programs added and removed on the branch leave no trace in history (issue 1577).
mesh/check pass 96a37f58ca76 on 030f9ee4e780 | unit 1173 run, 3272 kept, 13 skipped | integration 1212 run, 3274 kept, 22 skipped | over bound: unit, …
The controller's declared-config mirror never held de-spiegel's keys, and Resolve skipped
an assigned module it held no declarations of, silently: de-spiegel stayed held on novox
with its values set. Declarations now come from the indexer's trunk manifest with the
wanted build's laid over it per node; which module runs where from the seat
mesh-placement alone. A placed module with no readable manifest is listed as unresolved
with why, logged, and keeps its last resolved values.
mesh/check pass add6f143ca23 on 158348ede789 | unit 1601 run, 5122 kept, 47 skipped | integration 1637 run, 5215 kept, 49 skipped | over bound: unit, …
On 2026-10-29 the group feat/774-vault-mints-l2 was approved and never handed: hq#495 kept a Decline of an earlier ask beside the Approve of the next, readyAsks skipped it and handTurn returned nil for every member, with no log line. The Approve and a new ask now clear an earlier Decline, a run's answer names its ask (answered_ask), an approved merge that waits for nothing and is not handed logs why once and is a stalled line, and delivery_turns lists no unwritten turn while the check gates no merge.
The test built its module with no settings file and no Capacity; the new
buildstep.NodeCapacity answers 0 for that (no default names a node), so the
puller took no ask and the test timed out after 90 s in check 205f634c30df.
Failed first locally at origin/main af89893d (90.1 s), passes with the slot (2.5 s).
mesh/check failed: integration: meshbuildgo/cmd/mesh-build-go… | 105c4d628cbc on d836a31aa721 | judged by the candidate's mesh-build-go at 565c52f06c02
The operator, 2026-10-28: the gates and trunk_rule apply to every trunk,
the branches the mesh installs from, and later there may be more than
main. The trunks are read at the call from mesh-delivery-gate's source,
in one function (trunksOf), and fall back to main, said, only when it
names none. A force-push onto any trunk is refused, and trunk_rule says
whether the branch asked is a trunk.
The operator, 2026-10-28: a call waits for their Approve only if it removes
branch protection or allows a force-push to main. No TypeScript tool can
ask yet (no asker in the TypeScript SDK; ADR 0286's mark is not built in
the runner), so such a call is refused with nothing sent, and every other
call runs at once. No tool removes a rule.
enable_prune is never in the forge's answer and mirror_interval comes back
as a Go duration, so a write that worked failed its read-back. The first is
now said as not read back, the second compared as a duration.
allow_merge_update, default_update_style and has_code are taken,
projects_mode needs has_projects true, and the description names what is
left out: the name, the tracker and wiki objects, and the mirror's
credentials.
Gitea reads the push whitelist and force-push allowlist flags only beside
their parent set true and passes over a missing default branch, both with
a 200, so the tool said set for what did not change. It now refuses a
dependent field without its parent, reads the rule back and names each
field not applied, and says what the forge changed beside the call. The
bypass allowlist fields complete the 32. gitea_repo_settings_set_full sets
a repository's settings, its default branch among them, as the forge's
administrator: gitea_default_branch_set is refused as mesh-tools.
gitea_branch_protection_set_full takes every field of gitea's branch
protection API by its own name, changes only those given, writes as the
forge's administrator, logs the required why, answers the rule before and
after, and says whether the controller's trunk rule (judgedRule in
mesh-control build_source.go) now holds. The operator, 2026-10-28: a
generic tool for any configuration; design 47 L2 needs de-spiegel's main
set as a trunk.
mesh/check pass 6724dab0cf96 on 387ee59140c4 | unit 2192 run, 3794 kept, 57 skipped | integration 2208 run, 3829 kept, 57 skipped | over bound: unit, …
On ace's reboot of 2026-10-28 every unit had stopped within 17 s, yet the bus and
polkit were started again during the shutdown, nothing stopped them a second
time, and the reboot waited on reboot.target's 30-minute job timeout, silent,
until the operator forced it. node-power owns the shutdown on every machine, so
its drop-ins on reboot, poweroff and halt shorten the bound; each target keeps
its own forcing action, so the last phase still ends every process, unmounts
and syncs. The cause, node-tools starting bundles again while it stops, is
fixed in mesh-tools.
mesh/check pass a9d96b30be8d on 69056948bfa8 | unit 1639 run, 4201 kept, 46 skipped | integration 1674 run, 4215 kept, 47 skipped | over bound: unit, …
A watch that failed partway kept what it had taken; begun again, the runtime does not hand a key deleted meanwhile, so
a removed assignment read as standing and credentialRefusal could hand a consumer credential to a node no longer
running its module. Each attempt now begins from nothing held, and a late delivery to an older attempt changes nothing.
A 'not on the node' refusal is confirmed by a direct read first, since a watched mirror can be behind.
Seed-9's probe (13:31-13:36Z): novox's own of 57 secrets and 146 credentials took 26 s, past the node-engine's 15 s,
and ace and novox refused their whole shadow answer. own read the controller's assignment over the bus once per secret
and per credential (203 reads), read every record of every node, and synced the hand-out record once per value, under
the one lock every node's answers share.
Now the vault watches the assignments mirror (a watch, never a poll) and reads it from memory once caught up, over the
bus until then; one answer reads each module's assignment once; only own/<node>/ records are read; and every hand-out
of one answer is recorded in one synced write, none handed when it cannot be.
Quick fix weighed: a longer bound in the node-engine (VaultWithin). Thorough fix chosen: the cost grows with every
module and every node, and the lock is shared by every shadow answer and every apply.
An image build node up 24 days had lost its running kernel's modules to a linux-lts upgrade, so tun
could not load and every RUN line failed in pasta. mesh-build-image now proves the tun device and,
whatever its look refuses, judges its node not eligible (capacity 0 with the reason), so the asks go
to a node that can build them. The kernel module loads tun at boot and declares kernel-modules-hook,
which keeps the running kernel's modules across an upgrade. Needs mesh-sdk fix/ace-tun (Puller.Eligible).
mesh/check being carried to 470687ea4cce on 774fcdfa93ad | from 2a03c106f4b9
An edited pull request is announced into its new base at once; a close without a merge is announced by its event; the 30 s/5 min polls and the 10 min sweep are gone.
mesh/check being carried to f5d4b2f86ed4 on 2a03c106f4b9 | from 9fd95693db54, mesh-delivery ae7ec702a5e9
A re-announcement updated the base head but never the base: a pull request retargeted from nox-mesh to main stayed 'into
nox-mesh' and was never asked or seeded, and one retargeted away from main kept its open ask.
A delivery made earlier can be announced again after a newer one, with main's head moved on: its base_sha is the freshest.
The gate now keeps when each base_sha was announced and seeds from the latest.
source.main moved only at a merge, so a repository never merged through the gate had no trunk head and the checker could
never judge its pull requests. The gate already hears main's head on each gitea.pull.updated (base_sha); it now adds it for
a repository source.main lacks, from the newest open pull request into main, in one compare-and-set write that never
replaces a head. A pull request into another base seeds nothing (ADR 0484 §11).
move-in never replaces a value the vault holds, so where the controller made an own secret anew after the move, the
new value runs while the vault keeps the first. The verb own-take-running takes it from the node-engine of the machine
it is for, keeps the replaced value as the previous generation, raises the generation and says own-replaced without a
value; own_drift lists every own secret a node's shadow answer says another value of, mesh-wide. The module needs the
mesh-sdk head of fix/1126-seed-same-own-resync (delivery.OwnValuesDiffer, the seat's verb).
A group member made ready in an event handler has no ready run when its sibling
is looked at; the bound counted from the older sibling alone, so a re-push past
60 minutes asked at once as unanswered. Such a member now counts as ready now.
The bound also counts from a check starting again at the same heads, or its
verdict being taken away, so a pass that turns back into running never asks at
once as unanswered. Times in the wait and the ask are the operator's zone
(Europe/Brussels, as the messenger says them), and a placement change whose pass
holds no composition says that no node answered its placement.
The operator, 2026-10-27 23:54: "if you don't want me to approve it, don't send
the approval request". The gate asked the Approve the moment a pull request
opened, before its check answered, and five changes were approved unchecked.
Now the ask waits for the checker's verdict at the heads it covers (a group's
verdict of all its heads together; a placement change's verdict ends only once
its nodes answered, ADR 0559 §5). A pass or a failure is asked, the failure in
its words, since check-gates-merge false lets the operator merge it anyway. A
check with no verdict 60 minutes after the heads became ready is asked anyway,
saying so, and asked again in new words when its verdict comes.
Quick fix (only the ask's wording) against thorough (the one place that decides
when to ask, ungatedWaits): thorough, which is one place here.
The levels a build module judges hand the tests MESH_BUILD_NODE=1; the tests that run a step in bubblewrap fail on it when bwrap is missing. Issue 1309
A replaced mesh-build-go left a check ask's step running and its start
sweep spared it (issue 1890, note 21). mesh-build-go, mesh-build-node and
mesh-build-image pin mesh-sdk 981a35b5, whose steps name their owner and
whose sweep ends another owner's at once; each runs the sweep through one
method that main calls and that its test runs through the conformance
kit's left-running case. The failurekit check now refuses a build module
whose tests do not run that case, test step or not.
With check-gates-merge false a head is ready and asked before any verdict exists, yet the ask said "<pr> passed its
checks" (a group: "passed its checks"): on 2026-10-26 the operator approved mesh-delivery #79 and a six-repository group
on that claim while their checks had not answered.
The ask now reads the checker's verdict at exactly the heads it covers (checkAt, beside checkerAt): "passed its check"
only for a pass there; otherwise "its check has no verdict yet[: it is running (since HH:MM UTC)]" or "its check failed:
<first failure>", and the Approve clause says it merges "now, before its check ends" or "although its check failed".
While the check gates no merge, a pending ask whose check then passes or fails (or loses a pass it named) is withdrawn
and asked again in new words (the ask's AskCheck against the state now, endStaleAsks, the review-record path's
withdrawAsk); a check that starts running is no new word, so the wait stays one message. Whether a merge waits is
unchanged. The gate's log lines and stalled lines that claimed a pass for a ready head say the same state.
Quick fix: replace "passed its checks" by neutral words in the two summaries. Thorough fix: one reader of the check's
state at the ask's heads (checkAt) used by every text that names it, and the ask re-said when that state changes.
Chosen: thorough, as it costs one helper and one case in endStaleAsks, and the quick one would still leave a pending
ask silent about a failure that came after it.
Tests: rows in TestAnApprovedPullRequestIsMergedThroughTheMergeTool (gated pass; ungated no verdict, running, then
passed, then failed) and the ungated group's wording; no new test function.
ReadTreeManifest reads predefined.json and each templated module's templates (WithTemplatesFrom), and the test reads
the root's health-undeclared through Kept: none was listed, so a change to them reused a stale verdict. No other
marker's package reads manifests through ReadTreeManifest beyond what it lists. Review finding F1 on ba49a7f0.
go list leaves a file its build tags exclude (an integration test) in IgnoredGoFiles, which the digest did not hash;
mesh-provisioner-client's unit test globs *_test.go and reads two of them, so a change there reused a stale unit pass.
Review finding F2 on ba49a7f0.
47 packages carried the marker and were never kept: about 2000 tests per level ran on every check, whatever it
changed. The marker now lists, as paths or globs from the repository's root (? before a path whose absence is read),
what the package's tests read outside it; the digest hashes those files with the package's own non-Go files. A marker
that lists nothing, names an unclean path, or a line that matches nothing keeps today's never-kept digest.
The 46 markers list their reads; checks/deps and checks/trunk lose theirs (their tests read only temporary
directories). Digest form 6.
Quick fix of issue 1936, chosen by the operator 2026-10-26 21:56; the thorough fix (the Go test log's files kept with
each verdict) stays on the issue.
photos' admin-client, client and server Dockerfiles live in subdirectories and copy
paths from the module's root (admin-client/..., client-server/serve.mjs), as build-agent
built them and as the fingerprint reads the module's whole directory. Taking the
Dockerfile's own directory as context failed every such COPY with copier: stat
"/admin-client/package.json": no such file or directory, on shanks and on ace.
Quick fix (rejected): move photos' Dockerfiles to its repository root; it changes the
operator's photo application and leaves the trap for the next module.
Thorough fix (chosen): one context for every image, the module's directory; it never
leaves that directory, so the isolation of ADR 0487 section 2 holds.
mesh/delivery-group group fix/capacity-follows-cpu-share rejected: composed together: the checker's verdict at the members' heads (63694fe9222d): unit: ..test
mesh/check checking 3f8b0b42480b on 7c5c29421f02 | novox/mesh-catalog#511 in group fix/capacity-follows-cpu-share
mesh-build-go, -node and -image declare build-hours (node=HH:MM-HH:MM in the node's local time,
empty = any hour) and hand it to the SDK puller (the operator, 2026-10-26: g14 builds only from
18:00 to 06:00); their SDK pin moves to mesh-sdk d00dac1, which has it.
Each of mesh-build-go, -node and -image declares cores-per-step (6, 2, 2) and hands it to the
SDK puller, which bounds the configured capacity by floor(slice quota cores / cores-per-step),
read live; thread limits and the status tools follow the effective capacity (issue 1806's
follow-up: three Go checks on shanks' 12-core slice starved past the 30-minute step bound).
mesh-build-go says its lint and test phases with the ask id (issue 1890).
mesh/check checking 851e8782d569 on da29f77b1081 | novox/mesh-catalog#505 in group feat/1126-nodes-compose
One commit for the branch feat/1126-nodes-compose of mesh-catalog: its 15 commits squashed so its history does not carry two compiled programs committed by mistake and removed later, mesh-config (5.5 MB) and checks/placement (6.2 MB) (issue 1577). The tree equals the former head 2db56067. The operator allowed this rewrite of the feature branch on 2026-10-26.
mesh-build-node kept the first fifteen lines of node --test's output, so a passing line of the first file stood for the
failure. Both build modules now parse through the SDK (go test -json, node --test's TAP report written to a file, the
type-check and go vet as console failures), name themselves in the result, and run the SDK's captured cases; the
catalogue check failurekit refuses a node-build-* module with a test step whose tests do not run the kit.
mesh/check being carried to 854dbfb3f3f0 on 7c5c29421f02 | from 3690c149c4ad
The seed linked 188 issues at once and every one read as moved at the seed's minute, hiding when each
really moved; on a worked issue the link also counted as its worker's activity. These links only place
an issue, so last-moved and the worker's activity leave them out.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# Check("../.."): every manifest and the files it names.
out=append(out,fmt.Sprintf("%s:%d: requires the controller's repository: it is archived once its last module is built elsewhere, so nothing here is built from it (novox/hq ADR 0593 §11)",filepath.ToSlash(rel),n+1))
}
}
}
buckets,err:=bucketLines(root)
iferr!=nil{
returnnil,err
}
out=append(out,buckets...)
sort.Strings(out)
returnout,nil
}
// names collects the strings of a decoded manifest that name the controller; inConfig is under the module's `config`.
// The check refuses every name of the controller, the lease and the entries once kept to its write among them, on a
// tree of its own; a repository named mesh-controller (an issue's owner) and a word in prose are no dependency.
funcTestRefusalsJudgeATree(t*testing.T){
for_,row:=range[]struct{
namestring
filesmap[string]string
wantstring// empty: passes
}{
{"the lease is refused like any read",map[string]string{"modules/a/module.json":`{"module":"a","reads":["mesh-controller.lease"]}`},`a: names "mesh-controller.lease"`},
{"a verb once kept to the write",map[string]string{"modules/b/module.json":`{"module":"b","invokes":["seat:mesh-controller.collect"]}`},`b: names "seat:mesh-controller.collect"`},
{"the controller's own module",map[string]string{"modules/mesh-controller/module.json":`{"module":"mesh-controller"}`},"mesh-controller: the controller is no module of the catalogue"},
{"a bucket in code",map[string]string{"modules/e/cmd/e/main.go":"package main\nconst b = \"mesh-controller_assignments\"\n"},"modules/e/cmd/e/main.go:2: names the controller's bucket"},
{"a requirement of the controller's repository",map[string]string{"modules/h/go.mod":"module h\n\nrequire github.com/novox/mesh-controller v0.0.0\n"},"modules/h/go.mod:3: requires the controller's repository"},
{"its forge path in a check",map[string]string{"checks/i/go.mod":"module i\n\nrequire (\n\tgit.novox.be/novox/mesh-controller/modules/route-proxy v0.1.0\n)\n"},"checks/i/go.mod:4"},
{"another repository of the forge passes",map[string]string{"modules/j/go.mod":"module j\n\nrequire git.novox.be/novox/mesh-sdk/go v0.1.0\n"},""},
{"a bucket in a test is its data",map[string]string{"modules/e/cmd/e/main_test.go":"package main\n// mesh-controller_lease\n"},""},
{"a fixture copied from elsewhere",map[string]string{"modules/e/cmd/e/testdata/x.md":"mesh-controller_rollouts\n"},""},
{"an owner and prose pass",map[string]string{"modules/f/module.json":`{"module":"f","config":{"owners":{"default":["mesh-controller","mesh-controller modules/route-proxy"]}},"why":"the mesh-controller module is gone"}`},""},
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
refused=append(refused,fmt.Sprintf("it claims %s, and no test of it calls conformance.LeftRunning "+
"(mesh-build-go buildstep/conformance): run the kit's left-running case with the module's own start sweep (issue 1890)",seat))
}
// Every build module meets the network (a fetch, a download, an install, a publish), so every one runs the passing case: its
// steps say a network that did not answer as a transport fault the bus gives the ask again for (ADR 0664, issue 1748).
says,err:=runsTheKit(dir,"conformance.Passing(")
iferr!=nil{
returnnil,err
}
if!says{
refused=append(refused,fmt.Sprintf("it claims %s, and no test of it calls conformance.Passing "+
"(mesh-build-go buildstep/conformance): run the kit's passing case with the module's own path from a failed run to its step's error (issue 1748)",seat))
}
// Every build module gives a step that met a transport fault again by the bus (ADR 0664 §5): it asks the tool runner's
// capability in its manifest, so the delivery plan places a tool runner that states it first.
if!slices.Contains(m.Capabilities,settleDelay){
refused=append(refused,fmt.Sprintf("it claims %s, and its manifest's capabilities do not ask %s: a step given again by the bus needs "+
"a tool runner that can settle with a delay (ADR 0664 §5, issue 1748)",seat,settleDelay))
}
j.Refused=strings.Join(refused,"; ")
out=append(out,j)
}
returnout,nil
}
// testTool is the name of the module's test step tool (<prefix>_test), or "".
functestTool(tools[]json.RawMessage)string{
for_,raw:=rangetools{
varnamestring
ifjson.Unmarshal(raw,&name)!=nil{
vartstruct{
Namestring`json:"name"`
}
ifjson.Unmarshal(raw,&t)!=nil{
continue
}
name=t.Name
}
ifstrings.HasSuffix(name,"_test"){
returnname
}
}
return""
}
// runsTheKit says a _test.go file under dir calls the kit's function call (such as "conformance.Run(").
"modules/i/module.json":`{"claims":[{"name":"node-build-i"}],"capabilities":["other"],"tools":["build_i_build"]}`,// the whole kit, and no seat-settle-delay
"a bare name hides cmd/<name>":{"nfs-server\n",[]string{"modules/m/cmd/nfs-server/","modules/m/cmd/nfs-server/"+Probe,"modules/m/cmd/nfs-server/main.go"}},
"anchored to the binary":{"/nfs-server\n/cmd/nfs-server/nfs-server\n",nil},
"a glob ignoring Go source":{"*.go\n!main.go\n",[]string{"modules/m/cmd/"+Probe,"modules/m/cmd/nfs-server/"+Probe,
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# every manifest, decoded; and the root's kept count of resources that do not say how they are ready.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# Check("../.."): every manifest, and whether the path each image artifact builds from is there.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# Check("../.."): every manifest, a TypeScript module's package.json and whether its lock is there.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
{name:"a manifest the judge can read",files:map[string]string{"a":`{"module":"a","version":"1"}`}},
{name:"a field no part knows is the judge's to refuse",files:map[string]string{"a":`{"module":"a","version":"1","unheard":true}`}},
{name:"bytes that are no manifest",files:map[string]string{"a":`{"module":`},refused:"modules/a/module.json"},
{name:"a field given twice",files:map[string]string{"a":`{"module":"a","version":"1","invokes":["x.y"],"build":{"artifacts":[{}]},"invokes":["z.w"]}`},
refused:"modules/a/module.json: the field invokes is given twice"},
{name:"a field given twice deeper",files:map[string]string{"a":`{"module":"a","version":"1","build":{"artifacts":[{"name":"t","name":"u"}]}}`},
refused:"the field build.artifacts[0].name is given twice"},
{name:"two manifests of one module",files:map[string]string{"a":`{"module":"x","version":"1"}`,"b":`{"module":"x","version":"1"}`},
// Package nobinaries refuses a compiled program under modules/ (issue 1577): it is build output, made by the module's build step,
// Package nobinaries refuses a compiled program anywhere in the repository (issue 1577; first a checks/ binary slipped past a modules/-only rule): it is build output, made by the module's build step,
// and `go build` in a module's folder writes one beside go.mod where `git add -A` takes it.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# every tracked file of the repository (git ls-files, no path limit): the whole tree, so this package's verdict is never kept.
out=append(out,fmt.Sprintf("%s: names %q, a name that is retired: the indexer keeps no placement (novox/hq ADR 0567 §12) and the seat mesh-module-assigner's state is assignments (novox/hq ADR 0641)",module,s))
}
}
sort.Strings(out)
returnout,nil
}
// named collects the strings of a decoded manifest that start with one of the Prefixes.
{"a placement directory",map[string]string{"placement/ace.json":`{}`},"placement: the repository holds no placement"},
{"a particulars file",map[string]string{"particulars":"ace\n"},"particulars: the repository lists no node names"},
{"a read of the indexer's placement",map[string]string{"modules/a/module.json":`{"module":"a","reads":["mesh-delivery-indexer.placement"]}`},`a: names "mesh-delivery-indexer.placement"`},
{"a read of its candidates",map[string]string{"modules/b/module.json":`{"module":"b","reads":["mesh-delivery-indexer.placement-candidates"]}`},"placement-candidates"},
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# that none of the old check scripts stands at the root.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# Check("../.."): every manifest; its lists are this package's own files.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# check("../.."): every file of the modules the covered list names. The node names come from the run (MESH_NODE_NAMES).
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# Check("../.."): every manifest and every file of a module.
# What these tests read outside their package, as paths from the repository's root (issue 1936).
# every module whole (a directory is read whole, so a module's Go source at any depth enters the digest), for a line that takes a plan existing for its module handed.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# the root's list of predefined keys and every manifest that names one.
continue// the manifest validator names a malformed seat read
}
targets,state=holders[seat],local
}elseifowner,local,ok:=strings.Cut(r,".");ok{
targets,state=[]string{owner},local
}
for_,owner:=rangetargets{
dir,inCatalogue:=dirs[owner]
if!inCatalogue||owner==reader{
continue
}
a,seen:=owners[owner]
if!seen{
varproblems[]string
a,problems,err=AnnouncedBy(dir)
iferr!=nil{
returnnil,err
}
owners[owner]=a
for_,p:=rangeproblems{
out=append(out,owner+": "+p)
}
}
ifa==nil{
continue// announces nothing from code: read as before
}
readable,keeps:=a[state]
switch{
case!keeps:
out=append(out,fmt.Sprintf("%s reads %s.%s, which %s's code does not announce: the read is refused on the mesh",reader,owner,state,owner))
case!readable:
out=append(out,fmt.Sprintf("%s reads %s.%s, which %s's code announces not readable: the read is refused on the mesh; announce it readable",reader,owner,state,owner))
return"",false,"an announce.State without field names cannot be read; name its fields"
}
key,_:=kv.Key.(*ast.Ident)
ifkey==nil{
continue
}
switchkey.Name{
case"Name":
v,ok:=resolve(kv.Value,consts,0)
if!ok{
return"",false,fmt.Sprintf("the state's name %s cannot be read: name it by a string, a constant of the package, or a mesh-sdk constant in checks/readable's Known",exprString(kv.Value))
out=append(out,fmt.Sprintf("%s: uses %s.%s, which is the build runner's, no longer mesh-sdk's buildstep; import git.novox.be/novox/mesh-delivery/modules/mesh-delivery-sdk/steprun (novox/hq ADR 0593 §1)",rel,buildstep,sel.Sel.Name))
{"a removed package","modules/a/x.go",head+"\t\"git.novox.be/novox/mesh-sdk/go/compose\"\n)\n\nvar _ = compose.Resolve\n","imports git.novox.be/novox/mesh-sdk/go/compose, which left mesh-sdk; it is the node-engine"},
{"under a removed package","modules/a/x_test.go",head+"\t\"git.novox.be/novox/mesh-sdk/go/compose/frombus\"\n)\n","the node-engine"},
{"the runner through mesh-sdk's buildstep","modules/a/x.go",head+"\t\"git.novox.be/novox/mesh-sdk/go/buildstep\"\n)\n\nvar _ = buildstep.RunAsk\n","uses buildstep.RunAsk, which is the build runner's"},
{"the runner through an alias","modules/a/x.go",head+"\tsdkstep \"git.novox.be/novox/mesh-sdk/go/buildstep\"\n)\n\nvar _ = sdkstep.Puller{}\n","uses sdkstep.Puller"},
{"the contract of buildstep","modules/a/x.go",head+"\t\"git.novox.be/novox/mesh-sdk/go/buildstep\"\n)\n\nvar _ = buildstep.NewID\nvar _ buildstep.Failure\n",""},
{"the runner's own package","modules/a/x.go",head+"\t\"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-sdk/steprun\"\n)\n\nvar _ = steprun.RunAsk\n",""},
{"a copy in testdata","modules/a/testdata/x.go",head+"\t\"git.novox.be/novox/mesh-sdk/go/compose\"\n)\n",""},
{"a required module in a block",map[string]string{"a/go.mod":aMod+"\nrequire (\n\tgit.novox.be/novox/r/b/sub v0.0.0 // indirect\n)\n","a/x.go":src("git.novox.be/novox/r/b/sub/pkg"),"b/go.mod":bMod},""},
{"a module not required",map[string]string{"a/go.mod":aMod,"a/x.go":src("git.novox.be/novox/r/b/sub/pkg"),"b/go.mod":bMod},"x.go imports git.novox.be/novox/r/b/sub/pkg"},
{"a test file",map[string]string{"a/go.mod":aMod,"a/x_test.go":src("git.novox.be/novox/r/b/sub/pkg"),"b/go.mod":bMod},"x_test.go imports"},
{"a module the longest owner is not",map[string]string{"a/go.mod":aMod+"\nrequire git.novox.be/novox/r/b v0.0.0\n","a/x.go":src("git.novox.be/novox/r/b/sub/pkg"),"b/go.mod":"module git.novox.be/novox/r/b\n","b/sub/go.mod":bMod},"does not require"},
// BesideDir is where the checker places mesh-sdk's clone, as a directory under MESH_CHECK_BESIDE; its go/ tree is judged.
funcBesideDir()(string,error){
beside:=os.Getenv("MESH_CHECK_BESIDE")
ifbeside==""{
return"",fmt.Errorf("NOT CHECKED: MESH_CHECK_BESIDE is not set, so mesh-sdk's source is not beside this check; the checker places the SDK there (besideRules)")
}
dir:=filepath.Join(beside,"mesh-sdk","go")
if_,err:=os.Stat(dir);err!=nil{
return"",fmt.Errorf("NOT CHECKED: mesh-sdk is not beside this check in MESH_CHECK_BESIDE=%s: %w",beside,err)
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# Check("../.."): every manifest and the files it names.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# Check("../.."): every manifest and its templates.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# run("../.."): the root's lists of retired words and lines, and every module's texts.
These tests read files outside this directory (the whole catalogue, the repository, or its root files): mesh-build-go never keeps this package's verdict (issue 1935).
# What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole;
# ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept
# until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing.
# the copies of this package in every module that carries one.
@@ -6,38 +6,34 @@ directory and the file the mesh writes there from its setting `older-store-names
## Why a module beside the store
The store is the `distribution` module. A module that provides the artifact store cannot also build an
artifact: building publishes to the store, so the store would be needed to create itself, and the
controller's module check refuses that manifest. So the store's tools are a second module, as the
controller's refusal says to do. **Assign it to the machine that holds the store**: its tools read the
store's files through the store's own container, and anywhere else they answer that the container is not
on that machine.
The store is the `distribution` module, the registry seats' holder. These tools became a module of their own when the
indexer's judge refused a store holder that builds an artifact; that rule is gone (issue 1966), and the sweep stays its
own module, holding the seat `mesh-artifact-sweep`. It requires no provision: what it holds, releases and removes it
asks the registry seats `oci-artifact-registry` and `container-image-registry` (see *The sweep through the registry
seats*), and what the store holds it reads through the same seats' `list` (novox/hq ADR 0632 §4): it reads neither the
store's files nor its read side, so it runs on any machine.
## Tools
| tool | | what |
|---|---|---|
| `artifact_store_repositories` | r | every repository: tags and what each names, how many manifests (tagged or not), size |
| `artifact_store_usage` | r | the store's size, the largest repositories, bytes shared between repositories, bytes no manifest marks (what the nightly collector frees next) |
| `artifact_store_usage` | r | the store's size, each manifest's as its seat says it, and the largest repositories |
| `artifact_store_references` | r | what the controller's records and the catalogue's definitions say of each manifest, counted and sized by state and repository; each manifest listed when one repository is asked; what the records keep that the store does not hold |
| `artifact_store_collect` | a | a dry run unless `dry_run` is false: what the controller would let go of, and the bytes the nightly collector would free then and now. A real run needs `why` and asks the controller's `collect` |
### How the store is read
The store's door lists repositories and tags, but not a manifest no tag names, and the mesh pins every
machine by digest, so that is most of them. So the bundle reads the store's own files through its own
container (`docker exec mesh-registry`, busybox `find`, `stat` and `cat`), and only reads them: every
blob with its size, every manifest each repository holds, what each tag names, and each manifest's
content, four hundred to an exec. What it read it keeps (a manifest is named by its content, so it never
changes), and the next call reads only what is new. A manifest that could not be read is counted and
said; what it marks beyond itself is then unknown, so sizes may read low and freed bytes high, and the
answer says so.
The store's read side lists repositories and tags, but not a manifest no tag names, and the mesh pins every
machine by digest, so that is most of them. So the bundle asks the two registry seats' `list`
(`container-image-registry` for images and indexes, `oci-artifact-registry` for bundles and archives), which the
store's holder answers from the store's own files: each manifest's digest, whether it is an index and the manifests it
names, the tags naming it, its size and whether a hold keeps it (novox/hq ADR 0632 §4).
docker runs as the tool runner's account; a socket that refuses it is asked again through `sudo -n`,
never with a prompt, as the container runtime's own tools do.
A manifest *marks* its own content, its configuration and its layers, and an index marks the manifests
it lists. The store's collector removes every blob no manifest marks, so these numbers are its own.
A manifest's size is its own content and every blob it names, as its seat says it, so a layer two manifests share
is counted in each, and the bytes the store's nightly collector frees are the sizes of the manifests that go, an
upper bound. The address the bundle says the store is at comes from `${seat:container-image-registry:reach}`, the
image seat holder's listen (ADR 0632 §1), and is used for the catalogue's definitions only, never to reach the store.
### The states of a manifest
@@ -61,7 +57,7 @@ record names leaves its platform manifests unrecorded with it.
**What the definitions pin** (hq issue 323). A definition may pin an image of the store the mesh did not
make: pushed before the mesh built it, and pinned under the store's current name or a name it had before.
No record of the controller names it, yet a machine runs it, so `artifact_store_references` reads every
definition the catalogue holds (`mesh-catalog.catalog_modules`, then `catalog_module` for each, eight at
definition the catalogue holds (the seat mesh-catalog's verbs `modules`, then `module` for each, eight at
a time and within twenty seconds) and finds every `<name>/<repository>@sha256:…` in any of its strings,
under each of the store's names: `artifact-store://`, the store's address as the controller answers it,
and the names it had before. Those are the mesh's setting `older-store-names` (space-separated, `none` by
@@ -99,19 +95,27 @@ manifest that stays and would lose a platform it names — to be read before a r
go test ./...
```
Against a fake container that prints what the two scripts would: the listing parsed (a repository name
with slashes, a cut listing refused), manifests read with one absent or unreadable said as unread, a
digest never becoming a path outside the blobs, the mark (an index, a shared blob, a blob nothing marks),
every state, what the records keep that the store lacks, bytes freed counting a blob shared with a kept
manifest as kept, a dry run never confirming, a real run without `why` refused before anything is asked,
Against a fake of the two registry seats' `list`: the store read through it (an index and the manifests it names, a
bundle's holder, a hold, the seat's sizes), every state, what the records keep that the store lacks, bytes freed as the
sizes of what goes, a dry run never confirming, a real run without `why` refused before anything is asked,
the fall-back when the references let go of cannot be carried, a manifest a definition pins under the
store's current or an older name, a definition not read said first, escalation through `sudo -n`, and that the
store's current or an older name, a definition not read said first, and that the
tools served are exactly the manifest's `tools` and its `invokes` exactly the two controller verbs and the
catalogue's two tools.
Any command other than the two read-only scripts fails the test.
Any ask other than a seat's `list` fails the read tools' tests.
## Files it does not know
Each directory or archive this module declares says how it treats a file it did not write (ADR 0422, ADR 0416).
-`${dir:state}`: everything in it is the program's; the mesh moves nothing out (ADR 0422 §2).
### The sweep through the registry seats
The sweep writes nothing to the store's door (CAT-AS1, ADR 0617 §2): it asks the registry seats the store's holder
serves. Each kept bundle or archive is held on `oci-artifact-registry` and each kept copy of an upstream base on
`container-image-registry` (`hold`, with why it is kept) before anything goes; each eligible one is released, then
removed for `retention` on its seat (`release`, `remove`). It reads a reference in both forms, `artifact-store://<path>`
and `<seat>/<module>/<artifact>@<digest>`, as one artifact, and says artifacts-gone in the form the build named it. A
call a seat refuses stops the sweep and writes the finding `sweep-refused` in the module's findings; the next sweep no
seat refuses clears it (`sweepseats.go`).
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.