G C-1 (TS): a bundle reads its tool runner's capability words once and names a word not stated

mesh/capabilities answered {words}, an unknown call read as none, the node from MESH_NODE; the finding writer's bundle
transport requires finding-calls; a runtime refusal keeps its code.

Builds: design 47 G §576, §622, §488
Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 21:47:03 +01:00
parent 58bbc26219
commit 36974cddf9
5 changed files with 77 additions and 5 deletions
+24
View File
@@ -981,3 +981,27 @@ test("the finding writer owns its kinds, keeps a views reader's findings in its
await vw.delete(vf);
assert.equal(store.has("module.m=2eo=2es.view-waits"), false);
});
test("a bundle reads its tool runner's capability words once, reads an unknown call as none and names a word not stated (design 47 G §576)", async () => {
const { useRuntime, requireCapability } = await import("../dist/runtime/index.js");
const was = process.env.MESH_NODE;
process.env.MESH_NODE = "ace";
let asked = 0;
useRuntime(async (method) => {
asked++;
assert.equal(method, "mesh/capabilities");
return { words: ["finding-calls"] };
});
await requireCapability("finding-calls");
await assert.rejects(requireCapability("put-sessions"), /"put-sessions".*ace|ace.*"put-sessions"/);
assert.equal(asked, 1);
useRuntime(async () => { throw Object.assign(new Error("no mesh/capabilities"), { code: -32601 }); });
await assert.rejects(requireCapability("finding-calls"), /"finding-calls"/);
let tries = 0;
useRuntime(async () => { if (++tries === 1) throw new Error("pipe closed"); return { words: ["finding-calls"] }; });
await assert.rejects(requireCapability("finding-calls"), /pipe closed/);
await requireCapability("finding-calls"); // a failed read is asked again
useRuntime(undefined);
if (was === undefined) delete process.env.MESH_NODE;
else process.env.MESH_NODE = was;
});
+4
View File
@@ -353,6 +353,9 @@ test("a bundle's finding writer publishes with ack and listens with deliver new
};
const send = (m: unknown) => child.stdin.write(JSON.stringify(m) + "\n");
try {
// the capability words are read once, before the first call that needs one (design 47 G §576)
const caps = await until((m) => m.method === "mesh/capabilities");
send({ jsonrpc: "2.0", id: caps.id, result: { words: ["finding-calls"] } });
const sub = await until((m) => m.method === "mesh/subscribe");
assert.deepEqual(sub.params, { pattern: "mesh-conditions.findings-asked", deliver: "new" });
send({ jsonrpc: "2.0", id: sub.id, result: {} });
@@ -366,6 +369,7 @@ test("a bundle's finding writer publishes with ack and listens with deliver new
// The runtime answers an unacknowledged publish with {error}: the writer's publish fails, so it sends again.
send({ jsonrpc: "2.0", id: pub.id, result: { error: "no stream" } });
const answered = await until((m) => m.id === 2);
assert.equal(seen.filter((m) => m.method === "mesh/capabilities").length, 1, "the words are asked once");
assert.deepEqual(JSON.parse(answered.result.content[0].text), { said: false, why: "the bus did not acknowledge finding-written: no stream" });
} finally {
child.kill();