" + renderControls(snapshot, participants) + "" + avatarHtml(agent) + "
Selected Face
" + esc(agent.displayName) + "
" + esc(agent.identityId) + " / " + esc(agent.repoName) + "
" +
- statBar("Turn", minutes(agent.nextTurnInMinutes), turnPercent(agent.nextTurnInMinutes), "cool") +
+ statBar("Turn", minutes(agent.nextTurnInMinutes, agent.restState), turnPercent(agent.nextTurnInMinutes), agent.restState?.isNapping === true ? "warm" : "cool") +
statBar("Memory", number(memoryCount), Math.min(100, memoryCount * 7), "cool") +
statBar("Pressure", number(counts.pressures || 0), Math.min(100, (counts.pressures || 0) * 14), (counts.pressures || 0) > 4 ? "hot" : "") +
statBar("Heat", number(agent.heat), Math.min(100, (agent.heat || 0) * 34), (agent.heat || 0) > 1.5 ? "hot" : "") +
diff --git a/scripts/run-repo-face-heartbeats.ts b/scripts/run-repo-face-heartbeats.ts
index cca28f9..41789db 100644
--- a/scripts/run-repo-face-heartbeats.ts
+++ b/scripts/run-repo-face-heartbeats.ts
@@ -758,7 +758,24 @@ function projectSleepCycleForOperatorAbsence(
now: Date,
): VoidScheduledRuntime["sleepCycle"] {
if (idleCooling?.napModeActive !== true) {
- return sleepCycle;
+ const activeDreamThemes = sleepCycle.activeDreamThemes.filter((theme) => theme !== "operator-absence-dreaming");
+ if (sleepCycle.isNapping !== true || !sleepCycle.activeDreamThemes.includes("operator-absence-dreaming")) {
+ return activeDreamThemes.length === sleepCycle.activeDreamThemes.length
+ ? sleepCycle
+ : {
+ ...sleepCycle,
+ activeDreamThemes,
+ };
+ }
+
+ return {
+ ...sleepCycle,
+ isNapping: false,
+ currentNapStartedAt: undefined,
+ currentNapEndsAt: undefined,
+ nextNapStartsAt: new Date(now.getTime() + 180 * 60_000).toISOString(),
+ activeDreamThemes,
+ };
}
const nowMs = now.getTime();
diff --git a/state/evidence.jsonl b/state/evidence.jsonl
index a9501d8..479cf53 100644
--- a/state/evidence.jsonl
+++ b/state/evidence.jsonl
@@ -344,3 +344,4 @@
{"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."}
+{"ts":"2026-05-25T21:28:29Z","type":"implementation","status":"ok","note":"Fixed repo Face CTB wake/ready split: operator-absence naps now end when operator absence ends, and the swarm dashboard includes Face rest state so napping Faces are not shown as ready. Verified build and a forced repo-face heartbeat queued Fensalir, Norn, and Nibu."}