Skip to content
Back to skills

Build Probe

ASecurity

Turn a PRD's asserted facts into EMITTED facts. Writes one executable probe per measured claim in the PRD — each prints a single value — plus a lockfile pinning every source the PRD cites. PASS = every probe runs and prints exactly what the PRD says, and no cited source has moved. Runs after build-prd and before build-validate, and re-runs in seconds at every later stage as the drift detector. Use when a PRD asserts a number, a count, a filename, a line reference, or an "every X / none of X" ...

  • 6 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added October 5, 2026
ai-agentspythongobash

Security analysis

A100/100

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

Scanned October 5, 2026

npx -y skills add shawnclybor/clybor-claude-tooling --skill build-probe --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Build Probe?

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

Security grade badge for Build Probe
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/shawnclybor-build-probe/badge)](https://www.skillsdirectory.com/skills/shawnclybor-build-probe)

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

Download with Pro
SKILL.md
---
name: build-probe
description: >
  Turn a PRD's asserted facts into EMITTED facts. Writes one executable probe per measured claim in
  the PRD — each prints a single value — plus a lockfile pinning every source the PRD cites. PASS =
  every probe runs and prints exactly what the PRD says, and no cited source has moved. Runs after
  build-prd and before build-validate, and re-runs in seconds at every later stage as the drift
  detector. Use when a PRD asserts a number, a count, a filename, a line reference, or an "every X /
  none of X" claim. Triggers — "probe the PRD", "prove the anchors", "are the numbers still true",
  "recheck the sources", "/build probe".
---

# Build Probe

**A number in a PRD is a rumour until a script prints it.**

This stage exists because of a measured fact about the previous pipeline: across 21 recorded review
rounds, a freshly-written plan carried a mean of **11.9 must-fix**, and roughly half of every
finding was a checkable claim about the world that nobody had checked. A five-agent panel found
those at a cost of ~45 minutes. A 20-line script finds them in seconds, finds them the same way
every time, and — unlike a panel — can be re-run tomorrow.

## What this replaces

The old Stage 3 ran one detector (an LLM reviewer panel) against three different failure classes.
They have wildly different cheapest detectors:

| Class | Cheapest detector | Stage |
|---|---|---|
| **Facts** — numbers, counts, filenames, line refs, "every/none" claims | a script | **build-probe** (this) |
| **Plan incoherence** — unwritten fields, dependency inversions, unfalsifiable checks | `check-plan-soundness.py` | mechanical gate |
| **Premises** — is the frame right, is this the correct oracle | a human, or one scoped review | `build-validate` |

Probe first. What survives is judgment, and judgment is all `build-validate` should ever see.

## When to use

- After `build-prd`, before `build-validate`. Every measured claim in the PRD gets a probe.
- Before `build-plan`, `build-execute` and `build-evaluate` — re-run, seconds, as the drift gate.
- Any time someone asks "is that still true".

## When NOT to use

- A claim that is a **judgment**, not a measurement ("this is the right oracle", "the frame is
  audit not generate"). Probes cannot settle those. That is `build-validate`'s one job.
- A claim about something not yet built. A probe measures the world as it is; if the PRD asserts
  what the build *will* produce, that is the acceptance driver's job, not a probe's.

## The layout

```
.claude/PRPs/{slug}/probes/
  run.sh            runs every probe, diffs emitted vs expected, verifies the lock, exits non-zero on any mismatch
  lock.sh           adds/refreshes sources.lock entries WITHOUT dropping existing ones
  expected.tsv      probe_id <TAB> expected_value <TAB> what it proves     (one line per claim)
  p-<id>.sh         one probe per claim. Prints ONE value on stdout and nothing else.
  sources.lock      path <TAB> sha256 <TAB> size    for every file the PRD cites
```

Copy `templates/run.sh` and `templates/probe.sh` from this skill's directory. Do not invent a
different shape — the point is that any reader can run `bash probes/run.sh` without instructions.

## Phase 1: HARVEST every checkable claim

Read the PRD and list every claim that a script could settle. Be exhaustive; this is the cheap part.

- every number, sum, count, total, delta
- every filename, path, and line reference (line numbers drift — a probe re-checks them for free)
- every quoted string or label attributed to a document
- **every "every X" / "none of X" claim** — these break most often, because a subset was checked
  and generalised
- every suite or baseline count — probe it by RUNNING the suite, never by reading a prior report

A claim you cannot write a probe for is either a judgment (hand it to `build-validate`) or
unfalsifiable (which is itself a finding — say so, do not quietly drop it).

## Phase 2: WRITE one probe per claim

Each `p-<id>.sh` prints exactly one value on stdout. No commentary, no formatting, no exit-code
signalling — `run.sh` owns comparison and exit codes.

```bash
#!/usr/bin/env bash
# p-anchor1-rows.sh — PRD Anchor 1 item 1: the roster has 7 provider rows
set -euo pipefail
python3 - <<'PY'
import re, pdfplumber
with pdfplumber.open("...") as pdf:
    t = "\n".join((p.extract_text() or "") for p in pdf.pages)
print(len([l for l in t.splitlines() if ROW.match(l)]))
PY
```

Rules that keep probes honest:

1. **A probe reads the SOURCE, never the record.** Probing a value out of a file the build wrote
   proves the build agrees with itself. Read the PDF, the corpus, the code.
2. **One value, one probe.** A probe printing three numbers cannot say which one moved.
3. **Never write.** Probes are read-only. A probe that mutates a case tree has corrupted its own
   next run.
4. **Prints, does not judge.** `expected.tsv` holds the expectation, so the same probe re-used
   under a different expectation stays honest.
5. **A probe that cannot be written is a finding.** Record it in `expected.tsv` with expected value
   `UNPROVABLE` and a reason. `run.sh` counts these and prints them; it does not fail on them, and
   it never hides them.

## Phase 3: LOCK the sources

For every file the PRD or plan cites — including other slugs' `plan.md` and `prd.md` — record path,
`sha256`, and size in `sources.lock`.

This catches the class no reviewer can: **a cited document being rewritten underneath you.** It has
happened; a plan was folded from a sibling slug's task bodies while a concurrent session cut that
slug from 14 tasks to 10, and every citation silently pointed at different work.

```bash
bash probes/lock.sh <path> [<path> ...]
```

⚠ **Never build the lock by truncating it.** `: > sources.lock` in a loop is the obvious way and it
silently destroys pins someone else added — measured 2026-09-02, a concurrent session had pinned
three cited sibling plans and a probe repoint took those pins with it. Nothing detected it, because
a lock with *fewer* entries still verifies clean. `lock.sh` merges, and refuses to re-pin a source
whose hash has changed: re-pinning a moved file is a decision, never a side effect of adding one.

## Phase 4: RUN and report

```bash
bash .claude/PRPs/{slug}/probes/run.sh
```

Output is one line per probe — `OK`, `MISMATCH expected/got`, or `UNPROVABLE reason` — then the lock
verification, then a summary. Exit 0 only when every probe matches and the lock verifies.

**PASS = every probe OK, lock verified, zero MISMATCH.** `UNPROVABLE` entries do not block, but they
are carried into `build-validate` as premises, because that is what they are.

On MISMATCH the PRD is wrong, not the probe — fix the PRD and re-run. Never adjust `expected.tsv` to
match a probe's output; that converts the gate into a mirror. If a probe itself is wrong, fix the
probe and say so in the commit.

## Phase 5: REPORT

Write `.claude/PRPs/{slug}/probe.md`:

```markdown
## Probe: {slug}  —  {ISO date}

| probe | claim | expected | emitted | verdict |
|---|---|---|---|---|

**Sources locked:** N files, sha256 recorded.
**Verdict:** PASS / FAIL ({N} mismatches)
**Carried to build-validate as premises:** {list of UNPROVABLE entries — the judgment calls}
```

## Re-running later

Every subsequent stage begins with `bash probes/run.sh`. It costs seconds. A red probe at plan time
means a number moved or a source was rewritten, and that is worth more than any amount of re-reading.

Do NOT re-harvest claims at every stage. Harvest once, at PRD time. New claims arrive only when the
PRD changes, and a PRD change is exactly when a new probe should be written.

## Output

```
## Probes: {slug}

**Written:** N probes, M sources locked
**Result:** {N} OK · {N} MISMATCH · {N} UNPROVABLE
**Verdict:** PASS / FAIL

### Next step
PASS → `build-validate {slug}` — premises only, and the UNPROVABLE list above is its agenda.
FAIL → fix the PRD (not the expectations) and re-run.
```

## Guidelines

- Probes are committed. They are the build's memory of why anyone believed a number.
- A probe is cheap to write and free to re-run. When in doubt, write it.
- Do not probe what the build will produce. Probe what the world already contains.
- If harvesting turns up more than ~20 checkable claims, the PRD is probably asserting things it
  does not need. That is a signal about the PRD, not a reason for 40 probes.

Files in this skill

  • SKILL.md8.3 KB
  • templates/lock.sh1.8 KB
  • templates/probe.sh1 KB
  • templates/run.sh3.7 KB
  • test-probe-runner.sh3 KB

Attribution

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

Comments

Loading comments…

Newsletter

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