Skip to content
Back to skills

Safety Monitor

ASecurity

Calibrated verifier that scores an autonomous loop's output for risk (fabricated references, unsupported claims) before it ships, quarantining flagged artifacts for review instead of blocking the loop. Use when wiring a new autonomous/background loop, reviewing quarantined items, or asked about the safety/drift monitor.

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 16, 2026
ai-agentspythongobashtestinggit

Security analysis

A100/100

Pro scans all 14 files and shows the line behind each finding

Scanned October 16, 2026

npx -y skills add G-Eskayo/marvin --skill safety-monitor --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Safety Monitor?

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

Security grade badge for Safety Monitor
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/g-eskayo-safety-monitor/badge)](https://www.skillsdirectory.com/skills/g-eskayo-safety-monitor)

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: safety-monitor
description: Calibrated verifier that scores an autonomous loop's output for risk (fabricated references, unsupported claims) before it ships, quarantining flagged artifacts for review instead of blocking the loop. Use when wiring a new autonomous/background loop, reviewing quarantined items, or asked about the safety/drift monitor.
tags: [intent:safety, intent:quality, intent:monitor, type:library]
---

# Safety Monitor

**Phase 1 only** (see `DESIGN.md` for the full rollout plan). This covers
pure-generation loops — scoring an artifact's text against a loop-specific
rubric and quarantining it if it looks risky. The dual-channel drift audit
(`otr_log.py`, `drift_report.py`) described in `ARCHITECTURE.md` is **not
built yet** — don't reference those scripts as if they exist.

## What this actually does

`verify.py` sends an artifact + a loop-specific rubric to a cheap model
(haiku) and gets back a risk score in [0, 1]. `calibrate.py` picks the
threshold (tau) that decides pass vs. quarantine — a conservative default
(0.3) until at least 20 labeled examples exist for that loop, then a
risk-controlled threshold computed from real approve/deny labels. Anything
over tau lands in `~/.claude/quarantine.md` instead of shipping silently.

This is a **library**, not a cron job — `verify.py` and `calibrate.py` are
meant to be called synchronously from inside an existing loop script, right
before it writes its output. Nothing runs on a schedule yet.

## Scripts

| Script | Purpose |
|--------|---------|
| `scripts/verify.py` | `verify(text, loop_name) -> float` risk score; `quarantine(...)` writes a flagged item; `pass_or_quarantine(text, loop_name) -> bool` is the one-line integration point |
| `scripts/calibrate.py` | `get_tau(loop_name) -> float`; `calibrate(...)` recomputes tau from labeled data; `record_label(loop_name, score, label)` for when a review workflow exists to call it |
| `scripts/rubrics/daily_digest.md` | Rubric for `improve/scripts/daily_digest.py`'s output |
| `scripts/rubrics/research_colony.md` | Rubric for `research-colony/scripts/research_digest.py`'s output |
| `scripts/rubrics/self_improve.md` | Rubric for the retrospective-log.md line `background_review.py` appends |
| `scripts/rubrics/improvement_sweep.md` | Rubric for `improvement_sweep.py`'s queue entries — checks extraction coherence (tag/message/path mismatch), not hallucination, since this loop has no LLM call |

A rubric must exist for a loop before `verify()` can score it — `verify()`
raises (and fails open, returning 0.0 / "pass") if `rubrics/<loop_name>.md`
is missing. Add a new rubric before wiring a new loop in.

## Output files

- `~/.claude/quarantine.md` — human review queue; same approve/modify/deny
  convention as `improvement-queue.md`. No `/quarantine` review command
  exists yet — items are reviewed by reading and editing the file directly.
- `~/.claude/safety-monitor/tau.json` — per-loop threshold, created lazily.
- `~/.claude/safety-monitor/calibration.jsonl` — labeled `{loop, score,
  label}` rows, created lazily by `record_label()`. Empty until a review
  workflow starts calling it — `calibrate()` uses `DEFAULT_TAU` (0.3) until
  then.

## Integration status

All four loops from `SOURCES.md` are wired in:

- `background_review.py` (self_improve) — wired first, since it's the
  highest-blast-radius one (writes directly to the git-tracked, append-only
  `retrospective-log.md`). Verification is post-hoc: snapshot the log before
  the review runs, diff after, score the new line(s), revert the append +
  quarantine if flagged.
- `daily_digest.py` and `research_digest.py` — wrapped the same way as each
  other: `pass_or_quarantine(content, loop_name="...")` right before the
  write; on `False`, a short quarantine notice is written in place of the
  real content so the day's output file still exists (no retry-loop burning
  a fresh `claude` call on every re-run) but is clearly marked incomplete.
- `improvement_sweep.py` — same `pass_or_quarantine()` wrap, but this loop
  has no LLM call at all (its content is a deterministic regex/sort over a
  static-analysis scan), so `rubrics/improvement_sweep.md` checks extraction
  coherence (a `[KIND]` tag mismatched with its message, a garbled fragment,
  a malformed path) rather than hallucination. On quarantine, the block is
  simply not appended — no stub needed, since the next handoff produces a
  fresh (different) block rather than re-running the same one.

## Manual invocation / smoke test

```bash
# Score arbitrary text against a rubric
echo "some artifact text" | ~/.agents/venv/bin/python \
  ~/.agents/skills/safety-monitor/scripts/verify.py daily_digest

# Check/recompute a loop's threshold
~/.agents/venv/bin/python ~/.agents/skills/safety-monitor/scripts/calibrate.py daily_digest

# Show the quarantine queue
cat ~/.claude/quarantine.md
```

## Triggers

- "wire safety-monitor into X", "review quarantine", "show quarantine queue"
- Session start: if `~/.claude/quarantine.md` exists with unresolved items, mention the count (not yet wired into the session-start checklist — see below)

## Known gotchas

- `verify()`'s subagent call is `--tools ""` plus an explicit "you have no
  tool access" line in the prompt — both are load-bearing, not either alone.
  A rubric that asks "does this reference something that doesn't exist"
  invites haiku to go check by exploring the filesystem even when
  `source_context` already has what it needs, which measured 113s vs ~50-58s
  and blew through the old 60s timeout. See `retrospective.md` (2026-07-13)
  and the inline comment in `scripts/verify.py`. Keep this in mind for any
  new rubric-based subagent call, not just this one.

## Known gaps (tracked, not silently assumed fixed)

- Session-start check for `quarantine.md` is described in `REQUIREMENTS.md`
  (FR6) but not yet added to `~/.claude/CLAUDE.md`'s checklist.
- No `/quarantine` review command yet — `record_label()` exists but nothing
  calls it, so `calibrate()` will sit on `DEFAULT_TAU` indefinitely until
  one is built. Expect over-flagging until then — confirmed in testing that
  even a well-constructed, genuinely generalizable retrospective-log entry
  scored above tau; that's the documented cold-start conservatism, not a bug,
  but it's a real cost until real labels exist.
- OTR/drift audit (`otr_log.py`, `drift_report.py`) still not built — Phase 3.

Files in this skill

  • ARCHITECTURE.md7.2 KB
  • DESIGN.md5.5 KB
  • REQUIREMENTS.md5.4 KB
  • SKILL.md6.3 KB
  • SOURCES.md3 KB
  • retrospective.md1.5 KB
  • scripts/calibrate.py3.5 KB
  • scripts/process_quarantine_reviews.py4.6 KB
  • scripts/rubrics/daily_digest.md1.8 KB
  • scripts/rubrics/improvement_sweep.md1.7 KB
  • scripts/rubrics/research_colony.md1.7 KB
  • scripts/rubrics/self_improve.md2 KB
  • scripts/tests/test_verify.py3.6 KB
  • scripts/verify.py8 KB

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.