"Fires at TURN END - especially notification-driven turns (a worker finished, a background command completed - these FEEL like endings and are not) - and at every scheduled wake - re-arm the next wake as the last action, publish the dated status BLUF to SSOT first, audit and kill stale background jobs (verify the spawner died), recover after sleep gaps, land visible wins publicly the same cycle. Also fires on 'why did you stop' / 'progress update' / 'what is running' / 'keep going' - each such operator ask is a defect report against this skill."
Install
npx skillscat add simnova/openclinxr/loop-continuation Install via the SkillsCat registry.
Keeping the loop alive
Found by auditing 318 operator messages for corrections. This was the most repeated one, and no
existing skill covered it - my skills all taught me to distrust workers and artifacts; the
corrections were about trusting my own loop to keep running.
1. Re-arm at the END of EVERY turn - no exceptions
Verbatim: "keep going without my intervention - seems like you keep stopping", "Why stop keep
going", "are you still running - been a long time with no progress".
The mechanism. A turn driven by a task-notification - a worker finishing, a background command
completing - FEELS like an ending. It is not. If that turn ends without scheduling the next wake, the
loop is dead and the operator finds out before I do. I diagnosed this once and had to bake the fix
into my own standing prompt four separate times.
- The LAST action of every turn is the next wake.
- Notification-driven turns re-arm too. Especially those.
- "Nothing dispatchable right now" is not a stop condition - it is the cue to operationalize.
Stopping is only for a genuinely empty or fully-blocked board, said in one line.
Self-check at turn end: if the operator read nothing but the scheduler, would work resume without
them? If no, the turn is not finished.
2. Status is a durable surface, not chat
The operator asked "what is running" / "progress update" ten times in one session. Every one of
those asks is a wake that failed to publish.
- Every wake writes a dated BLUF to the SSOT before doing anything else: in flight / landed since
last wake / blocked and why / next. - If the operator has to ask what is in progress, the previous wake failed. Treat the ask itself
as a defect report against this skill, not as a request for information.
3. Audit your own background tasks every wake
"check status of shells you have running - are some of them things that should be killed?" - the
operator saw orphans I was not tracking.
- List live background tasks and long shells each wake. Kill iff EITHER: no advance in log lines
or target-file mtimes across two consecutive wakes; OR the spawner is gone while the child
persists. Record each askilled <pid> <artifact-checked>in that wake's BLUF. "Looked idle"
is not a criterion. - Kill means kill AND prevent re-spawn: "did you kill it and prevent it from spawning again?"
Verify the spawner is gone, not just the child. A job a loop relaunches next wake was not killed. - Judge liveness by durable artifacts - log lines, file mtimes, CPU over a window. Never by
pgrep -f,
which matches its own command line and once reported RUNNING through a 9.5-hour stall. Mechanics:grok-worker-monitoringsections 1 and 5.
4. Recover after a sleep or an unexplained gap
On any wake following a gap, verify workers, dev servers and long jobs are still alive and still
writing before dispatching on top of them. Assume nothing survived.
5. Close the loop on visible wins - same cycle
The operator asked for website updates five times, including "need to count wins to show
progress".
- A slice that lands something visible - asset, room, humanoid, rig - is not closed until the
public surface reflects it. Part of the landing checklist, not a follow-up. - Only graded, skeptic-passable images go public. A 26 KB error screenshot shipped as "evidence" once
already. Grade first, publish second.
6. ENUMERATE before you select — the missing step
Diagnosed 2026-08-22 by the superagent, after the operator found four pieces of unfinished work in one
hour that I had not: "Your tick enumerates STATES (harvest → killed-check → collision-check) and then
calls a selector. Nothing in the pipeline ever builds the candidate list from the world. Sweep is an
ENUMERATION step, and there is no enumeration step."
A perfect selector cannot select work it never enumerated. Duties 1–5 above are all reactive by
construction — task-notification, scheduled wake, operator ask. None of them compares the world
against the ledger. And the pulse cannot cover for it: the pulse measures throughput, never
inventory, so NUMBERS_ONLY reads healthy-flat on an 86-card backlog with 13 abandoned contracts,
because activity metrics see flow and not stock.
Every tick prints this line, next to the pulse row:
SWEEP: reds=N(oldest #id) undisp=N uncarded=N rel=<tag> quiet=N workers=n/floor bothy=<empty|tsk_|NOT DETERMINED>A tick report without it is an invalid tick — the same enforcement class as post-slice failing on a
missing token-introspection line, which is the only gate that has ever actually held.
The five queries behind it, ~15 s total:
| # | query | a hit means | do |
|---|---|---|---|
| S1 | it.fails( across apps packages tools test files, minus files containing ## FIXED |
a planted RED still unmet — a slice started and abandoned | bucket it; dispatch or close one per tick |
| S2 | open cards carrying lane: but no ## factory_step: |
assigned work that cannot dispatch | operationalize at most 2 |
| S3 | git log --since=24h --diff-filter=A over test/evidence paths, diffed against closed cards |
a contract landed with no card tracking its flip | open the flip card the same tick |
| S4 | upstream release tag vs the version pinned in the tree | a dependency moved while nobody looked | pin-bump card, or record the non-use reason |
| S5 | newest session updates.jsonl line counts across wakes |
a consult thread went silent mid-thought | resume or close it explicitly |
| S6 | BothyBoard tasks.next (always; PAT required; never ranks GitHub) |
ready set empty, or a tsk_* Planted card |
print bothy= on the SWEEP line; operationalize if empty while WCG cards should exist |
All four of the operator's catches map to these: lip-sync was S3, eyebrows S1, Rhubarb S2 verbatim,
IWSDK S4 verbatim. Four for four — none needed judgement, only enumeration.
Secondary trigger: if reds grows between consecutive ticks, the next action is a bucket decision
on the RED list before any new dispatch. Growth means work is being abandoned faster than finished.
7. PRODUCING_NOTHING obliges a NEEDS-DECISION record in the SAME tick
Not next tick. The verdict exists because ACTIVITY_INCREASING read like praise and got skimmed for
nine hours. When it fires, the tick states plainly what is in flight, why product bytes are zero, and
what would change it — or admits the loop is spinning. Do not explain the verdict away; it fires ongraded==0 && productCommits==0 && totalCommits>=3 && completions>=3, and every one of those is a fact.