sweeps
Skill4 starsChanged 29 days agoMITView on GitHub
Use when changing autonomous maintenance sweeps (SWEEP_ENABLED) — the scheduler, task catalog and prompts, cooldowns, per-run cost guards, aborted-run salvage, base-branch resolution, or the manual /sweep trigger.
- Commits and pushes
1 other project uses a version of this.
Adopted by
Most recently taken up by
- ahmadAlMezaal/noctraword for word, first seen Oct 15, 2026
Other versions1 project uses a version of this.
Word for word · 1
- ahmadAlMezaal/noctra★ 3100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository11 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- agent-backendsSkill
- architectureSkill
- auto-iterateSkill
- build-and-releaseSkill
- dashboardSkill
- github-identitySkill
- namingSkill
- setup-and-configSkill
- troubleshootingSkill
- writing-good-ticketsSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is 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.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 48
Announced: Every terminal outcome notifies through pipeline.notifySweepOutcome with tokens and estimated cost: aborted, failed, blocked, …
≈ “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.
Files
Autonomous maintenance sweeps
With SWEEP_ENABLED=true a third loop runs beside the Linear and PR-watcher loops, sharing the WaitGroup so shutdown drains in-flight tasks. Off by default.
sweep loop → scheduler.DueIn (cron SWEEP_SCHEDULE or fixed SWEEP_INTERVAL) → scheduler.Plan (SWEEP_REPOS or all cloned repos × task catalog)
→ filter by cooldown (per-repo, per-task, from state store)
→ pipeline.processSweepTask (bounded, shares the worker pool + active-set)
→ repo.CreateWorktreeWithBranch → agent.Run (task-specific prompt) → commit/push → gh pr createTasks, cooldowns, PRs
- The catalog lives in
internal/sweep/task_*.go; each file registers a task at init. Current tasks:lint-cleanup(weekly),dead-code(biweekly),deps-update(weekly),test-coverage(biweekly),doc-drift(biweekly),modernize(biweekly),bug-scan(biweekly, high-confidence defects only).SWEEP_TASKSscopes them. - Each task has a per-repo cooldown in the state DB (
sweep_states,state.SweepState). A run that fails on an expired login (describeAgentFailure(...).auth) does not record it: the task never ran, so it should retry next cycle once login is restored. - Branches are
noctra/sweep-<task>, identifiersSWEEP-<repo-slug>-<task>; thenamingskill has why they differ. Sweep PR bodies carryNoctraPRBodyMarker, so auto-iterate claims them, and amaintenancelabel so humans can bulk-close them. - Budget pause/exceeded skips sweeps, like ticket work.
- One cycle can land two tasks on the same repo (
scheduler.roundRobinrevisits repos on a second pass), and every worktree helper mutates the shared clone under its.git/configlock.internal/reposerialises them per clone vialockRepo; without it the loser fails withcould not lock config file .git/configand its task is silently dropped. Keep any new clone-mutatinggitcall inside that lock.
Base branch
Precedence, resolved in scheduler.repoTargets/Plan into Job.MainBranch (which feeds the worktree base, the branchAhead compare and the gh pr create base together):
- an
@branchsuffix on theSWEEP_REPOSentry (scheduler.parseSweepRepoRef); - the matching Linear project's
Branch:directive (linear.ListProjects→Project.RepoDirective, matched bygithub.ExtractOwnerRepo; discovery-path repos are keyed off theiroriginviarepo.OriginRemoteOf); - the repo's GitHub default branch (
origin/HEAD); MAIN_BRANCHforSWEEP_REPOSentries; repos found by scanning the clone directory fall back tomain(repo.DefaultBranchOf).
Per-run cost guards
The daily MAX_DAILY_* caps only gate between dispatches; a run in flight isn't stopped by them. Two per-run bounds close that gap:
SWEEP_TIMEOUT_MINUTES(default 20) caps wall-clock, shorter than the ticketAGENT_TIMEOUT.AGENT_MAX_TOKENS(config.AgentMaxTokens, wired into everyagent.RunOptions.MaxTokens) aborts any run once cumulative tokens cross it. Claude-only:claudeBackend.runStreamstreams--output-format stream-json, sums per-turn usage, and cancels on breach (agent.ErrTokenCapExceeded); other backends fall back to the timeout. Sweeps get aconfig.DefaultSweepMaxTokens(2M) floor when it is unset — a productive sweep lands around 0.6M, so 2M means mis-scoped, not nearly done. (History: one dead-code run burned 18.4M tokens / $33 before any guard; an 8M floor was then burned whole by a bug-scan in 4.5 min for nothing.)
The token ceiling is a guard, not a budget — raising it does not rescue a run. Every aborted sweep consumed exactly its ceiling (8M → 8,097,478; 2M → ~2.04M ×3; 5M → ~5.05M ×3), while every run that produced something finished under 1M. A task that hits the ceiling is non-converging; fix the task prompt, not AGENT_MAX_TOKENS. dead-code, test-coverage and deps-update shared an unbounded verify loop over a slow JS suite (bump → full suite → revert → repeat), so their prompts now cap the work (≤20 removals, ≤5 bumps) and the verification (≤2–4 full-suite runs) and say to ship what is already green. lint-cleanup converged on the same repo deps-update died on twice, which ruled the repo out.
Aborted runs
- Accounted for.
runStreamlearns true cost only from the terminalresultevent, which never arrives aftercancel(). It accumulates per-turn usage plus the model name while streaming and, whenresultis missing, estimates fromagent.PricesForModel(internal/agent/pricing.go). Before this, aborted runs recorded$0.00and ~$30 was invisible toMAX_DAILY_USD. - Recorded. Both abort paths (
ErrTimedOut,ErrTokenCapExceeded) go throughpipeline.abortSweepTask: record usage, record the cooldown, write arun_historyrow with statusaborted(notfailed— the run was healthy, we killed it), notify. Recording the cooldown is deliberate: an aborting task aborts again identically, so skipping it would re-burn the ceiling every cycle./sweep --forceis the escape hatch. - Salvaged.
pipeline.salvageAbortedWorkcommits any worktree changes, pushes, and opens a draft PR<prefix>: <description> (partial)whose body opens by saying the diff is UNVERIFIED (the agent never reached its build/test step). It carries the marker andmaintenancelabel, so auto-iterate drives a cheap CI fix instead of a fresh full scan. Therun_historyrow staysabortedbut carries the PR URL. - Announced. Every terminal outcome notifies through
pipeline.notifySweepOutcomewith tokens and estimated cost: aborted, failed, blocked, no-change, PR opened. It sends oncontext.WithoutCancel, becausemarkDonecancels the task context the momentprocessSweepTaskreturns.
Manual trigger
/sweep (Telegram), noctra sweep (CLI) and POST /api/sweep (dashboard, admin token) all funnel into Pipeline.TriggerSweep, which hands a sweep.PlanOptions to the existing runSweepLoop over the buffered sweepNow channel. The loop dispatches through its own WaitGroup, active-set and MAX_CONCURRENT accounting.
- A manual trigger never plans and dispatches inline: a second dispatcher beside the loop would bypass the worker-pool cap and double-run tasks.
- A manual sweep skips
MarkSwept, so it never shifts the scheduled cadence.PlanOptions.IgnoreCooldown(--force) is the only way to re-run inside a cooldown. Budget pause still refuses it. noctra sweepis a thin HTTP client over the dashboard admin API, not a second sweeper — two processes planning against one state DB would double-dispatch and race on cooldowns.
Config
| Env var | Default | Description |
SWEEP_ENABLED | false | Enable the sweep scheduler |
SWEEP_SCHEDULE | (empty) | 5-field cron (sweep.ParseCron, zero-dep); empty = use SWEEP_INTERVAL; invalid → warn + fall back. Cron mode waits for the next match |
SWEEP_INTERVAL | 86400 | Seconds between cycles; fires immediately on startup |
SWEEP_MAX_TASKS | 5 | Max tasks per run |
SWEEP_TIMEOUT_MINUTES | 20 | Per-task wall-clock cap |
SWEEP_TASKS | (all) | Comma-separated task names |
SWEEP_REPOS | (all cloned) | owner/name or git URLs, resolved via repo.ResolveDirect (clone-on-demand); replaces AllRepoPaths() discovery; unresolvable entries warn and skip. @branch suffix pins the base (also on full URLs and scp git@host:owner/name@staging) |
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
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.

