agentleFS
sonichisonichi/sutando/skills/proactive-loop/SKILL.md

proactive-loop

Skill396 starsChanged 6 months agoMITView on GitHub

Start Sutando's autonomous proactive loop. Monitors tasks, runs health checks, and builds missing capabilities on a recurring schedule.

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 0 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Very specific:

    If CronList already shows a main-loop / /proactive-loop job, run the per-pass body directly — never add a second loop driver.

    line 23
  2. Very specific:

    When this core consumes a task itself, move $WORKSPACE/tasks/<id>.txt to $WORKSPACE/tasks/archive/<id>.txt after writing its result.

    line 52
  3. Very specific:

    Questions: Read <workspace>/hosts/<host>/pending-questions.md.

    line 59
  4. Very specific:

    Build log: Read $WORKSPACE/build_log.md.

    line 74
  5. Very specific:

    Write the pick into the status step.

    line 77
  6. Very specific:

    Not running with no trees → Monitor bash src/watch-tasks-stream.sh persistent.

    line 111
  7. Very specific:

    Discord: Check the channels in reference_discord_channels.md.

    line 116

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Proactive Loop

One pass = the numbered steps below, in order. Each step is a command, its exit codes, and what to do per code. The reasoning, measurements and incidents behind every step live in docs/proactive-loop-rationale.md under the same step number; read it when a step surprises you, never per pass. A rule belongs here only as a command a mechanism enforces; prose lessons go to the rationale doc (tests/proactive-loop-skill-budget.test.py caps this file and refuses date stamps in it).

Usage: /proactive-loop [interval] (default 10m).

On activation

  1. /schedule-crons — registers the session crons and stamps them.
  2. Task watcher via the Monitor tool: command: 'bash src/watch-tasks-stream.sh', persistent: true, description: 'Streaming task watcher'. Each TASK_FILE: <name> line is one task to Read and process. Windows has no Monitor tool: src/startup.ps1 owns src/task-dispatcher.ps1; do not start another watcher.
  3. If CronList already shows a main-loop / /proactive-loop job, run the per-pass body directly — never add a second loop driver.

Per pass

WORKSPACE="$(bash scripts/sutando-config.sh workspace)" once; quote every "$WORKSPACE/..." path.

  1. Status. bash scripts/core-status.sh running "<what the owner is waiting on>"; rewrite on every pivot; bash scripts/core-status.sh idle at the end. Never > the JSON yourself. 0.5. Quota tier (Claude core): python3 $CLAUDE_CONFIG_DIR/skills/quota-tracker/scripts/read-quota.py | python3 skills/proactive-loop/scripts/quota-tier.py → TIER <FULL|MEDIUM|LIGHT|MINIMAL> (bound by …). Then python3 skills/proactive-loop/scripts/claude-quota-cadence.py --json → if effective_cron differs from the /proactive-loop job in CronList: capture the old job id, CronCreate the new job with prompt: "/proactive-loop" and cron: <effective_cron>, confirm it in CronList. Then CronDelete the old id and confirm exactly one /proactive-loop job remains. If create or confirmation fails, keep the old job and stop loudly. Codex core: python3 skills/proactive-loop/scripts/codex-quota-gate.py --json. Tier caps step 6's depth (LIGHT/MINIMAL: no self-development); it never skips owner tasks, health or the log. 0.7. Reconstruct. Invoke the context-reconstruct skill (a Skill-tool call, not a mention). It reads <workspace>/hosts/<host>/current-track.md first, then the live thread (python3 src/discord-read.py <channel> --serving <channel> when serving a task, --operator otherwise), pending questions, relay, build log. Trust the record over recall; maintain current-track.md.
  2. Tasks. Process every file in $WORKSPACE/tasks/; access_tier: team|other → the sandboxed path. Group a thread with [deduped: task-<latest>], staged under its FINAL name and gated into place — results/ is claimed by a poller in under a second, and the checker reads the source id from the BASENAME, so a generic temp name makes it pass everything: S="$WORKSPACE/state/dedup-staging/<file>" then python3 skills/proactive-loop/scripts/check-dedup-targets.py "$S" && mv -f "$S" "$WORKSPACE/results/<file>" (0 clean · 1 the dedup delivers nothing · 2 cannot answer). All-notice groups use [no-send] on each. Marker semantics belong to src/result_markers.py; never re-implement them. When this core consumes a task itself, move $WORKSPACE/tasks/<id>.txt to $WORKSPACE/tasks/archive/<id>.txt after writing its result; bridges and the Windows dispatcher archive their own claims. Before idle: python3 scripts/unanswered-tasks.py --workspace "$WORKSPACE" && bash scripts/core-status.sh idle (1 = a task got no result, so idle does not run). 1.5. Connect waits. python3 skills/connect-apps/scripts/connectors.py rearm restarts the waiter of any pending connector wait that lost it; idempotent, and a failure never blocks the pass.
  3. Questions. Read <workspace>/hosts/<host>/pending-questions.md; surface via results/question-<ts>.txt when voice is connected, plus a macOS notification.
  4. Health. python3 src/health-check.py; fix with --fix what it can. A warn is a pointer into the record: before investigating, grep -in "<entity from the warn TEXT>" "$H/pending-questions.md" "$H/current-track.md" with H="$WORKSPACE/hosts/$(bash scripts/sutando-config.sh host-label)"; a zero means try another token, then grep -n '^## ' "$H"/*.md before concluding absence. Extend a hit; never re-file it. 3.45. Duplicate issue gate, chained so a refusal cannot be skipped: python3 skills/proactive-loop/scripts/gh-duplicate-check.py --repo <owner/name> --title "<title>" && gh issue create --repo <owner/name> --title "..." --body-file <f> (0 no candidate · 1 do not file, candidates named · 2 cannot answer). 3.5. Policy. python3 skills/proactive-loop/scripts/self-development-enabled.py → disabled skips 4–8, 10, 11. Owner-requested tasks, pending questions, health/service recovery and the watcher remain active. Manual /proactive-loop invocation does not override the policy. 3.6. Tool suites. python3 skills/proactive-loop/scripts/tool-suites-check.py --workspace "$WORKSPACE" --repo "$PWD" (0 pass · 1 a suite failed · 2 cannot answer). Extra suites are declared in $WORKSPACE/hosts/<host>/tool-suites-extra.json. It passes no argv to a suite.
  5. Build log. Read $WORKSPACE/build_log.md; do not rebuild what works.
  6. Pick the highest-ROI unblocked item: owner tasks and blockers, then peer opinion-requested / review-requested claims in #bot2bot, then voice reliability, then regressions, then the menu. Write the pick into the status step.
  7. Act. A blocked primary is a cue to switch lanes, never to idle. Before pivoting from the owner's latest ask, read state/last-owner-activity.json and announce the pivot in the bot-to-bot channel per PERSONAL_CLAUDE.md. Skip this step only for: MINIMAL tier; owner active in the last ~5 min; state/presenter-mode.sentinel (bash scripts/presenter-mode.sh); state/loop-paused-until.sentinel; python3 src/shutdown.py check exiting 0 (finish in hand, write idle, do not relaunch). 6.5. Idle surface. Record the pass: python3 skills/proactive-loop/scripts/idle-surface-hash.py --state "$WORKSPACE/state/idle-streak.json" --pass-outcome substantive|noop. The held set is edited only through python3 skills/proactive-loop/scripts/idle-held.py --state "$WORKSPACE/state/idle-streak.json" --remove <id> --reason "<why>" --add <id>:<gate> --note <owner/repo#n> (no whole-list interface; a removal needs a reason); audit notes with --audit-notes "$PWD" and retire merged items. Compute: idle-held.py … | idle-surface-hash.py --state … → post <hash> or quiet <hash>. On post: send ONE FYI line to the owner's primary channel, THEN re-run the same pipe with --write on idle-held.py AND --commit on idle-surface-hash.py — each flag belongs to its own side, and --commit alone leaves added holds, removal reasons and notes unpersisted, so the next pass re-posts the stale hold. Never commit before the send; never build the list from recall. quiet + owner active in the last ~30 min → still drop a one-line activity signal. 6.7. Failure closure. Every reported failure ends with the mechanism that prevents its recurrence, linked, or the sentence "no mechanism exists, because X". A filed lesson is not a third option.
  8. Build log write. Append with O_APPEND and a random marker; assert count(MARK) == 1 by reading the file back. Never read-modify-replace. Then decide whether a relay/relay-<ts>.md note is owed (a PR event, a resolved question, a lifted or new blocker, a judgment) — most passes owe none. 7.5. Memory index, chained so a refusal cannot be skipped: python3 skills/proactive-loop/scripts/memory-index-budget.py --adding "<row>" && <append the row> (0 safe · 1 refuse, casualty named · 2 cannot answer). On refusal free room FIRST and check the row is still reachable from its hub before removing it; which rows go is the owner's call.
  9. Ask. Insert the question ABOVE the # Resolved divider of the per-host pending-questions.md, placed by importance (only the top 5 render anywhere), and assert with the reader: python3 -c "…src/check-pending-questions.py…get_waiting_questions()" — count went up, title matches, position ≤ VISIBLE_PREFIX. macOS notification; results/question-<ts>.txt when voice is connected. Then pivot; never block.
  10. Watcher. Act only on the task-watcher probe from step 3. Stop pids only when the probe presents owned and ownerless as two separately labelled groups; one undifferentiated list means change nothing. Not running with no trees → Monitor bash src/watch-tasks-stream.sh persistent. A missing sentinel is UNKNOWN, not dead; never hand-roll a process check. 9.5. PR thread gate, chained so a refusal cannot be skipped: python3 skills/proactive-loop/scripts/pr-monologue-check.py <PR url|number --repo owner/name> --me <your-login> && gh pr comment <number> --repo <owner/name> --body-file <f> (0 safe · 1 refuse, run and span named · 2 cannot answer). On refuse, re-solicit through a stand.
  11. Discord. Check the channels in reference_discord_channels.md; forward actionable public items to the dev channel. #bot2bot tags: claim: blocked: done: ping: nack: opinion-requested:. First PR opened wins a claim. Bots never merge. Three unresolved round-trips → both positions to pending-questions.md, proceed with the cheaper-to-reverse option.
  12. Heartbeat. Substantive pass + #bot2bot configured + other bot active → done: <one line> via the bot2bot-post skill. Never fall back to results/proactive-*.txt. Never write contextual-chips.json.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.