# Nightly deploy check — a replayable Reelier skill

Nightly gate that sweeps several routes of YOUR live deployment — 200 + a body sentinel on each — read-only

A real, read-only Reelier skill against a live public API — no account, no keys, no writes. Every replay proves: Each route of a live deployment answers 200 and still serves its expected body content.

- Steps: 3 · Assertions: 6 · Effect: read (counts parsed from the file, never hand-typed)
- Endpoints: https://www.reelier.com/ · https://www.reelier.com/blog · https://www.reelier.com/docs
- Canonical file: https://raw.githubusercontent.com/seldonframe/reelier/main/examples/portfolio/nightly-deploy-check.skill.md
- HTML page: https://www.reelier.com/skills/nightly-deploy-check

## What this checks

Three steps: an HTTP GET to each of a live deployment's routes — homepage, blog index, and docs. Six assertions, two per route: the route answered 200 and its response body contains a known sentinel string (a headline or tagline you know belongs on that page).

A 200 alone isn't enough. A route can return 200 while serving a blank shell or the wrong build, so each step pairs status == 200 with a body sentinel — the check catches the silent-wrong-content failure that a bare uptime ping misses.

The sentinels are stable strings, never volatile values. A route that goes down, or ships a build that dropped its sentinel, fails the assert and the receipt records a real failure — it never silently passes.

## The skill file (verbatim)

```markdown
---
name: nightly-deploy-check
description: Nightly gate that sweeps several routes of YOUR live deployment — 200 + a body sentinel on each — read-only
---

<!-- synced from seldonframe/reelier examples/portfolio — edit there -->

# Nightly deploy check

Inputs: (none — this file replays green as-is; see the personalization note)

<!--
  Personalization: swap the three literal https://www.reelier.com URLs for
  your own deploy URL and routes, and swap each `body contains "..."`
  sentinel for a stable string you know is on that page (a headline, a
  tagline, a nav label). The portfolio README's "Point these at YOUR
  project" section has the one-command version. The skill grammar has no
  default-value syntax for {{var}} holes — an unbound {{var}} is an explicit
  error, never a guessed fallback — so this file ships with literals that
  replay green with zero flags.

  This checks YOUR OWN deployed routes, not a third party's status page: it
  is the nightly "is my site still up AND still serving the right content"
  gate. A 200 alone isn't enough — a route can return 200 while serving a
  blank shell or the wrong build. Pairing status == 200 with a body sentinel
  catches the silent-wrong-content failure that a bare uptime ping misses.

  Pick sentinels that are STABLE run-to-run — a headline or tagline, never a
  volatile value (a date, a view count, a build hash) that flips tomorrow. A
  route that goes down, or ships a build that dropped the sentinel, fails the
  assert and the receipt records a real failure — it never silently passes.

  All three routes verified live on 2026-07-21: each 200, each sentinel
  present in the response body.
-->

## Steps

### Step 1 — Homepage is up and serving the real tagline
- intent: Confirm the homepage serves 200 and still carries its core tagline
- action: http.get {"url": "https://www.reelier.com/"}
- assert: status == 200
- assert: body contains "Snapshot tests and CI for agent workflows"
- effect: read

### Step 2 — Blog index is up with its real heading
- intent: Confirm the blog index serves 200 and still carries its heading
- action: http.get {"url": "https://www.reelier.com/blog"}
- assert: status == 200
- assert: body contains "The receipts, written out."
- effect: read

### Step 3 — Docs page is up with its real description
- intent: Confirm the docs page serves 200 and still carries its description
- action: http.get {"url": "https://www.reelier.com/docs"}
- assert: status == 200
- assert: body contains "What Reelier is, how it works, and how to use it."
- effect: read
```

## Run it yourself

`reelier run` takes a local file, so fetch the canonical copy first (or clone the repo). The replay writes its receipt to `.reelier/runs/`.

```sh
curl -fsSL https://raw.githubusercontent.com/seldonframe/reelier/main/examples/portfolio/nightly-deploy-check.skill.md -o nightly-deploy-check.skill.md
npx -y reelier@latest run nightly-deploy-check.skill.md

# or from a clone:
git clone https://github.com/seldonframe/reelier
cd reelier && npx -y reelier@latest run examples/portfolio/nightly-deploy-check.skill.md
```

## Seed receipt — 2026-07-21

Replayed for real with the published CLI (resolved to reelier@0.14.0) on 2026-07-21; the run record confirms passed: true and 0 LLM tokens (input + output). Verbatim output:

```
✓ Step 1 — Homepage is up and serving the real tagline [passed] 175ms
✓ Step 2 — Blog index is up with its real heading [passed] 44ms
✓ Step 3 — Docs page is up with its real description [passed] 26ms

PASSED: 3/3 steps ok, 0 failed, 245ms total
```

Standing audit log: a GitHub Action replays all five portfolio skills every 6 hours (plus on demand) — https://github.com/seldonframe/reelier/actions/workflows/portfolio-replay.yml. A failing endpoint produces an honestly failing receipt, never a retried-until-green one.

## Point it at your project

Swap the three literal https://www.reelier.com URLs for your own deploy URL and routes, and swap each body sentinel for a stable string you know is on that page (a headline, a tagline, a nav label). Unlike the single-token skills, there is no one find-and-replace that yields a green run here — each route's sentinel is page-specific — so this one is edited by hand rather than sed'd.

---

Reelier — agents make claims, Reelier writes receipts. AGPL-3.0.
Portfolio index: https://www.reelier.com/skills (twin: https://www.reelier.com/skills.md) · Replay ledger: https://www.reelier.com/replays · Machine-readable summary: https://www.reelier.com/llms.txt
