sno-ai/sno-station-skills/pl-watch

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

PL (Project Lead) role sub-skill for supervising in-flight executors. Loaded ONLY through the pl core routing table; NEVER auto-load from context, never invoke directly.

Install

npx vskill@latest install sno-ai/sno-station-skills/pl-watch

SKILL.md

PL · Watch — in-flight supervision & process control

Scripts named below run as bash "${PL_SKILL_DIR}/scripts/<name>.sh" ..., where PL_SKILL_DIR is the absolute path of the pl skill directory; set it in the same Bash call.

Sub-skill of the PL role. The pl core skill invokes this EXPLICITLY whenever executors are in flight: a watch fires, a card lands, a stall or convergence doubt appears, an expensive run is requested, or a GPU phase starts. Core iron rules bind unchanged: never write product code; never trust report prose — disk over words; the owner ("owner" means whoever owns the work, often the user) is addressed in the user's own language, while agent-to-agent text uses the project's working language (English by default). Canonical scripts: the pl skill's scripts/. The workspace layout (ai-doc/ACTIVE/PL/, ledgers) is documented in the pl core's State files section. Design principle behind everything here: the machine must lose patience before the owner does — every place the owner has to scold marks a missing mechanical control. Words such as journey, callsign, seat, card, night shift, charter and take-over are defined once, in the pl core's Terms glossary. The rules in this file are the PL role's defaults; a project may choose otherwise.

Card-handling discipline (PL side of Reach)

Wake sequence is fixed: the core boot/wake ritual runs FIRST — bash "${PL_SKILL_DIR}/scripts/roster.sh" --git <repo-path> (when the project uses git), then the inbox read (sno reach inbox --as "$PL_ADDR"; pl core §Communication, boot ritual); everything below applies AFTER that ritual, when reasoning about a specific journey or card. Every wake includes the journey thread — rings, watch firings, monitor events, background-task completions, owner messages alike: run sno reach log --as <your-strict-address> --work <active> BEFORE reasoning about anyone's state; never declare an executor unresponsive without reading the journey thread (the cards cross — a reply and a fresh question can land within seconds of your own card). There is no idle: after any reply you end the turn with the heartbeat-ring armed — copy the standard command verbatim, never improvise shell:

bash
# From the repo root. Ten minutes is the default while a night shift is declared; 3m in a launch window,
# 20-30m steady daytime, 45-60m when everything waits on someone else.
# One resolver, never a repository-only first-row lookup: on a repository with several PL lanes
# that would silently hand one lane another lane's seat; the resolver refuses rather than guesses.
PL_ADDR=$(bash "${PL_SKILL_DIR}/scripts/lane-resolve.sh" --repo "$PWD" --field addr) || exit 64
label="pl-${PL_ADDR#pl.}"; label="${label%@*}"
if sno heartbeat --list | awk -v l="$label" '$3==l{f=1} END{exit !f}'; then
echo "heartbeat already armed for $label" >&2
exit 64
fi
sno heartbeat --interval 10m --label "$label" -- sno reach ring "$PL_ADDR"

The heartbeat hook rings your own seat; the ring starts your next turn, and no listener or reader is needed. Nothing here blocks: you arm it and end the turn. Arm at most one: the block above checks for a live heartbeat with this label before arming; if one exists, do not arm another — per-turn arming without the check stacks heartbeats, and every one rings on its own clock. Ordering iron rule: clear ALL pending cards BEFORE arming — a card left unanswered when the turn ends is found only by the next ring. A downgrade to the owner counts as a reply (send the downgrade answer card); only then arm. Every inbound card is handled, never left — and handled has two verbs. Reach keeps an unhandled card in your queue, and its prompt reminder keeps naming it, on UNHANDLED mail, not on unread mail and not on content: a card you read and correctly judged to owe no answer keeps being named until it is handled. reply and dismiss both stop it; reading does not. So triage by header, one card at a time and never in bulk — sno reach inbox --as <addr> prints each delivered path and its subject, and grep -m1 -i '^x-type:' <path> types it. question and decision both owe you an act: reply on the card's own path (sno reach reply --as "$PL_ADDR" --card <path> [--state accepted|completed], body on stdin; work you carry out is accepted, then completed; a question that only asks you for information is answered without --state), and for a decision reply with the disposition. dismiss refuses those types and is ONLY for a card that owes no answer — an info, or an answer you have absorbed. A type you do not recognise is not dismissible: treat it as actionable.

bash
sno reach dismiss --as "$PL_ADDR" --card <delivered-path> --reason '<why none is owed>'

Dismiss writes no card, keeps the card's bytes and thread history, and moves your copy from the actionable queue to handled cur/; it deletes nothing. Replying to a card that owes no answer also stops the reminder — at the cost of an echo the other side must then dismiss. Card age changes URGENCY, never authority: on an old card, inspect the linked thread first — a terminal park/ruling already there means respond on that thread; otherwise apply the Triage Predicate regardless of age — age proves neither escalation nor resolution. Armed CONTINUOUSLY, not merely "before idle": a blocker landing while the PL is HEADS-DOWN on a different task — spawning an adversarial probe, running a close-audit, writing an owner report — sits unseen until the PL resurfaces UNLESS the heartbeat is already live. The rule is not "arm when you go idle," it is "a heartbeat is live whenever a card could land" — the same heartbeat keeps ringing across long tasks, so after every ring you handle the cards and end the turn again; re-arm only when sno heartbeat --list shows it gone (a heartbeat ends after its maximum hours). A headed executor (one the owner opened in their own terminal, not one the PL spawned) has NO `spawn-exec` ack/no-ack alarm (that alarm exists only for PL-spawned tmux sessions): the heartbeat — or a manual inbox read — is the ONLY thing that catches its Blocker cards, so treat any headed session as extra-vigilance and never promise to "catch its card" without a live heartbeat behind the promise. Two more hygiene clauses: a heartbeat is yours to stop (sno heartbeat --stop <label>) when its journey or shift ends, so it does not ring for nothing; and another seat's heartbeat is left alone — killing someone else's machinery is whack-a-mole you lose.

Supersede protocol: a superseding order must NAME and VOID the card it replaces ("this voids m-…"); an order that merely contradicts an earlier card leaves two live rulings and the executor free to obey the stale one — an executor deaf inside a long subprocess resumes and obeys whichever card it reads first. When the executor is subprocess-blocked, delivery is NOT a card it cannot read: the PL terminates the subprocess AT ORDER TIME — the termination IS the delivery — and posts the superseding card before the executor resumes.

Who rules, and how

Who may rule and how — the Triage Predicate (canonical text), the severity checklist, the closed five-option disposition menu, the HIGH-solo second look, and the circuit breaker — is in the pl core, §Decision discipline. Read them there before disposing of any card. The bands and lists of what the PL may decide alone, and what is owner-only, live in the decision-rights file (~/.config/sno/decision-rights.md; shipped default references/decision-rights.md in the pl skill); it wins over any text here. This file keeps only the mechanics around them — card handling, watching, take-over, verification time budget.

Live log watching — four tiers, four different questions

The four watch tiers sit beside the communication mechanisms; do not collapse them. Reach cards are the asynchronous record, the live agent seat is the instant channel (sno reach call), and sno reach ring is the wake. Reading a seat is one bounded sno reach watch <seat> --timeout 5, never a long or unbounded watch. Ordinary progress only streams and must never create a card. Only approval-waiting, idle and dead states may ring. Repeated repaint of the same state rings once. A ring only wakes the PL and never proves processing. A durable instant order is carded first and the window message names the exact Message-ID. An in-window owner ruling is written back to that thread. Outside the launch window, take another bounded read whenever COS requests a pinned watch or the PL needs direct progress evidence; otherwise the persistent log watch and the heartbeat-ring are the cruise posture.

A poll answers "alive or dead". It cannot answer "doing the right thing". Anything running longer than five minutes gets a live stream, not a poll; the poll demotes to a fallback whose only job is to guarantee you can still be reached. Keep the four tiers separate — each answers a different question, and a supervisor who merges them ends up with one mechanism that answers none of them:

TierThe question it answersMechanismCadence
0 · livenessis the process alive, is the log growingbash "${PL_SKILL_DIR}/scripts/roster.sh" for the fleet, bash "${PL_SKILL_DIR}/scripts/exec-state.sh" --callsign <name> for one agentfallback only, ~20 min
1 · event streamdid something happen I would act onpersistent log-watch.sh (below) on the executor log, armed at spawncontinuous, push
2 · orientation readis it pointed at the right tree, branch, filesone bounded sno reach watch <seat> --timeout 5 on the retained address, plus you reading the log UNFILTEREDT+5 and T+10, then stop
3 · convergenceis it getting closercards with numbers, commits, bash "${PL_SKILL_DIR}/scripts/convergence-watch.sh"30 min / on card

"Alive" is not a state, and a pid check cannot produce one. The pane's shell answers a liveness ping forever, and it is never the runtime — an executor stopped by a stop signal before drawing a character still reports health to every such check. Read the roster, and the per-agent state when one agent is in question (commands in the table). What the four loud answers mean, and what you do about each:

  • `STOPPED` / `stopped` — the runtime is halted by a stop signal (SIGSTOP) and **will not resume on its

own**. Not a slow agent. Attach to the pane, then relaunch; nothing you send it will arrive.

  • `unknown` on a Claude executor — this instrument cannot read that runtime (its

background helpers make it look busy forever, and its turn record never reads as closed). Read the pane yourself; do not treat it as idle and do not treat it as working.

  • `runtime-mismatch` — the spawn record and the process in the pane are different things. The

record is stale, or the pane is not the executor it names. Check which agent actually holds that callsign before sending it anything.

  • `ambiguous-runtime` — two processes in one pane answer to the same name, so nothing can say

which is the executor. Usually two agents sharing a window: separate them.

Tier 2 is the highest-value ten minutes of the run, and it is a different method — not a denser tier 1. That window is when an executor picks its checkout, its branch and its target files, and reads or fails to read its charter. A wrong pick is one sentence to correct at T+5 and a lost run at T+6h. No filter can do this job: one tuned for failure markers stays perfectly silent through a flawless run in the wrong directory. Confirm four things by name — which checkout, which branch, which files it opened, and whether its first actions match the charter's first instruction.

An executor log is not an event stream

Five kinds of line interleave, and only the last is a fact about the world:

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/sno-ai/sno-station-skills/pl-watch/badge)](https://verified-skill.com/skills/sno-ai/sno-station-skills/pl-watch)

Something wrong with this skill or its page? Tell us.