Don't watch. Wander. Philosophy: after you trigger something remote and slow, completion should find you — and the Agent must still verify the outcome, not assume it.
Meta vs implementation: This skill defines a portable best practice for any long-running remote task. Wander (
watch-workflow-*.sh) is the reference adapter when the source of truth is GitHub Actions. It is not the only valid monitor.
Every remote async task has the same shape:
text
Trigger → Runs elsewhere → Terminal state (+ artifacts)
(Agent) (cannot speed up) (User + Agent both need this)
The Agent should:
The loop is only complete when the Agent knows the terminal state (and, for failures, has enough log/context to fix).
Read the monitor output (terminal log, JSON summary, dashboard link + status scrape — whatever the backend provides).
Act on the result — do not consider the task "done" until the terminal state is confirmed:
Never assume success — "monitor started" ≠ "job succeeded".
Step A — Identify the system of record (where does the authoritative status live?)
ClassExamplesTypical system of recordRepo CIlint, tests, build in PRGitHub Actions, GitLab CI, Buildkite, Circle, …Mobile cloud buildEAS / Xcode Cloud / …Vendor build detail page, CLI status, webhook, or CI job that wraps the vendorDeploy / PaaSFly, Railway, Vercel, k8s rolloutProvider CLI/API, deploy dashboard, or CI deploy jobPublishnpm, stores, artifact registriesStore/CI pipeline status, not "upload started"
Step B — Pick a completion channel (lowest friction that preserves auditability)
workflow_dispatch).finished / errored when there is no CI wrapper and the vendor is authoritative.Step C — Run the monitor in the background unless the user asked to block the session.
Step D — After completion, fetch failure detail from that same system of record (failed step logs, EAS error page, deploy logs).
Do not default to "must be GitHub Actions" at Step A. Default to: whatever platform actually owns the terminal state for this trigger.
When the authoritative run is a GitHub Actions workflow (push, workflow_run, workflow_dispatch, etc.), use the Wander scripts as the monitor:
bash
# After Wander background process exits, check result:
gh run view <RUN_ID> --json conclusion -q .conclusion
# → "success" | "failure" | "cancelled" | "timed_out"
# If failure, fetch logs for Agent to diagnose:
gh run view <RUN_ID> --log-failed
Task taxonomy — examples (GHA column = when Wander adapter applies directly):
Task typeExamplesWander (GHA)CI testlint, unit test, e2e✅ When workflow is on GHABuildDocker, web bundle✅ When workflow is on GHAMobile buildEAS iOS/Android⚠️ Often indirect: GHA wrapper or vendor CLI/dashboardDeployRailway, Fly, Vercel✅/⚠️ CI job or provider-nativeRelease / publishnpm, store upload✅/⚠️ Same split as above
For EAS invoked only via CLI with no GHA: Wander scripts do not apply — use EAS/Expo status ( eas build:list, build URL, or project automation) per project docs.
Engine note: The wander repo today implements GitHub Actions polling + notifications. Other backends belong here as additional adapters (future) or as project-specific scripts that follow the same meta protocol.
Scope details: v1 scope: GitHub Actions today.
After triggering a long-running remote task, attach monitoring appropriate to that task's system of record — unless the user opts out or the task is trivially short.
If the triggered work is clearly GitHub Actions (or is wrapped entirely in a GHA workflow the Agent just started):
.workflows.yml if present → pick workflow + timing..github/workflows/ exists → identify the workflow (registry scan or ask), then start monitoring.watch-workflow-bg.sh <workflow.yml> — background unless the user wants to block.<workflow> on GitHub Actions; I'll notify when it finishes — you can keep working."gh run view <RUN_ID> --json conclusion. Do not declare success prematurely.gh run view <RUN_ID> --log-failed (or equivalent) and propose fix.If the work is not GHA (raw EAS CLI, provider-only deploy, etc.):
watch-workflow-bg.sh.If .github/workflows/ does not exist: do not auto-start Wander; choose another monitor per Step A–B above.
gh CLI installed and authenticatedjq installedWANDER_HOME (default ~/code/wander)bash
git clone https://github.com/ERerGB/wander.git ~/code/wander
cd ~/code/wander && chmod +x *.sh
Add to shell rc:
bash
export WANDER_HOME="${WANDER_HOME:-$HOME/code/wander}"
export PATH="$WANDER_HOME:$PATH"
alias wf='watch-workflow.sh'
alias wfbg='watch-workflow-bg.sh'
alias wfdt='watch-workflow-detached.sh'
ModeScriptUse caseBackgroundwatch-workflow-bg.shDefault. Keep working; get notified.Detachedwatch-workflow-detached.shClose terminal; logs to ~/.wander_logs/Foregroundwatch-workflow.shBlock session until done (rare)
Rule of thumb: prefer background. Use detached for > ~5 min if the terminal may close.
.workflows.yml, GHA)#Each workflow has different timing. The registry tells the GHA adapter what to expect:
yaml
workflows:
- name: "ci.yml"
description: "Lint + unit tests"
check_window: 180 # grace window if already finished when we start
expected_duration: 45 # typical runtime
category: "smoke"
- name: "build.yml"
description: "Docker build + push"
check_window: 600
expected_duration: 180
category: "build"
- name: "deploy.yml"
description: "Railway deploy"
check_window: 900
expected_duration: 300
category: "deploy"
check_window = if the workflow already finished before monitoring starts, how far back we still accept the run as "ours". Often ~ 6× expected_duration.
Auto-generate for a repo:
bash
cd /path/to/repo
"$WANDER_HOME/scripts-registry.sh" scan-workflows --auto-scope
Default check_window when unconfigured: 300s.
bash
git push origin main && "$WANDER_HOME/watch-workflow-bg.sh" ci.yml
bash
# scripts/watch-ci.sh
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WANDER_DIR="${WANDER_HOME:-$(dirname "$REPO_ROOT")/wander}"
exec "$WANDER_DIR/watch-workflow-bg.sh" ci.yml "$@"
Then: git push && ./scripts/watch-ci.sh
If EAS is triggered from a GHA workflow (e.g. eas-build.yml):
bash
git push origin feat/my-branch && "$WANDER_HOME/watch-workflow-bg.sh" eas-build.yml
If EAS is only CLI-triggered: monitor via EAS/Expo-native signals; optional team pattern is still to add a thin GHA workflow_dispatch wrapper if you want one uniform monitor.
bash
gh workflow run deploy.yml --ref main
"$WANDER_HOME/watch-workflow-bg.sh" deploy.yml main
ScenarioBehaviorWorkflow finishes before monitor startscheck_window may catch it; notify quicklyRun not appearing after ~30sWander waits, then exits with guidanceWrong branch filter on workflowNo run found; report and stopVery short workflowOften caught immediately via check_windowVery long workflowPrefer detached; logs survive terminal close
bash
gh run view <RUN_ID> --log-failed
gh run rerun <RUN_ID> --failed
For non-GHA tasks, use the same meta rule: pull that platform's primary failure surface (build log, deploy log, etc.).
$WANDER_HOME env var$(dirname "$REPO_ROOT")/wander~/code/wanderThe meta protocol is stable. Adapters are replaceable:
Until an adapter exists, prefer CI-as-facade or vendor-native poll — not silent assumption of success.