Commit Graph
81 Commits
Author SHA1 Message Date
jschoubben e8d1bf96be Names N3 (watchman): the watchman names its own buckets from its credential's module
Its states presence, pulse and stuck and its first views were named from the constant
WatchmanModule; they are now `<cred.Module>_<state>` (watch.BucketsOf), and the watchman's
stuck keys of presence take its own presence bucket's name.

Builds: design 47 G A-296

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 19:09:46 +01:00
jschoubben edc8bbd9ab §7, §428 (watchman): a bus user is said by its module's name, the tool runner's no differently
signals.go BusUserWords: the node-tools special word is gone (the node-engine's node.<node> user stays, a bus account form, not a
module name). The watchman's ControlNodeModule (signals.go:591, nats) and builderModule (names.go:17) went with A-197 and WM13.

Builds: design 47 G §7, §428

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:59:49 +01:00
jschoubben 3eca094c5c A-197: the watchman reads no node-engine state: have and health go, running ends a want's pulse
Removed with the reads of node-engine.have and mesh-host.health: the findings module-unhealthy (module <module>.<node>, token
unhealthy, urgent after four hours), kept-as-it-runs (module <module>.<node>, token kept), apply-failing from a have that failed
(machine <node>; the provisioner clients' half stays), machine-network, network-rewritten, network-unreachable, machine-units,
relogin-needed, directory-used-as-found, node-account-fallback, and the urgency of a silent control node. A want's pulse now ends on
the node-engine's running event (consumes node-engine.running).

Builds: design 47 G A-197, A-192, §541

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:58:55 +01:00
jschoubben 161d6e6451 WM16: a record is covered only by what is late for the entries of its own revision
record-opened is joined to the take-in.taken of its milestone, <branch>.<source revision>, whose entries name the modules; the
record-open finding is left unwritten only while one of those modules is held by an acting-part-late wait (or a store says full),
no longer while any wait is late. A record whose revision is not known taken is covered by a standing take-in-waits.

Builds: design 47 G §502, A-200

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:56:33 +01:00
jschoubben 1abc5ae6d9 WM9, WM15: the manifest findings are the indexer's verdicts heard as events
manifest-refused raises manifest-refused; manifest-accepted, which carries problems, raises manifest-outgrown or clears it
and any refusal; the start seeds both from indexer_verdicts. The indexer's modules view (ModuleVerdict, views.modules,
indexer_read_modules) is no longer followed, and manifest-waits is no longer written (§500).

Builds: design 47 G §500, §196, §668

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:55:02 +01:00
jschoubben faec6b5333 WM13 (watchman half): the builder's builds are no longer read; a package wait is heard as wait-held
The watchman's read of mesh-delivery-builder.builds (Build in mirror.go, the bucket, its manifest reads) goes; it hears the
builder's wait-held and wait-ended on the builder's stream, naming a package as their part, and times them as an acting
part's wait. A toolchain wait (no part) is left to the builder's own finding. The node-engine's have and mesh-host.health
reads stay: no event carries a have's phase, kept data, node record or a node's health report (asked of the lead).

Builds: design 47 G A-192, §484, §496, §602, §548

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:53:23 +01:00
jschoubben 62de8d0bb8 WM4, WM5: the watchman hears the node-engine's wait-held and wait-ended
A hold of the composition standing past 30 minutes is delivery-waits (node, module, reason), a wait for a kept build
past 60 minutes is kept-build-waits; each clears on wait-ended. The node-engine's version is not yet named in them
(it needs the catalog entry of the fingerprint running.<node>.<node-engine's module> names).

Builds: design 47 G §499, §541, §271, §376

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:49:48 +01:00
jschoubben 464206d2de WM1 (step half): a head behind a pending revision of its branch raises no pipeline-stands
The watchman keeps the watched branch each open take-in wait names (take-in.pending's branch) and times a head only
while its branch has none; once the revision is taken in the head is timed again from its own move. The head on a
branch whose branch-unprotected stands (§497's second sentence) is not built: nothing the watchman hears says it
(the forge bridge writes that finding, no event).

Builds: design 47 G §12, §75, §497

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:48:30 +01:00
jschoubben 893f425c56 WM14: a put without hold that stands is the finding put-stands
A wait held with step put (no part) raises put-stands once its bound has run from its clock, and wait-ended ends it; a pipeline's
wait raises nothing for it. The seed from assigner_puts waits on that tool answering since and bound (assigner's, not built here).

Builds: design 47 G §498
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:39:03 +01:00
jschoubben 71a35a6376 MV1: move contracts and sdk under modules/, importers follow
The delivery repository's contracts and SDK live under modules/ as
mesh-delivery-contracts and mesh-delivery-sdk, their Go module paths
renamed to match the folders (the TypeScript names already did), and
every importer in mesh-delivery, mesh-catalog, mesh-host, mesh-tools
and mesh-sdk follows in the same group: a design as it should be, one
path per module, checked by the group's check building every importer.

Builds: design 47 G §427, §88

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:09:56 +01:00
jschoubben e6f91ed349 Watchman: time a build seat's ask from its step-progress, not from the holders' steps (fix 10, A-136)
Builds: design 47 G §483, §496, §602, A-136
2026-11-12 02:18:50 +01:00
jschoubben 316cf8a3be The steps of the build seats are watched and read by their holders: no caller of BuildModuleOf is left but the view's
The watchman asks the seat that places modules who holds each build seat (seatlist.HolderOf) and watches that
holder's steps; its manifest reads the seats' steps and invokes the seat's assignments. The builder's stuck
reader looks a step up by its seat, the tests find the holders on their test seat list, the watchman's
integration bed answers who holds a seat. Its manifest tests take the manifest's requires.

Builds: design 47 G A-82, A-126
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 01:34:12 +01:00
jschoubben 0def1a70d7 Watchman: list the machines failing toward x in also of machine.x.network and machine.x.silent
Builds: design 47 G §706 (the watchman's change)

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-11 22:35:25 +01:00
jschoubben c8fb62c3ad Merge branch 'feat/47-G-findings4' into feat/47-G-dev4-join 2026-11-11 22:25:53 +01:00
jschoubben 7310af36e6 G findings4 watchman: a finding's id keeps the safe key parts its condition's key had
Builds: design 47 G §689, A-14
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 21:56:38 +01:00
jschoubben 8cbb86dfbd G findings4 watchman: the watchman's findings are the seat's generated type, written through mesh-sdk's finding writer; the resolved words go
Builds: design 47 G §689, §686 (A-3), §461, §384, A-13, A-14, A-22
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 21:55:43 +01:00
jschoubben 95e2427553 WM6 (§269): the watchman consumes the seat mesh-grants' wait-held and wait-ended, so a granting wait past its bound is acting-part-late
Its handler already takes any seat's wait events; the manifest's consumes gain the two. Not run here: the watchman does not build
against mesh-contracts' meshconditionsclient as it stands (the findings writer's migration is another developer's).

Builds: design 47 G §266, §269, G-20 A-12

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 21:45:10 +01:00
jschoubben 497f87176b The builder, checker, view and watchman read a step key as SD4 has it: ParseStepKey answers asker, node and id
The join with CT-SD4 (6351e988) gives ParseStepKey four values (G §484, §649); the callers that read only the node or the id follow.

Builds: design 47 G §484, §649

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 21:16:18 +01:00
jschoubben c48c7e723a WM6: the watchman hears an acting part's wait-held and wait-ended and writes acting-part-late once the wait's bound has run from clock-from
Taken from 2d796fe8 (its wait half only; the store and record halves are WM7's, built). The body is the seat mesh-wants' contract Wait.

Builds: design 47 G §266, §269, §277
2026-11-11 14:47:47 +01:00
jschoubben 9f43e927e4 WM7 (store-filling): a store clears below 80 % of its cap, not 70 %
Builds: design 47 G §181, §263

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 13:53:50 +01:00
jschoubben 5fcd76a9f9 WM7: the watchman raises record-open 24 hours after a merge unless another condition covers it, and store-filling from the seats' filling, full and room
Builds: design 47 G §148, §160, §181, §218, §263

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 11:56:50 +01:00
jschoubben 43bebef626 WM3: the watchman says machine-away and machine-back of the seat mesh-watchdogs when a machine's presence expires and when it is heard again
Builds: design 47 G §389, §436

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 11:52:13 +01:00
jschoubben 69aeb817e2 WM2: the watchman raises build-capacity-waits for a build seat whose oldest queued step has waited 60 minutes
Builds: design 47 G §86

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 11:49:32 +01:00
jschoubben 0f618f1998 WM1 (head half): the watchman raises pipeline-stands for a watched branch's head with no pipeline within five minutes
Builds: design 47 G §12, §75, §112 (the head half; the step half waits on a design question)

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 11:48:38 +01:00
jschoubben 393f69f766 The watchman's seed ends the waits and findings indexer_pending no longer names (issue 1966, note 195)
SeedTakeIn, run once indexer_pending answered and after the findings of a previous run were read,
ends every take-in wait, held wait and take-in-waits finding whose key the answer does not name, as a
take-in.taken would. A seed that could not ask is not run, so ends nothing.

Builds: design 47 "Taken in by the indexer it names" (A wait is bounded, said and recoverable: "At its start the watchman seeds its open waits from indexer_pending, and ends every take-in wait and take-in-waits finding it holds whose key indexer_pending no longer names"); 1966/AC195-5

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-10 23:45:52 +01:00
jschoubben c2e466e16c The indexer says take-in.taken for every wait indexer_pending names (issue 1966, note 195)
A merge taken in with no take-in.pending said for it (read from indexer_pending at a
watchman restart, or said pending by the own-build-unknown path) ended with no taken
event, so the watchman raised take-in-waits for a wait nothing held. takeInWholeBy now
says taken for each wait WaitsOf names for the claimed entries (a revision by its oldest
merge's key, a group by its g. key) as well as for its said waits, without saying a key
twice. Drops are unchanged.

Builds: design 47 "Taken in by the indexer it names" (A wait is bounded, said and recoverable); 1966/AC195-1, AC195-2, AC195-3, AC195-4

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-10 23:45:46 +01:00
jschoubben 0eafb2fe95 The assigner's state and verb placement are assignments, with its events, tools, views and every caller; the assigner copies the retired state at its start (issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 22:13:20 +01:00
jschoubben 03809d8d83 Merge origin/main into b7/registry: the group try and the successor validation take the group's contracts, clients and seat list (issue 1966, issue 1921)
The seat verb try gains members (ADR 0637 section 6); the try's group name and the missing-preview reason are one definition of mesh-delivery-sdk (ADR 0637 section 8).

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 20:41:41 +01:00
jschoubben b638303104 No client names the holder of the seat mesh-provisioner: each reader keeps its own constant, held to its manifest (ADR 0625 section 4, issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 19:36:21 +01:00
jschoubben f6f18d04e1 The delivery SDK's enginereads, findings and heard leave for the clients of their seats (ADR 0634 sections 1 and 2, issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 19:22:05 +01:00
jschoubben 69a2790099 The indexer fixes its own build once at its start and never learns it later; a merge held for an unknown own build is said pending with why and since (issue 1921, ADR 0633 §1)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 18:47:31 +01:00
jschoubben c8241d0be6 No client names a holder: each reader keeps its own constant, held to its manifest (ADR 0625 section 4, issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 18:37:28 +01:00
jschoubben 2d987c5632 Merge b7q/registry into the registry milestone's mesh-delivery: provisions, overlay and findings onto their clients (issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 17:02:08 +01:00
jschoubben 8f1ffcd44d The grants part publishes busgrants (the removals' grants, the ended controller's leftovers, what the watchman hears); the watchman takes them and the self-check's checked from the seat, provisions from meshprovisionerclient (ADR 0634 §4, ADR 0635 §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 17:00:01 +01:00
jschoubben 444fa48fbf watchman: its findings are written and read in the seat mesh-conditions' layout through meshconditionsclient (ADR 0634 §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 16:49:27 +01:00
jschoubben 738c8ca036 assigner, view, watchman: provisions come from meshprovisionerclient, not mesh-sdk go/provisions (ADR 0634 §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 16:45:25 +01:00
jschoubben 88d100b9d5 Watchman: the node-engine's, wants', build steps', builder's and catalog's names come from their clients and seats, the watchdogs' codec from meshwatchdogsclient; the holders and buckets it names are its own constants checked against its manifest (D-11; ADR 0634 §1, §2, §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-05 16:28:51 +01:00
jschoubben 1cda01b869 Merge main (take-in #153, #154) into the registry milestone's join (D-0; issue 1966) 2026-11-05 14:16:17 +01:00
jschoubben c78941e80b Take-in events are the indexer's ordinary events: no stream of its own, which the manifest validator refuses (issue 1585, ADR 0633 §5)
mesh/delivery merged: source.main moved to novox/mesh-delivery@4596fbe1b7ac
mesh/delivery-group group feat/take-in merged: every member is merged
mesh/check being carried to c78941e80b59 on 4596fbe1b7ac | from ae31b66a9e33, mesh-catalog fd4931a75261 | novox/mesh-delivery#153 in group feat/take-in
The group's check failed at 7b7096f3: the group's own manifest validator refuses the indexer's stream "take-in", outside
the bus's predefined forms. The lead's ruling: the indexer says take-in.pending and take-in.taken as its ordinary events
(its emits, mesh.mod.<module>.event.take-in.<kind>), as manifest-accepted is said, and keeps no stream. The wait's key is
in the body only: an emitted event names one event (no wildcard), and a key such as g.<group> is no event name. The
watchman consumes the two events by name on the shared events stream; it needs no replay, since it seeds its waits from
indexer_pending at its start. indexer_pending says the last event of each wait as take-in.<kind>.

Run locally, as the check runs it: cmd/mesh-judge over every manifest of mesh-catalog, mesh-delivery, mesh-host,
mesh-tools, mesh-networking and mesh-media-catalog, with this branch's and mesh-catalog's feat/take-in manifests in the
change case and origin/main's in the trunk case: 171 of 171 accepted in both. The same run with the indexer's manifest at
7b7096f3 refuses it with the check's words.

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-05 00:59:27 +01:00
jschoubben 7b7096f37e Take-in, review round 1: no claim left behind, no sleep at the start, waits seeded at a restart, ends asked readable (issue 1585, ADR 0633)
mesh/delivery-group group feat/take-in rejected: composed together: the checker's verdict at the members' heads (38623984d6ad): mesh-build-go
mesh/delivery closed: a newer head of the same pull request
mesh/check failed (2): mesh-build-go: the indexer's judge at the group's mesh-delivery head 7b7096f37ea76e1…; and 1 more | 7b7096f37ea7 on ae31b66a9e33
- A take-in releases its claims (compare-and-set, only while the claim is still its own) on a lost claim, on a claim it
  cannot read back, and on a merge it fails to take in: a claim left behind refused every later take-in until a
  restart. T5 row with a store that fails once, both ways.
- The start step waits for nothing: with the build it runs unknown it says so and the forge consumer starts; a merged
  message left unacknowledged asks the build again (clause 1). T10 row: the start answers at once and takes nothing in.
- A toolchain report evaluates pending again (ToolchainReported), since the build a revision names moves with the
  toolchain. T7 row: the revision is taken in once the report makes it name the running build.
- The group's end is told by its whole subject (process.ModuleStreamSubject), so a repository named forge/group is
  never taken for one; row in the indexer's handle test.
- The watchman asks the indexer's waits through indexer_pending at its start (invokes), before its durable consumer,
  which does not hear again what it acknowledged before a restart; the comment that said the whole stream is heard is
  corrected. W2 row: a wait seeded within its bound is raised past it.
- bridge_groups names each group's last end ask, its who, why and when, and the bridge's answer (state end-asks).
- The check's words for the indexer's rules: the trunk's manifest validator.
- The bridge's end drops the merged-state test its merge commit already implies.
- Test budget: groupask_test folded into groups_test, and the K1 mesh/check test into the owed status one: 804 unit
  tests (was 806).

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-05 00:28:56 +01:00
jschoubben 4e4601a1eb Take-in and forge contracts live with their owners: the indexer's takein package, the forge bridge's forgemsg package; mesh-sdk pinned at main (issue 1585, ADR 0633)
The operator, 2026-11-04: logic one module owns lives inside that module as a package of its own, so the take-in step
changes no mesh-sdk. TakeIn, its keys and event names, PendingWait and PendingAnswer move to
modules/mesh-delivery-indexer/takein (its merges a takein.Merge of its own); Forge whole, with its group fields,
ForgeGroupEnd and GroupMerge, moves to modules/mesh-delivery-forge-bridge/forgemsg. Both are nested Go modules that their
readers take by replace, as buildrun is. Every importer moves in this commit: the indexer, the bridge, the watchman and
the view. Forge's private checks (the repository name, the version) are copied small; mesh-sdk main still holds an unused
Forge until its own fold removes it.

The indexer, bridge, watchman, view and checker pin mesh-sdk 5a38a12 (origin/main), no feat/take-in commit.

The bridge's integration bus now grants the state end-asks that bridge_group_end_again added: without it every test of
the package failed on a permissions violation. Test budget: two new test functions (TestForge, TestTakeInEvents) and the
two the join added are paid by merging four pairs in internal/bridge; the repository stays at 806 unit tests.

Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-05 00:05:01 +01:00
jschoubben ed4f07b0d8 Watchman: a take-in wait past its bound heard in the replay is said once the consumer has caught up, not after a time (issue 1585, ADR 0633 §5)
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-04 23:10:23 +01:00
jschoubben 7609f2d9a2 Watchman: a replayed pending that its taken ends is never raised; a drop then a pending again is covered (issue 1585, ADR 0633 §5)
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-04 23:09:20 +01:00
jschoubben 0579e4e74d Watchman: hear the indexer's take-in stream and raise take-in-waits past 60 minutes (revision) or 30 (group) (issue 1585, ADR 0633 §5)
Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
2026-11-04 22:54:21 +01:00
jschoubben 441b6d2922 G-delivery 3, 4: family-not-heard says it clears at the part's next start; views.Bound is two minutes
Bind runs once at a part's start, so the finding's words no longer promise it clears when the grants part makes
the consumer. The assigner's comment on firstViewBound named five seconds for views.Bound, which is two minutes.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 18:10:51 +01:00
jschoubben 121c6d9c48 G-delivery 2: sdk/heard's cases are rows of the watchman's findings table
mesh-delivery is over its unit budget, so the new function goes; its three cases run as rows of an existing
table of a user of the package.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 18:10:16 +01:00
jschoubben d4598f5772 F-delivery 4: a consumer that does not hear its family is a finding until it binds
The indexer's, the assigner's, the builder's and the watchman's consumers that were not there or could not be
heard only said so in the log, so the part stayed healthy while it heard nothing (ADR 0615 §5). sdk/heard is
the one shared helper: the finding family-not-heard names the observer and the family, written when the
consumer does not bind and deleted when it does.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 16:34:02 +01:00
jschoubben 395a1a0f40 F-delivery 3: the watchman waits for created only for entries not yet said created
The bus module says created once per entry, so every later accepted manifest of the module raised a false
bus-state-overdue five minutes on. The watchman keeps a mark per entry said created, on its pulse state with no
time to live and read back at a restart; a refused or an entry no longer asked drops it.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 16:29:21 +01:00
jschoubben 84a5094684 Join: merge A5's grants part, keeper and watchman consumers (wip/registry-a5 d53986f)
Conflict: modules/mesh-delivery-watchman/manifest_test.go, both sides asserting m.Consumes,
and both adding a Consumes field to the test's manifest struct (kept once).
Git also auto-merged module.json into two "consumes" keys (A2g's first views and A5's
manifest-accepted and mesh-broker events): joined into one list, and the test asserts all five.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 14:51:50 +01:00
jschoubben 72d8e2155f DLV-M5: the watchman follows the assigner's wants and the indexer's modules by their read tools' first views, read once answered
ADR 0615 §1: the watchman invokes assigner_read_wants and indexer_read_modules, consumes their views
families and never reads either bucket; it keeps first-views and writes an unanswered first view as a
finding of its own. The lead's ruling: an owner that is down never holds the start; each state is read
on a goroutine once its first view is answered, and what it holds (seeded pulses, stuck keys, the
findings it is the source of) is reconciled then (watch.Awaits, ReadLate), never dropped at the start's
end. Tools watchman_first_views and watchman_first_view_again.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 14:06:04 +01:00