Install
$ agentstack add skill-glyphs-ai-glyph-dispatch-watchdog ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo 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.
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
tasktool with a Haiku/Sonnet subagent for the
poll loop. Agents describe; they don't reliably loop.
- Do not use
Start-Processto background the watchdog. The
process is invisible to the runtime.
- Do not use
mode:asyncwithoutdetach: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
statuswith 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:
- Persist the id (
task-id.txtin the mission folder is the
convention for task ids; workflow ids follow the same per-mission file convention).
- 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.
- On notification, read
watchdog.log's last line for the final
status and proceed.
- 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.
- 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.
- Author: glyphs-ai
- Source: glyphs-ai/glyph
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.