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
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
2026-11-04 11:39:47 +01:00
1514 changed files with 86906 additions and 43431 deletions
{"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"}`},""},
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))
"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,
{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"}`},
out=append(out,fmt.Sprintf("%s: names %q, which the indexer no longer keeps; placement is the seat mesh-placement's (novox/hq ADR 0567 §12)",module,s))
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)
@@ -99,5 +103,5 @@ func main() {
iflen(found)>0{
os.Exit(1)
}
fmt.Println("no placement directory, and no manifest reads the indexer's placement")
fmt.Println("no placement directory, and no manifest names the retired placement")
{"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"},
continue// the manifest validator names a malformed seat read
}
owners[owner]=a
for_,p:=rangeproblems{
out=append(out,owner+": "+p)
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))
}
}
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))
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-catalog/modules/mesh-build-go/buildstep (novox/hq ADR 0593 §1)",rel,buildstep,sel.Sel.Name))
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-catalog/modules/mesh-build-go/buildstep\"\n)\n\nvar _ = buildstep.RunAsk\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"},
@@ -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
@@ -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
// The artifact-store-tools module's Go bundle (novox/hq ADR 0251 §1–3, ADR 0571 clause 2, to-be 51): a process the
// node's runtime launches and speaks MCP over stdio to. It says what the artifact store holds — its repositories, its
// size, and what the mesh keeps of each manifest — read from the store's own files through the store's own container,
// and it holds the seat mesh-artifact-sweep: the keep set, the sweep at each build's end, and S25's image-missing.
// size, and what the mesh keeps of each manifest — read through the registry seats' list (novox/hq ADR 0632 §4), and it
// holds the seat mesh-artifact-sweep: the keep set, the sweep at each build's end, and S25's image-missing.
//
// **A module beside the store, not the store's own.** 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. So these tools are a
// second module, assigned to the machine that holds the store. stdout is the protocol; what this bundle says, it says
// on stderr.
// **A module beside the store, not the store's own.** It requires no provision: what it reads, holds and removes it asks
// the registry seats (listed.go, sweepseats.go), never the store's files or its read side. stdout is the protocol; what this bundle says, it says on stderr.
@@ -78,12 +78,12 @@ must see, a node that joins later included — kept, so it carries no secret eit
| what | how |
|---|---|
| what this node holds | the module's `holdings` state, one key for this node — the account, the kind, fingerprints and expiries, never a token — written at start and whenever the credentials file changes (hq ADR 0206) |
| what this node holds | the module's `holdings` state, one key for this node — the account, the kind, fingerprints and expiries, never a token — written at start and whenever the credentials file changes (hq ADR 0206), and said whole as the event `holdings-changed` at start, on every change and again when the licence manager says `holdings.asked` (design 39 bus-and-switch §23) |
| a person ran `/login` here | the credentials file gains a refresh token this module never writes; its next report shows it, and the licence manager asks `claude_code_grant` for it, giving its key — the one time a refresh token leaves the node, for the manager to adopt by refreshing it |
| what this node should hold | the licence manager's `bindings` state, this node's key; on a newer generation this module asks `anthropic-licence-manager.current` for its token, sealed to the key it sends, and writes it access-token-only — so the agent here never refreshes. A node that was off reads its key when it is back |
| what this node should hold | the licence manager's `binding.changed` naming this node, and at start (or a reconnect) its first view, `anthropic-licence-manager.bindings` with `consumer` this node; an event for another node is ignored. On a newer generation, at start, and on the vault's `secret-changed` for the licence it holds, this module asks `anthropic-licence-manager.current` which licence, and the vault's `get` for that licence's access token (`licence.<key>.access`), sealed to its own key, and writes it access-token-only — so the agent here never refreshes, and never receives a refresh token. A home holding no token is fetched again at the same generation (design 39 bus-and-switch §19, §22) |
| an MCP server registered through this module before registering was refused (hq issue 340) | a key in the module's `servers` state — `all.<server>` for every node, `<node>.<server>` for one; every node watches it and renders what applies to it, a node's own entry over the one for every node. A node that joins later, or was off, reads the whole current set at start; unregistering is a delete. Nothing adds a key any more: a new tool server is the operator's, in the `mcp_servers` setting at the controller's terminal |
| a proposed instruction section (hq ADR 0274) | a key in the module's `proposals` state per proposal, the ask published on `operator-channel` under this module's name, and the router's record of it read under that name alone; what a node approved is its own file, never the bus |
| a session's question to the operator (hq ADR 0332) | a key `q-…` in the module's `questions` state per question, the ask published on `operator-channel` under this module's name, and the router's record of it read under that name alone; the router's word that it ended without a choice is kept on the question; two slot keys `slot-1`, `slot-2` name the questions open |
| a session's question to the operator (hq ADR 0332) | a key `q-…` in the module's `questions` state per question, the ask published on `operator-channel` under this module's name, and the router's record of it read under that name alone; the router's word that it ended without a choice is kept on the question |
| a project's memory (hq ADR 0343) | a key in the module's `memory` state per file — `<kind>.<project and path, base64url>`, `operator` for the operator's own homes and `agent` for an agent account's — holding the text, its digest, the digest of the version it replaced, the node and when it changed; a removal is a value marked removed, never a deleted key. Written at the revision read, so of two nodes writing one file only one wins. Every node of the same kind watches it. No event and no tool answer carries memory text |
| the agent's configuration (hq ADR 0216) | a key in the module's `config` state per registration — `mesh.<kind>.<name>` for every node, `node.<node>.<kind>.<name>` for one, `home.<node>.<kind>.<name>` for one account's own directory — the item and its files in one value, at most 256 KiB. Every node watches it and renders what applies to it, a node item over a mesh item of the same kind and name. A hook, settings, or an item that would run something by itself is never taken, whenever it was put there (hq issue 340) |
@@ -122,7 +122,7 @@ The agent kept reaching for `ssh <machine> journalctl` while the service manager
- **The "instead of" table.** Every seat verb and module tool may say which shell commands it replaces
(`replaces`, in the seat's definition or the module's manifest). The module reads the bus — the seats' verbs from the
seats' contract, the placed modules' manifests from `mesh-delivery-indexer.modules` and `.manifests`, the
machines and where each module runs from `mesh-delivery-assigner.placement` (issue 1126: the controller that
machines and where each module runs from `mesh-delivery-assigner.assignments` (issue 1126: the controller that
answered this is not placed) — at start, every ten minutes and on `claude_code_render`, keeps it in its
state (`mesh-tools.json`), and renders it into `CLAUDE.md` as one row per seat or module: `<node>/<seat>.` and
each verb with the commands it replaces. Generated, never written by hand: a verb that gains `replaces` is in
@@ -150,8 +150,8 @@ record is how a habit that found a way round is seen.
## Tools
`claude_code_status`, `claude_code_render`, `claude_code_guard`, `claude_code_pull`, `claude_code_grant` (for the licence
manager), `claude_code_mcp_list`, `claude_code_mcp_unregister` (this node by default; `nodes: "all"` or a list for
`claude_code_status`, `claude_code_render`, `claude_code_guard`, `claude_code_pull` (asks the vault for this node's
licence token now), `claude_code_grant` (for the licence manager), `claude_code_mcp_list`, `claude_code_mcp_unregister` (this node by default; `nodes: "all"` or a list for
more).
**What a session runs or obeys is the operator's, at the controller's terminal** (hq issue 340). A hook, a
@@ -206,10 +206,20 @@ judges the record as this module would have made it, composes the ask again from
the text's digest, in time), and only then writes the section into its own `approved.json`, which the managed
instruction file renders under "Instructions the operator approved". A proposal is decided once per node, and an approval older than the last change applied to its section is never applied; a record
deleted from the bus removes nothing. Refused: shell lines, front matter, any `@` after a non-letter (a file the instruction file may read in), invisible or control characters, headings of level one to three, anything shaped like
a secret, more than 16 KiB, a name the terminal sets, and — at once, naming the terminal's line — whenever no channel
a secret, more than 16 KiB, and — at once, naming the terminal's line — whenever no channel
that proves its sender is there. The controller's hand-act log records each warrant once (`warranted`), read from the
router's record. The text is never logged.
**A section registered before is replaced or removed the same way** (hq issue 340, note 14): a section registered for the
mesh or the node before the controller's terminal took that over, or set there, is proposed over by name. The proposal
carries `over`, the digest of the registered text, which the act the operator's answer binds names; the ask says
plainly that it replaces (or removes) the registered section, with the registered text's fingerprint, and shows the new
text as any other. On Approve each node writes the section into `approved.json` with that `over`, and the managed
instruction file renders it in the place of the registered section (a removal leaves the section out); on Decline or at
expiry nothing changes. A replacement keeps the registered section's own heading form, because it replaces a mesh
section; the heading rule stays for every new shared section. `claude_code_proposals` shows each proposal's `registered
section` and `claude_code_registrations` lists what approvals replaced or removed.
**A session asks the operator a question on Telegram** (hq ADR 0332, issue 589). An agent that needs a decision while
the operator may be away from the terminal calls `claude_code_ask` with a headline, the context in plain words, two to
four options (a label and what choosing it means, exactly one recommended, with why), what it does if nobody
@@ -223,11 +233,8 @@ key says waiting, chosen (the option, who answered, on which channel, when), end
refused, cancelled, replaced), or not proven: the answer is read from the router's own record and held to the
question as `questions` keeps it, so a question rewritten after it was asked, a warrant for another ask or a choice
after expiry is never read as a choice. One call waits at most 60 s; the tool asks a session to read a question at
most once a minute, and nothing enforces it. At most two questions wait at once, mesh-wide: each holds one of two
slot keys in `questions`, taken by create or compare-and-set, so two nodes asking at once cannot both take the last,
and a slot that cannot be read refuses the question. Questions alone never fill the router's three open asks, so one
is left for a proposed instruction section while two are open. A question the router holds no record of, its refusal
not heard here, keeps its slot and reads as waiting until it expires: the router may still take it from its queue,
most once a minute, and nothing enforces it. No question is refused for how many wait: the router offers an asker at most three asks at once, holds the oldest back behind newer ones and offers it again when one ends (hq ADR 0666 §12). A question the router holds no record of, its refusal
not heard here, reads as waiting until it expires: the router may still take it from its queue,
and no cancel can overtake it there (the queue offers work again after an error, and a cancel of an ask not yet
recorded is dropped); once expired, the router refuses it if taken late. A refused question keeps none of
its words. An answer is the operator's word to the session and authorises nothing; a question never defaults.
// Ready is nil once every watched branch has its first view (none-yet counting as one), else says what it waits for.
Ready()error
}
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.