hyperhive/claude-plugins/plugins/base/skills/async-task-hygiene/SKILL.md

48 lines
2.6 KiB
Markdown

---
name: async-task-hygiene
description: Habits for background tasks and waiting. Don't truncate a background task's captured output with a tail/head pipe - the full output is saved regardless, so piping it away only throws away what you might need, slice it after the fact instead. Don't assume a background task from before a restart is still exactly where you left it - check its status rather than blindly re-running it. Prefer ending your turn (or a short bounded wait) over a sleep-based polling loop when waiting on something in progress. Use this whenever you launch, check on, or wait for background work.
---
# Async Task Hygiene
Background tasks (a build, a long command, anything you fire off and
check on later) have a few sharp edges worth knowing.
## Don't pipe away captured output
Don't do `some-long-command | tail -N` (or `| head -N`) when launching
a background task. The runner captures the **full** stdout/stderr to a
file regardless of what you piped through - so truncating the live
output doesn't save anything, it just means you can't slice the part
you didn't think you'd need until you needed it. Run the full command,
then read/grep the captured file however you want afterward. (Genuinely
unbounded streams you'll never read in full are the rare exception to
this - not normal command output.)
## Don't blindly re-run a task after a restart
If your environment restarted (container rebuild, harness restart) and
you had background tasks in flight, don't assume they're gone and
re-launch them from scratch. Check their status first - a task may
still be running, may have finished while you were down, or may
genuinely need restarting. Re-running blind can duplicate work or step
on a task that's still making progress.
## Prefer ending the turn over a sleep-loop
When you're waiting on something (a build, a task you started, a fixed
delay before retrying), a `sleep`-then-check loop blocks you from
reacting to anything else for that whole window. Prefer:
- **Between units of work:** just end the turn. Whatever wakes you next
(the task's own completion, a new message) drives the follow-up -
there's nothing to poll for.
- **Within a turn, if you must wait:** a short bounded wait that can be
interrupted by new input beats a blind sleep, since it lets you react
immediately if something more urgent shows up instead of only after
your poll interval elapses.
Concretely: if you started something and plan to check back, don't
`sleep N && check-status` in a loop. Either end the turn and let the
task's own completion (or the next message) drive the next step, or use
an interruptible wait if you genuinely need to stay in-turn.