From 579a8fd026bff0ff7faa0d75fa876b19a85a0b4e Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 25 May 2026 19:53:44 +0100 Subject: [PATCH] Slow repo Face CTB cadence range --- scripts/render-voidbot-swarm-dashboard.mjs | 10 +++++----- scripts/run-repo-face-heartbeats.ts | 10 +++++----- state/evidence.jsonl | 1 + 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/scripts/render-voidbot-swarm-dashboard.mjs b/scripts/render-voidbot-swarm-dashboard.mjs index 1b1608f..c79359f 100644 --- a/scripts/render-voidbot-swarm-dashboard.mjs +++ b/scripts/render-voidbot-swarm-dashboard.mjs @@ -1325,7 +1325,7 @@ function renderHtml(snapshot) { const controls = snapshot.controls || {}; const latest = (controls.manualTurnRequests || [])[0]; return "

Controls

" + - "
Heartbeat cadence
x" + esc(number(controls.cadenceMultiplier || 1)) + "
" + + "
Heartbeat cadence
x" + esc(number(controls.cadenceMultiplier || 1)) + "
" + "
Manual next turn
" + "
Latest request: " + esc(latest?.identityId || "none") + " " + esc(latest?.status || "") + "
" + "
"; @@ -1603,7 +1603,7 @@ function renderHtml(snapshot) { const forceButton = document.getElementById("force-turn"); if (forceSelect && selectedIdentity) forceSelect.value = selectedIdentity; if (cadenceInput && cadenceValue) { - cadenceInput.addEventListener("input", () => cadenceValue.textContent = "x" + Number(cadenceInput.value).toLocaleString(undefined, { maximumFractionDigits: 1 })); + cadenceInput.addEventListener("input", () => cadenceValue.textContent = "x" + Number(cadenceInput.value).toLocaleString(undefined, { maximumFractionDigits: 2 })); } if (cadenceApply && cadenceInput) { cadenceApply.addEventListener("click", async () => { @@ -1771,8 +1771,8 @@ async function handleControlUpdate(request, response) { } const body = await readRequestJson(request); const multiplier = Number(body.cadenceMultiplier); - if (!Number.isFinite(multiplier) || multiplier < 0.1 || multiplier > 12) { - writeJsonResponse(response, 400, { ok: false, error: "cadenceMultiplier must be between 0.1 and 12." }); + if (!Number.isFinite(multiplier) || multiplier < 0.01 || multiplier > 12) { + writeJsonResponse(response, 400, { ok: false, error: "cadenceMultiplier must be between 0.01 and 12." }); return; } const state = await readMutableHeartbeatState(); @@ -1827,7 +1827,7 @@ async function writeMutableHeartbeatState(state) { function normalizeDashboardControls(value) { const controls = value && typeof value === "object" ? value : {}; return { - cadenceMultiplier: Math.min(12, Math.max(0.1, Number(controls.cadenceMultiplier) || 1)), + cadenceMultiplier: Math.min(12, Math.max(0.01, Number(controls.cadenceMultiplier) || 1)), manualTurnRequests: Array.isArray(controls.manualTurnRequests) ? controls.manualTurnRequests : [], updatedAt: typeof controls.updatedAt === "string" ? controls.updatedAt : undefined, }; diff --git a/scripts/run-repo-face-heartbeats.ts b/scripts/run-repo-face-heartbeats.ts index 3f88e49..cca28f9 100644 --- a/scripts/run-repo-face-heartbeats.ts +++ b/scripts/run-repo-face-heartbeats.ts @@ -272,7 +272,7 @@ async function main(): Promise { } state.baseRecoveryMinutes = config.repoFaceHeartbeats.baseRecoveryMinutes; - const cadenceMultiplier = clamp(state.controls.cadenceMultiplier, 0.1, 12); + const cadenceMultiplier = clamp(state.controls.cadenceMultiplier, 0.01, 12); const effectiveGlobalHeat = config.repoFaceHeartbeats.globalHeat * cadenceMultiplier; state.globalHeat = effectiveGlobalHeat; const completedThisTick = new Set(); @@ -1502,7 +1502,7 @@ function reconcileParticipants( const groups = initiativeGroupsFor(spec); const heat = heatFor(spec, groups, globalHeat, heatOverrides); const urgency = urgencyFor(pressureByIdentity.get(spec.id)); - const effectiveSpeed = clamp(speed * heat * urgency, 0.1, 12); + const effectiveSpeed = clamp(speed * heat * urgency, 0.01, 12); const defaultNextTurnAt = Number.isFinite(current?.nextTurnAt) ? current.nextTurnAt : initiativeClock + ((baseRecoveryMinutes / count) * index); @@ -1596,7 +1596,7 @@ function pullNextTurnTowardUrgency( return nextTurnAt; } - const maxWait = Math.max(0.75, baseRecoveryMinutes / Math.max(effectiveSpeed, 0.1)); + const maxWait = Math.max(0.75, baseRecoveryMinutes / Math.max(effectiveSpeed, 0.01)); return Math.min(nextTurnAt, round3(initiativeClock + maxWait)); } @@ -5006,7 +5006,7 @@ function projectCharacterDescription(description: string | undefined): string | function recoveryFor(participant: FaceHeartbeatParticipant): number { const loadPenalty = 1 + participant.currentLoad * 0.75; - return (participant.baseRecoveryMinutes * loadPenalty) / Math.max(participant.effectiveSpeed, 0.1); + return (participant.baseRecoveryMinutes * loadPenalty) / Math.max(participant.effectiveSpeed, 0.01); } async function readHeartbeatState(path: string): Promise { @@ -5157,7 +5157,7 @@ function normalizeHeartbeatControls(value: unknown): FaceHeartbeatControls { : []; return { - cadenceMultiplier: Number.isFinite(cadenceMultiplier) ? clamp(cadenceMultiplier, 0.1, 12) : 1, + cadenceMultiplier: Number.isFinite(cadenceMultiplier) ? clamp(cadenceMultiplier, 0.01, 12) : 1, manualTurnRequests: manualTurnRequests.slice(-20), updatedAt: typeof record.updatedAt === "string" ? record.updatedAt : undefined, }; diff --git a/state/evidence.jsonl b/state/evidence.jsonl index d34c75a..a9501d8 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -343,3 +343,4 @@ {"ts":"2026-05-25T07:40:27Z","type":"implementation","status":"ok","note":"Created the Discord role for the new Norn Face and updated the private repo identity registry with roleId 1508373969076748361; role-addressed mentions can now target Norn once the running bot reloads the registry."} {"ts":"2026-05-25T12:49:01Z","type":"implementation","status":"ok","note":"Renamed the local EpiphanyGraph repo to Norn and updated the Norn Face registry/state to use E:/Projects/Norn and repo:Norn. The Norn repo builds with dotnet and the Norn viewer typecheck/build passes."} {"ts":"2026-05-25T17:36:36Z","type":"implementation","status":"ok","note":"Revived the local VoidBot stack and repo Face swarm: npm run stack:start restored runtime-stack.json to ready with bot PID 24512 and worker PID 30640, npm run state:check passed live-service gates with only a backup warning, state/agent-swarm-paused.json is now paused=false, repo Face heartbeats and mood drift ran ok, first unpaused Void moderation turn completed ok, and Norn reconciled into the active CTB participant roster."} +{"ts":"2026-05-25T18:53:32Z","type":"implementation","status":"ok","note":"Slowed repo Face CTB cadence by 10x in the live control surface: cadenceMultiplier is now 0.04, scheduler/dashboard/API minimum is 0.01, and effective-speed/recovery floors now preserve sub-0.1 cadence instead of silently flattening it. Typecheck and a real heartbeat pass succeeded without queuing an unprompted Face turn."}