/cron-payload-discipline
Discipline for cron/loop/monitor payloads. Triggers: cron, /loop, recurring tick, merge queue, no-progress.
$ golems-cli skills install cron-payload-disciplineUpdated 2 weeks ago
Cron payloads must query reality first. If the prompt already claims the state, the loop is rotten before it runs.
When to Use
- Writing a new
/loop, cron tick, or recurring monitor payload - Reviewing a payload that mentions PR state, agent state, collab state, or filesystem freshness
- Debugging repeated identical tick frames or "SILENT" loops that keep restating stale facts
- Any payload that is long enough to hide stale assumptions inside boilerplate
- Supervising merge queues, worker queues, collab tails, file-producing tasks, or quiet cmux workers
- Deciding whether a repeated parsed-only surface is genuinely idle, frozen, or still active
The Shared Primitive
Anthropic-native ! preprocessing is the foundation here:
"The
!syntax runs shell commands before the skill content is sent to Claude."
That means the payload should render live facts before Claude reasons about them. Claude should see current data, not a baked claim like BLOCKED REVIEW_REQUIRED.
The Rule
Never hardcode state strings inside a cron payload when the state can be queried live.
Forbidden examples:
PR #123 is BLOCKED REVIEW_REQUIRED3 PRs are waiting at merge gatesurface:7 is idleno collab changes since last tick
Required replacement pattern:
Tick frame:
- now: $(date -Iseconds)
- cycle: <N>
- last-action-timestamp: <ISO-8601>
Step 1: run a live query with `!`
!gh pr view <repo> <pr> --json mergeable,mergeStateStatus,reviewDecision
!list_surfaces
!find <dir> -newer <last-action-timestamp>
!brain_search "<topic>"
Step 2: reason from the rendered output, not from the template text
Step 3: dispatch, verify-and-decrement, or escalate-park based on the live resultFor monitor loops, extend the frame:
- last-genuine-dispatch-time: <ISO-8601>
- consecutive-no-change-ticks: <N>
- consecutive-no-push-ticks: <N>
- park-threshold: <N>Full SKILL.md source — includes LLM directives, anti-patterns, and technical instructions stripped from the Overview tab.
Cron payloads must query reality first. If the prompt already claims the state, the loop is rotten before it runs.
When to Use
- Writing a new
/loop, cron tick, or recurring monitor payload - Reviewing a payload that mentions PR state, agent state, collab state, or filesystem freshness
- Debugging repeated identical tick frames or "SILENT" loops that keep restating stale facts
- Any payload that is long enough to hide stale assumptions inside boilerplate
- Supervising merge queues, worker queues, collab tails, file-producing tasks, or quiet cmux workers
- Deciding whether a repeated parsed-only surface is genuinely idle, frozen, or still active
The Shared Primitive
Anthropic-native ! preprocessing is the foundation here:
"The
!syntax runs shell commands before the skill content is sent to Claude."
That means the payload should render live facts before Claude reasons about them. Claude should see current data, not a baked claim like BLOCKED REVIEW_REQUIRED.
The Rule
Never hardcode state strings inside a cron payload when the state can be queried live.
Forbidden examples:
PR #123 is BLOCKED REVIEW_REQUIRED3 PRs are waiting at merge gatesurface:7 is idleno collab changes since last tick
Required replacement pattern:
Tick frame:
- now: $(date -Iseconds)
- cycle: <N>
- last-action-timestamp: <ISO-8601>
Step 1: run a live query with `!`
!gh pr view <repo> <pr> --json mergeable,mergeStateStatus,reviewDecision
!list_surfaces
!find <dir> -newer <last-action-timestamp>
!brain_search "<topic>"
Step 2: reason from the rendered output, not from the template text
Step 3: dispatch, verify-and-decrement, or escalate-park based on the live resultFor monitor loops, extend the frame:
- last-genuine-dispatch-time: <ISO-8601>
- consecutive-no-change-ticks: <N>
- consecutive-no-push-ticks: <N>
- park-threshold: <N>Hard Rules
1. Live Query First
Step 1 in every cron payload must execute a live query.
Acceptable first-step queries:
!gh pr view!gh pr list!list_surfaces!read_screen!find <dir> -newer <timestamp>!brain_search
If step 1 is explanation, status narration, or a pre-baked claim, the payload is invalid.
2. No Hardcoded State Claims
Do not embed review state, merge state, agent state, or queue state as facts in the payload body.
Allowed:
- "If the live PR query shows
REVIEW_REQUIRED, dispatch reviewer follow-up."
Not allowed:
- "PR #189 is
REVIEW_REQUIRED, keep waiting."
2a. Review Dispatch Pins PR Head SHA
Any review-dispatch payload must identify the PR by immutable head, not only by branch name. Branch names can be renamed or force-pushed mid-review; PR #453's review prompt named a branch that had already drifted.
Required payload data:
- PR number and URL
headRefNameheadRefOid- base branch
Allowed target forms:
headRefOid=<sha>fromgh pr view <N> --json headRefName,headRefOid,baseRefName,urlrefs/pull/<N>/headplus a cross-check thatgit ls-remote origin refs/pull/<N>/headmatchesheadRefOid
Forbidden:
- "Review branch
<name>" as the only target - Prompts that let the reviewer resolve a branch name without checking the PR's current head SHA first
3. Frame Discipline Is Mandatory
Every recurring payload must include:
$(date)or equivalent rendered current timestamp- a cycle counter
- a
last-action-timestamp
Without these, identical frames are hard to distinguish from a stuck loop.
4. The Decision Tree Must Consume Live Data
The payload's branching logic must reference the output of the live query, not a static narrative written above it.
Good:
- "If
!gh pr viewreports mergeable=MERGEABLE, dispatch merge."
Bad:
- "Since this PR is blocked, keep monitoring."
5. Drive-To-Completion Outcome
Every recurring monitor tick must end in exactly one primary outcome:
| Outcome | Use when | Required side-effect |
|---|---|---|
dispatch | Live data shows a specific unblock or next action | Send one targeted instruction and update last-genuine-dispatch-time |
verify-and-decrement | Progress is claimed or implied but not proven | Read the source of truth; decrement/reset only if the side-effect exists |
escalate-park | Repeated ticks show no material queue delta | Escalate once with the exact blocker, then park/kill the loop branch |
Passive output like "I'm monitoring", "still watching", or repeated SILENT
with no decision context is invalid.
6. Counter Resets Need Verified Side-Effects
Reset consecutive-no-change-ticks and consecutive-no-push-ticks only after a
real queue decrement:
- PR merged
- assigned agent task completed
- expected file or artifact was actually written
No-op pings, identical telemetry, timestamp changes, and worker replies like "still looking" are not progress.
7. Freeze Detection Uses Rotating Full Reads
Repeated parsed_only output, unchanged token counts, or quiet panes are hints,
not verdicts. When several surfaces look frozen:
- Track
parsed_only_signature,consecutive_matching_parsed_ticks,last_full_read_time,last_full_read_summary,last_known_long_running_op, andidle_candidate_since. - Escalate exactly one worst offender to a full read per suspicious tick.
- Classify that surface as
active,idle-candidate,long-running, orunknown-needs-recheck. - Rotate to another offender on later ticks if needed.
Idle requires both:
- bottom-of-screen prompt proof (
›,>, or$) - materially identical full-screen reads for at least
60s
Known long-running operations (tests, builds, installs, deploys, migrations)
park the monitor branch, not the worker. Record the operation and re-check after
15m unless a stronger signal arrives.
8. Long Payload Gate
If a cron payload exceeds 30 lines and does not run a live query in step 1, treat it as a violation and rewrite it before use.
9. Lead/Orchestrator Inbound-Monitor Gate (Etan top priority, 2026-06-14)
A lead finished its lane, posted "Back to silent 👋" with no monitor armed; work routed to it via collab was a silent no-op. A "standing by" seat with no live inbound monitor is the same failure as a passive
SILENTtick (Rule 5) — it just hides behind "done."
If the payload belongs to a lead/orchestrator/weaver (a seat that receives collab-routed work):
- An armed persistent inbound monitor is a precondition, not an option. The seat's FIRST action is arming a native
Monitoron its channel (^### |BLOCKED|@<own-name>, exclude own). A recurring tick whose seat has no armed monitor is invalid — fix the seat before the tick. - "Stand by" / "keep monitoring" ticks are only valid with a live inbound monitor AND a consumed live query. Restate the channel tail (
!tail/grep for new@<name>/###) in step 1 and branch on it. A tick that says "still standing by" without reading the channel is the passive-output violation of Rule 5. - Going idle-and-blind is never a valid terminal outcome. Lane done →
dispatch(pick up monitor-surfaced work) or an explicit✅ DONE … monitor ARMED, standing bythat keeps the monitor running — never a stopped monitor.
Canonical law: /cmux-agents → "LEAD/ORCHESTRATOR MONITOR LAW"; /orc → "THE SECOND CARDINAL RULE".
Rewrite Protocol
When a payload violates this skill:
- Name the stale claim explicitly.
- Remove hardcoded state strings.
- Add a timestamped frame:
$(date), cycle, last-action-timestamp. - Move a
!live query to step 1. - Add monitor counters when the payload supervises a queue.
- Rewrite the decision tree so it consumes rendered query output.
- End in
dispatch,verify-and-decrement, orescalate-park. - For suspected freezes, add the one-full-read rotation and prompt-proof idle gate.
Anti-Patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| "Monitor pass: 3 PRs blocked" | Prompt claims state before checking it | Replace with !gh pr list/view in step 1 |
| 40-line cron prompt, live query in step 6 | Stale framing dominates reasoning | Put live query in step 1 |
SILENT autonomous repeated with no timestamps | Cannot tell fresh tick from copied frame | Add $(date), cycle, last-action-timestamp |
BLOCKED REVIEW_REQUIRED copied from yesterday | Model parrots stale state | Query review state live every tick |
| Resetting because a worker replied "looking" | Reply is not queue-decrement | Keep counting until a side-effect is verified |
| Parsed-only wrapper says idle | Wrapper text is telemetry, not truth | Rotate one full read onto the worst offender |
| Token count frozen, so worker is idle | Tool calls may continue without token movement | Full-read before any idle verdict |
| Build output stable for 2 minutes | Long-running ops can look unchanged | Park monitor branch and re-check later |
Composes With
| Skill | How it composes |
|---|---|
/never-fabricate | Prevents reporting prompt-state as verified reality |
/cmux-agents | Supplies surface/agent inspection and prompt-delivery mechanics |
/pr-loop | Merge queues should use these tick rules before claiming PR state |
Best Pass Rate
100%
Opus 4.6
Assertions
28
3 models tested
Avg Cost / Run
$0.2552
across models
Fastest (p50)
2.7s
Haiku 4.5
Behavior Evals
Phase 2 baseline — skill quality on ClaudeBehavior Baseline
| Assertion | Opus 4.6 | Sonnet 4.6 | Haiku 4.5 | Consensus |
|---|---|---|---|---|
| rejects-hardcoded-review-state | 1/3 | |||
| rewrites-step-1-to-live-query | 2/3 | |||
| explains-prompt-state-vs-live-state | 2/3 | |||
| preserves-frame-discipline | 3/3 | |||
| does-not-allow-explanatory-step-1 | 3/3 | |||
| moves-live-query-to-step-1 | 2/3 | |||
| removes-hardcoded-review-claim | 3/3 | |||
| keeps-decision-tree-after-query | 3/3 | |||
| does-not-accept-metadata-free-frame | 3/3 | |||
| adds-now-cycle-last-action | 3/3 | |||
| keeps-live-query | 2/3 | |||
| explains-why-staleness-would-be-undetectable | 2/3 | |||
| flags-over-30-lines-without-live-query-step-1 | 3/3 | |||
| collapses-stale-narration | 3/3 | |||
| restarts-payload-with-live-query | 3/3 | |||
| maintains-decision-tree-after-data | 3/3 | |||
| recognizes-compliant-step-1 | 2/3 | |||
| recognizes-valid-frame-discipline | 2/3 | |||
| does-not-invent-staleness-problem | 3/3 | |||
| connects-decision-tree-to-live-output | 3/3 | |||
| does-not-accept-hardcoded-review-loop | 1/3 | |||
| requires-live-query-step-1 | 2/3 | |||
| forces-one-of-three-outcomes | 2/3 | |||
| resets-only-after-verified-decrement | 2/3 | |||
| rejects-parsed-only-idle-verdict | 1/3 | |||
| forces-one-full-read-on-worst-offender | 2/3 | |||
| requires-bottom-prompt-plus-sixty-seconds | 1/3 | |||
| parks-long-running-ops | 3/3 |
Token Usage
Cost per Run
| Model | Input Tokens | Output Tokens | Cost / Run | Cost / 1K Runs |
|---|---|---|---|---|
| Opus 4.6 | 7,763 | 8,163 | $0.7287 | $728.70 |
| Sonnet 4.6 | 2,415 | 1,643 | $0.0319 | $31.90 |
| Haiku 4.5 | 3,042 | 3,443 | $0.0051 | $5.10 |
Response Time (p50)
Response Time (p95)
| Model | p50 | p95 | Overhead |
|---|---|---|---|
| Opus 4.6 | 5.2s | 9.9s | +91% |
| Sonnet 4.6 | 5.0s | 8.9s | +79% |
| Haiku 4.5 | 2.7s | 4.1s | +53% |
Last evaluated: 2026-03-12 · Data is generated from skill assertions (real cross-model benchmarks coming soon)
Changelog entries are derived from eval runs and skill version updates. Full cascading changelog (Phase 4D) coming soon.
Best Pass Rate
100%
Assertions
28
Models Tested
3
Evals Run
7
- +Initial release to Golems skill library
- +28 assertions across 7 eval scenarios
- +Eval fixtures included