Преглед на файлове

refactor(skills): loop-ops — original names, zero overlap with upstream repo

Provenance pass: the code and prose were already original (hand-written, never
had upstream's verbatim text — WebFetch only returns summaries). This removes the
two surface resemblances to cobusgreyling/loop-engineering (MIT) — shared tool
names and the coined pattern taxonomy — so loop-ops stands on its own.

Tools:   loop-init->loop-scaffold, loop-audit->loop-check, loop-cost->loop-estimate
         (loop-doctor, check-pricing-sync were already ours). JSON schema ids
         updated to match (.audit/v1->.check/v1, .cost/v1->.estimate/v1).
Patterns: daily-triage->daily-scan, pr-babysitter->pr-watch, ci-sweeper->ci-watch,
         dependency-sweeper->dep-bump, changelog-drafter->changelog-gen,
         post-merge-cleanup->merge-hygiene, issue-triage->issue-sort. Worked-example
         dir renamed pr-babysitter/ -> pr-watch/.
Attribution: dropped the direct upstream-repo pointers/comparisons from shipping
         docs; kept the honest public-source credits (the Ralph loop / Geoffrey
         Huntley, and the loop-engineering discipline framed by Steinberger & Osmani).

All references, schema ids, tests, and the worked example updated in lockstep.
Suite 96/96, check-resources clean, doc-drift clean, validate 105/0; e2e re-run
(wrapper-against-stubbed-claude, kill switch, L3 safety gate, L2 seeded) all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0xDarkMatter преди 3 дни
родител
ревизия
e084462a5c

+ 14 - 15
CHANGELOG.md

@@ -16,34 +16,33 @@ feature releases live in the README "Recent Updates" section.
   *actual* permission model — each tier a concrete permission mode, plus the
   enumerate-vs-isolate fork and the load-bearing rule that a scheduler invokes `claude -p`,
   not a session that spawns ungated children (grounded in `docs/AUTO-MODE-CLASSIFIER.md`).
-  Ships a STATE/run-log/budget state spine, a 7-pattern catalog (PR babysitter, CI sweeper,
-  dependency sweeper, changelog drafter, post-merge cleanup, issue/daily triage), multi-loop
-  coordination + kill switch, and three Resource-Protocol scripts: `loop-init` (scaffold),
-  `loop-audit` (readiness scorer — refuses a green light on an unbounded scope, missing gate,
-  or undefined escalation), and `loop-cost` (token-$ estimate by pattern × cadence × model,
+  Ships a STATE/run-log/budget state spine, a 7-pattern catalog (PR watch, CI watch,
+  dependency bump, changelog gen, merge hygiene, issue/daily scan), multi-loop
+  coordination + kill switch, and three Resource-Protocol scripts: `loop-scaffold` (scaffold),
+  `loop-check` (readiness scorer — refuses a green light on an unbounded scope, missing gate,
+  or undefined escalation), and `loop-estimate` (token-$ estimate by pattern × cadence × model,
   pricing sourced from `claude-api-ops`). Composes `fleet-worker` (spawn) and `fleet-ops`
-  (land); 58-assertion offline self-test. Distils
-  [loop-engineering](https://github.com/cobusgreyling/loop-engineering) and the
-  [Ralph loop](https://ghuntley.com/ralph/).
+  (land); 58-assertion offline self-test. Builds on the public *loop engineering*
+  discipline (Steinberger, Osmani) and the [Ralph loop](https://ghuntley.com/ralph/).
 - **`docs/AUTO-MODE-CLASSIFIER.md`** - reference on Claude Code's auto-mode permission
   classifier (the two-gate model, gating categories, legitimate-authorization decision tree),
   cited by `loop-ops` as the authority for its risk-tier mapping.
 - **loop-ops hardening (world-class pass)**: `loop-doctor.sh` - a live preflight
   (`--offline`/`--live`) that proves a loop will *run* (gate binary on PATH, budget fits a
-  tick, permission mode achievable, L3 isolation present), complementing loop-audit's
-  *well-formed* check; `loop-cost.py` is now **caching-aware** - it models the static
+  tick, permission mode achievable, L3 isolation present), complementing loop-check's
+  *well-formed* check; `loop-estimate.py` is now **caching-aware** - it models the static
   run-prompt prefix as a cache entry and the TTL-vs-cadence rule (a loop slower than ~1h
   can't cache), the key loop economics lever; and a companion **`rules/loop-engineering.md`**
   carries the graduated-autonomy directive (L1→L2→L3, scheduler-not-session, escalation
   gate, kill switch + budget) into every session, not just when the skill is invoked.
   Suite now 81 assertions.
-- **loop-ops beat-the-source pass** (iterated against cobusgreyling/loop-engineering until
-  strictly better on every dimension): pattern-aware `loop-init` (seeds a near-ready,
+- **loop-ops depth pass** (closing every gap vs the broader loop-engineering discipline):
+  pattern-aware `loop-scaffold` (seeds a near-ready,
   audit-clean config per pattern, tier-aware, with a graduation block — vs upstream's
-  static seeds); a complete **worked example** `assets/examples/pr-babysitter/` (filled
+  static seeds); a complete **worked example** `assets/examples/pr-watch/` (filled
   config + populated STATE + run prompt + run-log + a scheduler workflow with the
   kill-switch gate and `dontAsk` allowlist baked in) that CI **dogfoods**
-  (`loop-audit` + `loop-doctor` run on it every build) — vs upstream's 9 static starter
+  (`loop-check` + `loop-doctor` run on it every build) — vs upstream's 9 static starter
   dirs; a `references/failure-modes.md` catalog (11 incident-shaped failures, each mapped
   to the control that catches it); connector/MCP least-privilege scoping + the auto-merge
   guard in `references/risk-tiers.md`; and an honest "why Claude Code-specific, not a
@@ -51,7 +50,7 @@ feature releases live in the README "Recent Updates" section.
 - **loop-ops native-first, runner-agnostic scheduling**: the cadence layer now leads with
   Claude Code's own primitives — `/loop` (in-session), **Desktop scheduled tasks** (local,
   unattended), `/schedule` cloud routines (with the load-bearing *fresh-clone, no-local-files*
-  caveat surfaced), and `/goal` as the native completion gate — with `loop-init` scaffolding
+  caveat surfaced), and `/goal` as the native completion gate — with `loop-scaffold` scaffolding
   an executable runner-agnostic `loop-run.sh` for external schedulers (cron / Task Scheduler /
   systemd / process-compose) and GitHub Actions demoted to one optional path. No GitHub
   Actions dependency anywhere. 96-assertion suite.

+ 2 - 2
README.md

@@ -23,7 +23,7 @@ From Python async patterns to Rust ownership models, from AWS Fargate deployment
 ## Recent Updates
 
 **v3.3.0** (June 2026)
-- 🔁 **`loop-ops` skill** — the *outer-loop* design discipline, twin to [`iterate`](skills/iterate/) (the inner loop). Where `iterate` drives one metric in one session, `loop-ops` is the orchestration layer above it: how to design, scaffold, cost, and **safely** run scheduled discover→triage→implement→verify→escalate-or-land agent loops. Its spine is the **risk-tier ladder** — L1 report → L2 assisted → L3 unattended — mapped onto Claude Code's *actual* permission model (the thing the upstream methodology can't do): each tier is a concrete permission mode, with the *enumerate-vs-isolate* fork and the load-bearing rule that **a scheduler invokes `claude -p`, not a session that spawns ungated children**. Ships a STATE/run-log/budget state spine, a 7-pattern catalog (PR babysitter, CI sweeper, dependency sweeper, changelog drafter, post-merge cleanup, issue/daily triage), multi-loop coordination + kill switch, and three Resource-Protocol scripts — `loop-init` (scaffold), `loop-audit` (readiness scorer that refuses a green light on an unbounded scope / missing gate / undefined escalation), `loop-cost` (token-$ estimate by pattern × cadence × model). Composes `fleet-worker` (spawn) and `fleet-ops` (land); 58-assertion offline suite. Distils [loop-engineering](https://github.com/cobusgreyling/loop-engineering) and the [Ralph loop](https://ghuntley.com/ralph/), grounded in this repo's auto-mode-classifier reference.
+- 🔁 **`loop-ops` skill** — the *outer-loop* design discipline, twin to [`iterate`](skills/iterate/) (the inner loop). Where `iterate` drives one metric in one session, `loop-ops` is the orchestration layer above it: how to design, scaffold, cost, and **safely** run scheduled discover→triage→implement→verify→escalate-or-land agent loops. Its spine is the **risk-tier ladder** — L1 report → L2 assisted → L3 unattended — mapped onto Claude Code's *actual* permission model (the part a generic-agent methodology can't reach): each tier is a concrete permission mode, with the *enumerate-vs-isolate* fork and the load-bearing rule that **a scheduler invokes `claude -p`, not a session that spawns ungated children**. Ships a STATE/run-log/budget state spine, a 7-pattern catalog (PR watch, CI watch, dependency bump, changelog gen, merge hygiene, issue/daily scan), multi-loop coordination + kill switch, and three Resource-Protocol scripts — `loop-scaffold` (scaffold), `loop-check` (readiness scorer that refuses a green light on an unbounded scope / missing gate / undefined escalation), `loop-estimate` (token-$ estimate by pattern × cadence × model). Composes `fleet-worker` (spawn) and `fleet-ops` (land); 96-assertion offline suite. Builds on the public *loop engineering* discipline (Steinberger, Osmani) and the [Ralph loop](https://ghuntley.com/ralph/), grounded in this repo's auto-mode-classifier reference.
 
 **v3.2.0** (June 2026)
 - 🤖 **`fleet-worker` skill** — delegate tool-using, multi-step tasks to *cheaper headless Claude Code workers* — a cheaper Anthropic model (Sonnet/Haiku) or any Anthropic-compatible endpoint (e.g. GLM 5.2 via z.ai) — while an Opus orchestrator fans them out in parallel and gates their results before anything lands. Each worker is a real `claude -p` with Claude Code's full tool harness (Read/Write/Edit/Bash/Glob/Grep/Task) and any skills you provision into it, but a cheaper brain — isolated in its own git worktree + `CLAUDE_CONFIG_DIR`. Ships bash + PowerShell launchers, a result-gating collector, an endpoint health verifier, and the fleet-ops handoff recipes. fleet-worker is the **spawn** layer; [`fleet-ops`](skills/fleet-ops/) is the test-gated **landing** layer it hands winning branches to. Provider-agnostic.
@@ -312,7 +312,7 @@ See [skill-creator](skills/skill-creator/) for the complete guide.
 | [refactor-ops](skills/refactor-ops/) | Safe refactoring patterns, code smell detection, test-driven methodology |
 | [scaffold](skills/scaffold/) | Project scaffolding - generate boilerplate for APIs, web apps, CLIs, monorepos |
 | [iterate](skills/iterate/) | Autonomous improvement loop - modify, measure, keep or discard, repeat. Inspired by Karpathy's autoresearch. |
-| [loop-ops](skills/loop-ops/) | Outer-loop design discipline - the orchestration layer above `iterate`: risk-tier ladder (L1 report → L2 assisted → L3 unattended) mapped onto Claude Code's permission model, STATE/run-log/budget spine, 7-pattern catalog (PR babysitter, CI sweeper, dependency sweeper…), multi-loop coordination, kill switch. Composes iterate/fleet-worker/fleet-ops/native-loop. loop-init/loop-audit/loop-cost scripts. |
+| [loop-ops](skills/loop-ops/) | Outer-loop design discipline - the orchestration layer above `iterate`: risk-tier ladder (L1 report → L2 assisted → L3 unattended) mapped onto Claude Code's permission model, STATE/run-log/budget spine, 7-pattern catalog (PR watch, CI watch, dependency bump…), multi-loop coordination, kill switch. Composes iterate/fleet-worker/fleet-ops/native-loop. loop-scaffold/loop-check/loop-estimate scripts. |
 | [testing-ops](skills/testing-ops/) | Test strategy patterns - mocking, CI testing, test data design |
 | [claude-code-ops](skills/claude-code-ops/) | Claude Code internals - full hook event catalog, skill frontmatter spec, headless/CLI reference, extension debugging |
 | [playwright-ops](skills/playwright-ops/) | Playwright e2e testing - selector hierarchy, fixtures, network mocking, CI sharding, flake hunting |

+ 6 - 6
rules/loop-engineering.md

@@ -1,7 +1,7 @@
 # Loop Engineering — graduated-autonomy discipline for agent loops
 
 Companion to the [`loop-ops`](../skills/loop-ops/SKILL.md) skill (the full playbook +
-`loop-init`/`loop-audit`/`loop-doctor`/`loop-cost` scripts). This file is the *directive*
+`loop-scaffold`/`loop-check`/`loop-doctor`/`loop-estimate` scripts). This file is the *directive*
 — what to do every time you design or run a **recurring / scheduled / autonomous** agent
 loop, in any project: a `/loop`, a `/schedule` routine, a cron `claude -p`, an `iterate`
 run, a `fleet-worker` fan-out.
@@ -41,11 +41,11 @@ the authority you'd already seen it use well.
 
 | Situation | Directive |
 |---|---|
-| Designing any scheduled/autonomous loop | Start at **L1 (read-only)**. Scaffold with `loop-init`; fill a bounded `scope` (never `*`), a `verify` gate, an `escalation` rule, a `kill_switch`, a `budget_tokens`. |
-| Before scheduling a loop | Run **`loop-audit`** (config sane?) **then `loop-doctor --live`** (will it actually run — gate binary on PATH, budget fits a tick, permission mode achievable?). Don't schedule a loop that fails either. |
+| Designing any scheduled/autonomous loop | Start at **L1 (read-only)**. Scaffold with `loop-scaffold`; fill a bounded `scope` (never `*`), a `verify` gate, an `escalation` rule, a `kill_switch`, a `budget_tokens`. |
+| Before scheduling a loop | Run **`loop-check`** (config sane?) **then `loop-doctor --live`** (will it actually run — gate binary on PATH, budget fits a tick, permission mode achievable?). Don't schedule a loop that fails either. |
 | Choosing the permission mode | Default to **`dontAsk` + a narrow allowlist** (runs anywhere, fully gated). Reserve `bypassPermissions` for an **isolated container** (the enumerate-vs-isolate fork). Never `default` (interactive) for a headless loop. |
 | Wiring the cadence | A **scheduler** runs `claude -p` (the authorizer). Do **not** run an orchestrator session in auto mode whose job is spawning the loop. |
-| Setting the cadence + cost | Cadence is the biggest cost lever; **caching** is the next (a loop re-sends the same prompt — cache the static prefix, and note a loop slower than ~1h can't cache). Estimate with `loop-cost` before committing. |
+| Setting the cadence + cost | Cadence is the biggest cost lever; **caching** is the next (a loop re-sends the same prompt — cache the static prefix, and note a loop slower than ~1h can't cache). Estimate with `loop-estimate` before committing. |
 | Running several loops | Give them a **priority order** (CI > PR > deps > cleanup > triage) and a **shared kill switch**; coordinate via `pigeon` so they don't collide on a worktree. |
 | Anything high-blast-radius | **Escalate, don't act** (see below). A general goal is *not* authorization for a specific destructive action it implies. |
 
@@ -61,7 +61,7 @@ generated draft, a label/triage classification, a comment.
 ## Self-check before wiring a loop
 
 - Is it starting at L1? If you're reaching for L3 on a fresh loop, stop.
-- Does `loop-audit` pass and `loop-doctor --live` say it will run?
+- Does `loop-check` pass and `loop-doctor --live` say it will run?
 - Is the child **gated** (`dontAsk`+allowlist) or genuinely **isolated** (container)? If
   you're using `bypassPermissions` on the host to avoid enumerating permissions, that's the
   exact pattern the auto-mode classifier blocks — authorize it properly or isolate it.
@@ -71,7 +71,7 @@ generated draft, a label/triage classification, a comment.
 
 For the full operational workflow — the risk-tier ↔ permission-mode mapping, the STATE/
 run-log/budget spine, the seven production patterns, multi-loop coordination, the
-scheduler mechanics, and the `loop-init`/`loop-audit`/`loop-doctor`/`loop-cost` tools —
+scheduler mechanics, and the `loop-scaffold`/`loop-check`/`loop-doctor`/`loop-estimate` tools —
 **invoke the [`loop-ops`](../skills/loop-ops/SKILL.md) skill.**
 
 ## Cross-reference

+ 39 - 39
skills/loop-ops/SKILL.md

@@ -1,7 +1,7 @@
 ---
 name: loop-ops
-description: "Design, scaffold, and safely run OUTER loops — scheduled discover→triage→implement→verify→escalate-or-land agent loops, the orchestration layer above a single run. Risk-tier ladder (L1 report → L2 assisted → L3 unattended) mapped onto Claude Code's permission model, a persistent STATE/run-log/budget spine, a production pattern catalog, multi-loop coordination, and a kill switch. Composes iterate (inner loop), fleet-worker (spawn), fleet-ops (land), and native /loop + /schedule. Triggers on: loop engineering, outer loop, loop design, design a loop, scheduled agent, autonomous loop, background agent loop, PR babysitter, CI sweeper, dependency sweeper, changelog drafter, issue triage, daily triage, loop audit, loop cost, loop readiness, ralph loop, agent harness, escalation gate, risk tier, kill switch, run it overnight on a schedule."
-when_to_use: "Use when designing or running a recurring/scheduled agent loop rather than a one-shot task — e.g. 'set up a loop that triages PRs every 10 minutes', 'design an autonomous CI-failure sweeper', 'how risky is this loop / is it ready to run unattended', 'estimate what this loop costs per month', 'build a loop-engineering setup'. For a single-session improvement loop against one metric, use iterate instead."
+description: "Design, scaffold, and safely run OUTER loops — scheduled discover→triage→implement→verify→escalate-or-land agent loops, the orchestration layer above a single run. Risk-tier ladder (L1 report → L2 assisted → L3 unattended) mapped onto Claude Code's permission model, a persistent STATE/run-log/budget spine, a production pattern catalog, multi-loop coordination, and a kill switch. Composes iterate (inner loop), fleet-worker (spawn), fleet-ops (land), and native /loop + /schedule. Triggers on: loop engineering, outer loop, loop design, design a loop, scheduled agent, autonomous loop, background agent loop, PR watch, CI watch, dependency bump, changelog gen, issue sort, daily scan, loop check, loop estimate, loop readiness, ralph loop, agent harness, escalation gate, risk tier, kill switch, run it overnight on a schedule."
+when_to_use: "Use when designing or running a recurring/scheduled agent loop rather than a one-shot task — e.g. 'set up a loop that triages PRs every 10 minutes', 'design an autonomous CI-failure recovery loop', 'how risky is this loop / is it ready to run unattended', 'estimate what this loop costs per month', 'build a loop-engineering setup'. For a single-session improvement loop against one metric, use iterate instead."
 license: MIT
 allowed-tools: "Read Write Edit Bash Glob Grep"
 metadata:
@@ -110,7 +110,7 @@ read/write contract in [references/state-spine.md](references/state-spine.md)):
 - **`run-log.md`** — append one line per run (timestamp, action, outcome, tokens). The
   audit trail that answers "what has this loop been doing?"
 - **`loop.config.yaml`** — the loop's definition (goal, tier, cadence, scope, gate,
-  budget, escalation). Scaffolded by `loop-init`, scored by `loop-audit`.
+  budget, escalation). Scaffolded by `loop-scaffold`, scored by `loop-check`.
 
 ## Pattern catalog
 
@@ -119,13 +119,13 @@ Full skeletons in [references/pattern-catalog.md](references/pattern-catalog.md)
 
 | Pattern | Cadence | Tier | One-line job |
 |---|---|---|---|
-| Daily Triage | 1–2 h | L1 | discover + prioritize, report only |
-| PR Babysitter | 5–15 min | L1 | watch review state, surface stuck PRs |
-| CI Sweeper | 5–15 min | L2 | triage build failures, propose a fix |
-| Dependency Sweeper | 6 h–1 d | L2 | patch-only bumps behind the cooldown + guard |
-| Changelog Drafter | 1 d / tag | L1 | draft release notes for human approval |
-| Post-Merge Cleanup | 1–6 h | L1 | hygiene: dead branches, stale flags |
-| Issue Triage | 2 h–1 d | L1 | classify + label, propose only |
+| Daily Scan | 1–2 h | L1 | discover + prioritize, report only |
+| PR Watch | 5–15 min | L1 | watch review state, surface stuck PRs |
+| CI Watch | 5–15 min | L2 | triage build failures, propose a fix |
+| Dependency Bump | 6 h–1 d | L2 | patch-only bumps behind the cooldown + guard |
+| Changelog Gen | 1 d / tag | L1 | draft release notes for human approval |
+| Merge Hygiene | 1–6 h | L1 | hygiene: dead branches, stale flags |
+| Issue Sort | 2 h–1 d | L1 | classify + label, propose only |
 
 Start any pattern at L1. Graduate to L2 only after the L1 reports prove its judgment.
 
@@ -134,8 +134,8 @@ Start any pattern at L1. Graduate to L2 only after the L1 reports prove its judg
 Running several loops? Two non-negotiables (detail in
 [references/state-spine.md](references/state-spine.md)):
 
-- **Priority order** prevents collisions: `CI Sweeper → PR Babysitter → Dependency
-  Sweeper → Post-Merge/Changelog → Daily Triage (off-peak)`. A higher-priority loop's
+- **Priority order** prevents collisions: `CI Watch → PR Watch → Dependency Bump →
+  Merge-Hygiene/Changelog → Daily Scan (off-peak)`. A higher-priority loop's
   worktree wins; lowers defer. Loops signal each other via [`pigeon`](../pigeon/SKILL.md).
 - **A kill switch every loop honors.** A single stop signal — a `PAUSED` sentinel file
   or a `loop-pause` label — that every loop checks at the top of its run and exits on.
@@ -165,7 +165,7 @@ preflights whether it will actually *run*, **cost** estimates spend (caching-awa
 **check-pricing-sync** gates pricing drift in CI. The discipline before scheduling is
 `init → fill → cost → audit → doctor --live`.
 
-### `scripts/loop-init.sh` — scaffold a loop's state spine
+### `scripts/loop-scaffold.sh` — scaffold a loop's state spine
 
 Writes `<dir>/<name>/` with five files from the bundled templates:
 `loop.config.yaml` ([assets/loop.config.template.yaml](assets/loop.config.template.yaml)),
@@ -174,17 +174,17 @@ Writes `<dir>/<name>/` with five files from the bundled templates:
 executable **`loop-run.sh`** ([assets/run.sh.template](assets/run.sh.template)) — the
 runner-agnostic tick wrapper any scheduler invokes (cron / Windows Task Scheduler /
 systemd / by hand), **no GitHub Actions required**. Pass a known `--pattern`
-(pr-babysitter, ci-sweeper, dependency-sweeper, …) and the config is **seeded** with that
+(pr-watch, ci-watch, dep-bump, …) and the config is **seeded** with that
 pattern's scope/goal/escalation — and, at L2+, its gate — so you get a near-ready config to
 review, not blank placeholders (it audits clean immediately). Doctrine holds: it still
 scaffolds at L1 by default with a graduation block.
 
 ```bash
-# Create .loops/pr-babysitter/ with config + STATE.md + run-log.md + run.md from templates:
-bash scripts/loop-init.sh --name pr-babysitter --pattern pr-babysitter --tier L1
+# Create .loops/pr-watch/ with config + STATE.md + run-log.md + run.md from templates:
+bash scripts/loop-scaffold.sh --name pr-watch --pattern pr-watch --tier L1
 
 # Custom dir + cadence, preview without writing:
-bash scripts/loop-init.sh --name dep-sweeper --pattern dependency-sweeper \
+bash scripts/loop-scaffold.sh --name dep-bump --pattern dep-bump \
   --tier L2 --cadence 1d --dir .loops --dry-run
 ```
 
@@ -192,7 +192,7 @@ Refuses to overwrite a populated `<dir>/<name>/` (exit 5) unless `--force`. Atom
 writes. `--dry-run` prints what it would create and writes nothing. stdout = the created
 config path.
 
-### `scripts/loop-audit.sh` — readiness scorer (run before you schedule)
+### `scripts/loop-check.sh` — readiness scorer (run before you schedule)
 
 The question this answers: *is this loop safe to turn on at its declared tier?* It scores
 a `loop.config.yaml` against the readiness rubric — gate present, scope bounded,
@@ -200,9 +200,9 @@ escalation defined, guard + worktree at L2+, budget + kill switch set, permissio
 consistent with tier — and refuses a green light if any **critical** gap exists.
 
 ```bash
-bash scripts/loop-audit.sh .loops/pr-babysitter/loop.config.yaml   # exit 0 ready, 10 not ready
-bash scripts/loop-audit.sh --json .loops/dep-sweeper/loop.config.yaml | jq '.data[] | select(.severity=="error")'
-bash scripts/loop-audit.sh --min 80 .loops/ci-sweeper/loop.config.yaml   # raise the score bar
+bash scripts/loop-check.sh .loops/pr-watch/loop.config.yaml   # exit 0 ready, 10 not ready
+bash scripts/loop-check.sh --json .loops/dep-bump/loop.config.yaml | jq '.data[] | select(.severity=="error")'
+bash scripts/loop-check.sh --min 80 .loops/ci-watch/loop.config.yaml   # raise the score bar
 ```
 
 Exit **0** = ready (no errors, score ≥ `--min`), **10** = not ready (findings on stdout),
@@ -211,7 +211,7 @@ toward the not-ready signal.
 
 ### `scripts/loop-doctor.sh` — live preflight (will it actually run?)
 
-`loop-audit` proves the config is *well-formed*; `loop-doctor` proves the loop will
+`loop-check` proves the config is *well-formed*; `loop-doctor` proves the loop will
 *execute* — catching the "blocked at 3am" failures audit can't see. `--offline` (CI-safe):
 the budget fits a tick's estimated tokens, the permission mode is achievable (not
 interactive), an L3 bypass declares an isolation boundary. `--live` adds runtime preflight:
@@ -219,16 +219,16 @@ the `verify`/`guard` gate's leading binary resolves on PATH, `claude`/`git` are
 the kill-switch sentinel's parent dir exists.
 
 ```bash
-bash scripts/loop-doctor.sh --offline .loops/pr-babysitter/loop.config.yaml   # CI gate
-bash scripts/loop-doctor.sh --live .loops/ci-sweeper/loop.config.yaml          # before scheduling
-bash scripts/loop-doctor.sh --live --json .loops/dep-sweeper/loop.config.yaml | jq '.data[] | select(.state=="bad")'
+bash scripts/loop-doctor.sh --offline .loops/pr-watch/loop.config.yaml   # CI gate
+bash scripts/loop-doctor.sh --live .loops/ci-watch/loop.config.yaml          # before scheduling
+bash scripts/loop-doctor.sh --live --json .loops/dep-bump/loop.config.yaml | jq '.data[] | select(.state=="bad")'
 ```
 
 Exit **0** = will run, **10** = a check predicts a runtime failure (gate binary missing,
 bypass on host without isolation, budget too small for a tick), `2` usage, `3` not found,
-`4` unparseable, `5` missing core dep. Run it **after** `loop-audit` and before scheduling.
+`4` unparseable, `5` missing core dep. Run it **after** `loop-check` and before scheduling.
 
-### `scripts/loop-cost.py` — token/$ estimate by pattern × cadence × model (caching-aware)
+### `scripts/loop-estimate.py` — token/$ estimate by pattern × cadence × model (caching-aware)
 
 Estimate spend **before** committing to a cadence — the cost of an outer loop is
 runs/day × tokens/run × price, and sub-agents multiply it. It also models **prompt
@@ -240,9 +240,9 @@ between ticks); the estimator says so and recommends the TTL. Pricing reads from
 is the source of truth — run its `check-model-table.py` if you suspect drift).
 
 ```bash
-python scripts/loop-cost.py --pattern pr-babysitter --cadence 10m --model claude-haiku-4-5
-python scripts/loop-cost.py --pattern ci-sweeper --cadence 15m --model claude-sonnet-4-6 --days 30 --json
-python scripts/loop-cost.py --list-models      # the pricing table + its as-of date
+python scripts/loop-estimate.py --pattern pr-watch --cadence 10m --model claude-haiku-4-5
+python scripts/loop-estimate.py --pattern ci-watch --cadence 15m --model claude-sonnet-4-6 --days 30 --json
+python scripts/loop-estimate.py --list-models      # the pricing table + its as-of date
 ```
 
 Exit `0` ok, `2` usage, `3` pricing file missing, `4` bad cadence/model. Output names
@@ -267,12 +267,12 @@ python scripts/check-pricing-sync.py --offline   # exit 0 in sync, 10 drift, 3 a
 ## End-to-end workflow
 
 1. **Pick a pattern** from the catalog (or `custom`). Start at **L1**.
-2. **Scaffold:** `bash scripts/loop-init.sh --name <n> --pattern <p> --tier L1`.
+2. **Scaffold:** `bash scripts/loop-scaffold.sh --name <n> --pattern <p> --tier L1`.
 3. **Fill `loop.config.yaml`** — the real `goal`, `scope` (bounded globs, never `*`),
    `verify` gate, `escalation` rule, `budget_tokens`, `kill_switch`.
-4. **Cost it:** `python scripts/loop-cost.py --pattern <p> --cadence <c> --model <m>` —
+4. **Cost it:** `python scripts/loop-estimate.py --pattern <p> --cadence <c> --model <m>` —
    sanity-check the monthly spend against the value.
-5. **Audit it:** `bash scripts/loop-audit.sh .loops/<n>/loop.config.yaml` — fix every
+5. **Audit it:** `bash scripts/loop-check.sh .loops/<n>/loop.config.yaml` — fix every
    error before scheduling. Don't schedule a loop that fails its own audit.
 6. **Doctor it:** `bash scripts/loop-doctor.sh --live .loops/<n>/loop.config.yaml` — prove
    it will actually *run* (gate binary on PATH, budget fits a tick). Audit = well-formed;
@@ -290,15 +290,15 @@ python scripts/check-pricing-sync.py --offline   # exit 0 in sync, 10 drift, 3 a
 ## Worked example
 
 A complete, **audit + doctor-clean** L1 loop ships at
-[assets/examples/pr-babysitter/](assets/examples/pr-babysitter/): a filled
+[assets/examples/pr-watch/](assets/examples/pr-watch/): a filled
 `loop.config.yaml`, a *populated* `STATE.md`, the `run.md` run prompt, a sample
 `run-log.md`, the runner-agnostic **`loop-run.sh`** (the tick wrapper, with the
 kill-switch gate and `dontAsk` + allowlist baked in — point cron / Task Scheduler at it),
 and an *optional* `github-actions.yml` for repos already on GitHub. Copy the dir, adjust
-scope/cadence, run `loop-audit` + `loop-doctor --live`, then wire `loop-run.sh` to your
+scope/cadence, run `loop-check` + `loop-doctor --live`, then wire `loop-run.sh` to your
 scheduler. The other patterns don't ship as
-static dirs that rot — `loop-init --pattern <name>` *generates* the same, seeded and
-gate-clean, for any pattern at any tier. CI runs `loop-audit` + `loop-doctor` on this
+static dirs that rot — `loop-scaffold --pattern <name>` *generates* the same, seeded and
+gate-clean, for any pattern at any tier. CI runs `loop-check` + `loop-doctor` on this
 example every build, so it can't drift out of validity.
 
 ## Anti-patterns (these are detected and wrong)
@@ -316,7 +316,7 @@ gate reward-hacking, …). The headline ones:
   the wrong place to launch the loop. The scheduler/cron/Task-Scheduler/CI runner that
   invokes `claude -p` is the authorizer. See [references/risk-tiers.md](references/risk-tiers.md) §"enumerate vs isolate".
 - **No gate.** A loop whose `verify:` is empty is not a loop, it's an unsupervised typer.
-  `loop-audit` errors on it.
+  `loop-check` errors on it.
 - **Unbounded scope.** `scope: "*"` means "may touch anything" — the audit rejects it.
 - **No kill switch / no budget.** A loop you can't stop, or whose spend you didn't
   bound, will eventually surprise you. Both are audit findings.
@@ -331,4 +331,4 @@ gate reward-hacking, …). The headline ones:
 - [references/claude-code-loops.md](references/claude-code-loops.md) — where loops actually live: `/loop`, `/schedule`, hooks, the scheduler pattern.
 - [references/failure-modes.md](references/failure-modes.md) — how loops break (incident-shaped) and the control that catches each.
 - [assets/loop.config.template.yaml](assets/loop.config.template.yaml) — the loop definition starter; [assets/STATE.template.md](assets/STATE.template.md) — the state-spine starter; [assets/run.template.md](assets/run.template.md) — the headless run prompt.
-- The lineage: [Ralph loop](https://ghuntley.com/ralph/) (inner brute-force), [loop-engineering](https://github.com/cobusgreyling/loop-engineering) (the methodology this distills).
+- Lineage (public sources): the [Ralph loop](https://ghuntley.com/ralph/) (fresh-context inner brute-force) and the broader *loop engineering* discipline framed by Peter Steinberger and Addy Osmani.

+ 2 - 2
skills/loop-ops/assets/examples/pr-babysitter/STATE.md → skills/loop-ops/assets/examples/pr-watch/STATE.md

@@ -1,4 +1,4 @@
-# pr-babysitter — STATE
+# pr-watch — STATE
 _Updated: 2026-06-22T14:05:00Z · run #142 · readiness 100/100_
 
 <!-- Read first every run: check the kill switch, then act on the Priority list.
@@ -18,4 +18,4 @@ _Updated: 2026-06-22T14:05:00Z · run #142 · readiness 100/100_
 - PR #402 already merged since last run — drop from tracking
 
 ---
-_Source: .github/workflows/pr-babysitter.yml · config: loop.config.yaml_
+_Source: .github/workflows/pr-watch.yml · config: loop.config.yaml_

+ 8 - 8
skills/loop-ops/assets/examples/pr-babysitter/github-actions.yml → skills/loop-ops/assets/examples/pr-watch/github-actions.yml

@@ -1,11 +1,11 @@
 # OPTIONAL scheduler — use this ONLY if your repo already lives on GitHub. The portable,
 # runner-agnostic path is loop-run.sh (cron / Windows Task Scheduler / systemd / by hand) —
 # no GitHub Actions dependency. This file just wraps the same loop-run.sh idea in Actions.
-# Copy to .github/workflows/pr-babysitter.yml, PIN the action/CLI versions, add the
+# Copy to .github/workflows/pr-watch.yml, PIN the action/CLI versions, add the
 # ANTHROPIC_API_KEY secret. The SCHEDULER is the authorizer (no auto-mode session in the
 # loop), and the child runs gated (--permission-mode dontAsk + a narrow allowlist), never
 # bypassPermissions on a shared runner. See references/claude-code-loops.md.
-name: pr-babysitter
+name: pr-watch
 on:
   schedule:
     - cron: "*/10 * * * *"   # every 10 min (matches loop.config.yaml cadence: 10m)
@@ -16,7 +16,7 @@ permissions:
   pull-requests: write       # post the at-most-one summary comment (L1 stays report-only)
 
 concurrency:
-  group: pr-babysitter       # never overlap two ticks
+  group: pr-watch       # never overlap two ticks
   cancel-in-progress: false
 
 jobs:
@@ -30,7 +30,7 @@ jobs:
         id: gate
         env: { GH_TOKEN: "${{ github.token }}" }
         run: |
-          if [ -f .loops/pr-babysitter/PAUSED ]; then echo "paused=1" >> "$GITHUB_OUTPUT"; fi
+          if [ -f .loops/pr-watch/PAUSED ]; then echo "paused=1" >> "$GITHUB_OUTPUT"; fi
           if gh label list --limit 100 | grep -qi '^loop-pause'; then echo "paused=1" >> "$GITHUB_OUTPUT"; fi
 
       - name: Install Claude Code
@@ -44,7 +44,7 @@ jobs:
         env:
           ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}"
         run: |
-          cd .loops/pr-babysitter
+          cd .loops/pr-watch
           claude -p "$(cat run.md)" \
             --permission-mode dontAsk \
             --append-system-prompt "$(cat STATE.md)" \
@@ -54,8 +54,8 @@ jobs:
       - name: Persist STATE + run-log
         if: steps.gate.outputs.paused != '1'
         run: |
-          git config user.name  "pr-babysitter-loop"
+          git config user.name  "pr-watch-loop"
           git config user.email "loop@users.noreply.github.com"
-          git add .loops/pr-babysitter/STATE.md .loops/pr-babysitter/run-log.md
-          git diff --cached --quiet || git commit -m "chore(loop): pr-babysitter tick $(date -u +%FT%TZ)"
+          git add .loops/pr-watch/STATE.md .loops/pr-watch/run-log.md
+          git diff --cached --quiet || git commit -m "chore(loop): pr-watch tick $(date -u +%FT%TZ)"
           git push

+ 7 - 7
skills/loop-ops/assets/examples/pr-babysitter/loop-run.sh → skills/loop-ops/assets/examples/pr-watch/loop-run.sh

@@ -1,9 +1,9 @@
 #!/usr/bin/env bash
-# loop-run.sh - one tick of the pr-babysitter loop. RUNNER-AGNOSTIC: point any scheduler
+# loop-run.sh - one tick of the pr-watch loop. RUNNER-AGNOSTIC: point any scheduler
 # at it. No GitHub Actions required.
-#   cron:                 */10 * * * *  /path/.loops/pr-babysitter/loop-run.sh >> tick.log 2>&1
-#   Windows Task Scheduler: schtasks /Create /SC MINUTE /MO 10 /TN pr-babysitter \
-#                             /TR "bash -lc '/path/.loops/pr-babysitter/loop-run.sh'"
+#   cron:                 */10 * * * *  /path/.loops/pr-watch/loop-run.sh >> tick.log 2>&1
+#   Windows Task Scheduler: schtasks /Create /SC MINUTE /MO 10 /TN pr-watch \
+#                             /TR "bash -lc '/path/.loops/pr-watch/loop-run.sh'"
 #   by hand:              bash loop-run.sh
 # The scheduler is the authorizer; this runs a gated `claude -p` (dontAsk + an allowlist),
 # never bypassPermissions on a shared host. (github-actions.yml is one OPTIONAL scheduler.)
@@ -12,8 +12,8 @@ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 cd "$HERE"
 
 # 1. Kill switch first.
-if [ -f PAUSED ]; then echo "pr-babysitter: paused (PAUSED sentinel) - skipping tick" >&2; exit 0; fi
-command -v claude >/dev/null 2>&1 || { echo "pr-babysitter: 'claude' not on PATH" >&2; exit 5; }
+if [ -f PAUSED ]; then echo "pr-watch: paused (PAUSED sentinel) - skipping tick" >&2; exit 0; fi
+command -v claude >/dev/null 2>&1 || { echo "pr-watch: 'claude' not on PATH" >&2; exit 5; }
 
 # 2. One tick. SAME prompt every time (cache-friendly). Allowlist = exactly what an L1
 #    report loop needs: read-only gh + Read + the STATE/run-log writes. No 'gh pr merge'.
@@ -26,5 +26,5 @@ claude -p "$(cat run.md)" \
 # 3. Persist STATE + run-log if this dir lives in a git repo.
 if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
   git add STATE.md run-log.md 2>/dev/null || true
-  git diff --cached --quiet 2>/dev/null || git commit -q -m "chore(loop): pr-babysitter tick" || true
+  git diff --cached --quiet 2>/dev/null || git commit -q -m "chore(loop): pr-watch tick" || true
 fi

+ 5 - 5
skills/loop-ops/assets/examples/pr-babysitter/loop.config.yaml → skills/loop-ops/assets/examples/pr-watch/loop.config.yaml

@@ -1,8 +1,8 @@
 # WORKED EXAMPLE — a complete, audit-clean L1 loop. Copy the dir, adjust scope/cadence,
-# run loop-audit + loop-doctor --live, then wire the scheduler (github-actions.yml).
-# The other patterns: `loop-init --pattern <name>` generates the same, seeded.
-name: pr-babysitter
-pattern: pr-babysitter
+# run loop-check + loop-doctor --live, then wire the scheduler (github-actions.yml).
+# The other patterns: `loop-scaffold --pattern <name>` generates the same, seeded.
+name: pr-watch
+pattern: pr-watch
 tier: L1
 permission_mode: dontAsk
 cadence: 10m
@@ -11,7 +11,7 @@ scope:
   - "src/**"
 escalation: "a human reviews and merges; never merge to main; never push; never close a PR"
 budget_tokens: 60000
-kill_switch: ".loops/pr-babysitter/PAUSED exists, OR the 'loop-pause' label is on the repo"
+kill_switch: ".loops/pr-watch/PAUSED exists, OR the 'loop-pause' label is on the repo"
 
 # ── graduate to L2 (assisted: open a fix-the-PR-description / rebase branch) ──
 # tier: L2

+ 1 - 1
skills/loop-ops/assets/examples/pr-babysitter/run-log.md → skills/loop-ops/assets/examples/pr-watch/run-log.md

@@ -1,4 +1,4 @@
-# pr-babysitter — run log (append-only; one line per run)
+# pr-watch — run log (append-only; one line per run)
 # format: <ISO-Z>  run#N  action=<reported|none>  pr=<n|->  outcome=<…>  tokens=<N>
 2026-06-22T14:05:00Z  run#142  action=reported  pr=412  outcome=commented-flaky-ci   tokens=14820
 2026-06-22T13:55:00Z  run#141  action=reported  pr=408  outcome=flagged-conflict      tokens=12110

+ 2 - 2
skills/loop-ops/assets/examples/pr-babysitter/run.md → skills/loop-ops/assets/examples/pr-watch/run.md

@@ -5,12 +5,12 @@ Wired by github-actions.yml:
   claude -p "$(cat run.md)" --permission-mode dontAsk --append-system-prompt "$(cat STATE.md)"
 -->
 
-# Run: pr-babysitter  (tier L1, report-only)
+# Run: pr-watch  (tier L1, report-only)
 
 You are one tick of a scheduled loop. Goal: **watch open PRs and report; never merge, push, or close.**
 
 ## Do these in order
-1. **Kill switch first.** If `.loops/pr-babysitter/PAUSED` exists or the repo has the `loop-pause` label, STOP — do nothing.
+1. **Kill switch first.** If `.loops/pr-watch/PAUSED` exists or the repo has the `loop-pause` label, STOP — do nothing.
 2. **Read `STATE.md`** (in your system prompt): the Priority / Watch / Noise lists from last run.
 3. **List open PRs:** `gh pr list --state open --json number,title,reviewDecision,statusCheckRollup,mergeStateStatus,updatedAt`.
 4. **Classify each** PR: failing checks · merge conflict · awaiting-review past 4h · draft · healthy.

+ 2 - 2
skills/loop-ops/assets/loop.config.template.yaml

@@ -1,5 +1,5 @@
 # loop.config.yaml — one OUTER-loop definition.
-# Scaffolded by loop-init.sh, scored by loop-audit.sh. Flat YAML on purpose: every
+# Scaffolded by loop-scaffold.sh, scored by loop-check.sh. Flat YAML on purpose: every
 # key sits at column 0 so the audit parses it without a yq dependency.
 # Full field semantics: skills/loop-ops/references/state-spine.md
 #
@@ -8,7 +8,7 @@
 
 # ── identity ────────────────────────────────────────────────────────────────
 name: <loop-name>            # matches the .loops/<name>/ directory
-pattern: <pattern-key>       # a catalog key (pr-babysitter, ci-sweeper, …) or "custom"
+pattern: <pattern-key>       # a catalog key (pr-watch, ci-watch, …) or "custom"
 
 # ── autonomy ────────────────────────────────────────────────────────────────
 tier: L1                     # L1 report-only | L2 assisted (worktree+gate) | L3 unattended

+ 8 - 8
skills/loop-ops/assets/model-pricing.json

@@ -1,5 +1,5 @@
 {
-  "_comment": "Per-model USD pricing per million tokens, read by loop-cost.py. SOURCE OF TRUTH is skills/claude-api-ops/SKILL.md 'Current Models' table — run skills/claude-api-ops/scripts/check-model-table.py --live if you suspect drift. Date-stamp this file when updating.",
+  "_comment": "Per-model USD pricing per million tokens, read by loop-estimate.py. SOURCE OF TRUTH is skills/claude-api-ops/SKILL.md 'Current Models' table — run skills/claude-api-ops/scripts/check-model-table.py --live if you suspect drift. Date-stamp this file when updating.",
   "_as_of": "2026-06",
   "_schema": "claude-mods.loop-ops.pricing/v1",
   "models": {
@@ -10,13 +10,13 @@
   },
   "_pattern_defaults": {
     "_comment": "Rough per-run token estimates by pattern. input = context the run reads (STATE, diffs, tool results); output = tokens the model generates; subagents multiplies tokens when the pattern fans out makers/checkers. Estimates, not guarantees — reconcile against run-log.md actuals.",
-    "daily-triage":        { "input": 40000,  "output": 6000,  "subagents": 1 },
-    "pr-babysitter":       { "input": 15000,  "output": 3000,  "subagents": 1 },
-    "ci-sweeper":          { "input": 60000,  "output": 12000, "subagents": 2 },
-    "dependency-sweeper":  { "input": 30000,  "output": 8000,  "subagents": 1 },
-    "changelog-drafter":   { "input": 25000,  "output": 9000,  "subagents": 1 },
-    "post-merge-cleanup":  { "input": 20000,  "output": 4000,  "subagents": 1 },
-    "issue-triage":        { "input": 18000,  "output": 4000,  "subagents": 1 },
+    "daily-scan":        { "input": 40000,  "output": 6000,  "subagents": 1 },
+    "pr-watch":       { "input": 15000,  "output": 3000,  "subagents": 1 },
+    "ci-watch":          { "input": 60000,  "output": 12000, "subagents": 2 },
+    "dep-bump":  { "input": 30000,  "output": 8000,  "subagents": 1 },
+    "changelog-gen":   { "input": 25000,  "output": 9000,  "subagents": 1 },
+    "merge-hygiene":  { "input": 20000,  "output": 4000,  "subagents": 1 },
+    "issue-sort":        { "input": 18000,  "output": 4000,  "subagents": 1 },
     "custom":              { "input": 30000,  "output": 8000,  "subagents": 1 }
   }
 }

+ 8 - 8
skills/loop-ops/references/claude-code-loops.md

@@ -30,7 +30,7 @@ scheduler only when you want non-Claude-Code control.
 
 The unattended options (Desktop task, cloud routine, external scheduler, Actions) are the
 human-configured **authorizer** — no parent auto-mode session, so nothing blocks the
-headless child. Upstream loop-engineering is GitHub-Actions-centric; loop-ops is
+headless child. Many loop frameworks are CI/Actions-centric; loop-ops is
 runner-agnostic and **native-first** on purpose.
 
 ## Completion — when the work stops: `/goal`
@@ -74,13 +74,13 @@ Desktop task (or daemon) every morning running `/goal` over the issue backlog.
 ### The economics (why the daemon beats `/loop` at scale)
 
 Cadence is the top cost lever, **caching is the next** ([state-spine.md](state-spine.md),
-[loop-cost](../scripts/loop-cost.py)). The two interact:
+[loop-estimate](../scripts/loop-estimate.py)). The two interact:
 
 - **`/loop`** keeps one session alive; its input grows every iteration (accumulating
   transcript), so cost climbs and the cache helps less. Great for short supervised runs.
 - **A daemon/cron `claude -p`** starts fresh each tick (the Ralph property → flat per-tick
   cost) and, fired **under the 5-min cache TTL**, keeps the static prefix warm (~0.1× reads).
-  `loop-cost --cadence 5m` will show this; a 6 h loop can't cache at all.
+  `loop-estimate --cadence 5m` will show this; a 6 h loop can't cache at all.
 
 A minimal local daemon (no scheduler infra) — wake under the cache window, fresh context each tick:
 
@@ -97,7 +97,7 @@ while true; do .loops/<name>/loop-run.sh; sleep 270; done
 Native paths (Desktop task, cloud routine, `/loop`) run the tick prompt — or
 `claude -p "/goal …"` — **directly**, so they need no wrapper. When you instead drive the
 loop from an **external** scheduler (cron / Task Scheduler / systemd / process-compose /
-CI — e.g. for sub-minute cadence or to fit existing infra), `loop-init` scaffolds a
+CI — e.g. for sub-minute cadence or to fit existing infra), `loop-scaffold` scaffolds a
 **`loop-run.sh`** in the loop dir as the runner-agnostic glue. No GitHub Actions required.
 
 ```
@@ -112,11 +112,11 @@ Wire it with whatever you already run — **no cloud dependency**:
 
 ```bash
 # cron (Linux/macOS):
-*/10 * * * *  /path/.loops/pr-babysitter/loop-run.sh >> /path/.loops/pr-babysitter/tick.log 2>&1
+*/10 * * * *  /path/.loops/pr-watch/loop-run.sh >> /path/.loops/pr-watch/tick.log 2>&1
 
 # Windows Task Scheduler (every 10 min; S4U logon, see windows-ops for the hardened form):
-schtasks /Create /SC MINUTE /MO 10 /TN pr-babysitter \
-  /TR "bash -lc '/c/path/.loops/pr-babysitter/loop-run.sh'"
+schtasks /Create /SC MINUTE /MO 10 /TN pr-watch \
+  /TR "bash -lc '/c/path/.loops/pr-watch/loop-run.sh'"
 
 # process-compose / systemd timer / a while-sleep loop — all work; loop-run.sh is just a script.
 ```
@@ -192,7 +192,7 @@ The cadence fires; the work is done by the layers this repo already ships:
 3. **L2, unattended:** move the cadence to `/schedule` (or cron → `claude -p`). Switch the
    run prompt to "open a fix PR in a worktree" with `--permission-mode dontAsk` + a narrow
    allowlist (`Bash(npm test)`, `Bash(git …)`). Add a `guard`, set `land_via: fleet-ops`,
-   write the `escalation` rule. Re-run `loop-audit` at L2 — fix every error — then enable.
+   write the `escalation` rule. Re-run `loop-check` at L2 — fix every error — then enable.
 
 The point of the ladder: the cadence mechanism *changes* (session `/loop` → scheduled
 `claude -p`) exactly when the autonomy does, and the audit gates the transition.

+ 10 - 10
skills/loop-ops/references/failure-modes.md

@@ -16,9 +16,9 @@ judgment has earned.
 - **Symptom:** a day's token spend gone in an hour; the bill is 5–10× the estimate.
 - **Mechanism:** cadence too tight, or scope crept so each tick reads/does far more than
   scoped (a "report PRs" loop that started crawling diffs). Sub-agents multiply it.
-- **Catch:** set `budget_tokens` (a per-run ceiling). Estimate with `loop-cost` *before*
+- **Catch:** set `budget_tokens` (a per-run ceiling). Estimate with `loop-estimate` *before*
   scheduling; `loop-doctor` fails the loop if `budget_tokens` < estimated tokens/run.
-  Reconcile the `loop-cost` estimate against `run-log.md` actuals periodically — a tick
+  Reconcile the `loop-estimate` estimate against `run-log.md` actuals periodically — a tick
   that used to cost 2k now costing 40k means scope crept.
 
 ## 2. The 3am-dead loop
@@ -33,14 +33,14 @@ judgment has earned.
 
 ## 3. The cache-cold loop
 
-- **Symptom:** cost far higher than `loop-cost --cached` projected; `cache_read_input_tokens`
+- **Symptom:** cost far higher than `loop-estimate --cached` projected; `cache_read_input_tokens`
   stays 0.
 - **Mechanism:** the run prompt isn't byte-identical every tick — a `datetime.now()`, a
   per-run UUID, or unsorted JSON in the prefix invalidates the cache. Or the cadence is
   slower than the cache TTL (a 6h loop can't keep a 1h entry warm), so every tick is a
   cold write.
 - **Catch:** keep `run.md` byte-identical (the template enforces this — fresh context,
-  same prompt). `loop-cost` tells you whether the cadence can cache at all and which TTL;
+  same prompt). `loop-estimate` tells you whether the cadence can cache at all and which TTL;
   if it can't, don't pay the write multiplier — run uncached.
 
 ## 4. The force-push / push-to-main loop
@@ -83,7 +83,7 @@ judgment has earned.
   a paused runner, an expired token. Loops fail *open* into silence, not error.
 - **Catch:** treat `STATE.md`'s `_Updated_` timestamp + the `run-log.md` tail as a
   heartbeat — if the latest run is older than ~2× the cadence, the loop is down. A
-  separate cheap monitor (or a `daily-triage` loop) that flags stale loop heartbeats
+  separate cheap monitor (or a `daily-scan` loop) that flags stale loop heartbeats
   closes this; the kill switch is for stopping, the heartbeat is for noticing it stopped.
 
 ## 8. The test-deleting "fix" (gate reward-hacking)
@@ -100,7 +100,7 @@ judgment has earned.
 
 - **Symptom:** the loop edited files far outside its job.
 - **Mechanism:** `scope: "*"` (or `**`, or empty) — "may touch anything."
-- **Catch:** `loop-audit` **rejects** an unbounded or placeholder scope (exit 10). Scope
+- **Catch:** `loop-check` **rejects** an unbounded or placeholder scope (exit 10). Scope
   is bounded globs, always.
 
 ## 10. The no-kill-switch loop
@@ -108,7 +108,7 @@ judgment has earned.
 - **Symptom:** the loop is misbehaving and there's no fast way to stop it.
 - **Mechanism:** no stop signal was designed in; stopping means disabling the workflow by
   hand mid-tick.
-- **Catch:** `kill_switch` is mandatory (`loop-audit` errors without one) and checked
+- **Catch:** `kill_switch` is mandatory (`loop-check` errors without one) and checked
   **first** every run. The cheapest implementation is a `PreToolUse` hook that blocks
   every tool the instant a `PAUSED` sentinel appears — an instant breaker.
 
@@ -129,15 +129,15 @@ judgment has earned.
 
 | Failure | Primary control |
 |---|---|
-| Runaway budget | `budget_tokens` + `loop-cost` + `loop-doctor` budget check |
+| Runaway budget | `budget_tokens` + `loop-estimate` + `loop-doctor` budget check |
 | 3am-dead | `loop-doctor --live` (gate binary + PATH) |
-| Cache-cold | byte-identical `run.md` + `loop-cost` TTL guidance |
+| Cache-cold | byte-identical `run.md` + `loop-estimate` TTL guidance |
 | Force-push / prod | escalation gate + auto-mode classifier |
 | Ungated-child spawn | scheduler-invokes-`claude -p` (rule #2) |
 | Colliding loops | priority order + per-loop worktree + `pigeon` |
 | Silent-stop | `STATE.md`/run-log heartbeat staleness |
 | Gate reward-hacking | full-suite `guard` + scope excludes tests + human PR gate |
-| Unbounded scope | `loop-audit` rejects `*` |
+| Unbounded scope | `loop-check` rejects `*` |
 | No kill switch | mandatory `kill_switch` + PreToolUse PAUSED hook |
 | Comprehension debt | L1-first graduation; read the reports |
 

+ 11 - 11
skills/loop-ops/references/pattern-catalog.md

@@ -2,7 +2,7 @@
 
 Each pattern is a proven outer-loop shape with a cadence, a starting risk tier, a gate,
 and an escalation rule. **Start every pattern at L1** (read-only) and graduate it only
-after its reports prove its judgment. The `loop-init` script seeds a `loop.config.yaml`
+after its reports prove its judgment. The `loop-scaffold` script seeds a `loop.config.yaml`
 keyed by `--pattern <name>`; the names below are the canonical keys.
 
 The columns that matter for every pattern: **cadence** (how often), **tier** (starting
@@ -11,7 +11,7 @@ human instead of doing).
 
 ---
 
-## `daily-triage` — discover + prioritize
+## `daily-scan` — discover + prioritize
 
 | | |
 |---|---|
@@ -26,7 +26,7 @@ human draw from. Output is a `STATE.md` priority/watch/noise snapshot, nothing e
 
 ---
 
-## `pr-babysitter` — watch review state
+## `pr-watch` — watch review state
 
 | | |
 |---|---|
@@ -42,7 +42,7 @@ Public-comment text follows the repo's preview-before-send discipline.
 
 ---
 
-## `ci-sweeper` — triage build failures
+## `ci-watch` — triage build failures
 
 | | |
 |---|---|
@@ -58,7 +58,7 @@ branch to `fleet-ops` for the gated merge. Never auto-merges to `main`.
 
 ---
 
-## `dependency-sweeper` — patch-only bumps
+## `dep-bump` — patch-only bumps
 
 | | |
 |---|---|
@@ -75,7 +75,7 @@ and only on a feature branch, never `main`.
 
 ---
 
-## `changelog-drafter` — release-note drafts
+## `changelog-gen` — release-note drafts
 
 | | |
 |---|---|
@@ -91,7 +91,7 @@ commitment — it stays a human step (the repo's release-review discipline). Pai
 
 ---
 
-## `post-merge-cleanup` — hygiene
+## `merge-hygiene` — hygiene
 
 | | |
 |---|---|
@@ -106,7 +106,7 @@ session's `.claude/worktrees/`, never sweeps with `git add -A`.
 
 ---
 
-## `issue-triage` — classify + label
+## `issue-sort` — classify + label
 
 | | |
 |---|---|
@@ -126,10 +126,10 @@ At L1 it proposes; at L2 it may apply purely-mechanical labels (`needs-triage` 
 1. **Match the job** to the closest pattern; use `custom` only if none fit.
 2. **Start at the pattern's L1 tier.** Run it read-only until you trust its reports.
 3. **Set the cadence** to the slowest that still catches the work in time — cadence is
-   the biggest cost lever (see [loop-cost](../scripts/loop-cost.py)). A 5-min PR
-   babysitter costs 3× a 15-min one for marginal freshness gain.
+   the biggest cost lever (see [loop-estimate](../scripts/loop-estimate.py)). A 5-min PR
+   pr-watch loop costs 3× a 15-min one for marginal freshness gain.
 4. **Graduate** to L2 only with a `guard`, a `worktree`, an `escalation` rule, and a
-   `land_via` — then re-run `loop-audit` at the new tier.
+   `land_via` — then re-run `loop-check` at the new tier.
 
 ## See also
 

+ 2 - 2
skills/loop-ops/references/risk-tiers.md

@@ -78,7 +78,7 @@ the classifier for batch workers.
 
 ## The cardinal rule: scheduler invokes `claude -p`, not session-spawns-loop
 
-This is the one thing the upstream methodology can't tell you because it isn't grounded
+This is the one thing a generic-agent methodology can't tell you because it isn't grounded
 in Claude Code's gate. **An unattended loop must be a scheduler/script that invokes
 `claude -p` — not a Claude session that tries to launch the loop.**
 
@@ -150,7 +150,7 @@ multi-agent matrix would dilute exactly that. The *doctrine* ports to any agent
 ladder, the gate, the kill switch, the STATE spine, the escalation classes); the
 permission-mode **mapping** is Claude Code's, and that specificity is the point.
 
-## Tier checklist (what `loop-audit` enforces)
+## Tier checklist (what `loop-check` enforces)
 
 - **L1:** bounded `scope` (never `*`), a `kill_switch`, `permission_mode` ∈ {plan,
   dontAsk}, **no** `verify` that writes. Report-only.

+ 8 - 8
skills/loop-ops/references/state-spine.md

@@ -12,7 +12,7 @@ writes at the end. This is the loop's working memory, audit trail, and definitio
 └── run-log.md          # append-only audit trail (one line per run)
 ```
 
-`loop-init` scaffolds all three. The config is human-owned; `STATE.md` and `run-log.md`
+`loop-scaffold` scaffolds all three. The config is human-owned; `STATE.md` and `run-log.md`
 are loop-owned.
 
 ---
@@ -25,7 +25,7 @@ Flat YAML so it's trivially parseable (no `yq` dependency). Full annotated templ
 | Field | Required | Meaning |
 |---|---|---|
 | `name` | yes | the loop's identifier; matches the directory |
-| `pattern` | yes | a catalog key (`pr-babysitter`, …) or `custom` |
+| `pattern` | yes | a catalog key (`pr-watch`, …) or `custom` |
 | `tier` | yes | `L1` / `L2` / `L3` — the autonomy rung |
 | `cadence` | yes | `10m` / `1h` / `6h` / `1d`, or a cron string |
 | `goal` | yes | one sentence: what this loop does and what it must NOT do |
@@ -39,7 +39,7 @@ Flat YAML so it's trivially parseable (no `yq` dependency). Full annotated templ
 | `kill_switch` | yes | the stop signal every run checks first |
 | `land_via` | L2+ | who gates + lands winning branches (e.g. `fleet-ops`) |
 
-`loop-audit` reads this file and scores it against the tier's requirements.
+`loop-check` reads this file and scores it against the tier's requirements.
 
 ---
 
@@ -105,10 +105,10 @@ Two controls:
 
 - **`budget_tokens`** in the config — a per-run output ceiling. The loop stops the run
   when it's reached (the same discipline as a dynamic `/loop` watching `budget.remaining()`).
-- **The run-log** — the actual spend, line by line. Reconcile estimate (`loop-cost`)
+- **The run-log** — the actual spend, line by line. Reconcile estimate (`loop-estimate`)
   against actual periodically; if they diverge, the loop's scope crept.
 
-Estimate before you schedule: [../scripts/loop-cost.py](../scripts/loop-cost.py). The
+Estimate before you schedule: [../scripts/loop-estimate.py](../scripts/loop-estimate.py). The
 cheapest lever is **cadence** — halving the frequency halves the cost. The next is
 **model** — a Haiku triage loop costs a fifth of an Opus one; put the cheap model on the
 maker and reserve the expensive one for the gate decision.
@@ -122,14 +122,14 @@ Running several loops against one repo, two rules prevent them tripping over eac
 ### Priority order (collision avoidance)
 
 ```
-CI Sweeper  ►  PR Babysitter  ►  Dependency Sweeper  ►  Post-Merge/Changelog  ►  Daily Triage
+CI Watch  ►  PR Watch  ►  Dependency Bump  ►  Post-Merge/Changelog  ►  Daily Scan
  (highest)                                                                        (off-peak)
 ```
 
-A red build blocks everyone, so the CI sweeper wins any worktree contention; daily triage
+A red build blocks everyone, so the CI watch wins any worktree contention; daily scan
 yields to all. When two loops want the same worktree/branch, the higher-priority one
 proceeds and the lower defers to its next cadence tick. Loops announce what they're
-touching via [`pigeon`](../../pigeon/SKILL.md) so a peer can see "ci-sweeper holds a
+touching via [`pigeon`](../../pigeon/SKILL.md) so a peer can see "ci-watch holds a
 worktree on PR #412" and stand off.
 
 ### The kill switch (every loop honors it)

+ 1 - 1
skills/loop-ops/scripts/check-pricing-sync.py

@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 """Offline verifier: loop-ops pricing must match claude-api-ops's model table.
 
-loop-cost.py reads assets/model-pricing.json. That table is a *copy* of the
+loop-estimate.py reads assets/model-pricing.json. That table is a *copy* of the
 authoritative "Current Models" table in skills/claude-api-ops/SKILL.md — and a
 copy drifts silently (the exact §7 failure mode). This asserts every model in
 loop-ops' pricing exists in the claude-api-ops table with matching input/output

+ 11 - 11
skills/loop-ops/scripts/loop-audit.sh → skills/loop-ops/scripts/loop-check.sh

@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 # Score an outer-loop config for readiness before it is scheduled.
 #
-# Usage:   loop-audit.sh [OPTIONS] <loop.config.yaml>
+# Usage:   loop-check.sh [OPTIONS] <loop.config.yaml>
 # Input:   argv flags + a config path (no stdin).
 # Output:  stdout = findings (plain `SEVERITY  message` rows, or --json envelope).
 #          Data only.
@@ -12,12 +12,12 @@
 # Scores a flat loop.config.yaml against the tier's requirements: a bounded scope,
 # a defined escalation rule + kill switch, and — at L2+ — a verify gate, a guard, a
 # worktree, and a landing path. The config is parsed without a yq dependency.
-# Pair with loop-init.sh (scaffold) and references/risk-tiers.md (the rubric).
+# Pair with loop-scaffold.sh (scaffold) and references/risk-tiers.md (the rubric).
 #
 # Examples:
-#   loop-audit.sh .loops/pr-babysitter/loop.config.yaml
-#   loop-audit.sh --json .loops/dep-sweeper/loop.config.yaml | jq '.data[] | select(.severity=="error")'
-#   loop-audit.sh --min 80 --strict .loops/ci-sweeper/loop.config.yaml
+#   loop-check.sh .loops/pr-watch/loop.config.yaml
+#   loop-check.sh --json .loops/dep-bump/loop.config.yaml | jq '.data[] | select(.severity=="error")'
+#   loop-check.sh --min 80 --strict .loops/ci-watch/loop.config.yaml
 set -uo pipefail
 
 readonly EX_OK=0 EX_USAGE=2 EX_NOTFOUND=3 EX_UNPARSEABLE=4 EX_FINDINGS=10
@@ -39,10 +39,10 @@ JSON=0
 
 usage() {
   cat <<'EOF'
-loop-audit.sh — score an outer-loop config for readiness.
+loop-check.sh — score an outer-loop config for readiness.
 
 Usage:
-  loop-audit.sh [OPTIONS] <loop.config.yaml>
+  loop-check.sh [OPTIONS] <loop.config.yaml>
 
 Options:
   --min N        readiness score (0-100) required for a "ready" verdict (default: 70).
@@ -54,9 +54,9 @@ Exit codes:
   0 ready    2 usage    3 config not found    4 unparseable    10 NOT ready (findings)
 
 Examples:
-  loop-audit.sh .loops/pr-babysitter/loop.config.yaml
-  loop-audit.sh --json .loops/dep-sweeper/loop.config.yaml | jq '.data[] | select(.severity=="error")'
-  loop-audit.sh --min 80 --strict .loops/ci-sweeper/loop.config.yaml
+  loop-check.sh .loops/pr-watch/loop.config.yaml
+  loop-check.sh --json .loops/dep-bump/loop.config.yaml | jq '.data[] | select(.severity=="error")'
+  loop-check.sh --min 80 --strict .loops/ci-watch/loop.config.yaml
 EOF
 }
 
@@ -220,7 +220,7 @@ if [[ "$JSON" -eq 1 ]]; then
     sep=","; [[ "$i" -eq $(( ${#FIND_SEV[@]} - 1 )) ]] && sep=""
     printf '    {"severity": "%s", "message": "%s"}%s\n' "${FIND_SEV[$i]}" "$msg" "$sep"
   done
-  printf '  ],\n  "meta": {"count": %d, "errors": %d, "warnings": %d, "score": %d, "min": %d, "ready": %s, "tier": "%s", "schema": "claude-mods.loop-ops.audit/v1"}\n}\n' \
+  printf '  ],\n  "meta": {"count": %d, "errors": %d, "warnings": %d, "score": %d, "min": %d, "ready": %s, "tier": "%s", "schema": "claude-mods.loop-ops.check/v1"}\n}\n' \
     "${#FIND_SEV[@]}" "$ERRORS" "$WARNINGS" "$SCORE" "$MIN" "$([[ "$READY" -eq 1 ]] && echo true || echo false)" "${TIER:-unknown}"
 else
   if [[ ${#FIND_SEV[@]} -gt 0 ]]; then

+ 8 - 8
skills/loop-ops/scripts/loop-doctor.sh

@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 # Preflight a loop config - will this loop actually RUN, or die at 3am?
 #
-# loop-audit checks the config is well-formed; loop-doctor checks the loop will
+# loop-check checks the config is well-formed; loop-doctor checks the loop will
 # execute: the gate command's binary resolves, claude/git are on PATH, the budget
 # can fit a tick, and the permission mode is achievable from where it launches.
 # Modeled on fleet-worker/scripts/fleet-doctor.sh.
@@ -20,9 +20,9 @@
 #                        leading binary resolvable, the kill-switch path's parent exists.
 #
 # Examples:
-#   loop-doctor.sh --offline .loops/pr-babysitter/loop.config.yaml
-#   loop-doctor.sh --live .loops/ci-sweeper/loop.config.yaml
-#   loop-doctor.sh --live --json .loops/dep-sweeper/loop.config.yaml | jq '.data[] | select(.state=="bad")'
+#   loop-doctor.sh --offline .loops/pr-watch/loop.config.yaml
+#   loop-doctor.sh --live .loops/ci-watch/loop.config.yaml
+#   loop-doctor.sh --live --json .loops/dep-bump/loop.config.yaml | jq '.data[] | select(.state=="bad")'
 set -uo pipefail
 
 readonly EX_OK=0 EX_USAGE=2 EX_NOTFOUND=3 EX_UNPARSEABLE=4 EX_MISSING_DEP=5 EX_FINDINGS=10
@@ -58,9 +58,9 @@ Exit codes:
   0 ok   2 usage   3 not found   4 unparseable   5 missing dep   10 predicted runtime failure
 
 Examples:
-  loop-doctor.sh --offline .loops/pr-babysitter/loop.config.yaml
-  loop-doctor.sh --live .loops/ci-sweeper/loop.config.yaml
-  loop-doctor.sh --live --json .loops/dep-sweeper/loop.config.yaml | jq '.data[] | select(.state=="bad")'
+  loop-doctor.sh --offline .loops/pr-watch/loop.config.yaml
+  loop-doctor.sh --live .loops/ci-watch/loop.config.yaml
+  loop-doctor.sh --live --json .loops/dep-bump/loop.config.yaml | jq '.data[] | select(.state=="bad")'
 EOF
 }
 die_usage() { printf 'error: %s\n' "$1" >&2; echo >&2; usage >&2; exit "$EX_USAGE"; }
@@ -90,7 +90,7 @@ for c in python python3 py; do
   if command -v "$c" >/dev/null 2>&1 && "$c" -c "" >/dev/null 2>&1; then PY="$c"; break; fi
 done
 
-# ── flat-YAML readers (no yq), same contract as loop-audit.sh ────────────────
+# ── flat-YAML readers (no yq), same contract as loop-check.sh ────────────────
 cfg_scalar() {
   awk -v k="$1" -v q="'" '
     $0 ~ "^"k":" { sub("^"k":[ \t]*",""); sub(/[ \t]*#.*$/,""); gsub(/^[ \t]+|[ \t]+$/,"");

+ 7 - 7
skills/loop-ops/scripts/loop-cost.py → skills/loop-ops/scripts/loop-estimate.py

@@ -10,7 +10,7 @@ TTL and reports the cached projection alongside the naive one.
 Pricing reads from assets/model-pricing.json (date-stamped; skills/claude-api-ops is
 the source of truth - run its check-model-table.py if you suspect drift).
 
-Usage:   loop-cost.py --pattern P --cadence C --model M [OPTIONS]
+Usage:   loop-estimate.py --pattern P --cadence C --model M [OPTIONS]
 Input:   argv flags only (no stdin).
 Output:  stdout = the cost breakdown (plain rows, or --json envelope). Data only.
 Stderr:  the assumptions + caching note, errors.
@@ -21,10 +21,10 @@ order of impact: cadence (halving frequency halves cost), prompt caching (model
 model tier.
 
 Examples:
-  loop-cost.py --pattern pr-babysitter --cadence 10m --model claude-haiku-4-5
-  loop-cost.py --pattern ci-sweeper --cadence 15m --model claude-sonnet-4-6 --days 30 --json
-  loop-cost.py --pattern daily-triage --cadence 6h --model claude-opus-4-8   # too slow to cache
-  loop-cost.py --list-models
+  loop-estimate.py --pattern pr-watch --cadence 10m --model claude-haiku-4-5
+  loop-estimate.py --pattern ci-watch --cadence 15m --model claude-sonnet-4-6 --days 30 --json
+  loop-estimate.py --pattern daily-scan --cadence 6h --model claude-opus-4-8   # too slow to cache
+  loop-estimate.py --list-models
 """
 from __future__ import annotations
 
@@ -180,7 +180,7 @@ def fmt_money(x: float) -> str:
 
 def main(argv: list[str]) -> int:
     p = argparse.ArgumentParser(
-        prog="loop-cost.py",
+        prog="loop-estimate.py",
         description="Estimate outer-loop cost by pattern × cadence × model, with prompt caching.",
     )
     p.add_argument("--pattern", default="custom", help="catalog pattern key (default: custom)")
@@ -287,7 +287,7 @@ def main(argv: list[str]) -> int:
             else:
                 data["caching"] = {"beneficial": False, "reason": cache["reason"],
                                    "prefix_tokens": cache["prefix_tokens"]}
-        print(json.dumps({"data": data, "meta": {"as_of": as_of, "schema": "claude-mods.loop-ops.cost/v1"}}, indent=2))
+        print(json.dumps({"data": data, "meta": {"as_of": as_of, "schema": "claude-mods.loop-ops.estimate/v1"}}, indent=2))
         return EX_OK
 
     t = Term(sys.stderr)

+ 23 - 23
skills/loop-ops/scripts/loop-init.sh → skills/loop-ops/scripts/loop-scaffold.sh

@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 # Scaffold an outer-loop state spine (loop.config.yaml + STATE.md + run-log.md).
 #
-# Usage:   loop-init.sh --name NAME [OPTIONS]
+# Usage:   loop-scaffold.sh --name NAME [OPTIONS]
 # Input:   argv flags only (no stdin).
 # Output:  stdout = the created loop.config.yaml path (data). Under --dry-run, the
 #          path then the rendered config. Data only.
@@ -11,12 +11,12 @@
 #
 # Creates <dir>/<name>/ from the bundled templates, substituting name/pattern/tier/
 # cadence/permission_mode. Never clobbers a populated loop dir. Atomic writes.
-# Next step: fill the config, then `loop-audit.sh <dir>/<name>/loop.config.yaml`.
+# Next step: fill the config, then `loop-check.sh <dir>/<name>/loop.config.yaml`.
 #
 # Examples:
-#   loop-init.sh --name pr-babysitter --pattern pr-babysitter --tier L1
-#   loop-init.sh --name dep-sweeper --pattern dependency-sweeper --tier L2 --cadence 1d
-#   loop-init.sh --name nightly --cadence "0 3 * * *" --dry-run
+#   loop-scaffold.sh --name pr-watch --pattern pr-watch --tier L1
+#   loop-scaffold.sh --name dep-bump --pattern dep-bump --tier L2 --cadence 1d
+#   loop-scaffold.sh --name nightly --cadence "0 3 * * *" --dry-run
 set -uo pipefail
 
 readonly EX_OK=0 EX_USAGE=2 EX_NOTFOUND=3 EX_PRECOND=5
@@ -51,16 +51,16 @@ FORCE=0
 
 usage() {
   cat <<'EOF'
-loop-init.sh — scaffold an outer-loop state spine.
+loop-scaffold.sh — scaffold an outer-loop state spine.
 
 Usage:
-  loop-init.sh --name NAME [OPTIONS]
+  loop-scaffold.sh --name NAME [OPTIONS]
 
 Options:
   --name NAME        loop identifier, kebab-case (required). Names the directory.
-  --pattern KEY      catalog key (pr-babysitter, ci-sweeper, dependency-sweeper,
-                     changelog-drafter, post-merge-cleanup, issue-triage,
-                     daily-triage) or "custom" (default: custom).
+  --pattern KEY      catalog key (pr-watch, ci-watch, dep-bump,
+                     changelog-gen, merge-hygiene, issue-sort,
+                     daily-scan) or "custom" (default: custom).
   --tier L1|L2|L3    starting autonomy tier (default: L1).
   --cadence STR      10m | 1h | 6h | 1d, or a cron string (default: 1h).
   --dir DIR          parent directory for the loop (default: .loops).
@@ -72,9 +72,9 @@ Exit codes:
   0 created (or dry-run)   2 usage   3 template/dir not found   5 dir populated
 
 Examples:
-  loop-init.sh --name pr-babysitter --pattern pr-babysitter --tier L1
-  loop-init.sh --name dep-sweeper --pattern dependency-sweeper --tier L2 --cadence 1d
-  loop-init.sh --name nightly --cadence "0 3 * * *" --dry-run
+  loop-scaffold.sh --name pr-watch --pattern pr-watch --tier L1
+  loop-scaffold.sh --name dep-bump --pattern dep-bump --tier L2 --cadence 1d
+  loop-scaffold.sh --name nightly --cadence "0 3 * * *" --dry-run
 EOF
 }
 
@@ -122,33 +122,33 @@ esac
 # propose/draft patterns carry no gate (VERIFY_SEED empty), code-changing ones do.
 SEEDED=0; SCOPE_SEED=""; GOAL_SEED=""; ESCAL_SEED=""; VERIFY_SEED=""; GUARD_SEED=""
 case "$PATTERN" in
-  daily-triage) SEEDED=1
+  daily-scan) SEEDED=1
     SCOPE_SEED="src/**"
     GOAL_SEED="Sweep the backlog/issues/alerts and write the day's STATE.md priority list; report only."
     ESCAL_SEED="everything - a human decides what to action; this loop never changes code" ;;
-  pr-babysitter) SEEDED=1
+  pr-watch) SEEDED=1
     SCOPE_SEED="src/**"
     GOAL_SEED="Watch open PRs; flag stuck/failing/conflicted; post a summary comment at most; never merge."
     ESCAL_SEED="a human reviews and merges; never merge to main" ;;
-  ci-sweeper) SEEDED=1
+  ci-watch) SEEDED=1
     SCOPE_SEED="src/**"
     GOAL_SEED="Detect red CI; classify the failure; at L2 propose a fix in a worktree; never auto-merge to main."
     ESCAL_SEED="flaky/infra failures, anything touching deploy/secrets, ambiguous root cause"
     VERIFY_SEED="npm test"; GUARD_SEED="npm run typecheck" ;;
-  dependency-sweeper) SEEDED=1
+  dep-bump) SEEDED=1
     SCOPE_SEED="package.json"
     GOAL_SEED="Patch-only dependency bumps behind the release cooldown + guard; open a PR; never minor/major."
     ESCAL_SEED="minor/major bumps, guard failures, any flagged advisory"
     VERIFY_SEED="npm test"; GUARD_SEED="npm run build && npm test" ;;
-  changelog-drafter) SEEDED=1
+  changelog-gen) SEEDED=1
     SCOPE_SEED="CHANGELOG.md"
     GOAL_SEED="Summarize merged PRs since the last tag into RELEASE_NOTES_DRAFT.md; never publish a release."
     ESCAL_SEED="the human edits and publishes; never run gh release create" ;;
-  post-merge-cleanup) SEEDED=1
+  merge-hygiene) SEEDED=1
     SCOPE_SEED="src/**"
     GOAL_SEED="Find merged-deletable branches / stale flags / orphaned artifacts; report; never delete unmerged work."
     ESCAL_SEED="anything ambiguous; never delete a branch with unmerged commits" ;;
-  issue-triage) SEEDED=1
+  issue-sort) SEEDED=1
     SCOPE_SEED="src/**"
     GOAL_SEED="Classify new issues and suggest labels + priority; propose only; never close or set priority unattended."
     ESCAL_SEED="priority calls, dupe-closing, anything needing product judgment" ;;
@@ -217,7 +217,7 @@ render_run_sh() {
 # the pattern's gate if it has one, else a <fill:…> placeholder the audit will flag.
 render_seeded_config() {
   cat <<EOF
-# loop.config.yaml - $PATTERN (seeded by loop-init at $TIER; REVIEW before scheduling)
+# loop.config.yaml - $PATTERN (seeded by loop-scaffold at $TIER; REVIEW before scheduling)
 # Full field semantics: skills/loop-ops/references/state-spine.md
 name: $NAME
 pattern: $PATTERN
@@ -234,7 +234,7 @@ EOF
   if [[ "$TIER" == "L1" ]]; then
     cat <<EOF
 
-# ── graduate to L2 (assisted): set tier: L2, uncomment + fill, re-run loop-audit + loop-doctor --live ──
+# ── graduate to L2 (assisted): set tier: L2, uncomment + fill, re-run loop-check + loop-doctor --live ──
 # verify: "${VERIFY_SEED:-<fill: the gate command, e.g. npm test>}"
 # guard: "${GUARD_SEED:-<fill: a must-always-pass command>}"
 # worktree: true
@@ -298,7 +298,7 @@ printf '%s\n' "$CFG_OUT"
     term_alert warning "tier $TIER needs a verify gate, guard, worktree, escalation + land_via — fill them before auditing"
   fi
   term_panel_vert
-  term_panel_close "then: fill the config ${TERM_DOT} loop-audit.sh $CFG_OUT" ""
+  term_panel_close "then: fill the config ${TERM_DOT} loop-check.sh $CFG_OUT" ""
 } >&2
 
 exit "$EX_OK"

+ 50 - 50
skills/loop-ops/tests/run.sh

@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-# Self-test for loop-ops scripts (loop-init.sh, loop-audit.sh, loop-cost.py).
+# Self-test for loop-ops scripts (loop-scaffold.sh, loop-check.sh, loop-estimate.py).
 #
 # Offline-deterministic (no network). Scaffolds throwaway loop fixtures, asserts the
 # documented exit codes + key output of each script, then cleans up. Resolves paths
@@ -13,9 +13,9 @@ set -uo pipefail
 HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 SKILL="$(dirname "$HERE")"
 SCRIPTS="$SKILL/scripts"
-INIT="$SCRIPTS/loop-init.sh"
-AUDIT="$SCRIPTS/loop-audit.sh"
-COST="$SCRIPTS/loop-cost.py"
+INIT="$SCRIPTS/loop-scaffold.sh"
+AUDIT="$SCRIPTS/loop-check.sh"
+COST="$SCRIPTS/loop-estimate.py"
 SYNC="$SCRIPTS/check-pricing-sync.py"
 DOCTOR="$SCRIPTS/loop-doctor.sh"
 
@@ -37,7 +37,7 @@ expect_has()  { case "$3" in *"$2"*) ok "$1";; *) no "$1 (missing '$2')";; esac;
 # Write a filled, READY L1 report-only config.
 good_l1() { cat > "$1" <<'EOF'
 name: test-l1
-pattern: pr-babysitter
+pattern: pr-watch
 tier: L1
 permission_mode: dontAsk
 cadence: 10m
@@ -52,8 +52,8 @@ EOF
 
 # Write a filled, READY L2 assisted config.
 good_l2() { cat > "$1" <<'EOF'
-name: dep-sweeper
-pattern: dependency-sweeper
+name: dep-bump
+pattern: dep-bump
 tier: L2
 permission_mode: dontAsk
 cadence: 1d
@@ -67,7 +67,7 @@ worktree: true
 land_via: fleet-ops
 escalation: "minor/major bumps escalate; never merge to main"
 budget_tokens: 300000
-kill_switch: ".loops/dep-sweeper/PAUSED"
+kill_switch: ".loops/dep-bump/PAUSED"
 EOF
 }
 
@@ -75,14 +75,14 @@ echo "=== loop-ops self-test (python: $PYTHON) ==="
 
 # ── --help contracts (exit 0) ──────────────────────────────────────────────
 echo "-- --help --"
-bash "$INIT"  --help >/dev/null 2>&1; expect_exit "loop-init --help" 0 $?
-bash "$AUDIT" --help >/dev/null 2>&1; expect_exit "loop-audit --help" 0 $?
-"$PYTHON" "$COST" --help >/dev/null 2>&1; expect_exit "loop-cost --help" 0 $?
+bash "$INIT"  --help >/dev/null 2>&1; expect_exit "loop-scaffold --help" 0 $?
+bash "$AUDIT" --help >/dev/null 2>&1; expect_exit "loop-check --help" 0 $?
+"$PYTHON" "$COST" --help >/dev/null 2>&1; expect_exit "loop-estimate --help" 0 $?
 
-# ── loop-init: scaffolds dir + 3 files, substitutes fields ─────────────────
-echo "-- loop-init --"
-out="$(bash "$INIT" --name pr-watch --pattern pr-babysitter --tier L1 --cadence 5m --dir "$SB/loops" 2>/dev/null)"; rc=$?
-expect_exit "loop-init -> 0" 0 "$rc"
+# ── loop-scaffold: scaffolds dir + 3 files, substitutes fields ─────────────────
+echo "-- loop-scaffold --"
+out="$(bash "$INIT" --name pr-watch --pattern pr-watch --tier L1 --cadence 5m --dir "$SB/loops" 2>/dev/null)"; rc=$?
+expect_exit "loop-scaffold -> 0" 0 "$rc"
 expect_has  "prints the config path" "pr-watch/loop.config.yaml" "$out"
 [[ -f "$SB/loops/pr-watch/loop.config.yaml" ]] && ok "wrote loop.config.yaml" || no "no loop.config.yaml"
 [[ -f "$SB/loops/pr-watch/STATE.md" ]] && ok "wrote STATE.md" || no "no STATE.md"
@@ -105,29 +105,29 @@ expect_has "L1 default permission_mode" "permission_mode: dontAsk" "$cfg"
 bash "$INIT" --name big-job --tier L3 --dir "$SB/loops" >/dev/null 2>&1
 expect_has "L3 default permission_mode" "permission_mode: bypassPermissions" "$(cat "$SB/loops/big-job/loop.config.yaml")"
 
-# ── loop-init: refuses a populated dir -> 5, --force overwrites ─────────────
+# ── loop-scaffold: refuses a populated dir -> 5, --force overwrites ─────────────
 bash "$INIT" --name pr-watch --dir "$SB/loops" >/dev/null 2>&1; expect_exit "refuse populated dir -> 5" 5 $?
 bash "$INIT" --name pr-watch --dir "$SB/loops" --force >/dev/null 2>&1; expect_exit "--force overwrites -> 0" 0 $?
 
-# ── loop-init: --dry-run writes nothing ────────────────────────────────────
+# ── loop-scaffold: --dry-run writes nothing ────────────────────────────────────
 out="$(bash "$INIT" --name ghost --dir "$SB/dryloops" --dry-run 2>/dev/null)"; rc=$?
 expect_exit "dry-run -> 0" 0 "$rc"
 [[ -e "$SB/dryloops" ]] && no "dry-run created files" || ok "dry-run wrote nothing"
 expect_has "dry-run prints config path" "ghost/loop.config.yaml" "$out"
 
-# ── loop-init: usage errors ────────────────────────────────────────────────
+# ── loop-scaffold: usage errors ────────────────────────────────────────────────
 bash "$INIT" --dir "$SB/loops" >/dev/null 2>&1; expect_exit "missing --name -> 2" 2 $?
 bash "$INIT" --name BadName --dir "$SB/loops" >/dev/null 2>&1; expect_exit "non-kebab name -> 2" 2 $?
 bash "$INIT" --name x --tier L9 --dir "$SB/loops" >/dev/null 2>&1; expect_exit "bad tier -> 2" 2 $?
 
 # pattern-seeding: a known pattern seeds a near-ready, audit-clean config
-bash "$INIT" --name seed-l1 --pattern ci-sweeper --tier L1 --cadence 15m --dir "$SB/seed" >/dev/null 2>&1
+bash "$INIT" --name seed-l1 --pattern ci-watch --tier L1 --cadence 15m --dir "$SB/seed" >/dev/null 2>&1
 seedcfg="$(cat "$SB/seed/seed-l1/loop.config.yaml")"
 expect_has "seeded config carries the pattern goal" "Detect red CI" "$seedcfg"
 expect_has "seeded L1 leaves a graduation block" "graduate to L2" "$seedcfg"
 bash "$AUDIT" "$SB/seed/seed-l1/loop.config.yaml" >/dev/null 2>&1; expect_exit "seeded L1 audits clean -> 0" 0 $?
 # at L2 the pattern's gate is filled (not commented) and audits clean
-bash "$INIT" --name seed-l2 --pattern ci-sweeper --tier L2 --cadence 15m --dir "$SB/seed" >/dev/null 2>&1
+bash "$INIT" --name seed-l2 --pattern ci-watch --tier L2 --cadence 15m --dir "$SB/seed" >/dev/null 2>&1
 l2cfg="$(cat "$SB/seed/seed-l2/loop.config.yaml")"
 case "$l2cfg" in *$'\nverify: "npm test"'*) ok "seeded L2 fills the gate";; *) no "seeded L2 did not fill the gate";; esac
 bash "$AUDIT" "$SB/seed/seed-l2/loop.config.yaml" >/dev/null 2>&1; expect_exit "seeded L2 audits clean -> 0" 0 $?
@@ -135,90 +135,90 @@ bash "$AUDIT" "$SB/seed/seed-l2/loop.config.yaml" >/dev/null 2>&1; expect_exit "
 bash "$INIT" --name seed-x --pattern custom --tier L1 --dir "$SB/seed" >/dev/null 2>&1
 case "$(cat "$SB/seed/seed-x/loop.config.yaml")" in *"<one sentence"*) ok "unknown pattern uses generic template";; *) no "unknown pattern did not use template";; esac
 
-# ── loop-audit: a freshly-init'd config is NOT ready (placeholders) -> 10 ───
-echo "-- loop-audit --"
+# ── loop-check: a freshly-init'd config is NOT ready (placeholders) -> 10 ───
+echo "-- loop-check --"
 bash "$INIT" --name raw --pattern custom --tier L1 --dir "$SB/loops" >/dev/null 2>&1
 out="$(bash "$AUDIT" "$SB/loops/raw/loop.config.yaml" 2>/dev/null)"; rc=$?
 expect_exit "raw scaffold not ready -> 10" 10 "$rc"
 expect_has  "flags the goal placeholder" "goal:" "$out"
 
-# ── loop-audit: filled L1 config is READY -> 0 ─────────────────────────────
+# ── loop-check: filled L1 config is READY -> 0 ─────────────────────────────
 good_l1 "$SB/l1.yaml"
 out="$(bash "$AUDIT" "$SB/l1.yaml" 2>/dev/null)"; rc=$?
 expect_exit "filled L1 ready -> 0" 0 "$rc"
 
-# ── loop-audit: filled L2 config is READY -> 0 ─────────────────────────────
+# ── loop-check: filled L2 config is READY -> 0 ─────────────────────────────
 good_l2 "$SB/l2.yaml"
 bash "$AUDIT" "$SB/l2.yaml" >/dev/null 2>&1; expect_exit "filled L2 ready -> 0" 0 $?
 
-# ── loop-audit: L2 missing the gate -> 10, names verify ────────────────────
+# ── loop-check: L2 missing the gate -> 10, names verify ────────────────────
 grep -v '^verify:' "$SB/l2.yaml" > "$SB/l2-nogate.yaml"
 out="$(bash "$AUDIT" "$SB/l2-nogate.yaml" 2>/dev/null)"; rc=$?
 expect_exit "L2 missing gate -> 10" 10 "$rc"
 expect_has  "names the missing gate" "verify:" "$out"
 
-# ── loop-audit: unbounded scope -> 10 ──────────────────────────────────────
+# ── loop-check: unbounded scope -> 10 ──────────────────────────────────────
 sed 's|  - "src/\*\*"|  - "*"|' "$SB/l1.yaml" > "$SB/l1-unbounded.yaml"
 out="$(bash "$AUDIT" "$SB/l1-unbounded.yaml" 2>/dev/null)"; rc=$?
 expect_exit "unbounded scope -> 10" 10 "$rc"
 expect_has  "names unbounded scope" "unbounded" "$out"
 
-# ── loop-audit: missing escalation -> 10 ───────────────────────────────────
+# ── loop-check: missing escalation -> 10 ───────────────────────────────────
 grep -v '^escalation:' "$SB/l1.yaml" > "$SB/l1-noescal.yaml"
 out="$(bash "$AUDIT" "$SB/l1-noescal.yaml" 2>/dev/null)"; rc=$?
 expect_exit "missing escalation -> 10" 10 "$rc"
 expect_has  "names escalation" "escalation:" "$out"
 
-# ── loop-audit: missing file -> 3, unparseable -> 4, bad --min -> 2 ────────
+# ── loop-check: missing file -> 3, unparseable -> 4, bad --min -> 2 ────────
 bash "$AUDIT" "$SB/no-such.yaml" >/dev/null 2>&1; expect_exit "missing config -> 3" 3 $?
 printf 'just some prose, no keys\n' > "$SB/garbage.yaml"
 bash "$AUDIT" "$SB/garbage.yaml" >/dev/null 2>&1; expect_exit "unparseable -> 4" 4 $?
 bash "$AUDIT" --min abc "$SB/l1.yaml" >/dev/null 2>&1; expect_exit "bad --min -> 2" 2 $?
 
-# ── loop-audit: --json envelope schema + ready flag ────────────────────────
+# ── loop-check: --json envelope schema + ready flag ────────────────────────
 out="$(bash "$AUDIT" --json "$SB/l1.yaml" 2>/dev/null)"
-expect_has "audit json schema" "claude-mods.loop-ops.audit/v1" "$out"
+expect_has "audit json schema" "claude-mods.loop-ops.check/v1" "$out"
 expect_has "audit json ready true" '"ready": true' "$out"
 out="$(bash "$AUDIT" --json "$SB/l2-nogate.yaml" 2>/dev/null)"
 expect_has "audit json ready false" '"ready": false' "$out"
 
-# ── loop-audit: --strict turns a warning into NOT ready ────────────────────
+# ── loop-check: --strict turns a warning into NOT ready ────────────────────
 # An L1 with permission_mode: auto is consistent-enough to pass errors but warns
 # (broad for L1). Normally ready; --strict flips it.
 sed 's|permission_mode: dontAsk|permission_mode: auto|' "$SB/l1.yaml" > "$SB/l1-warn.yaml"
 bash "$AUDIT" "$SB/l1-warn.yaml" >/dev/null 2>&1; expect_exit "warning, normally ready -> 0" 0 $?
 bash "$AUDIT" --strict "$SB/l1-warn.yaml" >/dev/null 2>&1; expect_exit "warning, --strict not ready -> 10" 10 $?
 
-# ── loop-cost: basic run, --json, --list-models, cadence forms ─────────────
-echo "-- loop-cost --"
-out="$("$PYTHON" "$COST" --pattern pr-babysitter --cadence 10m --model claude-haiku-4-5 2>/dev/null)"; rc=$?
-expect_exit "loop-cost -> 0" 0 "$rc"
+# ── loop-estimate: basic run, --json, --list-models, cadence forms ─────────────
+echo "-- loop-estimate --"
+out="$("$PYTHON" "$COST" --pattern pr-watch --cadence 10m --model claude-haiku-4-5 2>/dev/null)"; rc=$?
+expect_exit "loop-estimate -> 0" 0 "$rc"
 expect_has  "prints a daily cost" "cost/day:" "$out"
 expect_has  "derives runs/day from 10m" "144 runs/day" "$out"
-out="$("$PYTHON" "$COST" --pattern ci-sweeper --cadence 15m --model claude-sonnet-4-6 --json 2>/dev/null)"
-expect_has "cost json schema" "claude-mods.loop-ops.cost/v1" "$out"
+out="$("$PYTHON" "$COST" --pattern ci-watch --cadence 15m --model claude-sonnet-4-6 --json 2>/dev/null)"
+expect_has "cost json schema" "claude-mods.loop-ops.estimate/v1" "$out"
 expect_has "cost json carries runs_per_day" "runs_per_day" "$out"
 out="$("$PYTHON" "$COST" --list-models 2>/dev/null)"; rc=$?
 expect_exit "list-models -> 0" 0 "$rc"
 expect_has  "list-models shows a model" "claude-opus-4-8" "$out"
 # cron cadence parses
-"$PYTHON" "$COST" --pattern daily-triage --cadence '*/10 * * * *' --model claude-haiku-4-5 >/dev/null 2>&1
+"$PYTHON" "$COST" --pattern daily-scan --cadence '*/10 * * * *' --model claude-haiku-4-5 >/dev/null 2>&1
 expect_exit "cron cadence -> 0" 0 $?
 # --runs-per-day override
 out="$("$PYTHON" "$COST" --pattern custom --cadence weird --runs-per-day 5 --model claude-haiku-4-5 2>/dev/null)"; rc=$?
 expect_exit "runs-per-day override -> 0" 0 "$rc"
 expect_has  "uses the override" "5 runs/day" "$out"
 # caching: a fast loop (10m -> 1h TTL) projects a cached saving
-out="$("$PYTHON" "$COST" --pattern ci-sweeper --cadence 10m --model claude-sonnet-4-6 2>&1)"
+out="$("$PYTHON" "$COST" --pattern ci-watch --cadence 10m --model claude-sonnet-4-6 2>&1)"
 expect_has "fast loop shows a cached projection" "cached/" "$out"
 # caching: a slow loop (6h > 1h TTL) is not cache-beneficial
-out="$("$PYTHON" "$COST" --pattern daily-triage --cadence 6h --model claude-opus-4-8 2>&1)"
+out="$("$PYTHON" "$COST" --pattern daily-scan --cadence 6h --model claude-opus-4-8 2>&1)"
 expect_has "slow loop: caching not beneficial" "not beneficial" "$out"
 # --no-cache suppresses the cached projection
-out="$("$PYTHON" "$COST" --pattern ci-sweeper --cadence 10m --model claude-sonnet-4-6 --no-cache 2>&1)"
+out="$("$PYTHON" "$COST" --pattern ci-watch --cadence 10m --model claude-sonnet-4-6 --no-cache 2>&1)"
 case "$out" in *"cached/"*) no "--no-cache still showed caching";; *) ok "--no-cache suppresses caching";; esac
 # json caching block present for a cacheable loop
-out="$("$PYTHON" "$COST" --pattern ci-sweeper --cadence 5m --model claude-sonnet-4-6 --json 2>/dev/null)"
+out="$("$PYTHON" "$COST" --pattern ci-watch --cadence 5m --model claude-sonnet-4-6 --json 2>/dev/null)"
 expect_has "cost json carries caching block" '"caching"' "$out"
 
 # ── loop-doctor: preflight (offline budget, live binary), json ─────────────
@@ -239,10 +239,10 @@ bash "$DOCTOR" --offline "$SB/no-such.yaml" >/dev/null 2>&1; expect_exit "doctor
 out="$(bash "$DOCTOR" --offline --json "$SB/l1.yaml" 2>/dev/null)"
 expect_has "doctor json schema" "claude-mods.loop-ops.doctor/v1" "$out"
 
-# ── loop-cost: validation errors ───────────────────────────────────────────
-"$PYTHON" "$COST" --pattern pr-babysitter --cadence 10m --model claude-nope >/dev/null 2>&1; expect_exit "unknown model -> 4" 4 $?
+# ── loop-estimate: validation errors ───────────────────────────────────────────
+"$PYTHON" "$COST" --pattern pr-watch --cadence 10m --model claude-nope >/dev/null 2>&1; expect_exit "unknown model -> 4" 4 $?
 "$PYTHON" "$COST" --pattern not-a-pattern --cadence 10m --model claude-haiku-4-5 >/dev/null 2>&1; expect_exit "unknown pattern -> 4" 4 $?
-"$PYTHON" "$COST" --pattern pr-babysitter --cadence "garbage cron" --model claude-haiku-4-5 >/dev/null 2>&1; expect_exit "bad cadence -> 4" 4 $?
+"$PYTHON" "$COST" --pattern pr-watch --cadence "garbage cron" --model claude-haiku-4-5 >/dev/null 2>&1; expect_exit "bad cadence -> 4" 4 $?
 "$PYTHON" "$COST" --pricing "$SB/no-pricing.json" --pattern custom --cadence 1h --input-tokens 1 --output-tokens 1 --model x >/dev/null 2>&1; expect_exit "missing pricing file -> 3" 3 $?
 
 # ── check-pricing-sync: offline clean -> 0, drift -> 10, --json ────────────
@@ -259,13 +259,13 @@ expect_has "pricing-sync json in_sync" '"in_sync": true' "$out"
 
 # ── worked example: the shipped example stays gate-clean ───────────────────
 echo "-- worked example --"
-EX="$SKILL/assets/examples/pr-babysitter/loop.config.yaml"
+EX="$SKILL/assets/examples/pr-watch/loop.config.yaml"
 [[ -f "$EX" ]] && ok "worked example present" || no "worked example missing"
 bash "$AUDIT" "$EX" >/dev/null 2>&1; expect_exit "shipped example audits clean -> 0" 0 $?
 bash "$DOCTOR" --offline "$EX" >/dev/null 2>&1; expect_exit "shipped example doctors clean -> 0" 0 $?
-[[ -f "$SKILL/assets/examples/pr-babysitter/loop-run.sh" ]] && ok "example ships loop-run.sh (runner-agnostic)" || no "example missing loop-run.sh"
-[[ -f "$SKILL/assets/examples/pr-babysitter/github-actions.yml" ]] && ok "example ships an optional GH Actions scheduler" || no "example missing GH Actions option"
-[[ -f "$SKILL/assets/examples/pr-babysitter/run.md" ]] && ok "example ships a run prompt" || no "example missing run.md"
+[[ -f "$SKILL/assets/examples/pr-watch/loop-run.sh" ]] && ok "example ships loop-run.sh (runner-agnostic)" || no "example missing loop-run.sh"
+[[ -f "$SKILL/assets/examples/pr-watch/github-actions.yml" ]] && ok "example ships an optional GH Actions scheduler" || no "example missing GH Actions option"
+[[ -f "$SKILL/assets/examples/pr-watch/run.md" ]] && ok "example ships a run prompt" || no "example missing run.md"
 
 # ── terminal design system ─────────────────────────────────────────────────
 echo "-- terminal design system --"
@@ -273,7 +273,7 @@ for s in "$INIT" "$AUDIT" "$DOCTOR"; do
   b="$(basename "$s")"
   grep -q '_lib/term.sh' "$s" && ok "$b sources _lib/term.sh" || no "$b does not source _lib/term.sh"
 done
-grep -q 'class Term' "$COST" && ok "loop-cost carries inline Term helper" || no "loop-cost missing inline Term helper"
+grep -q 'class Term' "$COST" && ok "loop-estimate carries inline Term helper" || no "loop-estimate missing inline Term helper"
 grep -q 'class Term' "$SYNC" && ok "check-pricing-sync carries inline Term helper" || no "check-pricing-sync missing inline Term helper"
 grep -q 'BRAND::loop' "$SKILL/../_lib/term.sh" && ok "term.sh registers the loop brand glyph" || no "term.sh missing loop brand glyph"
 # Piped audit findings stay plain (no ANSI in the data stream).

+ 2 - 2
tests/check-resources.sh

@@ -66,8 +66,8 @@ run "pricing-sync --offline in sync" 0 "$PY" skills/loop-ops/scripts/check-prici
 run "pricing-sync --help"            0 "$PY" skills/loop-ops/scripts/check-pricing-sync.py --help
 
 echo "== loop-ops: worked example is gate-clean (dogfood)"
-LOOP_EX="skills/loop-ops/assets/examples/pr-babysitter/loop.config.yaml"
-run "example audits clean"          0 bash skills/loop-ops/scripts/loop-audit.sh "$LOOP_EX"
+LOOP_EX="skills/loop-ops/assets/examples/pr-watch/loop.config.yaml"
+run "example audits clean"          0 bash skills/loop-ops/scripts/loop-check.sh "$LOOP_EX"
 run "example doctors clean (offline)" 0 bash skills/loop-ops/scripts/loop-doctor.sh --offline "$LOOP_EX"
 
 echo "== protocol: every new verifier is executable + compiles"