AgentStack
SKILL verified MIT Self-run

Dispatch Watchdog

skill-glyphs-ai-glyph-dispatch-watchdog · by glyphs-ai

Spawns a properly-detached cross-platform watchdog over a running glyph task or workflow — polls status, exits on terminal state, and reliably surfaces runtime completion notifications to the orchestrator session

No reviews yet
0 installs
4 views
0.0% view→install

Install

$ agentstack add skill-glyphs-ai-glyph-dispatch-watchdog

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Dispatch Watchdog? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Dispatch Watchdog Skill

Domain

A single primitive for any orchestrator agent that dispatches a long-running glyph task or workflow: given an id, spawn a watchdog that polls glyph show --json on a configurable cadence and exits when the entity reaches a terminal status (succeeded, failed, cancelled). The watchdog must be spawned in a way that the glyph runtime can observe its completion and deliver a notification back to the orchestrator's session — not all spawn patterns achieve this.

Boundary

In scope:

  • Spawning a detached watchdog process from the orchestrator's shell

using the runtime's mode:async + detach:true primitive.

  • A polling loop that reads task or workflow status via the glyph CLI

and exits cleanly on terminal state.

  • A persisted watchdog log (one line per poll) for after-the-fact

inspection.

  • Cross-platform invocation (Windows and macOS/Linux share one Node

body; only the OS-level spawn wrapper differs).

Out of scope:

  • Interpreting task output or success/failure semantics — that is the

caller's job after notification.

  • Cancelling stuck tasks — see the caller's stuck-task playbook.
  • Replacing the orchestrator's own monitoring tick loop; this is for

single long-running tasks or workflows where polling-in-foreground would block other work.

Why this skill exists

The glyph runtime delivers a completion notification to the orchestrator's session only when the watchdog is spawned through the mode:async + detach:true primitive shown below. Other spawn shapes silently break the notification path.

Primitive

The skill ships a Node script watchdog.mjs next to this file. Refer to it via the `` placeholder — your runtime resolves the path from context, so the body stays neutral across Copilot CLI, Claude Code, Gemini CLI, Cursor, Windsurf, Codex, and any other provisioner. The script depends only on the Node stdlib and runs identically on Windows, macOS, and Linux.

> ` is the directory containing this SKILL.md`. Resolve > from your runtime context.

Script CLI

node /watchdog.mjs \
        [poll-sec=60] [max-loops=240]
  • `` — selects which glyph subcommand to poll

(glyph task show vs glyph workflow show).

  • `` — the task or workflow id. Server-generated ids match

^[A-Za-z0-9-]+$; the script rejects anything else (defence-in-depth against shell injection through the polled CLI command).

  • `` — must be absolute. The script does not resolve

relative paths; under detached spawn process.cwd() is unspecified.

  • [poll-sec] — seconds between polls; default 60.
  • [max-loops] — give-up bound; default 240 (≈4 hours at the default

cadence). On hitting the bound the script writes max-loops-exceeded and exits 1.

Status extraction uses JSON.parse(raw).status, which indexes the top-level field directly. This is robust against long string values, backslash escapes (e.g. Windows paths in workflow details), and any "status": "..." substrings that appear inside nested string content — a regex against the raw JSON cannot make that distinction.

PowerShell (Windows) — spawn via mode:async + detach:true

# In glyph / Copilot CLI tool form:
#   powershell:
#     command:     node /watchdog.mjs task  "\watchdog.log"
#     mode:        async
#     detach:      true
#     initial_wait: 10

Use workflow in place of task to poll glyph workflow show --json instead.

The orchestrator returns immediately to other work; the runtime notifies the session when the watchdog exits.

Bash (macOS / Linux) — same pattern, runtime auto-wraps in setsid

# In glyph / Copilot CLI tool form:
#   bash / shell:
#     command:     node /watchdog.mjs task  "${mission_dir}/watchdog.log"
#     mode:        async
#     detach:      true
#     initial_wait: 10

(On Unix-like systems the runtime wraps detached commands with setsid automatically; the notification path is the same as Windows.)

Watchdog log format

First line is the start marker (see Caller contract item 4). One line per poll thereafter, monotonic-timestamp-prefixed, for debugging stuck or runaway watchdogs:

2026-05-22T08:30:00+00:00 watchdog started for 20260522-abc12345
2026-05-22T08:31:00+00:00 status=running
2026-05-22T08:32:00+00:00 status=running
2026-05-22T08:33:00+00:00 status=succeeded

Anti-patterns (do not use)

  • Do not use the task tool with a Haiku/Sonnet subagent for the

poll loop. Agents describe; they don't reliably loop.

  • Do not use Start-Process to background the watchdog. The

process is invisible to the runtime.

  • Do not use mode:async without detach:true. Session

shutdown will kill it.

  • Do not poll faster than every ~15s without good reason — every

poll is a CLI invocation that spawns a Node process.

  • Do not reach for child_process.execFileSync('glyph', ...)

when authoring an ad-hoc watchdog variant. On Windows + Node 22+ the CVE-2024-27980 hardening refuses to spawn .cmd shims via execFileSync and throws EINVAL. The shipped watchdog.mjs uses execSync with a shell-routed command and a strict id-regex guard for exactly this reason — do not "fix" it to execFileSync.

  • Do not extract status with a regex over the raw JSON. The

glyph workflow show --json payload includes a details field that JSON-encodes the workflow brief verbatim; briefs frequently contain "status": "..." substrings, and a first-match regex picks those up instead of the top-level field. watchdog.mjs uses JSON.parse(raw).status to dodge this; preserve that.

Caller contract

The caller (orchestrator) MUST:

  1. Persist the id (task-id.txt in the mission folder is the

convention for task ids; workflow ids follow the same per-mission file convention).

  1. Invoke the watchdog once per id. Do not re-spawn if one is

already alive. Liveness = watchdog.log mtime within 2× the configured poll interval. Older = dead; respawn.

  1. On notification, read watchdog.log's last line for the final

status and proceed.

  1. Verify start within 5s of spawning. Read the first line of

watchdog.log; it MUST contain watchdog started for . If the marker is absent, the watchdog is dead (bad args, missing id, exec failure) — fix the invocation and respawn. Do not proceed assuming monitoring is active.

  1. Verify status capture within 2× the configured poll interval.

Read watchdog.log and confirm at least one non-empty status= line exists. A line reading status= with no value indicates the polled CLI returned a payload without a top-level status field, or the call itself failed (look for a poll-error: … line on the previous tick for detail). Fix the underlying issue and respawn — do NOT wait for a completion notification, it will never arrive.

CHANGELOG

See CHANGELOG.md next to this file.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.