Fixes the SDK part of hq issue 365 (the issue tracker cannot prove who opened or changed an issue): a module is never told who called its tool.
What changes. The runtime names the caller it took from the subject a call arrived on in the tools/call's _meta (mesh/caller). stdio.CallerOf(args) inside a tool answers that bus user; stdio.Unproven ("unproven") when the runtime named none (an older runtime, or a call on the subject that names no caller), or named something that is not a bus user's name. Never read from arguments: a caller or _meta inside the arguments names nobody.
Backward compatible.Tool.Run(args) keeps its signature; a tool that never calls CallerOf is unchanged. The caller is held per call by the identity of the arguments map the tool is handed, so a tool reads it with the map it already has (one line for mesh-knowledge's callerOf). The TypeScript, Python, Rust and C bindings ignore _meta and are untouched.
Tests (fail first: they do not compile on main). go/caller_test.go: the caller the runtime named reaches the tool; a caller in the arguments is never the caller; no _meta, an empty or malformed one, is Unproven; arguments of no call have no caller. sh merge-check.sh passes (TypeScript suite and go/).
Rolls first. Nothing calls CallerOf until mesh-catalog's mesh-issues pins it (pinned at this branch's head d9e24e9 until merged; re-pin to the merge commit after).
Companion pull requests, same branch name: mesh-tools (runtime: caller-named subjects, caller handed to the module), mesh-controller (grants), mesh-catalog (mesh-issues reads the caller). Retirement of the old subjects: hq issue 464.
Fixes the SDK part of hq issue 365 (the issue tracker cannot prove who opened or changed an issue): a module is never told who called its tool.
**What changes.** The runtime names the caller it took from the subject a call arrived on in the `tools/call`'s `_meta` (`mesh/caller`). `stdio.CallerOf(args)` inside a tool answers that bus user; `stdio.Unproven` (`"unproven"`) when the runtime named none (an older runtime, or a call on the subject that names no caller), or named something that is not a bus user's name. Never read from `arguments`: a `caller` or `_meta` inside the arguments names nobody.
**Backward compatible.** `Tool.Run(args)` keeps its signature; a tool that never calls `CallerOf` is unchanged. The caller is held per call by the identity of the arguments map the tool is handed, so a tool reads it with the map it already has (one line for mesh-knowledge's `callerOf`). The TypeScript, Python, Rust and C bindings ignore `_meta` and are untouched.
**Tests (fail first: they do not compile on main).** go/caller_test.go: the caller the runtime named reaches the tool; a caller in the arguments is never the caller; no `_meta`, an empty or malformed one, is Unproven; arguments of no call have no caller. `sh merge-check.sh` passes (TypeScript suite and go/).
**Rolls first.** Nothing calls `CallerOf` until mesh-catalog's mesh-issues pins it (pinned at this branch's head d9e24e9 until merged; re-pin to the merge commit after).
Companion pull requests, same branch name: mesh-tools (runtime: caller-named subjects, caller handed to the module), mesh-controller (grants), mesh-catalog (mesh-issues reads the caller). Retirement of the old subjects: hq issue 464.
The runtime names the caller it took from the subject a call arrived on in the
call's _meta; stdio.CallerOf(args) hands it to the tool. Never read from the
arguments, and Unproven when the runtime named none, so a bundle on an older
runtime still says, explicitly, that its caller was not proven.
composed together: pass — every machine composes with the change as it did without (4 of 4 compose)
Machines
mesh-issues on novox: passed — healthy 3 times over 2m41s
mesh-knowledge on novox: passed — judged with mesh-issues: healthy 3 times over 2m41s
mesh-sdk on every machine running it: sent
mesh-issues on the rest running it: sent
mesh-knowledge on the rest running it: sent
Transitions
2026-10-11 03:26 (new) → proposed (announced): novox/mesh-sdk#20's head announced
2026-10-11 03:28 proposed → checked (checked): the verdict names this commit
2026-10-11 03:28 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-11 09:28 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-11 09:51 published → held (hold): something holds it for a person: its group's composed check did not pass for the heads that merged, or it merged and no walk was opened for it
2026-10-11 10:07 held → delivering (go): its walk started on a word that was not this owner's: the controller's own path, which waits for nobody, or a person's plans go
2026-10-11 10:11 delivering → delivered (done): its walk is done, carrying its own commit: every machine of its deploy plan passed, or was left as its policy says
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-sdk@d9e24e95a242` — **delivered** since 2026-10-11T10:11:55Z
**Delivery plan** — builds mesh-sdk, sent nowhere; no bus step
- tier 0: mesh-sdk
**Group** `fix/365-a-tool-call-names-its-caller`, in order: novox/mesh-controller@ebca7816bf08 → novox/mesh-catalog@61f81d44547a → novox/mesh-sdk@d9e24e95a242 → novox/mesh-tools@ab0f888d67d2
- novox/mesh-controller@ebca7816bf08 before novox/mesh-catalog@61f81d44547a: built by
- novox/mesh-controller@ebca7816bf08 before novox/mesh-sdk@d9e24e95a242: built by
- novox/mesh-controller@ebca7816bf08 before novox/mesh-tools@ab0f888d67d2: built by
- composed together: pass — every machine composes with the change as it did without (4 of 4 compose)
**Machines**
- mesh-issues on novox: passed — healthy 3 times over 2m41s
- mesh-knowledge on novox: passed — judged with mesh-issues: healthy 3 times over 2m41s
- mesh-sdk on every machine running it: sent
- mesh-issues on the rest running it: sent
- mesh-knowledge on the rest running it: sent
**Transitions**
- 2026-10-11 03:26 (new) → proposed (announced): novox/mesh-sdk#20's head announced
- 2026-10-11 03:28 proposed → checked (checked): the verdict names this commit
- 2026-10-11 03:28 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-11 09:28 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-11 09:51 published → held (hold): something holds it for a person: its group's composed check did not pass for the heads that merged, or it merged and no walk was opened for it
- 2026-10-11 10:07 held → delivering (go): its walk started on a word that was not this owner's: the controller's own path, which waits for nobody, or a person's `plans go`
- 2026-10-11 10:11 delivering → delivered (done): its walk is done, carrying its own commit: every machine of its deploy plan passed, or was left as its policy says
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-sdk)
mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript), go/merge-check.sh (go)
Delivery plan — builds mesh-sdk, sent nowhere; no bus step
tier 0: mesh-sdk
Run by the build seat on g14 as build-1791689170651169779 (builds --log build-1791689170651169779).
ok 11 - a waiting set the mesh asks for again settles, and nothing is retired
---
duration_ms: 68.085113
type: 'test'
...
# Subtest: delete refuses an active consumer and deletes only the named retired one
ok 12 - delete refuses an active consumer and deletes only the named retired one
---
duration_ms: 58.920703
type: 'test'
...
# Subtest: an addition acts on the first pass
ok 13 - an addition acts on the first pass
---
duration_ms: 13.475105
type: 'test'
...
# Subtest: what the backend holds at start is retired by the same rules
ok 14 - what the backend holds at start is retired by the same rules
---
duration_ms: 48.781987
type: 'test'
...
# Subtest: the four tools are registered for the module and answer
ok 15 - the four tools are registered for the module and answer
---
duration_ms: 1.925031
type: 'test'
...
# [tools] broken: contributor failed, exposing none: Error: no token
# Subtest: semver orders releases
ok 16 - semver orders releases
---
duration_ms: 0.766137
type: 'test'
...
# Subtest: module tools register and collect, a thrower is skipped not fatal
ok 17 - module tools register and collect, a thrower is skipped not fatal
---
duration_ms: 0.483858
type: 'test'
...
# [provisioner:analytics] webapp-anchor: no longer in /tmp/prov-N5RcGF/analytics.json; RETIRED, MARK ONLY — this provider cannot disable a consumer (its adapter has no retire), so webapp-anchor KEEPS ITS ACCESS and its data until a person deletes it with `cleanup delete`. Nothing was changed in the backend (novox/hq ADR 0230): the mesh stopped asking for it: the same answer in 5 passes over 0s, from 2026-10-11T03:28:35.703Z
# [provisioner:analytics] webapp-anchor: DELETING, asked by someone: gone for good
# Subtest: provisioner creates each consumer with the mesh's login and password; remove waits for a person's delete
ok 18 - provisioner creates each consumer with the mesh's login and password; remove waits for a person's delete
---
duration_ms: 219.395091
type: 'test'
...
# [provisioner:s3-bucket] mesh_anchor_ncloud: no longer in /tmp/prov-derived-KP51J3/store.json; RETIRED, MARK ONLY — this provider cannot disable a consumer (its adapter has no retire), so mesh_anchor_ncloud KEEPS ITS ACCESS and its data until a person deletes it with `cleanup delete`. Nothing was changed in the backend (novox/hq ADR 0230): the mesh stopped asking for it: the same answer in 5 passes over 0s, from 2026-10-11T03:28:35.940Z
# [provisioner:s3-bucket] mesh_anchor_ncloud: DELETING, asked by someone: unassigned
# Subtest: provisioner hands the adapter what the mesh derived, and still has it at withdrawal
ok 19 - provisioner hands the adapter what the mesh derived, and still has it at withdrawal
---
duration_ms: 126.565599
type: 'test'
...
# Subtest: provisioner stops calling an unreadable secret a race, and says what to look at
ok 20 - provisioner stops calling an unreadable secret a race, and says what to look at
---
duration_ms: 71.978154
type: 'test'
...
# [provisioner:postgres-database] contributions file unreadable (/tmp/prov-mxlVwy/postgres-database.json): ENOENT: no such file or directory, open '/tmp/prov-mxlVwy/postgres-database.json'; nothing applied or removed until it can be read
# [provisioner:postgres-database] contributions file readable again
# [provisioner:postgres-database] contributions file is not JSON (/tmp/prov-mxlVwy/postgres-database.json): SyntaxError: Expected property name or '}' in JSON at position 2 (line 1 column 3); nothing applied or removed until it can be read
# [provisioner:postgres-database] contributions file readable again
# [provisioner:postgres-database] /tmp/prov-mxlVwy/postgres-database.json is for s3-bucket, not postgres-database; nothing applied or removed until it can be read
# [provisioner:postgres-database] contributions file readable again
# [provisioner:postgres-database] /tmp/prov-mxlVwy/postgres-database.json has no given list; nothing applied or removed until it can be read
# [provisioner:postgres-database] contributions file readable again
# [provisioner:postgres-database] RETIREMENT WAITS FOR A PERSON: the mesh no longer asks for 2 of the 2 consumer(s) this provider holds (mesh_anchor_forge, mesh_anchor_mail), more than 3, or more than 50% of the 2 held. Nothing is retired until `retire approve` or `retire reject` (novox/hq ADR 0230)
# [provisioner:postgres-database] retirement of mesh_anchor_forge, mesh_anchor_mail approved by test: both unassigned on purpose
# [provisioner:postgres-database] mesh_anchor_forge: no longer in /tmp/prov-mxlVwy/postgres-database.json; RETIRED, MARK ONLY — this provider cannot disable a consumer (its adapter has no retire), so mesh_anchor_forge KEEPS ITS ACCESS and its data until a person deletes it with `cleanup delete`. Nothing was changed in the backend (novox/hq ADR 0230): approved by test: both unassigned on purpose
# [provisioner:postgres-database] mesh_anchor_mail: no longer in /tmp/prov-mxlVwy/postgres-database.json; RETIRED, MARK ONLY — this provider cannot disable a consumer (its adapter has no retire), so mesh_anchor_mail KEEPS ITS ACCESS and its data until a person deletes it with `cleanup delete`. Nothing was changed in the backend (novox/hq ADR 0230): approved by test: both unassigned on purpose
# Subtest: provisioner removes nothing while its contributions file cannot be used (novox/hq issue 241)
ok 21 - provisioner removes nothing while its contributions file cannot be used (novox/hq issue 241)
---
duration_ms: 1303.040758
type: 'test'
...
# [provisioner:cache] webapp-anchor: the backend no longer holds it; applying again
# Subtest: provisioner applies again what the backend no longer holds, and trusts memory without holds
ok 22 - provisioner applies again what the backend no longer holds, and trusts memory without holds
---
duration_ms: 214.503439
type: 'test'
...
# [provisioner:cache] webapp-anchor: could not check the backend, will ask again: Error: connection refused
# [provisioner:cache] webapp-anchor: could not check the backend, will ask again: Error: connection refused
# [provisioner:cache] webapp-anchor: could not check the backend, will ask again: Error: connection refused
# Subtest: provisioner keeps a consumer applied when the backend cannot be asked
ok 23 - provisioner keeps a consumer applied when the backend cannot be asked
---
duration_ms: 71.134823
type: 'test'
...
# Subtest: provisioner backs off when create does not satisfy holds, and says so
ok 24 - provisioner backs off when create does not satisfy holds, and says so
---
duration_ms: 402.64292
type: 'test'
...
# Subtest: provisioner treats a failed or hung holds as could-not-ask, and never logs the password
ok 25 - provisioner treats a failed or hung holds as could-not-ask, and never logs the password
---
duration_ms: 403.887466
type: 'test'
...
# Subtest: provisioner stops a verify pass at a timeout, and retries a failed re-apply at the next check
ok 26 - provisioner stops a verify pass at a timeout, and retries a failed re-apply at the next check
---
duration_ms: 312.832181
type: 'test'
...
# Subtest: modules can SERVE: a real async tool, loaded and invoked over the broker
ok 27 - modules can SERVE: a real async tool, loaded and invoked over the broker
---
duration_ms: 54.887499
type: 'test'
...
# Subtest: serving refuses one module exposing two tools of the same name
ok 28 - serving refuses one module exposing two tools of the same name
---
duration_ms: 0.487073
type: 'test'
...
# Subtest: events: a module emits, a listener and the audit sink (\#) both receive it, with metadata
ok 29 - events: a module emits, a listener and the audit sink (\#) both receive it, with metadata
---
duration_ms: 1.000276
type: 'test'
...
# Subtest: each registration is given the environment asked for it, and sees no other's (ADR 0192)
ok 30 - each registration is given the environment asked for it, and sees no other's (ADR 0192)
---
duration_ms: 0.364304
type: 'test'
...
# Subtest: a bundle on stdio lists its tools and answers a call, a seat's verb among them
ok 31 - a bundle on stdio lists its tools and answers a call, a seat's verb among them
---
duration_ms: 128.385452
type: 'test'
...
# Subtest: a bundle served as its module lists the seat's verbs as the seat's, whichever registered first (ADR 0193)
ok 32 - a bundle served as its module lists the seat's verbs as the seat's, whichever registered first (ADR 0193)
---
duration_ms: 64.792917
type: 'test'
...
# Subtest: a launched tool's emit is asked of the runtime, and the call answers once the runtime has published (ADR 0193)
ok 33 - a launched tool's emit is asked of the runtime, and the call answers once the runtime has published (ADR 0193)
---
duration_ms: 63.631148
type: 'test'
...
# Subtest: a launched bundle subscribes as it is imported, handles events the runtime hands it, and asks through it (ADR 0198)
ok 34 - a launched bundle subscribes as it is imported, handles events the runtime hands it, and asks through it (ADR 0198)
---
duration_ms: 3224.614788
type: 'test'
...
# Subtest: a subscribe the runtime refused leaves no handler behind, so one event is handled once (novox/hq issue 276)
ok 35 - a subscribe the runtime refused leaves no handler behind, so one event is handled once (novox/hq issue 276)
---
duration_ms: 83.969035
type: 'test'
...
# Subtest: a launched bundle watches its state as it is imported, has the current values before it goes on, and keeps state through the runtime (ADR 0201)
ok 36 - a launched bundle watches its state as it is imported, has the current values before it goes on, and keeps state through the runtime (ADR 0201)
---
duration_ms: 272.89904
type: 'test'
...
# Subtest: topics match as the runtime's do: * one segment, \# and ** any number
ok 37 - topics match as the runtime's do: * one segment, \# and ** any number
---
duration_ms: 3.825034
type: 'test'
...
1..37
# tests 37
# suites 0
# pass 37
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 3921.628509
NOT TESTED HERE: go/ (the Go binding) — the Go toolchain runs it from go/merge-check.sh
NOT TESTED HERE: python/, rust/, c/ — no toolchain of theirs runs a merge check
--- its go/merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-sdk/go 0.128s
ok git.novox.be/novox/mesh-sdk/go/asker 0.003s
ok git.novox.be/novox/mesh-sdk/go/asks 0.003s
ok git.novox.be/novox/mesh-sdk/go/cli 1.032s
? git.novox.be/novox/mesh-sdk/go/example [no test files]
ok git.novox.be/novox/mesh-sdk/go/health 0.003s
**Merge check** at `d9e24e95`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-sdk)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript), go/merge-check.sh (go)
**Delivery plan** — builds mesh-sdk, sent nowhere; no bus step
- tier 0: mesh-sdk
Run by the build seat on g14 as `build-1791689170651169779` (`builds --log build-1791689170651169779`).
```
ok 11 - a waiting set the mesh asks for again settles, and nothing is retired
---
duration_ms: 68.085113
type: 'test'
...
# Subtest: delete refuses an active consumer and deletes only the named retired one
ok 12 - delete refuses an active consumer and deletes only the named retired one
---
duration_ms: 58.920703
type: 'test'
...
# Subtest: an addition acts on the first pass
ok 13 - an addition acts on the first pass
---
duration_ms: 13.475105
type: 'test'
...
# Subtest: what the backend holds at start is retired by the same rules
ok 14 - what the backend holds at start is retired by the same rules
---
duration_ms: 48.781987
type: 'test'
...
# Subtest: the four tools are registered for the module and answer
ok 15 - the four tools are registered for the module and answer
---
duration_ms: 1.925031
type: 'test'
...
# [tools] broken: contributor failed, exposing none: Error: no token
# Subtest: semver orders releases
ok 16 - semver orders releases
---
duration_ms: 0.766137
type: 'test'
...
# Subtest: module tools register and collect, a thrower is skipped not fatal
ok 17 - module tools register and collect, a thrower is skipped not fatal
---
duration_ms: 0.483858
type: 'test'
...
# [provisioner:analytics] webapp-anchor: no longer in /tmp/prov-N5RcGF/analytics.json; RETIRED, MARK ONLY — this provider cannot disable a consumer (its adapter has no retire), so webapp-anchor KEEPS ITS ACCESS and its data until a person deletes it with `cleanup delete`. Nothing was changed in the backend (novox/hq ADR 0230): the mesh stopped asking for it: the same answer in 5 passes over 0s, from 2026-10-11T03:28:35.703Z
# [provisioner:analytics] webapp-anchor: DELETING, asked by someone: gone for good
# Subtest: provisioner creates each consumer with the mesh's login and password; remove waits for a person's delete
ok 18 - provisioner creates each consumer with the mesh's login and password; remove waits for a person's delete
---
duration_ms: 219.395091
type: 'test'
...
# [provisioner:s3-bucket] mesh_anchor_ncloud: no longer in /tmp/prov-derived-KP51J3/store.json; RETIRED, MARK ONLY — this provider cannot disable a consumer (its adapter has no retire), so mesh_anchor_ncloud KEEPS ITS ACCESS and its data until a person deletes it with `cleanup delete`. Nothing was changed in the backend (novox/hq ADR 0230): the mesh stopped asking for it: the same answer in 5 passes over 0s, from 2026-10-11T03:28:35.940Z
# [provisioner:s3-bucket] mesh_anchor_ncloud: DELETING, asked by someone: unassigned
# Subtest: provisioner hands the adapter what the mesh derived, and still has it at withdrawal
ok 19 - provisioner hands the adapter what the mesh derived, and still has it at withdrawal
---
duration_ms: 126.565599
type: 'test'
...
# Subtest: provisioner stops calling an unreadable secret a race, and says what to look at
ok 20 - provisioner stops calling an unreadable secret a race, and says what to look at
---
duration_ms: 71.978154
type: 'test'
...
# [provisioner:postgres-database] contributions file unreadable (/tmp/prov-mxlVwy/postgres-database.json): ENOENT: no such file or directory, open '/tmp/prov-mxlVwy/postgres-database.json'; nothing applied or removed until it can be read
# [provisioner:postgres-database] contributions file readable again
# [provisioner:postgres-database] contributions file is not JSON (/tmp/prov-mxlVwy/postgres-database.json): SyntaxError: Expected property name or '}' in JSON at position 2 (line 1 column 3); nothing applied or removed until it can be read
# [provisioner:postgres-database] contributions file readable again
# [provisioner:postgres-database] /tmp/prov-mxlVwy/postgres-database.json is for s3-bucket, not postgres-database; nothing applied or removed until it can be read
# [provisioner:postgres-database] contributions file readable again
# [provisioner:postgres-database] /tmp/prov-mxlVwy/postgres-database.json has no given list; nothing applied or removed until it can be read
# [provisioner:postgres-database] contributions file readable again
# [provisioner:postgres-database] RETIREMENT WAITS FOR A PERSON: the mesh no longer asks for 2 of the 2 consumer(s) this provider holds (mesh_anchor_forge, mesh_anchor_mail), more than 3, or more than 50% of the 2 held. Nothing is retired until `retire approve` or `retire reject` (novox/hq ADR 0230)
# [provisioner:postgres-database] retirement of mesh_anchor_forge, mesh_anchor_mail approved by test: both unassigned on purpose
# [provisioner:postgres-database] mesh_anchor_forge: no longer in /tmp/prov-mxlVwy/postgres-database.json; RETIRED, MARK ONLY — this provider cannot disable a consumer (its adapter has no retire), so mesh_anchor_forge KEEPS ITS ACCESS and its data until a person deletes it with `cleanup delete`. Nothing was changed in the backend (novox/hq ADR 0230): approved by test: both unassigned on purpose
# [provisioner:postgres-database] mesh_anchor_mail: no longer in /tmp/prov-mxlVwy/postgres-database.json; RETIRED, MARK ONLY — this provider cannot disable a consumer (its adapter has no retire), so mesh_anchor_mail KEEPS ITS ACCESS and its data until a person deletes it with `cleanup delete`. Nothing was changed in the backend (novox/hq ADR 0230): approved by test: both unassigned on purpose
# Subtest: provisioner removes nothing while its contributions file cannot be used (novox/hq issue 241)
ok 21 - provisioner removes nothing while its contributions file cannot be used (novox/hq issue 241)
---
duration_ms: 1303.040758
type: 'test'
...
# [provisioner:cache] webapp-anchor: the backend no longer holds it; applying again
# Subtest: provisioner applies again what the backend no longer holds, and trusts memory without holds
ok 22 - provisioner applies again what the backend no longer holds, and trusts memory without holds
---
duration_ms: 214.503439
type: 'test'
...
# [provisioner:cache] webapp-anchor: could not check the backend, will ask again: Error: connection refused
# [provisioner:cache] webapp-anchor: could not check the backend, will ask again: Error: connection refused
# [provisioner:cache] webapp-anchor: could not check the backend, will ask again: Error: connection refused
# Subtest: provisioner keeps a consumer applied when the backend cannot be asked
ok 23 - provisioner keeps a consumer applied when the backend cannot be asked
---
duration_ms: 71.134823
type: 'test'
...
# Subtest: provisioner backs off when create does not satisfy holds, and says so
ok 24 - provisioner backs off when create does not satisfy holds, and says so
---
duration_ms: 402.64292
type: 'test'
...
# Subtest: provisioner treats a failed or hung holds as could-not-ask, and never logs the password
ok 25 - provisioner treats a failed or hung holds as could-not-ask, and never logs the password
---
duration_ms: 403.887466
type: 'test'
...
# Subtest: provisioner stops a verify pass at a timeout, and retries a failed re-apply at the next check
ok 26 - provisioner stops a verify pass at a timeout, and retries a failed re-apply at the next check
---
duration_ms: 312.832181
type: 'test'
...
# Subtest: modules can SERVE: a real async tool, loaded and invoked over the broker
ok 27 - modules can SERVE: a real async tool, loaded and invoked over the broker
---
duration_ms: 54.887499
type: 'test'
...
# Subtest: serving refuses one module exposing two tools of the same name
ok 28 - serving refuses one module exposing two tools of the same name
---
duration_ms: 0.487073
type: 'test'
...
# Subtest: events: a module emits, a listener and the audit sink (\#) both receive it, with metadata
ok 29 - events: a module emits, a listener and the audit sink (\#) both receive it, with metadata
---
duration_ms: 1.000276
type: 'test'
...
# Subtest: each registration is given the environment asked for it, and sees no other's (ADR 0192)
ok 30 - each registration is given the environment asked for it, and sees no other's (ADR 0192)
---
duration_ms: 0.364304
type: 'test'
...
# Subtest: a bundle on stdio lists its tools and answers a call, a seat's verb among them
ok 31 - a bundle on stdio lists its tools and answers a call, a seat's verb among them
---
duration_ms: 128.385452
type: 'test'
...
# Subtest: a bundle served as its module lists the seat's verbs as the seat's, whichever registered first (ADR 0193)
ok 32 - a bundle served as its module lists the seat's verbs as the seat's, whichever registered first (ADR 0193)
---
duration_ms: 64.792917
type: 'test'
...
# Subtest: a launched tool's emit is asked of the runtime, and the call answers once the runtime has published (ADR 0193)
ok 33 - a launched tool's emit is asked of the runtime, and the call answers once the runtime has published (ADR 0193)
---
duration_ms: 63.631148
type: 'test'
...
# Subtest: a launched bundle subscribes as it is imported, handles events the runtime hands it, and asks through it (ADR 0198)
ok 34 - a launched bundle subscribes as it is imported, handles events the runtime hands it, and asks through it (ADR 0198)
---
duration_ms: 3224.614788
type: 'test'
...
# Subtest: a subscribe the runtime refused leaves no handler behind, so one event is handled once (novox/hq issue 276)
ok 35 - a subscribe the runtime refused leaves no handler behind, so one event is handled once (novox/hq issue 276)
---
duration_ms: 83.969035
type: 'test'
...
# Subtest: a launched bundle watches its state as it is imported, has the current values before it goes on, and keeps state through the runtime (ADR 0201)
ok 36 - a launched bundle watches its state as it is imported, has the current values before it goes on, and keeps state through the runtime (ADR 0201)
---
duration_ms: 272.89904
type: 'test'
...
# Subtest: topics match as the runtime's do: * one segment, \# and ** any number
ok 37 - topics match as the runtime's do: * one segment, \# and ** any number
---
duration_ms: 3.825034
type: 'test'
...
1..37
# tests 37
# suites 0
# pass 37
# fail 0
# cancelled 0
# skipped 0
# todo 0
# duration_ms 3921.628509
NOT TESTED HERE: go/ (the Go binding) — the Go toolchain runs it from go/merge-check.sh
NOT TESTED HERE: python/, rust/, c/ — no toolchain of theirs runs a merge check
--- its go/merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-sdk/go 0.128s
ok git.novox.be/novox/mesh-sdk/go/asker 0.003s
ok git.novox.be/novox/mesh-sdk/go/asks 0.003s
ok git.novox.be/novox/mesh-sdk/go/cli 1.032s
? git.novox.be/novox/mesh-sdk/go/example [no test files]
ok git.novox.be/novox/mesh-sdk/go/health 0.003s
```
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.
Fixes the SDK part of hq issue 365 (the issue tracker cannot prove who opened or changed an issue): a module is never told who called its tool.
What changes. The runtime names the caller it took from the subject a call arrived on in the
tools/call's_meta(mesh/caller).stdio.CallerOf(args)inside a tool answers that bus user;stdio.Unproven("unproven") when the runtime named none (an older runtime, or a call on the subject that names no caller), or named something that is not a bus user's name. Never read fromarguments: acalleror_metainside the arguments names nobody.Backward compatible.
Tool.Run(args)keeps its signature; a tool that never callsCallerOfis unchanged. The caller is held per call by the identity of the arguments map the tool is handed, so a tool reads it with the map it already has (one line for mesh-knowledge'scallerOf). The TypeScript, Python, Rust and C bindings ignore_metaand are untouched.Tests (fail first: they do not compile on main). go/caller_test.go: the caller the runtime named reaches the tool; a caller in the arguments is never the caller; no
_meta, an empty or malformed one, is Unproven; arguments of no call have no caller.sh merge-check.shpasses (TypeScript suite and go/).Rolls first. Nothing calls
CallerOfuntil mesh-catalog's mesh-issues pins it (pinned at this branch's headd9e24e9until merged; re-pin to the merge commit after).Companion pull requests, same branch name: mesh-tools (runtime: caller-named subjects, caller handed to the module), mesh-controller (grants), mesh-catalog (mesh-issues reads the caller). Retirement of the old subjects: hq issue 464.
Delivery
novox/mesh-sdk@d9e24e95a242— delivered since 2026-10-11T10:11:55ZDelivery plan — builds mesh-sdk, sent nowhere; no bus step
Group
fix/365-a-tool-call-names-its-caller, in order: novox/mesh-controller@ebca7816bf → novox/mesh-catalog@61f81d4454 → novox/mesh-sdk@d9e24e95a2 → novox/mesh-tools@ab0f888d67Machines
Transitions
plans goThe commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
d9e24e95mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-sdk)mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript), go/merge-check.sh (go)Delivery plan — builds mesh-sdk, sent nowhere; no bus step
Run by the build seat on g14 as
build-1791689170651169779(builds --log build-1791689170651169779).Companions for hq issue 365: mesh-controller#224 (grants), mesh-tools#27 (runtime), mesh-catalog#207 (mesh-issues). Merge order: mesh-sdk#20, mesh-controller#224, mesh-tools#27, mesh-catalog#207.