Prechádzať zdrojové kódy

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 2 týždňov pred
rodič
commit
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
   *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`,
   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`).
   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`
   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
 - **`docs/AUTO-MODE-CLASSIFIER.md`** - reference on Claude Code's auto-mode permission
   classifier (the two-gate model, gating categories, legitimate-authorization decision tree),
   classifier (the two-gate model, gating categories, legitimate-authorization decision tree),
   cited by `loop-ops` as the authority for its risk-tier mapping.
   cited by `loop-ops` as the authority for its risk-tier mapping.
 - **loop-ops hardening (world-class pass)**: `loop-doctor.sh` - a live preflight
 - **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
   (`--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
   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`**
   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
   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.
   gate, kill switch + budget) into every session, not just when the skill is invoked.
   Suite now 81 assertions.
   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
   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
   config + populated STATE + run prompt + run-log + a scheduler workflow with the
   kill-switch gate and `dontAsk` allowlist baked in) that CI **dogfoods**
   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
   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
   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
   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
 - **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,
   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*
   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 /
   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
   systemd / process-compose) and GitHub Actions demoted to one optional path. No GitHub
   Actions dependency anywhere. 96-assertion suite.
   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
 ## Recent Updates
 
 
 **v3.3.0** (June 2026)
 **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)
 **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.
 - 🤖 **`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 |
 | [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 |
 | [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. |
 | [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 |
 | [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 |
 | [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 |
 | [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
 # Loop Engineering — graduated-autonomy discipline for agent loops
 
 
 Companion to the [`loop-ops`](../skills/loop-ops/SKILL.md) skill (the full playbook +
 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
 — 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`
 loop, in any project: a `/loop`, a `/schedule` routine, a cron `claude -p`, an `iterate`
 run, a `fleet-worker` fan-out.
 run, a `fleet-worker` fan-out.
@@ -41,11 +41,11 @@ the authority you'd already seen it use well.
 
 
 | Situation | Directive |
 | 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. |
 | 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. |
 | 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. |
 | 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. |
 | 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
 ## Self-check before wiring a loop
 
 
 - Is it starting at L1? If you're reaching for L3 on a fresh loop, stop.
 - 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
 - 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
   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.
   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/
 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
 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.**
 **invoke the [`loop-ops`](../skills/loop-ops/SKILL.md) skill.**
 
 
 ## Cross-reference
 ## Cross-reference

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

@@ -1,7 +1,7 @@
 ---
 ---
 name: loop-ops
 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
 license: MIT
 allowed-tools: "Read Write Edit Bash Glob Grep"
 allowed-tools: "Read Write Edit Bash Glob Grep"
 metadata:
 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
 - **`run-log.md`** — append one line per run (timestamp, action, outcome, tokens). The
   audit trail that answers "what has this loop been doing?"
   audit trail that answers "what has this loop been doing?"
 - **`loop.config.yaml`** — the loop's definition (goal, tier, cadence, scope, gate,
 - **`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
 ## Pattern catalog
 
 
@@ -119,13 +119,13 @@ Full skeletons in [references/pattern-catalog.md](references/pattern-catalog.md)
 
 
 | Pattern | Cadence | Tier | One-line job |
 | 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.
 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
 Running several loops? Two non-negotiables (detail in
 [references/state-spine.md](references/state-spine.md)):
 [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).
   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
 - **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.
   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
 **check-pricing-sync** gates pricing drift in CI. The discipline before scheduling is
 `init → fill → cost → audit → doctor --live`.
 `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:
 Writes `<dir>/<name>/` with five files from the bundled templates:
 `loop.config.yaml` ([assets/loop.config.template.yaml](assets/loop.config.template.yaml)),
 `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
 executable **`loop-run.sh`** ([assets/run.sh.template](assets/run.sh.template)) — the
 runner-agnostic tick wrapper any scheduler invokes (cron / Windows Task Scheduler /
 runner-agnostic tick wrapper any scheduler invokes (cron / Windows Task Scheduler /
 systemd / by hand), **no GitHub Actions required**. Pass a known `--pattern`
 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
 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
 review, not blank placeholders (it audits clean immediately). Doctrine holds: it still
 scaffolds at L1 by default with a graduation block.
 scaffolds at L1 by default with a graduation block.
 
 
 ```bash
 ```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:
 # 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
   --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
 writes. `--dry-run` prints what it would create and writes nothing. stdout = the created
 config path.
 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
 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,
 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.
 consistent with tier — and refuses a green light if any **critical** gap exists.
 
 
 ```bash
 ```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),
 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?)
 ### `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):
 *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
 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:
 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.
 the kill-switch sentinel's parent dir exists.
 
 
 ```bash
 ```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,
 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,
 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
 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
 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).
 is the source of truth — run its `check-model-table.py` if you suspect drift).
 
 
 ```bash
 ```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
 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
 ## End-to-end workflow
 
 
 1. **Pick a pattern** from the catalog (or `custom`). Start at **L1**.
 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 `*`),
 3. **Fill `loop.config.yaml`** — the real `goal`, `scope` (bounded globs, never `*`),
    `verify` gate, `escalation` rule, `budget_tokens`, `kill_switch`.
    `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.
    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.
    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
 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;
    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
 ## Worked example
 
 
 A complete, **audit + doctor-clean** L1 loop ships at
 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
 `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
 `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),
 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
 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
 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.
 example every build, so it can't drift out of validity.
 
 
 ## Anti-patterns (these are detected and wrong)
 ## 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
   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".
   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.
 - **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.
 - **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
 - **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.
   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/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.
 - [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.
 - [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_
 _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.
 <!-- 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
 - 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,
 # 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) —
 # 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.
 # 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
 # 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
 # loop), and the child runs gated (--permission-mode dontAsk + a narrow allowlist), never
 # bypassPermissions on a shared runner. See references/claude-code-loops.md.
 # bypassPermissions on a shared runner. See references/claude-code-loops.md.
-name: pr-babysitter
+name: pr-watch
 on:
 on:
   schedule:
   schedule:
     - cron: "*/10 * * * *"   # every 10 min (matches loop.config.yaml cadence: 10m)
     - 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)
   pull-requests: write       # post the at-most-one summary comment (L1 stays report-only)
 
 
 concurrency:
 concurrency:
-  group: pr-babysitter       # never overlap two ticks
+  group: pr-watch       # never overlap two ticks
   cancel-in-progress: false
   cancel-in-progress: false
 
 
 jobs:
 jobs:
@@ -30,7 +30,7 @@ jobs:
         id: gate
         id: gate
         env: { GH_TOKEN: "${{ github.token }}" }
         env: { GH_TOKEN: "${{ github.token }}" }
         run: |
         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
           if gh label list --limit 100 | grep -qi '^loop-pause'; then echo "paused=1" >> "$GITHUB_OUTPUT"; fi
 
 
       - name: Install Claude Code
       - name: Install Claude Code
@@ -44,7 +44,7 @@ jobs:
         env:
         env:
           ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}"
           ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}"
         run: |
         run: |
-          cd .loops/pr-babysitter
+          cd .loops/pr-watch
           claude -p "$(cat run.md)" \
           claude -p "$(cat run.md)" \
             --permission-mode dontAsk \
             --permission-mode dontAsk \
             --append-system-prompt "$(cat STATE.md)" \
             --append-system-prompt "$(cat STATE.md)" \
@@ -54,8 +54,8 @@ jobs:
       - name: Persist STATE + run-log
       - name: Persist STATE + run-log
         if: steps.gate.outputs.paused != '1'
         if: steps.gate.outputs.paused != '1'
         run: |
         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 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
           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
 #!/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.
 # 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
 #   by hand:              bash loop-run.sh
 # The scheduler is the authorizer; this runs a gated `claude -p` (dontAsk + an allowlist),
 # 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.)
 # 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"
 cd "$HERE"
 
 
 # 1. Kill switch first.
 # 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
 # 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'.
 #    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.
 # 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
 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 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
 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,
 # 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
 tier: L1
 permission_mode: dontAsk
 permission_mode: dontAsk
 cadence: 10m
 cadence: 10m
@@ -11,7 +11,7 @@ scope:
   - "src/**"
   - "src/**"
 escalation: "a human reviews and merges; never merge to main; never push; never close a PR"
 escalation: "a human reviews and merges; never merge to main; never push; never close a PR"
 budget_tokens: 60000
 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) ──
 # ── graduate to L2 (assisted: open a fix-the-PR-description / rebase branch) ──
 # tier: L2
 # 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>
 # 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-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
 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)"
   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.**
 You are one tick of a scheduled loop. Goal: **watch open PRs and report; never merge, push, or close.**
 
 
 ## Do these in order
 ## 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.
 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`.
 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.
 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.
 # 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.
 # key sits at column 0 so the audit parses it without a yq dependency.
 # Full field semantics: skills/loop-ops/references/state-spine.md
 # Full field semantics: skills/loop-ops/references/state-spine.md
 #
 #
@@ -8,7 +8,7 @@
 
 
 # ── identity ────────────────────────────────────────────────────────────────
 # ── identity ────────────────────────────────────────────────────────────────
 name: <loop-name>            # matches the .loops/<name>/ directory
 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 ────────────────────────────────────────────────────────────────
 # ── autonomy ────────────────────────────────────────────────────────────────
 tier: L1                     # L1 report-only | L2 assisted (worktree+gate) | L3 unattended
 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",
   "_as_of": "2026-06",
   "_schema": "claude-mods.loop-ops.pricing/v1",
   "_schema": "claude-mods.loop-ops.pricing/v1",
   "models": {
   "models": {
@@ -10,13 +10,13 @@
   },
   },
   "_pattern_defaults": {
   "_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.",
     "_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 }
     "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
 The unattended options (Desktop task, cloud routine, external scheduler, Actions) are the
 human-configured **authorizer** — no parent auto-mode session, so nothing blocks 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.
 runner-agnostic and **native-first** on purpose.
 
 
 ## Completion — when the work stops: `/goal`
 ## 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)
 ### 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),
 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
 - **`/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.
   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
 - **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).
   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:
 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
 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
 `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 /
 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.
 **`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
 ```bash
 # cron (Linux/macOS):
 # 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):
 # 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.
 # 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
 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
    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`,
    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
 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.
 `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.
 - **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
 - **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.
   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.
   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.
   that used to cost 2k now costing 40k means scope crept.
 
 
 ## 2. The 3am-dead loop
 ## 2. The 3am-dead loop
@@ -33,14 +33,14 @@ judgment has earned.
 
 
 ## 3. The cache-cold loop
 ## 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.
   stays 0.
 - **Mechanism:** the run prompt isn't byte-identical every tick — a `datetime.now()`, a
 - **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
   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
   slower than the cache TTL (a 6h loop can't keep a 1h entry warm), so every tick is a
   cold write.
   cold write.
 - **Catch:** keep `run.md` byte-identical (the template enforces this — fresh context,
 - **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.
   if it can't, don't pay the write multiplier — run uncached.
 
 
 ## 4. The force-push / push-to-main loop
 ## 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.
   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
 - **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
   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.
   closes this; the kill switch is for stopping, the heartbeat is for noticing it stopped.
 
 
 ## 8. The test-deleting "fix" (gate reward-hacking)
 ## 8. The test-deleting "fix" (gate reward-hacking)
@@ -100,7 +100,7 @@ judgment has earned.
 
 
 - **Symptom:** the loop edited files far outside its job.
 - **Symptom:** the loop edited files far outside its job.
 - **Mechanism:** `scope: "*"` (or `**`, or empty) — "may touch anything."
 - **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.
   is bounded globs, always.
 
 
 ## 10. The no-kill-switch loop
 ## 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.
 - **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
 - **Mechanism:** no stop signal was designed in; stopping means disabling the workflow by
   hand mid-tick.
   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
   **first** every run. The cheapest implementation is a `PreToolUse` hook that blocks
   every tool the instant a `PAUSED` sentinel appears — an instant breaker.
   every tool the instant a `PAUSED` sentinel appears — an instant breaker.
 
 
@@ -129,15 +129,15 @@ judgment has earned.
 
 
 | Failure | Primary control |
 | 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) |
 | 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 |
 | Force-push / prod | escalation gate + auto-mode classifier |
 | Ungated-child spawn | scheduler-invokes-`claude -p` (rule #2) |
 | Ungated-child spawn | scheduler-invokes-`claude -p` (rule #2) |
 | Colliding loops | priority order + per-loop worktree + `pigeon` |
 | Colliding loops | priority order + per-loop worktree + `pigeon` |
 | Silent-stop | `STATE.md`/run-log heartbeat staleness |
 | Silent-stop | `STATE.md`/run-log heartbeat staleness |
 | Gate reward-hacking | full-suite `guard` + scope excludes tests + human PR gate |
 | 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 |
 | No kill switch | mandatory `kill_switch` + PreToolUse PAUSED hook |
 | Comprehension debt | L1-first graduation; read the reports |
 | 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,
 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
 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.
 keyed by `--pattern <name>`; the names below are the canonical keys.
 
 
 The columns that matter for every pattern: **cadence** (how often), **tier** (starting
 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.
 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.
 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
 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
 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
 ## 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
 ## 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
 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.**
 `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
 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.
 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,
 - **L1:** bounded `scope` (never `*`), a `kill_switch`, `permission_mode` ∈ {plan,
   dontAsk}, **no** `verify` that writes. Report-only.
   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)
 └── 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.
 are loop-owned.
 
 
 ---
 ---
@@ -25,7 +25,7 @@ Flat YAML so it's trivially parseable (no `yq` dependency). Full annotated templ
 | Field | Required | Meaning |
 | Field | Required | Meaning |
 |---|---|---|
 |---|---|---|
 | `name` | yes | the loop's identifier; matches the directory |
 | `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 |
 | `tier` | yes | `L1` / `L2` / `L3` — the autonomy rung |
 | `cadence` | yes | `10m` / `1h` / `6h` / `1d`, or a cron string |
 | `cadence` | yes | `10m` / `1h` / `6h` / `1d`, or a cron string |
 | `goal` | yes | one sentence: what this loop does and what it must NOT do |
 | `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 |
 | `kill_switch` | yes | the stop signal every run checks first |
 | `land_via` | L2+ | who gates + lands winning branches (e.g. `fleet-ops`) |
 | `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
 - **`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()`).
   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.
   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
 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
 **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.
 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)
 ### 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)
  (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
 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
 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.
 worktree on PR #412" and stand off.
 
 
 ### The kill switch (every loop honors it)
 ### 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
 #!/usr/bin/env python3
 """Offline verifier: loop-ops pricing must match claude-api-ops's model table.
 """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
 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
 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
 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
 #!/usr/bin/env bash
 # Score an outer-loop config for readiness before it is scheduled.
 # 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).
 # Input:   argv flags + a config path (no stdin).
 # Output:  stdout = findings (plain `SEVERITY  message` rows, or --json envelope).
 # Output:  stdout = findings (plain `SEVERITY  message` rows, or --json envelope).
 #          Data only.
 #          Data only.
@@ -12,12 +12,12 @@
 # Scores a flat loop.config.yaml against the tier's requirements: a bounded scope,
 # 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
 # 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.
 # 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:
 # 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
 set -uo pipefail
 
 
 readonly EX_OK=0 EX_USAGE=2 EX_NOTFOUND=3 EX_UNPARSEABLE=4 EX_FINDINGS=10
 readonly EX_OK=0 EX_USAGE=2 EX_NOTFOUND=3 EX_UNPARSEABLE=4 EX_FINDINGS=10
@@ -39,10 +39,10 @@ JSON=0
 
 
 usage() {
 usage() {
   cat <<'EOF'
   cat <<'EOF'
-loop-audit.sh — score an outer-loop config for readiness.
+loop-check.sh — score an outer-loop config for readiness.
 
 
 Usage:
 Usage:
-  loop-audit.sh [OPTIONS] <loop.config.yaml>
+  loop-check.sh [OPTIONS] <loop.config.yaml>
 
 
 Options:
 Options:
   --min N        readiness score (0-100) required for a "ready" verdict (default: 70).
   --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)
   0 ready    2 usage    3 config not found    4 unparseable    10 NOT ready (findings)
 
 
 Examples:
 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
 EOF
 }
 }
 
 
@@ -220,7 +220,7 @@ if [[ "$JSON" -eq 1 ]]; then
     sep=","; [[ "$i" -eq $(( ${#FIND_SEV[@]} - 1 )) ]] && sep=""
     sep=","; [[ "$i" -eq $(( ${#FIND_SEV[@]} - 1 )) ]] && sep=""
     printf '    {"severity": "%s", "message": "%s"}%s\n' "${FIND_SEV[$i]}" "$msg" "$sep"
     printf '    {"severity": "%s", "message": "%s"}%s\n' "${FIND_SEV[$i]}" "$msg" "$sep"
   done
   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}"
     "${#FIND_SEV[@]}" "$ERRORS" "$WARNINGS" "$SCORE" "$MIN" "$([[ "$READY" -eq 1 ]] && echo true || echo false)" "${TIER:-unknown}"
 else
 else
   if [[ ${#FIND_SEV[@]} -gt 0 ]]; then
   if [[ ${#FIND_SEV[@]} -gt 0 ]]; then

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

@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 #!/usr/bin/env bash
 # Preflight a loop config - will this loop actually RUN, or die at 3am?
 # 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
 # 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.
 # can fit a tick, and the permission mode is achievable from where it launches.
 # Modeled on fleet-worker/scripts/fleet-doctor.sh.
 # Modeled on fleet-worker/scripts/fleet-doctor.sh.
@@ -20,9 +20,9 @@
 #                        leading binary resolvable, the kill-switch path's parent exists.
 #                        leading binary resolvable, the kill-switch path's parent exists.
 #
 #
 # Examples:
 # 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
 set -uo pipefail
 
 
 readonly EX_OK=0 EX_USAGE=2 EX_NOTFOUND=3 EX_UNPARSEABLE=4 EX_MISSING_DEP=5 EX_FINDINGS=10
 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
   0 ok   2 usage   3 not found   4 unparseable   5 missing dep   10 predicted runtime failure
 
 
 Examples:
 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
 EOF
 }
 }
 die_usage() { printf 'error: %s\n' "$1" >&2; echo >&2; usage >&2; exit "$EX_USAGE"; }
 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
   if command -v "$c" >/dev/null 2>&1 && "$c" -c "" >/dev/null 2>&1; then PY="$c"; break; fi
 done
 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() {
 cfg_scalar() {
   awk -v k="$1" -v q="'" '
   awk -v k="$1" -v q="'" '
     $0 ~ "^"k":" { sub("^"k":[ \t]*",""); sub(/[ \t]*#.*$/,""); gsub(/^[ \t]+|[ \t]+$/,"");
     $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
 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).
 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).
 Input:   argv flags only (no stdin).
 Output:  stdout = the cost breakdown (plain rows, or --json envelope). Data only.
 Output:  stdout = the cost breakdown (plain rows, or --json envelope). Data only.
 Stderr:  the assumptions + caching note, errors.
 Stderr:  the assumptions + caching note, errors.
@@ -21,10 +21,10 @@ order of impact: cadence (halving frequency halves cost), prompt caching (model
 model tier.
 model tier.
 
 
 Examples:
 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
 from __future__ import annotations
 
 
@@ -180,7 +180,7 @@ def fmt_money(x: float) -> str:
 
 
 def main(argv: list[str]) -> int:
 def main(argv: list[str]) -> int:
     p = argparse.ArgumentParser(
     p = argparse.ArgumentParser(
-        prog="loop-cost.py",
+        prog="loop-estimate.py",
         description="Estimate outer-loop cost by pattern × cadence × model, with prompt caching.",
         description="Estimate outer-loop cost by pattern × cadence × model, with prompt caching.",
     )
     )
     p.add_argument("--pattern", default="custom", help="catalog pattern key (default: custom)")
     p.add_argument("--pattern", default="custom", help="catalog pattern key (default: custom)")
@@ -287,7 +287,7 @@ def main(argv: list[str]) -> int:
             else:
             else:
                 data["caching"] = {"beneficial": False, "reason": cache["reason"],
                 data["caching"] = {"beneficial": False, "reason": cache["reason"],
                                    "prefix_tokens": cache["prefix_tokens"]}
                                    "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
         return EX_OK
 
 
     t = Term(sys.stderr)
     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
 #!/usr/bin/env bash
 # Scaffold an outer-loop state spine (loop.config.yaml + STATE.md + run-log.md).
 # 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).
 # Input:   argv flags only (no stdin).
 # Output:  stdout = the created loop.config.yaml path (data). Under --dry-run, the
 # Output:  stdout = the created loop.config.yaml path (data). Under --dry-run, the
 #          path then the rendered config. Data only.
 #          path then the rendered config. Data only.
@@ -11,12 +11,12 @@
 #
 #
 # Creates <dir>/<name>/ from the bundled templates, substituting name/pattern/tier/
 # Creates <dir>/<name>/ from the bundled templates, substituting name/pattern/tier/
 # cadence/permission_mode. Never clobbers a populated loop dir. Atomic writes.
 # 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:
 # 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
 set -uo pipefail
 
 
 readonly EX_OK=0 EX_USAGE=2 EX_NOTFOUND=3 EX_PRECOND=5
 readonly EX_OK=0 EX_USAGE=2 EX_NOTFOUND=3 EX_PRECOND=5
@@ -51,16 +51,16 @@ FORCE=0
 
 
 usage() {
 usage() {
   cat <<'EOF'
   cat <<'EOF'
-loop-init.sh — scaffold an outer-loop state spine.
+loop-scaffold.sh — scaffold an outer-loop state spine.
 
 
 Usage:
 Usage:
-  loop-init.sh --name NAME [OPTIONS]
+  loop-scaffold.sh --name NAME [OPTIONS]
 
 
 Options:
 Options:
   --name NAME        loop identifier, kebab-case (required). Names the directory.
   --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).
   --tier L1|L2|L3    starting autonomy tier (default: L1).
   --cadence STR      10m | 1h | 6h | 1d, or a cron string (default: 1h).
   --cadence STR      10m | 1h | 6h | 1d, or a cron string (default: 1h).
   --dir DIR          parent directory for the loop (default: .loops).
   --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
   0 created (or dry-run)   2 usage   3 template/dir not found   5 dir populated
 
 
 Examples:
 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
 EOF
 }
 }
 
 
@@ -122,33 +122,33 @@ esac
 # propose/draft patterns carry no gate (VERIFY_SEED empty), code-changing ones do.
 # 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=""
 SEEDED=0; SCOPE_SEED=""; GOAL_SEED=""; ESCAL_SEED=""; VERIFY_SEED=""; GUARD_SEED=""
 case "$PATTERN" in
 case "$PATTERN" in
-  daily-triage) SEEDED=1
+  daily-scan) SEEDED=1
     SCOPE_SEED="src/**"
     SCOPE_SEED="src/**"
     GOAL_SEED="Sweep the backlog/issues/alerts and write the day's STATE.md priority list; report only."
     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" ;;
     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/**"
     SCOPE_SEED="src/**"
     GOAL_SEED="Watch open PRs; flag stuck/failing/conflicted; post a summary comment at most; never merge."
     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" ;;
     ESCAL_SEED="a human reviews and merges; never merge to main" ;;
-  ci-sweeper) SEEDED=1
+  ci-watch) SEEDED=1
     SCOPE_SEED="src/**"
     SCOPE_SEED="src/**"
     GOAL_SEED="Detect red CI; classify the failure; at L2 propose a fix in a worktree; never auto-merge to main."
     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"
     ESCAL_SEED="flaky/infra failures, anything touching deploy/secrets, ambiguous root cause"
     VERIFY_SEED="npm test"; GUARD_SEED="npm run typecheck" ;;
     VERIFY_SEED="npm test"; GUARD_SEED="npm run typecheck" ;;
-  dependency-sweeper) SEEDED=1
+  dep-bump) SEEDED=1
     SCOPE_SEED="package.json"
     SCOPE_SEED="package.json"
     GOAL_SEED="Patch-only dependency bumps behind the release cooldown + guard; open a PR; never minor/major."
     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"
     ESCAL_SEED="minor/major bumps, guard failures, any flagged advisory"
     VERIFY_SEED="npm test"; GUARD_SEED="npm run build && npm test" ;;
     VERIFY_SEED="npm test"; GUARD_SEED="npm run build && npm test" ;;
-  changelog-drafter) SEEDED=1
+  changelog-gen) SEEDED=1
     SCOPE_SEED="CHANGELOG.md"
     SCOPE_SEED="CHANGELOG.md"
     GOAL_SEED="Summarize merged PRs since the last tag into RELEASE_NOTES_DRAFT.md; never publish a release."
     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" ;;
     ESCAL_SEED="the human edits and publishes; never run gh release create" ;;
-  post-merge-cleanup) SEEDED=1
+  merge-hygiene) SEEDED=1
     SCOPE_SEED="src/**"
     SCOPE_SEED="src/**"
     GOAL_SEED="Find merged-deletable branches / stale flags / orphaned artifacts; report; never delete unmerged work."
     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" ;;
     ESCAL_SEED="anything ambiguous; never delete a branch with unmerged commits" ;;
-  issue-triage) SEEDED=1
+  issue-sort) SEEDED=1
     SCOPE_SEED="src/**"
     SCOPE_SEED="src/**"
     GOAL_SEED="Classify new issues and suggest labels + priority; propose only; never close or set priority unattended."
     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" ;;
     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.
 # the pattern's gate if it has one, else a <fill:…> placeholder the audit will flag.
 render_seeded_config() {
 render_seeded_config() {
   cat <<EOF
   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
 # Full field semantics: skills/loop-ops/references/state-spine.md
 name: $NAME
 name: $NAME
 pattern: $PATTERN
 pattern: $PATTERN
@@ -234,7 +234,7 @@ EOF
   if [[ "$TIER" == "L1" ]]; then
   if [[ "$TIER" == "L1" ]]; then
     cat <<EOF
     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>}"
 # verify: "${VERIFY_SEED:-<fill: the gate command, e.g. npm test>}"
 # guard: "${GUARD_SEED:-<fill: a must-always-pass command>}"
 # guard: "${GUARD_SEED:-<fill: a must-always-pass command>}"
 # worktree: true
 # 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"
     term_alert warning "tier $TIER needs a verify gate, guard, worktree, escalation + land_via — fill them before auditing"
   fi
   fi
   term_panel_vert
   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
 } >&2
 
 
 exit "$EX_OK"
 exit "$EX_OK"

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

@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
 #!/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
 # Offline-deterministic (no network). Scaffolds throwaway loop fixtures, asserts the
 # documented exit codes + key output of each script, then cleans up. Resolves paths
 # 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)"
 HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 SKILL="$(dirname "$HERE")"
 SKILL="$(dirname "$HERE")"
 SCRIPTS="$SKILL/scripts"
 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"
 SYNC="$SCRIPTS/check-pricing-sync.py"
 DOCTOR="$SCRIPTS/loop-doctor.sh"
 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.
 # Write a filled, READY L1 report-only config.
 good_l1() { cat > "$1" <<'EOF'
 good_l1() { cat > "$1" <<'EOF'
 name: test-l1
 name: test-l1
-pattern: pr-babysitter
+pattern: pr-watch
 tier: L1
 tier: L1
 permission_mode: dontAsk
 permission_mode: dontAsk
 cadence: 10m
 cadence: 10m
@@ -52,8 +52,8 @@ EOF
 
 
 # Write a filled, READY L2 assisted config.
 # Write a filled, READY L2 assisted config.
 good_l2() { cat > "$1" <<'EOF'
 good_l2() { cat > "$1" <<'EOF'
-name: dep-sweeper
-pattern: dependency-sweeper
+name: dep-bump
+pattern: dep-bump
 tier: L2
 tier: L2
 permission_mode: dontAsk
 permission_mode: dontAsk
 cadence: 1d
 cadence: 1d
@@ -67,7 +67,7 @@ worktree: true
 land_via: fleet-ops
 land_via: fleet-ops
 escalation: "minor/major bumps escalate; never merge to main"
 escalation: "minor/major bumps escalate; never merge to main"
 budget_tokens: 300000
 budget_tokens: 300000
-kill_switch: ".loops/dep-sweeper/PAUSED"
+kill_switch: ".loops/dep-bump/PAUSED"
 EOF
 EOF
 }
 }
 
 
@@ -75,14 +75,14 @@ echo "=== loop-ops self-test (python: $PYTHON) ==="
 
 
 # ── --help contracts (exit 0) ──────────────────────────────────────────────
 # ── --help contracts (exit 0) ──────────────────────────────────────────────
 echo "-- --help --"
 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"
 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/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"
 [[ -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
 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")"
 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" >/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 $?
 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=$?
 out="$(bash "$INIT" --name ghost --dir "$SB/dryloops" --dry-run 2>/dev/null)"; rc=$?
 expect_exit "dry-run -> 0" 0 "$rc"
 expect_exit "dry-run -> 0" 0 "$rc"
 [[ -e "$SB/dryloops" ]] && no "dry-run created files" || ok "dry-run wrote nothing"
 [[ -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"
 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" --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 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 $?
 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
 # 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")"
 seedcfg="$(cat "$SB/seed/seed-l1/loop.config.yaml")"
 expect_has "seeded config carries the pattern goal" "Detect red CI" "$seedcfg"
 expect_has "seeded config carries the pattern goal" "Detect red CI" "$seedcfg"
 expect_has "seeded L1 leaves a graduation block" "graduate to L2" "$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 $?
 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
 # 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")"
 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
 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 $?
 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
 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
 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
 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=$?
 out="$(bash "$AUDIT" "$SB/loops/raw/loop.config.yaml" 2>/dev/null)"; rc=$?
 expect_exit "raw scaffold not ready -> 10" 10 "$rc"
 expect_exit "raw scaffold not ready -> 10" 10 "$rc"
 expect_has  "flags the goal placeholder" "goal:" "$out"
 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"
 good_l1 "$SB/l1.yaml"
 out="$(bash "$AUDIT" "$SB/l1.yaml" 2>/dev/null)"; rc=$?
 out="$(bash "$AUDIT" "$SB/l1.yaml" 2>/dev/null)"; rc=$?
 expect_exit "filled L1 ready -> 0" 0 "$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"
 good_l2 "$SB/l2.yaml"
 bash "$AUDIT" "$SB/l2.yaml" >/dev/null 2>&1; expect_exit "filled L2 ready -> 0" 0 $?
 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"
 grep -v '^verify:' "$SB/l2.yaml" > "$SB/l2-nogate.yaml"
 out="$(bash "$AUDIT" "$SB/l2-nogate.yaml" 2>/dev/null)"; rc=$?
 out="$(bash "$AUDIT" "$SB/l2-nogate.yaml" 2>/dev/null)"; rc=$?
 expect_exit "L2 missing gate -> 10" 10 "$rc"
 expect_exit "L2 missing gate -> 10" 10 "$rc"
 expect_has  "names the missing gate" "verify:" "$out"
 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"
 sed 's|  - "src/\*\*"|  - "*"|' "$SB/l1.yaml" > "$SB/l1-unbounded.yaml"
 out="$(bash "$AUDIT" "$SB/l1-unbounded.yaml" 2>/dev/null)"; rc=$?
 out="$(bash "$AUDIT" "$SB/l1-unbounded.yaml" 2>/dev/null)"; rc=$?
 expect_exit "unbounded scope -> 10" 10 "$rc"
 expect_exit "unbounded scope -> 10" 10 "$rc"
 expect_has  "names unbounded scope" "unbounded" "$out"
 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"
 grep -v '^escalation:' "$SB/l1.yaml" > "$SB/l1-noescal.yaml"
 out="$(bash "$AUDIT" "$SB/l1-noescal.yaml" 2>/dev/null)"; rc=$?
 out="$(bash "$AUDIT" "$SB/l1-noescal.yaml" 2>/dev/null)"; rc=$?
 expect_exit "missing escalation -> 10" 10 "$rc"
 expect_exit "missing escalation -> 10" 10 "$rc"
 expect_has  "names escalation" "escalation:" "$out"
 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 $?
 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"
 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" "$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 $?
 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)"
 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"
 expect_has "audit json ready true" '"ready": true' "$out"
 out="$(bash "$AUDIT" --json "$SB/l2-nogate.yaml" 2>/dev/null)"
 out="$(bash "$AUDIT" --json "$SB/l2-nogate.yaml" 2>/dev/null)"
 expect_has "audit json ready false" '"ready": false' "$out"
 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
 # An L1 with permission_mode: auto is consistent-enough to pass errors but warns
 # (broad for L1). Normally ready; --strict flips it.
 # (broad for L1). Normally ready; --strict flips it.
 sed 's|permission_mode: dontAsk|permission_mode: auto|' "$SB/l1.yaml" > "$SB/l1-warn.yaml"
 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" "$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 $?
 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  "prints a daily cost" "cost/day:" "$out"
 expect_has  "derives runs/day from 10m" "144 runs/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"
 expect_has "cost json carries runs_per_day" "runs_per_day" "$out"
 out="$("$PYTHON" "$COST" --list-models 2>/dev/null)"; rc=$?
 out="$("$PYTHON" "$COST" --list-models 2>/dev/null)"; rc=$?
 expect_exit "list-models -> 0" 0 "$rc"
 expect_exit "list-models -> 0" 0 "$rc"
 expect_has  "list-models shows a model" "claude-opus-4-8" "$out"
 expect_has  "list-models shows a model" "claude-opus-4-8" "$out"
 # cron cadence parses
 # 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 $?
 expect_exit "cron cadence -> 0" 0 $?
 # --runs-per-day override
 # --runs-per-day override
 out="$("$PYTHON" "$COST" --pattern custom --cadence weird --runs-per-day 5 --model claude-haiku-4-5 2>/dev/null)"; rc=$?
 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_exit "runs-per-day override -> 0" 0 "$rc"
 expect_has  "uses the override" "5 runs/day" "$out"
 expect_has  "uses the override" "5 runs/day" "$out"
 # caching: a fast loop (10m -> 1h TTL) projects a cached saving
 # 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"
 expect_has "fast loop shows a cached projection" "cached/" "$out"
 # caching: a slow loop (6h > 1h TTL) is not cache-beneficial
 # 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"
 expect_has "slow loop: caching not beneficial" "not beneficial" "$out"
 # --no-cache suppresses the cached projection
 # --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
 case "$out" in *"cached/"*) no "--no-cache still showed caching";; *) ok "--no-cache suppresses caching";; esac
 # json caching block present for a cacheable loop
 # 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"
 expect_has "cost json carries caching block" '"caching"' "$out"
 
 
 # ── loop-doctor: preflight (offline budget, live binary), json ─────────────
 # ── 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)"
 out="$(bash "$DOCTOR" --offline --json "$SB/l1.yaml" 2>/dev/null)"
 expect_has "doctor json schema" "claude-mods.loop-ops.doctor/v1" "$out"
 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 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 $?
 "$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 ────────────
 # ── 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 ───────────────────
 # ── worked example: the shipped example stays gate-clean ───────────────────
 echo "-- worked example --"
 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"
 [[ -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 "$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 $?
 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 ─────────────────────────────────────────────────
 # ── terminal design system ─────────────────────────────────────────────────
 echo "-- terminal design system --"
 echo "-- terminal design system --"
@@ -273,7 +273,7 @@ for s in "$INIT" "$AUDIT" "$DOCTOR"; do
   b="$(basename "$s")"
   b="$(basename "$s")"
   grep -q '_lib/term.sh' "$s" && ok "$b sources _lib/term.sh" || no "$b does not source _lib/term.sh"
   grep -q '_lib/term.sh' "$s" && ok "$b sources _lib/term.sh" || no "$b does not source _lib/term.sh"
 done
 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 '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"
 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).
 # 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
 run "pricing-sync --help"            0 "$PY" skills/loop-ops/scripts/check-pricing-sync.py --help
 
 
 echo "== loop-ops: worked example is gate-clean (dogfood)"
 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"
 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"
 echo "== protocol: every new verifier is executable + compiles"