Skip to content
Back to skills

Moai Lane Watchdog

ASecurity

One lane stall watchdog iteration: measure lane progress on three channels, classify the stall cause, apply the remedy or resolve the judgment through the decision ladder — instead of waiting on a reply — then record the outcome and report. Reads the unified --auto doctrine at .claude/rules/moai/workflow/auto-semantics.md for the ladder, the gate inventory, and the record formats.

  • 1,228 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 5, 2026
ai-agentsgoshellbashgitapi

Works with

  • claude code
  • api
  • mcp

Security analysis

A100/100

Scanned October 5, 2026

npx -y skills add modu-ai/moai-adk --skill moai-lane-watchdog --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Moai Lane Watchdog?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Moai Lane Watchdog
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/modu-ai-moai-lane-watchdog/badge)](https://www.skillsdirectory.com/skills/modu-ai-moai-lane-watchdog)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: moai-lane-watchdog
description: >
  One lane stall watchdog iteration: measure lane progress on three
  channels, classify the stall cause, apply the remedy or resolve the
  judgment through the decision ladder — instead of waiting on a reply —
  then record the outcome and report. Reads the unified --auto doctrine at
  .claude/rules/moai/workflow/auto-semantics.md for the ladder, the gate
  inventory, and the record formats.
when_to_use: >
  Use when a loop iteration re-awakens a lane session (the awaken rule: the
  watchdog pass runs BEFORE card work resumes), when a lane shows no
  progress across the watch window, or when a lane needs a judgment to
  proceed and no reply has arrived.
license: Apache-2.0
compatibility: Designed for Claude Code and Codex sessions
allowed-tools: Read, Grep, Glob, Bash(git rev-parse:*), Bash(git status:*), Bash(git log:*), Bash(stat:*), Bash(ls:*), Bash(test:*), Bash(moai integration status:*)
user-invocable: false
metadata:
  version: "1.0.0"
  category: "workflow"
  status: "active"
  tags: "watchdog, stall, lane, ladder, decision-ladder, unattended, auto"

# MoAI Extension: Progressive Disclosure
progressive_disclosure:
  enabled: true
---

# Lane Stall Watchdog — One Iteration

One watchdog pass for a lane session (a factory lane running
under `moai cc` / `moai glm` / `moai codex`). The law — the ladder, the
outcome transitions, the gate inventory, the view–SSOT rule, the record
formats — lives in `.claude/rules/moai/workflow/auto-semantics.md`. Read
that doctrine before the first pass and whenever a step below needs its
detail; this body is the executable procedure.

## 0. Never prompt

The watchdog never asks the operator a question and never answers an
approval gate on anyone's behalf. Everything that would have been a question
becomes either a resolved judgment (the ladder) or an explicit wait record.
A keep-set gate — environment-impossible, operator-held, or an irreversible
external-shared operation — is never satisfied here: the recheck reads the
gate surface, and finding no change, it re-records the wait and yields.

## 1. Measure progress

Three channels (doctrine §3–4):

- **HEAD**: `git rev-parse --short HEAD` in the lane's own worktree.
- **evidence mtimes**: the newest mtime across `.moai/reports/<card-id>/`
  and the active SPEC's `progress.md`.
- **integration-window state**: `moai integration status`.

Compare against the previous snapshot at
`.moai/state/watchdog/<card-id>.json` (fields: `observed_at`, `head_sha`,
`evidence_mtime_max`, `window_state`). The lane is stalled only when ALL
THREE channels are unchanged AND the previous observation is at least N
minutes old. N defaults to 15 minutes and is a per-invocation parameter —
never a config key. No previous snapshot → record a fresh one, no stall
verdict (fail-open first observation). One channel moving is progress —
evidence mtime advancing without a commit included: end the iteration with
a one-line status — unless the lane itself is parked on a delegate (§3.5):
then the movement is the delegate's, and the deliverable read in §3.5
decides, not this rule. Write the new snapshot after the verdict.

## 2. Classify the cause

| Cause | Signature |
|---|---|
| **awaited-judgment** | the lane stopped where a judgment was needed (a gate, a verdict, a choice) and no reply arrived |
| **blocked-by** | the card waits on a predecessor card; the predecessor's landing state is the open question |
| **shell-error** | the lane halted on an unadjudicated command failure (a non-zero exit with no recorded disposition) |
| **accidental-stop** | the session died or was interrupted mid-card — an API error (a 429) ends the turn with no further model action — and no deliberate stop was recorded |
| **awaited-delegate** | the lane parked on delegated work — a spawned agent's report, a background run's completion — and the report or notice has not arrived; an `available` idle notice that promised a later report counts, because that agent sends nothing more unless it is messaged |

No stall / progress detected → end the iteration.

## 3. Apply the remedy

### 3.1 awaited-judgment — the decision ladder

Resolve through the ladder IN ORDER (doctrine §6–7). Availability failures
fail-open downward; negative or inconclusive verdicts never auto-proceed,
and at an authority gate they fail closed.

1. **Disk evidence** — read the deciding artifact directly: audit verdict
   files, the card's progress record, plan-audit verdicts, evidence paths.
   Evidence shows proceed → resume. Evidence shows do-not-proceed → record
   the wait; never proceed against evidence. Unreadable or absent → step 2.
2. **Decision board** — run `moai decision read --scope card:<id>` (the
   card's rulings plus every standing ruling; doctrine §11: the append-only
   board under the moai home, keyed by the project). A recorded judgment →
   follow it. A judgment that says wait → explicit wait record (with an id;
   doctrine §14). A record whose `resolves` names an open wait ends that
   wait. `board=absent` / `board=empty` → step 3; never wait on the board
   being filled. While a wait on the leader stays open, keep the one-shot
   short recheck of doctrine §14 armed.
3. **Audit cross** — run one `moai` MCP audit tool (`codex_audit`,
   `glm_audit`, `claude_audit`, or `audit_multi`) for an independent second
   opinion. Positive → proceed per verdict. Negative → fail-closed: no
   proceed; record + escalate to step 5. Tool absent → step 4. Inconclusive
   → record it, → step 4.
4. **jev_ask** — only while `workflow.jev.enabled` is true; a bounded
   proceed / retry / wait judgment with repeatable, side-effect-free
   parameters; never for completion, merge, or queue outcomes. Gated off or
   unavailable → step 5 (fail-open by design).
5. **Lead chat** — last resort. Record the explicit wait (§5 below), then
   yield.

Write a decision record naming whichever step resolved the judgment (§5
below).

### 3.2 blocked-by

Read the blocking predecessor's on-disk evidence directly (its
`.moai/reports/<card-id>/` path, its progress record). Evidence shows the
predecessor landed → resume. Otherwise record an explicit wait: reason +
predecessor id + recheck point. Where the predecessor was dropped, the wait
record names the queue relation-removal verb as the operator escape — the
lane does NOT run it (queue mutation is prohibited). The queue-level pickup
filter is another surface's decision; this remedy only reads.

### 3.3 shell-error

Adjudicate the error: transient (network blip, lock contention, flaky
timing) vs determinate (missing remote, bad ref, usage error).

- transient → retry at most 3 times, recording the error and the retry
  count each time; retries exhausted → structured blocker report.
- determinate → ZERO retries; straight to a structured blocker report with
  the verbatim error text.

Never halt indefinitely on an unadjudicated error; never loop silently.

### 3.4 accidental-stop

Resume by checkpoint return: use the session-handoff resume message with the
worktree-anchored Block 0 (`git rev-parse --show-toplevel` → this worktree),
resuming from the last recorded checkpoint in the card's progress record.
Never restart the card from zero.

### 3.5 awaited-delegate

Read the delegate's deliverable on disk — the artifacts it was asked to write,
its output file, its commits — against the delegation record (what was asked,
where it was to land). Never read the absence of its message as the absence of
its work.

- Deliverable present and consistent with the delegation → resume and consume
  it; never wait for the report or the notice. An agent that went `available`
  sends nothing more unless it is messaged, so the report may never come.
- Deliverable absent or partial and the delegate evidently ended (its idle or
  completion notice arrived, or its process is gone) → re-delegate with the
  partial state, or resume the delegate with `SendMessage` only while it is a
  live teammate. Never address a teammate stopped with `TaskStop` by name — one
  message revives it as an ownerless writer
  (`cross-session-messaging.md` § Rules). Record which.
- Deliverable absent and the evidence still moving (the delegate is working) →
  explicit wait whose recheck point is the next cron fire.
- Deliverable absent, no sign the delegate ended, and the evidence unchanged
  across two consecutive fires → structured blocker naming the delegate, what
  was asked of it, and the evidence read; do not wait a third time.

## 4. Decision board protocol

- **SSOT**: the disk board (doctrine §11). Append-only, one record per
  line; never rewrite board history.
- **Views**: render state with the runner's native task tool — TaskCreate /
  TaskUpdate on the Claude runner, `update_plan` on codex — and read
  judgments ONLY from disk. A view is never the SSOT; a long-form plan
  document is never the board.
- **Codex step ⑤**: no session-messaging tool exists there — cross-harness
  notice rides the broker (`session_msg_register` / `session_msg_send` +
  poll) and the queue-on-disk delegation channel; the wait reason is
  recorded on disk either way.

## 5. Decision records

Every autonomous gate transition and every ladder-resolved judgment writes
ONE grep-able line on the disk board:

```text
decision record: decided_by=<runner+role> evidence_refs=<paths+verdict-ids> ladder_path=<step>
```

`decided_by` names the deciding runner and role; `evidence_refs` names the
artifact paths and verdict ids the decision rests on; `ladder_path` names
the ladder step (①–⑤) or the gate row that resolved it. The sync audit
re-reads these records — write them so a stranger can re-verify.

## 6. Composition boundary

The queue-level pickup decision — the pickup filter that excludes unrelated
or blocked cards before a pick — belongs to the queue surface's owner. This
watchdog is queue-readonly: it reads evidence and state surfaces, performs
zero queue mutation, and never picks, drops, edits, or unrelates anything.

## 7. Output shape — escalate or record

Every iteration ends in exactly one of:

- **resumed** — progress detected or a judgment resolved; say which step,
  and cite the decision record line.
- **explicit wait** — the wait record line and its recheck point, nothing
  more; end the iteration (no idle-spin).
- **structured blocker** — determinate failure or retries exhausted: the
  verbatim error, what was attempted, the evidence read, and the decision
  owed. Return it to the orchestrating session; do not retry past the
  ceiling; do not prompt anyone.

## Boundaries (hard)

1. Never prompt the operator; never answer an approval gate. Keep-set gates
   (environment-impossible, operator-held, irreversible external-shared
   operations) are rechecked and yielded to, never satisfied by this skill.
2. Queue read-only (§6).
3. One writer per tree: the watchdog writes only its own snapshot, its own
   evidence records, and the disk board.
4. Verification is lane-local; no background load.
5. Hook-independent: awaken-tick only; no hook surface. The scheduler that
   fires the awaken is the lane's standing recheck cron (doctrine §5.1), armed
   at card intake — this skill is its prompt, not its owner.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.