From 95b899a666b9a605c86ce15b7e33bd1ad7c424d3 Mon Sep 17 00:00:00 2001 From: Lily Shen <115414357+lilyshen0722@users.noreply.github.com> Date: Sun, 25 Oct 2026 22:03:00 -0700 Subject: [PATCH] docs(claude-md): point Agent Runtime rules at fleet-efficiency.md One bullet at the top of Agent Runtime Quick Rules so every seat and session that loads CLAUDE.md reaches the 10-25 fleet rules (#2770): switch rather than park, refusals never switch harness, tiered routing, NO_REPLY over narration, the 5-agent pod cap, one prod deploy a day, gates by risk tier. Ratified by Cofounder under Sam's D77 delegation (ledger D84/D85). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01P5T53syWkei5c1npy2zrBB --- CLAUDE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 2978e242aa..748e56d6bf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -493,6 +493,8 @@ browser_evaluate: () => { localStorage.setItem('token', 'eyJ...'); location.relo These are prescriptive rules not derivable from reading the code: +- **How seats spend turns, models and quota** (switch rather than park, a refusal never switches harness, routed rows by tier, `NO_REPLY` over narration, the 5-agent pod cap, one prod deploy a day, gates by risk tier): [`docs/agents/fleet-efficiency.md`](docs/agents/fleet-efficiency.md). + - **NEVER set `heartbeat.global` (or `fixedPod`) in `moltbot.json`.** openclaw v2026.3.7's `HeartbeatSchema` is `.strict()` and has no `global` key — emitting it fails config validation and crash-loops the gateway (`Unrecognized key: "global"`), taking the whole fleet offline (2026-06-28 incident, PR #502). The heartbeat runner already fires **once per agent** (`for (const agent of state.agents.values())`); there is no per-pod fan-out to suppress. A prior rule claimed `global:true` was required to avoid per-pod firing — that was true of an older openclaw and is now false + dangerous. `normalizeHeartbeat` in both provisioners must emit only `{every, prompt, target, session}`; the provisioner has a regression test asserting `global`/`fixedPod` never appear. **This rule is scoped to `moltbot.json` and says nothing about `AgentInstallation.config.heartbeat.global`, which is a different field on a different surface with the opposite meaning** — read only by `schedulerService.ts:848` (the entire backend footprint), where `global: true` *dedupes* an agent's per-pod schedules into one. Without it the backend enqueues one heartbeat **per (agent, instance, pod)** — so "there is no per-pod fan-out to suppress" is true of the gateway runner and false of the backend scheduler. Setting the Mongo field is supported; emitting the `moltbot.json` key is the thing that crash-loops the fleet. See AX audit entry 22. - **`NO_REPLY` silences a reply that IS the sentinel, or that OPENS with it** — **position is the discriminator.** Total-match was the whole rule until TASK-067 (Sam, ratified 2026-08-26): the measured failure mode is AX-43, where a seat wrote `NO_REPLY.` followed by its private reasoning, believing the leading token silenced the turn — the kernel stripped the token and published the reasoning, 11 times in one day. A **leading** bare sentinel now suppresses the entire reply. A bare sentinel anywhere ELSE keeps PR #785's behaviour: treated as producer leakage, stripped whitespace-preserving, and the rest POSTS — because there it sits inside a reply the agent meant to send, and swallowing a genuine reply is the worse error. A sentinel inside backticks or a code fence is a deliberate mention and survives in every position, leading included — **backtick a sentinel to mention it.** Scope is agent-authored content only; the human path stays verbatim by design. Any new sentinel inherits all three contracts at birth (total-match suppression + leading-suppression + bare-stripped-elsewhere/backtick-preserved) plus a test for each. `AgentMessageService.sanitizeAgentContent`; tests in `backend/__tests__/unit/services/agentMessageService.chatNoise.test.js`.