From 5233283f3aca4437a8a5ff8a1c5e378a5b1c1862 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 15 Jul 2026 01:41:41 +0100 Subject: [PATCH] Publish swarm controls as bound Eve state --- scripts/render-voidbot-swarm-dashboard.mjs | 17 +++++++++++--- scripts/serve-voidbot-swarm-cultmesh.cjs | 26 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/scripts/render-voidbot-swarm-dashboard.mjs b/scripts/render-voidbot-swarm-dashboard.mjs index a26dbce..3d2cb88 100644 --- a/scripts/render-voidbot-swarm-dashboard.mjs +++ b/scripts/render-voidbot-swarm-dashboard.mjs @@ -978,8 +978,11 @@ function timestampForFile(date) { } function loadCultPackages() { + const cultLibRoot = process.env.VOIDBOT_CULTLIB_ROOT + ? resolve(process.env.VOIDBOT_CULTLIB_ROOT) + : resolve(repoRoot, "..", "CultLib-codex-cultmesh-reliability"); const candidates = [ - resolve(repoRoot, "..", "CultLib", "packages", "cultmesh-ts", "package.json"), + resolve(cultLibRoot, "packages", "cultmesh-ts", "package.json"), resolve(repoRoot, "..", "CultMeshTS", "package.json"), ]; for (const packageJson of candidates) { @@ -1379,10 +1382,17 @@ function buildEveProviderState(snapshot) { command: "swarm.set_heat", transport: "cultmesh-binding", providerId, - value: summary.globalHeat ?? 1, min: 0.05, max: 2, step: 0.05, + stateBindings: [{ + targetProp: "value", + pointerId: "globalHeat", + sourceId: "voidbot.swarm_control_state:voidbot-swarm", + schemaId: "voidbot.swarm_control_state.v1", + routeKind: "cultmesh-rudp", + routeDescription: swarmCultMeshRudpEndpoint, + }], }), ]), ]), @@ -1713,13 +1723,14 @@ function clampPercent(value) { } function eveNode(id, kind, props = {}, children = []) { - const { layout, style, ...nodeProps } = props ?? {}; + const { layout, style, stateBindings, ...nodeProps } = props ?? {}; return { id, kind, props: nodeProps, ...(layout && typeof layout === "object" ? { layout } : {}), ...(style && typeof style === "object" ? { style } : {}), + ...(Array.isArray(stateBindings) && stateBindings.length > 0 ? { stateBindings } : {}), children, }; } diff --git a/scripts/serve-voidbot-swarm-cultmesh.cjs b/scripts/serve-voidbot-swarm-cultmesh.cjs index 2e8ba80..3814abd 100644 --- a/scripts/serve-voidbot-swarm-cultmesh.cjs +++ b/scripts/serve-voidbot-swarm-cultmesh.cjs @@ -40,6 +40,7 @@ main().catch((error) => { }); async function main() { + await publishCurrentControlState(); server = CultMesh.createRudpDocumentServer("voidbot-swarm-cultmesh", connectionId, { bindHost: bind.host, bindPort: bind.port, @@ -83,6 +84,13 @@ async function main() { process.once("SIGTERM", shutdown); } +async function publishCurrentControlState() { + if (!fs.existsSync(controlStorePath)) return; + const controlNode = await CultMesh.createNode(controlStorePath, { documents: [documents.swarmControl] }); + const control = controlNode.get(documents.swarmControl, "voidbot-swarm"); + if (control) await projectAcceptedHeat(control); +} + async function applySwarmCommand(document) { if (document.schemaId !== "gamecult.eve.command.v1") return; const command = document.payload; @@ -101,6 +109,7 @@ async function applySwarmCommand(document) { }; await node.put(documents.swarmControl, "voidbot-swarm", control); await node.flush?.(true); + await projectAcceptedHeat(control); console.log(`Applied swarm heat ${control.globalHeat} from ${control.commandId}`); return { binding: bindings.commandReceipt, @@ -118,7 +127,7 @@ async function applySwarmCommand(document) { sourceVersion: Date.parse(control.updatedAt), issuedAtUtc: control.updatedAt, message: `Swarm heat applied at ${control.globalHeat}.`, - diagnostics: [{ binding: "voidbot.swarm.globalHeat", value: control.globalHeat }], + diagnostics: [{ code: "state-published", pointerId: "summary.globalHeat" }], }, sourceRuntimeId: "voidbot-swarm-cultmesh", sourceRole: "swarm-control-owner", @@ -126,6 +135,12 @@ async function applySwarmCommand(document) { }; } +async function projectAcceptedHeat(control) { + const node = await CultMesh.createNode(storePath, { documents: documentDefinitions }); + await node.put(documents.swarmControl, "voidbot-swarm", control); + await node.flush?.(true); +} + async function announceToOdin() { const node = await CultMesh.createNode(storePath, { documents: documentDefinitions, @@ -268,11 +283,14 @@ function defineDocuments(defineDocumentType) { } function loadCultRuntime() { - const packageJson = path.resolve(repoRoot, "..", "CultLib", "packages", "cultmesh-ts", "package.json"); + const cultLibRoot = process.env.VOIDBOT_CULTLIB_ROOT + ? path.resolve(process.env.VOIDBOT_CULTLIB_ROOT) + : path.resolve(repoRoot, "..", "CultLib-codex-cultmesh-reliability"); + const packageJson = path.resolve(cultLibRoot, "packages", "cultmesh-ts", "package.json"); const requireCult = createRequire(packageJson); const { CultMesh } = requireCult("./dist/index.js"); - const { CultNetDocumentRegistry, defineCultNetDocumentBinding } = createRequire(path.resolve(repoRoot, "..", "CultLib", "packages", "cultnet-ts", "package.json"))("./dist/index.js"); - const { defineDocumentType } = createRequire(path.resolve(repoRoot, "..", "CultLib", "packages", "cultcache-ts", "package.json"))("./dist/index.js"); + const { CultNetDocumentRegistry, defineCultNetDocumentBinding } = createRequire(path.resolve(cultLibRoot, "packages", "cultnet-ts", "package.json"))("./dist/index.js"); + const { defineDocumentType } = createRequire(path.resolve(cultLibRoot, "packages", "cultcache-ts", "package.json"))("./dist/index.js"); return { CultMesh, CultNetDocumentRegistry, defineCultNetDocumentBinding, defineDocumentType }; }